@opencode/ai 2.0.19 → 2.0.21
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/dist/cache-policy.js +21 -3
- package/dist/llm.d.ts +1 -1
- package/dist/promise.d.ts +2 -2
- package/dist/protocols/alibaba-chat.d.ts +16 -10
- package/dist/protocols/alibaba-responses.d.ts +14 -14
- package/dist/protocols/anthropic-messages.js +2 -15
- package/dist/protocols/bedrock-converse.d.ts +1 -1
- package/dist/protocols/bedrock-converse.js +38 -12
- package/dist/protocols/meta-messages.d.ts +5 -1
- package/dist/protocols/meta-messages.js +11 -4
- package/dist/protocols/meta-responses.d.ts +16 -16
- package/dist/protocols/mistral-chat.d.ts +6 -0
- package/dist/protocols/mistral-chat.js +8 -5
- package/dist/protocols/open-responses.d.ts +31 -31
- package/dist/protocols/openai-chat.d.ts +114 -71
- package/dist/protocols/openai-chat.js +31 -32
- package/dist/protocols/openai-compatible-chat.d.ts +16 -10
- package/dist/protocols/openai-compatible-responses.d.ts +2 -2
- package/dist/protocols/openai-responses.d.ts +22 -22
- package/dist/protocols/utils/claude-model.d.ts +8 -0
- package/dist/protocols/utils/claude-model.js +15 -0
- package/dist/protocols/utils/tool-stream.d.ts +3 -3
- package/dist/protocols/xai-responses.d.ts +14 -14
- package/dist/protocols/zai-chat.d.ts +16 -10
- package/dist/provider-error.d.ts +1 -0
- package/dist/provider-error.js +23 -1
- package/dist/providers/alibaba.d.ts +18 -12
- package/dist/providers/amazon-bedrock-mantle.d.ts +18 -12
- package/dist/providers/azure.d.ts +20 -14
- package/dist/providers/baseten.d.ts +32 -20
- package/dist/providers/cerebras.d.ts +32 -20
- package/dist/providers/cloudflare-ai-gateway.d.ts +36 -24
- package/dist/providers/cloudflare-ai-gateway.js +43 -35
- package/dist/providers/cloudflare-workers-ai.d.ts +32 -20
- package/dist/providers/deepinfra.d.ts +32 -20
- package/dist/providers/deepseek.d.ts +32 -20
- package/dist/providers/fireworks.d.ts +32 -20
- package/dist/providers/google-vertex-chat.d.ts +16 -10
- package/dist/providers/google-vertex-responses.d.ts +2 -2
- package/dist/providers/groq.d.ts +32 -20
- package/dist/providers/meta.d.ts +23 -13
- package/dist/providers/minimax.d.ts +18 -12
- package/dist/providers/moonshot.d.ts +18 -12
- package/dist/providers/openai-compatible-responses.d.ts +2 -2
- package/dist/providers/openai-compatible.d.ts +16 -10
- package/dist/providers/openai.d.ts +18 -12
- package/dist/providers/openrouter.d.ts +64 -40
- package/dist/providers/togetherai.d.ts +32 -20
- package/dist/providers/xai.d.ts +16 -10
- package/dist/providers/zai-coding-plan.d.ts +18 -12
- package/dist/providers/zai.d.ts +16 -10
- package/dist/route/client.d.ts +1 -1
- package/dist/route/executor.js +12 -8
- package/dist/schema/events.d.ts +30 -30
- package/dist/testing.d.ts +8 -8
- package/package.json +3 -3
package/dist/cache-policy.js
CHANGED
|
@@ -36,12 +36,30 @@ const resolve = (policy) => {
|
|
|
36
36
|
// prefix caching, Gemini's implicit + out-of-band CachedContent). Skip the
|
|
37
37
|
// whole policy pass for these — emitting hints would be harmless but pointless.
|
|
38
38
|
const RESPECTS_INLINE_HINTS = new Set([
|
|
39
|
+
"alibaba-messages",
|
|
39
40
|
"anthropic-messages",
|
|
40
41
|
"anthropic-compatible-messages",
|
|
42
|
+
"cloudflare-ai-gateway-messages",
|
|
41
43
|
"google-vertex-messages",
|
|
44
|
+
"meta-messages",
|
|
45
|
+
"minimax-messages",
|
|
46
|
+
"moonshot-messages",
|
|
47
|
+
"zai-coding-messages",
|
|
42
48
|
"bedrock-converse",
|
|
43
49
|
"openrouter",
|
|
44
50
|
]);
|
|
51
|
+
// OpenRouter upstreams other than Anthropic and Alibaba Qwen cache without breakpoints. Gemini uses only the last
|
|
52
|
+
// breakpoint, so a conversation-tail breakpoint writes a new cache every step and costs more than none. Qwen ignores
|
|
53
|
+
// breakpoints on tool definitions and caches tools with the system prompt.
|
|
54
|
+
const openRouterPolicy = (modelID) => {
|
|
55
|
+
// `~anthropic/claude-sonnet-latest` style IDs are OpenRouter aliases for the latest model in a family.
|
|
56
|
+
const id = modelID.replace(/^~/, "");
|
|
57
|
+
if (id.startsWith("anthropic/"))
|
|
58
|
+
return AUTO;
|
|
59
|
+
if (id.startsWith("qwen/"))
|
|
60
|
+
return { system: true, messages: { tail: 1 } };
|
|
61
|
+
return NONE;
|
|
62
|
+
};
|
|
45
63
|
const makeHint = (ttlSeconds) => ttlSeconds !== undefined ? new CacheHint({ type: "ephemeral", ttlSeconds }) : new CacheHint({ type: "ephemeral" });
|
|
46
64
|
const markLastTool = (tools, hint, budget) => {
|
|
47
65
|
const target = tools.at(-1);
|
|
@@ -122,9 +140,9 @@ const countHints = (request) => countToolHints(request.tools) +
|
|
|
122
140
|
export const applyCachePolicy = (request) => {
|
|
123
141
|
if (!RESPECTS_INLINE_HINTS.has(request.model.route.id))
|
|
124
142
|
return request;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
const policy = request.model.route.id === "openrouter" && (request.cache === undefined || request.cache === "auto")
|
|
144
|
+
? openRouterPolicy(request.model.id)
|
|
145
|
+
: resolve(request.cache);
|
|
128
146
|
if (!policy.tools && !policy.system && !policy.messages)
|
|
129
147
|
return request;
|
|
130
148
|
const hint = makeHint(policy.ttlSeconds);
|
package/dist/llm.d.ts
CHANGED
|
@@ -184,8 +184,8 @@ export declare class GenerateObjectResponse<T> {
|
|
|
184
184
|
} | {
|
|
185
185
|
readonly id: string;
|
|
186
186
|
readonly type: "tool-error";
|
|
187
|
-
readonly name: string;
|
|
188
187
|
readonly message: string;
|
|
188
|
+
readonly name: string;
|
|
189
189
|
readonly error?: unknown;
|
|
190
190
|
readonly providerMetadata?: {
|
|
191
191
|
readonly [x: string]: {
|
package/dist/promise.d.ts
CHANGED
|
@@ -211,8 +211,8 @@ export declare const make: (options?: Options) => {
|
|
|
211
211
|
} | {
|
|
212
212
|
readonly id: string;
|
|
213
213
|
readonly type: "tool-error";
|
|
214
|
-
readonly name: string;
|
|
215
214
|
readonly message: string;
|
|
215
|
+
readonly name: string;
|
|
216
216
|
readonly error?: unknown;
|
|
217
217
|
readonly providerMetadata?: {
|
|
218
218
|
readonly [x: string]: {
|
|
@@ -698,8 +698,8 @@ export declare const ai: {
|
|
|
698
698
|
} | {
|
|
699
699
|
readonly id: string;
|
|
700
700
|
readonly type: "tool-error";
|
|
701
|
-
readonly name: string;
|
|
702
701
|
readonly message: string;
|
|
702
|
+
readonly name: string;
|
|
703
703
|
readonly error?: unknown;
|
|
704
704
|
readonly providerMetadata?: {
|
|
705
705
|
readonly [x: string]: {
|
|
@@ -80,15 +80,18 @@ export declare const protocol: Protocol<{
|
|
|
80
80
|
})[];
|
|
81
81
|
} | {
|
|
82
82
|
readonly [x: string]: unknown;
|
|
83
|
-
readonly content: string |
|
|
83
|
+
readonly content: string | readonly {
|
|
84
|
+
readonly type: "text";
|
|
85
|
+
readonly text: string;
|
|
86
|
+
readonly cache_control?: {
|
|
87
|
+
readonly type: "ephemeral";
|
|
88
|
+
readonly ttl?: string | undefined;
|
|
89
|
+
} | undefined;
|
|
90
|
+
}[] | null;
|
|
84
91
|
readonly role: "assistant";
|
|
85
92
|
readonly reasoning?: string | undefined;
|
|
86
93
|
readonly reasoning_content?: string | undefined;
|
|
87
94
|
readonly reasoning_text?: string | undefined;
|
|
88
|
-
readonly cache_control?: {
|
|
89
|
-
readonly type: "ephemeral";
|
|
90
|
-
readonly ttl?: string | undefined;
|
|
91
|
-
} | undefined;
|
|
92
95
|
readonly tool_calls?: readonly {
|
|
93
96
|
readonly function: {
|
|
94
97
|
readonly name: string;
|
|
@@ -104,13 +107,16 @@ export declare const protocol: Protocol<{
|
|
|
104
107
|
}[] | undefined;
|
|
105
108
|
readonly reasoning_details?: unknown;
|
|
106
109
|
} | {
|
|
107
|
-
readonly content: string;
|
|
108
110
|
readonly role: "tool";
|
|
109
111
|
readonly tool_call_id: string;
|
|
110
|
-
readonly
|
|
111
|
-
readonly type: "
|
|
112
|
-
readonly
|
|
113
|
-
|
|
112
|
+
readonly content: string | readonly {
|
|
113
|
+
readonly type: "text";
|
|
114
|
+
readonly text: string;
|
|
115
|
+
readonly cache_control?: {
|
|
116
|
+
readonly type: "ephemeral";
|
|
117
|
+
readonly ttl?: string | undefined;
|
|
118
|
+
} | undefined;
|
|
119
|
+
}[];
|
|
114
120
|
})[];
|
|
115
121
|
readonly stream: true;
|
|
116
122
|
readonly max_completion_tokens?: number | undefined;
|
|
@@ -77,8 +77,8 @@ export declare const protocol: Protocol<{
|
|
|
77
77
|
} | {
|
|
78
78
|
readonly type: "input_file";
|
|
79
79
|
readonly filename: string;
|
|
80
|
-
readonly file_data?: string | undefined;
|
|
81
80
|
readonly detail?: string | undefined;
|
|
81
|
+
readonly file_data?: string | undefined;
|
|
82
82
|
readonly file_url?: string | undefined;
|
|
83
83
|
} | {
|
|
84
84
|
readonly type: "input_text";
|
|
@@ -114,8 +114,8 @@ export declare const protocol: Protocol<{
|
|
|
114
114
|
} | {
|
|
115
115
|
readonly type: "input_file";
|
|
116
116
|
readonly filename: string;
|
|
117
|
-
readonly file_data?: string | undefined;
|
|
118
117
|
readonly detail?: string | undefined;
|
|
118
|
+
readonly file_data?: string | undefined;
|
|
119
119
|
readonly file_url?: string | undefined;
|
|
120
120
|
} | {
|
|
121
121
|
readonly type: "input_text";
|
|
@@ -190,21 +190,10 @@ export declare const protocol: Protocol<{
|
|
|
190
190
|
readonly [x: string]: unknown;
|
|
191
191
|
readonly type: string;
|
|
192
192
|
readonly status?: unknown;
|
|
193
|
-
readonly code?: unknown;
|
|
194
193
|
readonly message?: unknown;
|
|
194
|
+
readonly code?: unknown;
|
|
195
195
|
readonly text?: string | undefined;
|
|
196
196
|
readonly error?: unknown;
|
|
197
|
-
readonly item?: {
|
|
198
|
-
readonly [x: string]: unknown;
|
|
199
|
-
readonly type: string;
|
|
200
|
-
readonly id?: string | undefined;
|
|
201
|
-
readonly name?: string | undefined;
|
|
202
|
-
readonly namespace?: string | undefined;
|
|
203
|
-
readonly arguments?: string | undefined;
|
|
204
|
-
readonly encrypted_content?: string | null | undefined;
|
|
205
|
-
readonly call_id?: string | undefined;
|
|
206
|
-
} | null | undefined;
|
|
207
|
-
readonly delta?: string | undefined;
|
|
208
197
|
readonly response?: {
|
|
209
198
|
readonly [x: string]: unknown;
|
|
210
199
|
readonly id?: string | undefined;
|
|
@@ -236,6 +225,17 @@ export declare const protocol: Protocol<{
|
|
|
236
225
|
readonly reason?: string | undefined;
|
|
237
226
|
} | null | undefined;
|
|
238
227
|
} | undefined;
|
|
228
|
+
readonly item?: {
|
|
229
|
+
readonly [x: string]: unknown;
|
|
230
|
+
readonly type: string;
|
|
231
|
+
readonly id?: string | undefined;
|
|
232
|
+
readonly name?: string | undefined;
|
|
233
|
+
readonly namespace?: string | undefined;
|
|
234
|
+
readonly arguments?: string | undefined;
|
|
235
|
+
readonly encrypted_content?: string | null | undefined;
|
|
236
|
+
readonly call_id?: string | undefined;
|
|
237
|
+
} | null | undefined;
|
|
238
|
+
readonly delta?: string | undefined;
|
|
239
239
|
readonly arguments?: string | undefined;
|
|
240
240
|
readonly item_id?: string | undefined;
|
|
241
241
|
readonly output_index?: number | undefined;
|
|
@@ -13,6 +13,7 @@ import { JsonObject, knownString, optionalArray, optionalNull, ProviderShared }
|
|
|
13
13
|
import { classifyProviderFailure } from "../provider-error.js";
|
|
14
14
|
import { effortUpdate, resolveEffortUpdates } from "../effort-updates.js";
|
|
15
15
|
import * as Cache from "./utils/cache.js";
|
|
16
|
+
import { claudeVersion, supportsThinkingBlockBinding, THINKING_BINDING_BETA } from "./utils/claude-model.js";
|
|
16
17
|
import { Lifecycle } from "./utils/lifecycle.js";
|
|
17
18
|
import { ToolStream } from "./utils/tool-stream.js";
|
|
18
19
|
const ADAPTER = "anthropic-messages";
|
|
@@ -850,20 +851,6 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (re
|
|
|
850
851
|
}
|
|
851
852
|
return messages;
|
|
852
853
|
});
|
|
853
|
-
// Accept gateway namespaces and Vertex suffixes without treating a snapshot date as a minor version.
|
|
854
|
-
const claudeVersion = (id) => {
|
|
855
|
-
const match = /(?:^|[./])claude-(?<family>[a-z]+)-(?<major>\d+)(?:[.-](?<minor>\d{1,2}))?(?:$|[-:@])/.exec(id.toLowerCase())?.groups;
|
|
856
|
-
if (!match)
|
|
857
|
-
return undefined;
|
|
858
|
-
return { family: match.family, major: Number(match.major), minor: Number(match.minor ?? 0) };
|
|
859
|
-
};
|
|
860
|
-
const supportsThinkingBlockBinding = (model) => {
|
|
861
|
-
const override = model.compatibility?.supportsThinkingBlockBinding;
|
|
862
|
-
if (override !== undefined)
|
|
863
|
-
return override;
|
|
864
|
-
const version = claudeVersion(model.id);
|
|
865
|
-
return version !== undefined && (version.major > 5 || (version.major === 5 && version.minor >= 1));
|
|
866
|
-
};
|
|
867
854
|
const supportsEffortUpdates = (model) => {
|
|
868
855
|
const override = model.compatibility?.supportsEffortUpdates;
|
|
869
856
|
if (override !== undefined)
|
|
@@ -1437,7 +1424,7 @@ function requiredBetaHeaders(body) {
|
|
|
1437
1424
|
betas.push("mid-conversation-output-config-2026-07-01");
|
|
1438
1425
|
const thinking = body.thinking;
|
|
1439
1426
|
if (thinking && thinking.type !== "disabled" && thinking.block_binding)
|
|
1440
|
-
betas.push(
|
|
1427
|
+
betas.push(THINKING_BINDING_BETA);
|
|
1441
1428
|
return betas;
|
|
1442
1429
|
}
|
|
1443
1430
|
export const route = Route.make({
|
|
@@ -141,7 +141,7 @@ interface ParserState {
|
|
|
141
141
|
readonly hasToolCalls: boolean;
|
|
142
142
|
readonly lifecycle: Lifecycle.State;
|
|
143
143
|
readonly reasoningSignatures: Readonly<Record<number, string>>;
|
|
144
|
-
readonly reasoningRedactedContent: Readonly<Record<number,
|
|
144
|
+
readonly reasoningRedactedContent: Readonly<Record<number, Uint8Array[]>>;
|
|
145
145
|
}
|
|
146
146
|
/**
|
|
147
147
|
* The Bedrock Converse protocol — request body construction, body schema, and
|
|
@@ -9,6 +9,7 @@ import { JsonObject, optionalArray, ProviderShared } from "./shared.js";
|
|
|
9
9
|
import { BedrockAuth } from "./utils/bedrock-auth.js";
|
|
10
10
|
import { BedrockCache } from "./utils/bedrock-cache.js";
|
|
11
11
|
import { BedrockMedia } from "./utils/bedrock-media.js";
|
|
12
|
+
import { supportsThinkingBlockBinding, THINKING_BINDING_BETA } from "./utils/claude-model.js";
|
|
12
13
|
import { Lifecycle } from "./utils/lifecycle.js";
|
|
13
14
|
import { MistralToolID } from "./utils/mistral-tool-id.js";
|
|
14
15
|
import { ToolStream } from "./utils/tool-stream.js";
|
|
@@ -351,18 +352,33 @@ const Options = Schema.Struct({
|
|
|
351
352
|
const decodeOptions = ProviderShared.validateWith(Schema.decodeUnknownEffect(Options));
|
|
352
353
|
// Claude on Bedrock requires the thinking budget below `maxTokens`, with a minimum of 1,024.
|
|
353
354
|
const MIN_THINKING_BUDGET = 1_024;
|
|
355
|
+
const isThinkingDisabled = Schema.is(Schema.Struct({
|
|
356
|
+
additionalModelRequestFields: Schema.Struct({ thinking: Schema.Struct({ type: Schema.Literal("disabled") }) }),
|
|
357
|
+
}));
|
|
358
|
+
// Claude 5.1+ binds each thinking signature to the prefix above it. Ask Bedrock to drop the affected blocks instead of
|
|
359
|
+
// failing when that prefix changes. `http.body` overlays this field by field, so callers can still override it.
|
|
360
|
+
const applyThinkingBindingDefault = (request, thinking) => {
|
|
361
|
+
if (isThinkingDisabled(request.http?.body))
|
|
362
|
+
return thinking;
|
|
363
|
+
if (!supportsThinkingBlockBinding(request.model))
|
|
364
|
+
return thinking;
|
|
365
|
+
return {
|
|
366
|
+
...(thinking ?? { type: "adaptive" }),
|
|
367
|
+
block_binding: { prefix_mismatch_behavior: "drop_block" },
|
|
368
|
+
};
|
|
369
|
+
};
|
|
354
370
|
const fromRequest = Effect.fn("BedrockConverse.fromRequest")(function* (request) {
|
|
355
371
|
const toolChoice = request.toolChoice ? yield* lowerToolChoice(request.toolChoice) : undefined;
|
|
356
372
|
const flattened = ProviderShared.flattenToolRequest(request);
|
|
357
373
|
const generation = request.generation;
|
|
358
374
|
const options = yield* decodeOptions(request.providerOptions ?? {});
|
|
359
375
|
const maxTokens = isNova2(request.model) && isHighReasoningEffort(request.http?.body) ? undefined : generation?.maxTokens;
|
|
360
|
-
const thinking = options.thinking === undefined
|
|
376
|
+
const thinking = applyThinkingBindingDefault(request, options.thinking === undefined
|
|
361
377
|
? undefined
|
|
362
378
|
: {
|
|
363
379
|
type: "enabled",
|
|
364
380
|
budget_tokens: ProviderShared.fitThinkingBudget(options.thinking.budgetTokens, maxTokens, MIN_THINKING_BUDGET),
|
|
365
|
-
};
|
|
381
|
+
});
|
|
366
382
|
// Bedrock-Claude shares Anthropic's 4-breakpoint cap. Spend the budget in
|
|
367
383
|
// tools → system → messages order to favour the highest-impact prefixes.
|
|
368
384
|
const breakpoints = BedrockCache.breakpoints(request.model.id);
|
|
@@ -407,6 +423,8 @@ const fromRequest = Effect.fn("BedrockConverse.fromRequest")(function* (request)
|
|
|
407
423
|
: {
|
|
408
424
|
...(generation?.topK === undefined ? {} : { top_k: generation.topK }),
|
|
409
425
|
...(thinking === undefined ? {} : { thinking }),
|
|
426
|
+
// Converse takes Anthropic betas in the body, and Bedrock rejects `block_binding` without this one.
|
|
427
|
+
...(thinking?.block_binding === undefined ? {} : { anthropic_beta: [THINKING_BINDING_BETA] }),
|
|
410
428
|
},
|
|
411
429
|
};
|
|
412
430
|
});
|
|
@@ -478,25 +496,29 @@ const step = (state, event) => Effect.gen(function* () {
|
|
|
478
496
|
const index = event.contentBlockDelta.contentBlockIndex;
|
|
479
497
|
const reasoning = event.contentBlockDelta.delta.reasoningContent;
|
|
480
498
|
const events = [];
|
|
481
|
-
const
|
|
499
|
+
const redactedChunk = yield* (() => {
|
|
482
500
|
if (reasoning.redactedContent === undefined)
|
|
483
501
|
return Effect.succeed(undefined);
|
|
484
|
-
return Effect.fromResult(Encoding.decodeBase64(reasoning.redactedContent)).pipe(Effect.
|
|
502
|
+
return Effect.fromResult(Encoding.decodeBase64(reasoning.redactedContent)).pipe(Effect.mapError((cause) => ProviderShared.eventError(ADAPTER, "Bedrock Converse reasoningContent.redactedContent contains invalid base64 data", undefined, cause)));
|
|
485
503
|
})();
|
|
486
|
-
const
|
|
504
|
+
const redactedChunks = state.reasoningRedactedContent[index] ?? [];
|
|
505
|
+
if (redactedChunk !== undefined)
|
|
506
|
+
redactedChunks.push(redactedChunk);
|
|
487
507
|
const metadata = (() => {
|
|
488
508
|
if (reasoning.signature)
|
|
489
509
|
return providerMetadata(state.providerMetadataKey, { signature: reasoning.signature });
|
|
490
|
-
if (
|
|
491
|
-
return providerMetadata(state.providerMetadataKey, { redactedData });
|
|
510
|
+
if (redactedChunk === undefined && reasoning.data !== undefined)
|
|
511
|
+
return providerMetadata(state.providerMetadataKey, { redactedData: reasoning.data });
|
|
492
512
|
})();
|
|
493
513
|
const lifecycle = (() => {
|
|
494
|
-
if (reasoning.text
|
|
495
|
-
return state.lifecycle;
|
|
496
|
-
|
|
514
|
+
if (reasoning.text !== undefined || metadata !== undefined)
|
|
515
|
+
return Lifecycle.reasoningDelta(state.lifecycle, events, `reasoning-${index}`, reasoning.text ?? "", metadata);
|
|
516
|
+
if (redactedChunk !== undefined)
|
|
517
|
+
return Lifecycle.reasoningStart(state.lifecycle, events, `reasoning-${index}`);
|
|
518
|
+
return state.lifecycle;
|
|
497
519
|
})();
|
|
498
520
|
const reasoningRedactedContent = (() => {
|
|
499
|
-
if (
|
|
521
|
+
if (redactedChunk !== undefined)
|
|
500
522
|
return { ...state.reasoningRedactedContent, [index]: redactedChunks };
|
|
501
523
|
if (reasoning.data === undefined)
|
|
502
524
|
return state.reasoningRedactedContent;
|
|
@@ -609,7 +631,11 @@ const onHalt = (state) => {
|
|
|
609
631
|
return state.finishReason.normalized;
|
|
610
632
|
})();
|
|
611
633
|
const events = [];
|
|
612
|
-
|
|
634
|
+
const lifecycle = Object.entries(state.reasoningRedactedContent).reduce((current, [index, chunks]) => {
|
|
635
|
+
const signature = state.reasoningSignatures[Number(index)];
|
|
636
|
+
return Lifecycle.reasoningEnd(current, events, `reasoning-${index}`, providerMetadata(state.providerMetadataKey, signature ? { signature } : { redactedData: encodeRedactedContent(chunks) }));
|
|
637
|
+
}, state.lifecycle);
|
|
638
|
+
Lifecycle.finish(lifecycle, events, {
|
|
613
639
|
reason: {
|
|
614
640
|
...state.finishReason,
|
|
615
641
|
normalized,
|
|
@@ -203,11 +203,15 @@ export declare const protocol: Protocol<{
|
|
|
203
203
|
readonly timezone?: string | undefined;
|
|
204
204
|
} | undefined;
|
|
205
205
|
} | {
|
|
206
|
-
readonly name: string;
|
|
207
206
|
readonly description: string;
|
|
207
|
+
readonly name: string;
|
|
208
208
|
readonly input_schema: {
|
|
209
209
|
readonly [x: string]: unknown;
|
|
210
210
|
};
|
|
211
|
+
readonly cache_control?: {
|
|
212
|
+
readonly type: "ephemeral";
|
|
213
|
+
readonly ttl?: "1h" | "5m" | undefined;
|
|
214
|
+
} | undefined;
|
|
211
215
|
})[] | undefined;
|
|
212
216
|
readonly system?: readonly {
|
|
213
217
|
readonly type: "text";
|
|
@@ -8,12 +8,19 @@ const WebSearch = Schema.Struct({
|
|
|
8
8
|
name: Schema.Literal("web_search"),
|
|
9
9
|
user_location: MetaResponses.WebSearch.fields.user_location,
|
|
10
10
|
});
|
|
11
|
+
const MetaCacheControl = Schema.Struct({
|
|
12
|
+
type: Schema.tag("ephemeral"),
|
|
13
|
+
ttl: Schema.optional(Schema.Literals(["5m", "1h"])),
|
|
14
|
+
});
|
|
15
|
+
const FunctionTool = Schema.Struct({
|
|
16
|
+
name: Schema.String,
|
|
17
|
+
description: Schema.String,
|
|
18
|
+
input_schema: JsonObject,
|
|
19
|
+
cache_control: Schema.optional(MetaCacheControl),
|
|
20
|
+
});
|
|
11
21
|
const Body = Schema.Struct({
|
|
12
22
|
...AnthropicMessages.AnthropicMessagesBody.fields,
|
|
13
|
-
tools: optionalArray(Schema.Union([
|
|
14
|
-
Schema.Struct({ name: Schema.String, description: Schema.String, input_schema: JsonObject }),
|
|
15
|
-
WebSearch,
|
|
16
|
-
])),
|
|
23
|
+
tools: optionalArray(Schema.Union([FunctionTool, WebSearch])),
|
|
17
24
|
});
|
|
18
25
|
const fromRequest = Effect.fn("MetaMessages.fromRequest")(function* (request) {
|
|
19
26
|
const projected = ProviderShared.flattenToolRequest(request);
|
|
@@ -92,8 +92,8 @@ export declare const protocol: Protocol<{
|
|
|
92
92
|
} | {
|
|
93
93
|
readonly type: "input_file";
|
|
94
94
|
readonly filename: string;
|
|
95
|
-
readonly file_data?: string | undefined;
|
|
96
95
|
readonly detail?: string | undefined;
|
|
96
|
+
readonly file_data?: string | undefined;
|
|
97
97
|
readonly file_url?: string | undefined;
|
|
98
98
|
} | {
|
|
99
99
|
readonly type: "input_text";
|
|
@@ -129,8 +129,8 @@ export declare const protocol: Protocol<{
|
|
|
129
129
|
} | {
|
|
130
130
|
readonly type: "input_file";
|
|
131
131
|
readonly filename: string;
|
|
132
|
-
readonly file_data?: string | undefined;
|
|
133
132
|
readonly detail?: string | undefined;
|
|
133
|
+
readonly file_data?: string | undefined;
|
|
134
134
|
readonly file_url?: string | undefined;
|
|
135
135
|
} | {
|
|
136
136
|
readonly type: "input_text";
|
|
@@ -219,21 +219,10 @@ export declare const protocol: Protocol<{
|
|
|
219
219
|
readonly [x: string]: unknown;
|
|
220
220
|
readonly type: string;
|
|
221
221
|
readonly status?: unknown;
|
|
222
|
-
readonly code?: unknown;
|
|
223
222
|
readonly message?: unknown;
|
|
223
|
+
readonly code?: unknown;
|
|
224
224
|
readonly text?: string | undefined;
|
|
225
225
|
readonly error?: unknown;
|
|
226
|
-
readonly item?: {
|
|
227
|
-
readonly [x: string]: unknown;
|
|
228
|
-
readonly type: string;
|
|
229
|
-
readonly id?: string | undefined;
|
|
230
|
-
readonly name?: string | undefined;
|
|
231
|
-
readonly namespace?: string | undefined;
|
|
232
|
-
readonly arguments?: string | undefined;
|
|
233
|
-
readonly encrypted_content?: string | null | undefined;
|
|
234
|
-
readonly call_id?: string | undefined;
|
|
235
|
-
} | null | undefined;
|
|
236
|
-
readonly delta?: string | undefined;
|
|
237
226
|
readonly response?: {
|
|
238
227
|
readonly [x: string]: unknown;
|
|
239
228
|
readonly id?: string | undefined;
|
|
@@ -265,6 +254,17 @@ export declare const protocol: Protocol<{
|
|
|
265
254
|
readonly reason?: string | undefined;
|
|
266
255
|
} | null | undefined;
|
|
267
256
|
} | undefined;
|
|
257
|
+
readonly item?: {
|
|
258
|
+
readonly [x: string]: unknown;
|
|
259
|
+
readonly type: string;
|
|
260
|
+
readonly id?: string | undefined;
|
|
261
|
+
readonly name?: string | undefined;
|
|
262
|
+
readonly namespace?: string | undefined;
|
|
263
|
+
readonly arguments?: string | undefined;
|
|
264
|
+
readonly encrypted_content?: string | null | undefined;
|
|
265
|
+
readonly call_id?: string | undefined;
|
|
266
|
+
} | null | undefined;
|
|
267
|
+
readonly delta?: string | undefined;
|
|
268
268
|
readonly arguments?: string | undefined;
|
|
269
269
|
readonly item_id?: string | undefined;
|
|
270
270
|
readonly output_index?: number | undefined;
|
|
@@ -338,8 +338,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
338
338
|
} | {
|
|
339
339
|
readonly type: "input_file";
|
|
340
340
|
readonly filename: string;
|
|
341
|
-
readonly file_data?: string | undefined;
|
|
342
341
|
readonly detail?: string | undefined;
|
|
342
|
+
readonly file_data?: string | undefined;
|
|
343
343
|
readonly file_url?: string | undefined;
|
|
344
344
|
} | {
|
|
345
345
|
readonly type: "input_text";
|
|
@@ -375,8 +375,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
375
375
|
} | {
|
|
376
376
|
readonly type: "input_file";
|
|
377
377
|
readonly filename: string;
|
|
378
|
-
readonly file_data?: string | undefined;
|
|
379
378
|
readonly detail?: string | undefined;
|
|
379
|
+
readonly file_data?: string | undefined;
|
|
380
380
|
readonly file_url?: string | undefined;
|
|
381
381
|
} | {
|
|
382
382
|
readonly type: "input_text";
|
|
@@ -8,6 +8,11 @@ import { Lifecycle } from "./utils/lifecycle.js";
|
|
|
8
8
|
import { ToolStream } from "./utils/tool-stream.js";
|
|
9
9
|
export declare const DEFAULT_BASE_URL = "https://api.mistral.ai/v1";
|
|
10
10
|
export declare const PATH = "/chat/completions";
|
|
11
|
+
declare const MistralThinkingUnit: Schema.StructWithRest<Schema.Struct<{
|
|
12
|
+
readonly type: Schema.optional<Schema.String>;
|
|
13
|
+
readonly text: Schema.optional<Schema.String>;
|
|
14
|
+
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>;
|
|
15
|
+
type MistralThinkingUnit = Schema.Schema.Type<typeof MistralThinkingUnit>;
|
|
11
16
|
declare const MistralThinkingContent: Schema.StructWithRest<Schema.Struct<{
|
|
12
17
|
readonly type: Schema.Literal<"thinking">;
|
|
13
18
|
readonly thinking: Schema.$Array<Schema.StructWithRest<Schema.Struct<{
|
|
@@ -212,6 +217,7 @@ interface ActiveContent {
|
|
|
212
217
|
readonly type: "text" | "reasoning";
|
|
213
218
|
readonly id: string;
|
|
214
219
|
readonly thinking?: MistralThinkingContent;
|
|
220
|
+
readonly thinkingUnits?: MistralThinkingUnit[];
|
|
215
221
|
}
|
|
216
222
|
export interface ParserState {
|
|
217
223
|
readonly tools: ToolStream.State<ToolKey>;
|
|
@@ -365,7 +365,7 @@ const closeActive = (state, events) => {
|
|
|
365
365
|
return state;
|
|
366
366
|
const lifecycle = state.active.type === "text"
|
|
367
367
|
? Lifecycle.textEnd(state.lifecycle, events, state.active.id)
|
|
368
|
-
: Lifecycle.reasoningEnd(state.lifecycle, events, state.active.id, thinkingMetadata(state.active.thinking
|
|
368
|
+
: Lifecycle.reasoningEnd(state.lifecycle, events, state.active.id, thinkingMetadata({ ...state.active.thinking, type: "thinking", thinking: state.active.thinkingUnits ?? [] }), thinkingText(state.active.thinkingUnits ?? []));
|
|
369
369
|
return { ...state, lifecycle, active: undefined };
|
|
370
370
|
};
|
|
371
371
|
const appendText = (state, events, text) => {
|
|
@@ -384,19 +384,22 @@ const appendThinking = (state, events, part) => {
|
|
|
384
384
|
const current = state.active?.type === "reasoning" ? state : closeActive(state, events);
|
|
385
385
|
const units = thinkingUnits(part.thinking);
|
|
386
386
|
const active = current.active ?? { type: "reasoning", id: `reasoning-${current.nextContent}` };
|
|
387
|
+
// Keep native units out of streamed events until the block is complete.
|
|
388
|
+
const accumulated = active.thinkingUnits ?? [];
|
|
389
|
+
accumulated.push(...units);
|
|
387
390
|
const thinking = {
|
|
388
391
|
...active.thinking,
|
|
389
392
|
...part,
|
|
390
393
|
type: "thinking",
|
|
391
|
-
thinking: [
|
|
394
|
+
thinking: [],
|
|
392
395
|
};
|
|
393
396
|
const text = thinkingText(units);
|
|
394
397
|
return {
|
|
395
398
|
...current,
|
|
396
399
|
lifecycle: text.length > 0
|
|
397
|
-
? Lifecycle.reasoningDelta(current.lifecycle, events, active.id, text
|
|
398
|
-
: Lifecycle.reasoningStart(current.lifecycle, events, active.id
|
|
399
|
-
active: { ...active, thinking },
|
|
400
|
+
? Lifecycle.reasoningDelta(current.lifecycle, events, active.id, text)
|
|
401
|
+
: Lifecycle.reasoningStart(current.lifecycle, events, active.id),
|
|
402
|
+
active: { ...active, thinking, thinkingUnits: accumulated },
|
|
400
403
|
nextContent: current.active ? current.nextContent : current.nextContent + 1,
|
|
401
404
|
};
|
|
402
405
|
};
|
|
@@ -629,21 +629,10 @@ export declare const decodeChannelEvent: (frame: string) => Effect.Effect<{
|
|
|
629
629
|
readonly [x: string]: unknown;
|
|
630
630
|
readonly type: string;
|
|
631
631
|
readonly status?: unknown;
|
|
632
|
-
readonly code?: unknown;
|
|
633
632
|
readonly message?: unknown;
|
|
633
|
+
readonly code?: unknown;
|
|
634
634
|
readonly text?: string | undefined;
|
|
635
635
|
readonly error?: unknown;
|
|
636
|
-
readonly item?: {
|
|
637
|
-
readonly [x: string]: unknown;
|
|
638
|
-
readonly type: string;
|
|
639
|
-
readonly id?: string | undefined;
|
|
640
|
-
readonly name?: string | undefined;
|
|
641
|
-
readonly namespace?: string | undefined;
|
|
642
|
-
readonly arguments?: string | undefined;
|
|
643
|
-
readonly encrypted_content?: string | null | undefined;
|
|
644
|
-
readonly call_id?: string | undefined;
|
|
645
|
-
} | null | undefined;
|
|
646
|
-
readonly delta?: string | undefined;
|
|
647
636
|
readonly response?: {
|
|
648
637
|
readonly [x: string]: unknown;
|
|
649
638
|
readonly id?: string | undefined;
|
|
@@ -675,6 +664,17 @@ export declare const decodeChannelEvent: (frame: string) => Effect.Effect<{
|
|
|
675
664
|
readonly reason?: string | undefined;
|
|
676
665
|
} | null | undefined;
|
|
677
666
|
} | undefined;
|
|
667
|
+
readonly item?: {
|
|
668
|
+
readonly [x: string]: unknown;
|
|
669
|
+
readonly type: string;
|
|
670
|
+
readonly id?: string | undefined;
|
|
671
|
+
readonly name?: string | undefined;
|
|
672
|
+
readonly namespace?: string | undefined;
|
|
673
|
+
readonly arguments?: string | undefined;
|
|
674
|
+
readonly encrypted_content?: string | null | undefined;
|
|
675
|
+
readonly call_id?: string | undefined;
|
|
676
|
+
} | null | undefined;
|
|
677
|
+
readonly delta?: string | undefined;
|
|
678
678
|
readonly arguments?: string | undefined;
|
|
679
679
|
readonly item_id?: string | undefined;
|
|
680
680
|
readonly output_index?: number | undefined;
|
|
@@ -896,8 +896,8 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
896
896
|
} | {
|
|
897
897
|
readonly type: "input_file";
|
|
898
898
|
readonly filename: string;
|
|
899
|
-
readonly file_data?: string | undefined;
|
|
900
899
|
readonly detail?: string | undefined;
|
|
900
|
+
readonly file_data?: string | undefined;
|
|
901
901
|
readonly file_url?: string | undefined;
|
|
902
902
|
} | {
|
|
903
903
|
readonly type: "input_text";
|
|
@@ -933,8 +933,8 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
933
933
|
} | {
|
|
934
934
|
readonly type: "input_file";
|
|
935
935
|
readonly filename: string;
|
|
936
|
-
readonly file_data?: string | undefined;
|
|
937
936
|
readonly detail?: string | undefined;
|
|
937
|
+
readonly file_data?: string | undefined;
|
|
938
938
|
readonly file_url?: string | undefined;
|
|
939
939
|
} | {
|
|
940
940
|
readonly type: "input_text";
|
|
@@ -1169,8 +1169,8 @@ export declare const step: (state: ParserState, event: NormalizedEvent) => AIErr
|
|
|
1169
1169
|
} | {
|
|
1170
1170
|
readonly id: string;
|
|
1171
1171
|
readonly type: "tool-error";
|
|
1172
|
-
readonly name: string;
|
|
1173
1172
|
readonly message: string;
|
|
1173
|
+
readonly name: string;
|
|
1174
1174
|
readonly error?: unknown;
|
|
1175
1175
|
readonly providerMetadata?: {
|
|
1176
1176
|
readonly [x: string]: {
|
|
@@ -1293,8 +1293,8 @@ export declare const protocol: Protocol<{
|
|
|
1293
1293
|
} | {
|
|
1294
1294
|
readonly type: "input_file";
|
|
1295
1295
|
readonly filename: string;
|
|
1296
|
-
readonly file_data?: string | undefined;
|
|
1297
1296
|
readonly detail?: string | undefined;
|
|
1297
|
+
readonly file_data?: string | undefined;
|
|
1298
1298
|
readonly file_url?: string | undefined;
|
|
1299
1299
|
} | {
|
|
1300
1300
|
readonly type: "input_text";
|
|
@@ -1330,8 +1330,8 @@ export declare const protocol: Protocol<{
|
|
|
1330
1330
|
} | {
|
|
1331
1331
|
readonly type: "input_file";
|
|
1332
1332
|
readonly filename: string;
|
|
1333
|
-
readonly file_data?: string | undefined;
|
|
1334
1333
|
readonly detail?: string | undefined;
|
|
1334
|
+
readonly file_data?: string | undefined;
|
|
1335
1335
|
readonly file_url?: string | undefined;
|
|
1336
1336
|
} | {
|
|
1337
1337
|
readonly type: "input_text";
|
|
@@ -1395,21 +1395,10 @@ export declare const protocol: Protocol<{
|
|
|
1395
1395
|
readonly [x: string]: unknown;
|
|
1396
1396
|
readonly type: string;
|
|
1397
1397
|
readonly status?: unknown;
|
|
1398
|
-
readonly code?: unknown;
|
|
1399
1398
|
readonly message?: unknown;
|
|
1399
|
+
readonly code?: unknown;
|
|
1400
1400
|
readonly text?: string | undefined;
|
|
1401
1401
|
readonly error?: unknown;
|
|
1402
|
-
readonly item?: {
|
|
1403
|
-
readonly [x: string]: unknown;
|
|
1404
|
-
readonly type: string;
|
|
1405
|
-
readonly id?: string | undefined;
|
|
1406
|
-
readonly name?: string | undefined;
|
|
1407
|
-
readonly namespace?: string | undefined;
|
|
1408
|
-
readonly arguments?: string | undefined;
|
|
1409
|
-
readonly encrypted_content?: string | null | undefined;
|
|
1410
|
-
readonly call_id?: string | undefined;
|
|
1411
|
-
} | null | undefined;
|
|
1412
|
-
readonly delta?: string | undefined;
|
|
1413
1402
|
readonly response?: {
|
|
1414
1403
|
readonly [x: string]: unknown;
|
|
1415
1404
|
readonly id?: string | undefined;
|
|
@@ -1441,6 +1430,17 @@ export declare const protocol: Protocol<{
|
|
|
1441
1430
|
readonly reason?: string | undefined;
|
|
1442
1431
|
} | null | undefined;
|
|
1443
1432
|
} | undefined;
|
|
1433
|
+
readonly item?: {
|
|
1434
|
+
readonly [x: string]: unknown;
|
|
1435
|
+
readonly type: string;
|
|
1436
|
+
readonly id?: string | undefined;
|
|
1437
|
+
readonly name?: string | undefined;
|
|
1438
|
+
readonly namespace?: string | undefined;
|
|
1439
|
+
readonly arguments?: string | undefined;
|
|
1440
|
+
readonly encrypted_content?: string | null | undefined;
|
|
1441
|
+
readonly call_id?: string | undefined;
|
|
1442
|
+
} | null | undefined;
|
|
1443
|
+
readonly delta?: string | undefined;
|
|
1444
1444
|
readonly arguments?: string | undefined;
|
|
1445
1445
|
readonly item_id?: string | undefined;
|
|
1446
1446
|
readonly output_index?: number | undefined;
|
|
@@ -1514,8 +1514,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1514
1514
|
} | {
|
|
1515
1515
|
readonly type: "input_file";
|
|
1516
1516
|
readonly filename: string;
|
|
1517
|
-
readonly file_data?: string | undefined;
|
|
1518
1517
|
readonly detail?: string | undefined;
|
|
1518
|
+
readonly file_data?: string | undefined;
|
|
1519
1519
|
readonly file_url?: string | undefined;
|
|
1520
1520
|
} | {
|
|
1521
1521
|
readonly type: "input_text";
|
|
@@ -1551,8 +1551,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1551
1551
|
} | {
|
|
1552
1552
|
readonly type: "input_file";
|
|
1553
1553
|
readonly filename: string;
|
|
1554
|
-
readonly file_data?: string | undefined;
|
|
1555
1554
|
readonly detail?: string | undefined;
|
|
1555
|
+
readonly file_data?: string | undefined;
|
|
1556
1556
|
readonly file_url?: string | undefined;
|
|
1557
1557
|
} | {
|
|
1558
1558
|
readonly type: "input_text";
|