/** * Per-conversation model routing. `/model use` points one conversation at a * provider/model route; unlike a workspace switch this keeps the SAME session — * a route is an `agentOptions` fact the host accepts on resume, not part of the * session's identity — so the conversation continues with its context intact * and only the model changes from the next message on. * * The catalog shown by `/model` comes from the host `llm` registry's own * listing. It is advisory by that service's contract: adapters may accept * models they do not list, so an unlisted route is set with a note, never * rejected. * * The mapping persists through the host settings service, in the same section * as credentials and workspace switches. * @module dsh-lark-channel/model */ import type { HostAgentOptions } from './host.ts'; import type { ConversationSubject } from './session.ts'; /** Show or switch this conversation's model route. Channel-owned: needs no agent. */ export declare const MODEL_COMMAND = "model"; /** Marks this plugin's model buttons apart from other card actions. */ export declare const MODEL_ACTION = "dsh-lark-channel/model"; /** Card payload carried by one model pick. */ export interface ModelActionValue extends ConversationSubject { readonly kind: typeof MODEL_ACTION; /** The route to switch to; absent means "back to the deployment default". */ readonly route?: string | undefined; } /** * Narrow an arbitrary card-action value to this module's pick payload. * @param value - raw button value from a card action event. * @returns the typed payload, or undefined for foreign card actions. */ export declare function modelActionValue(value: unknown): ModelActionValue | undefined; /** One provider/model pair, both halves known. */ export interface ModelRoute { readonly provider: string; readonly model: string; } /** One advertised model, as the host llm registry lists it. */ export interface CatalogEntry { readonly provider: string; readonly id: string; readonly name: string; } /** * Render a route (or a partial deployment selection) for the chat. * @param options - provider/model, either possibly absent. * @returns `provider/model`, the present half alone, or the host-default label. */ export declare function formatRoute(options: HostAgentOptions): string; /** * Parse one persisted entry back into a route. * @param entry - a non-marker entry value. * @returns the route, treating everything after the first `/` as the model id. */ export declare function parseRoute(entry: string): ModelRoute | undefined; /** What one `/model use` or `/model reset` attempt concluded. */ export interface RouteChange { /** False when the conversation was already on that route. */ readonly changed: boolean; /** Whether the mapping survives a restart. */ readonly durable: boolean; } /** Construction options for {@link ChatModels}. */ export interface ChatModelsOptions { /** Persisted conversation-key → serialized route; {@link DEFAULT_MARKER} means default. */ readonly entries?: Record | undefined; /** Deep-merge one patch into the plugin's settings section; false = not composed. */ readonly persist?: ((patch: { chatModels: Record; }) => Promise) | undefined; /** Operator console line. */ readonly report?: ((line: string) => void) | undefined; } /** * The per-conversation model state: which route each conversation asked for, * against the deployment default meaning "no entry". Pure state plus injected * persistence, mirroring the workspace store. */ export declare class ChatModels { private readonly entries; private readonly persist; private readonly report; /** The non-durable warning is orientation; once is enough. */ private warnedNotDurable; constructor(options?: ChatModelsOptions); /** The route one conversation asked for, or undefined for the deployment default. */ routeFor(key: string): ModelRoute | undefined; /** Whether one conversation runs on the deployment default. */ isDefault(key: string): boolean; /** Point one conversation at a route. */ set(key: string, route: ModelRoute): Promise; /** Return one conversation to the deployment default. */ reset(key: string): Promise; private record; } /** * Build the picker for one conversation. * * The catalog is advertised rather than exhaustive, so the picker offers the * first {@link PICKER_ROWS} routes and says how many it left out — the typed * form reaches any of them, including routes the registry never listed. * @param subject - the conversation the card governs and the chat it lives in. * @param catalog - advertised routes. * @param current - the route this conversation asked for, if any. * @param deploymentRoute - the default's display form. * @returns a card object for `send({ card })`. */ export declare function modelPickerCard(subject: ConversationSubject, catalog: readonly CatalogEntry[], current: ModelRoute | undefined, deploymentRoute: string): object; /** What {@link runModelCommand} needs from the bridge. */ export interface ModelCommandPorts { /** The host llm registry's advertised routes; empty when none is composed. */ readonly catalog: () => Promise; /** The deployment default's display form. */ readonly deploymentRoute: () => string; /** Awaited after a change, before the reply; releases the conversation's agent. */ readonly release: () => Promise; } /** * Resolve the operator's route input against the catalog: a full * `provider/model` form is taken as written, and a bare model id is accepted * when exactly one advertised route carries it — the same shorthand contract * `/cd` uses for directory basenames. * @param input - the operator's target exactly as typed. * @param catalog - advertised routes. * @returns the route with its catalog standing, or the refusal. */ export declare function resolveRouteInput(input: string, catalog: readonly CatalogEntry[]): { route: ModelRoute; listed: boolean; } | { reason: string; }; /** What one `/model` line produced: a card to send, or a line of markdown. */ export type ModelReply = { readonly card: object; } | { readonly markdown: string; }; /** * Run one `/model` command line and produce the chat reply. * * The bare form answers with the picker card; every other form answers in * text, because `/model use x` is what someone types when they already know * the route and want it applied without reading a card. * @param line - the complete line, slash included. * @param subject - the conversation the command is about, and where it lives. * @param store - the model route state. * @param ports - catalog, default display, and the release hook. * @returns the card or the markdown for the chat. */ export declare function runModelCommand(line: string, subject: ConversationSubject, store: ChatModels, ports: ModelCommandPorts): Promise; //# sourceMappingURL=model.d.ts.map