/** * `ModelRunner` — the single SSoT factory for LLM transports + language models. * * ## Why this exists (E9 · T11745 step 1 · T11761) * * CLEO previously constructed transports/SDK clients in FOUR places, each a * near-duplicate of the others: * * - `session-factory.transportForProvider` (the canonical one) * - `api.ts:_transportForConfig` * - `tool-loop.ts:_transportForProvider` * - the inline codex block in `role-executor.ts` (`:241`) * * plus the Vercel-AI-SDK `LanguageModel` construction duplicated in * `memory/llm-backend-resolver.ts` and the provider adapters. * * `ModelRunner.build(descriptor)` is the ONE place `new *Transport` / * `createAnthropic` / `createOpenAICompatible` may appear for the resolver * path. It consumes a {@link ResolvedLLMDescriptor} (carrying `apiMode`, * `baseUrl`, `authType`) and returns BOTH surfaces off the same sealed * credential: * * - `session` — a transport-backed {@link LlmSession} for the * cantbook/CLI/executor path (streaming, tool loops). * - `languageModel` — a Vercel AI SDK {@link LanguageModel} for the * sentient/adapters path (`generateText`/`generateObject`), * or `null` when the provider has no Vercel binding here. * * Because the descriptor carries `apiMode`, codex "just works": a * `codex_responses` descriptor builds a {@link CodexResponsesTransport} with * the OAuth Cloudflare headers — no inline branch at the call-site. * * @module llm/model-runner * @task T11745 * @task T11761 * @epic T11745 */ import type { ApiMode, ResolvedLLMDescriptor } from '@cleocode/contracts'; import type { LlmSession } from '@cleocode/contracts/llm/interfaces.js'; import type { LlmTransport } from '@cleocode/contracts/llm/normalized-response.js'; import type { ResolvedCredential } from '@cleocode/contracts/llm/resolved-credential.js'; import type { LanguageModel } from 'ai'; import type { ModelTransport } from './types-config.js'; /** * Both runtime surfaces produced from a single {@link ResolvedLLMDescriptor}. * * @task T11745 */ export interface BuiltModel { /** * Transport-backed session for the cantbook / CLI / executor path. * Always present (a transport is always constructible from the descriptor). */ readonly session: LlmSession; /** * Vercel AI SDK language model for the sentient / adapters path. * * `null` when the provider has no Vercel binding in core (e.g. bedrock, * codex's ChatGPT backend, gemini-native) — those callers use {@link session} * instead. The descriptor's `apiMode` determines which binding is built. */ readonly languageModel: LanguageModel | null; } /** * The single SSoT model factory (E9 · T11745). * * Stateless: every method takes a fully-resolved {@link ResolvedLLMDescriptor} * and constructs fresh transports / language models. No credential I/O, no * resolution — that happens upstream in `resolveLLMForRole` / * `resolveLLMForSystem`. */ export declare const ModelRunner: { /** * Construct the transport for a descriptor. This is the ONLY home for * `new *Transport` on the resolver path — the three legacy transport * factories delegate here (via {@link ModelRunner.buildTransportFromCredential}). * * Branches on `apiMode` (the descriptor's load-bearing field), falling back * to provider name for the anthropic/gemini/bedrock/ollama families. * * @param d - Fully-resolved descriptor. * @returns A wire-level transport bound to the descriptor's credential. */ readonly buildTransport: (d: ResolvedLLMDescriptor) => LlmTransport; /** * Lower-level transport factory: the single home for `new *Transport`. * * Accepts a fully-formed {@link ResolvedCredential} (so callers that already * hold one — `session-factory`, `api.ts`, `tool-loop.ts` — preserve their * `extraHeaders`/`baseUrl` verbatim) plus an optional explicit `apiMode`. * When `apiMode === 'codex_responses'` it builds the codex transport * regardless of provider name (xAI grok-via-responses, openai-oauth). * * @param provider - Resolved provider transport. * @param credential - Fully-resolved credential to wire in. * @param apiMode - Optional wire-protocol override (codex routing). * @returns A wire-level transport. */ readonly buildTransportFromCredential: (provider: ModelTransport, credential: ResolvedCredential, apiMode?: ApiMode) => LlmTransport; /** * Construct a Vercel AI SDK {@link LanguageModel} for the sentient/adapters * path, or `null` when core has no Vercel binding for the descriptor's * provider/apiMode. * * - `anthropic_messages` → `createAnthropic` * - `chat_completions` / `ollama_native` → `createOpenAICompatible` * - everything else (codex_responses, bedrock_converse) → `null` * * Returns `null` (rather than throwing) on any binding failure so the caller * degrades to the transport path. Async because the AI-SDK provider modules * are dynamically imported (keeps them out of the module-init chain). * * @param d - Fully-resolved descriptor. * @returns A Vercel `LanguageModel`, or `null` when unsupported here. */ readonly buildLanguageModel: (d: ResolvedLLMDescriptor) => Promise; /** * Build BOTH surfaces (transport session + Vercel language model) from one * descriptor. The transport session is always present; `languageModel` is * `null` for providers without a core Vercel binding. * * @param d - Fully-resolved descriptor. * @returns The {@link BuiltModel} pair. */ readonly build: (d: ResolvedLLMDescriptor) => Promise; }; //# sourceMappingURL=model-runner.d.ts.map