@fractaal/pi-ai 0.86.8 → 1.4.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 +105 -45
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +180 -141
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/dist/api/azure-openai-responses.js +8 -10
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +130 -96
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/classifier-shared.d.ts +21 -0
- package/dist/api/classifier-shared.d.ts.map +1 -0
- package/dist/api/classifier-shared.js +99 -0
- package/dist/api/classifier-shared.js.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -1
- package/dist/api/cloudflare-workers-ai-system-one.js +10 -1
- package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -1
- package/dist/api/constrained-sampling.d.ts +11 -1
- package/dist/api/constrained-sampling.d.ts.map +1 -1
- package/dist/api/constrained-sampling.js +33 -18
- package/dist/api/constrained-sampling.js.map +1 -1
- package/dist/api/google-generative-ai.d.ts.map +1 -1
- package/dist/api/google-generative-ai.js +4 -10
- package/dist/api/google-generative-ai.js.map +1 -1
- package/dist/api/google-shared.d.ts +2 -1
- package/dist/api/google-shared.d.ts.map +1 -1
- package/dist/api/google-shared.js +60 -3
- package/dist/api/google-shared.js.map +1 -1
- package/dist/api/google-vertex.d.ts.map +1 -1
- package/dist/api/google-vertex.js +9 -15
- package/dist/api/google-vertex.js.map +1 -1
- package/dist/api/lazy.d.ts +7 -2
- package/dist/api/lazy.d.ts.map +1 -1
- package/dist/api/lazy.js +28 -8
- package/dist/api/lazy.js.map +1 -1
- package/dist/api/llama-cpp-classify.d.ts.map +1 -1
- package/dist/api/llama-cpp-classify.js +4 -1
- package/dist/api/llama-cpp-classify.js.map +1 -1
- package/dist/api/mistral-conversations.d.ts.map +1 -1
- package/dist/api/mistral-conversations.js +50 -60
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +23 -14
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +83 -87
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-decisions.d.ts +4 -0
- package/dist/api/openai-decisions.d.ts.map +1 -0
- package/dist/api/openai-decisions.js +162 -0
- package/dist/api/openai-decisions.js.map +1 -0
- package/dist/api/openai-decisions.lazy.d.ts +3 -0
- package/dist/api/openai-decisions.lazy.d.ts.map +1 -0
- package/dist/api/openai-decisions.lazy.js +4 -0
- package/dist/api/openai-decisions.lazy.js.map +1 -0
- package/dist/api/openai-responses-shared.d.ts +26 -0
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +132 -66
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +38 -19
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/api/openrouter-images.d.ts.map +1 -1
- package/dist/api/openrouter-images.js +5 -3
- package/dist/api/openrouter-images.js.map +1 -1
- package/dist/api/pi-messages.d.ts +2 -0
- package/dist/api/pi-messages.d.ts.map +1 -1
- package/dist/api/pi-messages.js +18 -12
- package/dist/api/pi-messages.js.map +1 -1
- package/dist/api/simple-options.d.ts.map +1 -1
- package/dist/api/simple-options.js +2 -1
- package/dist/api/simple-options.js.map +1 -1
- package/dist/api/system-one-shared.d.ts +29 -3
- package/dist/api/system-one-shared.d.ts.map +1 -1
- package/dist/api/system-one-shared.js +54 -86
- package/dist/api/system-one-shared.js.map +1 -1
- package/dist/api/transform-messages.d.ts +16 -1
- package/dist/api/transform-messages.d.ts.map +1 -1
- package/dist/api/transform-messages.js +28 -15
- package/dist/api/transform-messages.js.map +1 -1
- package/dist/api/typesafe-system-one.d.ts.map +1 -1
- package/dist/api/typesafe-system-one.js +12 -1
- package/dist/api/typesafe-system-one.js.map +1 -1
- package/dist/auth/oauth/anthropic.d.ts.map +1 -1
- package/dist/auth/oauth/anthropic.js +14 -6
- package/dist/auth/oauth/anthropic.js.map +1 -1
- package/dist/auth/oauth/openai-chatgpt.js +1 -1
- package/dist/auth/oauth/openai-chatgpt.js.map +1 -1
- package/dist/auth/oauth/openai-codex.d.ts.map +1 -1
- package/dist/auth/oauth/openai-codex.js +4 -4
- package/dist/auth/oauth/openai-codex.js.map +1 -1
- package/dist/auth/types.d.ts +9 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/types.js.map +1 -1
- package/dist/compat/extension-oauth-types.d.ts +4 -0
- package/dist/compat/extension-oauth-types.d.ts.map +1 -1
- package/dist/compat/extension-oauth-types.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +9 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +23 -7
- package/dist/models.js.map +1 -1
- package/dist/providers/compat-schema.d.ts +509 -0
- package/dist/providers/compat-schema.d.ts.map +1 -0
- package/dist/providers/compat-schema.js +396 -0
- package/dist/providers/compat-schema.js.map +1 -0
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/amazon-bedrock.json +1 -1
- package/dist/providers/data/anthropic.json +1 -1
- package/dist/providers/data/azure.json +1 -1
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/cerebras.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/dist/providers/data/fireworks.json +1 -1
- package/dist/providers/data/github-copilot.json +1 -1
- package/dist/providers/data/google-vertex.json +1 -1
- package/dist/providers/data/google.json +1 -1
- package/dist/providers/data/groq.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/kimi-coding.json +1 -1
- package/dist/providers/data/meta.json +1 -1
- package/dist/providers/data/minimax-cn.json +1 -1
- package/dist/providers/data/minimax.json +1 -1
- package/dist/providers/data/mistral.json +1 -1
- package/dist/providers/data/moonshotai-cn.json +1 -1
- package/dist/providers/data/moonshotai.json +1 -1
- package/dist/providers/data/nvidia.json +1 -1
- package/dist/providers/data/openai-codex.json +1 -1
- package/dist/providers/data/openai.json +1 -1
- package/dist/providers/data/opencode-go.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/dist/providers/data/qwen-token-plan.json +1 -1
- package/dist/providers/data/radius.json +1 -1
- package/dist/providers/data/together.json +1 -1
- package/dist/providers/data/typesafe.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/providers/data/xai.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
- package/dist/providers/data/xiaomi.json +1 -1
- package/dist/providers/data/zai-coding-cn.json +1 -1
- package/dist/providers/faux.d.ts.map +1 -1
- package/dist/providers/faux.js +31 -9
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/kimi-coding.d.ts +1 -1
- package/dist/providers/kimi-coding.js +3 -3
- package/dist/providers/kimi-coding.js.map +1 -1
- package/dist/providers/model-schema.d.ts +91 -0
- package/dist/providers/model-schema.d.ts.map +1 -0
- package/dist/providers/model-schema.js +57 -0
- package/dist/providers/model-schema.js.map +1 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +12 -3
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/opencode-go.d.ts +3 -1
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +2 -0
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/openrouter-api.d.ts +40 -0
- package/dist/providers/openrouter-api.d.ts.map +1 -0
- package/dist/providers/openrouter-api.js +41 -0
- package/dist/providers/openrouter-api.js.map +1 -0
- package/dist/providers/openrouter.d.ts +11 -1
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +52 -1
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/radius-config.d.ts.map +1 -1
- package/dist/providers/radius-config.js +2 -1
- package/dist/providers/radius-config.js.map +1 -1
- package/dist/providers/radius.d.ts.map +1 -1
- package/dist/providers/radius.js +4 -12
- package/dist/providers/radius.js.map +1 -1
- package/dist/telemetry.d.ts +288 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +192 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +44 -307
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/error-body.d.ts.map +1 -1
- package/dist/utils/error-body.js +2 -1
- package/dist/utils/error-body.js.map +1 -1
- package/dist/utils/estimate.js +1 -1
- package/dist/utils/estimate.js.map +1 -1
- package/dist/utils/event-stream.d.ts +10 -1
- package/dist/utils/event-stream.d.ts.map +1 -1
- package/dist/utils/event-stream.js +25 -0
- package/dist/utils/event-stream.js.map +1 -1
- package/dist/utils/identity.d.ts +65 -0
- package/dist/utils/identity.d.ts.map +1 -0
- package/dist/utils/identity.js +141 -0
- package/dist/utils/identity.js.map +1 -0
- package/dist/utils/json-parse.d.ts +10 -0
- package/dist/utils/json-parse.d.ts.map +1 -1
- package/dist/utils/json-parse.js +26 -1
- package/dist/utils/json-parse.js.map +1 -1
- package/dist/utils/model-operations.d.ts +3 -1
- package/dist/utils/model-operations.d.ts.map +1 -1
- package/dist/utils/model-operations.js +6 -0
- package/dist/utils/model-operations.js.map +1 -1
- package/dist/utils/openrouter-cost.d.ts +24 -0
- package/dist/utils/openrouter-cost.d.ts.map +1 -0
- package/dist/utils/openrouter-cost.js +34 -0
- package/dist/utils/openrouter-cost.js.map +1 -0
- package/dist/utils/overflow.d.ts +1 -0
- package/dist/utils/overflow.d.ts.map +1 -1
- package/dist/utils/overflow.js +6 -1
- package/dist/utils/overflow.js.map +1 -1
- package/dist/utils/provider-retry.d.ts +2 -0
- package/dist/utils/provider-retry.d.ts.map +1 -1
- package/dist/utils/provider-retry.js +2 -0
- package/dist/utils/provider-retry.js.map +1 -1
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +26 -10
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/streaming-json.d.ts +84 -0
- package/dist/utils/streaming-json.d.ts.map +1 -0
- package/dist/utils/streaming-json.js +513 -0
- package/dist/utils/streaming-json.js.map +1 -0
- package/dist/utils/text.d.ts +7 -0
- package/dist/utils/text.d.ts.map +1 -1
- package/dist/utils/text.js +9 -0
- package/dist/utils/text.js.map +1 -1
- package/dist/utils/transcript.d.ts +22 -8
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +29 -18
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +3 -0
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +3 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +3 -3
- package/dist/utils/assistant-message-frame.d.ts +0 -77
- package/dist/utils/assistant-message-frame.d.ts.map +0 -1
- package/dist/utils/assistant-message-frame.js +0 -425
- package/dist/utils/assistant-message-frame.js.map +0 -1
- package/dist/utils/pi-user-agent.d.ts +0 -2
- package/dist/utils/pi-user-agent.d.ts.map +0 -1
- package/dist/utils/pi-user-agent.js +0 -12
- package/dist/utils/pi-user-agent.js.map +0 -1
|
@@ -4,17 +4,19 @@ import { calculateCost } from "../models.js";
|
|
|
4
4
|
import { appendAssistantMessageDiagnostic } from "../utils/diagnostics.js";
|
|
5
5
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
6
6
|
import { headersToRecord } from "../utils/headers.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { getIdentityHeaders } from "../utils/identity.js";
|
|
8
|
+
import { parseJsonWithRepair } from "../utils/json-parse.js";
|
|
9
|
+
import { applyOpenRouterReportedCost, isOpenRouterModel, } from "../utils/openrouter-cost.js";
|
|
9
10
|
import { getProviderEnvValue } from "../utils/provider-env.js";
|
|
10
11
|
import { retryProviderRequest } from "../utils/provider-retry.js";
|
|
11
12
|
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
13
|
+
import { ToolCallArgumentsStream } from "../utils/streaming-json.js";
|
|
12
14
|
import { getSystemMessageText, renderSystemMessageUpdate } from "../utils/text.js";
|
|
13
15
|
import { getCurrentTools, getInitialSystemMessage, resolveTranscript, } from "../utils/transcript.js";
|
|
14
16
|
import { getJsonSchemaToolParameters, resolveJsonSchemaStrictSampling, } from "./constrained-sampling.js";
|
|
15
17
|
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
|
|
16
18
|
import { adjustMaxTokensForThinking, buildBaseOptions, clampMaxTokensToContext } from "./simple-options.js";
|
|
17
|
-
import { transformMessages } from "./transform-messages.js";
|
|
19
|
+
import { splitErrorToolResultImages, transformMessages } from "./transform-messages.js";
|
|
18
20
|
/**
|
|
19
21
|
* Resolve cache retention preference.
|
|
20
22
|
* Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
|
|
@@ -75,6 +77,16 @@ const fromClaudeCodeName = (name, tools) => {
|
|
|
75
77
|
}
|
|
76
78
|
return name;
|
|
77
79
|
};
|
|
80
|
+
function convertImageBlock(image) {
|
|
81
|
+
return {
|
|
82
|
+
type: "image",
|
|
83
|
+
source: {
|
|
84
|
+
type: "base64",
|
|
85
|
+
media_type: image.mimeType,
|
|
86
|
+
data: image.data,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
78
90
|
/**
|
|
79
91
|
* Convert content blocks to Anthropic API format
|
|
80
92
|
*/
|
|
@@ -92,14 +104,7 @@ function convertContentBlocks(content) {
|
|
|
92
104
|
text: sanitizeSurrogates(block.text),
|
|
93
105
|
};
|
|
94
106
|
}
|
|
95
|
-
return
|
|
96
|
-
type: "image",
|
|
97
|
-
source: {
|
|
98
|
-
type: "base64",
|
|
99
|
-
media_type: block.mimeType,
|
|
100
|
-
data: block.data,
|
|
101
|
-
},
|
|
102
|
-
};
|
|
107
|
+
return convertImageBlock(block);
|
|
103
108
|
});
|
|
104
109
|
// If only images (no text), add placeholder text block
|
|
105
110
|
const hasText = blocks.some((b) => b.type === "text");
|
|
@@ -157,9 +162,6 @@ function mergeHeaders(...headerSources) {
|
|
|
157
162
|
}
|
|
158
163
|
return merged;
|
|
159
164
|
}
|
|
160
|
-
function mergeClientHeaders(...headerSources) {
|
|
161
|
-
return mergeHeaders({ "User-Agent": getPiUserAgent() }, ...headerSources);
|
|
162
|
-
}
|
|
163
165
|
function hasHeader(headers, name) {
|
|
164
166
|
if (!headers)
|
|
165
167
|
return false;
|
|
@@ -378,14 +380,12 @@ export const stream = (model, context, options) => {
|
|
|
378
380
|
const normalizedContext = resolveTranscript(context, getAnthropicCompat(model).supportsMidConvoSystemMessages);
|
|
379
381
|
const currentTools = getCurrentTools(normalizedContext.messages);
|
|
380
382
|
(async () => {
|
|
381
|
-
const providerThinkingLevel = model.compat?.supportsMidConvoEffort ? (options?.effort ?? "high") : undefined;
|
|
382
383
|
const output = {
|
|
383
384
|
role: "assistant",
|
|
384
385
|
content: [],
|
|
385
386
|
api: model.api,
|
|
386
387
|
provider: model.provider,
|
|
387
388
|
model: model.id,
|
|
388
|
-
...(providerThinkingLevel === undefined ? {} : { providerThinkingLevel }),
|
|
389
389
|
usage: {
|
|
390
390
|
input: 0,
|
|
391
391
|
output: 0,
|
|
@@ -421,28 +421,67 @@ export const stream = (model, context, options) => {
|
|
|
421
421
|
}
|
|
422
422
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
|
|
423
423
|
const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
|
|
424
|
-
const created = createClient(model, apiKey, options?.headers, options?.fetch, copilotDynamicHeaders, cacheSessionId, federation);
|
|
424
|
+
const created = createClient(model, apiKey, options?.headers, options?.fetch, copilotDynamicHeaders, cacheSessionId, federation, options?.identity);
|
|
425
425
|
client = created.client;
|
|
426
426
|
isOAuth = created.isOAuthToken;
|
|
427
427
|
}
|
|
428
|
-
let params = buildParams(model, normalizedContext, isOAuth, options);
|
|
429
|
-
const nextParams = await options?.onPayload?.(params, model);
|
|
430
|
-
if (nextParams !== undefined) {
|
|
431
|
-
params = { ...nextParams, stream: true };
|
|
432
|
-
}
|
|
433
428
|
const requestOptions = {
|
|
434
429
|
...(options?.signal ? { signal: options.signal } : {}),
|
|
435
430
|
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
436
431
|
maxRetries: 0,
|
|
437
432
|
};
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
433
|
+
let disablePreferredStrictTools = false;
|
|
434
|
+
let response;
|
|
435
|
+
for (;;) {
|
|
436
|
+
options?.signal?.throwIfAborted();
|
|
437
|
+
const built = buildParams(model, normalizedContext, isOAuth, options, disablePreferredStrictTools);
|
|
438
|
+
if (built.providerThinkingLevel)
|
|
439
|
+
output.providerThinkingLevel = built.providerThinkingLevel;
|
|
440
|
+
let params = built.params;
|
|
441
|
+
const nextParams = await options?.onPayload?.(params, model);
|
|
442
|
+
if (nextParams !== undefined) {
|
|
443
|
+
params = { ...nextParams, stream: true };
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
response = await retryProviderRequest(() => client.beta.messages.create(params, requestOptions).asResponse(), {
|
|
447
|
+
maxRetries: options?.maxRetries,
|
|
448
|
+
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
449
|
+
signal: options?.signal,
|
|
450
|
+
});
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
// Only downgrade a rejected request, never an already-started stream.
|
|
455
|
+
if (options?.signal?.aborted ||
|
|
456
|
+
disablePreferredStrictTools ||
|
|
457
|
+
!built.hasPreferredStrictTools ||
|
|
458
|
+
!(error instanceof Anthropic.APIError) ||
|
|
459
|
+
error.status !== 400 ||
|
|
460
|
+
error.type !== "invalid_request_error" ||
|
|
461
|
+
![
|
|
462
|
+
"The compiled grammar is too large",
|
|
463
|
+
"Too many strict tools (",
|
|
464
|
+
"Schemas contains too many parameters with union types (",
|
|
465
|
+
].some((message) => error.message.includes(message))) {
|
|
466
|
+
throw error;
|
|
467
|
+
}
|
|
468
|
+
disablePreferredStrictTools = true;
|
|
469
|
+
appendAssistantMessageDiagnostic(output, {
|
|
470
|
+
type: "anthropic_strict_tools_fallback",
|
|
471
|
+
timestamp: Date.now(),
|
|
472
|
+
error: { message: error.message },
|
|
473
|
+
details: { reason: "strict_tool_limits_exceeded" },
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
443
477
|
await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
|
|
444
478
|
stream.push({ type: "start", partial: output });
|
|
445
|
-
|
|
479
|
+
// Stream state per Anthropic block index, kept off the content blocks so it never reaches partials.
|
|
480
|
+
const openBlocks = new Map();
|
|
481
|
+
const openBlock = (anthropicIndex) => {
|
|
482
|
+
const open = openBlocks.get(anthropicIndex);
|
|
483
|
+
return open === undefined ? undefined : { ...open, block: output.content[open.contentIndex] };
|
|
484
|
+
};
|
|
446
485
|
for await (const event of iterateAnthropicEvents(response, options?.signal)) {
|
|
447
486
|
await options?.onProviderStreamEvent?.(event, model);
|
|
448
487
|
if (event.type === "message_start") {
|
|
@@ -477,105 +516,92 @@ export const stream = (model, context, options) => {
|
|
|
477
516
|
continue;
|
|
478
517
|
}
|
|
479
518
|
if (event.content_block.type === "text") {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
text: event.content_block.text ?? "",
|
|
483
|
-
index: event.index,
|
|
484
|
-
};
|
|
485
|
-
output.content.push(block);
|
|
519
|
+
output.content.push({ type: "text", text: event.content_block.text ?? "" });
|
|
520
|
+
openBlocks.set(event.index, { contentIndex: output.content.length - 1 });
|
|
486
521
|
stream.push({ type: "text_start", contentIndex: output.content.length - 1, partial: output });
|
|
487
522
|
}
|
|
488
523
|
else if (event.content_block.type === "thinking") {
|
|
489
|
-
|
|
524
|
+
output.content.push({
|
|
490
525
|
type: "thinking",
|
|
491
526
|
thinking: event.content_block.thinking ?? "",
|
|
492
527
|
thinkingSignature: event.content_block.signature ?? "",
|
|
493
|
-
|
|
494
|
-
};
|
|
495
|
-
output.content.push(block);
|
|
528
|
+
});
|
|
529
|
+
openBlocks.set(event.index, { contentIndex: output.content.length - 1 });
|
|
496
530
|
stream.push({ type: "thinking_start", contentIndex: output.content.length - 1, partial: output });
|
|
497
531
|
}
|
|
498
532
|
else if (event.content_block.type === "redacted_thinking") {
|
|
499
|
-
|
|
533
|
+
output.content.push({
|
|
500
534
|
type: "thinking",
|
|
501
535
|
thinking: "[Reasoning redacted]",
|
|
502
536
|
thinkingSignature: event.content_block.data,
|
|
503
537
|
redacted: true,
|
|
504
|
-
|
|
505
|
-
};
|
|
506
|
-
output.content.push(block);
|
|
538
|
+
});
|
|
539
|
+
openBlocks.set(event.index, { contentIndex: output.content.length - 1 });
|
|
507
540
|
stream.push({ type: "thinking_start", contentIndex: output.content.length - 1, partial: output });
|
|
508
541
|
}
|
|
509
542
|
else if (event.content_block.type === "tool_use") {
|
|
510
|
-
|
|
543
|
+
output.content.push({
|
|
511
544
|
type: "toolCall",
|
|
512
545
|
id: event.content_block.id,
|
|
513
546
|
name: isOAuth
|
|
514
547
|
? fromClaudeCodeName(event.content_block.name, currentTools)
|
|
515
548
|
: event.content_block.name,
|
|
516
549
|
arguments: event.content_block.input ?? {},
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
550
|
+
});
|
|
551
|
+
openBlocks.set(event.index, {
|
|
552
|
+
contentIndex: output.content.length - 1,
|
|
553
|
+
arguments: new ToolCallArgumentsStream(),
|
|
554
|
+
});
|
|
521
555
|
stream.push({ type: "toolcall_start", contentIndex: output.content.length - 1, partial: output });
|
|
522
556
|
}
|
|
523
557
|
}
|
|
524
558
|
else if (event.type === "content_block_delta") {
|
|
559
|
+
const open = openBlock(event.index);
|
|
525
560
|
if (event.delta.type === "text_delta") {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (block && block.type === "text") {
|
|
529
|
-
block.text += event.delta.text;
|
|
561
|
+
if (open?.block.type === "text") {
|
|
562
|
+
open.block.text += event.delta.text;
|
|
530
563
|
stream.push({
|
|
531
564
|
type: "text_delta",
|
|
532
|
-
contentIndex:
|
|
565
|
+
contentIndex: open.contentIndex,
|
|
533
566
|
delta: event.delta.text,
|
|
534
567
|
partial: output,
|
|
535
568
|
});
|
|
536
569
|
}
|
|
537
570
|
}
|
|
538
571
|
else if (event.delta.type === "thinking_delta") {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
if (block && block.type === "thinking") {
|
|
542
|
-
block.thinking += event.delta.thinking;
|
|
572
|
+
if (open?.block.type === "thinking") {
|
|
573
|
+
open.block.thinking += event.delta.thinking;
|
|
543
574
|
stream.push({
|
|
544
575
|
type: "thinking_delta",
|
|
545
|
-
contentIndex:
|
|
576
|
+
contentIndex: open.contentIndex,
|
|
546
577
|
delta: event.delta.thinking,
|
|
547
578
|
partial: output,
|
|
548
579
|
});
|
|
549
580
|
}
|
|
550
581
|
}
|
|
551
582
|
else if (event.delta.type === "input_json_delta") {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
if (block && block.type === "toolCall") {
|
|
555
|
-
block.partialJson += event.delta.partial_json;
|
|
556
|
-
block.arguments = parseStreamingJson(block.partialJson);
|
|
583
|
+
if (open?.block.type === "toolCall" && open.arguments !== undefined) {
|
|
584
|
+
open.block.arguments = open.arguments.append(event.delta.partial_json);
|
|
557
585
|
stream.push({
|
|
558
586
|
type: "toolcall_delta",
|
|
559
|
-
contentIndex:
|
|
587
|
+
contentIndex: open.contentIndex,
|
|
560
588
|
delta: event.delta.partial_json,
|
|
561
589
|
partial: output,
|
|
562
590
|
});
|
|
563
591
|
}
|
|
564
592
|
}
|
|
565
593
|
else if (event.delta.type === "signature_delta") {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
block.thinkingSignature = block.thinkingSignature || "";
|
|
570
|
-
block.thinkingSignature += event.delta.signature;
|
|
594
|
+
if (open?.block.type === "thinking") {
|
|
595
|
+
open.block.thinkingSignature = open.block.thinkingSignature || "";
|
|
596
|
+
open.block.thinkingSignature += event.delta.signature;
|
|
571
597
|
}
|
|
572
598
|
}
|
|
573
599
|
}
|
|
574
600
|
else if (event.type === "content_block_stop") {
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
if (
|
|
578
|
-
|
|
601
|
+
const open = openBlock(event.index);
|
|
602
|
+
openBlocks.delete(event.index);
|
|
603
|
+
if (open) {
|
|
604
|
+
const { block, contentIndex: index } = open;
|
|
579
605
|
if (block.type === "text") {
|
|
580
606
|
stream.push({
|
|
581
607
|
type: "text_end",
|
|
@@ -592,11 +618,8 @@ export const stream = (model, context, options) => {
|
|
|
592
618
|
partial: output,
|
|
593
619
|
});
|
|
594
620
|
}
|
|
595
|
-
else if (block.type === "toolCall") {
|
|
596
|
-
block.arguments
|
|
597
|
-
// Finalize in-place and strip the scratch buffer so replay only
|
|
598
|
-
// carries parsed arguments.
|
|
599
|
-
delete block.partialJson;
|
|
621
|
+
else if (block.type === "toolCall" && open.arguments !== undefined) {
|
|
622
|
+
Object.assign(block, open.arguments.finish());
|
|
600
623
|
stream.push({
|
|
601
624
|
type: "toolcall_end",
|
|
602
625
|
contentIndex: index,
|
|
@@ -648,6 +671,11 @@ export const stream = (model, context, options) => {
|
|
|
648
671
|
output.usage.totalTokens =
|
|
649
672
|
output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
650
673
|
calculateCost(usageModel, output.usage);
|
|
674
|
+
if (isOpenRouterModel(model) && event.usage) {
|
|
675
|
+
// OpenRouter adds billing fields to streamed message_delta usage at runtime,
|
|
676
|
+
// although its OpenAPI schema and the Anthropic SDK do not type those fields.
|
|
677
|
+
applyOpenRouterReportedCost(output.usage, event.usage);
|
|
678
|
+
}
|
|
651
679
|
}
|
|
652
680
|
}
|
|
653
681
|
if (options?.signal?.aborted) {
|
|
@@ -676,11 +704,6 @@ export const stream = (model, context, options) => {
|
|
|
676
704
|
stream.end();
|
|
677
705
|
}
|
|
678
706
|
catch (error) {
|
|
679
|
-
for (const block of output.content) {
|
|
680
|
-
delete block.index;
|
|
681
|
-
// partialJson is only a streaming scratch buffer; never persist it.
|
|
682
|
-
delete block.partialJson;
|
|
683
|
-
}
|
|
684
707
|
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
685
708
|
output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
|
|
686
709
|
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
@@ -748,7 +771,7 @@ export const streamSimple = (model, context, options) => {
|
|
|
748
771
|
function isOAuthToken(apiKey) {
|
|
749
772
|
return apiKey.includes("sk-ant-oat");
|
|
750
773
|
}
|
|
751
|
-
function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sessionId, federation) {
|
|
774
|
+
function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sessionId, federation, identity) {
|
|
752
775
|
// Copilot: Bearer auth.
|
|
753
776
|
if (model.provider === "github-copilot") {
|
|
754
777
|
const client = new PiAnthropic({
|
|
@@ -757,14 +780,14 @@ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sess
|
|
|
757
780
|
baseURL: model.baseUrl,
|
|
758
781
|
dangerouslyAllowBrowser: true,
|
|
759
782
|
fetch,
|
|
760
|
-
defaultHeaders:
|
|
783
|
+
defaultHeaders: mergeHeaders(getIdentityHeaders(model, identity), {
|
|
761
784
|
accept: "application/json",
|
|
762
785
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
763
786
|
}, model.headers, dynamicHeaders, optionsHeaders),
|
|
764
787
|
});
|
|
765
788
|
return { client, isOAuthToken: false };
|
|
766
789
|
}
|
|
767
|
-
// OAuth: Bearer auth, Claude Code identity headers
|
|
790
|
+
// OAuth: Bearer auth, Claude Code identity headers instead of the client identity.
|
|
768
791
|
if (apiKey && isOAuthToken(apiKey)) {
|
|
769
792
|
const client = new PiAnthropic({
|
|
770
793
|
apiKey: null,
|
|
@@ -772,7 +795,7 @@ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sess
|
|
|
772
795
|
baseURL: model.baseUrl,
|
|
773
796
|
dangerouslyAllowBrowser: true,
|
|
774
797
|
fetch,
|
|
775
|
-
defaultHeaders:
|
|
798
|
+
defaultHeaders: mergeHeaders({
|
|
776
799
|
accept: "application/json",
|
|
777
800
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
778
801
|
"user-agent": `claude-cli/${claudeCodeVersion}`,
|
|
@@ -788,7 +811,7 @@ function createClient(model, apiKey, optionsHeaders, fetch, dynamicHeaders, sess
|
|
|
788
811
|
const header = compat.sessionAffinityFormat === "openrouter" ? "x-session-id" : "x-session-affinity";
|
|
789
812
|
sessionAffinityHeaders[header] = sessionId;
|
|
790
813
|
}
|
|
791
|
-
const defaultHeaders =
|
|
814
|
+
const defaultHeaders = mergeHeaders(getIdentityHeaders(model, identity), {
|
|
792
815
|
accept: "application/json",
|
|
793
816
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
794
817
|
}, sessionAffinityHeaders, model.headers, optionsHeaders);
|
|
@@ -855,7 +878,7 @@ function getBetaFeatures(model, context, isOAuthToken, nativeToolChanges, option
|
|
|
855
878
|
features.push(INLINE_TOOLS_BETA);
|
|
856
879
|
return [...new Set(features)];
|
|
857
880
|
}
|
|
858
|
-
function buildParams(model, context, isOAuthToken, options) {
|
|
881
|
+
function buildParams(model, context, isOAuthToken, options, disablePreferredStrictTools = false) {
|
|
859
882
|
const { cacheControl } = getCacheControl(model, options?.cacheRetention, options?.env);
|
|
860
883
|
const compat = getAnthropicCompat(model);
|
|
861
884
|
const initialSystemMessage = getInitialSystemMessage(context.messages);
|
|
@@ -866,18 +889,28 @@ function buildParams(model, context, isOAuthToken, options) {
|
|
|
866
889
|
// by value in a `tool_addition` block, which also expresses same-name redefinitions.
|
|
867
890
|
// Anthropic rejects a tool list where every tool is deferred, so there must be an initial
|
|
868
891
|
// active tool to anchor the placeholder. Otherwise the current tool list is sent.
|
|
892
|
+
let hasPreferredStrictTools = false;
|
|
893
|
+
const convertToolDefinitions = (tools, toolCacheControl) => {
|
|
894
|
+
const definitions = convertTools(tools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools, toolCacheControl, disablePreferredStrictTools);
|
|
895
|
+
if (definitions.some((definition, index) => {
|
|
896
|
+
const config = tools[index].constrainedSampling;
|
|
897
|
+
return definition.strict === true && config && config.type === "json_schema" && config.strict === "prefer";
|
|
898
|
+
})) {
|
|
899
|
+
hasPreferredStrictTools = true;
|
|
900
|
+
}
|
|
901
|
+
return definitions;
|
|
902
|
+
};
|
|
869
903
|
const initialTools = initialSystemMessage?.toolsAdded ?? [];
|
|
870
904
|
const nativeToolChanges = compat.supportsMidConvoSystemMessages && compat.supportsMidConvoToolChanges && initialTools.length > 0;
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
|
|
905
|
+
const thinkingDisabled = model.reasoning && options?.thinkingEnabled === false && model.thinkingLevelMap?.off !== null;
|
|
906
|
+
// Effort cannot change between messages while thinking is disabled, so "off" sends no effort markers.
|
|
907
|
+
const effortMessages = model.compat?.supportsMidConvoEffort === true && !thinkingDisabled;
|
|
908
|
+
const converted = convertMessages(conversationMessages, isOAuthToken, cacheControl, compat.allowEmptySignature, effortMessages ? model.provider : undefined, nativeToolChanges ? convertToolDefinitions : undefined);
|
|
874
909
|
const activeEffort = options?.effort ?? "high";
|
|
875
910
|
const betaFeatures = getBetaFeatures(model, context, isOAuthToken, nativeToolChanges, options);
|
|
876
911
|
const params = {
|
|
877
912
|
model: model.id,
|
|
878
|
-
messages:
|
|
879
|
-
? insertThinkingLevelMessages(converted, activeEffort)
|
|
880
|
-
: converted.messages,
|
|
913
|
+
messages: effortMessages ? insertThinkingLevelMessages(converted, activeEffort) : converted.messages,
|
|
881
914
|
max_tokens: options?.maxTokens ?? model.maxTokens,
|
|
882
915
|
stream: true,
|
|
883
916
|
...(betaFeatures.length > 0 ? { betas: betaFeatures } : {}),
|
|
@@ -922,50 +955,50 @@ function buildParams(model, context, isOAuthToken, options) {
|
|
|
922
955
|
// placeholder. The list never changes afterwards: later tools are defined by value in
|
|
923
956
|
// `tool_addition` blocks and withdrawn by `tool_removal`, so the cached prefix survives
|
|
924
957
|
// every tool change.
|
|
925
|
-
params.tools = [
|
|
926
|
-
...convertTools(initialTools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools, toolCacheControl),
|
|
927
|
-
DEFERRED_TOOL_PLACEHOLDER,
|
|
928
|
-
];
|
|
958
|
+
params.tools = [...convertToolDefinitions(initialTools, toolCacheControl), DEFERRED_TOOL_PLACEHOLDER];
|
|
929
959
|
}
|
|
930
960
|
else {
|
|
931
961
|
const tools = getCurrentTools(context.messages);
|
|
932
962
|
if (tools.length > 0) {
|
|
933
|
-
params.tools =
|
|
963
|
+
params.tools = convertToolDefinitions(tools, toolCacheControl);
|
|
934
964
|
}
|
|
935
965
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
966
|
+
if (thinkingDisabled) {
|
|
967
|
+
// No effort is sent, so the model default applies. Anthropic rejects `block_binding`
|
|
968
|
+
// with disabled thinking.
|
|
969
|
+
params.thinking = { type: "disabled" };
|
|
970
|
+
}
|
|
971
|
+
else if (effortMessages) {
|
|
972
|
+
// Managed effort models use adaptive thinking so prefix mismatches can
|
|
973
|
+
// be dropped instead of surfacing as persistent 400 responses.
|
|
939
974
|
params.thinking = {
|
|
940
975
|
type: "adaptive",
|
|
941
976
|
display: options?.thinkingDisplay ?? "summarized",
|
|
942
977
|
block_binding: { prefix_mismatch_behavior: "drop_block" },
|
|
943
978
|
};
|
|
944
|
-
|
|
979
|
+
// Effort markers set the level for every reply. The top-level effort is part of the cached
|
|
980
|
+
// prompt, so it stays fixed. It is "low" because organizations can cap effort and reject
|
|
981
|
+
// requests containing any level above the cap.
|
|
982
|
+
params.output_config = { effort: "low" };
|
|
945
983
|
}
|
|
946
|
-
else if (model.reasoning) {
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
params.output_config = { effort: options.effort };
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
else {
|
|
959
|
-
// Budget-based thinking for older models
|
|
960
|
-
params.thinking = {
|
|
961
|
-
type: "enabled",
|
|
962
|
-
budget_tokens: options.thinkingBudgetTokens || 1024,
|
|
963
|
-
display,
|
|
964
|
-
};
|
|
984
|
+
else if (model.reasoning && options?.thinkingEnabled) {
|
|
985
|
+
// Default to "summarized" so Opus 4.7 and Mythos Preview behave like
|
|
986
|
+
// older Claude 4 models (whose API default is also "summarized").
|
|
987
|
+
const display = options.thinkingDisplay ?? "summarized";
|
|
988
|
+
if (model.compat?.forceAdaptiveThinking === true) {
|
|
989
|
+
// Adaptive thinking: Claude decides when and how much to think.
|
|
990
|
+
params.thinking = { type: "adaptive", display };
|
|
991
|
+
if (options.effort) {
|
|
992
|
+
params.output_config = { effort: options.effort };
|
|
965
993
|
}
|
|
966
994
|
}
|
|
967
|
-
else
|
|
968
|
-
|
|
995
|
+
else {
|
|
996
|
+
// Budget-based thinking for older models
|
|
997
|
+
params.thinking = {
|
|
998
|
+
type: "enabled",
|
|
999
|
+
budget_tokens: options.thinkingBudgetTokens || 1024,
|
|
1000
|
+
display,
|
|
1001
|
+
};
|
|
969
1002
|
}
|
|
970
1003
|
}
|
|
971
1004
|
if (options?.metadata) {
|
|
@@ -986,17 +1019,17 @@ function buildParams(model, context, isOAuthToken, options) {
|
|
|
986
1019
|
if (allowedFallbackModels && allowedFallbackModels.length > 0) {
|
|
987
1020
|
params.fallbacks = allowedFallbackModels.map((fallback) => ({ model: fallback.model }));
|
|
988
1021
|
}
|
|
989
|
-
return params;
|
|
1022
|
+
return { params, hasPreferredStrictTools, providerThinkingLevel: effortMessages ? activeEffort : undefined };
|
|
990
1023
|
}
|
|
991
1024
|
// Normalize tool call IDs to match Anthropic's required pattern and length
|
|
992
1025
|
function normalizeToolCallId(id) {
|
|
993
1026
|
return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
|
|
994
1027
|
}
|
|
995
|
-
function convertToolResult(msg) {
|
|
1028
|
+
function convertToolResult(msg, content = msg.content) {
|
|
996
1029
|
return {
|
|
997
1030
|
type: "tool_result",
|
|
998
1031
|
tool_use_id: msg.toolCallId,
|
|
999
|
-
content: convertContentBlocks(
|
|
1032
|
+
content: convertContentBlocks(content),
|
|
1000
1033
|
is_error: msg.isError,
|
|
1001
1034
|
};
|
|
1002
1035
|
}
|
|
@@ -1006,7 +1039,9 @@ convertToolDefinitions) {
|
|
|
1006
1039
|
const params = [];
|
|
1007
1040
|
const assistantLevels = new Map();
|
|
1008
1041
|
// Later system messages are held back and emitted directly before the next assistant
|
|
1009
|
-
// message (or at the end of the transcript).
|
|
1042
|
+
// message that is sent (or at the end of the transcript). Assistant messages that convert to
|
|
1043
|
+
// no blocks are dropped, so holding past them keeps an update from landing before a user
|
|
1044
|
+
// message (#11091). Anthropic requires `tool_result` blocks to
|
|
1010
1045
|
// immediately follow their `tool_use`, so a system message between them is rejected; this
|
|
1011
1046
|
// also mirrors where the managed-effort system messages are inserted. As a result an
|
|
1012
1047
|
// update placed before a user message in the transcript lands after it on the wire.
|
|
@@ -1061,14 +1096,7 @@ convertToolDefinitions) {
|
|
|
1061
1096
|
};
|
|
1062
1097
|
}
|
|
1063
1098
|
else {
|
|
1064
|
-
return
|
|
1065
|
-
type: "image",
|
|
1066
|
-
source: {
|
|
1067
|
-
type: "base64",
|
|
1068
|
-
media_type: item.mimeType,
|
|
1069
|
-
data: item.data,
|
|
1070
|
-
},
|
|
1071
|
-
};
|
|
1099
|
+
return convertImageBlock(item);
|
|
1072
1100
|
}
|
|
1073
1101
|
});
|
|
1074
1102
|
const filteredBlocks = blocks.filter((b) => {
|
|
@@ -1086,7 +1114,6 @@ convertToolDefinitions) {
|
|
|
1086
1114
|
}
|
|
1087
1115
|
}
|
|
1088
1116
|
else if (msg.role === "assistant") {
|
|
1089
|
-
flushPendingSystemMessages();
|
|
1090
1117
|
const blocks = [];
|
|
1091
1118
|
for (const block of msg.content) {
|
|
1092
1119
|
if (block.type === "text") {
|
|
@@ -1144,6 +1171,7 @@ convertToolDefinitions) {
|
|
|
1144
1171
|
}
|
|
1145
1172
|
if (blocks.length === 0)
|
|
1146
1173
|
continue;
|
|
1174
|
+
flushPendingSystemMessages();
|
|
1147
1175
|
const messageIndex = params.length;
|
|
1148
1176
|
params.push({
|
|
1149
1177
|
role: "assistant",
|
|
@@ -1159,16 +1187,24 @@ convertToolDefinitions) {
|
|
|
1159
1187
|
else if (msg.role === "toolResult") {
|
|
1160
1188
|
// Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint.
|
|
1161
1189
|
const toolResults = [];
|
|
1190
|
+
// Anthropic rejects error tool results that contain anything but text, so their images follow
|
|
1191
|
+
// all tool results of the turn, which must come first in the user message (#10794).
|
|
1192
|
+
const errorImages = [];
|
|
1162
1193
|
let j = i;
|
|
1163
1194
|
while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
|
|
1164
|
-
|
|
1195
|
+
const toolMsg = transformedMessages[j];
|
|
1196
|
+
const split = splitErrorToolResultImages(toolMsg);
|
|
1197
|
+
toolResults.push(convertToolResult(toolMsg, split?.content));
|
|
1198
|
+
if (split) {
|
|
1199
|
+
errorImages.push({ type: "text", text: split.caption }, ...split.images.map(convertImageBlock));
|
|
1200
|
+
}
|
|
1165
1201
|
j++;
|
|
1166
1202
|
}
|
|
1167
1203
|
// Skip the messages we've already processed.
|
|
1168
1204
|
i = j - 1;
|
|
1169
1205
|
params.push({
|
|
1170
1206
|
role: "user",
|
|
1171
|
-
content: toolResults,
|
|
1207
|
+
content: [...toolResults, ...errorImages],
|
|
1172
1208
|
});
|
|
1173
1209
|
}
|
|
1174
1210
|
}
|
|
@@ -1255,11 +1291,14 @@ const isAnthropicStrictUnsupportedKeyword = (key, value) => {
|
|
|
1255
1291
|
return typeof value !== "string" || !ANTHROPIC_STRICT_STRING_FORMATS.has(value);
|
|
1256
1292
|
return false;
|
|
1257
1293
|
};
|
|
1258
|
-
function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, supportsStrictTools, cacheControl) {
|
|
1294
|
+
function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, supportsStrictTools, cacheControl, disablePreferredStrictTools = false) {
|
|
1259
1295
|
if (!tools)
|
|
1260
1296
|
return [];
|
|
1261
1297
|
return tools.map((tool, index) => {
|
|
1262
|
-
const
|
|
1298
|
+
const config = tool.constrainedSampling;
|
|
1299
|
+
const strict = disablePreferredStrictTools && config && config.type === "json_schema" && config.strict === "prefer"
|
|
1300
|
+
? undefined
|
|
1301
|
+
: resolveJsonSchemaStrictSampling(tool, supportsStrictTools, isAnthropicStrictUnsupportedKeyword);
|
|
1263
1302
|
const parameters = getJsonSchemaToolParameters(tool, strict);
|
|
1264
1303
|
const schema = parameters;
|
|
1265
1304
|
const legacyInputSchema = {
|