/** * [WHO]: Provides ModelController, CycleModelError, ModelCycleResult — model + thinking-level management * [FROM]: Depends on @catui/ai (Model, modelsAreEqual), @catui/agent-core (types), * ./session-context (ModelControllerContext), ./thinking-levels, ./model-cycle * [TO]: Consumed by core/runtime/agent-session.ts (constructs one, delegates the public methods) * [HERE]: core/runtime/agent-session.ts split — owns setModel/cycleModel and thinking-level methods * * Extracted from AgentSession (S2 controller). Session state is reached through narrow * ModelControllerContext capabilities; behavior is identical to the former AgentSession methods. */ import type { AgentLoopFrameworkInput, AgentLoopPolicyOptions, ThinkingLevel } from "@catui/agent-core"; import type { Model } from "@catui/ai/types"; import type { ModelControllerContext } from "./session-context.js"; /** Result of cycling the model. */ export interface ModelCycleResult { model: Model; thinkingLevel: ThinkingLevel; isScoped: boolean; } /** Raised when cycling cannot find a usable model (e.g. all OAuth tokens expired). */ export declare class CycleModelError extends Error { readonly provider?: string | undefined; readonly code?: "oauth_expired" | "no_valid_key" | "api_error" | undefined; constructor(message: string, provider?: string | undefined, code?: "oauth_expired" | "no_valid_key" | "api_error" | undefined); } export declare class ModelController { private readonly ctx; constructor(ctx: ModelControllerContext); private _emitModelSelect; /** * Apply a model change: persist to session + settings, set the thinking level * (explicit when given, otherwise auto-picked from capabilities), and emit * model_select. Shared by setModel and the cycle paths. */ private _applyModelChange; /** * Set model directly. Validates API key, saves to session and settings. * @throws Error if no API key available for the model */ setModel(model: Model): Promise; /** * Restore a model from session history without appending a new model-change * entry or changing default settings. */ restoreModel(model: Model): Promise; /** * Restore thinking state while switching/resuming a session. * * When the session has an explicit thinking entry, use the normal setter so * clamping and default-setting persistence stay identical to user-driven changes. * When the session has no entry, seed the session history from the configured * default without changing the configured default itself. */ restoreThinkingLevel(options: { hasThinkingEntry: boolean; sessionThinkingLevel: ThinkingLevel; defaultThinkingLevel: ThinkingLevel; }): void; /** * Cycle to next/previous model. Uses scoped models if available, otherwise all available models. * @returns The new model info, or undefined if only one model available */ cycleModel(direction?: "forward" | "backward"): Promise; private _getScopedModelsWithApiKey; private _cycleScopedModel; private _cycleAvailableModel; /** * Set thinking level, clamped to model capabilities. Saves to session and settings * only if the level actually changes. */ setThinkingLevel(level: ThinkingLevel): void; /** Set the session-level agent loop framework override. */ setAgentLoopFramework(framework: AgentLoopFrameworkInput | undefined): void; /** Update runtime loop policy options for subsequent turns. */ setLoopPolicy(options: Partial): void; /** Cycle to next thinking level. @returns new level, or undefined if model doesn't support thinking. */ cycleThinkingLevel(): ThinkingLevel | undefined; /** Thinking levels available for the current model. */ getAvailableThinkingLevels(): ThinkingLevel[]; /** Whether the current model supports xhigh thinking. */ supportsXhighThinking(): boolean; /** Whether the current model supports thinking/reasoning. */ supportsThinking(): boolean; }