@theokit/sdk 2.10.0 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,8 @@
1
- import type { SDKAssistantMessage, SDKUserMessageEvent } from "../../types/messages.js";
1
+ import type { SDKAssistantMessage, SDKThinkingMessage, SDKUserMessageEvent } from "../../types/messages.js";
2
2
  import type { LlmMessage, LlmToolCallPart } from "../llm/types.js";
3
3
  import type { AgentLoopInputs } from "./loop-types.js";
4
4
  export declare function buildUserEvent(inputs: AgentLoopInputs): SDKUserMessageEvent;
5
5
  export declare function buildAssistantEvent(inputs: AgentLoopInputs, text: string): SDKAssistantMessage;
6
+ /** issue #47: the reasoning the model produced this turn, as a `thinking` SDKMessage. */
7
+ export declare function buildThinkingEvent(inputs: AgentLoopInputs, text: string): SDKThinkingMessage;
6
8
  export declare function buildAssistantTurn(text: string, toolCalls: LlmToolCallPart[]): LlmMessage;
@@ -1,4 +1,48 @@
1
1
  import type { LlmClient, LlmEvent, LlmFinish, LlmRequest } from "./types.js";
2
+ interface OpenAIDeltaChunk {
3
+ choices?: Array<{
4
+ index: number;
5
+ delta?: {
6
+ content?: string;
7
+ /** OpenRouter unified reasoning delta (issue #47) — streamed separately from `content`. */
8
+ reasoning?: string;
9
+ /**
10
+ * Sibling reasoning field used by some OpenAI-compatible providers (DeepSeek's direct API,
11
+ * many vLLM / LMStudio reasoning parsers). Treated identically to `reasoning` (issue #47,
12
+ * F-domain-2). OpenRouter normalizes to `reasoning`; this is the fallback for non-OpenRouter
13
+ * compat endpoints reached via `baseUrl` override.
14
+ */
15
+ reasoning_content?: string;
16
+ tool_calls?: Array<{
17
+ index: number;
18
+ id?: string;
19
+ function?: {
20
+ name?: string;
21
+ arguments?: string;
22
+ };
23
+ }>;
24
+ };
25
+ finish_reason?: string | null;
26
+ }>;
27
+ usage?: {
28
+ prompt_tokens?: number;
29
+ completion_tokens?: number;
30
+ /**
31
+ * OpenAI + OpenRouter extended usage (D376). Anthropic prompt caching
32
+ * surfaces as `prompt_tokens_details.cached_tokens` on OpenRouter passthrough;
33
+ * native OpenAI exposes the same field on `chatcmpl-*` responses.
34
+ */
35
+ prompt_tokens_details?: {
36
+ cached_tokens?: number;
37
+ };
38
+ completion_tokens_details?: {
39
+ reasoning_tokens?: number;
40
+ };
41
+ /** Anthropic-on-OpenRouter passes cache_creation_tokens top-level (cline#10266). */
42
+ cache_creation_input_tokens?: number;
43
+ cache_read_input_tokens?: number;
44
+ };
45
+ }
2
46
  export declare class OpenAIClient implements LlmClient {
3
47
  private readonly options;
4
48
  readonly name = "openai";
@@ -7,3 +51,23 @@ export declare class OpenAIClient implements LlmClient {
7
51
  constructor(options: OpenAIClientOptions);
8
52
  stream(request: LlmRequest, signal: AbortSignal): AsyncGenerator<LlmEvent, LlmFinish, void>;
9
53
  }
54
+ declare class OpenAIStreamAccumulator {
55
+ private text;
56
+ private stopReason;
57
+ private inputTokens?;
58
+ private outputTokens?;
59
+ private cacheReadTokens?;
60
+ private cacheWriteTokens?;
61
+ private reasoningTokens?;
62
+ private readonly toolCalls;
63
+ consume(chunk: OpenAIDeltaChunk): LlmEvent[];
64
+ private applyReasoningDelta;
65
+ private applyUsage;
66
+ private applyContentDelta;
67
+ private mergeToolCallDeltas;
68
+ private applyFinishReason;
69
+ finish(): LlmFinish;
70
+ }
71
+ /** issue #47 test seam — exercise reasoning-delta parsing without a live stream. */
72
+ export declare const __testing__OpenAIStreamAccumulator: typeof OpenAIStreamAccumulator;
73
+ export {};
@@ -80,10 +80,25 @@ export interface LlmRequest {
80
80
  temperature?: number;
81
81
  /** T3.6 — opt into native structured outputs (OpenAI-compat providers). */
82
82
  responseFormat?: LlmResponseFormat;
83
+ /**
84
+ * Reasoning / extended-thinking request (issue #47). Derived from `ModelSelection.params` (the
85
+ * `thinking` param). The wire encoding is provider-specific: OpenRouter (and OpenAI-compatible
86
+ * passthroughs) use the unified `reasoning: { effort }` object; native OpenAI Chat Completions uses
87
+ * the top-level `reasoning_effort` string (see `buildOpenAIBody`). The model streams reasoning back
88
+ * as `delta.reasoning` (or `delta.reasoning_content` on some compat providers), surfaced as
89
+ * `reasoning_delta` events. `effort` is required once the object is present — an empty object would
90
+ * request nothing.
91
+ */
92
+ reasoning?: {
93
+ effort: string;
94
+ };
83
95
  }
84
96
  export type LlmEvent = {
85
97
  type: "text_delta";
86
98
  text: string;
99
+ } | {
100
+ type: "reasoning_delta";
101
+ text: string;
87
102
  } | {
88
103
  type: "tool_use";
89
104
  id: string;
package/dist/models.cjs CHANGED
@@ -66,6 +66,18 @@ var EXACT = /* @__PURE__ */ new Map([
66
66
  maxOutputTokens: 1e5
67
67
  }
68
68
  ],
69
+ [
70
+ // GPT-4.1 — 1M-context flagship; multimodal + structured output (RADAR #92.a).
71
+ "openai/gpt-4.1",
72
+ {
73
+ supportsVision: true,
74
+ supportsStructuredOutput: true,
75
+ supportsToolUse: true,
76
+ supportsCacheControl: false,
77
+ maxContextTokens: 1047576,
78
+ maxOutputTokens: 32768
79
+ }
80
+ ],
69
81
  // Anthropic family
70
82
  [
71
83
  "anthropic/claude-opus-4",
@@ -143,6 +155,111 @@ var EXACT = /* @__PURE__ */ new Map([
143
155
  maxContextTokens: 2e5,
144
156
  maxOutputTokens: 4096
145
157
  }
158
+ ],
159
+ // Dot-form OpenRouter slugs theocode uses (RADAR #92.a). These are the same
160
+ // models as their dash-form siblings above; capability parity is intentional.
161
+ // Without these entries the dotted slugs fall through to the 4096 default
162
+ // (`anthropic/claude-3.5-sonnet` ≠ `anthropic/claude-3-5-sonnet`).
163
+ [
164
+ "anthropic/claude-opus-4.1",
165
+ {
166
+ supportsVision: true,
167
+ supportsStructuredOutput: false,
168
+ supportsToolUse: true,
169
+ supportsCacheControl: true,
170
+ maxContextTokens: 2e5,
171
+ maxOutputTokens: 32e3
172
+ }
173
+ ],
174
+ [
175
+ "anthropic/claude-sonnet-4.5",
176
+ {
177
+ supportsVision: true,
178
+ supportsStructuredOutput: false,
179
+ supportsToolUse: true,
180
+ supportsCacheControl: true,
181
+ maxContextTokens: 2e5,
182
+ maxOutputTokens: 16e3
183
+ }
184
+ ],
185
+ [
186
+ "anthropic/claude-3.5-sonnet",
187
+ {
188
+ supportsVision: true,
189
+ supportsStructuredOutput: false,
190
+ supportsToolUse: true,
191
+ supportsCacheControl: true,
192
+ maxContextTokens: 2e5,
193
+ maxOutputTokens: 8192
194
+ }
195
+ ],
196
+ // Cheap OpenRouter slugs (RADAR #92.a) — previously fell to the 4096
197
+ // CONSERVATIVE default. toolUse on; vision/structuredOutput only for Gemini.
198
+ [
199
+ "qwen/qwen3-coder-30b-a3b-instruct",
200
+ {
201
+ supportsVision: false,
202
+ supportsStructuredOutput: false,
203
+ supportsToolUse: true,
204
+ supportsCacheControl: false,
205
+ maxContextTokens: 16e4,
206
+ maxOutputTokens: 8e3
207
+ }
208
+ ],
209
+ [
210
+ "deepseek/deepseek-v4-flash",
211
+ {
212
+ supportsVision: false,
213
+ supportsStructuredOutput: false,
214
+ supportsToolUse: true,
215
+ supportsCacheControl: false,
216
+ maxContextTokens: 1048576,
217
+ maxOutputTokens: 8e3
218
+ }
219
+ ],
220
+ [
221
+ "deepseek/deepseek-v3.2",
222
+ {
223
+ supportsVision: false,
224
+ supportsStructuredOutput: false,
225
+ supportsToolUse: true,
226
+ supportsCacheControl: false,
227
+ maxContextTokens: 131072,
228
+ maxOutputTokens: 8e3
229
+ }
230
+ ],
231
+ [
232
+ "z-ai/glm-4.7-flash",
233
+ {
234
+ supportsVision: false,
235
+ supportsStructuredOutput: false,
236
+ supportsToolUse: true,
237
+ supportsCacheControl: false,
238
+ maxContextTokens: 202752,
239
+ maxOutputTokens: 8e3
240
+ }
241
+ ],
242
+ [
243
+ "google/gemini-2.5-flash-lite",
244
+ {
245
+ supportsVision: true,
246
+ supportsStructuredOutput: true,
247
+ supportsToolUse: true,
248
+ supportsCacheControl: false,
249
+ maxContextTokens: 1048576,
250
+ maxOutputTokens: 8e3
251
+ }
252
+ ],
253
+ [
254
+ "google/gemini-2.5-pro",
255
+ {
256
+ supportsVision: true,
257
+ supportsStructuredOutput: true,
258
+ supportsToolUse: true,
259
+ supportsCacheControl: false,
260
+ maxContextTokens: 1048576,
261
+ maxOutputTokens: 8e3
262
+ }
146
263
  ]
147
264
  ]);
148
265
  var ROUTING_PREFIXES = ["openrouter/", "vertex/", "bedrock/"];
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/llm/model-capabilities.ts","../src/internal/llm/model-identifier.ts","../src/internal/llm/model-option.ts"],"names":[],"mappings":"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","file":"models.cjs","sourcesContent":["/**\n * T3.10c — Model capability registry (DR3 #17).\n *\n * Typed per-model flags that let the SDK gate features at the boundary\n * (before hitting the provider) instead of letting opaque 400s surface.\n *\n * Resolution algorithm:\n * 1. Strip routing prefixes (openrouter/, vertex/, bedrock/) AND the\n * OpenRouter `:variant` suffix (:free/:nitro/…) to find the bare vendor id.\n * 2. Exact match in the `EXACT` catalog → return entry.\n * 3. Vendor inference (e.g., `claude-*` → `anthropic/claude-*`) → return entry.\n * 4. No match → conservative defaults (all false, minimum tokens).\n *\n * Module is internal, but `ModelCapabilities` + `resolveModelCapabilities` are\n * re-exported publicly via the `@theokit/sdk/models` subpath (see their @public tags).\n */\n\n/**\n * Per-model capability shape. Consumers use this to gate features at\n * the SDK boundary (before request construction, not after 400).\n *\n * @public\n */\nexport interface ModelCapabilities {\n supportsVision: boolean;\n supportsStructuredOutput: boolean;\n supportsToolUse: boolean;\n supportsCacheControl: boolean;\n maxContextTokens: number;\n maxOutputTokens: number;\n}\n\nconst CONSERVATIVE_DEFAULTS: ModelCapabilities = {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: false,\n supportsCacheControl: false,\n maxContextTokens: 4096,\n maxOutputTokens: 4096,\n};\n\n/** Exact-match capability entries. Keys are `vendor/model` (no routing prefix). */\nconst EXACT: ReadonlyMap<string, ModelCapabilities> = new Map([\n // OpenAI family\n [\n \"openai/gpt-4o\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4o-mini\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4-turbo\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"openai/o1\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n [\n \"openai/o3\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n // Anthropic family\n [\n \"anthropic/claude-opus-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 32_000,\n },\n ],\n [\n \"anthropic/claude-sonnet-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 16_000,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet-latest\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-haiku-latest\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-haiku\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"anthropic/claude-3-opus\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n]);\n\n/** Routing prefixes to strip to find the underlying vendor model. */\nconst ROUTING_PREFIXES = [\"openrouter/\", \"vertex/\", \"bedrock/\"] as const;\n\n/**\n * Resolve per-model capability flags (vision/structured-output/tool-use/cache +\n * `maxContextTokens`/`maxOutputTokens`) for a model id. Pure, sync, offline (a\n * static catalog — no network). Strips routing prefixes (`openrouter/`/`vertex/`/\n * `bedrock/`) and OpenRouter `:variant` suffixes before lookup; unknown models get\n * conservative defaults. Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function resolveModelCapabilities(modelId: string): ModelCapabilities {\n const bare = stripVariantSuffix(stripRoutingPrefix(modelId));\n const exact = EXACT.get(bare);\n if (exact !== undefined) return exact;\n // Routing-prefixed models (vertex/claude-3-5-sonnet) strip to bare\n // model name without vendor. Try inferring the vendor from the name.\n const withVendor = inferVendorPrefix(bare);\n if (withVendor !== bare) {\n const vendored = EXACT.get(withVendor);\n if (vendored !== undefined) return vendored;\n }\n return CONSERVATIVE_DEFAULTS;\n}\n\nfunction stripRoutingPrefix(modelId: string): string {\n for (const prefix of ROUTING_PREFIXES) {\n if (modelId.startsWith(prefix)) return modelId.slice(prefix.length);\n }\n return modelId;\n}\n\n/**\n * Strip an OpenRouter variant suffix (`:free`/`:nitro`/`:floor`/`:beta`/…) so the\n * catalog lookup hits the underlying model. Model slugs contain no `:` except the\n * variant separator, so cutting at the first `:` is safe.\n */\nfunction stripVariantSuffix(modelId: string): string {\n const i = modelId.indexOf(\":\");\n return i >= 0 ? modelId.slice(0, i) : modelId;\n}\n\n/** Infer vendor prefix from bare model name for routing-prefixed lookups. */\nfunction inferVendorPrefix(bare: string): string {\n if (bare.startsWith(\"claude\")) return `anthropic/${bare}`;\n if (bare.startsWith(\"gpt-\") || bare.startsWith(\"o1\") || bare.startsWith(\"o3\"))\n return `openai/${bare}`;\n if (bare.startsWith(\"gemini\")) return `google/${bare}`;\n return bare;\n}\n","/**\n * Model identifier parsing (T1.2 follow-up, ADR D182 zero-config UX).\n *\n * SDK callers pass model strings like:\n * - `\"ollama/llama3.2:3b\"` → provider=\"ollama\", name=\"llama3.2:3b\"\n * - `\"anthropic/claude-3-5-sonnet\"` → provider=\"anthropic\", name=\"claude-3-5-sonnet\"\n * - `\"openrouter/meta-llama/llama-3\"` → provider=\"openrouter\", name=\"meta-llama/llama-3\"\n * - `\"claude-sonnet-4-6\"` → provider=undefined, name=\"claude-sonnet-4-6\"\n *\n * The first `/` separates the provider from the rest. Models with embedded\n * slashes (e.g. OpenRouter routing) keep the remainder intact. Tag suffixes\n * (`:latest`, `:3b`) are preserved as part of the name — Ollama expects them.\n *\n * **Returns `undefined` provider** when no `/` is present so callers can\n * fall back to env-var detection. Empty/whitespace components are treated\n * as no-prefix.\n *\n * Aligned with OpenClaw `extensions/ollama/src/discovery-shared.ts`\n * (`OLLAMA_PROVIDER_ID = \"ollama\"`) and Hermes `hermes_cli/providers.py`\n * (ALIASES table, `normalize_provider`).\n *\n * Public via `@theokit/sdk/models` (M5-8).\n *\n * @public\n */\n\nexport interface ParsedModelId {\n /** Provider name extracted from the prefix (lowercase), or undefined. */\n provider: string | undefined;\n /** Model name to send to the provider — prefix stripped. */\n name: string;\n}\n\n/** Provider aliases mirrored from Hermes `hermes_cli/providers.py` ALIASES. */\nconst PROVIDER_ALIASES: Readonly<Record<string, string>> = {\n \"llama-cpp\": \"llamacpp\",\n \"llama.cpp\": \"llamacpp\",\n \"lm-studio\": \"lmstudio\",\n lm_studio: \"lmstudio\",\n};\n\nexport function parseModelId(modelId: string | undefined): ParsedModelId {\n if (modelId === undefined || modelId.length === 0) {\n return { provider: undefined, name: \"\" };\n }\n const slash = modelId.indexOf(\"/\");\n if (slash <= 0 || slash === modelId.length - 1) {\n return { provider: undefined, name: modelId };\n }\n const rawProvider = modelId.slice(0, slash).trim().toLowerCase();\n const name = modelId.slice(slash + 1).trim();\n if (rawProvider.length === 0 || name.length === 0) {\n return { provider: undefined, name: modelId };\n }\n const canonical = PROVIDER_ALIASES[rawProvider] ?? rawProvider;\n return { provider: canonical, name };\n}\n","import { parseModelId } from \"./model-identifier.js\";\n\n/**\n * A UI-friendly model option — the shape a `<select>`/dropdown consumes.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport interface ModelOption {\n /** The original model id (what you pass back to the SDK). */\n value: string;\n /** Best-effort human label (see {@link humanizeModelName}). */\n label: string;\n /** Provider from the slug prefix, or `undefined` when none. */\n provider: string | undefined;\n}\n\n/** Tokens rendered upper-case rather than title-case. */\nconst ACRONYMS = new Set([\"gpt\", \"ai\", \"hd\", \"ui\", \"api\", \"sdk\", \"llm\", \"xl\"]);\n\nfunction prettyToken(token: string): string {\n if (ACRONYMS.has(token.toLowerCase())) return token.toUpperCase();\n return token.charAt(0).toUpperCase() + token.slice(1);\n}\n\n/**\n * Turn a model id into a best-effort human label: strip the routing/vendor\n * prefix to the core model segment, split on `-`/`_`/`.`/whitespace, title-case\n * each token (known acronyms upper-cased), and append an OpenRouter `:variant`\n * in parentheses. Deterministic, pure, dependency-free.\n *\n * Best-effort, NOT vendor-canonical: `\"anthropic/claude-3-5-sonnet\"` →\n * `\"Claude 3 5 Sonnet\"`. A UI wanting exact marketing names overrides per id.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function humanizeModelName(modelId: string): string {\n const { name } = parseModelId(modelId);\n if (name.length === 0) return \"\";\n const colon = name.indexOf(\":\");\n // Strip a trailing slash so a typo'd `gpt-4o/` keeps its name (not lost to an\n // empty last segment).\n const base = (colon >= 0 ? name.slice(0, colon) : name).replace(/\\/+$/, \"\");\n const variant = colon >= 0 ? name.slice(colon + 1) : \"\";\n const lastSlash = base.lastIndexOf(\"/\");\n const core = lastSlash >= 0 ? base.slice(lastSlash + 1) : base;\n const label = core\n .split(/[-_.\\s]+/)\n .filter((t) => t.length > 0)\n .map(prettyToken)\n .join(\" \");\n if (label.length === 0) return variant; // no base label (e.g. \":free\") → bare variant\n return variant.length > 0 ? `${label} (${variant})` : label;\n}\n\n/**\n * Build a {@link ModelOption} (`{ value, label, provider }`) for a model id —\n * a dropdown-ready entry composing {@link humanizeModelName} + `parseModelId`.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function toModelOption(modelId: string): ModelOption {\n return {\n value: modelId,\n label: humanizeModelName(modelId),\n provider: parseModelId(modelId).provider,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/llm/model-capabilities.ts","../src/internal/llm/model-identifier.ts","../src/internal/llm/model-option.ts"],"names":[],"mappings":"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","file":"models.cjs","sourcesContent":["/**\n * T3.10c — Model capability registry (DR3 #17).\n *\n * Typed per-model flags that let the SDK gate features at the boundary\n * (before hitting the provider) instead of letting opaque 400s surface.\n *\n * Resolution algorithm:\n * 1. Strip routing prefixes (openrouter/, vertex/, bedrock/) AND the\n * OpenRouter `:variant` suffix (:free/:nitro/…) to find the bare vendor id.\n * 2. Exact match in the `EXACT` catalog → return entry.\n * 3. Vendor inference (e.g., `claude-*` → `anthropic/claude-*`) → return entry.\n * 4. No match → conservative defaults (all false, minimum tokens).\n *\n * Module is internal, but `ModelCapabilities` + `resolveModelCapabilities` are\n * re-exported publicly via the `@theokit/sdk/models` subpath (see their @public tags).\n */\n\n/**\n * Per-model capability shape. Consumers use this to gate features at\n * the SDK boundary (before request construction, not after 400).\n *\n * @public\n */\nexport interface ModelCapabilities {\n supportsVision: boolean;\n supportsStructuredOutput: boolean;\n supportsToolUse: boolean;\n supportsCacheControl: boolean;\n maxContextTokens: number;\n maxOutputTokens: number;\n}\n\nconst CONSERVATIVE_DEFAULTS: ModelCapabilities = {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: false,\n supportsCacheControl: false,\n maxContextTokens: 4096,\n maxOutputTokens: 4096,\n};\n\n/** Exact-match capability entries. Keys are `vendor/model` (no routing prefix). */\nconst EXACT: ReadonlyMap<string, ModelCapabilities> = new Map([\n // OpenAI family\n [\n \"openai/gpt-4o\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4o-mini\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4-turbo\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"openai/o1\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n [\n \"openai/o3\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n [\n // GPT-4.1 — 1M-context flagship; multimodal + structured output (RADAR #92.a).\n \"openai/gpt-4.1\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_047_576,\n maxOutputTokens: 32_768,\n },\n ],\n // Anthropic family\n [\n \"anthropic/claude-opus-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 32_000,\n },\n ],\n [\n \"anthropic/claude-sonnet-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 16_000,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet-latest\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-haiku-latest\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-haiku\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"anthropic/claude-3-opus\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n // Dot-form OpenRouter slugs theocode uses (RADAR #92.a). These are the same\n // models as their dash-form siblings above; capability parity is intentional.\n // Without these entries the dotted slugs fall through to the 4096 default\n // (`anthropic/claude-3.5-sonnet` ≠ `anthropic/claude-3-5-sonnet`).\n [\n \"anthropic/claude-opus-4.1\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 32_000,\n },\n ],\n [\n \"anthropic/claude-sonnet-4.5\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 16_000,\n },\n ],\n [\n \"anthropic/claude-3.5-sonnet\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n // Cheap OpenRouter slugs (RADAR #92.a) — previously fell to the 4096\n // CONSERVATIVE default. toolUse on; vision/structuredOutput only for Gemini.\n [\n \"qwen/qwen3-coder-30b-a3b-instruct\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 160_000,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"deepseek/deepseek-v4-flash\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_048_576,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"deepseek/deepseek-v3.2\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 131_072,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"z-ai/glm-4.7-flash\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 202_752,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"google/gemini-2.5-flash-lite\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_048_576,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"google/gemini-2.5-pro\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_048_576,\n maxOutputTokens: 8000,\n },\n ],\n]);\n\n/** Routing prefixes to strip to find the underlying vendor model. */\nconst ROUTING_PREFIXES = [\"openrouter/\", \"vertex/\", \"bedrock/\"] as const;\n\n/**\n * Resolve per-model capability flags (vision/structured-output/tool-use/cache +\n * `maxContextTokens`/`maxOutputTokens`) for a model id. Pure, sync, offline (a\n * static catalog — no network). Strips routing prefixes (`openrouter/`/`vertex/`/\n * `bedrock/`) and OpenRouter `:variant` suffixes before lookup; unknown models get\n * conservative defaults. Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function resolveModelCapabilities(modelId: string): ModelCapabilities {\n const bare = stripVariantSuffix(stripRoutingPrefix(modelId));\n const exact = EXACT.get(bare);\n if (exact !== undefined) return exact;\n // Routing-prefixed models (vertex/claude-3-5-sonnet) strip to bare\n // model name without vendor. Try inferring the vendor from the name.\n const withVendor = inferVendorPrefix(bare);\n if (withVendor !== bare) {\n const vendored = EXACT.get(withVendor);\n if (vendored !== undefined) return vendored;\n }\n return CONSERVATIVE_DEFAULTS;\n}\n\nfunction stripRoutingPrefix(modelId: string): string {\n for (const prefix of ROUTING_PREFIXES) {\n if (modelId.startsWith(prefix)) return modelId.slice(prefix.length);\n }\n return modelId;\n}\n\n/**\n * Strip an OpenRouter variant suffix (`:free`/`:nitro`/`:floor`/`:beta`/…) so the\n * catalog lookup hits the underlying model. Model slugs contain no `:` except the\n * variant separator, so cutting at the first `:` is safe.\n */\nfunction stripVariantSuffix(modelId: string): string {\n const i = modelId.indexOf(\":\");\n return i >= 0 ? modelId.slice(0, i) : modelId;\n}\n\n/** Infer vendor prefix from bare model name for routing-prefixed lookups. */\nfunction inferVendorPrefix(bare: string): string {\n if (bare.startsWith(\"claude\")) return `anthropic/${bare}`;\n if (bare.startsWith(\"gpt-\") || bare.startsWith(\"o1\") || bare.startsWith(\"o3\"))\n return `openai/${bare}`;\n if (bare.startsWith(\"gemini\")) return `google/${bare}`;\n return bare;\n}\n","/**\n * Model identifier parsing (T1.2 follow-up, ADR D182 zero-config UX).\n *\n * SDK callers pass model strings like:\n * - `\"ollama/llama3.2:3b\"` → provider=\"ollama\", name=\"llama3.2:3b\"\n * - `\"anthropic/claude-3-5-sonnet\"` → provider=\"anthropic\", name=\"claude-3-5-sonnet\"\n * - `\"openrouter/meta-llama/llama-3\"` → provider=\"openrouter\", name=\"meta-llama/llama-3\"\n * - `\"claude-sonnet-4-6\"` → provider=undefined, name=\"claude-sonnet-4-6\"\n *\n * The first `/` separates the provider from the rest. Models with embedded\n * slashes (e.g. OpenRouter routing) keep the remainder intact. Tag suffixes\n * (`:latest`, `:3b`) are preserved as part of the name — Ollama expects them.\n *\n * **Returns `undefined` provider** when no `/` is present so callers can\n * fall back to env-var detection. Empty/whitespace components are treated\n * as no-prefix.\n *\n * Aligned with OpenClaw `extensions/ollama/src/discovery-shared.ts`\n * (`OLLAMA_PROVIDER_ID = \"ollama\"`) and Hermes `hermes_cli/providers.py`\n * (ALIASES table, `normalize_provider`).\n *\n * Public via `@theokit/sdk/models` (M5-8).\n *\n * @public\n */\n\nexport interface ParsedModelId {\n /** Provider name extracted from the prefix (lowercase), or undefined. */\n provider: string | undefined;\n /** Model name to send to the provider — prefix stripped. */\n name: string;\n}\n\n/** Provider aliases mirrored from Hermes `hermes_cli/providers.py` ALIASES. */\nconst PROVIDER_ALIASES: Readonly<Record<string, string>> = {\n \"llama-cpp\": \"llamacpp\",\n \"llama.cpp\": \"llamacpp\",\n \"lm-studio\": \"lmstudio\",\n lm_studio: \"lmstudio\",\n};\n\nexport function parseModelId(modelId: string | undefined): ParsedModelId {\n if (modelId === undefined || modelId.length === 0) {\n return { provider: undefined, name: \"\" };\n }\n const slash = modelId.indexOf(\"/\");\n if (slash <= 0 || slash === modelId.length - 1) {\n return { provider: undefined, name: modelId };\n }\n const rawProvider = modelId.slice(0, slash).trim().toLowerCase();\n const name = modelId.slice(slash + 1).trim();\n if (rawProvider.length === 0 || name.length === 0) {\n return { provider: undefined, name: modelId };\n }\n const canonical = PROVIDER_ALIASES[rawProvider] ?? rawProvider;\n return { provider: canonical, name };\n}\n","import { parseModelId } from \"./model-identifier.js\";\n\n/**\n * A UI-friendly model option — the shape a `<select>`/dropdown consumes.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport interface ModelOption {\n /** The original model id (what you pass back to the SDK). */\n value: string;\n /** Best-effort human label (see {@link humanizeModelName}). */\n label: string;\n /** Provider from the slug prefix, or `undefined` when none. */\n provider: string | undefined;\n}\n\n/** Tokens rendered upper-case rather than title-case. */\nconst ACRONYMS = new Set([\"gpt\", \"ai\", \"hd\", \"ui\", \"api\", \"sdk\", \"llm\", \"xl\"]);\n\nfunction prettyToken(token: string): string {\n if (ACRONYMS.has(token.toLowerCase())) return token.toUpperCase();\n return token.charAt(0).toUpperCase() + token.slice(1);\n}\n\n/**\n * Turn a model id into a best-effort human label: strip the routing/vendor\n * prefix to the core model segment, split on `-`/`_`/`.`/whitespace, title-case\n * each token (known acronyms upper-cased), and append an OpenRouter `:variant`\n * in parentheses. Deterministic, pure, dependency-free.\n *\n * Best-effort, NOT vendor-canonical: `\"anthropic/claude-3-5-sonnet\"` →\n * `\"Claude 3 5 Sonnet\"`. A UI wanting exact marketing names overrides per id.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function humanizeModelName(modelId: string): string {\n const { name } = parseModelId(modelId);\n if (name.length === 0) return \"\";\n const colon = name.indexOf(\":\");\n // Strip a trailing slash so a typo'd `gpt-4o/` keeps its name (not lost to an\n // empty last segment).\n const base = (colon >= 0 ? name.slice(0, colon) : name).replace(/\\/+$/, \"\");\n const variant = colon >= 0 ? name.slice(colon + 1) : \"\";\n const lastSlash = base.lastIndexOf(\"/\");\n const core = lastSlash >= 0 ? base.slice(lastSlash + 1) : base;\n const label = core\n .split(/[-_.\\s]+/)\n .filter((t) => t.length > 0)\n .map(prettyToken)\n .join(\" \");\n if (label.length === 0) return variant; // no base label (e.g. \":free\") → bare variant\n return variant.length > 0 ? `${label} (${variant})` : label;\n}\n\n/**\n * Build a {@link ModelOption} (`{ value, label, provider }`) for a model id —\n * a dropdown-ready entry composing {@link humanizeModelName} + `parseModelId`.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function toModelOption(modelId: string): ModelOption {\n return {\n value: modelId,\n label: humanizeModelName(modelId),\n provider: parseModelId(modelId).provider,\n };\n}\n"]}
package/dist/models.js CHANGED
@@ -64,6 +64,18 @@ var EXACT = /* @__PURE__ */ new Map([
64
64
  maxOutputTokens: 1e5
65
65
  }
66
66
  ],
67
+ [
68
+ // GPT-4.1 — 1M-context flagship; multimodal + structured output (RADAR #92.a).
69
+ "openai/gpt-4.1",
70
+ {
71
+ supportsVision: true,
72
+ supportsStructuredOutput: true,
73
+ supportsToolUse: true,
74
+ supportsCacheControl: false,
75
+ maxContextTokens: 1047576,
76
+ maxOutputTokens: 32768
77
+ }
78
+ ],
67
79
  // Anthropic family
68
80
  [
69
81
  "anthropic/claude-opus-4",
@@ -141,6 +153,111 @@ var EXACT = /* @__PURE__ */ new Map([
141
153
  maxContextTokens: 2e5,
142
154
  maxOutputTokens: 4096
143
155
  }
156
+ ],
157
+ // Dot-form OpenRouter slugs theocode uses (RADAR #92.a). These are the same
158
+ // models as their dash-form siblings above; capability parity is intentional.
159
+ // Without these entries the dotted slugs fall through to the 4096 default
160
+ // (`anthropic/claude-3.5-sonnet` ≠ `anthropic/claude-3-5-sonnet`).
161
+ [
162
+ "anthropic/claude-opus-4.1",
163
+ {
164
+ supportsVision: true,
165
+ supportsStructuredOutput: false,
166
+ supportsToolUse: true,
167
+ supportsCacheControl: true,
168
+ maxContextTokens: 2e5,
169
+ maxOutputTokens: 32e3
170
+ }
171
+ ],
172
+ [
173
+ "anthropic/claude-sonnet-4.5",
174
+ {
175
+ supportsVision: true,
176
+ supportsStructuredOutput: false,
177
+ supportsToolUse: true,
178
+ supportsCacheControl: true,
179
+ maxContextTokens: 2e5,
180
+ maxOutputTokens: 16e3
181
+ }
182
+ ],
183
+ [
184
+ "anthropic/claude-3.5-sonnet",
185
+ {
186
+ supportsVision: true,
187
+ supportsStructuredOutput: false,
188
+ supportsToolUse: true,
189
+ supportsCacheControl: true,
190
+ maxContextTokens: 2e5,
191
+ maxOutputTokens: 8192
192
+ }
193
+ ],
194
+ // Cheap OpenRouter slugs (RADAR #92.a) — previously fell to the 4096
195
+ // CONSERVATIVE default. toolUse on; vision/structuredOutput only for Gemini.
196
+ [
197
+ "qwen/qwen3-coder-30b-a3b-instruct",
198
+ {
199
+ supportsVision: false,
200
+ supportsStructuredOutput: false,
201
+ supportsToolUse: true,
202
+ supportsCacheControl: false,
203
+ maxContextTokens: 16e4,
204
+ maxOutputTokens: 8e3
205
+ }
206
+ ],
207
+ [
208
+ "deepseek/deepseek-v4-flash",
209
+ {
210
+ supportsVision: false,
211
+ supportsStructuredOutput: false,
212
+ supportsToolUse: true,
213
+ supportsCacheControl: false,
214
+ maxContextTokens: 1048576,
215
+ maxOutputTokens: 8e3
216
+ }
217
+ ],
218
+ [
219
+ "deepseek/deepseek-v3.2",
220
+ {
221
+ supportsVision: false,
222
+ supportsStructuredOutput: false,
223
+ supportsToolUse: true,
224
+ supportsCacheControl: false,
225
+ maxContextTokens: 131072,
226
+ maxOutputTokens: 8e3
227
+ }
228
+ ],
229
+ [
230
+ "z-ai/glm-4.7-flash",
231
+ {
232
+ supportsVision: false,
233
+ supportsStructuredOutput: false,
234
+ supportsToolUse: true,
235
+ supportsCacheControl: false,
236
+ maxContextTokens: 202752,
237
+ maxOutputTokens: 8e3
238
+ }
239
+ ],
240
+ [
241
+ "google/gemini-2.5-flash-lite",
242
+ {
243
+ supportsVision: true,
244
+ supportsStructuredOutput: true,
245
+ supportsToolUse: true,
246
+ supportsCacheControl: false,
247
+ maxContextTokens: 1048576,
248
+ maxOutputTokens: 8e3
249
+ }
250
+ ],
251
+ [
252
+ "google/gemini-2.5-pro",
253
+ {
254
+ supportsVision: true,
255
+ supportsStructuredOutput: true,
256
+ supportsToolUse: true,
257
+ supportsCacheControl: false,
258
+ maxContextTokens: 1048576,
259
+ maxOutputTokens: 8e3
260
+ }
144
261
  ]
145
262
  ]);
146
263
  var ROUTING_PREFIXES = ["openrouter/", "vertex/", "bedrock/"];
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/llm/model-capabilities.ts","../src/internal/llm/model-identifier.ts","../src/internal/llm/model-option.ts"],"names":[],"mappings":"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","file":"models.js","sourcesContent":["/**\n * T3.10c — Model capability registry (DR3 #17).\n *\n * Typed per-model flags that let the SDK gate features at the boundary\n * (before hitting the provider) instead of letting opaque 400s surface.\n *\n * Resolution algorithm:\n * 1. Strip routing prefixes (openrouter/, vertex/, bedrock/) AND the\n * OpenRouter `:variant` suffix (:free/:nitro/…) to find the bare vendor id.\n * 2. Exact match in the `EXACT` catalog → return entry.\n * 3. Vendor inference (e.g., `claude-*` → `anthropic/claude-*`) → return entry.\n * 4. No match → conservative defaults (all false, minimum tokens).\n *\n * Module is internal, but `ModelCapabilities` + `resolveModelCapabilities` are\n * re-exported publicly via the `@theokit/sdk/models` subpath (see their @public tags).\n */\n\n/**\n * Per-model capability shape. Consumers use this to gate features at\n * the SDK boundary (before request construction, not after 400).\n *\n * @public\n */\nexport interface ModelCapabilities {\n supportsVision: boolean;\n supportsStructuredOutput: boolean;\n supportsToolUse: boolean;\n supportsCacheControl: boolean;\n maxContextTokens: number;\n maxOutputTokens: number;\n}\n\nconst CONSERVATIVE_DEFAULTS: ModelCapabilities = {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: false,\n supportsCacheControl: false,\n maxContextTokens: 4096,\n maxOutputTokens: 4096,\n};\n\n/** Exact-match capability entries. Keys are `vendor/model` (no routing prefix). */\nconst EXACT: ReadonlyMap<string, ModelCapabilities> = new Map([\n // OpenAI family\n [\n \"openai/gpt-4o\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4o-mini\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4-turbo\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"openai/o1\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n [\n \"openai/o3\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n // Anthropic family\n [\n \"anthropic/claude-opus-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 32_000,\n },\n ],\n [\n \"anthropic/claude-sonnet-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 16_000,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet-latest\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-haiku-latest\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-haiku\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"anthropic/claude-3-opus\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n]);\n\n/** Routing prefixes to strip to find the underlying vendor model. */\nconst ROUTING_PREFIXES = [\"openrouter/\", \"vertex/\", \"bedrock/\"] as const;\n\n/**\n * Resolve per-model capability flags (vision/structured-output/tool-use/cache +\n * `maxContextTokens`/`maxOutputTokens`) for a model id. Pure, sync, offline (a\n * static catalog — no network). Strips routing prefixes (`openrouter/`/`vertex/`/\n * `bedrock/`) and OpenRouter `:variant` suffixes before lookup; unknown models get\n * conservative defaults. Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function resolveModelCapabilities(modelId: string): ModelCapabilities {\n const bare = stripVariantSuffix(stripRoutingPrefix(modelId));\n const exact = EXACT.get(bare);\n if (exact !== undefined) return exact;\n // Routing-prefixed models (vertex/claude-3-5-sonnet) strip to bare\n // model name without vendor. Try inferring the vendor from the name.\n const withVendor = inferVendorPrefix(bare);\n if (withVendor !== bare) {\n const vendored = EXACT.get(withVendor);\n if (vendored !== undefined) return vendored;\n }\n return CONSERVATIVE_DEFAULTS;\n}\n\nfunction stripRoutingPrefix(modelId: string): string {\n for (const prefix of ROUTING_PREFIXES) {\n if (modelId.startsWith(prefix)) return modelId.slice(prefix.length);\n }\n return modelId;\n}\n\n/**\n * Strip an OpenRouter variant suffix (`:free`/`:nitro`/`:floor`/`:beta`/…) so the\n * catalog lookup hits the underlying model. Model slugs contain no `:` except the\n * variant separator, so cutting at the first `:` is safe.\n */\nfunction stripVariantSuffix(modelId: string): string {\n const i = modelId.indexOf(\":\");\n return i >= 0 ? modelId.slice(0, i) : modelId;\n}\n\n/** Infer vendor prefix from bare model name for routing-prefixed lookups. */\nfunction inferVendorPrefix(bare: string): string {\n if (bare.startsWith(\"claude\")) return `anthropic/${bare}`;\n if (bare.startsWith(\"gpt-\") || bare.startsWith(\"o1\") || bare.startsWith(\"o3\"))\n return `openai/${bare}`;\n if (bare.startsWith(\"gemini\")) return `google/${bare}`;\n return bare;\n}\n","/**\n * Model identifier parsing (T1.2 follow-up, ADR D182 zero-config UX).\n *\n * SDK callers pass model strings like:\n * - `\"ollama/llama3.2:3b\"` → provider=\"ollama\", name=\"llama3.2:3b\"\n * - `\"anthropic/claude-3-5-sonnet\"` → provider=\"anthropic\", name=\"claude-3-5-sonnet\"\n * - `\"openrouter/meta-llama/llama-3\"` → provider=\"openrouter\", name=\"meta-llama/llama-3\"\n * - `\"claude-sonnet-4-6\"` → provider=undefined, name=\"claude-sonnet-4-6\"\n *\n * The first `/` separates the provider from the rest. Models with embedded\n * slashes (e.g. OpenRouter routing) keep the remainder intact. Tag suffixes\n * (`:latest`, `:3b`) are preserved as part of the name — Ollama expects them.\n *\n * **Returns `undefined` provider** when no `/` is present so callers can\n * fall back to env-var detection. Empty/whitespace components are treated\n * as no-prefix.\n *\n * Aligned with OpenClaw `extensions/ollama/src/discovery-shared.ts`\n * (`OLLAMA_PROVIDER_ID = \"ollama\"`) and Hermes `hermes_cli/providers.py`\n * (ALIASES table, `normalize_provider`).\n *\n * Public via `@theokit/sdk/models` (M5-8).\n *\n * @public\n */\n\nexport interface ParsedModelId {\n /** Provider name extracted from the prefix (lowercase), or undefined. */\n provider: string | undefined;\n /** Model name to send to the provider — prefix stripped. */\n name: string;\n}\n\n/** Provider aliases mirrored from Hermes `hermes_cli/providers.py` ALIASES. */\nconst PROVIDER_ALIASES: Readonly<Record<string, string>> = {\n \"llama-cpp\": \"llamacpp\",\n \"llama.cpp\": \"llamacpp\",\n \"lm-studio\": \"lmstudio\",\n lm_studio: \"lmstudio\",\n};\n\nexport function parseModelId(modelId: string | undefined): ParsedModelId {\n if (modelId === undefined || modelId.length === 0) {\n return { provider: undefined, name: \"\" };\n }\n const slash = modelId.indexOf(\"/\");\n if (slash <= 0 || slash === modelId.length - 1) {\n return { provider: undefined, name: modelId };\n }\n const rawProvider = modelId.slice(0, slash).trim().toLowerCase();\n const name = modelId.slice(slash + 1).trim();\n if (rawProvider.length === 0 || name.length === 0) {\n return { provider: undefined, name: modelId };\n }\n const canonical = PROVIDER_ALIASES[rawProvider] ?? rawProvider;\n return { provider: canonical, name };\n}\n","import { parseModelId } from \"./model-identifier.js\";\n\n/**\n * A UI-friendly model option — the shape a `<select>`/dropdown consumes.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport interface ModelOption {\n /** The original model id (what you pass back to the SDK). */\n value: string;\n /** Best-effort human label (see {@link humanizeModelName}). */\n label: string;\n /** Provider from the slug prefix, or `undefined` when none. */\n provider: string | undefined;\n}\n\n/** Tokens rendered upper-case rather than title-case. */\nconst ACRONYMS = new Set([\"gpt\", \"ai\", \"hd\", \"ui\", \"api\", \"sdk\", \"llm\", \"xl\"]);\n\nfunction prettyToken(token: string): string {\n if (ACRONYMS.has(token.toLowerCase())) return token.toUpperCase();\n return token.charAt(0).toUpperCase() + token.slice(1);\n}\n\n/**\n * Turn a model id into a best-effort human label: strip the routing/vendor\n * prefix to the core model segment, split on `-`/`_`/`.`/whitespace, title-case\n * each token (known acronyms upper-cased), and append an OpenRouter `:variant`\n * in parentheses. Deterministic, pure, dependency-free.\n *\n * Best-effort, NOT vendor-canonical: `\"anthropic/claude-3-5-sonnet\"` →\n * `\"Claude 3 5 Sonnet\"`. A UI wanting exact marketing names overrides per id.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function humanizeModelName(modelId: string): string {\n const { name } = parseModelId(modelId);\n if (name.length === 0) return \"\";\n const colon = name.indexOf(\":\");\n // Strip a trailing slash so a typo'd `gpt-4o/` keeps its name (not lost to an\n // empty last segment).\n const base = (colon >= 0 ? name.slice(0, colon) : name).replace(/\\/+$/, \"\");\n const variant = colon >= 0 ? name.slice(colon + 1) : \"\";\n const lastSlash = base.lastIndexOf(\"/\");\n const core = lastSlash >= 0 ? base.slice(lastSlash + 1) : base;\n const label = core\n .split(/[-_.\\s]+/)\n .filter((t) => t.length > 0)\n .map(prettyToken)\n .join(\" \");\n if (label.length === 0) return variant; // no base label (e.g. \":free\") → bare variant\n return variant.length > 0 ? `${label} (${variant})` : label;\n}\n\n/**\n * Build a {@link ModelOption} (`{ value, label, provider }`) for a model id —\n * a dropdown-ready entry composing {@link humanizeModelName} + `parseModelId`.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function toModelOption(modelId: string): ModelOption {\n return {\n value: modelId,\n label: humanizeModelName(modelId),\n provider: parseModelId(modelId).provider,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/llm/model-capabilities.ts","../src/internal/llm/model-identifier.ts","../src/internal/llm/model-option.ts"],"names":[],"mappings":"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","file":"models.js","sourcesContent":["/**\n * T3.10c — Model capability registry (DR3 #17).\n *\n * Typed per-model flags that let the SDK gate features at the boundary\n * (before hitting the provider) instead of letting opaque 400s surface.\n *\n * Resolution algorithm:\n * 1. Strip routing prefixes (openrouter/, vertex/, bedrock/) AND the\n * OpenRouter `:variant` suffix (:free/:nitro/…) to find the bare vendor id.\n * 2. Exact match in the `EXACT` catalog → return entry.\n * 3. Vendor inference (e.g., `claude-*` → `anthropic/claude-*`) → return entry.\n * 4. No match → conservative defaults (all false, minimum tokens).\n *\n * Module is internal, but `ModelCapabilities` + `resolveModelCapabilities` are\n * re-exported publicly via the `@theokit/sdk/models` subpath (see their @public tags).\n */\n\n/**\n * Per-model capability shape. Consumers use this to gate features at\n * the SDK boundary (before request construction, not after 400).\n *\n * @public\n */\nexport interface ModelCapabilities {\n supportsVision: boolean;\n supportsStructuredOutput: boolean;\n supportsToolUse: boolean;\n supportsCacheControl: boolean;\n maxContextTokens: number;\n maxOutputTokens: number;\n}\n\nconst CONSERVATIVE_DEFAULTS: ModelCapabilities = {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: false,\n supportsCacheControl: false,\n maxContextTokens: 4096,\n maxOutputTokens: 4096,\n};\n\n/** Exact-match capability entries. Keys are `vendor/model` (no routing prefix). */\nconst EXACT: ReadonlyMap<string, ModelCapabilities> = new Map([\n // OpenAI family\n [\n \"openai/gpt-4o\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4o-mini\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 16_384,\n },\n ],\n [\n \"openai/gpt-4-turbo\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 128_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"openai/o1\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n [\n \"openai/o3\",\n {\n supportsVision: false,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 200_000,\n maxOutputTokens: 100_000,\n },\n ],\n [\n // GPT-4.1 — 1M-context flagship; multimodal + structured output (RADAR #92.a).\n \"openai/gpt-4.1\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_047_576,\n maxOutputTokens: 32_768,\n },\n ],\n // Anthropic family\n [\n \"anthropic/claude-opus-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 32_000,\n },\n ],\n [\n \"anthropic/claude-sonnet-4\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 16_000,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-sonnet-latest\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-5-haiku-latest\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n [\n \"anthropic/claude-3-haiku\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n [\n \"anthropic/claude-3-opus\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 4096,\n },\n ],\n // Dot-form OpenRouter slugs theocode uses (RADAR #92.a). These are the same\n // models as their dash-form siblings above; capability parity is intentional.\n // Without these entries the dotted slugs fall through to the 4096 default\n // (`anthropic/claude-3.5-sonnet` ≠ `anthropic/claude-3-5-sonnet`).\n [\n \"anthropic/claude-opus-4.1\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 32_000,\n },\n ],\n [\n \"anthropic/claude-sonnet-4.5\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 16_000,\n },\n ],\n [\n \"anthropic/claude-3.5-sonnet\",\n {\n supportsVision: true,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: true,\n maxContextTokens: 200_000,\n maxOutputTokens: 8192,\n },\n ],\n // Cheap OpenRouter slugs (RADAR #92.a) — previously fell to the 4096\n // CONSERVATIVE default. toolUse on; vision/structuredOutput only for Gemini.\n [\n \"qwen/qwen3-coder-30b-a3b-instruct\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 160_000,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"deepseek/deepseek-v4-flash\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_048_576,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"deepseek/deepseek-v3.2\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 131_072,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"z-ai/glm-4.7-flash\",\n {\n supportsVision: false,\n supportsStructuredOutput: false,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 202_752,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"google/gemini-2.5-flash-lite\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_048_576,\n maxOutputTokens: 8000,\n },\n ],\n [\n \"google/gemini-2.5-pro\",\n {\n supportsVision: true,\n supportsStructuredOutput: true,\n supportsToolUse: true,\n supportsCacheControl: false,\n maxContextTokens: 1_048_576,\n maxOutputTokens: 8000,\n },\n ],\n]);\n\n/** Routing prefixes to strip to find the underlying vendor model. */\nconst ROUTING_PREFIXES = [\"openrouter/\", \"vertex/\", \"bedrock/\"] as const;\n\n/**\n * Resolve per-model capability flags (vision/structured-output/tool-use/cache +\n * `maxContextTokens`/`maxOutputTokens`) for a model id. Pure, sync, offline (a\n * static catalog — no network). Strips routing prefixes (`openrouter/`/`vertex/`/\n * `bedrock/`) and OpenRouter `:variant` suffixes before lookup; unknown models get\n * conservative defaults. Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function resolveModelCapabilities(modelId: string): ModelCapabilities {\n const bare = stripVariantSuffix(stripRoutingPrefix(modelId));\n const exact = EXACT.get(bare);\n if (exact !== undefined) return exact;\n // Routing-prefixed models (vertex/claude-3-5-sonnet) strip to bare\n // model name without vendor. Try inferring the vendor from the name.\n const withVendor = inferVendorPrefix(bare);\n if (withVendor !== bare) {\n const vendored = EXACT.get(withVendor);\n if (vendored !== undefined) return vendored;\n }\n return CONSERVATIVE_DEFAULTS;\n}\n\nfunction stripRoutingPrefix(modelId: string): string {\n for (const prefix of ROUTING_PREFIXES) {\n if (modelId.startsWith(prefix)) return modelId.slice(prefix.length);\n }\n return modelId;\n}\n\n/**\n * Strip an OpenRouter variant suffix (`:free`/`:nitro`/`:floor`/`:beta`/…) so the\n * catalog lookup hits the underlying model. Model slugs contain no `:` except the\n * variant separator, so cutting at the first `:` is safe.\n */\nfunction stripVariantSuffix(modelId: string): string {\n const i = modelId.indexOf(\":\");\n return i >= 0 ? modelId.slice(0, i) : modelId;\n}\n\n/** Infer vendor prefix from bare model name for routing-prefixed lookups. */\nfunction inferVendorPrefix(bare: string): string {\n if (bare.startsWith(\"claude\")) return `anthropic/${bare}`;\n if (bare.startsWith(\"gpt-\") || bare.startsWith(\"o1\") || bare.startsWith(\"o3\"))\n return `openai/${bare}`;\n if (bare.startsWith(\"gemini\")) return `google/${bare}`;\n return bare;\n}\n","/**\n * Model identifier parsing (T1.2 follow-up, ADR D182 zero-config UX).\n *\n * SDK callers pass model strings like:\n * - `\"ollama/llama3.2:3b\"` → provider=\"ollama\", name=\"llama3.2:3b\"\n * - `\"anthropic/claude-3-5-sonnet\"` → provider=\"anthropic\", name=\"claude-3-5-sonnet\"\n * - `\"openrouter/meta-llama/llama-3\"` → provider=\"openrouter\", name=\"meta-llama/llama-3\"\n * - `\"claude-sonnet-4-6\"` → provider=undefined, name=\"claude-sonnet-4-6\"\n *\n * The first `/` separates the provider from the rest. Models with embedded\n * slashes (e.g. OpenRouter routing) keep the remainder intact. Tag suffixes\n * (`:latest`, `:3b`) are preserved as part of the name — Ollama expects them.\n *\n * **Returns `undefined` provider** when no `/` is present so callers can\n * fall back to env-var detection. Empty/whitespace components are treated\n * as no-prefix.\n *\n * Aligned with OpenClaw `extensions/ollama/src/discovery-shared.ts`\n * (`OLLAMA_PROVIDER_ID = \"ollama\"`) and Hermes `hermes_cli/providers.py`\n * (ALIASES table, `normalize_provider`).\n *\n * Public via `@theokit/sdk/models` (M5-8).\n *\n * @public\n */\n\nexport interface ParsedModelId {\n /** Provider name extracted from the prefix (lowercase), or undefined. */\n provider: string | undefined;\n /** Model name to send to the provider — prefix stripped. */\n name: string;\n}\n\n/** Provider aliases mirrored from Hermes `hermes_cli/providers.py` ALIASES. */\nconst PROVIDER_ALIASES: Readonly<Record<string, string>> = {\n \"llama-cpp\": \"llamacpp\",\n \"llama.cpp\": \"llamacpp\",\n \"lm-studio\": \"lmstudio\",\n lm_studio: \"lmstudio\",\n};\n\nexport function parseModelId(modelId: string | undefined): ParsedModelId {\n if (modelId === undefined || modelId.length === 0) {\n return { provider: undefined, name: \"\" };\n }\n const slash = modelId.indexOf(\"/\");\n if (slash <= 0 || slash === modelId.length - 1) {\n return { provider: undefined, name: modelId };\n }\n const rawProvider = modelId.slice(0, slash).trim().toLowerCase();\n const name = modelId.slice(slash + 1).trim();\n if (rawProvider.length === 0 || name.length === 0) {\n return { provider: undefined, name: modelId };\n }\n const canonical = PROVIDER_ALIASES[rawProvider] ?? rawProvider;\n return { provider: canonical, name };\n}\n","import { parseModelId } from \"./model-identifier.js\";\n\n/**\n * A UI-friendly model option — the shape a `<select>`/dropdown consumes.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport interface ModelOption {\n /** The original model id (what you pass back to the SDK). */\n value: string;\n /** Best-effort human label (see {@link humanizeModelName}). */\n label: string;\n /** Provider from the slug prefix, or `undefined` when none. */\n provider: string | undefined;\n}\n\n/** Tokens rendered upper-case rather than title-case. */\nconst ACRONYMS = new Set([\"gpt\", \"ai\", \"hd\", \"ui\", \"api\", \"sdk\", \"llm\", \"xl\"]);\n\nfunction prettyToken(token: string): string {\n if (ACRONYMS.has(token.toLowerCase())) return token.toUpperCase();\n return token.charAt(0).toUpperCase() + token.slice(1);\n}\n\n/**\n * Turn a model id into a best-effort human label: strip the routing/vendor\n * prefix to the core model segment, split on `-`/`_`/`.`/whitespace, title-case\n * each token (known acronyms upper-cased), and append an OpenRouter `:variant`\n * in parentheses. Deterministic, pure, dependency-free.\n *\n * Best-effort, NOT vendor-canonical: `\"anthropic/claude-3-5-sonnet\"` →\n * `\"Claude 3 5 Sonnet\"`. A UI wanting exact marketing names overrides per id.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function humanizeModelName(modelId: string): string {\n const { name } = parseModelId(modelId);\n if (name.length === 0) return \"\";\n const colon = name.indexOf(\":\");\n // Strip a trailing slash so a typo'd `gpt-4o/` keeps its name (not lost to an\n // empty last segment).\n const base = (colon >= 0 ? name.slice(0, colon) : name).replace(/\\/+$/, \"\");\n const variant = colon >= 0 ? name.slice(colon + 1) : \"\";\n const lastSlash = base.lastIndexOf(\"/\");\n const core = lastSlash >= 0 ? base.slice(lastSlash + 1) : base;\n const label = core\n .split(/[-_.\\s]+/)\n .filter((t) => t.length > 0)\n .map(prettyToken)\n .join(\" \");\n if (label.length === 0) return variant; // no base label (e.g. \":free\") → bare variant\n return variant.length > 0 ? `${label} (${variant})` : label;\n}\n\n/**\n * Build a {@link ModelOption} (`{ value, label, provider }`) for a model id —\n * a dropdown-ready entry composing {@link humanizeModelName} + `parseModelId`.\n *\n * Public via `@theokit/sdk/models`.\n *\n * @public\n */\nexport function toModelOption(modelId: string): ModelOption {\n return {\n value: modelId,\n label: humanizeModelName(modelId),\n provider: parseModelId(modelId).provider,\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theokit/sdk",
3
- "version": "2.10.0",
3
+ "version": "2.11.1",
4
4
  "description": "TypeScript SDK for the Theo agent harness — same surface, local or cloud.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/usetheo/theokit-sdk#readme",
@@ -298,15 +298,6 @@
298
298
  "**/agent.js",
299
299
  "**/agent.cjs"
300
300
  ],
301
- "scripts": {
302
- "build": "tsup && cp src/internal/providers/provider-catalog.json dist/provider-catalog.json",
303
- "test": "vitest run --no-file-parallelism",
304
- "test:watch": "vitest",
305
- "typecheck": "tsc --noEmit",
306
- "clean": "rm -rf dist",
307
- "docs:json": "typedoc --options typedoc.json",
308
- "docs:drift": "tsx scripts/check-docs-drift.ts"
309
- },
310
301
  "peerDependencies": {
311
302
  "@lancedb/lancedb": "^0.30.0",
312
303
  "@types/ws": ">=8.0.0",
@@ -363,8 +354,6 @@
363
354
  "devDependencies": {
364
355
  "@opentelemetry/api": "^1.9.1",
365
356
  "@opentelemetry/sdk-trace-base": "^1.30.1",
366
- "@theokit/sdk-handoff": "workspace:*",
367
- "@theokit/sdk-memory": "workspace:*",
368
357
  "@types/better-sqlite3": "^7.6.13",
369
358
  "@types/proper-lockfile": "^4.1.4",
370
359
  "@types/ws": "^8.18.0",
@@ -374,6 +363,17 @@
374
363
  "sqlite-vec": "^0.1.9",
375
364
  "typedoc": "^0.28.19",
376
365
  "ws": "^8.18.0",
377
- "zod": "^4.0.0"
366
+ "zod": "^4.0.0",
367
+ "@theokit/sdk-handoff": "0.1.0",
368
+ "@theokit/sdk-memory": "0.2.0"
369
+ },
370
+ "scripts": {
371
+ "build": "tsup && cp src/internal/providers/provider-catalog.json dist/provider-catalog.json",
372
+ "test": "vitest run --no-file-parallelism",
373
+ "test:watch": "vitest",
374
+ "typecheck": "tsc --noEmit",
375
+ "clean": "rm -rf dist",
376
+ "docs:json": "typedoc --options typedoc.json",
377
+ "docs:drift": "tsx scripts/check-docs-drift.ts"
378
378
  }
379
- }
379
+ }