@yourgpt/llm-sdk 2.6.0-beta.3 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +46 -10
- package/dist/adapters/index.d.mts +11 -13
- package/dist/adapters/index.d.ts +11 -13
- package/dist/adapters/index.js +327 -100
- package/dist/adapters/index.mjs +327 -100
- package/dist/audio-K-Z3-Bce.d.mts +191 -0
- package/dist/audio-K-Z3-Bce.d.ts +191 -0
- package/dist/{base-BICaQaRS.d.mts → base-6LzczuCg.d.ts} +8 -1
- package/dist/{base-CpRPB8u8.d.ts → base-DySbTP8C.d.mts} +8 -1
- package/dist/decisions-CJzOt87t.d.mts +137 -0
- package/dist/decisions-CJzOt87t.d.ts +137 -0
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/http-BQxUT5A9.d.mts +9 -0
- package/dist/http-BQxUT5A9.d.ts +9 -0
- package/dist/index.d.mts +14 -8
- package/dist/index.d.ts +14 -8
- package/dist/index.js +599 -195
- package/dist/index.mjs +596 -196
- package/dist/providers/anthropic/index.d.mts +7 -4
- package/dist/providers/anthropic/index.d.ts +7 -4
- package/dist/providers/anthropic/index.js +383 -102
- package/dist/providers/anthropic/index.mjs +383 -102
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/cloudflare/index.d.mts +11 -0
- package/dist/providers/cloudflare/index.d.ts +11 -0
- package/dist/providers/cloudflare/index.js +743 -0
- package/dist/providers/cloudflare/index.mjs +741 -0
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +108 -59
- package/dist/providers/fireworks/index.mjs +108 -59
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +108 -59
- package/dist/providers/google/index.mjs +108 -59
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/openai/index.d.mts +38 -6
- package/dist/providers/openai/index.d.ts +38 -6
- package/dist/providers/openai/index.js +1378 -84
- package/dist/providers/openai/index.mjs +1376 -85
- package/dist/providers/openrouter/index.d.mts +21 -4
- package/dist/providers/openrouter/index.d.ts +21 -4
- package/dist/providers/openrouter/index.js +967 -130
- package/dist/providers/openrouter/index.mjs +967 -131
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +108 -59
- package/dist/providers/togetherai/index.mjs +108 -59
- package/dist/providers/typesafe/index.d.mts +8 -0
- package/dist/providers/typesafe/index.d.ts +8 -0
- package/dist/providers/typesafe/index.js +735 -0
- package/dist/providers/typesafe/index.mjs +733 -0
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +108 -59
- package/dist/providers/xai/index.mjs +108 -59
- package/dist/{types-DCFqkJAy.d.ts → types-B0y6VZSQ.d.ts} +1 -1
- package/dist/{types-DHQEMFHA.d.mts → types-BXQMtaCX.d.ts} +17 -3
- package/dist/{types-C3RgRbEC.d.mts → types-BY6BVhFg.d.mts} +1 -1
- package/dist/{types-Dikj3En4.d.ts → types-C7_qVSSd.d.mts} +17 -3
- package/dist/{types-Dg1Bcg1k.d.mts → types-D7lzMMLu.d.mts} +13 -1
- package/dist/{types-Dg1Bcg1k.d.ts → types-D7lzMMLu.d.ts} +13 -1
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/docs/decisions.md +174 -0
- package/docs/media.md +201 -0
- package/docs/multimodal-and-audio.md +9 -2
- package/package.json +34 -12
- package/dist/audio-BBSwnjo8.d.mts +0 -92
- package/dist/audio-BBSwnjo8.d.ts +0 -92
|
@@ -85,6 +85,120 @@ function toolOutputForProvider(value, provider) {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// src/core/provider-error.ts
|
|
89
|
+
function invalidProviderResponse(message) {
|
|
90
|
+
return Object.assign(new Error(message), {
|
|
91
|
+
name: "InvalidProviderResponseError",
|
|
92
|
+
status: 502,
|
|
93
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function providerErrorEvent(error, code) {
|
|
97
|
+
const details = error ?? {};
|
|
98
|
+
const event = {
|
|
99
|
+
type: "error",
|
|
100
|
+
message: error instanceof Error ? error.message : String(error),
|
|
101
|
+
code,
|
|
102
|
+
...typeof details.status === "number" ? { status: details.status } : {},
|
|
103
|
+
...typeof details.code === "string" ? { providerCode: details.code } : {},
|
|
104
|
+
...typeof details.param === "string" ? { param: details.param } : {},
|
|
105
|
+
...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
|
|
106
|
+
};
|
|
107
|
+
Object.defineProperty(event, "cause", { value: error, enumerable: false });
|
|
108
|
+
return event;
|
|
109
|
+
}
|
|
110
|
+
function throwIfAborted(signal) {
|
|
111
|
+
if (!signal?.aborted) return;
|
|
112
|
+
const error = new Error("The operation was aborted");
|
|
113
|
+
error.name = "AbortError";
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/core/tool-validation.ts
|
|
118
|
+
function parseToolArguments(value) {
|
|
119
|
+
let args = value;
|
|
120
|
+
if (typeof value === "string") {
|
|
121
|
+
try {
|
|
122
|
+
args = JSON.parse(value || "{}");
|
|
123
|
+
} catch {
|
|
124
|
+
throw invalidProviderResponse("Tool arguments are not valid JSON");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (args === null || typeof args !== "object" || Array.isArray(args))
|
|
128
|
+
throw invalidProviderResponse("Tool arguments must be a JSON object");
|
|
129
|
+
return args;
|
|
130
|
+
}
|
|
131
|
+
function validateToolCalls(calls) {
|
|
132
|
+
const ids = /* @__PURE__ */ new Set();
|
|
133
|
+
for (const call of calls) {
|
|
134
|
+
if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
|
|
135
|
+
throw invalidProviderResponse(
|
|
136
|
+
"Tool calls have missing or duplicate identities"
|
|
137
|
+
);
|
|
138
|
+
ids.add(call.id);
|
|
139
|
+
if (typeof call.args === "string")
|
|
140
|
+
throw invalidProviderResponse("Parsed tool arguments must be an object");
|
|
141
|
+
parseToolArguments(call.args);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/core/anthropic-replay.ts
|
|
146
|
+
function anthropicReplay(content) {
|
|
147
|
+
if (!Array.isArray(content) || !content.some(
|
|
148
|
+
(b) => b?.type === "thinking" || b?.type === "redacted_thinking"
|
|
149
|
+
))
|
|
150
|
+
return void 0;
|
|
151
|
+
const blocks = content.flatMap((block) => {
|
|
152
|
+
if (block?.type === "thinking" && typeof block.thinking === "string" && typeof block.signature === "string")
|
|
153
|
+
return [
|
|
154
|
+
{
|
|
155
|
+
type: "thinking",
|
|
156
|
+
thinking: block.thinking,
|
|
157
|
+
signature: block.signature
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
if (block?.type === "redacted_thinking" && typeof block.data === "string")
|
|
161
|
+
return [{ type: "redacted_thinking", data: block.data }];
|
|
162
|
+
if (block?.type === "text" && typeof block.text === "string")
|
|
163
|
+
return [{ type: "text", text: block.text }];
|
|
164
|
+
if (block?.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string")
|
|
165
|
+
return [
|
|
166
|
+
{
|
|
167
|
+
type: "tool_use",
|
|
168
|
+
id: block.id,
|
|
169
|
+
name: block.name,
|
|
170
|
+
input: block.input
|
|
171
|
+
}
|
|
172
|
+
];
|
|
173
|
+
return [];
|
|
174
|
+
});
|
|
175
|
+
return { anthropic: { content: blocks } };
|
|
176
|
+
}
|
|
177
|
+
function anthropicReplayContent(metadata) {
|
|
178
|
+
const state = metadata?.anthropic;
|
|
179
|
+
return anthropicReplay(state?.content)?.anthropic?.content;
|
|
180
|
+
}
|
|
181
|
+
function collectAnthropicContent(blocks, event) {
|
|
182
|
+
if (event.type === "content_block_start")
|
|
183
|
+
blocks[event.index] = { ...event.content_block };
|
|
184
|
+
const block = blocks[event.index];
|
|
185
|
+
if (event.type !== "content_block_delta" || !block) return;
|
|
186
|
+
const delta = event.delta;
|
|
187
|
+
if (delta.type === "thinking_delta")
|
|
188
|
+
block.thinking = (block.thinking ?? "") + delta.thinking;
|
|
189
|
+
else if (delta.type === "signature_delta")
|
|
190
|
+
block.signature = (block.signature ?? "") + delta.signature;
|
|
191
|
+
else if (delta.type === "text_delta")
|
|
192
|
+
block.text = (block.text ?? "") + delta.text;
|
|
193
|
+
else if (delta.type === "input_json_delta") {
|
|
194
|
+
block.partialInput = (block.partialInput ?? "") + delta.partial_json;
|
|
195
|
+
try {
|
|
196
|
+
block.input = JSON.parse(block.partialInput);
|
|
197
|
+
} catch {
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
88
202
|
// src/adapters/base.ts
|
|
89
203
|
function stringifyForDebug(value) {
|
|
90
204
|
return JSON.stringify(
|
|
@@ -163,7 +277,22 @@ function stripSchemaKeys(schema, keysToDrop, options = {}) {
|
|
|
163
277
|
)) {
|
|
164
278
|
if (keysToDrop.has(key)) continue;
|
|
165
279
|
const renamed = options.renameKeys?.[key] ?? key;
|
|
166
|
-
|
|
280
|
+
if ([
|
|
281
|
+
"properties",
|
|
282
|
+
"$defs",
|
|
283
|
+
"definitions",
|
|
284
|
+
"patternProperties",
|
|
285
|
+
"dependentSchemas"
|
|
286
|
+
].includes(key) && value && typeof value === "object" && !Array.isArray(value)) {
|
|
287
|
+
out[renamed] = Object.fromEntries(
|
|
288
|
+
Object.entries(value).map(([name, child]) => [
|
|
289
|
+
name,
|
|
290
|
+
stripSchemaKeys(child, keysToDrop, options)
|
|
291
|
+
])
|
|
292
|
+
);
|
|
293
|
+
} else if (["enum", "const", "default", "examples"].includes(key)) {
|
|
294
|
+
out[renamed] = value;
|
|
295
|
+
} else out[renamed] = stripSchemaKeys(value, keysToDrop, options);
|
|
167
296
|
}
|
|
168
297
|
if (options.forceAdditionalPropertiesFalse && out.type === "object") {
|
|
169
298
|
out.additionalProperties = false;
|
|
@@ -310,6 +439,14 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
310
439
|
const msg = messages[i];
|
|
311
440
|
if (msg.role === "system") continue;
|
|
312
441
|
if (msg.role === "assistant") {
|
|
442
|
+
const replay = anthropicReplayContent(msg.providerMetadata);
|
|
443
|
+
if (replay) {
|
|
444
|
+
formatted.push({
|
|
445
|
+
role: "assistant",
|
|
446
|
+
content: replay
|
|
447
|
+
});
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
313
450
|
const content = [];
|
|
314
451
|
if (msg.content) {
|
|
315
452
|
content.push({ type: "text", text: msg.content });
|
|
@@ -364,6 +501,52 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
364
501
|
};
|
|
365
502
|
}
|
|
366
503
|
|
|
504
|
+
// src/core/anthropic-parameters.ts
|
|
505
|
+
function anthropicMaxTokens(maxTokens, thinking) {
|
|
506
|
+
return maxTokens ?? Math.max(4096, Number(thinking?.budget_tokens ?? 0) + 1);
|
|
507
|
+
}
|
|
508
|
+
function anthropicModelRules(model) {
|
|
509
|
+
const match = /^claude-(opus|sonnet|haiku)-(\d+)(?:-(\d{1,2})(?=-|$))?(?:-|$)/i.exec(
|
|
510
|
+
model
|
|
511
|
+
);
|
|
512
|
+
const family = match?.[1]?.toLowerCase();
|
|
513
|
+
const major = Number(match?.[2] ?? 0);
|
|
514
|
+
const minor = Number(match?.[3] ?? 0);
|
|
515
|
+
const adaptive = major >= 5 || major === 4 && minor >= 6;
|
|
516
|
+
return {
|
|
517
|
+
structured: major >= 5 || major === 4 && minor >= 5,
|
|
518
|
+
thinking: major >= 4 || /^claude-3-7-/.test(model),
|
|
519
|
+
adaptive,
|
|
520
|
+
rejectsSampling: major >= 5 || family === "opus" && major === 4 && minor >= 7
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
function anthropicInputTokens(usage) {
|
|
524
|
+
return (usage?.input_tokens ?? 0) + (usage?.cache_creation_input_tokens ?? 0) + (usage?.cache_read_input_tokens ?? 0);
|
|
525
|
+
}
|
|
526
|
+
function anthropicThinking(model, thinking) {
|
|
527
|
+
if (!thinking) return void 0;
|
|
528
|
+
if (thinking.type === "enabled") {
|
|
529
|
+
if (anthropicModelRules(model).adaptive) {
|
|
530
|
+
console.warn(
|
|
531
|
+
`[llm-sdk] ${model}: using adaptive thinking instead of a legacy token budget.`
|
|
532
|
+
);
|
|
533
|
+
return { type: "adaptive" };
|
|
534
|
+
}
|
|
535
|
+
return { type: "enabled", budget_tokens: thinking.budgetTokens ?? 1e4 };
|
|
536
|
+
}
|
|
537
|
+
return { ...thinking };
|
|
538
|
+
}
|
|
539
|
+
function anthropicTemperature(model, temperature, thinking = false) {
|
|
540
|
+
if (temperature === void 0) return {};
|
|
541
|
+
if (thinking || anthropicModelRules(model).rejectsSampling) {
|
|
542
|
+
console.warn(
|
|
543
|
+
`[llm-sdk] ${model}: omitted temperature because this model or thinking mode does not support it.`
|
|
544
|
+
);
|
|
545
|
+
return {};
|
|
546
|
+
}
|
|
547
|
+
return { temperature };
|
|
548
|
+
}
|
|
549
|
+
|
|
367
550
|
// src/providers/anthropic/provider.ts
|
|
368
551
|
var ANTHROPIC_MODELS = {
|
|
369
552
|
// Claude 4 series
|
|
@@ -473,6 +656,10 @@ function anthropic(modelId, options = {}) {
|
|
|
473
656
|
return client;
|
|
474
657
|
}
|
|
475
658
|
const modelConfig = ANTHROPIC_MODELS[modelId] ?? ANTHROPIC_MODELS["claude-3-5-sonnet-latest"];
|
|
659
|
+
const thinking = anthropicThinking(
|
|
660
|
+
modelId,
|
|
661
|
+
options.thinking && ("enabled" in options.thinking ? options.thinking.enabled ? { type: "enabled", budgetTokens: options.thinking.budgetTokens } : void 0 : options.thinking)
|
|
662
|
+
);
|
|
476
663
|
return {
|
|
477
664
|
provider: "anthropic",
|
|
478
665
|
modelId,
|
|
@@ -480,8 +667,8 @@ function anthropic(modelId, options = {}) {
|
|
|
480
667
|
supportsVision: modelConfig.vision,
|
|
481
668
|
supportsTools: modelConfig.tools,
|
|
482
669
|
supportsStreaming: true,
|
|
483
|
-
supportsJsonMode:
|
|
484
|
-
supportsThinking: modelConfig.thinking,
|
|
670
|
+
supportsJsonMode: anthropicModelRules(modelId).structured,
|
|
671
|
+
supportsThinking: modelConfig.thinking || anthropicModelRules(modelId).thinking,
|
|
485
672
|
supportsPDF: modelConfig.pdf,
|
|
486
673
|
maxTokens: modelConfig.maxTokens,
|
|
487
674
|
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
@@ -491,25 +678,34 @@ function anthropic(modelId, options = {}) {
|
|
|
491
678
|
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
492
679
|
const requestOptions = {
|
|
493
680
|
model: modelId,
|
|
494
|
-
max_tokens: params.maxTokens
|
|
681
|
+
max_tokens: anthropicMaxTokens(params.maxTokens, thinking),
|
|
495
682
|
system: system || void 0,
|
|
496
683
|
messages,
|
|
497
|
-
tools: params.tools
|
|
684
|
+
tools: params.tools,
|
|
685
|
+
...options.cacheControl ? { cache_control: { type: "ephemeral" } } : {}
|
|
498
686
|
};
|
|
499
|
-
|
|
500
|
-
requestOptions
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
type
|
|
505
|
-
|
|
506
|
-
|
|
687
|
+
Object.assign(
|
|
688
|
+
requestOptions,
|
|
689
|
+
anthropicTemperature(
|
|
690
|
+
modelId,
|
|
691
|
+
params.temperature,
|
|
692
|
+
!!thinking && thinking.type !== "disabled"
|
|
693
|
+
)
|
|
694
|
+
);
|
|
695
|
+
if (params.responseFormat?.type === "json_object") {
|
|
696
|
+
requestOptions.system = (system || "") + "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences.";
|
|
507
697
|
}
|
|
698
|
+
if (thinking) requestOptions.thinking = thinking;
|
|
508
699
|
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
509
|
-
if (outputConfig) {
|
|
510
|
-
requestOptions.output_config =
|
|
700
|
+
if (outputConfig || options.effort) {
|
|
701
|
+
requestOptions.output_config = {
|
|
702
|
+
...outputConfig,
|
|
703
|
+
...options.effort ? { effort: options.effort } : {}
|
|
704
|
+
};
|
|
511
705
|
}
|
|
512
|
-
const response = await client2.messages.create(requestOptions
|
|
706
|
+
const response = await client2.messages.create(requestOptions, {
|
|
707
|
+
signal: params.signal
|
|
708
|
+
});
|
|
513
709
|
let text = "";
|
|
514
710
|
const toolCalls = [];
|
|
515
711
|
for (const block of response.content) {
|
|
@@ -523,14 +719,21 @@ function anthropic(modelId, options = {}) {
|
|
|
523
719
|
});
|
|
524
720
|
}
|
|
525
721
|
}
|
|
722
|
+
validateToolCalls(toolCalls);
|
|
723
|
+
if (toolCalls.length && response.stop_reason !== "tool_use")
|
|
724
|
+
throw invalidProviderResponse(
|
|
725
|
+
"Anthropic response ended with incomplete tool calls"
|
|
726
|
+
);
|
|
526
727
|
return {
|
|
527
728
|
text,
|
|
729
|
+
reasoningText: response.content.filter((b) => b.type === "thinking").map((b) => b.thinking).join("") || void 0,
|
|
730
|
+
providerMetadata: anthropicReplay(response.content),
|
|
528
731
|
toolCalls,
|
|
529
732
|
finishReason: mapFinishReason(response.stop_reason),
|
|
530
733
|
usage: {
|
|
531
|
-
promptTokens: response.usage
|
|
734
|
+
promptTokens: anthropicInputTokens(response.usage),
|
|
532
735
|
completionTokens: response.usage?.output_tokens ?? 0,
|
|
533
|
-
totalTokens: (response.usage
|
|
736
|
+
totalTokens: anthropicInputTokens(response.usage) + (response.usage?.output_tokens ?? 0)
|
|
534
737
|
},
|
|
535
738
|
rawResponse: response
|
|
536
739
|
};
|
|
@@ -540,37 +743,47 @@ function anthropic(modelId, options = {}) {
|
|
|
540
743
|
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
541
744
|
const requestOptions = {
|
|
542
745
|
model: modelId,
|
|
543
|
-
max_tokens: params.maxTokens
|
|
746
|
+
max_tokens: anthropicMaxTokens(params.maxTokens, thinking),
|
|
544
747
|
system: system || void 0,
|
|
545
748
|
messages,
|
|
546
|
-
tools: params.tools
|
|
749
|
+
tools: params.tools,
|
|
750
|
+
...options.cacheControl ? { cache_control: { type: "ephemeral" } } : {}
|
|
547
751
|
};
|
|
548
|
-
|
|
549
|
-
requestOptions
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
type
|
|
554
|
-
|
|
555
|
-
|
|
752
|
+
Object.assign(
|
|
753
|
+
requestOptions,
|
|
754
|
+
anthropicTemperature(
|
|
755
|
+
modelId,
|
|
756
|
+
params.temperature,
|
|
757
|
+
!!thinking && thinking.type !== "disabled"
|
|
758
|
+
)
|
|
759
|
+
);
|
|
760
|
+
if (params.responseFormat?.type === "json_object") {
|
|
761
|
+
requestOptions.system = (system || "") + "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences.";
|
|
556
762
|
}
|
|
763
|
+
if (thinking) requestOptions.thinking = thinking;
|
|
557
764
|
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
558
|
-
if (outputConfig) {
|
|
559
|
-
requestOptions.output_config =
|
|
765
|
+
if (outputConfig || options.effort) {
|
|
766
|
+
requestOptions.output_config = {
|
|
767
|
+
...outputConfig,
|
|
768
|
+
...options.effort ? { effort: options.effort } : {}
|
|
769
|
+
};
|
|
560
770
|
}
|
|
561
|
-
const stream = await client2.messages.stream(requestOptions
|
|
771
|
+
const stream = await client2.messages.stream(requestOptions, {
|
|
772
|
+
signal: params.signal
|
|
773
|
+
});
|
|
562
774
|
let currentToolUse = null;
|
|
563
775
|
let inputTokens = 0;
|
|
564
776
|
let outputTokens = 0;
|
|
777
|
+
const content = [];
|
|
778
|
+
const toolCalls = [];
|
|
779
|
+
let stopReason;
|
|
565
780
|
for await (const event of stream) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
781
|
+
collectAnthropicContent(content, event);
|
|
782
|
+
throwIfAborted(params.signal);
|
|
570
783
|
switch (event.type) {
|
|
571
784
|
case "message_start":
|
|
572
785
|
if (event.message?.usage) {
|
|
573
|
-
inputTokens = event.message.usage
|
|
786
|
+
inputTokens = anthropicInputTokens(event.message.usage);
|
|
574
787
|
}
|
|
575
788
|
break;
|
|
576
789
|
case "content_block_start":
|
|
@@ -585,20 +798,19 @@ function anthropic(modelId, options = {}) {
|
|
|
585
798
|
case "content_block_delta":
|
|
586
799
|
if (event.delta?.type === "text_delta") {
|
|
587
800
|
yield { type: "text-delta", text: event.delta.text };
|
|
801
|
+
} else if (event.delta?.type === "thinking_delta") {
|
|
802
|
+
yield { type: "reasoning-delta", text: event.delta.thinking };
|
|
588
803
|
} else if (event.delta?.type === "input_json_delta" && currentToolUse) {
|
|
589
804
|
currentToolUse.input += event.delta.partial_json;
|
|
590
805
|
}
|
|
591
806
|
break;
|
|
592
807
|
case "content_block_stop":
|
|
593
808
|
if (currentToolUse) {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
args: JSON.parse(currentToolUse.input || "{}")
|
|
600
|
-
}
|
|
601
|
-
};
|
|
809
|
+
toolCalls.push({
|
|
810
|
+
id: currentToolUse.id,
|
|
811
|
+
name: currentToolUse.name,
|
|
812
|
+
args: parseToolArguments(currentToolUse.input)
|
|
813
|
+
});
|
|
602
814
|
currentToolUse = null;
|
|
603
815
|
}
|
|
604
816
|
break;
|
|
@@ -607,19 +819,32 @@ function anthropic(modelId, options = {}) {
|
|
|
607
819
|
outputTokens = event.usage.output_tokens ?? 0;
|
|
608
820
|
}
|
|
609
821
|
if (event.delta?.stop_reason) {
|
|
610
|
-
|
|
611
|
-
type: "finish",
|
|
612
|
-
finishReason: mapFinishReason(event.delta.stop_reason),
|
|
613
|
-
usage: {
|
|
614
|
-
promptTokens: inputTokens,
|
|
615
|
-
completionTokens: outputTokens,
|
|
616
|
-
totalTokens: inputTokens + outputTokens
|
|
617
|
-
}
|
|
618
|
-
};
|
|
822
|
+
stopReason = event.delta.stop_reason;
|
|
619
823
|
}
|
|
620
824
|
break;
|
|
621
825
|
}
|
|
622
826
|
}
|
|
827
|
+
throwIfAborted(params.signal);
|
|
828
|
+
if (!stopReason || currentToolUse)
|
|
829
|
+
throw invalidProviderResponse(
|
|
830
|
+
"Anthropic stream ended before its turn completed"
|
|
831
|
+
);
|
|
832
|
+
validateToolCalls(toolCalls);
|
|
833
|
+
if (toolCalls.length && stopReason !== "tool_use")
|
|
834
|
+
throw invalidProviderResponse(
|
|
835
|
+
"Anthropic stream ended with incomplete tool calls"
|
|
836
|
+
);
|
|
837
|
+
for (const toolCall of toolCalls) yield { type: "tool-call", toolCall };
|
|
838
|
+
yield {
|
|
839
|
+
type: "finish",
|
|
840
|
+
finishReason: mapFinishReason(stopReason),
|
|
841
|
+
providerMetadata: anthropicReplay(content),
|
|
842
|
+
usage: {
|
|
843
|
+
promptTokens: inputTokens,
|
|
844
|
+
completionTokens: outputTokens,
|
|
845
|
+
totalTokens: inputTokens + outputTokens
|
|
846
|
+
}
|
|
847
|
+
};
|
|
623
848
|
}
|
|
624
849
|
};
|
|
625
850
|
}
|
|
@@ -637,7 +862,7 @@ function mapFinishReason(reason) {
|
|
|
637
862
|
}
|
|
638
863
|
}
|
|
639
864
|
function formatMessagesForAnthropic2(messages) {
|
|
640
|
-
|
|
865
|
+
const system = extractAnthropicSystemPrompt(messages);
|
|
641
866
|
const formatted = [];
|
|
642
867
|
const pendingToolResults = [];
|
|
643
868
|
const flushToolResults = () => {
|
|
@@ -663,7 +888,6 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
663
888
|
};
|
|
664
889
|
for (const msg of messages) {
|
|
665
890
|
if (msg.role === "system") {
|
|
666
|
-
system += (system ? "\n" : "") + msg.content;
|
|
667
891
|
continue;
|
|
668
892
|
}
|
|
669
893
|
if (msg.role === "assistant" && pendingToolResults.length > 0) {
|
|
@@ -701,6 +925,11 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
701
925
|
formatted.push({ role: "user", content });
|
|
702
926
|
}
|
|
703
927
|
} else if (msg.role === "assistant") {
|
|
928
|
+
const replay = anthropicReplayContent(msg.providerMetadata);
|
|
929
|
+
if (replay) {
|
|
930
|
+
formatted.push({ role: "assistant", content: replay });
|
|
931
|
+
continue;
|
|
932
|
+
}
|
|
704
933
|
const content = [];
|
|
705
934
|
if (msg.content) {
|
|
706
935
|
content.push({ type: "text", text: msg.content });
|
|
@@ -756,7 +985,10 @@ var AnthropicAdapter = class {
|
|
|
756
985
|
if (!this.client) {
|
|
757
986
|
const { default: Anthropic } = await import('@anthropic-ai/sdk');
|
|
758
987
|
this.client = new Anthropic({
|
|
759
|
-
apiKey: this.config.apiKey
|
|
988
|
+
apiKey: this.config.apiKey,
|
|
989
|
+
baseURL: this.config.baseUrl,
|
|
990
|
+
timeout: this.config.timeout,
|
|
991
|
+
defaultHeaders: this.config.headers
|
|
760
992
|
});
|
|
761
993
|
}
|
|
762
994
|
return this.client;
|
|
@@ -793,6 +1025,15 @@ var AnthropicAdapter = class {
|
|
|
793
1025
|
lastToolCallIds = [];
|
|
794
1026
|
toolResultIndex = 0;
|
|
795
1027
|
}
|
|
1028
|
+
const replay = anthropicReplayContent(
|
|
1029
|
+
msg.providerMetadata
|
|
1030
|
+
);
|
|
1031
|
+
if (replay) {
|
|
1032
|
+
messages.push({ role: "assistant", content: replay });
|
|
1033
|
+
lastToolCallIds = replay.filter((b) => b.type === "tool_use").map((b) => b.id);
|
|
1034
|
+
toolResultIndex = 0;
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
796
1037
|
const content = [];
|
|
797
1038
|
if (msg.content && typeof msg.content === "string" && msg.content.trim()) {
|
|
798
1039
|
content.push({ type: "text", text: msg.content });
|
|
@@ -968,7 +1209,7 @@ var AnthropicAdapter = class {
|
|
|
968
1209
|
*/
|
|
969
1210
|
buildRequestOptions(request) {
|
|
970
1211
|
const responseFormat = request.config?.responseFormat;
|
|
971
|
-
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text." : "";
|
|
1212
|
+
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences." : "";
|
|
972
1213
|
let systemMessage;
|
|
973
1214
|
let messages;
|
|
974
1215
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
@@ -990,7 +1231,17 @@ var AnthropicAdapter = class {
|
|
|
990
1231
|
const tools = anthropicNativeSearch?.enabled ? this.buildNativeSearchTools(
|
|
991
1232
|
request.toolDefinitions ?? [],
|
|
992
1233
|
anthropicNativeSearch.variant
|
|
993
|
-
) : request.
|
|
1234
|
+
) : request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
|
|
1235
|
+
name: tool.name,
|
|
1236
|
+
description: tool.description,
|
|
1237
|
+
// Keep the original schema. Legacy ActionParameter conversion
|
|
1238
|
+
// cannot represent unions, null, or nested required constraints.
|
|
1239
|
+
input_schema: tool.inputSchema ?? {
|
|
1240
|
+
type: "object",
|
|
1241
|
+
properties: {},
|
|
1242
|
+
required: []
|
|
1243
|
+
}
|
|
1244
|
+
})) : request.actions?.map((action) => ({
|
|
994
1245
|
name: action.name,
|
|
995
1246
|
description: action.description,
|
|
996
1247
|
input_schema: {
|
|
@@ -1032,12 +1283,25 @@ var AnthropicAdapter = class {
|
|
|
1032
1283
|
};
|
|
1033
1284
|
}
|
|
1034
1285
|
}
|
|
1286
|
+
const thinking = anthropicThinking(
|
|
1287
|
+
request.config?.model || this.model,
|
|
1288
|
+
this.config.thinking
|
|
1289
|
+
);
|
|
1035
1290
|
const options = {
|
|
1036
1291
|
model: request.config?.model || this.model,
|
|
1037
|
-
max_tokens:
|
|
1292
|
+
max_tokens: anthropicMaxTokens(
|
|
1293
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1294
|
+
thinking
|
|
1295
|
+
),
|
|
1038
1296
|
system: systemMessage,
|
|
1039
1297
|
messages,
|
|
1040
|
-
tools: tools.length ? tools : void 0
|
|
1298
|
+
tools: tools.length ? tools : void 0,
|
|
1299
|
+
...this.config.cacheControl ? { cache_control: { type: "ephemeral" } } : {},
|
|
1300
|
+
...anthropicTemperature(
|
|
1301
|
+
request.config?.model || this.model,
|
|
1302
|
+
request.config?.temperature ?? this.config.temperature,
|
|
1303
|
+
!!this.config.thinking && this.config.thinking.type !== "disabled"
|
|
1304
|
+
)
|
|
1041
1305
|
};
|
|
1042
1306
|
const anthropicToolOptions = request.providerToolOptions?.anthropic;
|
|
1043
1307
|
if (tools.length > 0 && anthropicToolOptions) {
|
|
@@ -1056,15 +1320,13 @@ var AnthropicAdapter = class {
|
|
|
1056
1320
|
options.server_tool_configuration = serverToolConfiguration;
|
|
1057
1321
|
}
|
|
1058
1322
|
const outputConfig = toAnthropicOutputConfig(responseFormat);
|
|
1059
|
-
if (outputConfig) {
|
|
1060
|
-
options.output_config =
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
options.thinking = {
|
|
1064
|
-
type: "enabled",
|
|
1065
|
-
budget_tokens: this.config.thinking.budgetTokens || 1e4
|
|
1323
|
+
if (outputConfig || this.config.effort) {
|
|
1324
|
+
options.output_config = {
|
|
1325
|
+
...outputConfig,
|
|
1326
|
+
...this.config.effort ? { effort: this.config.effort } : {}
|
|
1066
1327
|
};
|
|
1067
1328
|
}
|
|
1329
|
+
if (thinking) options.thinking = thinking;
|
|
1068
1330
|
return { options, messages };
|
|
1069
1331
|
}
|
|
1070
1332
|
/**
|
|
@@ -1084,7 +1346,9 @@ var AnthropicAdapter = class {
|
|
|
1084
1346
|
nonStreamingOptions,
|
|
1085
1347
|
request.debug
|
|
1086
1348
|
);
|
|
1087
|
-
const response = await client.messages.create(nonStreamingOptions
|
|
1349
|
+
const response = await client.messages.create(nonStreamingOptions, {
|
|
1350
|
+
signal: request.signal
|
|
1351
|
+
});
|
|
1088
1352
|
logProviderPayload(
|
|
1089
1353
|
"anthropic",
|
|
1090
1354
|
"response payload",
|
|
@@ -1107,14 +1371,20 @@ var AnthropicAdapter = class {
|
|
|
1107
1371
|
});
|
|
1108
1372
|
}
|
|
1109
1373
|
}
|
|
1374
|
+
validateToolCalls(toolCalls);
|
|
1375
|
+
if (toolCalls.length && response.stop_reason !== "tool_use")
|
|
1376
|
+
throw invalidProviderResponse(
|
|
1377
|
+
"Anthropic response ended with incomplete tool calls"
|
|
1378
|
+
);
|
|
1110
1379
|
return {
|
|
1111
1380
|
content,
|
|
1381
|
+
providerMetadata: anthropicReplay(response.content),
|
|
1112
1382
|
toolCalls,
|
|
1113
1383
|
thinking: thinking || void 0,
|
|
1114
1384
|
usage: response.usage ? {
|
|
1115
|
-
promptTokens: response.usage
|
|
1385
|
+
promptTokens: anthropicInputTokens(response.usage),
|
|
1116
1386
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
1117
|
-
totalTokens: (response.usage
|
|
1387
|
+
totalTokens: anthropicInputTokens(response.usage) + (response.usage.output_tokens ?? 0)
|
|
1118
1388
|
} : void 0,
|
|
1119
1389
|
rawResponse: response
|
|
1120
1390
|
};
|
|
@@ -1134,28 +1404,33 @@ var AnthropicAdapter = class {
|
|
|
1134
1404
|
options,
|
|
1135
1405
|
request.debug
|
|
1136
1406
|
);
|
|
1137
|
-
const stream = await client.messages.stream(options
|
|
1407
|
+
const stream = await client.messages.stream(options, {
|
|
1408
|
+
signal: request.signal
|
|
1409
|
+
});
|
|
1138
1410
|
let currentToolUse = null;
|
|
1139
1411
|
let isInThinkingBlock = false;
|
|
1412
|
+
const content = [];
|
|
1413
|
+
const toolCalls = [];
|
|
1414
|
+
let stopReason;
|
|
1140
1415
|
const collectedCitations = [];
|
|
1141
1416
|
let citationIndex = 0;
|
|
1142
1417
|
let usage;
|
|
1143
1418
|
for await (const event of stream) {
|
|
1419
|
+
collectAnthropicContent(content, event);
|
|
1144
1420
|
logProviderPayload("anthropic", "stream event", event, request.debug);
|
|
1145
|
-
|
|
1146
|
-
break;
|
|
1147
|
-
}
|
|
1421
|
+
throwIfAborted(request.signal);
|
|
1148
1422
|
switch (event.type) {
|
|
1149
1423
|
case "message_start":
|
|
1150
1424
|
if (event.message?.usage) {
|
|
1151
1425
|
usage = {
|
|
1152
|
-
prompt_tokens: event.message.usage
|
|
1426
|
+
prompt_tokens: anthropicInputTokens(event.message.usage),
|
|
1153
1427
|
completion_tokens: 0,
|
|
1154
|
-
total_tokens: event.message.usage
|
|
1428
|
+
total_tokens: anthropicInputTokens(event.message.usage)
|
|
1155
1429
|
};
|
|
1156
1430
|
}
|
|
1157
1431
|
break;
|
|
1158
1432
|
case "message_delta":
|
|
1433
|
+
if (event.delta?.stop_reason) stopReason = event.delta.stop_reason;
|
|
1159
1434
|
if (event.usage && usage) {
|
|
1160
1435
|
usage.completion_tokens = event.usage.output_tokens;
|
|
1161
1436
|
usage.total_tokens = usage.prompt_tokens + event.usage.output_tokens;
|
|
@@ -1168,13 +1443,6 @@ var AnthropicAdapter = class {
|
|
|
1168
1443
|
name: event.content_block.name,
|
|
1169
1444
|
input: ""
|
|
1170
1445
|
};
|
|
1171
|
-
if (currentToolUse.name !== "web_search") {
|
|
1172
|
-
yield {
|
|
1173
|
-
type: "action:start",
|
|
1174
|
-
id: currentToolUse.id,
|
|
1175
|
-
name: currentToolUse.name
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
1446
|
} else if (event.content_block.type === "web_search_tool_result") {
|
|
1179
1447
|
const webSearchResult = event.content_block;
|
|
1180
1448
|
if (webSearchResult.content && Array.isArray(webSearchResult.content)) {
|
|
@@ -1223,16 +1491,11 @@ var AnthropicAdapter = class {
|
|
|
1223
1491
|
case "content_block_stop":
|
|
1224
1492
|
if (currentToolUse) {
|
|
1225
1493
|
if (currentToolUse.name !== "web_search") {
|
|
1226
|
-
|
|
1227
|
-
type: "action:args",
|
|
1494
|
+
toolCalls.push({
|
|
1228
1495
|
id: currentToolUse.id,
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
type: "action:end",
|
|
1233
|
-
id: currentToolUse.id,
|
|
1234
|
-
name: currentToolUse.name
|
|
1235
|
-
};
|
|
1496
|
+
name: currentToolUse.name,
|
|
1497
|
+
args: parseToolArguments(currentToolUse.input)
|
|
1498
|
+
});
|
|
1236
1499
|
}
|
|
1237
1500
|
currentToolUse = null;
|
|
1238
1501
|
}
|
|
@@ -1245,18 +1508,33 @@ var AnthropicAdapter = class {
|
|
|
1245
1508
|
break;
|
|
1246
1509
|
}
|
|
1247
1510
|
}
|
|
1511
|
+
throwIfAborted(request.signal);
|
|
1512
|
+
if (!stopReason || currentToolUse)
|
|
1513
|
+
throw invalidProviderResponse(
|
|
1514
|
+
"Anthropic stream ended before its turn completed"
|
|
1515
|
+
);
|
|
1516
|
+
validateToolCalls(toolCalls);
|
|
1517
|
+
if (toolCalls.length && stopReason !== "tool_use")
|
|
1518
|
+
throw invalidProviderResponse(
|
|
1519
|
+
"Anthropic stream ended with incomplete tool calls"
|
|
1520
|
+
);
|
|
1521
|
+
for (const call of toolCalls) {
|
|
1522
|
+
yield { type: "action:start", id: call.id, name: call.name };
|
|
1523
|
+
yield {
|
|
1524
|
+
type: "action:args",
|
|
1525
|
+
id: call.id,
|
|
1526
|
+
args: JSON.stringify(call.args)
|
|
1527
|
+
};
|
|
1528
|
+
yield { type: "action:end", id: call.id, name: call.name };
|
|
1529
|
+
}
|
|
1248
1530
|
if (collectedCitations.length > 0) {
|
|
1249
1531
|
const uniqueCitations = deduplicateCitations(collectedCitations);
|
|
1250
1532
|
yield { type: "citation", citations: uniqueCitations };
|
|
1251
1533
|
}
|
|
1252
1534
|
yield { type: "message:end" };
|
|
1253
|
-
yield { type: "done", usage };
|
|
1535
|
+
yield { type: "done", usage, providerMetadata: anthropicReplay(content) };
|
|
1254
1536
|
} catch (error) {
|
|
1255
|
-
yield
|
|
1256
|
-
type: "error",
|
|
1257
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
1258
|
-
code: "ANTHROPIC_ERROR"
|
|
1259
|
-
};
|
|
1537
|
+
yield providerErrorEvent(error, "ANTHROPIC_ERROR");
|
|
1260
1538
|
}
|
|
1261
1539
|
}
|
|
1262
1540
|
};
|
|
@@ -1372,7 +1650,11 @@ function createAnthropic(config = {}) {
|
|
|
1372
1650
|
apiKey,
|
|
1373
1651
|
model: modelId,
|
|
1374
1652
|
baseUrl: config.baseUrl,
|
|
1375
|
-
|
|
1653
|
+
timeout: config.timeout,
|
|
1654
|
+
headers: config.headers,
|
|
1655
|
+
cacheControl: config.cacheControl,
|
|
1656
|
+
thinking: config.thinking ?? (config.thinkingBudget ? { type: "enabled", budgetTokens: config.thinkingBudget } : void 0),
|
|
1657
|
+
effort: config.effort
|
|
1376
1658
|
});
|
|
1377
1659
|
};
|
|
1378
1660
|
const getCapabilities = (modelId) => {
|
|
@@ -1380,7 +1662,7 @@ function createAnthropic(config = {}) {
|
|
|
1380
1662
|
return {
|
|
1381
1663
|
supportsVision: model.vision,
|
|
1382
1664
|
supportsTools: model.tools,
|
|
1383
|
-
supportsThinking:
|
|
1665
|
+
supportsThinking: anthropicModelRules(modelId).thinking,
|
|
1384
1666
|
supportsStreaming: true,
|
|
1385
1667
|
supportsPDF: true,
|
|
1386
1668
|
supportsAudio: false,
|
|
@@ -1392,8 +1674,7 @@ function createAnthropic(config = {}) {
|
|
|
1392
1674
|
"image/gif",
|
|
1393
1675
|
"image/webp"
|
|
1394
1676
|
],
|
|
1395
|
-
|
|
1396
|
-
supportsJsonMode: true,
|
|
1677
|
+
supportsJsonMode: anthropicModelRules(modelId).structured,
|
|
1397
1678
|
supportsSystemMessages: true
|
|
1398
1679
|
};
|
|
1399
1680
|
};
|