@opencode/ai 0.0.0-reserved → 2.0.1
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/README.md +879 -2
- package/dist/cache-policy.d.ts +2 -0
- package/dist/cache-policy.js +129 -0
- package/dist/image-client.d.ts +19 -0
- package/dist/image-client.js +28 -0
- package/dist/image.d.ts +110 -0
- package/dist/image.js +103 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +12 -0
- package/dist/llm.d.ts +252 -0
- package/dist/llm.js +74 -0
- package/dist/protocols/alibaba-chat.d.ts +225 -0
- package/dist/protocols/alibaba-chat.js +75 -0
- package/dist/protocols/alibaba-messages.d.ts +350 -0
- package/dist/protocols/alibaba-messages.js +40 -0
- package/dist/protocols/alibaba-responses.d.ts +255 -0
- package/dist/protocols/alibaba-responses.js +80 -0
- package/dist/protocols/anthropic-messages.d.ts +980 -0
- package/dist/protocols/anthropic-messages.js +1460 -0
- package/dist/protocols/bedrock-converse.d.ts +499 -0
- package/dist/protocols/bedrock-converse.js +643 -0
- package/dist/protocols/bedrock-event-stream.d.ts +9 -0
- package/dist/protocols/bedrock-event-stream.js +97 -0
- package/dist/protocols/gemini.d.ts +285 -0
- package/dist/protocols/gemini.js +671 -0
- package/dist/protocols/google-images.d.ts +30 -0
- package/dist/protocols/google-images.js +181 -0
- package/dist/protocols/index.d.ts +12 -0
- package/dist/protocols/index.js +12 -0
- package/dist/protocols/meta-images.d.ts +26 -0
- package/dist/protocols/meta-images.js +89 -0
- package/dist/protocols/meta-messages.d.ts +356 -0
- package/dist/protocols/meta-messages.js +41 -0
- package/dist/protocols/meta-responses.d.ts +473 -0
- package/dist/protocols/meta-responses.js +173 -0
- package/dist/protocols/mistral-chat.d.ts +540 -0
- package/dist/protocols/mistral-chat.js +624 -0
- package/dist/protocols/open-responses-channel.d.ts +25 -0
- package/dist/protocols/open-responses-channel.js +141 -0
- package/dist/protocols/open-responses-continuation.d.ts +16 -0
- package/dist/protocols/open-responses-continuation.js +170 -0
- package/dist/protocols/open-responses.d.ts +1715 -0
- package/dist/protocols/open-responses.js +1228 -0
- package/dist/protocols/openai-chat.d.ts +860 -0
- package/dist/protocols/openai-chat.js +966 -0
- package/dist/protocols/openai-compatible-chat.d.ts +109 -0
- package/dist/protocols/openai-compatible-chat.js +19 -0
- package/dist/protocols/openai-compatible-responses.d.ts +172 -0
- package/dist/protocols/openai-compatible-responses.js +18 -0
- package/dist/protocols/openai-images.d.ts +32 -0
- package/dist/protocols/openai-images.js +183 -0
- package/dist/protocols/openai-responses.d.ts +1389 -0
- package/dist/protocols/openai-responses.js +260 -0
- package/dist/protocols/shared.d.ts +193 -0
- package/dist/protocols/shared.js +290 -0
- package/dist/protocols/utils/bedrock-auth.d.ts +60 -0
- package/dist/protocols/utils/bedrock-auth.js +85 -0
- package/dist/protocols/utils/bedrock-cache.d.ts +19 -0
- package/dist/protocols/utils/bedrock-cache.js +49 -0
- package/dist/protocols/utils/bedrock-media.d.ts +55 -0
- package/dist/protocols/utils/bedrock-media.js +73 -0
- package/dist/protocols/utils/cache.d.ts +6 -0
- package/dist/protocols/utils/cache.js +5 -0
- package/dist/protocols/utils/gemini-tool-schema.d.ts +2 -0
- package/dist/protocols/utils/gemini-tool-schema.js +103 -0
- package/dist/protocols/utils/image-input.d.ts +21 -0
- package/dist/protocols/utils/image-input.js +20 -0
- package/dist/protocols/utils/lifecycle.d.ts +24 -0
- package/dist/protocols/utils/lifecycle.js +72 -0
- package/dist/protocols/utils/meta-image.d.ts +2 -0
- package/dist/protocols/utils/meta-image.js +13 -0
- package/dist/protocols/utils/open-responses-options.d.ts +56 -0
- package/dist/protocols/utils/open-responses-options.js +61 -0
- package/dist/protocols/utils/openai-image.d.ts +5 -0
- package/dist/protocols/utils/openai-image.js +18 -0
- package/dist/protocols/utils/openai-options.d.ts +16 -0
- package/dist/protocols/utils/openai-options.js +14 -0
- package/dist/protocols/utils/partial-json-options.d.ts +62 -0
- package/dist/protocols/utils/partial-json-options.js +52 -0
- package/dist/protocols/utils/partial-json.d.ts +8 -0
- package/dist/protocols/utils/partial-json.js +279 -0
- package/dist/protocols/utils/responses-checkpoint.d.ts +4 -0
- package/dist/protocols/utils/responses-checkpoint.js +107 -0
- package/dist/protocols/utils/responses-compaction.d.ts +4 -0
- package/dist/protocols/utils/responses-compaction.js +129 -0
- package/dist/protocols/utils/responses-hosted-tools.d.ts +26 -0
- package/dist/protocols/utils/responses-hosted-tools.js +32 -0
- package/dist/protocols/utils/tool-schema.d.ts +8 -0
- package/dist/protocols/utils/tool-schema.js +54 -0
- package/dist/protocols/utils/tool-stream.d.ts +710 -0
- package/dist/protocols/utils/tool-stream.js +155 -0
- package/dist/protocols/xai-images.d.ts +26 -0
- package/dist/protocols/xai-images.js +106 -0
- package/dist/protocols/xai-responses.d.ts +250 -0
- package/dist/protocols/xai-responses.js +81 -0
- package/dist/protocols/zai-chat.d.ts +202 -0
- package/dist/protocols/zai-chat.js +49 -0
- package/dist/protocols/zai-images.d.ts +22 -0
- package/dist/protocols/zai-images.js +79 -0
- package/dist/protocols/zai-messages.d.ts +344 -0
- package/dist/protocols/zai-messages.js +27 -0
- package/dist/protocols.d.ts +1 -0
- package/dist/protocols.js +1 -0
- package/dist/provider-error.d.ts +15 -0
- package/dist/provider-error.js +125 -0
- package/dist/provider-package.d.ts +15 -0
- package/dist/provider-package.js +1 -0
- package/dist/provider.d.ts +23 -0
- package/dist/provider.js +2 -0
- package/dist/providers/alibaba/chat.d.ts +1 -0
- package/dist/providers/alibaba/chat.js +1 -0
- package/dist/providers/alibaba/messages.d.ts +3 -0
- package/dist/providers/alibaba/messages.js +1 -0
- package/dist/providers/alibaba/responses.d.ts +3 -0
- package/dist/providers/alibaba/responses.js +1 -0
- package/dist/providers/alibaba.d.ts +711 -0
- package/dist/providers/alibaba.js +94 -0
- package/dist/providers/amazon-bedrock/mantle/chat.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle/chat.js +1 -0
- package/dist/providers/amazon-bedrock/mantle/responses.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle/responses.js +1 -0
- package/dist/providers/amazon-bedrock/mantle.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle.js +1 -0
- package/dist/providers/amazon-bedrock-mantle.d.ts +313 -0
- package/dist/providers/amazon-bedrock-mantle.js +79 -0
- package/dist/providers/amazon-bedrock.d.ts +173 -0
- package/dist/providers/amazon-bedrock.js +41 -0
- package/dist/providers/anthropic-compatible.d.ts +309 -0
- package/dist/providers/anthropic-compatible.js +50 -0
- package/dist/providers/anthropic.d.ts +307 -0
- package/dist/providers/anthropic.js +42 -0
- package/dist/providers/azure/chat.d.ts +2 -0
- package/dist/providers/azure/chat.js +1 -0
- package/dist/providers/azure/responses.d.ts +2 -0
- package/dist/providers/azure/responses.js +1 -0
- package/dist/providers/azure.d.ts +598 -0
- package/dist/providers/azure.js +115 -0
- package/dist/providers/baseten.d.ts +228 -0
- package/dist/providers/baseten.js +38 -0
- package/dist/providers/cerebras.d.ts +227 -0
- package/dist/providers/cerebras.js +40 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +237 -0
- package/dist/providers/cloudflare-ai-gateway.js +65 -0
- package/dist/providers/cloudflare-workers-ai.d.ts +231 -0
- package/dist/providers/cloudflare-workers-ai.js +51 -0
- package/dist/providers/deepinfra.d.ts +227 -0
- package/dist/providers/deepinfra.js +43 -0
- package/dist/providers/deepseek.d.ts +228 -0
- package/dist/providers/deepseek.js +41 -0
- package/dist/providers/fireworks.d.ts +228 -0
- package/dist/providers/fireworks.js +38 -0
- package/dist/providers/google-vertex/chat.d.ts +2 -0
- package/dist/providers/google-vertex/chat.js +1 -0
- package/dist/providers/google-vertex/gemini.d.ts +2 -0
- package/dist/providers/google-vertex/gemini.js +1 -0
- package/dist/providers/google-vertex/messages.d.ts +2 -0
- package/dist/providers/google-vertex/messages.js +1 -0
- package/dist/providers/google-vertex/responses.d.ts +2 -0
- package/dist/providers/google-vertex/responses.js +1 -0
- package/dist/providers/google-vertex-chat.d.ts +132 -0
- package/dist/providers/google-vertex-chat.js +55 -0
- package/dist/providers/google-vertex-messages.d.ts +306 -0
- package/dist/providers/google-vertex-messages.js +75 -0
- package/dist/providers/google-vertex-responses.d.ts +197 -0
- package/dist/providers/google-vertex-responses.js +56 -0
- package/dist/providers/google-vertex-shared.d.ts +22 -0
- package/dist/providers/google-vertex-shared.js +72 -0
- package/dist/providers/google-vertex.d.ts +119 -0
- package/dist/providers/google-vertex.js +98 -0
- package/dist/providers/google.d.ts +114 -0
- package/dist/providers/google.js +42 -0
- package/dist/providers/groq.d.ts +314 -0
- package/dist/providers/groq.js +81 -0
- package/dist/providers/index.d.ts +31 -0
- package/dist/providers/index.js +31 -0
- package/dist/providers/meta/chat.d.ts +2 -0
- package/dist/providers/meta/chat.js +1 -0
- package/dist/providers/meta/messages.d.ts +2 -0
- package/dist/providers/meta/messages.js +1 -0
- package/dist/providers/meta/responses.d.ts +2 -0
- package/dist/providers/meta/responses.js +1 -0
- package/dist/providers/meta.d.ts +636 -0
- package/dist/providers/meta.js +113 -0
- package/dist/providers/minimax/chat.d.ts +4 -0
- package/dist/providers/minimax/chat.js +8 -0
- package/dist/providers/minimax/messages.d.ts +1 -0
- package/dist/providers/minimax/messages.js +1 -0
- package/dist/providers/minimax/responses.d.ts +4 -0
- package/dist/providers/minimax/responses.js +8 -0
- package/dist/providers/minimax.d.ts +598 -0
- package/dist/providers/minimax.js +89 -0
- package/dist/providers/mistral.d.ts +207 -0
- package/dist/providers/mistral.js +28 -0
- package/dist/providers/moonshot/chat.d.ts +1 -0
- package/dist/providers/moonshot/chat.js +1 -0
- package/dist/providers/moonshot/messages.d.ts +4 -0
- package/dist/providers/moonshot/messages.js +8 -0
- package/dist/providers/moonshot/responses.d.ts +4 -0
- package/dist/providers/moonshot/responses.js +8 -0
- package/dist/providers/moonshot.d.ts +596 -0
- package/dist/providers/moonshot.js +90 -0
- package/dist/providers/open-responses-options.d.ts +6 -0
- package/dist/providers/open-responses-options.js +1 -0
- package/dist/providers/openai/chat.d.ts +2 -0
- package/dist/providers/openai/chat.js +1 -0
- package/dist/providers/openai/responses.d.ts +2 -0
- package/dist/providers/openai/responses.js +1 -0
- package/dist/providers/openai-compatible/responses.d.ts +1 -0
- package/dist/providers/openai-compatible/responses.js +1 -0
- package/dist/providers/openai-compatible-responses.d.ts +195 -0
- package/dist/providers/openai-compatible-responses.js +32 -0
- package/dist/providers/openai-compatible.d.ts +130 -0
- package/dist/providers/openai-compatible.js +33 -0
- package/dist/providers/openai-options.d.ts +26 -0
- package/dist/providers/openai-options.js +41 -0
- package/dist/providers/openai.d.ts +404 -0
- package/dist/providers/openai.js +82 -0
- package/dist/providers/openrouter.d.ts +563 -0
- package/dist/providers/openrouter.js +114 -0
- package/dist/providers/togetherai.d.ts +227 -0
- package/dist/providers/togetherai.js +40 -0
- package/dist/providers/xai.d.ts +163 -0
- package/dist/providers/xai.js +88 -0
- package/dist/providers/zai/chat.d.ts +1 -0
- package/dist/providers/zai/chat.js +1 -0
- package/dist/providers/zai-coding-plan/chat.d.ts +1 -0
- package/dist/providers/zai-coding-plan/chat.js +1 -0
- package/dist/providers/zai-coding-plan/messages.d.ts +4 -0
- package/dist/providers/zai-coding-plan/messages.js +8 -0
- package/dist/providers/zai-coding-plan/responses.d.ts +4 -0
- package/dist/providers/zai-coding-plan/responses.js +8 -0
- package/dist/providers/zai-coding-plan.d.ts +577 -0
- package/dist/providers/zai-coding-plan.js +63 -0
- package/dist/providers/zai.d.ts +149 -0
- package/dist/providers/zai.js +53 -0
- package/dist/providers.d.ts +1 -0
- package/dist/providers.js +1 -0
- package/dist/route/auth-options.d.ts +34 -0
- package/dist/route/auth-options.js +14 -0
- package/dist/route/auth.d.ts +51 -0
- package/dist/route/auth.js +87 -0
- package/dist/route/client.d.ts +430 -0
- package/dist/route/client.js +307 -0
- package/dist/route/endpoint.d.ts +28 -0
- package/dist/route/endpoint.js +21 -0
- package/dist/route/executor.d.ts +27 -0
- package/dist/route/executor.js +183 -0
- package/dist/route/framing.d.ts +29 -0
- package/dist/route/framing.js +14 -0
- package/dist/route/index.d.ts +16 -0
- package/dist/route/index.js +9 -0
- package/dist/route/protocol.d.ts +76 -0
- package/dist/route/protocol.js +16 -0
- package/dist/route/transport/http.d.ts +34 -0
- package/dist/route/transport/http.js +68 -0
- package/dist/route/transport/index.d.ts +41 -0
- package/dist/route/transport/index.js +4 -0
- package/dist/route/transport/websocket-channel.d.ts +57 -0
- package/dist/route/transport/websocket-channel.js +1 -0
- package/dist/route/transport/websocket.d.ts +56 -0
- package/dist/route/transport/websocket.js +370 -0
- package/dist/route.d.ts +1 -0
- package/dist/route.js +1 -0
- package/dist/schema/errors.d.ts +170 -0
- package/dist/schema/errors.js +131 -0
- package/dist/schema/events.d.ts +8123 -0
- package/dist/schema/events.js +550 -0
- package/dist/schema/ids.d.ts +17 -0
- package/dist/schema/ids.js +10 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/messages.d.ts +646 -0
- package/dist/schema/messages.js +301 -0
- package/dist/schema/options.d.ts +159 -0
- package/dist/schema/options.js +189 -0
- package/dist/testing.d.ts +1693 -0
- package/dist/testing.js +129 -0
- package/dist/tool-history.d.ts +2 -0
- package/dist/tool-history.js +84 -0
- package/dist/tool-runtime.d.ts +15 -0
- package/dist/tool-runtime.js +62 -0
- package/dist/tool.d.ts +136 -0
- package/dist/tool.js +66 -0
- package/dist/utils/record.d.ts +2 -0
- package/dist/utils/record.js +2 -0
- package/dist/utils/sanitize.d.ts +1 -0
- package/dist/utils/sanitize.js +12 -0
- package/package.json +43 -10
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { LLM } from "@opencode/schema/llm";
|
|
3
|
+
import { ContentBlockID, ToolCallID } from "./ids.js";
|
|
4
|
+
import { Message, CompactionPart, ProviderMetadata, ToolCallPart, ToolOutput, ToolResultPart, ToolResultValue, } from "./messages.js";
|
|
5
|
+
import { ProviderFailureClassification } from "./errors.js";
|
|
6
|
+
export const FinishReason = LLM.FinishReason;
|
|
7
|
+
export { ProviderMetadata } from "./messages.js";
|
|
8
|
+
/**
|
|
9
|
+
* Token usage reported by an LLM provider.
|
|
10
|
+
*
|
|
11
|
+
* **Inclusive totals** (match AI SDK / OpenAI / LangChain convention — a
|
|
12
|
+
* reader from any of those ecosystems sees the number they expect):
|
|
13
|
+
*
|
|
14
|
+
* - `inputTokens` — total prompt tokens, *including* cached reads/writes.
|
|
15
|
+
* - `outputTokens` — total output tokens, *including* reasoning.
|
|
16
|
+
* - `totalTokens` — provider-supplied total, or `inputTokens + outputTokens`.
|
|
17
|
+
*
|
|
18
|
+
* **Non-overlapping breakdown** (every field is independently meaningful;
|
|
19
|
+
* consumers never have to subtract):
|
|
20
|
+
*
|
|
21
|
+
* - `nonCachedInputTokens` — the "fresh" portion of the prompt.
|
|
22
|
+
* - `cacheReadInputTokens` — input tokens served from cache.
|
|
23
|
+
* - `cacheWriteInputTokens` — input tokens written to cache.
|
|
24
|
+
* - `reasoningTokens` — subset of `outputTokens` spent on hidden reasoning.
|
|
25
|
+
*
|
|
26
|
+
* **Invariant**: `nonCachedInputTokens + cacheReadInputTokens +
|
|
27
|
+
* cacheWriteInputTokens = inputTokens`, and `reasoningTokens ≤ outputTokens`.
|
|
28
|
+
* Each protocol mapper computes whichever side it doesn't get natively,
|
|
29
|
+
* with `Math.max(0, …)` clamping for defense against provider bugs. Because
|
|
30
|
+
* every breakdown field is stored independently, downstream consumers can
|
|
31
|
+
* read whatever they need (cost-by-category, context-pressure, AI-SDK-style
|
|
32
|
+
* inclusive total) without ever subtracting — eliminating the underflow
|
|
33
|
+
* class of bug where a clamped difference would silently store the wrong
|
|
34
|
+
* value.
|
|
35
|
+
*
|
|
36
|
+
* **Semantics by provider**:
|
|
37
|
+
*
|
|
38
|
+
* - OpenAI Chat / Responses / Gemini: provider reports inclusive
|
|
39
|
+
* `inputTokens` and an inclusive `outputTokens`; mapper subtracts to
|
|
40
|
+
* derive the breakdown.
|
|
41
|
+
* - Anthropic and Bedrock report the input breakdown natively: Anthropic's
|
|
42
|
+
* `input_tokens` and Bedrock's `inputTokens` are non-cached only. Their
|
|
43
|
+
* mappers sum the breakdown to derive the inclusive `inputTokens`.
|
|
44
|
+
* Anthropic's `outputTokens` includes extended thinking. Newer responses
|
|
45
|
+
* expose that subset as `output_tokens_details.thinking_tokens`, which maps
|
|
46
|
+
* to `reasoningTokens`; older responses leave it undefined.
|
|
47
|
+
*
|
|
48
|
+
* `providerMetadata` always carries the provider's raw usage payload —
|
|
49
|
+
* keyed by provider name (`{ openai: ... }`, `{ anthropic: ... }`, etc.)
|
|
50
|
+
* — for fields we don't normalize and for billing-level audit trails.
|
|
51
|
+
* Matches the same escape-hatch field on `LLMEvent`.
|
|
52
|
+
*/
|
|
53
|
+
export class Usage extends Schema.Class("AI.Usage")({
|
|
54
|
+
/** Effective input size of the final message iteration, when reported; not billed totals. */
|
|
55
|
+
contextTokens: Schema.optional(Schema.Number),
|
|
56
|
+
inputTokens: Schema.optional(Schema.Number),
|
|
57
|
+
outputTokens: Schema.optional(Schema.Number),
|
|
58
|
+
nonCachedInputTokens: Schema.optional(Schema.Number),
|
|
59
|
+
cacheReadInputTokens: Schema.optional(Schema.Number),
|
|
60
|
+
cacheWriteInputTokens: Schema.optional(Schema.Number),
|
|
61
|
+
reasoningTokens: Schema.optional(Schema.Number),
|
|
62
|
+
totalTokens: Schema.optional(Schema.Number),
|
|
63
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
64
|
+
}) {
|
|
65
|
+
/**
|
|
66
|
+
* Non-reasoning output tokens (including compaction summaries) — `outputTokens` minus `reasoningTokens`, clamped
|
|
67
|
+
* to zero. The one place subtraction happens in this contract; the clamp
|
|
68
|
+
* means a provider reporting `reasoningTokens > outputTokens` produces a
|
|
69
|
+
* harmless zero rather than a negative that crashes downstream schemas.
|
|
70
|
+
*/
|
|
71
|
+
get visibleOutputTokens() {
|
|
72
|
+
return Math.max(0, (this.outputTokens ?? 0) - (this.reasoningTokens ?? 0));
|
|
73
|
+
}
|
|
74
|
+
static from(input) {
|
|
75
|
+
return input instanceof Usage ? input : new Usage(input);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** A replacement context window, not an assistant message to append to prior history. */
|
|
79
|
+
export class CompactionResponse extends Schema.Class("LLM.CompactionResponse")({
|
|
80
|
+
replacement: Schema.Array(Message),
|
|
81
|
+
usage: Schema.optional(Usage),
|
|
82
|
+
}) {
|
|
83
|
+
}
|
|
84
|
+
/** A checkpoint only; retained history and replacement-window construction belong to the caller. */
|
|
85
|
+
export class CompactionCheckpointResponse extends Schema.Class("LLM.CompactionCheckpointResponse")({
|
|
86
|
+
checkpoint: CompactionPart.pipe(Schema.refine((part) => part.encrypted !== undefined && part.encrypted.length > 0, { message: "A checkpoint response requires encrypted compaction content" })),
|
|
87
|
+
responseID: Schema.String.check(Schema.isPattern(/\S/)),
|
|
88
|
+
usage: Schema.optional(Usage),
|
|
89
|
+
}) {
|
|
90
|
+
}
|
|
91
|
+
export const StepStart = Schema.Struct({
|
|
92
|
+
type: Schema.tag("step-start"),
|
|
93
|
+
index: Schema.Number,
|
|
94
|
+
}).annotate({ identifier: "LLM.Event.StepStart" });
|
|
95
|
+
export const TextStart = Schema.Struct({
|
|
96
|
+
type: Schema.tag("text-start"),
|
|
97
|
+
id: ContentBlockID,
|
|
98
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
99
|
+
}).annotate({ identifier: "LLM.Event.TextStart" });
|
|
100
|
+
export const TextDelta = Schema.Struct({
|
|
101
|
+
type: Schema.tag("text-delta"),
|
|
102
|
+
id: ContentBlockID,
|
|
103
|
+
text: Schema.String,
|
|
104
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
105
|
+
}).annotate({ identifier: "LLM.Event.TextDelta" });
|
|
106
|
+
export const TextEnd = Schema.Struct({
|
|
107
|
+
type: Schema.tag("text-end"),
|
|
108
|
+
id: ContentBlockID,
|
|
109
|
+
/** Authoritative complete value; replaces accumulated deltas when present. */
|
|
110
|
+
text: Schema.optional(Schema.String),
|
|
111
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
112
|
+
}).annotate({ identifier: "LLM.Event.TextEnd" });
|
|
113
|
+
export const ReasoningStart = Schema.Struct({
|
|
114
|
+
type: Schema.tag("reasoning-start"),
|
|
115
|
+
id: ContentBlockID,
|
|
116
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
117
|
+
}).annotate({ identifier: "LLM.Event.ReasoningStart" });
|
|
118
|
+
export const ReasoningDelta = Schema.Struct({
|
|
119
|
+
type: Schema.tag("reasoning-delta"),
|
|
120
|
+
id: ContentBlockID,
|
|
121
|
+
text: Schema.String,
|
|
122
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
123
|
+
}).annotate({ identifier: "LLM.Event.ReasoningDelta" });
|
|
124
|
+
export const ReasoningEnd = Schema.Struct({
|
|
125
|
+
type: Schema.tag("reasoning-end"),
|
|
126
|
+
id: ContentBlockID,
|
|
127
|
+
/** Authoritative complete value; replaces accumulated deltas when present. */
|
|
128
|
+
text: Schema.optional(Schema.String),
|
|
129
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
130
|
+
}).annotate({ identifier: "LLM.Event.ReasoningEnd" });
|
|
131
|
+
export const ToolInputStart = Schema.Struct({
|
|
132
|
+
type: Schema.tag("tool-input-start"),
|
|
133
|
+
id: ToolCallID,
|
|
134
|
+
name: Schema.String,
|
|
135
|
+
namespace: Schema.optional(Schema.String),
|
|
136
|
+
providerExecuted: Schema.optional(Schema.Boolean),
|
|
137
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
138
|
+
}).annotate({ identifier: "LLM.Event.ToolInputStart" });
|
|
139
|
+
export const ToolInputDelta = Schema.Struct({
|
|
140
|
+
type: Schema.tag("tool-input-delta"),
|
|
141
|
+
id: ToolCallID,
|
|
142
|
+
name: Schema.String,
|
|
143
|
+
namespace: Schema.optional(Schema.String),
|
|
144
|
+
text: Schema.String,
|
|
145
|
+
/** Best-effort parse of all input fragments received through this delta. */
|
|
146
|
+
input: Schema.optional(Schema.Unknown),
|
|
147
|
+
}).annotate({ identifier: "LLM.Event.ToolInputDelta" });
|
|
148
|
+
export const ToolInputEnd = Schema.Struct({
|
|
149
|
+
type: Schema.tag("tool-input-end"),
|
|
150
|
+
id: ToolCallID,
|
|
151
|
+
name: Schema.String,
|
|
152
|
+
namespace: Schema.optional(Schema.String),
|
|
153
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
154
|
+
}).annotate({ identifier: "LLM.Event.ToolInputEnd" });
|
|
155
|
+
/** A local tool call whose final input could not be decoded. */
|
|
156
|
+
export const ToolInputError = Schema.Struct({
|
|
157
|
+
type: Schema.tag("tool-input-error"),
|
|
158
|
+
id: ToolCallID,
|
|
159
|
+
name: Schema.String,
|
|
160
|
+
namespace: Schema.optional(Schema.String),
|
|
161
|
+
raw: Schema.String,
|
|
162
|
+
}).annotate({ identifier: "LLM.Event.ToolInputError" });
|
|
163
|
+
export const ToolCall = Schema.Struct({
|
|
164
|
+
type: Schema.tag("tool-call"),
|
|
165
|
+
id: ToolCallID,
|
|
166
|
+
name: Schema.String,
|
|
167
|
+
namespace: Schema.optional(Schema.String),
|
|
168
|
+
input: Schema.Unknown,
|
|
169
|
+
providerExecuted: Schema.optional(Schema.Boolean),
|
|
170
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
171
|
+
}).annotate({ identifier: "LLM.Event.ToolCall" });
|
|
172
|
+
export const ToolResult = Schema.Struct({
|
|
173
|
+
type: Schema.tag("tool-result"),
|
|
174
|
+
id: ToolCallID,
|
|
175
|
+
name: Schema.String,
|
|
176
|
+
namespace: Schema.optional(Schema.String),
|
|
177
|
+
result: ToolResultValue,
|
|
178
|
+
output: Schema.optional(ToolOutput),
|
|
179
|
+
providerExecuted: Schema.optional(Schema.Boolean),
|
|
180
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
181
|
+
}).annotate({ identifier: "LLM.Event.ToolResult" });
|
|
182
|
+
export const ToolError = Schema.Struct({
|
|
183
|
+
type: Schema.tag("tool-error"),
|
|
184
|
+
id: ToolCallID,
|
|
185
|
+
name: Schema.String,
|
|
186
|
+
namespace: Schema.optional(Schema.String),
|
|
187
|
+
message: Schema.String,
|
|
188
|
+
error: Schema.optional(Schema.Defect()),
|
|
189
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
190
|
+
}).annotate({ identifier: "LLM.Event.ToolError" });
|
|
191
|
+
export const FinishReasonDetails = Schema.Struct({
|
|
192
|
+
normalized: FinishReason,
|
|
193
|
+
raw: Schema.optional(Schema.String),
|
|
194
|
+
}).annotate({ identifier: "LLM.FinishReasonDetails" });
|
|
195
|
+
export const StepFinish = Schema.Struct({
|
|
196
|
+
type: Schema.tag("step-finish"),
|
|
197
|
+
index: Schema.Number,
|
|
198
|
+
reason: FinishReasonDetails,
|
|
199
|
+
usage: Schema.optional(Usage),
|
|
200
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
201
|
+
}).annotate({ identifier: "LLM.Event.StepFinish" });
|
|
202
|
+
export const Finish = Schema.Struct({
|
|
203
|
+
type: Schema.tag("finish"),
|
|
204
|
+
reason: FinishReasonDetails,
|
|
205
|
+
usage: Schema.optional(Usage),
|
|
206
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
207
|
+
}).annotate({ identifier: "LLM.Event.Finish" });
|
|
208
|
+
export const ProviderErrorEvent = Schema.Struct({
|
|
209
|
+
type: Schema.tag("provider-error"),
|
|
210
|
+
message: Schema.String,
|
|
211
|
+
classification: Schema.optional(ProviderFailureClassification),
|
|
212
|
+
providerMetadata: Schema.optional(ProviderMetadata),
|
|
213
|
+
}).annotate({ identifier: "LLM.Event.ProviderError" });
|
|
214
|
+
const llmEventTagged = Schema.Union([
|
|
215
|
+
CompactionPart,
|
|
216
|
+
StepStart,
|
|
217
|
+
TextStart,
|
|
218
|
+
TextDelta,
|
|
219
|
+
TextEnd,
|
|
220
|
+
ReasoningStart,
|
|
221
|
+
ReasoningDelta,
|
|
222
|
+
ReasoningEnd,
|
|
223
|
+
ToolInputStart,
|
|
224
|
+
ToolInputDelta,
|
|
225
|
+
ToolInputEnd,
|
|
226
|
+
ToolInputError,
|
|
227
|
+
ToolCall,
|
|
228
|
+
ToolResult,
|
|
229
|
+
ToolError,
|
|
230
|
+
StepFinish,
|
|
231
|
+
Finish,
|
|
232
|
+
ProviderErrorEvent,
|
|
233
|
+
]).pipe(Schema.toTaggedUnion("type"));
|
|
234
|
+
const contentBlockID = (value) => ContentBlockID.make(value);
|
|
235
|
+
const toolCallID = (value) => ToolCallID.make(value);
|
|
236
|
+
/**
|
|
237
|
+
* camelCase aliases for `LLMEvent.guards` (provided by `Schema.toTaggedUnion`).
|
|
238
|
+
* Lets consumers write `events.filter(LLMEvent.is.toolCall)` instead of
|
|
239
|
+
* `events.filter(LLMEvent.guards["tool-call"])`.
|
|
240
|
+
*/
|
|
241
|
+
export const LLMEvent = Object.assign(llmEventTagged, {
|
|
242
|
+
compaction: CompactionPart.make,
|
|
243
|
+
stepStart: StepStart.make,
|
|
244
|
+
textStart: (input) => TextStart.make({ ...input, id: contentBlockID(input.id) }),
|
|
245
|
+
textDelta: (input) => TextDelta.make({ ...input, id: contentBlockID(input.id) }),
|
|
246
|
+
textEnd: (input) => TextEnd.make({ ...input, id: contentBlockID(input.id) }),
|
|
247
|
+
reasoningStart: (input) => ReasoningStart.make({ ...input, id: contentBlockID(input.id) }),
|
|
248
|
+
reasoningDelta: (input) => ReasoningDelta.make({ ...input, id: contentBlockID(input.id) }),
|
|
249
|
+
reasoningEnd: (input) => ReasoningEnd.make({ ...input, id: contentBlockID(input.id) }),
|
|
250
|
+
toolInputStart: (input) => ToolInputStart.make({ ...input, id: toolCallID(input.id) }),
|
|
251
|
+
toolInputDelta: (input) => ToolInputDelta.make({ ...input, id: toolCallID(input.id) }),
|
|
252
|
+
toolInputEnd: (input) => ToolInputEnd.make({ ...input, id: toolCallID(input.id) }),
|
|
253
|
+
toolInputError: (input) => ToolInputError.make({ ...input, id: toolCallID(input.id) }),
|
|
254
|
+
toolCall: (input) => ToolCall.make({ ...input, id: toolCallID(input.id) }),
|
|
255
|
+
toolResult: (input) => ToolResult.make({
|
|
256
|
+
...input,
|
|
257
|
+
id: toolCallID(input.id),
|
|
258
|
+
output: input.output === undefined ? undefined : ToolOutput.make(input.output.structured, input.output.content),
|
|
259
|
+
}),
|
|
260
|
+
toolError: (input) => ToolError.make({ ...input, id: toolCallID(input.id) }),
|
|
261
|
+
stepFinish: (input) => StepFinish.make({
|
|
262
|
+
...input,
|
|
263
|
+
usage: input.usage === undefined ? undefined : Usage.from(input.usage),
|
|
264
|
+
}),
|
|
265
|
+
finish: (input) => Finish.make({
|
|
266
|
+
...input,
|
|
267
|
+
usage: input.usage === undefined ? undefined : Usage.from(input.usage),
|
|
268
|
+
}),
|
|
269
|
+
providerError: ProviderErrorEvent.make,
|
|
270
|
+
is: {
|
|
271
|
+
compaction: llmEventTagged.guards.compaction,
|
|
272
|
+
stepStart: llmEventTagged.guards["step-start"],
|
|
273
|
+
textStart: llmEventTagged.guards["text-start"],
|
|
274
|
+
textDelta: llmEventTagged.guards["text-delta"],
|
|
275
|
+
textEnd: llmEventTagged.guards["text-end"],
|
|
276
|
+
reasoningStart: llmEventTagged.guards["reasoning-start"],
|
|
277
|
+
reasoningDelta: llmEventTagged.guards["reasoning-delta"],
|
|
278
|
+
reasoningEnd: llmEventTagged.guards["reasoning-end"],
|
|
279
|
+
toolInputStart: llmEventTagged.guards["tool-input-start"],
|
|
280
|
+
toolInputDelta: llmEventTagged.guards["tool-input-delta"],
|
|
281
|
+
toolInputEnd: llmEventTagged.guards["tool-input-end"],
|
|
282
|
+
toolInputError: llmEventTagged.guards["tool-input-error"],
|
|
283
|
+
toolCall: llmEventTagged.guards["tool-call"],
|
|
284
|
+
toolResult: llmEventTagged.guards["tool-result"],
|
|
285
|
+
toolError: llmEventTagged.guards["tool-error"],
|
|
286
|
+
stepFinish: llmEventTagged.guards["step-finish"],
|
|
287
|
+
finish: llmEventTagged.guards.finish,
|
|
288
|
+
providerError: llmEventTagged.guards["provider-error"],
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
/** Joins deltas per fragment, letting an authoritative end value replace that fragment's accumulated deltas. */
|
|
292
|
+
const joinFragments = (events, isDelta, isEnd) => {
|
|
293
|
+
const order = [];
|
|
294
|
+
const parts = new Map();
|
|
295
|
+
for (const event of events) {
|
|
296
|
+
if (isDelta(event)) {
|
|
297
|
+
if (!parts.has(event.id))
|
|
298
|
+
order.push(event.id);
|
|
299
|
+
parts.set(event.id, (parts.get(event.id) ?? "") + event.text);
|
|
300
|
+
}
|
|
301
|
+
if (isEnd(event) && event.text !== undefined) {
|
|
302
|
+
if (!parts.has(event.id))
|
|
303
|
+
order.push(event.id);
|
|
304
|
+
parts.set(event.id, event.text);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return order.map((id) => parts.get(id)).join("");
|
|
308
|
+
};
|
|
309
|
+
const responseText = (events) => joinFragments(events, LLMEvent.is.textDelta, LLMEvent.is.textEnd);
|
|
310
|
+
const responseReasoning = (events) => joinFragments(events, LLMEvent.is.reasoningDelta, LLMEvent.is.reasoningEnd);
|
|
311
|
+
const responseUsage = (events) => events.reduce((usage, event) => ("usage" in event && event.usage !== undefined ? event.usage : usage), undefined);
|
|
312
|
+
const emptyResponseState = () => ({
|
|
313
|
+
events: [],
|
|
314
|
+
message: Message.assistant([]),
|
|
315
|
+
textParts: {},
|
|
316
|
+
reasoningParts: {},
|
|
317
|
+
toolInputs: {},
|
|
318
|
+
});
|
|
319
|
+
const appendEvent = (state, event) => {
|
|
320
|
+
const events = [...state.events, event];
|
|
321
|
+
if (LLMEvent.is.finish(event)) {
|
|
322
|
+
return {
|
|
323
|
+
...state,
|
|
324
|
+
events,
|
|
325
|
+
usage: event.usage ?? state.usage,
|
|
326
|
+
finishReason: event.reason,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (LLMEvent.is.providerError(event)) {
|
|
330
|
+
return {
|
|
331
|
+
...state,
|
|
332
|
+
events,
|
|
333
|
+
finishReason: state.finishReason ?? { normalized: "error" },
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
...state,
|
|
338
|
+
events,
|
|
339
|
+
usage: "usage" in event && event.usage !== undefined ? event.usage : state.usage,
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
const textContent = (text, providerMetadata) => providerMetadata === undefined ? { type: "text", text } : { type: "text", text, providerMetadata };
|
|
343
|
+
const reasoningContent = (text, providerMetadata) => providerMetadata === undefined ? { type: "reasoning", text } : { type: "reasoning", text, providerMetadata };
|
|
344
|
+
const contentWith = (state, content) => ({
|
|
345
|
+
...state,
|
|
346
|
+
message: Message.assistant(content),
|
|
347
|
+
});
|
|
348
|
+
const appendContent = (state, part) => contentWith(state, [...state.message.content, part]);
|
|
349
|
+
const replaceContent = (state, index, part) => contentWith(state, state.message.content.map((item, itemIndex) => (itemIndex === index ? part : item)));
|
|
350
|
+
const ensureText = (state, id, providerMetadata) => {
|
|
351
|
+
if (state.textParts[id])
|
|
352
|
+
return state;
|
|
353
|
+
return {
|
|
354
|
+
...appendContent(state, textContent("", providerMetadata)),
|
|
355
|
+
textParts: {
|
|
356
|
+
...state.textParts,
|
|
357
|
+
[id]: { contentIndex: state.message.content.length, text: "", providerMetadata },
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
const reduceTextDelta = (state, event) => {
|
|
362
|
+
const started = ensureText(state, event.id, event.providerMetadata);
|
|
363
|
+
const current = started.textParts[event.id];
|
|
364
|
+
if (!current)
|
|
365
|
+
return started;
|
|
366
|
+
const text = current.text + event.text;
|
|
367
|
+
const providerMetadata = event.providerMetadata ?? current.providerMetadata;
|
|
368
|
+
return {
|
|
369
|
+
...replaceContent(started, current.contentIndex, textContent(text, providerMetadata)),
|
|
370
|
+
textParts: { ...started.textParts, [event.id]: { ...current, text, providerMetadata } },
|
|
371
|
+
};
|
|
372
|
+
};
|
|
373
|
+
const reduceTextEnd = (state, event) => {
|
|
374
|
+
const current = state.textParts[event.id];
|
|
375
|
+
if (!current)
|
|
376
|
+
return state;
|
|
377
|
+
const text = event.text ?? current.text;
|
|
378
|
+
const providerMetadata = event.providerMetadata ?? current.providerMetadata;
|
|
379
|
+
return {
|
|
380
|
+
...replaceContent(state, current.contentIndex, textContent(text, providerMetadata)),
|
|
381
|
+
textParts: { ...state.textParts, [event.id]: { ...current, text, providerMetadata } },
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
const ensureReasoning = (state, id, providerMetadata) => {
|
|
385
|
+
if (state.reasoningParts[id])
|
|
386
|
+
return state;
|
|
387
|
+
return {
|
|
388
|
+
...appendContent(state, reasoningContent("", providerMetadata)),
|
|
389
|
+
reasoningParts: {
|
|
390
|
+
...state.reasoningParts,
|
|
391
|
+
[id]: { contentIndex: state.message.content.length, text: "", providerMetadata },
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
};
|
|
395
|
+
const reduceReasoningDelta = (state, event) => {
|
|
396
|
+
const started = ensureReasoning(state, event.id, event.providerMetadata);
|
|
397
|
+
const current = started.reasoningParts[event.id];
|
|
398
|
+
if (!current)
|
|
399
|
+
return started;
|
|
400
|
+
const text = current.text + event.text;
|
|
401
|
+
const providerMetadata = event.providerMetadata ?? current.providerMetadata;
|
|
402
|
+
return {
|
|
403
|
+
...replaceContent(started, current.contentIndex, reasoningContent(text, providerMetadata)),
|
|
404
|
+
reasoningParts: { ...started.reasoningParts, [event.id]: { ...current, text, providerMetadata } },
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
const reduceReasoningEnd = (state, event) => {
|
|
408
|
+
const current = state.reasoningParts[event.id];
|
|
409
|
+
if (!current)
|
|
410
|
+
return state;
|
|
411
|
+
const text = event.text ?? current.text;
|
|
412
|
+
const providerMetadata = event.providerMetadata ?? current.providerMetadata;
|
|
413
|
+
return {
|
|
414
|
+
...replaceContent(state, current.contentIndex, reasoningContent(text, providerMetadata)),
|
|
415
|
+
reasoningParts: { ...state.reasoningParts, [event.id]: { ...current, text, providerMetadata } },
|
|
416
|
+
};
|
|
417
|
+
};
|
|
418
|
+
const reduceToolInputStart = (state, event) => ({
|
|
419
|
+
...state,
|
|
420
|
+
toolInputs: {
|
|
421
|
+
...state.toolInputs,
|
|
422
|
+
[event.id]: {
|
|
423
|
+
name: event.name,
|
|
424
|
+
namespace: event.namespace,
|
|
425
|
+
text: "",
|
|
426
|
+
providerMetadata: event.providerMetadata,
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
const reduceToolInputDelta = (state, event) => {
|
|
431
|
+
const current = state.toolInputs[event.id] ?? { name: event.name, namespace: event.namespace, text: "" };
|
|
432
|
+
return {
|
|
433
|
+
...state,
|
|
434
|
+
toolInputs: { ...state.toolInputs, [event.id]: { ...current, text: current.text + event.text } },
|
|
435
|
+
};
|
|
436
|
+
};
|
|
437
|
+
const reduceToolInputEnd = (state, event) => {
|
|
438
|
+
const current = state.toolInputs[event.id] ?? { name: event.name, namespace: event.namespace, text: "" };
|
|
439
|
+
return {
|
|
440
|
+
...state,
|
|
441
|
+
toolInputs: {
|
|
442
|
+
...state.toolInputs,
|
|
443
|
+
[event.id]: {
|
|
444
|
+
...current,
|
|
445
|
+
name: event.name,
|
|
446
|
+
namespace: event.namespace,
|
|
447
|
+
providerMetadata: event.providerMetadata ?? current.providerMetadata,
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
};
|
|
452
|
+
const toolCallContent = (event) => ToolCallPart.make({
|
|
453
|
+
id: event.id,
|
|
454
|
+
name: event.name,
|
|
455
|
+
namespace: event.namespace,
|
|
456
|
+
input: event.input,
|
|
457
|
+
...(event.providerExecuted === undefined ? {} : { providerExecuted: event.providerExecuted }),
|
|
458
|
+
...(event.providerMetadata === undefined ? {} : { providerMetadata: event.providerMetadata }),
|
|
459
|
+
});
|
|
460
|
+
const toolResultContent = (event) => ToolResultPart.make({
|
|
461
|
+
id: event.id,
|
|
462
|
+
name: event.name,
|
|
463
|
+
namespace: event.namespace,
|
|
464
|
+
result: event.result,
|
|
465
|
+
...(event.providerExecuted === undefined ? {} : { providerExecuted: event.providerExecuted }),
|
|
466
|
+
...(event.providerMetadata === undefined ? {} : { providerMetadata: event.providerMetadata }),
|
|
467
|
+
});
|
|
468
|
+
const reduceToolCall = (state, event) => {
|
|
469
|
+
const { [event.id]: _finished, ...toolInputs } = state.toolInputs;
|
|
470
|
+
return { ...appendContent(state, toolCallContent(event)), toolInputs };
|
|
471
|
+
};
|
|
472
|
+
const reduceResponseState = (state, event) => {
|
|
473
|
+
const next = appendEvent(state, event);
|
|
474
|
+
switch (event.type) {
|
|
475
|
+
case "compaction":
|
|
476
|
+
return appendContent(next, event);
|
|
477
|
+
case "text-start":
|
|
478
|
+
return ensureText(next, event.id, event.providerMetadata);
|
|
479
|
+
case "text-delta":
|
|
480
|
+
return reduceTextDelta(next, event);
|
|
481
|
+
case "text-end":
|
|
482
|
+
return reduceTextEnd(next, event);
|
|
483
|
+
case "reasoning-start":
|
|
484
|
+
return ensureReasoning(next, event.id, event.providerMetadata);
|
|
485
|
+
case "reasoning-delta":
|
|
486
|
+
return reduceReasoningDelta(next, event);
|
|
487
|
+
case "reasoning-end":
|
|
488
|
+
return reduceReasoningEnd(next, event);
|
|
489
|
+
case "tool-input-start":
|
|
490
|
+
return reduceToolInputStart(next, event);
|
|
491
|
+
case "tool-input-delta":
|
|
492
|
+
return reduceToolInputDelta(next, event);
|
|
493
|
+
case "tool-input-end":
|
|
494
|
+
return reduceToolInputEnd(next, event);
|
|
495
|
+
case "tool-input-error": {
|
|
496
|
+
const { [event.id]: _finished, ...toolInputs } = next.toolInputs;
|
|
497
|
+
return { ...next, toolInputs };
|
|
498
|
+
}
|
|
499
|
+
case "tool-call":
|
|
500
|
+
return reduceToolCall(next, event);
|
|
501
|
+
case "tool-result":
|
|
502
|
+
return appendContent(next, toolResultContent(event));
|
|
503
|
+
default:
|
|
504
|
+
return next;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
export class LLMResponse extends Schema.Class("LLM.Response")({
|
|
508
|
+
message: Message,
|
|
509
|
+
events: Schema.Array(LLMEvent),
|
|
510
|
+
usage: Schema.optional(Usage),
|
|
511
|
+
finishReason: FinishReasonDetails,
|
|
512
|
+
}) {
|
|
513
|
+
/** Concatenated assistant text; each fragment's `text-end` value replaces its accumulated deltas when present. */
|
|
514
|
+
get text() {
|
|
515
|
+
return responseText(this.events);
|
|
516
|
+
}
|
|
517
|
+
/** Concatenated reasoning text; each fragment's `reasoning-end` value replaces its accumulated deltas when present. */
|
|
518
|
+
get reasoning() {
|
|
519
|
+
return responseReasoning(this.events);
|
|
520
|
+
}
|
|
521
|
+
/** Completed tool calls emitted by the provider. */
|
|
522
|
+
get toolCalls() {
|
|
523
|
+
return this.events.filter(LLMEvent.is.toolCall);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
(function (LLMResponse) {
|
|
527
|
+
/** Initial reducer state for assembling one provider attempt. */
|
|
528
|
+
LLMResponse.empty = emptyResponseState;
|
|
529
|
+
/** Purely fold one provider-neutral event into the attempt assembly state. */
|
|
530
|
+
LLMResponse.reduce = reduceResponseState;
|
|
531
|
+
/** Return a completed response only after a terminal finish or provider error. */
|
|
532
|
+
LLMResponse.complete = (state) => state.finishReason === undefined
|
|
533
|
+
? undefined
|
|
534
|
+
: new LLMResponse({
|
|
535
|
+
message: state.message,
|
|
536
|
+
events: [...state.events],
|
|
537
|
+
usage: state.usage,
|
|
538
|
+
finishReason: state.finishReason,
|
|
539
|
+
});
|
|
540
|
+
/** Convenience reducer for callers that already have a collected event list. */
|
|
541
|
+
LLMResponse.fromEvents = (events) => LLMResponse.complete(events.reduce(LLMResponse.reduce, LLMResponse.empty()));
|
|
542
|
+
/** Concatenate assistant text from a response or collected event list. */
|
|
543
|
+
LLMResponse.text = (response) => responseText(response.events);
|
|
544
|
+
/** Return response usage, falling back to the latest usage-bearing event. */
|
|
545
|
+
LLMResponse.usage = (response) => response.usage ?? responseUsage(response.events);
|
|
546
|
+
/** Return completed tool calls from a response or collected event list. */
|
|
547
|
+
LLMResponse.toolCalls = (response) => response.events.filter(LLMEvent.is.toolCall);
|
|
548
|
+
/** Concatenate reasoning text from a response or collected event list. */
|
|
549
|
+
LLMResponse.reasoning = (response) => responseReasoning(response.events);
|
|
550
|
+
})(LLMResponse || (LLMResponse = {}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Stable string identifier for a protocol implementation. */
|
|
3
|
+
export declare const ProtocolID: Schema.String;
|
|
4
|
+
export type ProtocolID = Schema.Schema.Type<typeof ProtocolID>;
|
|
5
|
+
/** Stable string identifier for the runnable route. */
|
|
6
|
+
export declare const RouteID: Schema.String;
|
|
7
|
+
export type RouteID = Schema.Schema.Type<typeof RouteID>;
|
|
8
|
+
export declare const ModelID: Schema.brand<Schema.String, "AI.ModelID">;
|
|
9
|
+
export type ModelID = typeof ModelID.Type;
|
|
10
|
+
export declare const ProviderID: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
11
|
+
export type ProviderID = typeof ProviderID.Type;
|
|
12
|
+
export declare const ResponseID: Schema.String;
|
|
13
|
+
export type ResponseID = Schema.Schema.Type<typeof ResponseID>;
|
|
14
|
+
export declare const ContentBlockID: Schema.String;
|
|
15
|
+
export type ContentBlockID = Schema.Schema.Type<typeof ContentBlockID>;
|
|
16
|
+
export declare const ToolCallID: Schema.String;
|
|
17
|
+
export type ToolCallID = Schema.Schema.Type<typeof ToolCallID>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Stable string identifier for a protocol implementation. */
|
|
3
|
+
export const ProtocolID = Schema.String;
|
|
4
|
+
/** Stable string identifier for the runnable route. */
|
|
5
|
+
export const RouteID = Schema.String;
|
|
6
|
+
export const ModelID = Schema.String.pipe(Schema.brand("AI.ModelID"));
|
|
7
|
+
export const ProviderID = Schema.String.pipe(Schema.brand("AI.ProviderID"));
|
|
8
|
+
export const ResponseID = Schema.String;
|
|
9
|
+
export const ContentBlockID = Schema.String;
|
|
10
|
+
export const ToolCallID = Schema.String;
|