universal-llm-client 4.3.0 → 4.5.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 (151) hide show
  1. package/CHANGELOG.md +27 -24
  2. package/README.md +60 -11
  3. package/dist/ai-model.d.ts +12 -1
  4. package/dist/ai-model.d.ts.map +1 -1
  5. package/dist/ai-model.js +36 -1
  6. package/dist/ai-model.js.map +1 -1
  7. package/dist/auditor.js.map +1 -1
  8. package/dist/client.js.map +1 -1
  9. package/dist/gemma-channel.d.ts +14 -0
  10. package/dist/gemma-channel.d.ts.map +1 -0
  11. package/dist/gemma-channel.js +38 -0
  12. package/dist/gemma-channel.js.map +1 -0
  13. package/dist/gemma-diffusion.d.ts +49 -0
  14. package/dist/gemma-diffusion.d.ts.map +1 -0
  15. package/dist/gemma-diffusion.js +147 -0
  16. package/dist/gemma-diffusion.js.map +1 -0
  17. package/dist/http.d.ts +4 -0
  18. package/dist/http.d.ts.map +1 -1
  19. package/dist/http.js +14 -1
  20. package/dist/http.js.map +1 -1
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +4 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/interfaces.d.ts +163 -7
  26. package/dist/interfaces.d.ts.map +1 -1
  27. package/dist/interfaces.js.map +1 -1
  28. package/dist/mcp.js.map +1 -1
  29. package/dist/providers/anthropic.d.ts.map +1 -1
  30. package/dist/providers/anthropic.js +28 -3
  31. package/dist/providers/anthropic.js.map +1 -1
  32. package/dist/providers/google.d.ts +22 -1
  33. package/dist/providers/google.d.ts.map +1 -1
  34. package/dist/providers/google.js +223 -13
  35. package/dist/providers/google.js.map +1 -1
  36. package/dist/providers/index.js.map +1 -1
  37. package/dist/providers/ollama.d.ts +2 -0
  38. package/dist/providers/ollama.d.ts.map +1 -1
  39. package/dist/providers/ollama.js +59 -30
  40. package/dist/providers/ollama.js.map +1 -1
  41. package/dist/providers/openai.d.ts +14 -0
  42. package/dist/providers/openai.d.ts.map +1 -1
  43. package/dist/providers/openai.js +200 -22
  44. package/dist/providers/openai.js.map +1 -1
  45. package/dist/router.d.ts +2 -0
  46. package/dist/router.d.ts.map +1 -1
  47. package/dist/router.js +4 -0
  48. package/dist/router.js.map +1 -1
  49. package/dist/stream-decoder.d.ts +12 -0
  50. package/dist/stream-decoder.d.ts.map +1 -1
  51. package/dist/stream-decoder.js +182 -5
  52. package/dist/stream-decoder.js.map +1 -1
  53. package/dist/structured-output.js.map +1 -1
  54. package/dist/thinking.d.ts +36 -0
  55. package/dist/thinking.d.ts.map +1 -0
  56. package/dist/thinking.js +52 -0
  57. package/dist/thinking.js.map +1 -0
  58. package/dist/tools.js.map +1 -1
  59. package/dist/zod-adapter.js.map +1 -1
  60. package/package.json +4 -1
  61. package/src/ai-model.ts +400 -0
  62. package/src/auditor.ts +213 -0
  63. package/src/client.ts +402 -0
  64. package/src/debug/debug-google-streaming.ts +97 -0
  65. package/src/debug/debug-tool-execution.ts +86 -0
  66. package/src/debug/test-lmstudio-tools.ts +155 -0
  67. package/src/demos/README.md +47 -0
  68. package/src/demos/basic/universal-llm-examples.ts +161 -0
  69. package/src/demos/diffusion-gemma/.env +29 -0
  70. package/src/demos/diffusion-gemma/.env.example +27 -0
  71. package/src/demos/diffusion-gemma/CLAUDE.md +95 -0
  72. package/src/demos/diffusion-gemma/README.md +59 -0
  73. package/src/demos/diffusion-gemma/canvas.ts +1606 -0
  74. package/src/demos/diffusion-gemma/docker-compose.yml +29 -0
  75. package/src/demos/diffusion-gemma/probe-stream.ts +51 -0
  76. package/src/demos/diffusion-gemma/probe-tools.ts +55 -0
  77. package/src/demos/diffusion-gemma/server.ts +1205 -0
  78. package/src/demos/diffusion-gemma/start-vllm.sh +98 -0
  79. package/src/demos/mcp/astrid-memory-demo.ts +295 -0
  80. package/src/demos/mcp/astrid-persona-memory.ts +357 -0
  81. package/src/demos/mcp/mcp-mongodb-demo.ts +275 -0
  82. package/src/demos/mcp/simple-astrid-memory.ts +148 -0
  83. package/src/demos/mcp/simple-mcp-demo.ts +68 -0
  84. package/src/demos/mcp/working-mcp-demo.ts +62 -0
  85. package/src/demos/model-alias-demo.ts +0 -0
  86. package/src/demos/tools/RAG_MEMORY_INTEGRATION.md +267 -0
  87. package/src/demos/tools/astrid-memory-demo.ts +270 -0
  88. package/src/demos/tools/astrid-production-memory-clean.ts +785 -0
  89. package/src/demos/tools/astrid-production-memory.ts +558 -0
  90. package/src/demos/tools/basic-translation-test.ts +66 -0
  91. package/src/demos/tools/chromadb-similarity-tuning.ts +390 -0
  92. package/src/demos/tools/clean-multilingual-conversation.ts +209 -0
  93. package/src/demos/tools/clean-translation-test.ts +119 -0
  94. package/src/demos/tools/clean-universal-multilingual-test.ts +131 -0
  95. package/src/demos/tools/complete-rag-demo.ts +369 -0
  96. package/src/demos/tools/complete-tool-demo.ts +132 -0
  97. package/src/demos/tools/demo-tool-calling.ts +124 -0
  98. package/src/demos/tools/dynamic-language-switching-test.ts +251 -0
  99. package/src/demos/tools/hybrid-thinking-test.ts +154 -0
  100. package/src/demos/tools/memory-integration-test.ts +420 -0
  101. package/src/demos/tools/multilingual-memory-system.ts +802 -0
  102. package/src/demos/tools/ondemand-translation-demo.ts +655 -0
  103. package/src/demos/tools/production-tool-demo.ts +245 -0
  104. package/src/demos/tools/revolutionary-multilingual-test.ts +151 -0
  105. package/src/demos/tools/rigorous-language-analysis.ts +218 -0
  106. package/src/demos/tools/test-universal-memory-system.ts +126 -0
  107. package/src/demos/tools/translation-integration-guide.ts +346 -0
  108. package/src/demos/tools/universal-memory-system.ts +560 -0
  109. package/src/gemma-channel.ts +47 -0
  110. package/src/gemma-diffusion.ts +167 -0
  111. package/src/http.ts +261 -0
  112. package/src/index.ts +180 -0
  113. package/src/interfaces.ts +843 -0
  114. package/src/mcp.ts +345 -0
  115. package/src/providers/anthropic.ts +796 -0
  116. package/src/providers/google.ts +840 -0
  117. package/src/providers/index.ts +8 -0
  118. package/src/providers/ollama.ts +503 -0
  119. package/src/providers/openai.ts +587 -0
  120. package/src/router.ts +785 -0
  121. package/src/stream-decoder.ts +535 -0
  122. package/src/structured-output.ts +759 -0
  123. package/src/test-scripts/test-advanced-tools.ts +310 -0
  124. package/src/test-scripts/test-google-deep-research.ts +33 -0
  125. package/src/test-scripts/test-google-streaming-enhanced.ts +147 -0
  126. package/src/test-scripts/test-google-streaming.ts +63 -0
  127. package/src/test-scripts/test-google-system-prompt-comprehensive.ts +189 -0
  128. package/src/test-scripts/test-google-thinking.ts +46 -0
  129. package/src/test-scripts/test-mcp-config.ts +28 -0
  130. package/src/test-scripts/test-mcp-connection.ts +29 -0
  131. package/src/test-scripts/test-system-message-positions.ts +163 -0
  132. package/src/test-scripts/test-system-prompt-improvement-demo.ts +83 -0
  133. package/src/test-scripts/test-tool-calling.ts +231 -0
  134. package/src/test-scripts/test-vllm-qwen36.ts +256 -0
  135. package/src/tests/ai-model.test.ts +1614 -0
  136. package/src/tests/auditor.test.ts +224 -0
  137. package/src/tests/gemma-diffusion.test.ts +115 -0
  138. package/src/tests/http.test.ts +200 -0
  139. package/src/tests/interfaces.test.ts +117 -0
  140. package/src/tests/providers/anthropic.test.ts +118 -0
  141. package/src/tests/providers/google.test.ts +841 -0
  142. package/src/tests/providers/ollama.test.ts +1034 -0
  143. package/src/tests/providers/openai.test.ts +1511 -0
  144. package/src/tests/router.test.ts +254 -0
  145. package/src/tests/stream-decoder.test.ts +263 -0
  146. package/src/tests/structured-output.test.ts +1450 -0
  147. package/src/tests/thinking.test.ts +65 -0
  148. package/src/tests/tools.test.ts +175 -0
  149. package/src/thinking.ts +73 -0
  150. package/src/tools.ts +246 -0
  151. package/src/zod-adapter.ts +72 -0
package/CHANGELOG.md CHANGED
@@ -5,41 +5,44 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [4.3.0] - 2026-05-14
8
+ ## [4.5.0] - 2026-06-14
9
9
 
10
10
  ### Added
11
11
 
12
- - **`TokenUsageInfo.reasoningTokens`** new optional field reporting server-side thinking/reasoning tokens that are billed but not emitted as visible text. Currently populated by the Google provider from `usageMetadata.thoughtsTokenCount` for Gemini thinking models (2.5 Pro / 3.x Pro). Other providers either roll thinking into `outputTokens` (Ollama) or surface it via `DecodedEvent { type: 'thinking' }`.
13
- - **`GoogleResponse.usageMetadata.thoughtsTokenCount`** typed on the raw provider response shape.
12
+ - **Server-side reasoning field support (OpenAI-compatible provider)** Reasoning models served over the OpenAI-compatible API (vLLM `--reasoning-parser`, DeepSeek-R1, etc.) return their chain-of-thought in a dedicated `reasoning_content` (vLLM) / `reasoning` (some gateways) field instead of inline `<think>` tags. The OpenAI provider now surfaces it:
13
+ - `chat()` populates `LLMChatResponse.reasoning` from `message.reasoning_content` / `message.reasoning`, keeping `message.content` clean
14
+ - `chatStream()` emits `delta.reasoning_content` / `delta.reasoning` chunks as `thinking` stream events and accumulates them into the final `reasoning`
15
+ - Inline `<think>` parsing (via `StandardChatDecoder`) is preserved as a fallback for servers run without a reasoning parser
16
+ - `OpenAIResponse` message type extended with optional `reasoning` / `reasoning_content`
17
+ - Verified end-to-end against vLLM serving `nvidia/Qwen3.6-35B-A3B-NVFP4` (NVFP4) on Blackwell — reasoning, streaming `thinking` events, tool calling (`qwen3_xml`), and structured output all pass
18
+ - **Unified `thinking` flag with levels across all providers** — `thinking` (model config) and per-call `ChatOptions.thinking` accept `true`/`false` **or a level `'minimal' | 'low' | 'medium' | 'high'`** (new `ThinkingLevel` type), mapped to each backend's native control so apps switch providers without reasoning-specific code. A shared `resolveThinking` helper (`src/thinking.ts`) normalizes the value; each provider maps it:
19
+ - **OpenAI-compatible** → OpenAI reasoning models (o-series / GPT-5, by name) get `reasoning_effort:<level>`; vLLM / Qwen get `chat_template_kwargs.enable_thinking`. Emitted only when explicitly set.
20
+ - **Google / Gemini** → Gemini 3.x `thinkingConfig.thinkingLevel`; Gemini 2.5/2.0 `thinkingBudget` (level→budget map, `0` off, `-1` dynamic). `includeThoughts` enabled when thinking is on.
21
+ - **Anthropic** → extended thinking `budget_tokens` from the level (kept `< max_tokens`; temperature omitted, per API).
22
+ - **Ollama** → `think` on/off (no native levels).
23
+ - Per-call overrides model config everywhere. Verified live against vLLM (Qwen3.6-NVFP4) and **Gemini 3.5 Flash** (levels produce distinct reasoning-token counts); unit-tested per provider + `resolveThinking`.
24
+ - **Gemini reasoning text surfaced** — with thinking on, the Google provider sets `includeThoughts:true` and routes `thought:true` parts into `response.reasoning` (non-streaming) and live `thinking` stream events, matching how Qwen/Anthropic expose chain-of-thought (previously only `reasoningTokens` was reported). Verified live on `gemini-3.5-flash` (654–976 chars of reasoning across levels).
25
+ - **Gemini Deep Research API** — new Google-only `AIModel.deepResearch(input, opts)` (creates a `/v1beta/interactions` background interaction and polls to completion → `{ id, status, report, steps }`) and `AIModel.deepResearchStream(input, opts)` (live `thought`/`text`/`status` events). New `DeepResearchOptions`/`DeepResearchResult`/`DeepResearchStep`/`DeepResearchEvent` types. Throws a clear error if no Google provider is configured. Create + poll plumbing verified live.
26
+ - **Generation stats — `usage.durationMs` and `usage.tokensPerSecond`** — decode throughput is now reported on `LLMChatResponse.usage`: server-precise for Ollama (from `eval_count` / `eval_duration`, which were previously discarded), and client-measured wall-clock for OpenAI-compatible / vLLM (which return no timing in `usage`). `OllamaResponse` gained `total_duration` / `load_duration` typings.
27
+ - **OpenAI-compatible transport flexibility** — `ProviderConfig` gains `headers`, `queryParams`, `authHeader`, `authPrefix`, and `apiBasePath` for Azure OpenAI, custom gateways, and non-`/v1` servers (no custom code needed). Honored by the OpenAI-compatible provider (`headers`/`authHeader`/`authPrefix` also by Ollama, via `buildHeaders`); a `buildUrl` helper applies `queryParams`/`apiBasePath` across all endpoints and preserves any query string already on the base URL. Includes a 2026 provider-API-landscape research doc (`docs/research/`).
14
28
 
15
- ### Changed
16
-
17
- - **Slimmer published tarball** — `src/` is no longer shipped to npm. The published package drops from ~271 kB / 144 files to ~146 kB / 72 files. Source maps now embed original sources (`inlineSources: true`), so debuggers stepping into the library continue to show TypeScript source without needing the raw `.ts` files in the tarball.
18
-
19
- ## [4.2.0] - Previously released
20
-
21
- ### Added
29
+ ### Fixed
22
30
 
23
- - **Ollama native thinking enabled by default** `think` parameter is now sent on every request to prevent model-default thinking from leaking into tool selection / reasoning paths.
24
- - **Ollama stream idle timeout** — `OllamaClient` enforces a minimum response wait time to avoid hung streams.
25
- - **Ollama live context length** — provider now fetches the running context length from `/api/ps` and reports model capabilities.
26
- - **Google Gemini service tiers** — configurable service tier with per-tier timeouts and retry logic.
27
- - **`LLMAudioContent` type** — audio content support across providers.
28
- - **Structured output tolerates markdown fences** — JSON output wrapped in ```` ```json ```` fences is now parsed correctly.
31
+ - **README** the tool-execution trace field is `response.toolExecutions` (array of `{ tool_call_id, output, error?, duration? }`), not `toolTrace`; corrected the `chatWithTools` example.
29
32
 
30
- ## [4.1.0] - Previously released
33
+ ## [4.4.0] - 2026-06-11
31
34
 
32
35
  ### Added
33
36
 
34
- - **Prompt caching support** — first-class cache configuration plumbed through providers.
35
- - **Anthropic provider** — `AnthropicClient` implementation of the universal protocol.
36
- - **Request cancellation** `signal: AbortSignal` accepted on all chat methods.
37
- - **Decoupled structured output from Zod** — new generic `SchemaConfig` interface; Zod becomes an adapter (`./zod` sub-path) rather than a hard dependency on the schema path.
38
- - **Wider JSONSchema tuple types** — schema utilities accept more JSON Schema tuple shapes.
37
+ - **Diffusion LM support (DiffusionGemma family)** — First-class client-side protocol for diffusion language models served by OpenAI-compatible endpoints that ship without server-side reasoning or tool-call parsers (e.g. current vLLM diffusion builds, which reject request-level `tools` with auto tool choice):
38
+ - `gemma-diffusion.ts`model detection (`isGemmaDiffusionModel`), native channel parsing (`<|channel>thought … <channel|>` reasoning, `<|tool_call>call:name{…}<tool_call|>` tool calls), and pseudo-JSON argument conversion (`gemmaArgsToJson`: `<|"|>` quote tokens, bare keys, nested objects/arrays)
39
+ - OpenAI provider native mode (auto-detected from the model name, `gemmaNativeProtocol` option to override): sends `skip_special_tokens: false` and `tools` + `tool_choice: "none"` (declarations still render into the chat template), parses reasoning and tool calls client-side, and yields decoder-classified `thinking`/`text` streaming events
40
+ - Full agentic `chatWithTools` loop works end-to-end against DiffusionGemma; history tool turns use standard structured `tool_calls` + `role: "tool"` messages
41
+ - **"Signal from Noise" demo** (`src/demos/diffusion-gemma/`) vLLM test harness plus a diffusion chat canvas that animates block-parallel denoising paced by real block arrivals, with replay/scrubbing, reasoning-channel separation, a rendered-markdown reading view, and an engine-reload entropy control
39
42
 
40
- ### Changed
43
+ ### Fixed
41
44
 
42
- - Tests migrated to the new `fromZod` adapter API.
45
+ - Stray unbalanced `<channel|>` / `<turn|>` markers emitted by diffusion models are stripped from parsed content
43
46
 
44
47
  ## [4.0.0] - 2026-03-13
45
48
 
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # universal-llm-client
2
2
 
3
- A universal LLM client for JavaScript/TypeScript with **transparent provider failover**, streaming tool execution, pluggable reasoning strategies, and native observability.
3
+ A universal LLM client for JavaScript/TypeScript with **transparent provider failover** and a **provider-agnostic reasoning API** — one set of code across OpenAI, Anthropic, Google Gemini, Ollama, vLLM, and any OpenAI-compatible endpoint. Streaming tool execution, structured output, generation stats, and native observability included.
4
4
 
5
5
  ```typescript
6
6
  import { AIModel } from 'universal-llm-client';
7
7
 
8
8
  const model = new AIModel({
9
- model: 'gemini-2.5-flash',
9
+ model: 'gemini-3.5-flash',
10
10
  providers: [
11
11
  { type: 'google', apiKey: process.env.GOOGLE_API_KEY },
12
12
  { type: 'openai', url: 'https://openrouter.ai/api', apiKey: process.env.OPENROUTER_KEY },
@@ -26,10 +26,13 @@ const response = await model.chat([
26
26
  ## Features
27
27
 
28
28
  - 🔄 **Transparent Failover** — Priority-ordered provider chain with retries, health tracking, and cooldowns
29
+ - 🧠 **Unified Reasoning** — One `thinking` flag (`true`/`false` or a level: `'minimal' | 'low' | 'medium' | 'high'`) mapped to each backend's native control; chain-of-thought surfaced as `response.reasoning` + streaming `thinking` events (with `<think>`-tag parsing as a fallback)
29
30
  - 🛠️ **Tool Calling** — Register tools once, works across all providers. Autonomous multi-turn execution loop
30
31
  - 📋 **Structured Output** — Zod schema validation, JSON Schema support, streaming, and type-safe responses
31
32
  - 🌊 **Streaming** — First-class async generator streaming with pluggable decoder strategies
32
- - 🧠 **Reasoning** — Native `<think>` tag parsing, interleaved reasoning, and model thinking support
33
+ - 🔬 **Deep Research** — Drive Google Gemini's agentic Deep Research (background interactions with polling + streaming)
34
+ - 📈 **Generation Stats** — `usage.tokensPerSecond` and `durationMs` reported across providers
35
+ - 🔌 **Flexible Transport** — Custom headers, query params, auth header/prefix, and base path for Azure OpenAI and gateways
33
36
  - 🔍 **Observability** — Built-in auditor interface for logging, cost tracking, and behavioral analysis
34
37
  - 🌐 **Universal Runtime** — Node.js 22+, Bun, Deno, and modern browsers
35
38
  - 🤖 **MCP Native** — Bridge MCP servers to LLM tools with zero glue code
@@ -39,11 +42,14 @@ const response = await model.chat([
39
42
 
40
43
  | Provider | Type | Notes |
41
44
  |---|---|---|
42
- | **Ollama** | `ollama` | Local or cloud models, NDJSON streaming, model pulling, vision/multimodal |
43
- | **OpenAI** | `openai` | GPT-4o, o3, etc. Also works with OpenRouter, Groq, LM Studio, vLLM |
44
- | **Google AI Studio** | `google` | Gemini models, system instructions, multimodal |
45
- | **Vertex AI** | `vertex` | Same as Google AI but with regional endpoints and Bearer tokens |
46
- | **LlamaCpp** | `llamacpp` | Local llama.cpp / llama-server instances |
45
+ | **Ollama** | `ollama` | Local or cloud models, NDJSON streaming, model pulling, vision/multimodal, native thinking |
46
+ | **OpenAI + Compat** | `openai` | GPT series, o-series + **any OpenAI-compatible endpoint**: xAI/Grok, Mistral, DeepSeek, Cohere Compatibility, Groq, Together, Fireworks, OpenRouter, Perplexity Sonar, vLLM, LM Studio, TGI, most self-hosted servers |
47
+ | **Google AI Studio** | `google` | Gemini models, system instructions, multimodal, native thinking + grounding |
48
+ | **Vertex AI** | `vertex` | Same as Google AI but with regional endpoints, Bearer tokens, service tiers (flex/priority) |
49
+ | **Anthropic (Claude)** | `anthropic` | Claude 3.5/4 models via native Messages API. Excellent tool use, extended thinking with signatures, strong prompt caching |
50
+ | **LlamaCpp** | `llamacpp` | Local llama.cpp / llama-server instances (OpenAI-compatible under the hood) |
51
+
52
+ **Most of the world** is reachable via `type: 'openai'` + a `url` override. We only maintain dedicated clients for fundamentally different protocols (Anthropic Messages, Google Gemini) that offer unique high-value capabilities, plus Ollama for local developer experience. See `docs/guide/providers.md` and the research survey in `docs/research/provider-api-landscape-2026.md`.
47
53
 
48
54
  ---
49
55
 
@@ -98,6 +104,44 @@ for await (const event of model.chatStream([
98
104
  }
99
105
  ```
100
106
 
107
+ ### Thinking & Reasoning
108
+
109
+ Set one `thinking` value — `true`/`false` or a level (`'minimal' | 'low' | 'medium' | 'high'`) —
110
+ and it maps to each provider's native control (Gemini `thinkingLevel`/`thinkingBudget`, OpenAI
111
+ `reasoning_effort`, vLLM `enable_thinking`, Anthropic `budget_tokens`, Ollama `think`):
112
+
113
+ ```typescript
114
+ const model = new AIModel({
115
+ model: 'gemini-3.5-flash',
116
+ thinking: 'high', // true | false | 'minimal' | 'low' | 'medium' | 'high'
117
+ providers: [{ type: 'google', apiKey: process.env.GOOGLE_API_KEY }],
118
+ });
119
+
120
+ const res = await model.chat([{ role: 'user', content: 'Solve this step by step: ...' }]);
121
+ console.log(res.message.content); // final answer (clean)
122
+ console.log(res.reasoning); // chain-of-thought, when the model exposes it
123
+
124
+ // Per-call override (e.g. turn thinking off for structured output)
125
+ await model.chat(messages, { thinking: false });
126
+ ```
127
+
128
+ ### Deep Research (Gemini)
129
+
130
+ Run Google's agentic Deep Research — creates a background interaction and polls to completion:
131
+
132
+ ```typescript
133
+ const result = await model.deepResearch('Research the history of Google TPUs.', {
134
+ tools: ['google_search', 'url_context'],
135
+ });
136
+ console.log(result.status, result.report);
137
+
138
+ // Or stream intermediate thoughts and steps as they arrive:
139
+ for await (const ev of model.deepResearchStream('Compare RISC-V vs ARM in 2026.')) {
140
+ if (ev.type === 'thought') console.log('[thinking]', ev.content);
141
+ else if (ev.type === 'text') process.stdout.write(ev.content);
142
+ }
143
+ ```
144
+
101
145
  ### Tool Calling
102
146
 
103
147
  ```typescript
@@ -124,8 +168,8 @@ const response = await model.chatWithTools([
124
168
 
125
169
  console.log(response.message.content);
126
170
  // "The weather in Tokyo is 22°C and sunny."
127
- console.log(response.toolTrace);
128
- // [{ name: 'get_weather', args: { city: 'Tokyo' }, result: {...}, duration: 5 }]
171
+ console.log(response.toolExecutions);
172
+ // [{ tool_call_id: 'call_abc', output: { temperature: 22, condition: 'sunny', city: 'Tokyo' }, duration: 5 }]
129
173
  ```
130
174
 
131
175
  ### Provider Failover
@@ -421,13 +465,18 @@ new AIModel(config: AIModelConfig)
421
465
 
422
466
  | Property | Type | Description |
423
467
  |---|---|---|
424
- | `type` | `string` | `'ollama'`, `'openai'`, `'google'`, `'vertex'`, `'llamacpp'` |
468
+ | `type` | `string` | `'ollama'`, `'openai'`, `'google'`, `'vertex'`, `'llamacpp'`, `'anthropic'` |
425
469
  | `url` | `string` | Provider URL (has sensible defaults) |
426
470
  | `apiKey` | `string` | API key or Bearer token |
427
471
  | `priority` | `number` | Lower = tried first (defaults to array index) |
428
472
  | `model` | `string` | Override model name for this provider |
429
473
  | `region` | `string` | Vertex AI region (e.g., `'us-central1'`) |
430
474
  | `apiVersion` | `string` | API version (e.g., `'v1beta'`) |
475
+ | `headers` | `Record<string,string>` | Extra headers merged into requests — OpenAI-compatible & Ollama (Azure `api-key`, gateways) |
476
+ | `queryParams` | `Record<string,string>` | Query params appended to URLs — OpenAI-compatible only (e.g. Azure `api-version`) |
477
+ | `authHeader` | `string` | Header name for the key — OpenAI-compatible & Ollama (e.g. `'api-key'`) |
478
+ | `authPrefix` | `string` | Prefix before the key value — OpenAI-compatible & Ollama (e.g. `''` for api-key style) |
479
+ | `apiBasePath` | `string` | OpenAI-compatible only: override or disable the `/v1` suffix (use `''` for full Azure deployment URLs) |
431
480
 
432
481
  **Methods:**
433
482
 
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Provider classes are internal — the user never imports them.
8
8
  */
9
- import { type AIModelConfig, type LLMChatMessage, type LLMChatResponse, type ChatOptions, type ModelMetadata, type LLMFunction, type ToolHandler } from './interfaces.js';
9
+ import { type AIModelConfig, type LLMChatMessage, type LLMChatResponse, type ChatOptions, type ModelMetadata, type LLMFunction, type ToolHandler, type DeepResearchOptions, type DeepResearchResult, type DeepResearchEvent } from './interfaces.js';
10
10
  import type { DecodedEvent } from './stream-decoder.js';
11
11
  import { type ProviderStatus } from './router.js';
12
12
  import { type StructuredOutputResult, type SchemaConfig } from './structured-output.js';
@@ -113,6 +113,17 @@ export declare class AIModel {
113
113
  embed(text: string): Promise<number[]>;
114
114
  /** Generate embeddings for multiple texts */
115
115
  embedArray(texts: string[]): Promise<number[][]>;
116
+ private getGoogleClient;
117
+ /**
118
+ * Run an agentic Deep Research interaction (Gemini only): creates it and
119
+ * polls until completion. Throws if no Google provider is configured.
120
+ */
121
+ deepResearch(input: string, options?: DeepResearchOptions): Promise<DeepResearchResult>;
122
+ /**
123
+ * Stream a Deep Research interaction's intermediate thought/text/step events
124
+ * (Gemini only), returning the final result. Throws if no Google provider.
125
+ */
126
+ deepResearchStream(input: string, options?: DeepResearchOptions): AsyncGenerator<DeepResearchEvent, DeepResearchResult, unknown>;
116
127
  /** Register a tool callable by the LLM (broadcast to all providers) */
117
128
  registerTool(name: string, description: string, parameters: LLMFunction['parameters'], handler: ToolHandler): void;
118
129
  /** Register multiple tools at once */
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model.d.ts","sourceRoot":"","sources":["../src/ai-model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ai-model.d.ts","sourceRoot":"","sources":["../src/ai-model.ts"],"names":[],"mappings":"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"}
package/dist/ai-model.js CHANGED
@@ -172,6 +172,34 @@ export class AIModel {
172
172
  return this.router.embedArray(texts);
173
173
  }
174
174
  // ========================================================================
175
+ // Deep Research (Gemini-only)
176
+ // ========================================================================
177
+ getGoogleClient(method) {
178
+ const googleClients = this.router.getClients().filter((c) => c instanceof GoogleClient);
179
+ // Prefer an AI Studio client — Vertex AI doesn't support Deep Research.
180
+ const aiStudio = googleClients.find(c => c.supportsDeepResearch());
181
+ if (aiStudio)
182
+ return aiStudio;
183
+ if (googleClients.length > 0) {
184
+ throw new Error(`${method} requires an AI Studio Google provider (type: "google"); Vertex AI is not supported for Deep Research.`);
185
+ }
186
+ throw new Error(`${method} requires a Google provider (type: "google"). None is configured.`);
187
+ }
188
+ /**
189
+ * Run an agentic Deep Research interaction (Gemini only): creates it and
190
+ * polls until completion. Throws if no Google provider is configured.
191
+ */
192
+ async deepResearch(input, options) {
193
+ return this.getGoogleClient('deepResearch').deepResearch(input, options);
194
+ }
195
+ /**
196
+ * Stream a Deep Research interaction's intermediate thought/text/step events
197
+ * (Gemini only), returning the final result. Throws if no Google provider.
198
+ */
199
+ async *deepResearchStream(input, options) {
200
+ return yield* this.getGoogleClient('deepResearchStream').deepResearchStream(input, options);
201
+ }
202
+ // ========================================================================
175
203
  // Tool Registration
176
204
  // ========================================================================
177
205
  /** Register a tool callable by the LLM (broadcast to all providers) */
@@ -232,9 +260,16 @@ export class AIModel {
232
260
  retries: this.config.retries ?? 2,
233
261
  debug: this.config.debug ?? false,
234
262
  defaultParameters: this.config.defaultParameters,
235
- thinking: this.config.thinking ?? false,
263
+ // Preserve `undefined` (not set) vs explicit false so providers can
264
+ // decide whether to send a thinking toggle at all.
265
+ thinking: this.config.thinking,
236
266
  region: providerConfig.region,
237
267
  apiVersion: providerConfig.apiVersion,
268
+ extraHeaders: providerConfig.headers,
269
+ queryParams: providerConfig.queryParams,
270
+ authHeader: providerConfig.authHeader,
271
+ authPrefix: providerConfig.authPrefix,
272
+ apiBasePath: providerConfig.apiBasePath,
238
273
  };
239
274
  switch (type) {
240
275
  case 'ollama':
@@ -1 +1 @@
1
- {"version":3,"file":"ai-model.js","sourceRoot":"","sources":["../src/ai-model.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Universal LLM Client v3 — AIModel (The Universal Client)\r\n *\r\n * The only public-facing class. Developers configure one model with\r\n * multiple provider backends for transparent failover.\r\n *\r\n * Provider classes are internal — the user never imports them.\r\n */\r\n\r\nimport {\r\n AIModelApiType,\r\n type AIModelConfig,\r\n type ProviderConfig,\r\n type LLMClientOptions,\r\n type LLMChatMessage,\r\n type LLMChatResponse,\r\n type ChatOptions,\r\n type ModelMetadata,\r\n type LLMFunction,\r\n type ToolHandler,\r\n} from './interfaces.js';\r\nimport type { DecodedEvent } from './stream-decoder.js';\r\nimport { Router, type RouterConfig, type ProviderStatus } from './router.js';\r\nimport type { Auditor } from './auditor.js';\r\nimport { NoopAuditor } from './auditor.js';\r\nimport { OllamaClient } from './providers/ollama.js';\r\nimport { OpenAICompatibleClient } from './providers/openai.js';\r\nimport { GoogleClient } from './providers/google.js';\r\nimport { AnthropicClient } from './providers/anthropic.js';\r\nimport { BaseLLMClient } from './client.js';\r\nimport {\r\n type StructuredOutputResult,\r\n type SchemaConfig,\r\n} from './structured-output.js';\r\n\r\n// ============================================================================\r\n// Default Provider URLs\r\n// ============================================================================\r\n\r\nconst DEFAULT_URLS: Record<string, string> = {\r\n ollama: 'http://localhost:11434',\r\n openai: 'https://api.openai.com',\r\n llamacpp: 'http://localhost:8080',\r\n anthropic: 'https://api.anthropic.com',\r\n // google and vertex build their own URLs internally\r\n};\r\n\r\n// ============================================================================\r\n// AIModel — The Universal Client\r\n// ============================================================================\r\n\r\nexport class AIModel {\r\n private router: Router;\r\n private auditor: Auditor;\r\n private config: AIModelConfig;\r\n\r\n constructor(config: AIModelConfig) {\r\n this.config = config;\r\n this.auditor = config.auditor ?? new NoopAuditor();\r\n\r\n const routerConfig: RouterConfig = {\r\n retriesPerProvider: config.retries ?? 2,\r\n auditor: this.auditor,\r\n };\r\n this.router = new Router(routerConfig);\r\n\r\n // Initialize providers in order\r\n for (let i = 0; i < config.providers.length; i++) {\r\n const providerConfig = config.providers[i]!;\r\n const client = this.createClient(providerConfig);\r\n const id = `${this.normalizeType(providerConfig.type)}-${i}`;\r\n\r\n this.router.addProvider({\r\n id,\r\n client,\r\n priority: providerConfig.priority ?? i,\r\n modelOverride: providerConfig.model,\r\n });\r\n }\r\n }\r\n\r\n // ========================================================================\r\n // Chat\r\n // ========================================================================\r\n\r\n /** Send a chat request with automatic failover across providers */\r\n async chat(\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): Promise<LLMChatResponse> {\r\n return this.router.chat(messages, options);\r\n }\r\n\r\n /** Chat with automatic tool execution (multi-turn loop) */\r\n async chatWithTools(\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions & { maxIterations?: number },\r\n ): Promise<LLMChatResponse> {\r\n return this.router.chatWithTools(messages, options);\r\n }\r\n\r\n /** Stream chat response with pluggable decoder strategy */\r\n async *chatStream(\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): AsyncGenerator<DecodedEvent, LLMChatResponse | void, unknown> {\r\n return yield* this.router.chatStream(messages, options);\r\n }\r\n\r\n // ========================================================================\r\n // Structured Output\r\n // ========================================================================\r\n\r\n /**\r\n * Generate structured output from the LLM with automatic failover.\r\n * Validates the response against the provided Zod schema.\r\n * Throws StructuredOutputError on validation failure.\r\n *\r\n * @template T The output type\r\n * @param config Schema configuration (JSON Schema + optional validator)\r\n * @param messages Chat messages to send\r\n * @param options Additional options (temperature, maxTokens, etc.)\r\n * @returns Promise resolving to validated structured output\r\n * @throws StructuredOutputError if JSON parsing fails or validation fails\r\n *\r\n * @example\r\n * ```typescript\r\n * import { fromZod } from 'universal-llm-client/zod';\r\n * const UserConfig = fromZod(z.object({\r\n * name: z.string(),\r\n * age: z.number(),\r\n * }));\r\n *\r\n * const user = await model.generateStructured(UserConfig, [\r\n * { role: 'user', content: 'Generate a user profile' },\r\n * ]);\r\n * // user.name: string, user.age: number\r\n * ```\r\n */\r\n async generateStructured<T>(\r\n config: SchemaConfig<T>,\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): Promise<T> {\r\n return this.router.generateStructured(config, messages, options);\r\n }\r\n\r\n /**\r\n * Try to generate structured output, returning a result object instead of throwing.\r\n * Same as generateStructured but returns { ok: true, value } on success\r\n * and { ok: false, error, rawOutput } on failure.\r\n *\r\n * @template T The output type\r\n * @param config Schema configuration (JSON Schema + optional validator)\r\n * @param messages Chat messages to send\r\n * @param options Additional options (temperature, maxTokens, etc.)\r\n * @returns StructuredOutputResult<T> - either success with value or failure with error\r\n *\r\n * @example\r\n * ```typescript\r\n * const result = await model.tryParseStructured(config, messages);\r\n *\r\n * if (result.ok) {\r\n * console.log('User:', result.value.name);\r\n * } else {\r\n * console.log('Error:', result.error.message);\r\n * console.log('Raw output:', result.rawOutput);\r\n * }\r\n * ```\r\n */\r\n async tryParseStructured<T>(\r\n config: SchemaConfig<T>,\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): Promise<StructuredOutputResult<T>> {\r\n return this.router.tryParseStructured(config, messages, options);\r\n }\r\n\r\n /**\r\n * Stream structured output with partial validated objects.\r\n *\r\n * Yields partial validated objects as JSON generates, then returns the\r\n * complete validated object on stream completion.\r\n *\r\n * For invalid partial JSON, no yield occurs (partial validation is best-effort).\r\n * On stream completion, if the final JSON fails validation, throws StructuredOutputError.\r\n *\r\n * @template T The output type\r\n * @param config Schema configuration (JSON Schema + optional validator)\r\n * @param messages Chat messages to send\r\n * @param options Additional options (temperature, maxTokens, etc.)\r\n * @yields Partial validated objects as the JSON stream progresses\r\n * @returns Complete validated object on stream completion\r\n * @throws StructuredOutputError if final validation fails\r\n *\r\n * @example\r\n * ```typescript\r\n * import { fromZod } from 'universal-llm-client/zod';\r\n * const UserConfig = fromZod(z.object({\r\n * name: z.string(),\r\n * age: z.number(),\r\n * }));\r\n *\r\n * const stream = model.generateStructuredStream(UserConfig, [\r\n * { role: 'user', content: 'Generate a user' },\r\n * ]);\r\n *\r\n * for await (const partial of stream) {\r\n * console.log('Partial user:', partial);\r\n * }\r\n * ```\r\n */\r\n async *generateStructuredStream<T>(\r\n config: SchemaConfig<T>,\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): AsyncGenerator<T, T, unknown> {\r\n return yield* this.router.generateStructuredStream(config, messages, options);\r\n }\r\n\r\n // ========================================================================\r\n // Embeddings\r\n // ========================================================================\r\n\r\n /** Generate embedding for a single text */\r\n async embed(text: string): Promise<number[]> {\r\n return this.router.embed(text);\r\n }\r\n\r\n /** Generate embeddings for multiple texts */\r\n async embedArray(texts: string[]): Promise<number[][]> {\r\n return this.router.embedArray(texts);\r\n }\r\n\r\n // ========================================================================\r\n // Tool Registration\r\n // ========================================================================\r\n\r\n /** Register a tool callable by the LLM (broadcast to all providers) */\r\n registerTool(\r\n name: string,\r\n description: string,\r\n parameters: LLMFunction['parameters'],\r\n handler: ToolHandler,\r\n ): void {\r\n this.router.registerTool(name, description, parameters, handler);\r\n }\r\n\r\n /** Register multiple tools at once */\r\n registerTools(\r\n tools: Array<{\r\n name: string;\r\n description: string;\r\n parameters: LLMFunction['parameters'];\r\n handler: ToolHandler;\r\n }>,\r\n ): void {\r\n this.router.registerTools(tools);\r\n }\r\n\r\n // ========================================================================\r\n // Model Management\r\n // ========================================================================\r\n\r\n /** Get available models from all configured providers */\r\n async getModels(): Promise<string[]> {\r\n return this.router.getModels();\r\n }\r\n\r\n /** Get metadata about the current model (context length, capabilities) */\r\n async getModelInfo(): Promise<ModelMetadata> {\r\n return this.router.getModelInfo();\r\n }\r\n\r\n /** Switch model at runtime (updates all providers) */\r\n setModel(name: string): void {\r\n this.config.model = name;\r\n // The model name change will be picked up by the providers\r\n // through the router on next request\r\n }\r\n\r\n /** Get the current model name */\r\n get model(): string {\r\n return this.config.model;\r\n }\r\n\r\n // ========================================================================\r\n // Provider Status\r\n // ========================================================================\r\n\r\n /** Get health/status of all configured providers */\r\n getProviderStatus(): ProviderStatus[] {\r\n return this.router.getStatus();\r\n }\r\n\r\n // ========================================================================\r\n // Lifecycle\r\n // ========================================================================\r\n\r\n /** Clean shutdown — flush auditor, disconnect MCP, etc. */\r\n async dispose(): Promise<void> {\r\n await this.auditor.flush?.();\r\n }\r\n\r\n // ========================================================================\r\n // Internal: Provider Factory\r\n // ========================================================================\r\n\r\n private createClient(providerConfig: ProviderConfig): BaseLLMClient {\r\n const type = this.normalizeType(providerConfig.type);\r\n const modelName = providerConfig.model ?? this.config.model;\r\n\r\n const clientOptions: LLMClientOptions = {\r\n model: modelName,\r\n url: providerConfig.url ?? DEFAULT_URLS[type] ?? '',\r\n apiType: type as AIModelApiType,\r\n apiKey: providerConfig.apiKey,\r\n timeout: this.config.timeout ?? 30000,\r\n retries: this.config.retries ?? 2,\r\n debug: this.config.debug ?? false,\r\n defaultParameters: this.config.defaultParameters,\r\n thinking: this.config.thinking ?? false,\r\n region: providerConfig.region,\r\n apiVersion: providerConfig.apiVersion,\r\n };\r\n\r\n switch (type) {\r\n case 'ollama':\r\n return new OllamaClient(clientOptions, this.auditor);\r\n\r\n case 'openai':\r\n case 'llamacpp':\r\n return new OpenAICompatibleClient(clientOptions, this.auditor);\r\n\r\n case 'google':\r\n case 'vertex':\r\n return new GoogleClient(clientOptions, this.auditor);\r\n\r\n case 'anthropic':\r\n return new AnthropicClient(clientOptions, this.auditor);\r\n\r\n default:\r\n throw new Error(`Unknown provider type: ${type}`);\r\n }\r\n }\r\n\r\n private normalizeType(type: string): string {\r\n return type.toLowerCase();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"ai-model.js","sourceRoot":"","sources":["../src/ai-model.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"auditor.js","sourceRoot":"","sources":["../src/auditor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Universal LLM Client v3 — Auditor (Observability)\r\n *\r\n * Every LLM interaction (request, response, tool call, retry, failover)\r\n * is recorded through the Auditor interface. Frameworks inject their own\r\n * Auditor for dashboards, cost tracking, or behavioral scoring.\r\n */\r\n\r\nimport type { TokenUsageInfo, ToolExecutionResult } from './interfaces.js';\r\n\r\n// ============================================================================\r\n// Audit Event\r\n// ============================================================================\r\n\r\nexport type AuditEventType =\r\n | 'request'\r\n | 'response'\r\n | 'stream_start'\r\n | 'stream_end'\r\n | 'tool_call'\r\n | 'tool_result'\r\n | 'error'\r\n | 'retry'\r\n | 'failover'\r\n | 'structured_request'\r\n | 'structured_response'\r\n | 'structured_validation_error';\r\n\r\nexport interface AuditEvent {\r\n /** Unix timestamp in ms */\r\n timestamp: number;\r\n /** Event type */\r\n type: AuditEventType;\r\n /** Provider that generated this event */\r\n provider?: string;\r\n /** Model name */\r\n model?: string;\r\n /** Duration in ms (for request/response pairs) */\r\n duration?: number;\r\n /** Token usage (for response events) */\r\n usage?: TokenUsageInfo;\r\n /** Tool execution details (for tool_call/tool_result events) */\r\n toolExecution?: ToolExecutionResult;\r\n /** Error message (for error/retry events) */\r\n error?: string;\r\n /** Arbitrary metadata for framework-specific data */\r\n metadata?: Record<string, unknown>;\r\n /** Schema name for structured output events */\r\n schemaName?: string;\r\n /** Raw output snippet for validation errors */\r\n rawOutput?: string;\r\n}\r\n\r\n// ============================================================================\r\n// Auditor Interface\r\n// ============================================================================\r\n\r\n/**\r\n * Interface for LLM observability.\r\n *\r\n * Implement this to capture all LLM lifecycle events.\r\n * The library calls `record()` at every interaction point.\r\n */\r\nexport interface Auditor {\r\n /** Record an audit event */\r\n record(event: AuditEvent): void;\r\n /** Flush any buffered events (optional) */\r\n flush?(): Promise<void>;\r\n}\r\n\r\n// ============================================================================\r\n// Built-in Auditors\r\n// ============================================================================\r\n\r\n/**\r\n * Zero-overhead auditor that discards all events.\r\n * Used as the default when no auditor is configured.\r\n */\r\nexport class NoopAuditor implements Auditor {\r\n record(_event: AuditEvent): void {\r\n // Intentionally empty\r\n }\r\n}\r\n\r\n/**\r\n * Structured console logging auditor.\r\n * Useful for development and debugging.\r\n */\r\nexport class ConsoleAuditor implements Auditor {\r\n private prefix: string;\r\n\r\n constructor(prefix: string = '[LLM]') {\r\n this.prefix = prefix;\r\n }\r\n\r\n record(event: AuditEvent): void {\r\n const parts = [\r\n this.prefix,\r\n event.type.toUpperCase(),\r\n event.provider ? `[${event.provider}]` : '',\r\n event.model ? `(${event.model})` : '',\r\n ].filter(Boolean);\r\n\r\n switch (event.type) {\r\n case 'request':\r\n console.log(parts.join(' '), '→');\r\n break;\r\n case 'response':\r\n console.log(\r\n parts.join(' '),\r\n event.duration ? `${event.duration}ms` : '',\r\n event.usage ? `${event.usage.totalTokens} tokens` : '',\r\n );\r\n break;\r\n case 'stream_start':\r\n console.log(parts.join(' '), 'streaming...');\r\n break;\r\n case 'stream_end':\r\n console.log(\r\n parts.join(' '),\r\n 'done',\r\n event.duration ? `${event.duration}ms` : '',\r\n );\r\n break;\r\n case 'tool_call':\r\n console.log(parts.join(' '), event.toolExecution?.tool_call_id ?? '');\r\n break;\r\n case 'tool_result':\r\n console.log(\r\n parts.join(' '),\r\n event.toolExecution?.error ? '❌' : '✅',\r\n event.toolExecution?.duration ? `${event.toolExecution.duration}ms` : '',\r\n );\r\n break;\r\n case 'error':\r\n console.error(parts.join(' '), event.error ?? 'Unknown error');\r\n break;\r\n case 'retry':\r\n console.warn(parts.join(' '), event.error ?? '', event.metadata ?? '');\r\n break;\r\n case 'failover':\r\n console.warn(parts.join(' '), '→', event.metadata?.['nextProvider'] ?? '');\r\n break;\r\n case 'structured_request':\r\n console.log(\r\n parts.join(' '),\r\n `schema=${event.schemaName ?? 'unknown'}`,\r\n '→',\r\n );\r\n break;\r\n case 'structured_response':\r\n console.log(\r\n parts.join(' '),\r\n event.duration ? `${event.duration}ms` : '',\r\n `schema=${event.schemaName ?? 'unknown'}`,\r\n );\r\n break;\r\n case 'structured_validation_error':\r\n console.error(\r\n parts.join(' '),\r\n `schema=${event.schemaName ?? 'unknown'}`,\r\n event.error ?? 'Validation failed',\r\n event.rawOutput ? `raw=${event.rawOutput.slice(0, 50)}...` : '',\r\n );\r\n break;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Buffered auditor that collects events for batch processing.\r\n * Useful for custom sinks (OpenTelemetry, DataDog, databases, etc.)\r\n */\r\nexport class BufferedAuditor implements Auditor {\r\n private events: AuditEvent[] = [];\r\n private maxBufferSize: number;\r\n private onFlush?: (events: AuditEvent[]) => Promise<void>;\r\n\r\n constructor(options: {\r\n maxBufferSize?: number;\r\n onFlush?: (events: AuditEvent[]) => Promise<void>;\r\n } = {}) {\r\n this.maxBufferSize = options.maxBufferSize ?? 1000;\r\n this.onFlush = options.onFlush;\r\n }\r\n\r\n record(event: AuditEvent): void {\r\n this.events.push(event);\r\n if (this.events.length >= this.maxBufferSize) {\r\n // Auto-flush when buffer is full (fire and forget)\r\n this.flush().catch(() => {});\r\n }\r\n }\r\n\r\n /** Get all buffered events */\r\n getEvents(): ReadonlyArray<AuditEvent> {\r\n return this.events;\r\n }\r\n\r\n /** Flush buffered events to the configured sink */\r\n async flush(): Promise<void> {\r\n if (this.events.length === 0) return;\r\n const batch = this.events.splice(0);\r\n if (this.onFlush) {\r\n await this.onFlush(batch);\r\n }\r\n }\r\n\r\n /** Clear all buffered events without flushing */\r\n clear(): void {\r\n this.events.length = 0;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"auditor.js","sourceRoot":"","sources":["../src/auditor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Universal LLM Client v3 — Base LLM Client\r\n *\r\n * Abstract base class for all LLM providers.\r\n * Handles tool registration, execution, and the autonomous\r\n * multi-turn tool execution loop.\r\n */\r\n\r\nimport type {\r\n LLMClientOptions,\r\n LLMChatMessage,\r\n LLMChatResponse,\r\n LLMToolDefinition,\r\n LLMToolCall,\r\n LLMFunction,\r\n ToolRegistry,\r\n ToolHandler,\r\n ToolExecutionResult,\r\n ChatOptions,\r\n ModelMetadata,\r\n} from './interfaces.js';\r\nimport {\r\n StructuredOutputError,\r\n type StructuredOutputOptions,\r\n type SchemaConfig,\r\n} from './structured-output.js';\r\nimport type { DecodedEvent } from './stream-decoder.js';\r\nimport type { Auditor } from './auditor.js';\r\nimport { NoopAuditor } from './auditor.js';\r\n\r\n// ============================================================================\r\n// Abstract Base Client\r\n// ============================================================================\r\n\r\nexport abstract class BaseLLMClient {\r\n protected options: LLMClientOptions;\r\n protected toolRegistry: ToolRegistry = {};\r\n protected auditor: Auditor;\r\n protected debug: boolean;\r\n\r\n constructor(options: LLMClientOptions, auditor?: Auditor) {\r\n this.options = options;\r\n this.auditor = auditor ?? new NoopAuditor();\r\n this.debug = options.debug ?? false;\r\n }\r\n\r\n // ========================================================================\r\n // Abstract Methods (implemented by providers)\r\n // ========================================================================\r\n\r\n /** Send a chat request and get a response */\r\n abstract chat(\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): Promise<LLMChatResponse>;\r\n\r\n /** Stream a chat response as decoded events */\r\n abstract chatStream(\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions,\r\n ): AsyncGenerator<DecodedEvent, LLMChatResponse | void, unknown>;\r\n\r\n /** Get available models */\r\n abstract getModels(): Promise<string[]>;\r\n\r\n /** Generate embeddings for text */\r\n abstract embed(text: string): Promise<number[]>;\r\n\r\n /** Generate embeddings for multiple texts */\r\n async embedArray(texts: string[]): Promise<number[][]> {\r\n return Promise.all(texts.map(t => this.embed(t)));\r\n }\r\n\r\n /**\r\n * Get metadata about a model (context length, architecture, etc.)\r\n * Override per-provider for accurate data.\r\n */\r\n async getModelInfo(_modelName?: string): Promise<ModelMetadata> {\r\n return { contextLength: 8192 }; // Conservative default\r\n }\r\n\r\n // ========================================================================\r\n // Tool Registration\r\n // ========================================================================\r\n\r\n /**\r\n * Sanitize tool name for LLM compatibility.\r\n * LLM APIs require function names matching [a-zA-Z0-9_-].\r\n * Module-prefixed names like \"@core/computer:list_windows\" are cleaned.\r\n */\r\n private sanitizeToolName(name: string): string {\r\n return name\r\n .replace(/^@[^:]+:/, '') // Strip module prefix\r\n .replace(/[^a-zA-Z0-9_-]/g, '_') // Replace illegal chars\r\n .replace(/_+/g, '_') // Collapse\r\n .replace(/^_|_$/g, ''); // Trim\r\n }\r\n\r\n /** Register a tool/function callable by the model */\r\n registerTool(\r\n name: string,\r\n description: string,\r\n parameters: LLMFunction['parameters'],\r\n handler: ToolHandler,\r\n ): void {\r\n const safeName = this.sanitizeToolName(name);\r\n this.toolRegistry[name] = {\r\n definition: { name: safeName, description, parameters },\r\n handler,\r\n };\r\n // Index by sanitized name for reverse lookup\r\n if (safeName !== name && !this.toolRegistry[safeName]) {\r\n this.toolRegistry[safeName] = this.toolRegistry[name]!;\r\n }\r\n this.debugLog(`Registered tool: ${name} (LLM name: ${safeName})`);\r\n }\r\n\r\n /** Register multiple tools at once */\r\n registerTools(\r\n tools: Array<{\r\n name: string;\r\n description: string;\r\n parameters: LLMFunction['parameters'];\r\n handler: ToolHandler;\r\n }>,\r\n ): void {\r\n for (const tool of tools) {\r\n this.registerTool(tool.name, tool.description, tool.parameters, tool.handler);\r\n }\r\n }\r\n\r\n /** Get all registered tool definitions (deduplicated by sanitized name) */\r\n getToolDefinitions(): LLMToolDefinition[] {\r\n const seen = new Set<string>();\r\n const defs: LLMToolDefinition[] = [];\r\n for (const { definition } of Object.values(this.toolRegistry)) {\r\n if (seen.has(definition.name)) continue;\r\n seen.add(definition.name);\r\n defs.push({ type: 'function' as const, function: definition });\r\n }\r\n return defs;\r\n }\r\n\r\n // ========================================================================\r\n // Tool Execution\r\n // ========================================================================\r\n\r\n /** Execute a single tool call with fuzzy name matching */\r\n async executeTool(toolCall: LLMToolCall): Promise<ToolExecutionResult> {\r\n const toolName = toolCall.function.name;\r\n const start = Date.now();\r\n let tool = this.toolRegistry[toolName];\r\n\r\n // Fuzzy lookup: try suffix match (LLM stripped module prefix)\r\n if (!tool) {\r\n const entries = Object.entries(this.toolRegistry);\r\n const bySuffix = entries.find(([k]) => k.endsWith(`:${toolName}`));\r\n if (bySuffix) {\r\n tool = bySuffix[1];\r\n this.debugLog(`Fuzzy tool match: \"${toolName}\" → \"${bySuffix[0]}\"`);\r\n }\r\n\r\n // Try prefix match: if only one tool in that module, use it\r\n if (!tool) {\r\n const byPrefix = entries.filter(([k]) => k.startsWith(`${toolName}:`));\r\n if (byPrefix.length === 1) {\r\n tool = byPrefix[0]![1];\r\n this.debugLog(`Fuzzy tool match (single): \"${toolName}\" → \"${byPrefix[0]![0]}\"`);\r\n }\r\n }\r\n }\r\n\r\n if (!tool) {\r\n const result: ToolExecutionResult = {\r\n tool_call_id: toolCall.id,\r\n output: null,\r\n error: `Unknown tool: ${toolName}`,\r\n duration: Date.now() - start,\r\n };\r\n this.auditor.record({\r\n timestamp: Date.now(),\r\n type: 'tool_result',\r\n toolExecution: result,\r\n error: result.error,\r\n });\r\n return result;\r\n }\r\n\r\n this.auditor.record({\r\n timestamp: Date.now(),\r\n type: 'tool_call',\r\n metadata: { toolName, arguments: toolCall.function.arguments },\r\n });\r\n\r\n try {\r\n const args = JSON.parse(toolCall.function.arguments);\r\n const output = await tool.handler(args);\r\n const result: ToolExecutionResult = {\r\n tool_call_id: toolCall.id,\r\n output,\r\n duration: Date.now() - start,\r\n };\r\n this.auditor.record({\r\n timestamp: Date.now(),\r\n type: 'tool_result',\r\n toolExecution: result,\r\n });\r\n return result;\r\n } catch (error) {\r\n const result: ToolExecutionResult = {\r\n tool_call_id: toolCall.id,\r\n output: null,\r\n error: error instanceof Error ? error.message : String(error),\r\n duration: Date.now() - start,\r\n };\r\n this.auditor.record({\r\n timestamp: Date.now(),\r\n type: 'tool_result',\r\n toolExecution: result,\r\n error: result.error,\r\n });\r\n return result;\r\n }\r\n }\r\n\r\n /** Execute multiple tool calls in parallel */\r\n async executeTools(toolCalls: LLMToolCall[]): Promise<ToolExecutionResult[]> {\r\n return Promise.all(toolCalls.map(tc => this.executeTool(tc)));\r\n }\r\n\r\n // ========================================================================\r\n // Chat with Tools (multi-turn autonomous loop)\r\n // ========================================================================\r\n\r\n /**\r\n * Chat with automatic tool execution.\r\n * Continues until the model stops calling tools or max iterations reached.\r\n * Returns the complete execution trace in `toolExecutions`.\r\n */\r\n async chatWithTools(\r\n messages: LLMChatMessage[],\r\n options?: ChatOptions & { maxIterations?: number },\r\n ): Promise<LLMChatResponse> {\r\n const maxIterations = options?.maxIterations ?? 10;\r\n const conversationMessages = [...messages];\r\n const allToolExecutions: ToolExecutionResult[] = [];\r\n let iterations = 0;\r\n\r\n while (iterations < maxIterations) {\r\n const response = await this.chat(conversationMessages, {\r\n ...options,\r\n tools: this.getToolDefinitions(),\r\n });\r\n\r\n // If no tool calls, return with full trace\r\n if (!response.message.tool_calls?.length) {\r\n return {\r\n ...response,\r\n toolExecutions: allToolExecutions.length > 0 ? allToolExecutions : undefined,\r\n };\r\n }\r\n\r\n // Add assistant message with tool calls\r\n conversationMessages.push(response.message);\r\n\r\n // Execute tools in parallel\r\n const toolResults = await this.executeTools(response.message.tool_calls);\r\n allToolExecutions.push(...toolResults);\r\n\r\n // Add tool results as messages\r\n for (const result of toolResults) {\r\n conversationMessages.push({\r\n role: 'tool',\r\n content: typeof result.output === 'string'\r\n ? result.output\r\n : JSON.stringify(result.output),\r\n tool_call_id: result.tool_call_id,\r\n });\r\n }\r\n\r\n iterations++;\r\n }\r\n\r\n // Max iterations — final call without tools\r\n const finalResponse = await this.chat(conversationMessages);\r\n return {\r\n ...finalResponse,\r\n toolExecutions: allToolExecutions,\r\n };\r\n }\r\n\r\n // ========================================================================\r\n // Helpers\r\n // ========================================================================\r\n\r\n /** Set the model name at runtime */\r\n setModel(modelName: string): void {\r\n this.options.model = modelName;\r\n this.debugLog(`Model switched to: ${modelName}`);\r\n }\r\n\r\n /** Get the current model name */\r\n get model(): string {\r\n return this.options.model;\r\n }\r\n\r\n /** Get the base URL */\r\n get url(): string {\r\n return this.options.url;\r\n }\r\n\r\n /** Set the auditor instance */\r\n setAuditor(auditor: Auditor): void {\r\n this.auditor = auditor;\r\n }\r\n\r\n protected debugLog(message: string, data?: unknown): void {\r\n if (this.debug) {\r\n console.log(`[LLM:${this.options.model}] ${message}`, data ?? '');\r\n }\r\n }\r\n\r\n /**\r\n * Generate a unique ID for tool calls when the provider doesn't provide one.\r\n */\r\n protected generateToolCallId(): string {\r\n return `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\r\n }\r\n\r\n // ========================================================================\r\n // Structured Output Helpers (shared across all providers)\r\n // ========================================================================\r\n\r\n /**\r\n * Extract schema options from ChatOptions.\r\n * Returns null if no schema is provided.\r\n * Returns a SchemaConfig if a schema was found.\r\n */\r\n protected extractSchemaOptions(options?: ChatOptions): (StructuredOutputOptions<unknown> & { schemaConfig: SchemaConfig<unknown> }) | null {\r\n if (!options) return null;\r\n\r\n if (options.schema) {\r\n return {\r\n schemaConfig: options.schema,\r\n name: options.schemaName,\r\n description: options.schemaDescription,\r\n };\r\n }\r\n\r\n if (options.jsonSchema) {\r\n // Raw JSON Schema without validation\r\n const config: SchemaConfig<unknown> = {\r\n jsonSchema: options.jsonSchema,\r\n };\r\n return {\r\n schemaConfig: config,\r\n name: options.schemaName,\r\n description: options.schemaDescription,\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Validate structured response using a SchemaConfig.\r\n * Throws StructuredOutputError on failure.\r\n */\r\n protected validateStructuredResponse(content: string, config: SchemaConfig<unknown>): void {\r\n if (!content) {\r\n throw new StructuredOutputError(\r\n 'Empty response from LLM',\r\n { rawOutput: content },\r\n );\r\n }\r\n\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(content);\r\n } catch (error) {\r\n const syntaxError = error instanceof SyntaxError\r\n ? error\r\n : new SyntaxError(String(error));\r\n throw new StructuredOutputError(\r\n `Failed to parse JSON: ${syntaxError.message}`,\r\n { rawOutput: content, cause: syntaxError },\r\n );\r\n }\r\n\r\n if (config.validate) {\r\n try {\r\n config.validate(parsed);\r\n } catch (error) {\r\n const validationError = error instanceof Error ? error : new Error(String(error));\r\n throw new StructuredOutputError(\r\n `Validation failed: ${validationError.message}`,\r\n { rawOutput: content, cause: validationError },\r\n );\r\n }\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Gemma 4 can emit its thought channel as text control tokens instead of the
3
+ * generic Ollama `message.thinking` field. Keep that provider quirk isolated so
4
+ * callers receive final-answer text and reasoning separately.
5
+ */
6
+ export interface GemmaThoughtExtraction {
7
+ readonly content: string;
8
+ readonly reasoning: string;
9
+ readonly found: boolean;
10
+ }
11
+ export declare const GEMMA_THOUGHT_OPENERS: readonly ["<|channel>thought", "<|thought"];
12
+ export declare function extractGemmaThoughtChannels(input: string): GemmaThoughtExtraction;
13
+ export declare function normalizeGemmaThought(thought: string): string;
14
+ //# sourceMappingURL=gemma-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemma-channel.d.ts","sourceRoot":"","sources":["../src/gemma-channel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,sBAAsB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CAC3B;AAKD,eAAO,MAAM,qBAAqB,6CAA8C,CAAC;AAEjF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,sBAAsB,CAyBjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Gemma 4 can emit its thought channel as text control tokens instead of the
3
+ * generic Ollama `message.thinking` field. Keep that provider quirk isolated so
4
+ * callers receive final-answer text and reasoning separately.
5
+ */
6
+ const GEMMA_THOUGHT_BLOCK = /<\|channel>\s*thought\s*\r?\n?([\s\S]*?)<channel\|>/gi;
7
+ const GEMMA_COMPACT_THOUGHT_BLOCK = /<\|thought\s*\r?\n?([\s\S]*?)\|>/gi;
8
+ export const GEMMA_THOUGHT_OPENERS = ['<|channel>thought', '<|thought'];
9
+ export function extractGemmaThoughtChannels(input) {
10
+ if (!input)
11
+ return { content: input, reasoning: '', found: false };
12
+ const reasoningParts = [];
13
+ let found = false;
14
+ const content = input
15
+ .replace(GEMMA_THOUGHT_BLOCK, (_match, thought) => {
16
+ found = true;
17
+ const normalized = normalizeGemmaThought(thought);
18
+ if (normalized)
19
+ reasoningParts.push(normalized);
20
+ return '';
21
+ })
22
+ .replace(GEMMA_COMPACT_THOUGHT_BLOCK, (_match, thought) => {
23
+ found = true;
24
+ const normalized = normalizeGemmaThought(thought);
25
+ if (normalized)
26
+ reasoningParts.push(normalized);
27
+ return '';
28
+ });
29
+ return {
30
+ content,
31
+ reasoning: reasoningParts.join('\n\n'),
32
+ found,
33
+ };
34
+ }
35
+ export function normalizeGemmaThought(thought) {
36
+ return thought.replace(/^\s+/, '').replace(/\s+$/, '');
37
+ }
38
+ //# sourceMappingURL=gemma-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemma-channel.js","sourceRoot":"","sources":["../src/gemma-channel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,mBAAmB,GAAG,uDAAuD,CAAC;AACpF,MAAM,2BAA2B,GAAG,oCAAoC,CAAC;AAEzE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,mBAAmB,EAAE,WAAW,CAAU,CAAC;AAEjF,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACrD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAEnE,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,MAAM,OAAO,GAAG,KAAK;SAChB,OAAO,CAAC,mBAAmB,EAAE,CAAC,MAAM,EAAE,OAAe,EAAE,EAAE;QACtD,KAAK,GAAG,IAAI,CAAC;QACb,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,UAAU;YAAE,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC;IACd,CAAC,CAAC;SACD,OAAO,CAAC,2BAA2B,EAAE,CAAC,MAAM,EAAE,OAAe,EAAE,EAAE;QAC9D,KAAK,GAAG,IAAI,CAAC;QACb,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,UAAU;YAAE,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEP,OAAO;QACH,OAAO;QACP,SAAS,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QACtC,KAAK;KACR,CAAC;AACN,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACjD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * DiffusionGemma (vLLM) native-protocol adapter.
3
+ *
4
+ * Trimmed vLLM builds that serve DiffusionGemma ship with NO reasoning parser
5
+ * and NO tool-call parser module, and they reject OpenAI-style `tools` unless
6
+ * `--tool-call-parser` is configured. Everything therefore has to be handled
7
+ * client-side, against the model's native channel format (visible only when
8
+ * the request sets `skip_special_tokens: false`):
9
+ *
10
+ * <|channel>thought ...reasoning... <channel|> reasoning channel
11
+ * <|tool_call>call:name{k:<|"|>v<|"|>,n:3}<tool_call|> tool call
12
+ *
13
+ * Tool-call arguments are NOT JSON: keys are bare, strings are wrapped in the
14
+ * <|"|> quote token, numbers/booleans are bare (see the model's
15
+ * chat_template.jinja `format_argument` macro). `gemmaArgsToJson` converts
16
+ * that into a standard JSON string.
17
+ *
18
+ * Request-side protocol (implemented in the OpenAI provider):
19
+ * - always send `skip_special_tokens: false`
20
+ * - send `tools` with `tool_choice: 'none'` — vLLM still renders the
21
+ * declarations into the chat template, it just skips its (absent) parser
22
+ * - send history tool turns structurally (assistant `tool_calls` +
23
+ * `role: 'tool'` messages) — the chat template renders them natively
24
+ */
25
+ export interface GemmaParsedToolCall {
26
+ readonly name: string;
27
+ /** JSON-encoded arguments object, ready for LLMToolCall.function.arguments */
28
+ readonly argumentsJson: string;
29
+ }
30
+ export interface GemmaDiffusionParsed {
31
+ /** Final answer with reasoning, tool-call blocks and special tokens removed */
32
+ readonly content: string;
33
+ readonly reasoning: string;
34
+ readonly toolCalls: readonly GemmaParsedToolCall[];
35
+ }
36
+ /** Models that speak this native protocol when served by vLLM. */
37
+ export declare function isGemmaDiffusionModel(model: string): boolean;
38
+ /**
39
+ * Convert the Gemma template's pseudo-JSON argument syntax to a JSON string.
40
+ * Lenient by design: bare words that aren't numbers/booleans become strings,
41
+ * since the model occasionally omits the quote token.
42
+ */
43
+ export declare function gemmaArgsToJson(body: string): string;
44
+ /**
45
+ * Parse a complete raw DiffusionGemma output into reasoning, tool calls and
46
+ * clean answer text.
47
+ */
48
+ export declare function parseGemmaDiffusionOutput(raw: string): GemmaDiffusionParsed;
49
+ //# sourceMappingURL=gemma-diffusion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemma-diffusion.d.ts","sourceRoot":"","sources":["../src/gemma-diffusion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACtD;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE5D;AAaD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwEpD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CA2B3E"}