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.
- package/AGENT_SETUP.md +182 -0
- package/DOCUMENTATION.md +614 -0
- package/LICENSE +21 -0
- package/QUICKSTART.md +164 -0
- package/README.md +151 -0
- package/config/agents/README.md +27 -0
- package/config/agents/examples/ares.yaml +74 -0
- package/config/agents/examples/cartographers.yaml +115 -0
- package/config/agents/examples/claude.yaml +17 -0
- package/config/agents/examples/council.yaml +65 -0
- package/config/agents/examples/critic.yaml +74 -0
- package/config/agents/examples/delegation.yaml +29 -0
- package/config/agents/examples/hierarchical.yaml +26 -0
- package/config/agents/examples/image_production.yaml +112 -0
- package/config/agents/examples/librarian.yaml +75 -0
- package/config/agents/examples/model_zoo.yaml +81 -0
- package/config/agents/examples/patient_advocate.yaml +107 -0
- package/config/agents/examples/scriptorium.yaml +96 -0
- package/config/agents/examples/style_council.yaml +83 -0
- package/config/agents/examples/syndicate.yaml +34 -0
- package/config/agents/examples/tutor.yaml +66 -0
- package/config/agents/syndicateSchema.yaml +291 -0
- package/dist/lib/config.d.ts +108 -0
- package/dist/lib/config.js +110 -0
- package/dist/lib/dispatch.d.ts +133 -0
- package/dist/lib/dispatch.js +182 -0
- package/dist/lib/grounding.d.ts +28 -0
- package/dist/lib/grounding.js +61 -0
- package/dist/lib/index.d.ts +14 -0
- package/dist/lib/index.js +13 -0
- package/dist/lib/loadEnv.d.ts +21 -0
- package/dist/lib/loadEnv.js +58 -0
- package/dist/lib/loadSyndicate.d.ts +177 -0
- package/dist/lib/loadSyndicate.js +264 -0
- package/dist/lib/memory/supabaseMemoryService.d.ts +118 -0
- package/dist/lib/memory/supabaseMemoryService.js +499 -0
- package/dist/lib/models/claudeLlm.d.ts +93 -0
- package/dist/lib/models/claudeLlm.js +332 -0
- package/dist/lib/models/gptLlm.d.ts +110 -0
- package/dist/lib/models/gptLlm.js +497 -0
- package/dist/lib/models/grokLlm.d.ts +64 -0
- package/dist/lib/models/grokLlm.js +86 -0
- package/dist/lib/models/ollamaLlm.d.ts +105 -0
- package/dist/lib/models/ollamaLlm.js +134 -0
- package/dist/lib/models/openAiCompatibleLlm.d.ts +125 -0
- package/dist/lib/models/openAiCompatibleLlm.js +331 -0
- package/dist/lib/models/providerMap.d.ts +28 -0
- package/dist/lib/models/providerMap.js +45 -0
- package/dist/lib/models/registry.d.ts +71 -0
- package/dist/lib/models/registry.js +159 -0
- package/dist/lib/models/schemaNormalize.d.ts +22 -0
- package/dist/lib/models/schemaNormalize.js +58 -0
- package/dist/lib/observability/supabaseSpanExporter.d.ts +35 -0
- package/dist/lib/observability/supabaseSpanExporter.js +115 -0
- package/dist/lib/observability/tracer.d.ts +44 -0
- package/dist/lib/observability/tracer.js +242 -0
- package/dist/lib/persistence/supabaseProvider.d.ts +44 -0
- package/dist/lib/persistence/supabaseProvider.js +88 -0
- package/dist/lib/session/supabaseSessionService.d.ts +26 -0
- package/dist/lib/session/supabaseSessionService.js +193 -0
- package/dist/lib/session/transcript.d.ts +193 -0
- package/dist/lib/session/transcript.js +309 -0
- package/dist/lib/toolRegistry.d.ts +15 -0
- package/dist/lib/toolRegistry.js +58 -0
- package/dist/lib/tools/collectionsSearchTool.d.ts +55 -0
- package/dist/lib/tools/collectionsSearchTool.js +86 -0
- package/dist/lib/tools/generateImageTool.d.ts +16 -0
- package/dist/lib/tools/generateImageTool.js +119 -0
- package/dist/lib/tools/inspectImageTool.d.ts +21 -0
- package/dist/lib/tools/inspectImageTool.js +97 -0
- package/dist/lib/tools/mcpToolFactory.d.ts +2 -0
- package/dist/lib/tools/mcpToolFactory.js +116 -0
- package/dist/lib/tools/toolContract.d.ts +78 -0
- package/dist/lib/tools/toolContract.js +129 -0
- package/dist/lib/tools/webExtractTool.d.ts +70 -0
- package/dist/lib/tools/webExtractTool.js +461 -0
- package/dist/lib/tools/webSearchTool.d.ts +53 -0
- package/dist/lib/tools/webSearchTool.js +126 -0
- package/dist/lib/tools/wikiTools.d.ts +112 -0
- package/dist/lib/tools/wikiTools.js +697 -0
- package/dist/lib/tools/xSearchTool.d.ts +61 -0
- package/dist/lib/tools/xSearchTool.js +125 -0
- package/dist/lib/wiki/agentRun.d.ts +39 -0
- package/dist/lib/wiki/agentRun.js +79 -0
- package/dist/lib/wiki/builder.d.ts +71 -0
- package/dist/lib/wiki/builder.js +165 -0
- package/dist/lib/wiki/dive.d.ts +56 -0
- package/dist/lib/wiki/dive.js +208 -0
- package/dist/lib/wiki/entities.d.ts +220 -0
- package/dist/lib/wiki/entities.js +661 -0
- package/dist/lib/wiki/extract.d.ts +97 -0
- package/dist/lib/wiki/extract.js +305 -0
- package/dist/lib/wiki/fill.d.ts +37 -0
- package/dist/lib/wiki/fill.js +175 -0
- package/dist/lib/wiki/format.d.ts +132 -0
- package/dist/lib/wiki/format.js +177 -0
- package/dist/lib/wiki/graph.d.ts +80 -0
- package/dist/lib/wiki/graph.js +147 -0
- package/dist/lib/wiki/lint.d.ts +58 -0
- package/dist/lib/wiki/lint.js +267 -0
- package/dist/lib/wiki/markdown.d.ts +127 -0
- package/dist/lib/wiki/markdown.js +336 -0
- package/dist/lib/wiki/pipeline.d.ts +69 -0
- package/dist/lib/wiki/pipeline.js +119 -0
- package/dist/lib/wiki/vault.d.ts +84 -0
- package/dist/lib/wiki/vault.js +194 -0
- package/dist/scripts/a2a_server.d.ts +2 -0
- package/dist/scripts/a2a_server.js +997 -0
- package/dist/scripts/syndicate_chat.d.ts +2 -0
- package/dist/scripts/syndicate_chat.js +485 -0
- package/package.json +96 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/models/ollamaLlm.ts — open-weight / local model provider for the ADK
|
|
3
|
+
* LLMRegistry, served by Ollama.
|
|
4
|
+
*
|
|
5
|
+
* WHY this file exists:
|
|
6
|
+
* Every other provider in this framework bills per token and requires an
|
|
7
|
+
* API key. An open-weight model pulled through Ollama runs on the user's
|
|
8
|
+
* own machine: no key, no account, no data leaving the device. That makes
|
|
9
|
+
* it the teaching provider for the lyceumagents.com curriculum's Part 1 —
|
|
10
|
+
* and a legitimate production choice wherever privacy or cost demands
|
|
11
|
+
* local inference.
|
|
12
|
+
*
|
|
13
|
+
* The ADK JS package (@google/adk v1.x) is Gemini-native, but exposes the
|
|
14
|
+
* same extension point claudeLlm.ts uses: subclass BaseLlm, implement
|
|
15
|
+
* generateContentAsync(), register via LLMRegistry.register(). Any agent
|
|
16
|
+
* with model: "ollama/<model>" then routes here automatically.
|
|
17
|
+
*
|
|
18
|
+
* HOW TO ENABLE:
|
|
19
|
+
* 1. Install Ollama (https://ollama.com — macOS: brew install ollama)
|
|
20
|
+
* and start it (the desktop app, or `ollama serve`).
|
|
21
|
+
* 2. Pull a model that supports tool calling (see the table below):
|
|
22
|
+
* ollama pull qwen3.5:9b # the default recommendation
|
|
23
|
+
* ollama pull qwen3.5:4b # lighter; teaching and small machines
|
|
24
|
+
* 3. Set model: "ollama/qwen3.5:9b" in your YAML. No API key needed —
|
|
25
|
+
* registerAvailableProviders() registers this provider unconditionally.
|
|
26
|
+
* Optional: OLLAMA_BASE_URL in .env overrides the default endpoint
|
|
27
|
+
* (http://localhost:11434/v1 — Ollama's OpenAI-compatible API).
|
|
28
|
+
*
|
|
29
|
+
* CHOOSING A MODEL (current as of August 2026):
|
|
30
|
+
* The binding constraint is memory, not taste. A model must fit in RAM
|
|
31
|
+
* (unified memory on Apple Silicon) with room left for the KV cache and
|
|
32
|
+
* the OS — as a rule of thumb, the weights should occupy no more than
|
|
33
|
+
* ~70% of total memory. Every model below is Apache-2.0 and does native
|
|
34
|
+
* tool calling, which is the capability floor for agent work.
|
|
35
|
+
*
|
|
36
|
+
* model Q4 size fits comfortably in use it for
|
|
37
|
+
* ───────────────────────────────────────────────────────────────────
|
|
38
|
+
* qwen3.5:2b 2.7 GB 8 GB toy / CI runs
|
|
39
|
+
* qwen3.5:4b 3.4 GB 8–16 GB teaching, demos
|
|
40
|
+
* qwen3.5:9b 6.6 GB 16 GB+ DEFAULT — real work
|
|
41
|
+
* qwen3.5:27b 17 GB 32 GB+ heavier local work
|
|
42
|
+
* qwen3.8:27b 18 GB 32 GB+ strongest local
|
|
43
|
+
*
|
|
44
|
+
* Qwen3.8 (August 2026) is the strongest open-weight Qwen and the one to
|
|
45
|
+
* reach for on a 32 GB+ machine, but it ships in 27B ONLY — 18 GB of
|
|
46
|
+
* weights before any context — so it does not fit the 16/18 GB laptops
|
|
47
|
+
* this framework is usually developed on. Qwen3.5 (February 2026) is the
|
|
48
|
+
* newest generation that offers small dense sizes, which is why the
|
|
49
|
+
* default here is qwen3.5:9b rather than the bigger number. Qwen3.7 is
|
|
50
|
+
* API-only and has no weights to pull.
|
|
51
|
+
*
|
|
52
|
+
* Vision: qwen3-vl:8b remains the pinned choice for image work; the
|
|
53
|
+
* qwen3.5 family is multimodal, so ollama/qwen3.5:9b also accepts images.
|
|
54
|
+
*
|
|
55
|
+
* DESIGN NOTES:
|
|
56
|
+
* - Zero dependencies: talks to Ollama's OpenAI-compatible endpoint with
|
|
57
|
+
* the built-in fetch — the shared translation core lives in
|
|
58
|
+
* lib/models/openAiCompatibleLlm.ts.
|
|
59
|
+
* - The "ollama/" prefix is a routing namespace for the LLMRegistry and is
|
|
60
|
+
* stripped before the HTTP call (Ollama knows the model as "qwen3:8b").
|
|
61
|
+
* - Reasoning models (qwen3 family) emit <think>…</think> blocks before
|
|
62
|
+
* their answer. The base class surfaces them as a { thought: true }
|
|
63
|
+
* part — printers show the scratchpad dimmed; it stays out of history.
|
|
64
|
+
* - Vision: ADK inlineData parts (images) are translated to OpenAI
|
|
65
|
+
* image_url data URIs, so ollama/qwen3-vl:8b can see attached images.
|
|
66
|
+
*
|
|
67
|
+
* LIMITATIONS vs Gemini:
|
|
68
|
+
* - web_search: a local model has no native search, so the tool is
|
|
69
|
+
* omitted with a warning. A local agent's grounding is what you supply:
|
|
70
|
+
* pasted material, subagents, or MCP tools.
|
|
71
|
+
* - generate_image / inspect_image call Gemini image models directly and
|
|
72
|
+
* still require a Gemini key regardless of the inference model.
|
|
73
|
+
* - thinkingConfig is Gemini-only; qwen3 thinks on its own schedule.
|
|
74
|
+
*/
|
|
75
|
+
import type { LlmRequest, LlmResponse } from '@google/adk';
|
|
76
|
+
import { OpenAiCompatibleLlm } from './openAiCompatibleLlm.ts';
|
|
77
|
+
export declare class OllamaLlm extends OpenAiCompatibleLlm {
|
|
78
|
+
/**
|
|
79
|
+
* Model ids namespaced "ollama/<model>" route here after registration,
|
|
80
|
+
* e.g. model: "ollama/qwen3:8b" in a syndicate YAML.
|
|
81
|
+
*/
|
|
82
|
+
static readonly supportedModels: Array<string | RegExp>;
|
|
83
|
+
private baseUrl;
|
|
84
|
+
constructor({ model, baseUrl }: {
|
|
85
|
+
model: string;
|
|
86
|
+
baseUrl?: string;
|
|
87
|
+
});
|
|
88
|
+
protected providerId(): string;
|
|
89
|
+
protected endpointUrl(): string;
|
|
90
|
+
protected headers(): Record<string, string>;
|
|
91
|
+
protected wireModelName(): string;
|
|
92
|
+
protected httpError(status: number, detail: string): LlmResponse;
|
|
93
|
+
protected unreachable(message: string): LlmResponse;
|
|
94
|
+
protected extraBodyFields(_llmRequest: LlmRequest): Record<string, unknown>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Registers OllamaLlm with the ADK LLMRegistry.
|
|
98
|
+
*
|
|
99
|
+
* Unlike registerClaudeLlm(), this needs no key gate — a local provider has
|
|
100
|
+
* no credential to check. Registration is still explicit (not at import
|
|
101
|
+
* time) so entrypoints stay in control of which providers are active.
|
|
102
|
+
* If Ollama isn't running, agents fail at call time with a clear
|
|
103
|
+
* OLLAMA_UNREACHABLE message that says how to start it.
|
|
104
|
+
*/
|
|
105
|
+
export declare function registerOllamaLlm(): void;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/models/ollamaLlm.ts — open-weight / local model provider for the ADK
|
|
3
|
+
* LLMRegistry, served by Ollama.
|
|
4
|
+
*
|
|
5
|
+
* WHY this file exists:
|
|
6
|
+
* Every other provider in this framework bills per token and requires an
|
|
7
|
+
* API key. An open-weight model pulled through Ollama runs on the user's
|
|
8
|
+
* own machine: no key, no account, no data leaving the device. That makes
|
|
9
|
+
* it the teaching provider for the lyceumagents.com curriculum's Part 1 —
|
|
10
|
+
* and a legitimate production choice wherever privacy or cost demands
|
|
11
|
+
* local inference.
|
|
12
|
+
*
|
|
13
|
+
* The ADK JS package (@google/adk v1.x) is Gemini-native, but exposes the
|
|
14
|
+
* same extension point claudeLlm.ts uses: subclass BaseLlm, implement
|
|
15
|
+
* generateContentAsync(), register via LLMRegistry.register(). Any agent
|
|
16
|
+
* with model: "ollama/<model>" then routes here automatically.
|
|
17
|
+
*
|
|
18
|
+
* HOW TO ENABLE:
|
|
19
|
+
* 1. Install Ollama (https://ollama.com — macOS: brew install ollama)
|
|
20
|
+
* and start it (the desktop app, or `ollama serve`).
|
|
21
|
+
* 2. Pull a model that supports tool calling (see the table below):
|
|
22
|
+
* ollama pull qwen3.5:9b # the default recommendation
|
|
23
|
+
* ollama pull qwen3.5:4b # lighter; teaching and small machines
|
|
24
|
+
* 3. Set model: "ollama/qwen3.5:9b" in your YAML. No API key needed —
|
|
25
|
+
* registerAvailableProviders() registers this provider unconditionally.
|
|
26
|
+
* Optional: OLLAMA_BASE_URL in .env overrides the default endpoint
|
|
27
|
+
* (http://localhost:11434/v1 — Ollama's OpenAI-compatible API).
|
|
28
|
+
*
|
|
29
|
+
* CHOOSING A MODEL (current as of August 2026):
|
|
30
|
+
* The binding constraint is memory, not taste. A model must fit in RAM
|
|
31
|
+
* (unified memory on Apple Silicon) with room left for the KV cache and
|
|
32
|
+
* the OS — as a rule of thumb, the weights should occupy no more than
|
|
33
|
+
* ~70% of total memory. Every model below is Apache-2.0 and does native
|
|
34
|
+
* tool calling, which is the capability floor for agent work.
|
|
35
|
+
*
|
|
36
|
+
* model Q4 size fits comfortably in use it for
|
|
37
|
+
* ───────────────────────────────────────────────────────────────────
|
|
38
|
+
* qwen3.5:2b 2.7 GB 8 GB toy / CI runs
|
|
39
|
+
* qwen3.5:4b 3.4 GB 8–16 GB teaching, demos
|
|
40
|
+
* qwen3.5:9b 6.6 GB 16 GB+ DEFAULT — real work
|
|
41
|
+
* qwen3.5:27b 17 GB 32 GB+ heavier local work
|
|
42
|
+
* qwen3.8:27b 18 GB 32 GB+ strongest local
|
|
43
|
+
*
|
|
44
|
+
* Qwen3.8 (August 2026) is the strongest open-weight Qwen and the one to
|
|
45
|
+
* reach for on a 32 GB+ machine, but it ships in 27B ONLY — 18 GB of
|
|
46
|
+
* weights before any context — so it does not fit the 16/18 GB laptops
|
|
47
|
+
* this framework is usually developed on. Qwen3.5 (February 2026) is the
|
|
48
|
+
* newest generation that offers small dense sizes, which is why the
|
|
49
|
+
* default here is qwen3.5:9b rather than the bigger number. Qwen3.7 is
|
|
50
|
+
* API-only and has no weights to pull.
|
|
51
|
+
*
|
|
52
|
+
* Vision: qwen3-vl:8b remains the pinned choice for image work; the
|
|
53
|
+
* qwen3.5 family is multimodal, so ollama/qwen3.5:9b also accepts images.
|
|
54
|
+
*
|
|
55
|
+
* DESIGN NOTES:
|
|
56
|
+
* - Zero dependencies: talks to Ollama's OpenAI-compatible endpoint with
|
|
57
|
+
* the built-in fetch — the shared translation core lives in
|
|
58
|
+
* lib/models/openAiCompatibleLlm.ts.
|
|
59
|
+
* - The "ollama/" prefix is a routing namespace for the LLMRegistry and is
|
|
60
|
+
* stripped before the HTTP call (Ollama knows the model as "qwen3:8b").
|
|
61
|
+
* - Reasoning models (qwen3 family) emit <think>…</think> blocks before
|
|
62
|
+
* their answer. The base class surfaces them as a { thought: true }
|
|
63
|
+
* part — printers show the scratchpad dimmed; it stays out of history.
|
|
64
|
+
* - Vision: ADK inlineData parts (images) are translated to OpenAI
|
|
65
|
+
* image_url data URIs, so ollama/qwen3-vl:8b can see attached images.
|
|
66
|
+
*
|
|
67
|
+
* LIMITATIONS vs Gemini:
|
|
68
|
+
* - web_search: a local model has no native search, so the tool is
|
|
69
|
+
* omitted with a warning. A local agent's grounding is what you supply:
|
|
70
|
+
* pasted material, subagents, or MCP tools.
|
|
71
|
+
* - generate_image / inspect_image call Gemini image models directly and
|
|
72
|
+
* still require a Gemini key regardless of the inference model.
|
|
73
|
+
* - thinkingConfig is Gemini-only; qwen3 thinks on its own schedule.
|
|
74
|
+
*/
|
|
75
|
+
import { LLMRegistry } from '@google/adk';
|
|
76
|
+
import { OpenAiCompatibleLlm } from "./openAiCompatibleLlm.js";
|
|
77
|
+
const DEFAULT_BASE_URL = 'http://localhost:11434/v1';
|
|
78
|
+
// ── OllamaLlm ─────────────────────────────────────────────────────────────────
|
|
79
|
+
export class OllamaLlm extends OpenAiCompatibleLlm {
|
|
80
|
+
/**
|
|
81
|
+
* Model ids namespaced "ollama/<model>" route here after registration,
|
|
82
|
+
* e.g. model: "ollama/qwen3:8b" in a syndicate YAML.
|
|
83
|
+
*/
|
|
84
|
+
static supportedModels = [/^ollama\/.+/];
|
|
85
|
+
baseUrl;
|
|
86
|
+
constructor({ model, baseUrl }) {
|
|
87
|
+
super({ model });
|
|
88
|
+
this.baseUrl =
|
|
89
|
+
baseUrl || process.env.OLLAMA_BASE_URL || DEFAULT_BASE_URL;
|
|
90
|
+
}
|
|
91
|
+
providerId() {
|
|
92
|
+
return 'ollama';
|
|
93
|
+
}
|
|
94
|
+
endpointUrl() {
|
|
95
|
+
return `${this.baseUrl}/chat/completions`;
|
|
96
|
+
}
|
|
97
|
+
headers() {
|
|
98
|
+
return {}; // no auth — local
|
|
99
|
+
}
|
|
100
|
+
wireModelName() {
|
|
101
|
+
return this.model.replace(/^ollama\//, '');
|
|
102
|
+
}
|
|
103
|
+
// webSearchBodyFields() stays at the base default (null): no native
|
|
104
|
+
// search locally — the tool is omitted with a warning, keys stay optional.
|
|
105
|
+
httpError(status, detail) {
|
|
106
|
+
return {
|
|
107
|
+
errorCode: 'OLLAMA_HTTP_ERROR',
|
|
108
|
+
errorMessage: `Ollama returned ${status}: ${detail.slice(0, 400)}. Is the model pulled? Try: ollama pull ${this.wireModelName()}`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
unreachable(message) {
|
|
112
|
+
return {
|
|
113
|
+
errorCode: 'OLLAMA_UNREACHABLE',
|
|
114
|
+
errorMessage: `Could not reach Ollama at ${this.baseUrl} (${message}). ` +
|
|
115
|
+
'Is it running? Start the Ollama app or run: ollama serve',
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
extraBodyFields(_llmRequest) {
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ── Registration helper ───────────────────────────────────────────────────────
|
|
123
|
+
/**
|
|
124
|
+
* Registers OllamaLlm with the ADK LLMRegistry.
|
|
125
|
+
*
|
|
126
|
+
* Unlike registerClaudeLlm(), this needs no key gate — a local provider has
|
|
127
|
+
* no credential to check. Registration is still explicit (not at import
|
|
128
|
+
* time) so entrypoints stay in control of which providers are active.
|
|
129
|
+
* If Ollama isn't running, agents fail at call time with a clear
|
|
130
|
+
* OLLAMA_UNREACHABLE message that says how to start it.
|
|
131
|
+
*/
|
|
132
|
+
export function registerOllamaLlm() {
|
|
133
|
+
LLMRegistry.register(OllamaLlm);
|
|
134
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/models/openAiCompatibleLlm.ts — shared base class for every provider
|
|
3
|
+
* that speaks the OpenAI chat-completions wire format.
|
|
4
|
+
*
|
|
5
|
+
* WHY this file exists:
|
|
6
|
+
* Separates the OpenAI chat-completions wire translation (ADK Content →
|
|
7
|
+
* chat messages, tool-definition building, tool_call parsing, usage
|
|
8
|
+
* accounting, reasoning surfacing) from provider specifics, so any
|
|
9
|
+
* /chat/completions-speaking provider is a small subclass supplying only
|
|
10
|
+
* the endpoint, auth headers, wire model name, and extra body fields.
|
|
11
|
+
* Current subclass: Ollama (local, keyless). xAI Grok used to live here
|
|
12
|
+
* too, but xAI's Agent Tools API is Responses-shaped, so GrokLlm now
|
|
13
|
+
* subclasses GptLlm instead (see lib/models/grokLlm.ts).
|
|
14
|
+
*
|
|
15
|
+
* WHAT THE BASE PROVIDES (uniformly, for every subclass):
|
|
16
|
+
* - Tool schemas normalized to lowercase JSON-Schema types
|
|
17
|
+
* (lib/models/schemaNormalize.ts — the ADK/Gemini dialect is uppercase).
|
|
18
|
+
* - usage → LlmResponse.usageMetadata mapping (prompt_tokens →
|
|
19
|
+
* promptTokenCount, completion_tokens → candidatesTokenCount,
|
|
20
|
+
* completion_tokens_details.reasoning_tokens → thoughtsTokenCount),
|
|
21
|
+
* so traceAgentRun / traceLlmGeneration count tokens for every provider.
|
|
22
|
+
* - Reasoning ("<think>…</think>" blocks, reasoning_content fields)
|
|
23
|
+
* surfaced as a { text, thought: true } part in a partial response —
|
|
24
|
+
* printers display it dimmed; it never enters session history.
|
|
25
|
+
* - A per-request `llm.request` OpenTelemetry span (lib/observability).
|
|
26
|
+
* - web_search handling: subclasses with native search return its body
|
|
27
|
+
* fields from webSearchBodyFields(); those without return null and the
|
|
28
|
+
* base omits the tool with a one-time warning + span attribute.
|
|
29
|
+
*/
|
|
30
|
+
import { BaseLlm } from '@google/adk';
|
|
31
|
+
import type { LlmRequest, LlmResponse } from '@google/adk';
|
|
32
|
+
import type { BaseLlmConnection } from '@google/adk';
|
|
33
|
+
type OpenAiContentPart = {
|
|
34
|
+
type: 'text';
|
|
35
|
+
text: string;
|
|
36
|
+
} | {
|
|
37
|
+
type: 'image_url';
|
|
38
|
+
image_url: {
|
|
39
|
+
url: string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
type OpenAiMessage = {
|
|
43
|
+
role: 'system';
|
|
44
|
+
content: string;
|
|
45
|
+
} | {
|
|
46
|
+
role: 'user';
|
|
47
|
+
content: string | OpenAiContentPart[];
|
|
48
|
+
} | {
|
|
49
|
+
role: 'assistant';
|
|
50
|
+
content: string | null;
|
|
51
|
+
tool_calls?: Array<{
|
|
52
|
+
id: string;
|
|
53
|
+
type: 'function';
|
|
54
|
+
function: {
|
|
55
|
+
name: string;
|
|
56
|
+
arguments: string;
|
|
57
|
+
};
|
|
58
|
+
}>;
|
|
59
|
+
} | {
|
|
60
|
+
role: 'tool';
|
|
61
|
+
tool_call_id: string;
|
|
62
|
+
content: string;
|
|
63
|
+
};
|
|
64
|
+
/** Splits "<think>…</think>" scratchpad from the reply. */
|
|
65
|
+
export declare function splitThinkBlocks(text: string): {
|
|
66
|
+
reasoning: string;
|
|
67
|
+
answer: string;
|
|
68
|
+
};
|
|
69
|
+
export declare abstract class OpenAiCompatibleLlm extends BaseLlm {
|
|
70
|
+
private webSearchWarned;
|
|
71
|
+
/** Provider id for telemetry, e.g. 'ollama', 'xai'. */
|
|
72
|
+
protected abstract providerId(): string;
|
|
73
|
+
/** Full chat-completions URL, e.g. "https://api.x.ai/v1/chat/completions". */
|
|
74
|
+
protected abstract endpointUrl(): string;
|
|
75
|
+
/** Auth/extra headers. Content-Type is added by the base. */
|
|
76
|
+
protected abstract headers(): Record<string, string>;
|
|
77
|
+
/** Model id as the wire expects it (e.g. strip the "ollama/" namespace). */
|
|
78
|
+
protected wireModelName(): string;
|
|
79
|
+
/** Provider-specific request body fields (merged last). */
|
|
80
|
+
protected extraBodyFields(_llmRequest: LlmRequest): Record<string, unknown>;
|
|
81
|
+
/**
|
|
82
|
+
* Body fields enabling the provider's NATIVE web search, or null when the
|
|
83
|
+
* provider has none (the base then omits the tool and warns once).
|
|
84
|
+
*/
|
|
85
|
+
protected webSearchBodyFields(): Record<string, unknown> | null;
|
|
86
|
+
/**
|
|
87
|
+
* Extracts reasoning from the response message. Default: "<think>" blocks
|
|
88
|
+
* in content plus the reasoning_content / reasoning fields emitted by
|
|
89
|
+
* OpenAI-compatible reasoning models.
|
|
90
|
+
*/
|
|
91
|
+
protected extractReasoning(message: {
|
|
92
|
+
content?: string | null;
|
|
93
|
+
reasoning_content?: string;
|
|
94
|
+
reasoning?: string;
|
|
95
|
+
}): {
|
|
96
|
+
reasoning: string;
|
|
97
|
+
answer: string;
|
|
98
|
+
};
|
|
99
|
+
/** Yielded before the HTTP call when a precondition is missing (e.g. no
|
|
100
|
+
* API key). Return undefined when ready to call. */
|
|
101
|
+
protected missingRequirement(): LlmResponse | undefined;
|
|
102
|
+
/** Error response for a non-2xx HTTP status. */
|
|
103
|
+
protected httpError(status: number, detail: string): LlmResponse;
|
|
104
|
+
/** Error response when the endpoint can't be reached at all. */
|
|
105
|
+
protected unreachable(message: string): LlmResponse;
|
|
106
|
+
generateContentAsync(llmRequest: LlmRequest, stream?: boolean): AsyncGenerator<LlmResponse, void>;
|
|
107
|
+
private generateInner;
|
|
108
|
+
/** ADK Contents (Google GenAI format) → OpenAI-compatible chat messages. */
|
|
109
|
+
protected buildMessages(llmRequest: LlmRequest): OpenAiMessage[];
|
|
110
|
+
/** ADK toolsDict → OpenAI function-tool definitions (lowercase schemas). */
|
|
111
|
+
protected buildTools(llmRequest: LlmRequest): unknown[];
|
|
112
|
+
/**
|
|
113
|
+
* Live/bidirectional streaming — not part of the OpenAI-compatible
|
|
114
|
+
* chat-completions surface. Throws to surface this clearly.
|
|
115
|
+
*/
|
|
116
|
+
connect(_llmRequest: LlmRequest): Promise<BaseLlmConnection>;
|
|
117
|
+
}
|
|
118
|
+
/** OpenAI-style usage → GenAI usageMetadata (undefined when absent). */
|
|
119
|
+
export declare function mapUsage(usage: any): {
|
|
120
|
+
promptTokenCount?: number;
|
|
121
|
+
candidatesTokenCount?: number;
|
|
122
|
+
thoughtsTokenCount?: number;
|
|
123
|
+
totalTokenCount?: number;
|
|
124
|
+
} | undefined;
|
|
125
|
+
export {};
|