melchizedek-agents 0.9.0

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 (111) hide show
  1. package/AGENT_SETUP.md +182 -0
  2. package/DOCUMENTATION.md +614 -0
  3. package/LICENSE +21 -0
  4. package/QUICKSTART.md +164 -0
  5. package/README.md +151 -0
  6. package/config/agents/README.md +27 -0
  7. package/config/agents/examples/ares.yaml +74 -0
  8. package/config/agents/examples/cartographers.yaml +115 -0
  9. package/config/agents/examples/claude.yaml +17 -0
  10. package/config/agents/examples/council.yaml +65 -0
  11. package/config/agents/examples/critic.yaml +74 -0
  12. package/config/agents/examples/delegation.yaml +29 -0
  13. package/config/agents/examples/hierarchical.yaml +26 -0
  14. package/config/agents/examples/image_production.yaml +112 -0
  15. package/config/agents/examples/librarian.yaml +75 -0
  16. package/config/agents/examples/model_zoo.yaml +81 -0
  17. package/config/agents/examples/patient_advocate.yaml +107 -0
  18. package/config/agents/examples/scriptorium.yaml +96 -0
  19. package/config/agents/examples/style_council.yaml +83 -0
  20. package/config/agents/examples/syndicate.yaml +34 -0
  21. package/config/agents/examples/tutor.yaml +66 -0
  22. package/config/agents/syndicateSchema.yaml +291 -0
  23. package/dist/lib/config.d.ts +108 -0
  24. package/dist/lib/config.js +110 -0
  25. package/dist/lib/dispatch.d.ts +133 -0
  26. package/dist/lib/dispatch.js +182 -0
  27. package/dist/lib/grounding.d.ts +28 -0
  28. package/dist/lib/grounding.js +61 -0
  29. package/dist/lib/index.d.ts +14 -0
  30. package/dist/lib/index.js +13 -0
  31. package/dist/lib/loadEnv.d.ts +21 -0
  32. package/dist/lib/loadEnv.js +58 -0
  33. package/dist/lib/loadSyndicate.d.ts +177 -0
  34. package/dist/lib/loadSyndicate.js +264 -0
  35. package/dist/lib/memory/supabaseMemoryService.d.ts +118 -0
  36. package/dist/lib/memory/supabaseMemoryService.js +499 -0
  37. package/dist/lib/models/claudeLlm.d.ts +93 -0
  38. package/dist/lib/models/claudeLlm.js +332 -0
  39. package/dist/lib/models/gptLlm.d.ts +110 -0
  40. package/dist/lib/models/gptLlm.js +497 -0
  41. package/dist/lib/models/grokLlm.d.ts +64 -0
  42. package/dist/lib/models/grokLlm.js +86 -0
  43. package/dist/lib/models/ollamaLlm.d.ts +105 -0
  44. package/dist/lib/models/ollamaLlm.js +134 -0
  45. package/dist/lib/models/openAiCompatibleLlm.d.ts +125 -0
  46. package/dist/lib/models/openAiCompatibleLlm.js +331 -0
  47. package/dist/lib/models/providerMap.d.ts +28 -0
  48. package/dist/lib/models/providerMap.js +45 -0
  49. package/dist/lib/models/registry.d.ts +71 -0
  50. package/dist/lib/models/registry.js +159 -0
  51. package/dist/lib/models/schemaNormalize.d.ts +22 -0
  52. package/dist/lib/models/schemaNormalize.js +58 -0
  53. package/dist/lib/observability/supabaseSpanExporter.d.ts +35 -0
  54. package/dist/lib/observability/supabaseSpanExporter.js +115 -0
  55. package/dist/lib/observability/tracer.d.ts +44 -0
  56. package/dist/lib/observability/tracer.js +242 -0
  57. package/dist/lib/persistence/supabaseProvider.d.ts +44 -0
  58. package/dist/lib/persistence/supabaseProvider.js +88 -0
  59. package/dist/lib/session/supabaseSessionService.d.ts +26 -0
  60. package/dist/lib/session/supabaseSessionService.js +193 -0
  61. package/dist/lib/session/transcript.d.ts +193 -0
  62. package/dist/lib/session/transcript.js +309 -0
  63. package/dist/lib/toolRegistry.d.ts +15 -0
  64. package/dist/lib/toolRegistry.js +58 -0
  65. package/dist/lib/tools/collectionsSearchTool.d.ts +55 -0
  66. package/dist/lib/tools/collectionsSearchTool.js +86 -0
  67. package/dist/lib/tools/generateImageTool.d.ts +16 -0
  68. package/dist/lib/tools/generateImageTool.js +119 -0
  69. package/dist/lib/tools/inspectImageTool.d.ts +21 -0
  70. package/dist/lib/tools/inspectImageTool.js +97 -0
  71. package/dist/lib/tools/mcpToolFactory.d.ts +2 -0
  72. package/dist/lib/tools/mcpToolFactory.js +116 -0
  73. package/dist/lib/tools/toolContract.d.ts +78 -0
  74. package/dist/lib/tools/toolContract.js +129 -0
  75. package/dist/lib/tools/webExtractTool.d.ts +70 -0
  76. package/dist/lib/tools/webExtractTool.js +461 -0
  77. package/dist/lib/tools/webSearchTool.d.ts +53 -0
  78. package/dist/lib/tools/webSearchTool.js +126 -0
  79. package/dist/lib/tools/wikiTools.d.ts +112 -0
  80. package/dist/lib/tools/wikiTools.js +697 -0
  81. package/dist/lib/tools/xSearchTool.d.ts +61 -0
  82. package/dist/lib/tools/xSearchTool.js +125 -0
  83. package/dist/lib/wiki/agentRun.d.ts +39 -0
  84. package/dist/lib/wiki/agentRun.js +79 -0
  85. package/dist/lib/wiki/builder.d.ts +71 -0
  86. package/dist/lib/wiki/builder.js +165 -0
  87. package/dist/lib/wiki/dive.d.ts +56 -0
  88. package/dist/lib/wiki/dive.js +208 -0
  89. package/dist/lib/wiki/entities.d.ts +220 -0
  90. package/dist/lib/wiki/entities.js +661 -0
  91. package/dist/lib/wiki/extract.d.ts +97 -0
  92. package/dist/lib/wiki/extract.js +305 -0
  93. package/dist/lib/wiki/fill.d.ts +37 -0
  94. package/dist/lib/wiki/fill.js +175 -0
  95. package/dist/lib/wiki/format.d.ts +132 -0
  96. package/dist/lib/wiki/format.js +177 -0
  97. package/dist/lib/wiki/graph.d.ts +80 -0
  98. package/dist/lib/wiki/graph.js +147 -0
  99. package/dist/lib/wiki/lint.d.ts +58 -0
  100. package/dist/lib/wiki/lint.js +267 -0
  101. package/dist/lib/wiki/markdown.d.ts +127 -0
  102. package/dist/lib/wiki/markdown.js +336 -0
  103. package/dist/lib/wiki/pipeline.d.ts +69 -0
  104. package/dist/lib/wiki/pipeline.js +119 -0
  105. package/dist/lib/wiki/vault.d.ts +84 -0
  106. package/dist/lib/wiki/vault.js +194 -0
  107. package/dist/scripts/a2a_server.d.ts +2 -0
  108. package/dist/scripts/a2a_server.js +997 -0
  109. package/dist/scripts/syndicate_chat.d.ts +2 -0
  110. package/dist/scripts/syndicate_chat.js +485 -0
  111. package/package.json +96 -0
@@ -0,0 +1,332 @@
1
+ /**
2
+ * lib/models/claudeLlm.ts — Anthropic Claude provider for the ADK LLMRegistry.
3
+ *
4
+ * WHY this file exists:
5
+ * The ADK JS package (@google/adk v1.x) is Gemini-native. It does not ship a
6
+ * Claude adapter the way the ADK Java SDK does. However, the ADK exposes a
7
+ * clean extension point: subclass BaseLlm, implement generateContentAsync(),
8
+ * and register the class via LLMRegistry.register(). The registry maps model
9
+ * name patterns to provider classes, so once registered, any LlmAgent with
10
+ * model: "claude-*" will automatically route through this class.
11
+ *
12
+ * HOW TO ENABLE:
13
+ * 1. Install the Anthropic SDK:
14
+ * npm install @anthropic-ai/sdk
15
+ * 2. Add your API key to .env:
16
+ * ANTHROPIC_API_KEY=sk-ant-...
17
+ * 3. registerAvailableProviders() (lib/models/registry.ts) registers this
18
+ * adapter automatically when the key is set.
19
+ * 4. Set model: "claude-sonnet-4-6" (or any claude-* id) in your YAML.
20
+ *
21
+ * CAPABILITIES:
22
+ * - Tools: FunctionTools AND MCP-discovered tools work. Tool schemas are
23
+ * normalized from the ADK/Gemini UPPERCASE dialect to the lowercase
24
+ * JSON-Schema types Anthropic requires (lib/models/schemaNormalize.ts).
25
+ * - web_search: declaring the `web_search` tool in YAML enables Anthropic's
26
+ * native web_search server tool — searches run on Anthropic's side.
27
+ * - Extended thinking: generateContentConfig.thinkingConfig.thinkingBudget
28
+ * maps to Anthropic's thinking parameter. Thinking blocks are surfaced
29
+ * as { text, thought: true } parts (display-only; kept out of session
30
+ * history). NOTE: thinking + tool use in the same agent is NOT supported
31
+ * this pass — Anthropic requires signed thinking blocks to be replayed
32
+ * on tool loops; the raw blocks are stashed in customMetadata
33
+ * ['anthropic.thinking'] for a future upgrade.
34
+ * - Token usage: response.usage is mapped to LlmResponse.usageMetadata, so
35
+ * traceAgentRun / llm.request spans count Claude tokens like Gemini's.
36
+ *
37
+ * LIMITATIONS vs Gemini:
38
+ * - generate_image tool uses the Gemini image model directly and is not
39
+ * affected by the inference model choice.
40
+ * - Live/bidirectional streaming (connect) is not supported.
41
+ *
42
+ * CONTENT FORMAT TRANSLATION:
43
+ * The ADK uses Google GenAI Content/Part objects internally. This adapter
44
+ * translates them to Anthropic MessageParam format and maps the response back
45
+ * to LlmResponse. Tool calls (function_call / function_response parts) are
46
+ * translated to Anthropic's tool_use / tool_result blocks.
47
+ */
48
+ import { BaseLlm, LLMRegistry } from '@google/adk';
49
+ import { traceLlmGeneration, setLlmSpanAttribute, } from "../observability/tracer.js";
50
+ import { wantsWebSearch, isWebSearchSentinel, } from "../tools/webSearchTool.js";
51
+ import { toLowercaseJsonSchema } from "./schemaNormalize.js";
52
+ /** Anthropic's minimum extended-thinking budget. */
53
+ const MIN_THINKING_BUDGET = 1024;
54
+ // ── Request building (exported for offline tests) ────────────────────────────
55
+ /** ADK toolsDict → Anthropic tool definitions (lowercase schemas; the
56
+ * web_search sentinel becomes Anthropic's native server tool). */
57
+ export function buildAnthropicTools(llmRequest) {
58
+ const anthropicTools = [];
59
+ for (const [, tool] of Object.entries(llmRequest.toolsDict ?? {})) {
60
+ if (isWebSearchSentinel(tool))
61
+ continue; // added as a server tool below
62
+ const t = tool;
63
+ if (t.name && t.description) {
64
+ anthropicTools.push({
65
+ name: t.name,
66
+ description: t.description,
67
+ input_schema: toLowercaseJsonSchema(t.parameters ?? { type: 'object', properties: {} }),
68
+ });
69
+ }
70
+ }
71
+ if (wantsWebSearch(llmRequest)) {
72
+ // Anthropic-native server tool: search runs on Anthropic's side, results
73
+ // are grounded into the reply — no client-side execution.
74
+ anthropicTools.push({
75
+ type: 'web_search_20250305',
76
+ name: 'web_search',
77
+ max_uses: 5,
78
+ });
79
+ }
80
+ return anthropicTools;
81
+ }
82
+ // ── ClaudeLlm ─────────────────────────────────────────────────────────────────
83
+ export class ClaudeLlm extends BaseLlm {
84
+ /**
85
+ * Regex patterns that map model name strings to this provider.
86
+ * Any model: "claude-*" in a YAML config will route here after registration.
87
+ */
88
+ static supportedModels = [/^claude-.+/];
89
+ apiKey;
90
+ constructor({ model, apiKey }) {
91
+ super({ model });
92
+ this.apiKey = apiKey;
93
+ }
94
+ /**
95
+ * Main generation method called by the ADK Runner for every turn.
96
+ *
97
+ * We translate ADK's LlmRequest (Google Content format) → Anthropic
98
+ * MessageParam format, call the Anthropic Messages API, then translate
99
+ * the response back to LlmResponse. The whole call is wrapped in an
100
+ * llm.request OpenTelemetry span (provider/model/tokens/latency).
101
+ */
102
+ async *generateContentAsync(llmRequest, stream = false) {
103
+ yield* traceLlmGeneration({ provider: 'anthropic', model: this.model }, this.generateInner(llmRequest, stream));
104
+ }
105
+ async *generateInner(llmRequest, stream) {
106
+ const apiKey = this.apiKey || process.env.ANTHROPIC_API_KEY;
107
+ if (!apiKey) {
108
+ yield {
109
+ errorCode: 'MISSING_API_KEY',
110
+ errorMessage: 'ANTHROPIC_API_KEY is not set in environment.',
111
+ };
112
+ return;
113
+ }
114
+ // Dynamic import — only loads @anthropic-ai/sdk when actually called,
115
+ // so the framework boots without the SDK installed for Gemini-only users.
116
+ let Anthropic;
117
+ try {
118
+ const mod = await import('@anthropic-ai/sdk');
119
+ Anthropic = mod.default ?? mod.Anthropic;
120
+ }
121
+ catch {
122
+ yield {
123
+ errorCode: 'SDK_NOT_INSTALLED',
124
+ errorMessage: 'The @anthropic-ai/sdk package is not installed. Run: npm install @anthropic-ai/sdk',
125
+ };
126
+ return;
127
+ }
128
+ const client = new Anthropic({ apiKey });
129
+ // ── Translate ADK Contents → Anthropic messages ──────────────────────────
130
+ const systemParts = [];
131
+ const messages = [];
132
+ for (const content of llmRequest.contents) {
133
+ // System instruction lives in config.systemInstruction, not contents.
134
+ // But ADK also injects it as a 'system' role content — extract it.
135
+ if (content.role === 'system') {
136
+ const text = content.parts
137
+ ?.filter((p) => p.text)
138
+ .map((p) => p.text)
139
+ .join('\n');
140
+ if (text)
141
+ systemParts.push(text);
142
+ continue;
143
+ }
144
+ const role = content.role === 'model' ? 'assistant' : 'user';
145
+ const blocks = [];
146
+ for (const part of content.parts ?? []) {
147
+ const p = part;
148
+ if (p.thought) {
149
+ // Prior-turn scratchpad is display-only; never replay it as text.
150
+ continue;
151
+ }
152
+ if (p.text) {
153
+ blocks.push({ type: 'text', text: p.text });
154
+ }
155
+ else if (p.functionCall) {
156
+ // ADK function_call → Anthropic tool_use
157
+ blocks.push({
158
+ type: 'tool_use',
159
+ id: p.functionCall.id ?? `tool_${Date.now()}`,
160
+ name: p.functionCall.name,
161
+ input: p.functionCall.args ?? {},
162
+ });
163
+ }
164
+ else if (p.functionResponse) {
165
+ // ADK function_response → Anthropic tool_result
166
+ blocks.push({
167
+ type: 'tool_result',
168
+ tool_use_id: p.functionResponse.id ?? '',
169
+ content: JSON.stringify(p.functionResponse.response ?? {}),
170
+ });
171
+ }
172
+ }
173
+ if (blocks.length > 0) {
174
+ messages.push({ role, content: blocks });
175
+ }
176
+ }
177
+ // Also pull system instruction from generateContentConfig if present
178
+ const configSystem = llmRequest.config?.systemInstruction;
179
+ if (configSystem) {
180
+ const text = typeof configSystem === 'string'
181
+ ? configSystem
182
+ : configSystem.parts?.map((p) => p.text).join('\n') ?? '';
183
+ if (text)
184
+ systemParts.unshift(text);
185
+ }
186
+ // ── Build Anthropic tool definitions from ADK toolsDict ──────────────────
187
+ const anthropicTools = buildAnthropicTools(llmRequest);
188
+ if (wantsWebSearch(llmRequest)) {
189
+ setLlmSpanAttribute('llm.web_search.native', true);
190
+ }
191
+ // ── Extended thinking (Gemini thinkingConfig → Anthropic thinking) ───────
192
+ const cfg = llmRequest.config ?? {};
193
+ let maxTokens = cfg.maxOutputTokens ?? 4096;
194
+ let thinking;
195
+ const requestedBudget = cfg.thinkingConfig?.thinkingBudget;
196
+ if (typeof requestedBudget === 'number' && requestedBudget > 0) {
197
+ const budget = Math.max(requestedBudget, MIN_THINKING_BUDGET);
198
+ thinking = { type: 'enabled', budget_tokens: budget };
199
+ // Anthropic requires max_tokens to exceed the thinking budget.
200
+ maxTokens = Math.max(maxTokens, budget + 2048);
201
+ }
202
+ const requestBase = {
203
+ model: this.model,
204
+ max_tokens: maxTokens,
205
+ system: systemParts.join('\n\n') || undefined,
206
+ messages,
207
+ tools: anthropicTools.length > 0 ? anthropicTools : undefined,
208
+ ...(thinking ? { thinking } : {}),
209
+ };
210
+ // ── Call Anthropic API ────────────────────────────────────────────────────
211
+ try {
212
+ if (stream) {
213
+ // Streaming path
214
+ const streamResponse = await client.messages.stream(requestBase);
215
+ for await (const chunk of streamResponse) {
216
+ if (chunk.type === 'content_block_delta') {
217
+ if (chunk.delta.type === 'text_delta') {
218
+ yield {
219
+ content: {
220
+ role: 'model',
221
+ parts: [{ text: chunk.delta.text }],
222
+ },
223
+ partial: true,
224
+ };
225
+ }
226
+ else if (chunk.delta.type === 'thinking_delta') {
227
+ yield {
228
+ content: {
229
+ role: 'model',
230
+ parts: [{ text: chunk.delta.thinking, thought: true }],
231
+ },
232
+ partial: true,
233
+ };
234
+ }
235
+ }
236
+ }
237
+ // Final message: tool_use blocks, thinking stash, and token usage.
238
+ const final = await streamResponse.finalMessage();
239
+ yield this.finalResponse(final, /*includeText=*/ false);
240
+ }
241
+ else {
242
+ // Non-streaming path
243
+ const response = await client.messages.create(requestBase);
244
+ // Thinking first, as a display-only partial.
245
+ const thinkingText = (response.content ?? [])
246
+ .filter((b) => b.type === 'thinking')
247
+ .map((b) => b.thinking)
248
+ .join('\n\n');
249
+ if (thinkingText) {
250
+ yield {
251
+ content: {
252
+ role: 'model',
253
+ parts: [{ text: thinkingText, thought: true }],
254
+ },
255
+ partial: true,
256
+ };
257
+ }
258
+ yield this.finalResponse(response, /*includeText=*/ true);
259
+ }
260
+ }
261
+ catch (err) {
262
+ const msg = err instanceof Error ? err.message : String(err);
263
+ yield { errorCode: 'ANTHROPIC_ERROR', errorMessage: msg };
264
+ }
265
+ }
266
+ /** Maps a complete Anthropic message → the final LlmResponse. */
267
+ finalResponse(response, includeText) {
268
+ const parts = [];
269
+ const thinkingBlocks = [];
270
+ for (const block of response.content ?? []) {
271
+ if (block.type === 'text' && includeText) {
272
+ parts.push({ text: block.text });
273
+ }
274
+ else if (block.type === 'tool_use') {
275
+ parts.push({
276
+ functionCall: { name: block.name, args: block.input, id: block.id },
277
+ });
278
+ }
279
+ else if (block.type === 'thinking') {
280
+ // Raw signed blocks, preserved for a future thinking+tools upgrade
281
+ // (Anthropic requires them replayed verbatim on tool loops).
282
+ thinkingBlocks.push(block);
283
+ }
284
+ }
285
+ const usage = response.usage;
286
+ return {
287
+ ...(parts.length > 0 ? { content: { role: 'model', parts } } : {}),
288
+ turnComplete: true,
289
+ ...(usage
290
+ ? {
291
+ usageMetadata: {
292
+ ...(usage.input_tokens !== undefined
293
+ ? { promptTokenCount: usage.input_tokens }
294
+ : {}),
295
+ ...(usage.output_tokens !== undefined
296
+ ? { candidatesTokenCount: usage.output_tokens }
297
+ : {}),
298
+ ...(usage.input_tokens !== undefined &&
299
+ usage.output_tokens !== undefined
300
+ ? { totalTokenCount: usage.input_tokens + usage.output_tokens }
301
+ : {}),
302
+ },
303
+ }
304
+ : {}),
305
+ ...(thinkingBlocks.length > 0
306
+ ? { customMetadata: { 'anthropic.thinking': thinkingBlocks } }
307
+ : {}),
308
+ };
309
+ }
310
+ /**
311
+ * Live/bidirectional streaming connection — not supported by the Anthropic
312
+ * Messages API. Throws to surface this clearly rather than silently failing.
313
+ */
314
+ async connect(_llmRequest) {
315
+ throw new Error('ClaudeLlm does not support live bidirectional connections. ' +
316
+ 'Use a Gemini model for live/streaming sessions.');
317
+ }
318
+ }
319
+ // ── Registration helper ───────────────────────────────────────────────────────
320
+ /**
321
+ * Registers ClaudeLlm with the ADK LLMRegistry.
322
+ *
323
+ * WHY a separate function instead of auto-registering at import time:
324
+ * Auto-registration at module load would cause every consumer of this file
325
+ * to unconditionally register Claude, even if ANTHROPIC_API_KEY is absent.
326
+ * By making registration explicit, registerAvailableProviders() can
327
+ * conditionally call this only when the key is present, and log a clear
328
+ * message about which provider is active.
329
+ */
330
+ export function registerClaudeLlm() {
331
+ LLMRegistry.register(ClaudeLlm);
332
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * lib/models/gptLlm.ts — OpenAI GPT provider for the ADK LLMRegistry.
3
+ *
4
+ * WHY this file exists:
5
+ * Model optionality: any agent YAML with model: "gpt-*" (or an o-series
6
+ * id like "o4-mini") routes here after registration. Unlike Grok/Ollama
7
+ * this adapter does NOT reuse the chat-completions base class — it speaks
8
+ * OpenAI's Responses API through the official `openai` SDK, because the
9
+ * Responses API is where OpenAI exposes reasoning summaries (the model's
10
+ * thinking, surfaced as { thought: true } parts here) and the first-class
11
+ * `web_search` tool this framework's web_search abstraction maps to.
12
+ *
13
+ * HOW TO ENABLE:
14
+ * 1. Install the SDK (already in package.json): npm install
15
+ * 2. Add your API key to .env: OPENAI_API_KEY=sk-...
16
+ * 3. Set model: "gpt-5-mini" (or any gpt-* / o-series id) in your YAML.
17
+ * registerAvailableProviders() registers this adapter when the key is set.
18
+ *
19
+ * CONTENT FORMAT TRANSLATION:
20
+ * ADK Content/Part objects → Responses API `input` items:
21
+ * user/model text → { role, content } message items
22
+ * functionCall part → { type:'function_call', call_id, name, arguments }
23
+ * functionResponse part → { type:'function_call_output', call_id, output }
24
+ * The call_id round-trip matters: this adapter emits functionCall.id so
25
+ * ADK echoes it back on the tool response, and the Responses API requires
26
+ * function_call_output.call_id to match the originating call.
27
+ *
28
+ * Response `output` items map back:
29
+ * 'reasoning' summary → { text, thought: true } partial (display-only)
30
+ * 'message' output_text → text part
31
+ * 'function_call' → functionCall part
32
+ * usage.input_tokens / output_tokens / output_tokens_details.reasoning_tokens
33
+ * → LlmResponse.usageMetadata, so token telemetry works like every provider.
34
+ *
35
+ * STREAMING (ADK stream=true, i.e. RunConfig streamingMode: SSE):
36
+ * The request is sent with { stream: true }; SSE deltas
37
+ * (response.output_text.delta / response.reasoning_summary_text.delta)
38
+ * are yielded as { partial: true } responses — the ADK Runner displays
39
+ * but does NOT persist partial events — and the terminal
40
+ * response.completed payload is mapped through the same final-response
41
+ * translator as the non-streaming path, carrying full content + usage
42
+ * as the ONE event that lands in the session. Function calls are never
43
+ * delta-streamed (both OpenAI and xAI deliver them whole).
44
+ */
45
+ import { BaseLlm } from '@google/adk';
46
+ import type { LlmRequest, LlmResponse } from '@google/adk';
47
+ import type { BaseLlmConnection } from '@google/adk';
48
+ /** ADK Contents → Responses API `input` items + `instructions` string. */
49
+ export declare function buildResponsesInput(llmRequest: LlmRequest): {
50
+ instructions: string | undefined;
51
+ input: any[];
52
+ };
53
+ /** ADK toolsDict (+ web_search sentinel) → Responses API tool definitions. */
54
+ export declare function buildResponsesTools(llmRequest: LlmRequest): any[];
55
+ /** Maps one Responses-API SSE event to a displayable delta, or null for
56
+ * event types that carry none. Function calls are NOT delta-streamed —
57
+ * both OpenAI and xAI deliver them whole in the final response. */
58
+ export declare function streamEventDelta(ev: any): {
59
+ thought: boolean;
60
+ text: string;
61
+ } | null;
62
+ export declare class GptLlm extends BaseLlm {
63
+ /** gpt-* and o-series ids route here after registration. */
64
+ static readonly supportedModels: Array<string | RegExp>;
65
+ protected apiKey?: string;
66
+ constructor({ model, apiKey }: {
67
+ model: string;
68
+ apiKey?: string;
69
+ });
70
+ /** Provider id for telemetry and error codes. */
71
+ protected providerId(): string;
72
+ /** SDK baseURL override; undefined = api.openai.com. */
73
+ protected baseURL(): string | undefined;
74
+ protected apiKeyFromEnv(): string | undefined;
75
+ protected missingKeyMessage(): string;
76
+ /** Responses API `reasoning` request param, or undefined to omit it.
77
+ * Base: reasoning summaries for OpenAI's reasoning-capable ids.
78
+ * Subclasses override per vendor (GrokLlm pins grok-4.5 to a reasoning
79
+ * effort). A 400 from a model that rejects the param is retried once
80
+ * without it — see createWithRetry. */
81
+ protected reasoningParam(): Record<string, unknown> | undefined;
82
+ /** Extra options for the OpenAI SDK client constructor. Subclasses
83
+ * override per vendor (GrokLlm sets a long request timeout, per xAI's
84
+ * streaming guidance for reasoning models). */
85
+ protected clientOptions(): Record<string, unknown>;
86
+ generateContentAsync(llmRequest: LlmRequest, stream?: boolean): AsyncGenerator<LlmResponse, void>;
87
+ private generateInner;
88
+ /** responses.create with the guarded reasoning retry: if the model
89
+ * rejects the reasoning param with a 400 (a non-reasoning model matched
90
+ * the pattern), drop it and try once more. */
91
+ private createWithRetry;
92
+ /** Final (non-delta) Response → LlmResponse yields: reasoning summaries
93
+ * as a display-only thought part, then text/functionCall parts with
94
+ * usage. Shared by the non-streaming path and the stream finalizer
95
+ * (which sets skipThoughts — its summaries already streamed as deltas). */
96
+ private mapFinalResponse;
97
+ /** SSE streaming: yield displayable DELTAS as { partial: true } responses
98
+ * (the ADK Runner shows but never persists partials), then map the
99
+ * terminal response.completed payload through mapFinalResponse — full
100
+ * content + usage, the ONE event that lands in the session. Usage rides
101
+ * only the final response so the tracer never double-counts tokens. */
102
+ private streamResponses;
103
+ /** Live/bidirectional streaming is not wired for this adapter. */
104
+ connect(_llmRequest: LlmRequest): Promise<BaseLlmConnection>;
105
+ }
106
+ /**
107
+ * Registers GptLlm with the ADK LLMRegistry. Called by
108
+ * registerAvailableProviders() when OPENAI_API_KEY is present.
109
+ */
110
+ export declare function registerGptLlm(): void;