/** * `/models` local-model lifecycle and `/fitness` probe/role-assignment flows * extracted from interactive-mode. * * `/models` is a USER-invoked local-model manager (list/add/remove/stop, never a * model-invokable tool); the fitness helpers probe a model on the current host * and land a shaped role. The server/selector flows share a `LocalModelHost` * seam, while `runFitnessAndAssign`/`assignFitnessRole` take narrow host shapes * matching their prototype-driven behaviour tests (fitness-probe-gate, * fitness-role-assignment), which keep exercising interactive-mode's thin * wrappers unchanged. */ import { type Component, Container, type TUI } from "@caupulican/pi-tui"; import type { AgentSession } from "../../core/agent-session.ts"; import type { ModelRegistry } from "../../core/model-registry.ts"; import { PrismLlamaCppRuntime, type PrismModelDescriptor } from "../../core/models/llamacpp-runtime.ts"; import type { OllamaRuntime, TransformersRuntime } from "../../core/models/local-runtime.ts"; import { NeedleRuntime } from "../../core/models/needle-runtime.ts"; import type { SettingsManager } from "../../core/settings-manager.ts"; import { type FitnessRole } from "./components/fitness-role-selector.ts"; type SelectorFactory = (done: () => void) => { component: Component; focus: Component; }; /** Narrow seam for persisting a probed model's role — matches the fitness-role test. */ export interface AssignRoleHost { readonly settingsManager: SettingsManager; showStatus(message: string): void; } /** Seam for the fitness probe + role-selector flow — matches the fitness-probe-gate test. */ export interface RunFitnessHost { readonly session: Pick & { modelRegistry?: ModelRegistry; }; readonly settingsManager: SettingsManager; readonly chatContainer: Container; readonly ui: TUI; showStatus(message: string): void; showError(message: string): void; showSelector(create: SelectorFactory): void; } /** Full seam for the `/models` server/selector flows. */ export interface LocalModelHost { readonly localRuntime: OllamaRuntime; readonly session: AgentSession; readonly settingsManager: SettingsManager; readonly ui: TUI; readonly chatContainer: Container; getTransformersRuntime(modelId: string, baseUrl?: string): TransformersRuntime; /** * Seam for the pi-managed prism llama.cpp runtime (Bonsai-27B and future curated prism-ml * models). Production (interactive-mode.ts's `localModelHost()`) always supplies this, wired * through `AgentSession.getPrismLlamaCppRuntime()` -> `LocalRuntimeController`'s cached instance * — the SAME instance the readiness gate uses, mirroring `getTransformersRuntime` above (cached * for the session's lifetime, so `stop()`/`removePrismLlamaCppModel` reattach to the SAME * instance that holds the running child process instead of each tracking an untracked one). * Optional only so tests can inject a fake without needing the full session stack; the fallback * below (a fresh, uncached instance) is a test convenience, never the production path. */ getPrismLlamaCppRuntime?(): PrismLlamaCppRuntime; /** * Seam for the pi-managed needle runtime (see needle-runtime.ts) — optional so tests can inject a * fake, falling back to a fresh instance otherwise. Unlike `getPrismLlamaCppRuntime` above, needle * has no session-caching need: every invocation is a one-shot `runCommand` call with no persistent * child process to reattach to (needle-runtime.ts's `dispose()` is a documented no-op), so a fresh * instance per call is functionally identical to a cached one — `runtimeDir()`/`modelsDir()`/ * `checkpointPath()` are pure path derivations from `agentDir`, not in-memory state. */ getNeedleRuntime?(): NeedleRuntime; showStatus(message: string): void; showError(message: string): void; showSelector(create: SelectorFactory): void; } /** * /models — USER-invoked local model lifecycle (never a model-invokable tool): * list/add/remove/stop per local-model-lifecycle-design.md. Removal is explicit-only with * full disclosure; a pasted install command is parsed for its ref, never executed. */ export declare function handleModelsCommand(host: LocalModelHost, argsText: string): Promise; export declare function ensureLocalServer(host: LocalModelHost): Promise; export declare function listLocalModels(host: LocalModelHost): Promise; export declare function addLocalModel(host: LocalModelHost, pullRef: string, preselectRole?: FitnessRole): Promise; export declare function addTransformersModel(host: LocalModelHost, modelId: string, preselectRole?: FitnessRole): Promise; /** * Zero-setup pipeline for a curated prism llama.cpp model (Bonsai-27B): install the pinned prism * llama.cpp runtime (prebuilt release download, no compiler needed), ensure both GGUF files and * start llama-server (see `ensurePrismModelFilesThenServe`), register the model, then probe * fitness. Mirrors addTransformersModel's shape — each stage checks its own `{ ok }`/ * `{ runtimeInstalled }` result and stops with an honest status message on failure; nothing * continues past a failed stage. */ export declare function addPrismLlamaCppModel(host: LocalModelHost, descriptor: PrismModelDescriptor, preselectRole?: FitnessRole): Promise; export declare function removeLocalModel(host: LocalModelHost, ref: string, confirmed: boolean): Promise; /** * Zero-setup pipeline for needle (see needle-runtime.ts): a standalone 26M-parameter function-call * test bench, NOT a chat/executor/lane model — no OpenAI-compatible endpoint, no models.json * registration, no /fitness probe. Install the pinned needle clone+venv (menu pick = consent, same * doctrine as the Transformers/prism precedents), download and sha256-verify the pickle checkpoint * (never called implicitly by installManaged — see the module's SECURITY note: the checkpoint is a * pickle file, arbitrary code execution on load by construction, so this is deliberately a separate * consent-adjacent step, not folded into install), then run its own smoke test as the honest * post-install verification. Each stage checks its own `{ ok }` result and stops with a stage-tagged * status on failure; nothing continues past a failed stage. */ export declare function addNeedleModel(host: LocalModelHost): Promise; /** /fitness with no args: pick a model from the configured registry, probe it, assign a role. */ /** Pick a validated suggestion → install it → probe on this host → land its shaped role. */ export declare function showModelSuggestionSelector(host: LocalModelHost): void; export declare function showFitnessModelSelector(host: LocalModelHost): void; /** Probe a model's fitness, show the report, then offer one-step role assignment. When the model * came from a validated suggestion, `preselectRole` lands its shaped role already highlighted. */ export declare function runFitnessAndAssign(host: RunFitnessHost, modelRef: string, preselectRole?: FitnessRole): Promise; /** Persist a role assignment from the post-probe selector into the matching settings. */ export declare function assignFitnessRole(host: AssignRoleHost, modelRef: string, role: FitnessRole): void; export {}; //# sourceMappingURL=local-model-commands.d.ts.map