@deepstrike/sdk 0.2.52 → 0.2.61

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.
Files changed (151) hide show
  1. package/README.md +28 -28
  2. package/dist/agent-ir.d.ts +103 -0
  3. package/dist/agent-ir.js +134 -0
  4. package/dist/agent.d.ts +67 -0
  5. package/dist/agent.js +36 -0
  6. package/dist/collaboration/harness.js +1 -1
  7. package/dist/collaboration/modes/creator-verifier.d.ts +2 -7
  8. package/dist/collaboration/modes/creator-verifier.js +4 -6
  9. package/dist/collaboration/pool.d.ts +8 -20
  10. package/dist/collaboration/pool.js +27 -97
  11. package/dist/compat/anthropic/mcp.d.ts +15 -0
  12. package/dist/compat/anthropic/mcp.js +10 -0
  13. package/dist/compat/openai/agent.d.ts +34 -0
  14. package/dist/compat/openai/agent.js +24 -0
  15. package/dist/governance.d.ts +1 -17
  16. package/dist/governance.js +1 -34
  17. package/dist/guardrail.d.ts +6 -0
  18. package/dist/guardrail.js +1 -0
  19. package/dist/handoff-target.d.ts +12 -0
  20. package/dist/handoff-target.js +1 -0
  21. package/dist/harness/manifest.js +0 -4
  22. package/dist/index.d.ts +19 -7
  23. package/dist/index.js +8 -5
  24. package/dist/kernel.d.ts +2 -20
  25. package/dist/knowledge/public.d.ts +29 -0
  26. package/dist/knowledge/public.js +1 -0
  27. package/dist/mcp-server.d.ts +28 -0
  28. package/dist/mcp-server.js +1 -0
  29. package/dist/memory/agent.d.ts +2 -2
  30. package/dist/memory/agent.js +2 -2
  31. package/dist/memory/durable.d.ts +16 -0
  32. package/dist/memory/durable.js +46 -0
  33. package/dist/memory/in-memory-store.d.ts +9 -7
  34. package/dist/memory/in-memory-store.js +8 -2
  35. package/dist/memory/protocols.d.ts +22 -4
  36. package/dist/memory/public.d.ts +4 -3
  37. package/dist/memory/public.js +3 -2
  38. package/dist/os/public.d.ts +1 -1
  39. package/dist/os/public.js +1 -1
  40. package/dist/providers/anthropic-adapter.d.ts +59 -0
  41. package/dist/providers/anthropic-adapter.js +530 -0
  42. package/dist/providers/anthropic-compatible.d.ts +2 -3
  43. package/dist/providers/anthropic-compatible.js +8 -5
  44. package/dist/providers/anthropic.d.ts +20 -23
  45. package/dist/providers/anthropic.js +176 -395
  46. package/dist/providers/base.d.ts +2 -2
  47. package/dist/providers/base.js +50 -8
  48. package/dist/providers/capability-router.d.ts +29 -0
  49. package/dist/providers/capability-router.js +43 -0
  50. package/dist/providers/catalog.d.ts +16 -4
  51. package/dist/providers/catalog.js +112 -36
  52. package/dist/providers/content-normalization.d.ts +57 -0
  53. package/dist/providers/content-normalization.js +238 -0
  54. package/dist/providers/content-policy.d.ts +16 -0
  55. package/dist/providers/content-policy.js +39 -0
  56. package/dist/providers/credentials.d.ts +83 -0
  57. package/dist/providers/credentials.js +190 -0
  58. package/dist/providers/endpoints.d.ts +137 -0
  59. package/dist/providers/endpoints.js +128 -0
  60. package/dist/providers/factories.js +25 -9
  61. package/dist/providers/gemini-adapter.d.ts +33 -0
  62. package/dist/providers/gemini-adapter.js +264 -0
  63. package/dist/providers/gemini.d.ts +16 -3
  64. package/dist/providers/gemini.js +97 -195
  65. package/dist/providers/model-catalog.d.ts +37 -0
  66. package/dist/providers/model-catalog.js +62 -0
  67. package/dist/providers/model-registry.d.ts +119 -0
  68. package/dist/providers/model-registry.js +379 -0
  69. package/dist/providers/ollama-adapter.d.ts +65 -0
  70. package/dist/providers/ollama-adapter.js +188 -0
  71. package/dist/providers/ollama.d.ts +9 -4
  72. package/dist/providers/ollama.js +96 -109
  73. package/dist/providers/openai-chat-dialects.d.ts +154 -0
  74. package/dist/providers/openai-chat-dialects.js +179 -0
  75. package/dist/providers/openai-chat.d.ts +46 -18
  76. package/dist/providers/openai-chat.js +416 -51
  77. package/dist/providers/openai-responses-adapter.d.ts +42 -0
  78. package/dist/providers/openai-responses-adapter.js +343 -0
  79. package/dist/providers/openai-responses.d.ts +19 -33
  80. package/dist/providers/openai-responses.js +164 -264
  81. package/dist/providers/openai.d.ts +29 -76
  82. package/dist/providers/openai.js +195 -292
  83. package/dist/providers/protocol-adapter.d.ts +39 -0
  84. package/dist/providers/protocol-adapter.js +13 -0
  85. package/dist/providers/protocol-capabilities.d.ts +34 -0
  86. package/dist/providers/protocol-capabilities.js +44 -0
  87. package/dist/providers/provider-error.d.ts +31 -0
  88. package/dist/providers/provider-error.js +153 -0
  89. package/dist/providers/public.d.ts +26 -3
  90. package/dist/providers/public.js +13 -1
  91. package/dist/providers/registry.d.ts +7 -6
  92. package/dist/providers/registry.js +47 -20
  93. package/dist/providers/request-plan.d.ts +89 -0
  94. package/dist/providers/request-plan.js +199 -0
  95. package/dist/providers/usage-normalizer.d.ts +48 -0
  96. package/dist/providers/usage-normalizer.js +139 -0
  97. package/dist/providers/vendor-profiles.d.ts +2 -15
  98. package/dist/providers/vendor-profiles.js +14 -60
  99. package/dist/runtime/canonical-kernel-step.d.ts +1 -2
  100. package/dist/runtime/canonical-kernel-step.js +47 -12
  101. package/dist/runtime/context-policy.d.ts +10 -12
  102. package/dist/runtime/context-policy.js +6 -8
  103. package/dist/runtime/durable-content.d.ts +50 -0
  104. package/dist/runtime/durable-content.js +159 -0
  105. package/dist/runtime/execution-plane.d.ts +2 -2
  106. package/dist/runtime/execution-plane.js +2 -2
  107. package/dist/runtime/kernel-event-log.js +0 -1
  108. package/dist/runtime/kernel-step.d.ts +0 -1
  109. package/dist/runtime/kernel-step.js +4 -2
  110. package/dist/runtime/mcp-proxy-plane.d.ts +25 -1
  111. package/dist/runtime/mcp-proxy-plane.js +44 -6
  112. package/dist/runtime/output-schema.d.ts +1 -2
  113. package/dist/runtime/provider-replay.d.ts +5 -1
  114. package/dist/runtime/provider-replay.js +26 -27
  115. package/dist/runtime/reactive-session.d.ts +1 -1
  116. package/dist/runtime/reactive-session.js +2 -3
  117. package/dist/runtime/run-group.d.ts +1 -1
  118. package/dist/runtime/runner.d.ts +31 -45
  119. package/dist/runtime/runner.js +178 -63
  120. package/dist/runtime/session-log.d.ts +8 -1
  121. package/dist/runtime/session-log.js +42 -2
  122. package/dist/runtime/session-repair.d.ts +1 -1
  123. package/dist/runtime/session-repair.js +1 -1
  124. package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
  125. package/dist/runtime/sub-agent-orchestrator.js +8 -11
  126. package/dist/runtime/workflow-control-flow.d.ts +0 -4
  127. package/dist/runtime/workflow-control-flow.js +0 -16
  128. package/dist/session.d.ts +11 -0
  129. package/dist/session.js +1 -0
  130. package/dist/skill.d.ts +17 -0
  131. package/dist/skill.js +16 -0
  132. package/dist/skills/loader.d.ts +3 -0
  133. package/dist/tools/errors.d.ts +1 -3
  134. package/dist/tools/errors.js +1 -3
  135. package/dist/tools/index.d.ts +3 -0
  136. package/dist/types/agent.d.ts +21 -9
  137. package/dist/types/agent.js +30 -4
  138. package/dist/types.d.ts +135 -17
  139. package/package.json +4 -4
  140. package/dist/providers/deepseek.d.ts +0 -46
  141. package/dist/providers/deepseek.js +0 -97
  142. package/dist/providers/glm.d.ts +0 -25
  143. package/dist/providers/glm.js +0 -48
  144. package/dist/providers/kimi.d.ts +0 -23
  145. package/dist/providers/kimi.js +0 -30
  146. package/dist/providers/minimax.d.ts +0 -49
  147. package/dist/providers/minimax.js +0 -98
  148. package/dist/providers/profiles.d.ts +0 -1992
  149. package/dist/providers/profiles.js +0 -796
  150. package/dist/providers/qwen.d.ts +0 -38
  151. package/dist/providers/qwen.js +0 -97
@@ -1,163 +1,98 @@
1
1
  import { GoogleGenerativeAI } from "@google/generative-ai";
2
2
  import { withServerRuntimeGuard } from "../runtime/server.js";
3
- import { CircuitBreaker, normalizeToolCall, turnsWithStateAppended } from "./base.js";
4
- import { endpointProfiles } from "./profiles.js";
5
- import { UnsupportedModalityError } from "./base.js";
3
+ import { CircuitBreaker } from "./base.js";
4
+ import { endpointProfiles } from "./endpoints.js";
5
+ import { normalizeCanonicalAdapterInput, normalizeCanonicalContext, } from "./content-normalization.js";
6
+ import { GeminiAdapter, canonicalGeminiContents, geminiVendorConfig } from "./gemini-adapter.js";
7
+ import { circuitOpenError, classifyProviderError } from "./provider-error.js";
6
8
  const GEMINI_BASE = endpointProfiles["gemini.google"].baseURL;
7
- const GEMINI_POLICIES = {
8
- "gemini-3-pro-preview": { maxTurns: 50 },
9
- "gemini-3-flash-preview": { maxTurns: 25 },
10
- "gemini-3.5-flash": { maxTurns: 30 },
11
- "gemini-2.5-pro": { maxTurns: 35 },
12
- "gemini-2.5-flash": { maxTurns: 20 },
13
- "gemini-2.0-flash": { maxTurns: 15 },
14
- "gemini-2.0-flash-lite": { maxTurns: 10 },
15
- "gemini-1.5-pro": { maxTurns: 30 },
16
- "gemini-1.5-flash": { maxTurns: 15 },
17
- };
18
9
  export function buildContents(turns) {
19
- const contents = [];
20
- for (const msg of turns) {
21
- if (msg.role === "tool") {
22
- const parts = (msg.contentParts ?? [])
23
- .filter(p => p.type === "tool_result")
24
- .map(p => {
25
- if (p.type !== "tool_result")
26
- return { text: "" };
27
- let toolName = p.callId;
28
- for (let i = turns.length - 1; i >= 0; i--) {
29
- const turn = turns[i];
30
- if (turn.role === "assistant" && turn.toolCalls) {
31
- const matched = turn.toolCalls.find(tc => tc.id === p.callId);
32
- if (matched) {
33
- toolName = matched.name;
34
- break;
35
- }
36
- }
37
- }
38
- return {
39
- functionResponse: { name: toolName, response: { output: p.output } },
40
- };
41
- });
42
- if (parts.length)
43
- contents.push({ role: "user", parts });
44
- continue;
45
- }
46
- const role = msg.role === "assistant" ? "model" : "user";
47
- const parts = [];
48
- if (msg.toolCalls?.length) {
49
- for (const tc of msg.toolCalls) {
50
- let args = {};
51
- try {
52
- args = JSON.parse(tc.arguments);
53
- }
54
- catch {
55
- args = {};
56
- }
57
- parts.push({ functionCall: { name: tc.name, args } });
58
- }
59
- }
60
- // Multimodal: render contentParts (text + image) when present, else the plain
61
- // text body. Without this, image inputs to Gemini were silently dropped.
62
- if (msg.contentParts?.length) {
63
- for (const p of msg.contentParts) {
64
- if (p.type === "text")
65
- parts.push({ text: p.text });
66
- else if (p.type === "image") {
67
- if (p.data)
68
- parts.push({ inlineData: { mimeType: p.mediaType ?? "image/png", data: p.data } });
69
- else if (p.url)
70
- parts.push({ fileData: { mimeType: p.mediaType ?? "image/png", fileUri: p.url } });
71
- }
72
- else if (p.type === "audio") {
73
- if (!p.data)
74
- throw new UnsupportedModalityError("audio", "gemini");
75
- parts.push({ inlineData: { mimeType: p.mediaType ?? "audio/wav", data: p.data } });
76
- }
77
- else if (p.type === "tool_result") {
78
- // tool results are handled via functionResponse on tool role messages
79
- }
80
- else {
81
- throw new UnsupportedModalityError(String(p.type ?? "unknown"), "gemini");
82
- }
83
- }
84
- }
85
- else if (msg.content) {
86
- parts.push({ text: msg.content });
87
- }
88
- if (parts.length)
89
- contents.push({ role, parts });
90
- }
91
- return contents;
92
- }
93
- function buildTools(tools) {
94
- if (!tools.length)
95
- return [];
96
- return [{
97
- functionDeclarations: tools.map(t => ({
98
- name: t.name,
99
- description: t.description,
100
- parameters: JSON.parse(t.parameters),
101
- })),
102
- }];
10
+ return canonicalGeminiContents(normalizeCanonicalContext({ systemText: "", turns }));
103
11
  }
104
12
  export class GeminiProvider {
105
13
  model;
14
+ resolvedRuntime;
106
15
  genAI;
107
16
  circuit;
108
17
  maxRetries;
109
18
  baseDelay;
110
19
  requestOptions;
111
- constructor(apiKey, model = "gemini-2.0-flash", retry = { maxRetries: 3, baseDelay: 1000 }, baseURL = GEMINI_BASE) {
20
+ resolvedRuntimePolicy;
21
+ adapter = new GeminiAdapter();
22
+ constructor(apiKey, model = "gemini-2.0-flash", retry = { maxRetries: 3, baseDelay: 1000 }, baseURL = GEMINI_BASE, runtimePolicy = {}, resolvedRuntime) {
112
23
  this.model = model;
24
+ this.resolvedRuntime = resolvedRuntime;
113
25
  this.genAI = withServerRuntimeGuard(() => new GoogleGenerativeAI(apiKey));
114
26
  this.circuit = new CircuitBreaker();
115
27
  this.maxRetries = retry.maxRetries;
116
28
  this.baseDelay = retry.baseDelay;
117
29
  this.requestOptions = { baseUrl: baseURL };
30
+ this.resolvedRuntimePolicy = runtimePolicy;
118
31
  }
119
32
  runtimePolicy() {
120
- return GEMINI_POLICIES[this.model] ?? {};
33
+ return this.resolvedRuntimePolicy;
34
+ }
35
+ bindResolvedRuntime(resolved) {
36
+ if (resolved.identity.protocol !== "gemini"
37
+ || resolved.identity.modelId !== this.model) {
38
+ throw new Error("GeminiProvider received a mismatched resolved runtime");
39
+ }
40
+ this.resolvedRuntime = resolved;
41
+ }
42
+ adapterInput(context, tools, extensions) {
43
+ if (!this.resolvedRuntime) {
44
+ // Direct class construction is a published compatibility path. A-07 replaces it with
45
+ // injected runtime profiles; until then this local descriptor contains no Registry lookup.
46
+ const resolved = {
47
+ identity: {
48
+ providerId: "gemini",
49
+ modelId: this.model,
50
+ endpointId: "gemini.google",
51
+ protocol: "gemini",
52
+ },
53
+ model: { id: `gemini/${this.model}`, providerId: "gemini", kind: "generation", intrinsic: {} },
54
+ endpoint: endpointProfiles["gemini.google"],
55
+ adapter: this,
56
+ effectiveCapabilities: {
57
+ inputModalities: Object.fromEntries(["text", "image", "audio", "video", "file"].map(modality => [modality, { state: modality === "video" || modality === "file" ? "unsupported" : "unknown", evidence: [] }])),
58
+ outputModalities: Object.fromEntries(["text", "image", "audio", "embedding"].map(modality => [modality, { state: "unknown", evidence: [] }])),
59
+ tools: { state: "unknown", evidence: [] },
60
+ reasoning: { state: "unknown", evidence: [] },
61
+ parallelToolCalls: { state: "unknown", evidence: [] },
62
+ structuredOutput: { state: "unknown", evidence: [] },
63
+ promptCaching: { state: "unknown", evidence: [] },
64
+ nativeTokenCounting: { state: "unknown", evidence: [] },
65
+ mediaForms: Object.fromEntries(["imageUrl", "imageBase64", "fileId", "audioUrl", "audioBase64"].map(form => [form, { state: "unknown", evidence: [] }])),
66
+ },
67
+ };
68
+ return normalizeCanonicalAdapterInput({ context, tools, resolved, extensions });
69
+ }
70
+ return normalizeCanonicalAdapterInput({
71
+ context,
72
+ tools,
73
+ resolved: this.resolvedRuntime,
74
+ extensions,
75
+ });
121
76
  }
122
77
  async complete(context, tools, extensions) {
123
78
  if (this.circuit.isOpen())
124
- throw new Error("Circuit breaker open");
125
- const system = context.systemText || undefined;
126
- const contents = buildContents(turnsWithStateAppended(context));
127
- const geminiTools = buildTools(tools);
79
+ throw circuitOpenError("gemini");
80
+ let input;
81
+ let plan;
82
+ try {
83
+ input = this.adapterInput(context, tools, extensions);
84
+ plan = this.adapter.buildRequest(input);
85
+ }
86
+ catch (error) {
87
+ throw classifyProviderError("gemini", error);
88
+ }
128
89
  let lastErr;
129
90
  for (let i = 0; i < this.maxRetries; i++) {
130
91
  try {
131
- const vc = this.vendorConfig(extensions);
132
- const allTools = [...geminiTools, ...(vc.tools ?? [])];
133
- const m = this.genAI.getGenerativeModel({
134
- ...this.modelExtensions(extensions),
135
- model: this.model,
136
- ...(system ? { systemInstruction: system } : {}),
137
- ...(allTools.length ? { tools: allTools } : {}),
138
- ...(vc.generationConfig ? { generationConfig: vc.generationConfig } : {}),
139
- }, this.requestOptions);
140
- const resp = await m.generateContent({ contents });
92
+ const m = this.genAI.getGenerativeModel(plan.modelParams, this.requestOptions);
93
+ const resp = await m.generateContent(plan.request);
141
94
  this.circuit.recordSuccess();
142
- const candidate = resp.response.candidates?.[0];
143
- let content = "";
144
- const toolCalls = [];
145
- for (const part of candidate?.content.parts ?? []) {
146
- if (part.text)
147
- content += part.text;
148
- else if (part.functionCall) {
149
- const tc = normalizeToolCall(part.functionCall.name, part.functionCall.name, part.functionCall.args);
150
- if (tc)
151
- toolCalls.push(tc);
152
- }
153
- }
154
- const usage = resp.response.usageMetadata;
155
- return {
156
- role: "assistant",
157
- content,
158
- tokenCount: usage?.candidatesTokenCount ?? usage?.totalTokenCount,
159
- toolCalls,
160
- };
95
+ return this.adapter.decodeComplete(resp.response, { input }).message;
161
96
  }
162
97
  catch (err) {
163
98
  lastErr = err;
@@ -166,60 +101,40 @@ export class GeminiProvider {
166
101
  await new Promise(r => setTimeout(r, this.baseDelay * 2 ** i));
167
102
  }
168
103
  }
169
- throw lastErr;
104
+ throw classifyProviderError("gemini", lastErr);
170
105
  }
171
106
  async *stream(context, tools, extensions) {
172
- const system = context.systemText || undefined;
173
- const contents = buildContents(turnsWithStateAppended(context));
174
- const geminiTools = buildTools(tools);
175
- const vc = this.vendorConfig(extensions);
176
- const allTools = [...geminiTools, ...(vc.tools ?? [])];
177
- const m = this.genAI.getGenerativeModel({
178
- ...this.modelExtensions(extensions),
179
- model: this.model,
180
- ...(system ? { systemInstruction: system } : {}),
181
- ...(allTools.length ? { tools: allTools } : {}),
182
- ...(vc.generationConfig ? { generationConfig: vc.generationConfig } : {}),
183
- }, this.requestOptions);
184
- const result = await m.generateContentStream({ contents });
185
- const toolCalls = [];
186
- for await (const chunk of result.stream) {
187
- for (const part of chunk.candidates?.[0]?.content.parts ?? []) {
188
- if (part.text)
189
- yield { type: "text_delta", delta: part.text };
190
- else if (part.functionCall) {
191
- const { name, args } = part.functionCall;
192
- toolCalls.push({ id: `call_${toolCalls.length + 1}`, name, args: args });
193
- }
107
+ try {
108
+ const input = this.adapterInput(context, tools, extensions);
109
+ const plan = this.adapter.buildRequest(input);
110
+ const m = this.genAI.getGenerativeModel(plan.modelParams, this.requestOptions);
111
+ const result = await m.generateContentStream(plan.request);
112
+ const state = this.adapter.createStreamState({ input });
113
+ for await (const chunk of result.stream) {
114
+ for (const event of this.adapter.pushStreamChunk(chunk, state).events)
115
+ yield event;
194
116
  }
117
+ for (const event of this.adapter.finishStream(state, await result.response).events)
118
+ yield event;
195
119
  }
196
- for (const tc of toolCalls) {
197
- yield { type: "tool_call", id: tc.id, name: tc.name, arguments: tc.args };
198
- }
199
- const usage = (await result.response).usageMetadata;
200
- if (usage?.totalTokenCount) {
201
- // Gemini implicit/explicit cache hits are reported as cachedContentTokenCount,
202
- // a subset of promptTokenCount (which stays the full prompt for accounting).
203
- const cachedTokens = usage.cachedContentTokenCount ?? 0;
204
- yield {
205
- type: "usage",
206
- totalTokens: usage.totalTokenCount,
207
- inputTokens: usage.promptTokenCount ?? 0,
208
- outputTokens: usage.candidatesTokenCount ?? 0,
209
- ...(cachedTokens > 0 ? { cacheReadInputTokens: cachedTokens } : {}),
210
- };
120
+ catch (error) {
121
+ throw classifyProviderError("gemini", error);
211
122
  }
212
123
  }
213
- modelExtensions(extensions) {
214
- if (!extensions)
215
- return {};
216
- // Strip keys handled explicitly elsewhere (incl. the vendor server-tool / structured-output keys
217
- // consumed by `vendorConfig`) so they never leak raw into getGenerativeModel.
218
- // Strip keys handled explicitly: the SDK fields set below + the named vendor keys consumed by
219
- // `vendorConfig`. A caller-provided raw `generationConfig` still passes through (and is merged with
220
- // any structured-output config at the call site).
221
- const { model: _model, systemInstruction: _systemInstruction, tools: _tools, google_search: _gs, response_mime_type: _rmt, response_schema: _rs, ...rest } = extensions;
222
- return rest;
124
+ /**
125
+ * spc_011-C-05: preflight native token count via `GenerativeModel.countTokens` — reuses the
126
+ * same contents/tools/vendorConfig construction `complete()` uses so the counted request and
127
+ * the sent request never diverge.
128
+ */
129
+ async countTokens(context, tools, extensions) {
130
+ const plan = this.adapter.buildRequest(this.adapterInput(context, tools, extensions));
131
+ const m = this.genAI.getGenerativeModel(plan.modelParams, this.requestOptions);
132
+ const resp = await m.countTokens(plan.request);
133
+ return {
134
+ inputTokens: resp.totalTokens,
135
+ source: { kind: "native", provider: "gemini" },
136
+ confidence: "exact",
137
+ };
223
138
  }
224
139
  /**
225
140
  * Gemini vendor features from extensions, mapped to the Node SDK shape (mirrors the Python provider's
@@ -230,19 +145,6 @@ export class GeminiProvider {
230
145
  * pairing this with google_search).
231
146
  */
232
147
  vendorConfig(extensions) {
233
- const ext = extensions ?? {};
234
- const tools = [];
235
- if (ext.google_search)
236
- tools.push({ googleSearch: typeof ext.google_search === "object" ? ext.google_search : {} });
237
- // Seed from any caller-provided raw generationConfig, then layer the named structured-output keys.
238
- const gc = { ...ext.generationConfig };
239
- if (ext.response_mime_type != null)
240
- gc.responseMimeType = ext.response_mime_type;
241
- if (ext.response_schema != null)
242
- gc.responseSchema = ext.response_schema;
243
- return {
244
- ...(tools.length ? { tools } : {}),
245
- ...(Object.keys(gc).length ? { generationConfig: gc } : {}),
246
- };
148
+ return geminiVendorConfig(extensions ?? {});
247
149
  }
248
150
  }
@@ -0,0 +1,37 @@
1
+ import type { ModelRegistration } from "./model-registry.js";
2
+ export type { ModelRegistration } from "./model-registry.js";
3
+ /** A query-only model catalog. Catalogs describe models; selection policy belongs to CapabilityRouter. */
4
+ export interface ModelCatalog {
5
+ list(): Promise<readonly ModelRegistration[]>;
6
+ get(modelId: string): Promise<ModelRegistration | undefined>;
7
+ }
8
+ export interface ModelCatalogSource {
9
+ list(): Promise<readonly ModelRegistration[]>;
10
+ }
11
+ export type ModelCatalogRefreshResult = {
12
+ ok: true;
13
+ } | {
14
+ ok: false;
15
+ errorCode: "refresh_failed";
16
+ };
17
+ /** Immutable, deterministic model facts supplied by the SDK or an application. */
18
+ export declare class StaticModelCatalog implements ModelCatalog {
19
+ private readonly registrations;
20
+ private readonly byId;
21
+ constructor(registrations: readonly ModelRegistration[]);
22
+ list(): Promise<readonly ModelRegistration[]>;
23
+ get(modelId: string): Promise<ModelRegistration | undefined>;
24
+ }
25
+ /**
26
+ * A host-owned discovery cache. Refresh never throws and never deletes the last good snapshot;
27
+ * callers can keep using the static catalog when a remote provider is unavailable.
28
+ */
29
+ export declare class DynamicModelCatalog implements ModelCatalog {
30
+ private readonly source;
31
+ private readonly fallback;
32
+ private snapshot;
33
+ constructor(source: ModelCatalogSource, fallback?: ModelCatalog);
34
+ list(): Promise<readonly ModelRegistration[]>;
35
+ get(modelId: string): Promise<ModelRegistration | undefined>;
36
+ refresh(): Promise<ModelCatalogRefreshResult>;
37
+ }
@@ -0,0 +1,62 @@
1
+ /** Immutable, deterministic model facts supplied by the SDK or an application. */
2
+ export class StaticModelCatalog {
3
+ registrations;
4
+ byId;
5
+ constructor(registrations) {
6
+ const byId = new Map();
7
+ for (const registration of registrations) {
8
+ const id = registration.descriptor.id;
9
+ if (byId.has(id))
10
+ throw new Error(`Duplicate model catalog entry: ${id}`);
11
+ byId.set(id, registration);
12
+ }
13
+ this.registrations = [...byId.values()].sort((a, b) => a.descriptor.id.localeCompare(b.descriptor.id));
14
+ this.byId = byId;
15
+ }
16
+ async list() {
17
+ return this.registrations;
18
+ }
19
+ async get(modelId) {
20
+ return this.byId.get(modelId);
21
+ }
22
+ }
23
+ /**
24
+ * A host-owned discovery cache. Refresh never throws and never deletes the last good snapshot;
25
+ * callers can keep using the static catalog when a remote provider is unavailable.
26
+ */
27
+ export class DynamicModelCatalog {
28
+ source;
29
+ fallback;
30
+ snapshot = new Map();
31
+ constructor(source, fallback = new StaticModelCatalog([])) {
32
+ this.source = source;
33
+ this.fallback = fallback;
34
+ }
35
+ async list() {
36
+ const merged = new Map();
37
+ for (const registration of await this.fallback.list())
38
+ merged.set(registration.descriptor.id, registration);
39
+ for (const registration of this.snapshot.values())
40
+ merged.set(registration.descriptor.id, registration);
41
+ return [...merged.values()].sort((a, b) => a.descriptor.id.localeCompare(b.descriptor.id));
42
+ }
43
+ async get(modelId) {
44
+ return this.snapshot.get(modelId) ?? await this.fallback.get(modelId);
45
+ }
46
+ async refresh() {
47
+ try {
48
+ const next = new Map();
49
+ for (const registration of await this.source.list()) {
50
+ const id = registration.descriptor.id;
51
+ if (next.has(id))
52
+ throw new Error("duplicate dynamic model catalog entry");
53
+ next.set(id, registration);
54
+ }
55
+ this.snapshot = next;
56
+ return { ok: true };
57
+ }
58
+ catch {
59
+ return { ok: false, errorCode: "refresh_failed" };
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,119 @@
1
+ import type { LLMProvider, RuntimePolicy } from "../types.js";
2
+ import { type EndpointProfile, type EndpointProfileId, type EndpointProtocol, type ProviderId } from "./endpoints.js";
3
+ import { type GenerationProtocol, type InputModality, type OutputModality, type ProtocolRuntimeCapabilities, type ProtocolRuntimeCapabilityOverrides } from "./protocol-capabilities.js";
4
+ export type { GenerationProtocol, InputModality, OutputModality, ProtocolRuntimeCapabilities, ProtocolRuntimeCapabilityOverrides, } from "./protocol-capabilities.js";
5
+ export type ModelKind = "generation" | "embedding";
6
+ export type CapabilityState = "supported" | "unsupported" | "unknown";
7
+ export declare const MODEL_CAPABILITY_STATES: readonly CapabilityState[];
8
+ export interface ModelDescriptor {
9
+ id: string;
10
+ providerId: string;
11
+ kind: ModelKind;
12
+ contextWindow?: number;
13
+ maxOutputTokens?: number;
14
+ intrinsic: {
15
+ inputModalities?: readonly InputModality[];
16
+ outputModalities?: readonly OutputModality[];
17
+ tools?: boolean;
18
+ reasoning?: boolean;
19
+ };
20
+ }
21
+ export interface ModelRegistration {
22
+ descriptor: ModelDescriptor;
23
+ defaultEndpointId: EndpointProfileId;
24
+ recommendedRuntimePolicy?: RuntimePolicy;
25
+ }
26
+ export interface DynamicModelDescriptorResolver {
27
+ readonly providerId: ProviderId;
28
+ resolve(modelId: string): ModelRegistration;
29
+ }
30
+ export interface EndpointRuntimeCapabilities {
31
+ nativeTokenCounting?: boolean;
32
+ promptCaching?: boolean;
33
+ protocolOverrides?: ProtocolRuntimeCapabilityOverrides;
34
+ }
35
+ export interface CacheCapabilityEvidence {
36
+ endpointId: EndpointProfileId;
37
+ source: string;
38
+ verifiedAt: "2026-08-26";
39
+ classification: "documentation" | "live_probe";
40
+ usageFields: readonly string[];
41
+ }
42
+ export interface TokenMeasurementEvidence {
43
+ endpointId: EndpointProfileId;
44
+ source: string;
45
+ verifiedAt: "2026-08-26";
46
+ providerApiState: "supported" | "unsupported" | "unknown";
47
+ adapterState: "available" | "unavailable";
48
+ method: "provider_preflight" | "official_local_tokenizer" | "postflight" | "heuristic";
49
+ coverage: readonly string[];
50
+ sdk: string;
51
+ }
52
+ export type CapabilityEvidenceLayer = "model" | "protocol" | "endpoint";
53
+ export interface EffectiveCapability<T = boolean> {
54
+ state: CapabilityState;
55
+ value?: T;
56
+ evidence: readonly CapabilityEvidenceLayer[];
57
+ }
58
+ export interface EffectiveModelCapabilities {
59
+ inputModalities: Record<InputModality, EffectiveCapability>;
60
+ outputModalities: Record<OutputModality, EffectiveCapability>;
61
+ tools: EffectiveCapability;
62
+ reasoning: EffectiveCapability;
63
+ parallelToolCalls: EffectiveCapability;
64
+ structuredOutput: EffectiveCapability;
65
+ promptCaching: EffectiveCapability;
66
+ nativeTokenCounting: EffectiveCapability;
67
+ mediaForms: {
68
+ imageUrl: EffectiveCapability;
69
+ imageBase64: EffectiveCapability;
70
+ fileId: EffectiveCapability;
71
+ audioUrl: EffectiveCapability;
72
+ audioBase64: EffectiveCapability;
73
+ };
74
+ }
75
+ export interface ResolvedProviderRuntime<TAdapter = LLMProvider> {
76
+ identity: {
77
+ providerId: ProviderId;
78
+ modelId: string;
79
+ endpointId: EndpointProfileId;
80
+ protocol: GenerationProtocol;
81
+ };
82
+ model: ModelDescriptor;
83
+ endpoint: EndpointProfile;
84
+ adapter: TAdapter;
85
+ effectiveCapabilities: EffectiveModelCapabilities;
86
+ runtimePolicy?: RuntimePolicy;
87
+ }
88
+ export interface RegistryRuleEvidence {
89
+ ruleId: string;
90
+ classification: "routing" | "policy" | "protocol" | "endpoint";
91
+ source: string;
92
+ verifiedAt: "2026-08-12";
93
+ }
94
+ export declare const registryEvidence: readonly RegistryRuleEvidence[];
95
+ export declare const cacheCapabilityEvidence: readonly CacheCapabilityEvidence[];
96
+ export declare const tokenMeasurementEvidence: readonly TokenMeasurementEvidence[];
97
+ export declare function defaultModelForProvider(providerId: ProviderId): string;
98
+ export declare function defaultEndpointForProvider(providerId: ProviderId): EndpointProfileId;
99
+ export declare class ModelRegistry {
100
+ resolve(modelId: string, providerId?: ProviderId): ModelRegistration | undefined;
101
+ }
102
+ export declare const modelRegistry: ModelRegistry;
103
+ export declare function normalizeModelId(providerId: string, modelId: string): string;
104
+ export declare function getRuntimePolicy(providerId: string, modelId: string): RuntimePolicy;
105
+ export declare const protocolRuntimeCapabilities: Record<GenerationProtocol, ProtocolRuntimeCapabilities>;
106
+ export declare const endpointRuntimeCapabilities: Partial<Record<EndpointProfileId, EndpointRuntimeCapabilities>>;
107
+ export declare function resolveEffectiveCapability<T = boolean>(layers: readonly {
108
+ layer: CapabilityEvidenceLayer;
109
+ state: CapabilityState;
110
+ value?: T;
111
+ }[]): EffectiveCapability<T>;
112
+ export declare function resolveEffectiveModelCapabilities(input: {
113
+ model: ModelDescriptor;
114
+ protocol: GenerationProtocol;
115
+ endpointCapabilities?: EndpointRuntimeCapabilities;
116
+ }): EffectiveModelCapabilities;
117
+ export declare function generationProtocol(protocol: EndpointProtocol): GenerationProtocol | undefined;
118
+ export declare function endpointCapabilitiesFor(endpointId: EndpointProfileId, preserveEndpointIdentity: boolean, preserveCacheEvidence?: boolean): EndpointRuntimeCapabilities | undefined;
119
+ export declare function isKnownProviderId(value: string): value is ProviderId;