@nhtio/adk 0.1.0-master-f0aa531d
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/LICENSE.md +9 -0
- package/README.md +3 -0
- package/batteries/index.d.ts +28 -0
- package/batteries/llm/index.d.ts +11 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +916 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/adapter.d.ts +101 -0
- package/batteries/llm/openai_chat_completions/adapter.mjs +914 -0
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/exceptions.cjs +89 -0
- package/batteries/llm/openai_chat_completions/exceptions.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/exceptions.d.ts +97 -0
- package/batteries/llm/openai_chat_completions/exceptions.mjs +81 -0
- package/batteries/llm/openai_chat_completions/exceptions.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs +819 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/helpers.d.ts +233 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs +783 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/index.d.ts +27 -0
- package/batteries/llm/openai_chat_completions/types.cjs +1 -0
- package/batteries/llm/openai_chat_completions/types.d.ts +524 -0
- package/batteries/llm/openai_chat_completions/types.mjs +0 -0
- package/batteries/llm/openai_chat_completions/validation.cjs +190 -0
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/validation.d.ts +31 -0
- package/batteries/llm/openai_chat_completions/validation.mjs +187 -0
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions.cjs +51 -0
- package/batteries/llm/openai_chat_completions.mjs +5 -0
- package/batteries/llm/webllm_chat_completions/adapter.cjs +658 -0
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/adapter.d.ts +103 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs +656 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +70 -0
- package/batteries/llm/webllm_chat_completions/exceptions.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/exceptions.d.ts +74 -0
- package/batteries/llm/webllm_chat_completions/exceptions.mjs +65 -0
- package/batteries/llm/webllm_chat_completions/exceptions.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/helpers.cjs +38 -0
- package/batteries/llm/webllm_chat_completions/helpers.d.ts +6 -0
- package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -0
- package/batteries/llm/webllm_chat_completions/index.d.ts +25 -0
- package/batteries/llm/webllm_chat_completions/types.d.ts +31 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs +115 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/validation.d.ts +8 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs +112 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions.cjs +50 -0
- package/batteries/llm/webllm_chat_completions.mjs +6 -0
- package/batteries/llm.cjs +63 -0
- package/batteries/llm.mjs +10 -0
- package/batteries/storage/flydrive/index.d.ts +167 -0
- package/batteries/storage/flydrive.cjs +249 -0
- package/batteries/storage/flydrive.cjs.map +1 -0
- package/batteries/storage/flydrive.mjs +249 -0
- package/batteries/storage/flydrive.mjs.map +1 -0
- package/batteries/storage/in_memory/index.d.ts +106 -0
- package/batteries/storage/in_memory.cjs +121 -0
- package/batteries/storage/in_memory.cjs.map +1 -0
- package/batteries/storage/in_memory.mjs +119 -0
- package/batteries/storage/in_memory.mjs.map +1 -0
- package/batteries/storage/index.d.ts +18 -0
- package/batteries/storage/opfs/index.d.ts +299 -0
- package/batteries/storage/opfs.cjs +368 -0
- package/batteries/storage/opfs.cjs.map +1 -0
- package/batteries/storage/opfs.mjs +366 -0
- package/batteries/storage/opfs.mjs.map +1 -0
- package/batteries/storage.cjs +4 -0
- package/batteries/storage.mjs +2 -0
- package/batteries/tools/color/index.d.ts +37 -0
- package/batteries/tools/color.cjs +659 -0
- package/batteries/tools/color.cjs.map +1 -0
- package/batteries/tools/color.mjs +655 -0
- package/batteries/tools/color.mjs.map +1 -0
- package/batteries/tools/comparison/index.d.ts +29 -0
- package/batteries/tools/comparison.cjs +171 -0
- package/batteries/tools/comparison.cjs.map +1 -0
- package/batteries/tools/comparison.mjs +168 -0
- package/batteries/tools/comparison.mjs.map +1 -0
- package/batteries/tools/data_structure/index.d.ts +30 -0
- package/batteries/tools/data_structure.cjs +270 -0
- package/batteries/tools/data_structure.cjs.map +1 -0
- package/batteries/tools/data_structure.mjs +267 -0
- package/batteries/tools/data_structure.mjs.map +1 -0
- package/batteries/tools/datetime_extended/index.d.ts +51 -0
- package/batteries/tools/datetime_extended.cjs +309 -0
- package/batteries/tools/datetime_extended.cjs.map +1 -0
- package/batteries/tools/datetime_extended.mjs +302 -0
- package/batteries/tools/datetime_extended.mjs.map +1 -0
- package/batteries/tools/datetime_math/index.d.ts +36 -0
- package/batteries/tools/datetime_math.cjs +175 -0
- package/batteries/tools/datetime_math.cjs.map +1 -0
- package/batteries/tools/datetime_math.mjs +171 -0
- package/batteries/tools/datetime_math.mjs.map +1 -0
- package/batteries/tools/encoding/index.d.ts +36 -0
- package/batteries/tools/encoding.cjs +156 -0
- package/batteries/tools/encoding.cjs.map +1 -0
- package/batteries/tools/encoding.mjs +152 -0
- package/batteries/tools/encoding.mjs.map +1 -0
- package/batteries/tools/formatting/index.d.ts +28 -0
- package/batteries/tools/formatting.cjs +120 -0
- package/batteries/tools/formatting.cjs.map +1 -0
- package/batteries/tools/formatting.mjs +117 -0
- package/batteries/tools/formatting.mjs.map +1 -0
- package/batteries/tools/geo_basics/index.d.ts +33 -0
- package/batteries/tools/geo_basics.cjs +136 -0
- package/batteries/tools/geo_basics.cjs.map +1 -0
- package/batteries/tools/geo_basics.mjs +132 -0
- package/batteries/tools/geo_basics.mjs.map +1 -0
- package/batteries/tools/index.d.ts +32 -0
- package/batteries/tools/math/index.d.ts +37 -0
- package/batteries/tools/math.cjs +136 -0
- package/batteries/tools/math.cjs.map +1 -0
- package/batteries/tools/math.mjs +133 -0
- package/batteries/tools/math.mjs.map +1 -0
- package/batteries/tools/memory/index.d.ts +73 -0
- package/batteries/tools/memory.cjs +193 -0
- package/batteries/tools/memory.cjs.map +1 -0
- package/batteries/tools/memory.mjs +187 -0
- package/batteries/tools/memory.mjs.map +1 -0
- package/batteries/tools/parsing/index.d.ts +47 -0
- package/batteries/tools/parsing.cjs +191 -0
- package/batteries/tools/parsing.cjs.map +1 -0
- package/batteries/tools/parsing.mjs +185 -0
- package/batteries/tools/parsing.mjs.map +1 -0
- package/batteries/tools/retrievables/index.d.ts +81 -0
- package/batteries/tools/retrievables.cjs +215 -0
- package/batteries/tools/retrievables.cjs.map +1 -0
- package/batteries/tools/retrievables.mjs +209 -0
- package/batteries/tools/retrievables.mjs.map +1 -0
- package/batteries/tools/standing_instructions/index.d.ts +64 -0
- package/batteries/tools/standing_instructions.cjs +126 -0
- package/batteries/tools/standing_instructions.cjs.map +1 -0
- package/batteries/tools/standing_instructions.mjs +121 -0
- package/batteries/tools/standing_instructions.mjs.map +1 -0
- package/batteries/tools/statistics/index.d.ts +46 -0
- package/batteries/tools/statistics.cjs +253 -0
- package/batteries/tools/statistics.cjs.map +1 -0
- package/batteries/tools/statistics.mjs +248 -0
- package/batteries/tools/statistics.mjs.map +1 -0
- package/batteries/tools/string_processing/index.d.ts +29 -0
- package/batteries/tools/string_processing.cjs +154 -0
- package/batteries/tools/string_processing.cjs.map +1 -0
- package/batteries/tools/string_processing.mjs +151 -0
- package/batteries/tools/string_processing.mjs.map +1 -0
- package/batteries/tools/structured_data/index.d.ts +34 -0
- package/batteries/tools/structured_data.cjs +189 -0
- package/batteries/tools/structured_data.cjs.map +1 -0
- package/batteries/tools/structured_data.mjs +185 -0
- package/batteries/tools/structured_data.mjs.map +1 -0
- package/batteries/tools/text_analysis/index.d.ts +31 -0
- package/batteries/tools/text_analysis.cjs +120 -0
- package/batteries/tools/text_analysis.cjs.map +1 -0
- package/batteries/tools/text_analysis.mjs +117 -0
- package/batteries/tools/text_analysis.mjs.map +1 -0
- package/batteries/tools/text_comparison/index.d.ts +28 -0
- package/batteries/tools/text_comparison.cjs +96 -0
- package/batteries/tools/text_comparison.cjs.map +1 -0
- package/batteries/tools/text_comparison.mjs +93 -0
- package/batteries/tools/text_comparison.mjs.map +1 -0
- package/batteries/tools/time/index.d.ts +27 -0
- package/batteries/tools/time.cjs +63 -0
- package/batteries/tools/time.cjs.map +1 -0
- package/batteries/tools/time.mjs +60 -0
- package/batteries/tools/time.mjs.map +1 -0
- package/batteries/tools/unit_conversion/index.d.ts +19 -0
- package/batteries/tools/unit_conversion.cjs +452 -0
- package/batteries/tools/unit_conversion.cjs.map +1 -0
- package/batteries/tools/unit_conversion.mjs +450 -0
- package/batteries/tools/unit_conversion.mjs.map +1 -0
- package/batteries/tools.cjs +80 -0
- package/batteries/tools.mjs +21 -0
- package/batteries.cjs +142 -0
- package/batteries.mjs +30 -0
- package/chunk-KmRHZBOW.js +35 -0
- package/common-DeZaonK1.mjs +208 -0
- package/common-DeZaonK1.mjs.map +1 -0
- package/common-Od8edUXU.js +232 -0
- package/common-Od8edUXU.js.map +1 -0
- package/common.cjs +31 -0
- package/common.d.ts +108 -0
- package/common.mjs +8 -0
- package/dispatch_runner-9j6bXHL3.mjs +1609 -0
- package/dispatch_runner-9j6bXHL3.mjs.map +1 -0
- package/dispatch_runner-CsoH0nld.js +1627 -0
- package/dispatch_runner-CsoH0nld.js.map +1 -0
- package/dispatch_runner.cjs +3 -0
- package/dispatch_runner.d.ts +17 -0
- package/dispatch_runner.mjs +2 -0
- package/exceptions-D5YrO9Vm.js +280 -0
- package/exceptions-D5YrO9Vm.js.map +1 -0
- package/exceptions-NrzIHw_R.mjs +244 -0
- package/exceptions-NrzIHw_R.mjs.map +1 -0
- package/exceptions.cjs +33 -0
- package/exceptions.d.ts +52 -0
- package/exceptions.mjs +3 -0
- package/factories.cjs +4 -0
- package/factories.d.ts +39 -0
- package/factories.mjs +2 -0
- package/forge.cjs +9 -0
- package/forge.d.ts +49 -0
- package/forge.mjs +5 -0
- package/guards.cjs +96 -0
- package/guards.cjs.map +1 -0
- package/guards.d.ts +83 -0
- package/guards.mjs +72 -0
- package/guards.mjs.map +1 -0
- package/index.cjs +107 -0
- package/index.cjs.map +1 -0
- package/index.d.ts +18 -0
- package/index.mjs +31 -0
- package/index.mjs.map +1 -0
- package/lib/classes/artifact_tool.d.ts +129 -0
- package/lib/classes/base_exception.d.ts +83 -0
- package/lib/classes/identity.d.ts +71 -0
- package/lib/classes/media.d.ts +326 -0
- package/lib/classes/memory.d.ts +72 -0
- package/lib/classes/message.d.ts +137 -0
- package/lib/classes/registry.d.ts +79 -0
- package/lib/classes/retrievable.d.ts +100 -0
- package/lib/classes/spooled_artifact.d.ts +296 -0
- package/lib/classes/spooled_json_artifact.d.ts +158 -0
- package/lib/classes/spooled_markdown_artifact.d.ts +202 -0
- package/lib/classes/thought.d.ts +142 -0
- package/lib/classes/tokenizable.d.ts +124 -0
- package/lib/classes/tool.d.ts +228 -0
- package/lib/classes/tool_call.d.ts +190 -0
- package/lib/classes/tool_registry.d.ts +159 -0
- package/lib/classes/turn_gate.d.ts +109 -0
- package/lib/contracts/dispatch_context.d.ts +345 -0
- package/lib/contracts/media_reader.d.ts +60 -0
- package/lib/contracts/spool_reader.d.ts +80 -0
- package/lib/contracts/spooled_artifact_constructor.d.ts +38 -0
- package/lib/contracts/turn_runner_config.d.ts +101 -0
- package/lib/contracts/turn_runner_context.d.ts +267 -0
- package/lib/dispatch_runner.d.ts +98 -0
- package/lib/exceptions/runtime.d.ts +370 -0
- package/lib/helpers/media_readers.d.ts +39 -0
- package/lib/turn_runner.d.ts +144 -0
- package/lib/types/dispatch_context.d.ts +233 -0
- package/lib/types/dispatch_runner.d.ts +387 -0
- package/lib/types/turn_runner.d.ts +322 -0
- package/lib/utils/canonical_json.d.ts +18 -0
- package/lib/utils/exceptions.d.ts +78 -0
- package/lib/utils/guards.d.ts +32 -0
- package/lib/utils/validation.d.ts +77 -0
- package/package.json +334 -0
- package/runtime-BJVkrGQe.js +519 -0
- package/runtime-BJVkrGQe.js.map +1 -0
- package/runtime-CrEPIFgr.mjs +346 -0
- package/runtime-CrEPIFgr.mjs.map +1 -0
- package/skills/adk-assembly/SKILL.md +109 -0
- package/skills/adk-assembly/references/assembly-contract.md +66 -0
- package/skills/adk-assembly/references/executors-tools-pipelines-events.md +113 -0
- package/skills/adk-assembly/references/first-integration.md +93 -0
- package/skills/adk-assembly/references/storage-and-context.md +102 -0
- package/spooled_artifact-C5ZtGxuJ.mjs +544 -0
- package/spooled_artifact-C5ZtGxuJ.mjs.map +1 -0
- package/spooled_artifact-Cm9Te22K.js +568 -0
- package/spooled_artifact-Cm9Te22K.js.map +1 -0
- package/spooled_artifact.cjs +7 -0
- package/spooled_artifact.d.ts +40 -0
- package/spooled_artifact.mjs +3 -0
- package/spooled_markdown_artifact-BpUJol0W.mjs +771 -0
- package/spooled_markdown_artifact-BpUJol0W.mjs.map +1 -0
- package/spooled_markdown_artifact-RRB113sy.js +786 -0
- package/spooled_markdown_artifact-RRB113sy.js.map +1 -0
- package/thought-CDb457b4.mjs +470 -0
- package/thought-CDb457b4.mjs.map +1 -0
- package/thought-DuN2PgdO.js +494 -0
- package/thought-DuN2PgdO.js.map +1 -0
- package/tool-COSeH8I6.js +302 -0
- package/tool-COSeH8I6.js.map +1 -0
- package/tool-D2WB1EA1.mjs +296 -0
- package/tool-D2WB1EA1.mjs.map +1 -0
- package/tool_call-BKyyxGaZ.mjs +578 -0
- package/tool_call-BKyyxGaZ.mjs.map +1 -0
- package/tool_call-DFgzcVcU.js +608 -0
- package/tool_call-DFgzcVcU.js.map +1 -0
- package/tool_registry-Dkfprsck.js +641 -0
- package/tool_registry-Dkfprsck.js.map +1 -0
- package/tool_registry-DqLOyGyG.mjs +592 -0
- package/tool_registry-DqLOyGyG.mjs.map +1 -0
- package/turn_runner-CMm2BHdX.js +615 -0
- package/turn_runner-CMm2BHdX.js.map +1 -0
- package/turn_runner-y7eyEcJH.mjs +603 -0
- package/turn_runner-y7eyEcJH.mjs.map +1 -0
- package/turn_runner.cjs +3 -0
- package/turn_runner.d.ts +21 -0
- package/turn_runner.mjs +2 -0
- package/types.cjs +1 -0
- package/types.d.ts +56 -0
- package/types.mjs +0 -0
- package/vite-env.d.ts +23 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../../chunk-KmRHZBOW.js");
|
|
3
|
+
const require_tool_registry = require("../../../tool_registry-Dkfprsck.js");
|
|
4
|
+
const require_thought = require("../../../thought-DuN2PgdO.js");
|
|
5
|
+
require("../../../common-Od8edUXU.js");
|
|
6
|
+
const require_tool_call = require("../../../tool_call-DFgzcVcU.js");
|
|
7
|
+
const require_spooled_artifact = require("../../../spooled_artifact-Cm9Te22K.js");
|
|
8
|
+
require("../../../guards.cjs");
|
|
9
|
+
const require_batteries_storage_in_memory = require("../../storage/in_memory.cjs");
|
|
10
|
+
const require_batteries_llm_openai_chat_completions_helpers = require("../openai_chat_completions/helpers.cjs");
|
|
11
|
+
const require_batteries_llm_webllm_chat_completions_exceptions = require("./exceptions.cjs");
|
|
12
|
+
const require_batteries_llm_webllm_chat_completions_validation = require("./validation.cjs");
|
|
13
|
+
require("./helpers.cjs");
|
|
14
|
+
let uuid = require("uuid");
|
|
15
|
+
let luxon = require("luxon");
|
|
16
|
+
let js_sha256 = require("js-sha256");
|
|
17
|
+
//#region src/batteries/llm/webllm_chat_completions/adapter.ts
|
|
18
|
+
/**
|
|
19
|
+
* Cross-environment executor adapter for WebLLM Chat Completions compatible endpoints.
|
|
20
|
+
*
|
|
21
|
+
* @module @nhtio/adk/batteries/llm/webllm_chat_completions/adapter
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* Cross-environment LLM adapter for the WebLLM Chat Completions wire shape. Chat Completions was
|
|
25
|
+
* chosen as the ADK's reference adapter because it is the de-facto interchange format for the
|
|
26
|
+
* majority of OpenAI-compatible gateways (vLLM, Together, Groq, Fireworks, Ollama, Azure OpenAI,
|
|
27
|
+
* OpenRouter, DeepSeek, Mistral La Plateforme, and most self-hosted deployments). Its tool-call
|
|
28
|
+
* synthetic-history shape (`role: 'assistant', tool_calls: [...]` followed by `role: 'tool'` with
|
|
29
|
+
* `tool_call_id`) is the lowest-common-denominator that every conformant gateway accepts.
|
|
30
|
+
*
|
|
31
|
+
* The adapter is built around three pluggable layers:
|
|
32
|
+
*
|
|
33
|
+
* 1. **Translation helpers** — the thirteen swappable functions exported from `./helpers` turn
|
|
34
|
+
* ADK primitives ({@link @nhtio/adk!Tokenizable}, {@link @nhtio/adk!Memory}, {@link @nhtio/adk!Message}, {@link @nhtio/adk!Thought},
|
|
35
|
+
* {@link @nhtio/adk!ToolCall}, {@link @nhtio/adk!Tool}, {@link @nhtio/adk!ArtifactTool}, {@link @nhtio/adk!SpooledArtifact}) into Chat
|
|
36
|
+
* Completions wire shapes. Consumers override individual helpers via `options.helpers.*` to
|
|
37
|
+
* customise envelope formats, bucket ordering, thought surfacing, or JSON Schema generation
|
|
38
|
+
* without forking the adapter.
|
|
39
|
+
* 2. **Three-layer options merging** — constructor baseline, per-`executor()` overrides, and
|
|
40
|
+
* per-iteration `ctx.stash.webLLMChatCompletions` overrides combine with key-by-key
|
|
41
|
+
* precedence for `helpers` and wholesale replacement for everything else.
|
|
42
|
+
* The merged shape is re-validated on every iteration so a malformed stash override
|
|
43
|
+
* fails loud, not silently.
|
|
44
|
+
* 3. **WebLLM engine invocation** — accepts a preloaded `engine` or lazy `createEngine` factory.
|
|
45
|
+
* The resolved request body is passed directly to WebLLM's OpenAI-compatible chat API.
|
|
46
|
+
*
|
|
47
|
+
* Per-iteration flow (steps 1–9 of the plan):
|
|
48
|
+
* 1. Merge constructor / executor / stash options and re-validate.
|
|
49
|
+
* 2. Resolve helpers, falling back to bundled `default*` for each unset field.
|
|
50
|
+
* 3. Forge artifact-query tools by walking `ctx.turnToolCalls`, collecting unique
|
|
51
|
+
* `SpooledArtifact` constructors, calling `<Ctor>.forgeTools(ctx)` on each, and merging the
|
|
52
|
+
* results with `ctx.tools`.
|
|
53
|
+
* 4. Pre-render every persisted tool-call result into the prompt-ready string the timeline will
|
|
54
|
+
* use, cached by `tc.id`.
|
|
55
|
+
* 5. When `tokenEncoding !== null`, sum the token weight of every persisted bucket and throw
|
|
56
|
+
* {@link @nhtio/adk/batteries!E_WEBLLM_CHAT_COMPLETIONS_CONTEXT_OVERFLOW} when the total exceeds `contextWindow`.
|
|
57
|
+
* 6. Build the request body via `buildChatCompletionsHistory`; carry vendor-opaque reasoning
|
|
58
|
+
* blocks through the `_adk_reasoning_payloads` side-channel.
|
|
59
|
+
* 7. Resolve or lazily create a WebLLM engine and call `engine.chat.completions.create(body)`.
|
|
60
|
+
* 8. Streaming path: consume WebLLM's async chunk iterable; surface deltas through
|
|
61
|
+
* `helpers.reportMessage` / `reportThought` / `reportToolCall`; assemble tool-call deltas via
|
|
62
|
+
* the accumulator; persist `Message` / `Thought` / `ToolCall` records on stream end.
|
|
63
|
+
* 9. Non-streaming path: consume the returned Chat Completion object; same persistence +
|
|
64
|
+
* tool-execution loop.
|
|
65
|
+
*/
|
|
66
|
+
var ADK_CONTROL_KEYS = new Set([
|
|
67
|
+
"engine",
|
|
68
|
+
"createEngine",
|
|
69
|
+
"engineConfig",
|
|
70
|
+
"chatOptions",
|
|
71
|
+
"stream",
|
|
72
|
+
"bucketOrder",
|
|
73
|
+
"contextWindow",
|
|
74
|
+
"selfIdentity",
|
|
75
|
+
"thoughtSurfacing",
|
|
76
|
+
"tokenEncoding",
|
|
77
|
+
"replayCompatibility",
|
|
78
|
+
"helpers",
|
|
79
|
+
"strictToolChoice",
|
|
80
|
+
"unsupportedMediaPolicy",
|
|
81
|
+
"onInitProgress",
|
|
82
|
+
"isWebGPUAvailable",
|
|
83
|
+
"autoAck"
|
|
84
|
+
]);
|
|
85
|
+
var mergeHelpers = (layers) => {
|
|
86
|
+
let merged;
|
|
87
|
+
for (const layer of layers) {
|
|
88
|
+
if (!layer) continue;
|
|
89
|
+
merged = {
|
|
90
|
+
...merged ?? {},
|
|
91
|
+
...layer
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return merged;
|
|
95
|
+
};
|
|
96
|
+
var mergeOptions = (baseline, exec, stash) => {
|
|
97
|
+
const layers = [
|
|
98
|
+
baseline,
|
|
99
|
+
exec ?? {},
|
|
100
|
+
stash ?? {}
|
|
101
|
+
];
|
|
102
|
+
const out = {};
|
|
103
|
+
for (const layer of layers) for (const [k, v] of Object.entries(layer)) {
|
|
104
|
+
if (v === void 0) continue;
|
|
105
|
+
if (k === "helpers") continue;
|
|
106
|
+
out[k] = v;
|
|
107
|
+
}
|
|
108
|
+
const helpers = mergeHelpers(layers.map((l) => l.helpers));
|
|
109
|
+
if (helpers !== void 0) out.helpers = helpers;
|
|
110
|
+
return out;
|
|
111
|
+
};
|
|
112
|
+
var resolveHelpers = (overrides) => {
|
|
113
|
+
const src = overrides ?? {};
|
|
114
|
+
return {
|
|
115
|
+
descriptionToChatCompletionsJsonSchema: src.descriptionToChatCompletionsJsonSchema ?? require_batteries_llm_openai_chat_completions_helpers.defaultDescriptionToChatCompletionsJsonSchema,
|
|
116
|
+
renderUntrustedContent: src.renderUntrustedContent ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderUntrustedContent,
|
|
117
|
+
renderTrustedContent: src.renderTrustedContent ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderTrustedContent,
|
|
118
|
+
renderStandingInstructions: src.renderStandingInstructions ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderStandingInstructions,
|
|
119
|
+
renderMemories: src.renderMemories ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderMemories,
|
|
120
|
+
renderRetrievables: src.renderRetrievables ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderRetrievables,
|
|
121
|
+
renderRetrievableSafetyDirective: src.renderRetrievableSafetyDirective ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderRetrievableSafetyDirective,
|
|
122
|
+
renderFirstPartyRetrievables: src.renderFirstPartyRetrievables ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderFirstPartyRetrievables,
|
|
123
|
+
renderThirdPartyPublicRetrievables: src.renderThirdPartyPublicRetrievables ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderThirdPartyPublicRetrievables,
|
|
124
|
+
renderThirdPartyPrivateRetrievables: src.renderThirdPartyPrivateRetrievables ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderThirdPartyPrivateRetrievables,
|
|
125
|
+
renderTimelineMessage: src.renderTimelineMessage ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderTimelineMessage,
|
|
126
|
+
renderThought: src.renderThought ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderThought,
|
|
127
|
+
filterThoughts: src.filterThoughts ?? require_batteries_llm_openai_chat_completions_helpers.defaultFilterThoughts,
|
|
128
|
+
toolsToChatCompletionsTools: src.toolsToChatCompletionsTools ?? require_batteries_llm_openai_chat_completions_helpers.defaultToolsToChatCompletionsTools,
|
|
129
|
+
renderChatCompletionsSystemPrompt: src.renderChatCompletionsSystemPrompt ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderChatCompletionsSystemPrompt,
|
|
130
|
+
renderChatCompletionsToolCallResult: src.renderChatCompletionsToolCallResult ?? require_batteries_llm_openai_chat_completions_helpers.defaultRenderChatCompletionsToolCallResult,
|
|
131
|
+
buildChatCompletionsHistory: src.buildChatCompletionsHistory ?? require_batteries_llm_openai_chat_completions_helpers.defaultBuildChatCompletionsHistory,
|
|
132
|
+
createChatCompletionsToolCallDeltaAccumulator: src.createChatCompletionsToolCallDeltaAccumulator ?? require_batteries_llm_openai_chat_completions_helpers.defaultCreateChatCompletionsToolCallDeltaAccumulator
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
var computeChecksum = (tool, args) => (0, js_sha256.sha256)(require_tool_registry.canonicalStringify({
|
|
136
|
+
tool,
|
|
137
|
+
args
|
|
138
|
+
}));
|
|
139
|
+
var nowIso = () => luxon.DateTime.now().toISO() ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
140
|
+
var estimateTokensOf = async (value, encoding) => {
|
|
141
|
+
return Promise.resolve(value.estimateTokens(encoding));
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Opinionated cross-environment LLM adapter for the WebLLM Chat Completions wire shape.
|
|
145
|
+
*
|
|
146
|
+
* @remarks
|
|
147
|
+
* Construction validates options eagerly via {@link @nhtio/adk/batteries!validateOptions} and throws
|
|
148
|
+
* {@link @nhtio/adk/batteries!E_INVALID_WEBLLM_CHAT_COMPLETIONS_OPTIONS} on failure — config bugs fail loud, not at
|
|
149
|
+
* dispatch time. The returned instance is reusable: call {@link WebLLMChatCompletionsAdapter.executor}
|
|
150
|
+
* once per `DispatchRunner` configuration to obtain an {@link @nhtio/adk!DispatchExecutorFn} bound to the
|
|
151
|
+
* baseline plus optional executor-scope overrides.
|
|
152
|
+
*
|
|
153
|
+
* Per-iteration overrides live on the active {@link @nhtio/adk!DispatchContext}'s
|
|
154
|
+
* `stash.webLLMChatCompletions` slot and take highest precedence — they merge into the
|
|
155
|
+
* executor-scope shape on every iteration. `helpers` merge key-by-key across all three layers;
|
|
156
|
+
* every other field is replaced wholesale at the highest layer that
|
|
157
|
+
* sets it.
|
|
158
|
+
*/
|
|
159
|
+
var WebLLMChatCompletionsAdapter = class WebLLMChatCompletionsAdapter {
|
|
160
|
+
/**
|
|
161
|
+
* Customary key for per-iteration overrides on `ctx.stash`. The adapter reads
|
|
162
|
+
* `ctx.stash.get(WebLLMChatCompletionsAdapter.STASH_KEY, {})` at the start of every
|
|
163
|
+
* iteration and merges the value into the resolved options shape.
|
|
164
|
+
*/
|
|
165
|
+
static STASH_KEY = "webLLMChatCompletions";
|
|
166
|
+
#baseline;
|
|
167
|
+
#engine;
|
|
168
|
+
#enginePromise;
|
|
169
|
+
static isAvailable() {
|
|
170
|
+
return typeof globalThis.navigator !== "undefined" && "gpu" in globalThis.navigator && typeof globalThis.navigator.gpu !== "undefined";
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* @param options - Constructor-baseline options. Re-validated on every iteration after
|
|
174
|
+
* per-dispatch and per-iteration overrides are layered in.
|
|
175
|
+
* @throws {@link @nhtio/adk/batteries!E_INVALID_WEBLLM_CHAT_COMPLETIONS_OPTIONS} when `options` does not satisfy
|
|
176
|
+
* {@link @nhtio/adk/batteries!webLLMChatCompletionsOptionsSchema}.
|
|
177
|
+
*/
|
|
178
|
+
constructor(options) {
|
|
179
|
+
this.#baseline = require_batteries_llm_webllm_chat_completions_validation.validateOptions(options);
|
|
180
|
+
this.#engine = this.#baseline.engine;
|
|
181
|
+
}
|
|
182
|
+
async preload(overrides) {
|
|
183
|
+
const merged = require_batteries_llm_webllm_chat_completions_validation.validateOptions(mergeOptions(this.#baseline, overrides, void 0));
|
|
184
|
+
return this.#resolveEngine(merged);
|
|
185
|
+
}
|
|
186
|
+
reset() {
|
|
187
|
+
this.#engine = void 0;
|
|
188
|
+
this.#enginePromise = void 0;
|
|
189
|
+
}
|
|
190
|
+
isAvailable() {
|
|
191
|
+
return (this.#baseline.isWebGPUAvailable ?? WebLLMChatCompletionsAdapter.isAvailable)();
|
|
192
|
+
}
|
|
193
|
+
async #resolveEngine(merged) {
|
|
194
|
+
if (merged.engine) {
|
|
195
|
+
this.#engine = merged.engine;
|
|
196
|
+
return merged.engine;
|
|
197
|
+
}
|
|
198
|
+
if (this.#engine) return this.#engine;
|
|
199
|
+
if (!(merged.isWebGPUAvailable ?? WebLLMChatCompletionsAdapter.isAvailable)()) throw new require_batteries_llm_webllm_chat_completions_exceptions.E_INVALID_WEBLLM_CHAT_COMPLETIONS_OPTIONS(["WebLLM requires a browser/runtime with WebGPU support"]);
|
|
200
|
+
this.#enginePromise ??= (async () => {
|
|
201
|
+
const engine = await (merged.createEngine ?? (async ({ model, engineConfig, chatOptions, onInitProgress }) => {
|
|
202
|
+
const { CreateMLCEngine } = await import("@mlc-ai/web-llm");
|
|
203
|
+
return await CreateMLCEngine(model, {
|
|
204
|
+
...engineConfig ?? {},
|
|
205
|
+
initProgressCallback: onInitProgress
|
|
206
|
+
}, chatOptions);
|
|
207
|
+
}))({
|
|
208
|
+
model: merged.model,
|
|
209
|
+
engineConfig: merged.engineConfig,
|
|
210
|
+
chatOptions: merged.chatOptions,
|
|
211
|
+
onInitProgress: merged.onInitProgress
|
|
212
|
+
});
|
|
213
|
+
this.#engine = engine;
|
|
214
|
+
return engine;
|
|
215
|
+
})();
|
|
216
|
+
return this.#enginePromise;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Returns an {@link @nhtio/adk!DispatchExecutorFn} bound to this adapter's baseline plus optional
|
|
220
|
+
* executor-scope overrides. The returned function is reusable across iterations — every
|
|
221
|
+
* iteration re-merges with `ctx.stash[STASH_KEY]` and re-validates the result.
|
|
222
|
+
*
|
|
223
|
+
* @param overrides - Optional executor-scope overrides. Higher precedence than the baseline,
|
|
224
|
+
* lower precedence than `ctx.stash[STASH_KEY]`.
|
|
225
|
+
* @returns An {@link @nhtio/adk!DispatchExecutorFn} suitable for `DispatchRunner`.
|
|
226
|
+
*/
|
|
227
|
+
executor(overrides) {
|
|
228
|
+
const baseline = this.#baseline;
|
|
229
|
+
const adapterClass = WebLLMChatCompletionsAdapter;
|
|
230
|
+
return async (ctx, helpers) => {
|
|
231
|
+
const localWarn = (msg) => {
|
|
232
|
+
helpers.log.warn({
|
|
233
|
+
kind: "helper-warning",
|
|
234
|
+
message: msg
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
const stashRaw = ctx.stash.get(adapterClass.STASH_KEY, {});
|
|
238
|
+
const merged = require_batteries_llm_webllm_chat_completions_validation.validateOptions(mergeOptions(baseline, overrides, stashRaw && typeof stashRaw === "object" ? stashRaw : {}));
|
|
239
|
+
if (merged.tokenEncoding !== null && merged.contextWindow === void 0) throw new require_batteries_llm_webllm_chat_completions_exceptions.E_INVALID_WEBLLM_CHAT_COMPLETIONS_OPTIONS(["tokenEncoding is non-null but contextWindow is undefined"]);
|
|
240
|
+
const resolvedHelpers = resolveHelpers(merged.helpers);
|
|
241
|
+
const uniqueCtors = /* @__PURE__ */ new Set();
|
|
242
|
+
for (const tc of ctx.turnToolCalls) {
|
|
243
|
+
const ctor = tc.results?.constructor;
|
|
244
|
+
if (ctor && require_spooled_artifact.SpooledArtifact.isSpooledArtifactConstructor(ctor)) uniqueCtors.add(ctor);
|
|
245
|
+
}
|
|
246
|
+
const forgedRegistries = [];
|
|
247
|
+
for (const ctor of uniqueCtors) {
|
|
248
|
+
const forgeFn = ctor.forgeTools;
|
|
249
|
+
if (typeof forgeFn === "function") forgedRegistries.push(forgeFn.call(ctor, ctx));
|
|
250
|
+
}
|
|
251
|
+
const mergedRegistry = require_tool_registry.ToolRegistry.merge([ctx.tools, ...forgedRegistries], { onCollision: "replace" });
|
|
252
|
+
mergedRegistry.bindContext(ctx);
|
|
253
|
+
const renderedToolCallResults = /* @__PURE__ */ new Map();
|
|
254
|
+
for (const tc of ctx.turnToolCalls) {
|
|
255
|
+
const rendered = await resolvedHelpers.renderChatCompletionsToolCallResult({
|
|
256
|
+
toolCall: tc,
|
|
257
|
+
results: tc.results,
|
|
258
|
+
tool: mergedRegistry.get(tc.tool),
|
|
259
|
+
renderUntrustedContent: resolvedHelpers.renderUntrustedContent,
|
|
260
|
+
renderTrustedContent: resolvedHelpers.renderTrustedContent,
|
|
261
|
+
unsupportedMediaPolicy: merged.unsupportedMediaPolicy ?? "throw",
|
|
262
|
+
warn: localWarn
|
|
263
|
+
});
|
|
264
|
+
renderedToolCallResults.set(tc.id, rendered);
|
|
265
|
+
}
|
|
266
|
+
if (merged.tokenEncoding !== null && merged.contextWindow !== void 0) {
|
|
267
|
+
const encoding = merged.tokenEncoding;
|
|
268
|
+
let spTokens = await estimateTokensOf(ctx.systemPrompt, encoding);
|
|
269
|
+
let siTokens = 0;
|
|
270
|
+
for (const si of ctx.standingInstructions) siTokens += await estimateTokensOf(si, encoding);
|
|
271
|
+
let memTokens = 0;
|
|
272
|
+
for (const mem of ctx.turnMemories) memTokens += await estimateTokensOf(mem.content, encoding);
|
|
273
|
+
let retTokens = 0;
|
|
274
|
+
for (const r of ctx.turnRetrievables) retTokens += await estimateTokensOf(r.content, encoding);
|
|
275
|
+
let tlTokens = 0;
|
|
276
|
+
for (const msg of ctx.turnMessages) if (msg.content !== void 0) tlTokens += await estimateTokensOf(msg.content, encoding);
|
|
277
|
+
for (const th of ctx.turnThoughts) tlTokens += await estimateTokensOf(th.content, encoding);
|
|
278
|
+
for (const rendered of renderedToolCallResults.values()) {
|
|
279
|
+
const tk = new require_tool_registry.Tokenizable(typeof rendered === "string" ? rendered : rendered.filter((b) => b.type === "text").map((b) => b.text).join("\n"));
|
|
280
|
+
tlTokens += await estimateTokensOf(tk, encoding);
|
|
281
|
+
}
|
|
282
|
+
const total = spTokens + siTokens + memTokens + retTokens + tlTokens;
|
|
283
|
+
const perBucketObj = {
|
|
284
|
+
systemPrompt: spTokens,
|
|
285
|
+
standingInstructions: siTokens,
|
|
286
|
+
memories: memTokens,
|
|
287
|
+
retrievables: retTokens,
|
|
288
|
+
timeline: tlTokens
|
|
289
|
+
};
|
|
290
|
+
helpers.log.debug({
|
|
291
|
+
kind: "context-window-usage",
|
|
292
|
+
message: `Context window usage: ${total}/${merged.contextWindow} tokens`,
|
|
293
|
+
payload: {
|
|
294
|
+
total,
|
|
295
|
+
limit: merged.contextWindow,
|
|
296
|
+
encoding,
|
|
297
|
+
perBucket: perBucketObj
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
if (total > merged.contextWindow) {
|
|
301
|
+
const perBucket = JSON.stringify(perBucketObj);
|
|
302
|
+
throw new require_batteries_llm_webllm_chat_completions_exceptions.E_WEBLLM_CHAT_COMPLETIONS_CONTEXT_OVERFLOW([
|
|
303
|
+
total,
|
|
304
|
+
merged.contextWindow,
|
|
305
|
+
encoding,
|
|
306
|
+
perBucket
|
|
307
|
+
]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const forcedToolNames = [];
|
|
311
|
+
const toolChoice = merged.tool_choice;
|
|
312
|
+
let toolChoiceVariant = "function";
|
|
313
|
+
if (toolChoice && typeof toolChoice === "object") {
|
|
314
|
+
if ("function" in toolChoice && toolChoice.type === "function") forcedToolNames.push(toolChoice.function.name);
|
|
315
|
+
else if ("custom" in toolChoice && toolChoice.type === "custom") forcedToolNames.push(toolChoice.custom.name);
|
|
316
|
+
else if (toolChoice.type === "allowed_tools") {
|
|
317
|
+
toolChoiceVariant = "allowed_tools";
|
|
318
|
+
for (const entry of toolChoice.allowed_tools.tools) if ("function" in entry) forcedToolNames.push(entry.function.name);
|
|
319
|
+
else if ("custom" in entry) forcedToolNames.push(entry.custom.name);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const forcedForgedHits = [];
|
|
323
|
+
for (const name of forcedToolNames) if (mergedRegistry.get(name)?.ephemeral === true) forcedForgedHits.push({ toolName: name });
|
|
324
|
+
if (forcedForgedHits.length > 0) {
|
|
325
|
+
if (merged.strictToolChoice === true) throw new require_batteries_llm_webllm_chat_completions_exceptions.E_INVALID_WEBLLM_CHAT_COMPLETIONS_OPTIONS([`tool_choice forces forged ephemeral artifact-query tool(s): ${forcedForgedHits.map((h) => h.toolName).join(", ")} — these may not exist on the next iteration. Remove the override or unset strictToolChoice.`]);
|
|
326
|
+
helpers.log.warn({
|
|
327
|
+
kind: "tool-choice-forged-artifact",
|
|
328
|
+
message: `tool_choice forces ${forcedForgedHits.length} forged ephemeral artifact-query tool(s); this is almost always a misconfiguration`,
|
|
329
|
+
payload: {
|
|
330
|
+
toolNames: forcedForgedHits.map((h) => h.toolName),
|
|
331
|
+
variant: toolChoiceVariant
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
const { messages: wireMessages, reasoningPayloads } = await resolvedHelpers.buildChatCompletionsHistory({
|
|
336
|
+
systemPrompt: ctx.systemPrompt,
|
|
337
|
+
standingInstructions: ctx.standingInstructions,
|
|
338
|
+
memories: ctx.turnMemories,
|
|
339
|
+
retrievables: ctx.turnRetrievables,
|
|
340
|
+
messages: ctx.turnMessages,
|
|
341
|
+
thoughts: ctx.turnThoughts,
|
|
342
|
+
toolCalls: ctx.turnToolCalls,
|
|
343
|
+
tools: mergedRegistry,
|
|
344
|
+
renderedToolCallResults,
|
|
345
|
+
bucketOrder: merged.bucketOrder ?? [
|
|
346
|
+
"standingInstructions",
|
|
347
|
+
"memories",
|
|
348
|
+
"retrievables",
|
|
349
|
+
"timeline"
|
|
350
|
+
],
|
|
351
|
+
selfIdentity: merged.selfIdentity ?? "assistant",
|
|
352
|
+
thoughtSurfacing: merged.thoughtSurfacing ?? "all-self",
|
|
353
|
+
replayCompatibility: merged.replayCompatibility ?? [],
|
|
354
|
+
renderChatCompletionsToolCallResult: resolvedHelpers.renderChatCompletionsToolCallResult,
|
|
355
|
+
renderChatCompletionsSystemPrompt: resolvedHelpers.renderChatCompletionsSystemPrompt,
|
|
356
|
+
renderStandingInstructions: resolvedHelpers.renderStandingInstructions,
|
|
357
|
+
renderMemories: resolvedHelpers.renderMemories,
|
|
358
|
+
renderRetrievables: resolvedHelpers.renderRetrievables,
|
|
359
|
+
renderRetrievableSafetyDirective: resolvedHelpers.renderRetrievableSafetyDirective,
|
|
360
|
+
renderFirstPartyRetrievables: resolvedHelpers.renderFirstPartyRetrievables,
|
|
361
|
+
renderThirdPartyPublicRetrievables: resolvedHelpers.renderThirdPartyPublicRetrievables,
|
|
362
|
+
renderThirdPartyPrivateRetrievables: resolvedHelpers.renderThirdPartyPrivateRetrievables,
|
|
363
|
+
renderTimelineMessage: resolvedHelpers.renderTimelineMessage,
|
|
364
|
+
renderThought: resolvedHelpers.renderThought,
|
|
365
|
+
filterThoughts: resolvedHelpers.filterThoughts,
|
|
366
|
+
renderUntrustedContent: resolvedHelpers.renderUntrustedContent,
|
|
367
|
+
renderTrustedContent: resolvedHelpers.renderTrustedContent,
|
|
368
|
+
unsupportedMediaPolicy: merged.unsupportedMediaPolicy ?? "throw",
|
|
369
|
+
warn: localWarn
|
|
370
|
+
});
|
|
371
|
+
const stream = merged.stream ?? true;
|
|
372
|
+
const body = {
|
|
373
|
+
model: merged.model,
|
|
374
|
+
messages: wireMessages,
|
|
375
|
+
stream
|
|
376
|
+
};
|
|
377
|
+
for (const [k, v] of Object.entries(merged)) {
|
|
378
|
+
if (ADK_CONTROL_KEYS.has(k)) continue;
|
|
379
|
+
if (k === "model" || k === "messages" || k === "stream") continue;
|
|
380
|
+
if (v === void 0) continue;
|
|
381
|
+
body[k] = v;
|
|
382
|
+
}
|
|
383
|
+
const toolsArr = mergedRegistry.all();
|
|
384
|
+
if (toolsArr.length > 0) body.tools = resolvedHelpers.toolsToChatCompletionsTools(toolsArr, { descriptionToChatCompletionsJsonSchema: resolvedHelpers.descriptionToChatCompletionsJsonSchema });
|
|
385
|
+
if (reasoningPayloads.length > 0) body._adk_reasoning_payloads = reasoningPayloads;
|
|
386
|
+
let completion;
|
|
387
|
+
try {
|
|
388
|
+
completion = await (await this.#resolveEngine(merged)).chat.completions.create(body);
|
|
389
|
+
} catch (err) {
|
|
390
|
+
helpers.log.error({
|
|
391
|
+
kind: "webllm-engine-error",
|
|
392
|
+
message: `WebLLM engine failure: ${require_tool_registry.isError(err) ? err.message : String(err)}`,
|
|
393
|
+
payload: { detail: require_tool_registry.isError(err) ? err.message : String(err) }
|
|
394
|
+
});
|
|
395
|
+
ctx.nack(new require_batteries_llm_webllm_chat_completions_exceptions.E_WEBLLM_CHAT_COMPLETIONS_STREAM_ERROR([require_tool_registry.isError(err) ? err.message : String(err)]));
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const spoolStore = new require_batteries_storage_in_memory.InMemorySpoolStore();
|
|
399
|
+
const executeAndPersistToolCall = async (call) => {
|
|
400
|
+
const tool = mergedRegistry.get(call.name);
|
|
401
|
+
let args = {};
|
|
402
|
+
let parseError;
|
|
403
|
+
if (call.args && call.args.length > 0) try {
|
|
404
|
+
const parsed = JSON.parse(call.args);
|
|
405
|
+
if (require_tool_registry.isObject(parsed)) args = parsed;
|
|
406
|
+
else parseError = new require_batteries_llm_webllm_chat_completions_exceptions.E_WEBLLM_CHAT_COMPLETIONS_INVALID_TOOL_CALL_ARGS([`must be a JSON object; received ${Array.isArray(parsed) ? "array" : parsed === null ? "null" : typeof parsed}`, call.args]);
|
|
407
|
+
} catch {
|
|
408
|
+
parseError = new require_batteries_llm_webllm_chat_completions_exceptions.E_WEBLLM_CHAT_COMPLETIONS_INVALID_TOOL_CALL_ARGS(["are not valid JSON", call.args]);
|
|
409
|
+
}
|
|
410
|
+
const completedAt = nowIso();
|
|
411
|
+
if (parseError !== void 0) {
|
|
412
|
+
const results = new require_tool_registry.Tokenizable(parseError.message);
|
|
413
|
+
helpers.reportToolCall(call.id, {
|
|
414
|
+
tool: call.name,
|
|
415
|
+
args
|
|
416
|
+
});
|
|
417
|
+
helpers.reportToolCall(call.id, {
|
|
418
|
+
results,
|
|
419
|
+
isError: true,
|
|
420
|
+
isComplete: true
|
|
421
|
+
});
|
|
422
|
+
const checksum = computeChecksum(call.name, args);
|
|
423
|
+
await ctx.storeToolCall(new require_tool_call.ToolCall({
|
|
424
|
+
id: call.id,
|
|
425
|
+
tool: call.name,
|
|
426
|
+
args,
|
|
427
|
+
checksum,
|
|
428
|
+
isComplete: true,
|
|
429
|
+
isError: true,
|
|
430
|
+
results,
|
|
431
|
+
createdAt: completedAt,
|
|
432
|
+
updatedAt: completedAt,
|
|
433
|
+
completedAt
|
|
434
|
+
}));
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (!tool) {
|
|
438
|
+
const results = new require_tool_registry.Tokenizable(`Tool not found: ${call.name}`);
|
|
439
|
+
helpers.reportToolCall(call.id, {
|
|
440
|
+
tool: call.name,
|
|
441
|
+
args
|
|
442
|
+
});
|
|
443
|
+
helpers.reportToolCall(call.id, {
|
|
444
|
+
results,
|
|
445
|
+
isError: true,
|
|
446
|
+
isComplete: true
|
|
447
|
+
});
|
|
448
|
+
const checksum = computeChecksum(call.name, args);
|
|
449
|
+
await ctx.storeToolCall(new require_tool_call.ToolCall({
|
|
450
|
+
id: call.id,
|
|
451
|
+
tool: call.name,
|
|
452
|
+
args,
|
|
453
|
+
checksum,
|
|
454
|
+
isComplete: true,
|
|
455
|
+
isError: true,
|
|
456
|
+
results,
|
|
457
|
+
createdAt: completedAt,
|
|
458
|
+
updatedAt: completedAt,
|
|
459
|
+
completedAt
|
|
460
|
+
}));
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
helpers.reportToolCall(call.id, {
|
|
464
|
+
tool: tool.name,
|
|
465
|
+
args
|
|
466
|
+
});
|
|
467
|
+
const isArtifactTool = require_spooled_artifact.ArtifactTool.isArtifactTool(tool);
|
|
468
|
+
let results = new require_tool_registry.Tokenizable("");
|
|
469
|
+
let toolHadError = false;
|
|
470
|
+
try {
|
|
471
|
+
const raw = await tool.executor(ctx)(args);
|
|
472
|
+
if (isArtifactTool) if (require_tool_registry.Tokenizable.isTokenizable(raw)) results = raw;
|
|
473
|
+
else if (typeof raw === "string") results = new require_tool_registry.Tokenizable(raw);
|
|
474
|
+
else throw new Error(`ArtifactTool "${tool.name}" returned a non-string/non-Tokenizable value`);
|
|
475
|
+
else if (require_tool_call.Media.isMedia(raw)) results = raw;
|
|
476
|
+
else if (Array.isArray(raw) && raw.length > 0 && raw.every((m) => require_tool_call.Media.isMedia(m))) results = raw;
|
|
477
|
+
else if (typeof raw === "string" || require_tool_registry.isInstanceOf(raw, "Uint8Array", Uint8Array)) {
|
|
478
|
+
const reader = spoolStore.write(call.id, raw);
|
|
479
|
+
results = new ((tool.artifactConstructor?.()) ?? require_spooled_artifact.SpooledArtifact)(reader);
|
|
480
|
+
} else {
|
|
481
|
+
const reader = spoolStore.write(call.id, String(raw));
|
|
482
|
+
results = new ((tool.artifactConstructor?.()) ?? require_spooled_artifact.SpooledArtifact)(reader);
|
|
483
|
+
}
|
|
484
|
+
} catch (err) {
|
|
485
|
+
toolHadError = true;
|
|
486
|
+
let detailMsg = require_tool_registry.isError(err) ? err.message : String(err);
|
|
487
|
+
if (require_tool_registry.isError(err) && require_tool_registry.isError(err.cause) && err.cause.message && err.cause.message !== err.message) detailMsg = `${detailMsg} ${err.cause.message}`;
|
|
488
|
+
results = new require_tool_registry.Tokenizable(detailMsg);
|
|
489
|
+
}
|
|
490
|
+
helpers.reportToolCall(call.id, {
|
|
491
|
+
results,
|
|
492
|
+
isError: toolHadError,
|
|
493
|
+
isComplete: true
|
|
494
|
+
});
|
|
495
|
+
const checksum = computeChecksum(tool.name, args);
|
|
496
|
+
const completedAt2 = nowIso();
|
|
497
|
+
await ctx.storeToolCall(new require_tool_call.ToolCall({
|
|
498
|
+
id: call.id,
|
|
499
|
+
tool: tool.name,
|
|
500
|
+
args,
|
|
501
|
+
checksum,
|
|
502
|
+
isComplete: true,
|
|
503
|
+
isError: toolHadError,
|
|
504
|
+
results,
|
|
505
|
+
fromArtifactTool: isArtifactTool,
|
|
506
|
+
createdAt: completedAt2,
|
|
507
|
+
updatedAt: completedAt2,
|
|
508
|
+
completedAt: completedAt2
|
|
509
|
+
}));
|
|
510
|
+
};
|
|
511
|
+
const selfIdentity = merged.selfIdentity ?? "assistant";
|
|
512
|
+
if (stream) {
|
|
513
|
+
const chunks = completion;
|
|
514
|
+
if (!chunks || typeof chunks[Symbol.asyncIterator] !== "function") {
|
|
515
|
+
ctx.nack(new require_batteries_llm_webllm_chat_completions_exceptions.E_WEBLLM_CHAT_COMPLETIONS_STREAM_ERROR(["engine did not return a stream"]));
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const accumulator = resolvedHelpers.createChatCompletionsToolCallDeltaAccumulator();
|
|
519
|
+
const streamId = (0, uuid.v6)();
|
|
520
|
+
let partialMessageContent = "";
|
|
521
|
+
let partialThoughtContent = "";
|
|
522
|
+
let sawMessageDelta = false;
|
|
523
|
+
let sawThoughtDelta = false;
|
|
524
|
+
const drainAndPersist = async () => {
|
|
525
|
+
if (sawMessageDelta) {
|
|
526
|
+
helpers.reportMessage(streamId, "", { isComplete: true });
|
|
527
|
+
await ctx.storeMessage(new require_thought.Message({
|
|
528
|
+
id: streamId,
|
|
529
|
+
role: "assistant",
|
|
530
|
+
content: partialMessageContent,
|
|
531
|
+
identity: selfIdentity,
|
|
532
|
+
createdAt: nowIso(),
|
|
533
|
+
updatedAt: nowIso()
|
|
534
|
+
}));
|
|
535
|
+
}
|
|
536
|
+
if (sawThoughtDelta) {
|
|
537
|
+
helpers.reportThought(streamId, "", { isComplete: true });
|
|
538
|
+
await ctx.storeThought(new require_thought.Thought({
|
|
539
|
+
id: streamId,
|
|
540
|
+
content: partialThoughtContent,
|
|
541
|
+
identity: selfIdentity,
|
|
542
|
+
createdAt: nowIso(),
|
|
543
|
+
updatedAt: nowIso()
|
|
544
|
+
}));
|
|
545
|
+
}
|
|
546
|
+
const calls = accumulator.drain();
|
|
547
|
+
helpers.log.debug({
|
|
548
|
+
kind: "accumulator-finalised",
|
|
549
|
+
message: `Stream finalised: ${calls.length} tool call(s), message=${sawMessageDelta}, thought=${sawThoughtDelta}`,
|
|
550
|
+
payload: {
|
|
551
|
+
toolCallCount: calls.length,
|
|
552
|
+
sawMessageDelta,
|
|
553
|
+
sawThoughtDelta
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
if (calls.length === 0) {
|
|
557
|
+
if (merged.autoAck) ctx.ack();
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
for (const call of calls) {
|
|
561
|
+
if (ctx.abortSignal.aborted) return;
|
|
562
|
+
await executeAndPersistToolCall(call);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
try {
|
|
566
|
+
for await (const chunk of chunks) {
|
|
567
|
+
if (ctx.abortSignal.aborted) return;
|
|
568
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
569
|
+
if (!delta) continue;
|
|
570
|
+
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
571
|
+
sawMessageDelta = true;
|
|
572
|
+
partialMessageContent += delta.content;
|
|
573
|
+
helpers.reportMessage(streamId, delta.content);
|
|
574
|
+
}
|
|
575
|
+
const reasoning = delta.reasoning_content;
|
|
576
|
+
if (typeof reasoning === "string" && reasoning.length > 0) {
|
|
577
|
+
sawThoughtDelta = true;
|
|
578
|
+
partialThoughtContent += reasoning;
|
|
579
|
+
helpers.reportThought(streamId, reasoning);
|
|
580
|
+
}
|
|
581
|
+
if (Array.isArray(delta.tool_calls)) for (const d of delta.tool_calls) accumulator.feed(d);
|
|
582
|
+
}
|
|
583
|
+
await drainAndPersist();
|
|
584
|
+
} catch (err) {
|
|
585
|
+
if (ctx.abortSignal.aborted) return;
|
|
586
|
+
helpers.log.error({
|
|
587
|
+
kind: "stream-error",
|
|
588
|
+
message: `WebLLM stream failed: ${require_tool_registry.isError(err) ? err.message : String(err)}`,
|
|
589
|
+
payload: { detail: require_tool_registry.isError(err) ? err.message : String(err) }
|
|
590
|
+
});
|
|
591
|
+
ctx.nack(new require_batteries_llm_webllm_chat_completions_exceptions.E_WEBLLM_CHAT_COMPLETIONS_STREAM_ERROR([require_tool_registry.isError(err) ? err.message : String(err)]));
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const parsed = completion;
|
|
597
|
+
const choice = parsed.choices?.[0];
|
|
598
|
+
if (!choice) {
|
|
599
|
+
if (merged.autoAck) ctx.ack();
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
const msg = choice.message;
|
|
603
|
+
const responseId = parsed.id ?? (0, uuid.v6)();
|
|
604
|
+
if (msg && typeof msg.content === "string" && msg.content.length > 0) {
|
|
605
|
+
const messageId = `${responseId}:message`;
|
|
606
|
+
helpers.reportMessage(messageId, msg.content, { isComplete: true });
|
|
607
|
+
await ctx.storeMessage(new require_thought.Message({
|
|
608
|
+
id: messageId,
|
|
609
|
+
role: "assistant",
|
|
610
|
+
content: msg.content,
|
|
611
|
+
identity: selfIdentity,
|
|
612
|
+
createdAt: nowIso(),
|
|
613
|
+
updatedAt: nowIso()
|
|
614
|
+
}));
|
|
615
|
+
}
|
|
616
|
+
const reasoning = msg?.reasoning_content;
|
|
617
|
+
if (typeof reasoning === "string" && reasoning.length > 0) {
|
|
618
|
+
const thoughtId = `${responseId}:thought`;
|
|
619
|
+
helpers.reportThought(thoughtId, reasoning, { isComplete: true });
|
|
620
|
+
await ctx.storeThought(new require_thought.Thought({
|
|
621
|
+
id: thoughtId,
|
|
622
|
+
content: reasoning,
|
|
623
|
+
identity: selfIdentity,
|
|
624
|
+
createdAt: nowIso(),
|
|
625
|
+
updatedAt: nowIso()
|
|
626
|
+
}));
|
|
627
|
+
}
|
|
628
|
+
const rawCalls = msg?.tool_calls ?? [];
|
|
629
|
+
if (rawCalls.length === 0) {
|
|
630
|
+
if (merged.autoAck) ctx.ack();
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
const calls = rawCalls.map((tc) => ({
|
|
634
|
+
id: tc.id,
|
|
635
|
+
type: tc.type ?? "function",
|
|
636
|
+
name: tc.function?.name ?? "",
|
|
637
|
+
args: tc.function?.arguments ?? ""
|
|
638
|
+
}));
|
|
639
|
+
for (const call of calls) {
|
|
640
|
+
if (ctx.abortSignal.aborted) return;
|
|
641
|
+
await executeAndPersistToolCall(call);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Returns `true` when `value` is an {@link WebLLMChatCompletionsAdapter} instance.
|
|
647
|
+
*
|
|
648
|
+
* @param value - The value to test.
|
|
649
|
+
* @returns `true` when `value` is an `WebLLMChatCompletionsAdapter` instance.
|
|
650
|
+
*/
|
|
651
|
+
static isWebLLMChatCompletionsAdapter(value) {
|
|
652
|
+
return require_tool_registry.isInstanceOf(value, "WebLLMChatCompletionsAdapter", WebLLMChatCompletionsAdapter);
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
//#endregion
|
|
656
|
+
exports.WebLLMChatCompletionsAdapter = WebLLMChatCompletionsAdapter;
|
|
657
|
+
|
|
658
|
+
//# sourceMappingURL=adapter.cjs.map
|