@yourgpt/llm-sdk 2.6.0-beta.2 → 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 +87 -17
- package/dist/adapters/index.d.mts +11 -13
- package/dist/adapters/index.d.ts +11 -13
- package/dist/adapters/index.js +406 -114
- package/dist/adapters/index.mjs +406 -114
- 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 +17 -9
- package/dist/index.d.ts +17 -9
- package/dist/index.js +698 -205
- package/dist/index.mjs +695 -206
- package/dist/providers/anthropic/index.d.mts +7 -4
- package/dist/providers/anthropic/index.d.ts +7 -4
- package/dist/providers/anthropic/index.js +389 -115
- package/dist/providers/anthropic/index.mjs +389 -115
- 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 +181 -60
- package/dist/providers/fireworks/index.mjs +181 -60
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +181 -60
- package/dist/providers/google/index.mjs +181 -60
- 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 +1451 -85
- package/dist/providers/openai/index.mjs +1449 -86
- package/dist/providers/openrouter/index.d.mts +21 -4
- package/dist/providers/openrouter/index.d.ts +21 -4
- package/dist/providers/openrouter/index.js +1040 -131
- package/dist/providers/openrouter/index.mjs +1040 -132
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +181 -60
- package/dist/providers/togetherai/index.mjs +181 -60
- 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 +181 -60
- package/dist/providers/xai/index.mjs +181 -60
- 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
|
@@ -87,6 +87,120 @@ function toolOutputForProvider(value, provider) {
|
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// src/core/provider-error.ts
|
|
91
|
+
function invalidProviderResponse(message) {
|
|
92
|
+
return Object.assign(new Error(message), {
|
|
93
|
+
name: "InvalidProviderResponseError",
|
|
94
|
+
status: 502,
|
|
95
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function providerErrorEvent(error, code) {
|
|
99
|
+
const details = error ?? {};
|
|
100
|
+
const event = {
|
|
101
|
+
type: "error",
|
|
102
|
+
message: error instanceof Error ? error.message : String(error),
|
|
103
|
+
code,
|
|
104
|
+
...typeof details.status === "number" ? { status: details.status } : {},
|
|
105
|
+
...typeof details.code === "string" ? { providerCode: details.code } : {},
|
|
106
|
+
...typeof details.param === "string" ? { param: details.param } : {},
|
|
107
|
+
...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
|
|
108
|
+
};
|
|
109
|
+
Object.defineProperty(event, "cause", { value: error, enumerable: false });
|
|
110
|
+
return event;
|
|
111
|
+
}
|
|
112
|
+
function throwIfAborted(signal) {
|
|
113
|
+
if (!signal?.aborted) return;
|
|
114
|
+
const error = new Error("The operation was aborted");
|
|
115
|
+
error.name = "AbortError";
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/core/tool-validation.ts
|
|
120
|
+
function parseToolArguments(value) {
|
|
121
|
+
let args = value;
|
|
122
|
+
if (typeof value === "string") {
|
|
123
|
+
try {
|
|
124
|
+
args = JSON.parse(value || "{}");
|
|
125
|
+
} catch {
|
|
126
|
+
throw invalidProviderResponse("Tool arguments are not valid JSON");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (args === null || typeof args !== "object" || Array.isArray(args))
|
|
130
|
+
throw invalidProviderResponse("Tool arguments must be a JSON object");
|
|
131
|
+
return args;
|
|
132
|
+
}
|
|
133
|
+
function validateToolCalls(calls) {
|
|
134
|
+
const ids = /* @__PURE__ */ new Set();
|
|
135
|
+
for (const call of calls) {
|
|
136
|
+
if (!call || typeof call.id !== "string" || !call.id || typeof call.name !== "string" || !call.name || ids.has(call.id))
|
|
137
|
+
throw invalidProviderResponse(
|
|
138
|
+
"Tool calls have missing or duplicate identities"
|
|
139
|
+
);
|
|
140
|
+
ids.add(call.id);
|
|
141
|
+
if (typeof call.args === "string")
|
|
142
|
+
throw invalidProviderResponse("Parsed tool arguments must be an object");
|
|
143
|
+
parseToolArguments(call.args);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/core/anthropic-replay.ts
|
|
148
|
+
function anthropicReplay(content) {
|
|
149
|
+
if (!Array.isArray(content) || !content.some(
|
|
150
|
+
(b) => b?.type === "thinking" || b?.type === "redacted_thinking"
|
|
151
|
+
))
|
|
152
|
+
return void 0;
|
|
153
|
+
const blocks = content.flatMap((block) => {
|
|
154
|
+
if (block?.type === "thinking" && typeof block.thinking === "string" && typeof block.signature === "string")
|
|
155
|
+
return [
|
|
156
|
+
{
|
|
157
|
+
type: "thinking",
|
|
158
|
+
thinking: block.thinking,
|
|
159
|
+
signature: block.signature
|
|
160
|
+
}
|
|
161
|
+
];
|
|
162
|
+
if (block?.type === "redacted_thinking" && typeof block.data === "string")
|
|
163
|
+
return [{ type: "redacted_thinking", data: block.data }];
|
|
164
|
+
if (block?.type === "text" && typeof block.text === "string")
|
|
165
|
+
return [{ type: "text", text: block.text }];
|
|
166
|
+
if (block?.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string")
|
|
167
|
+
return [
|
|
168
|
+
{
|
|
169
|
+
type: "tool_use",
|
|
170
|
+
id: block.id,
|
|
171
|
+
name: block.name,
|
|
172
|
+
input: block.input
|
|
173
|
+
}
|
|
174
|
+
];
|
|
175
|
+
return [];
|
|
176
|
+
});
|
|
177
|
+
return { anthropic: { content: blocks } };
|
|
178
|
+
}
|
|
179
|
+
function anthropicReplayContent(metadata) {
|
|
180
|
+
const state = metadata?.anthropic;
|
|
181
|
+
return anthropicReplay(state?.content)?.anthropic?.content;
|
|
182
|
+
}
|
|
183
|
+
function collectAnthropicContent(blocks, event) {
|
|
184
|
+
if (event.type === "content_block_start")
|
|
185
|
+
blocks[event.index] = { ...event.content_block };
|
|
186
|
+
const block = blocks[event.index];
|
|
187
|
+
if (event.type !== "content_block_delta" || !block) return;
|
|
188
|
+
const delta = event.delta;
|
|
189
|
+
if (delta.type === "thinking_delta")
|
|
190
|
+
block.thinking = (block.thinking ?? "") + delta.thinking;
|
|
191
|
+
else if (delta.type === "signature_delta")
|
|
192
|
+
block.signature = (block.signature ?? "") + delta.signature;
|
|
193
|
+
else if (delta.type === "text_delta")
|
|
194
|
+
block.text = (block.text ?? "") + delta.text;
|
|
195
|
+
else if (delta.type === "input_json_delta") {
|
|
196
|
+
block.partialInput = (block.partialInput ?? "") + delta.partial_json;
|
|
197
|
+
try {
|
|
198
|
+
block.input = JSON.parse(block.partialInput);
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
90
204
|
// src/adapters/base.ts
|
|
91
205
|
function stringifyForDebug(value) {
|
|
92
206
|
return JSON.stringify(
|
|
@@ -165,7 +279,22 @@ function stripSchemaKeys(schema, keysToDrop, options = {}) {
|
|
|
165
279
|
)) {
|
|
166
280
|
if (keysToDrop.has(key)) continue;
|
|
167
281
|
const renamed = options.renameKeys?.[key] ?? key;
|
|
168
|
-
|
|
282
|
+
if ([
|
|
283
|
+
"properties",
|
|
284
|
+
"$defs",
|
|
285
|
+
"definitions",
|
|
286
|
+
"patternProperties",
|
|
287
|
+
"dependentSchemas"
|
|
288
|
+
].includes(key) && value && typeof value === "object" && !Array.isArray(value)) {
|
|
289
|
+
out[renamed] = Object.fromEntries(
|
|
290
|
+
Object.entries(value).map(([name, child]) => [
|
|
291
|
+
name,
|
|
292
|
+
stripSchemaKeys(child, keysToDrop, options)
|
|
293
|
+
])
|
|
294
|
+
);
|
|
295
|
+
} else if (["enum", "const", "default", "examples"].includes(key)) {
|
|
296
|
+
out[renamed] = value;
|
|
297
|
+
} else out[renamed] = stripSchemaKeys(value, keysToDrop, options);
|
|
169
298
|
}
|
|
170
299
|
if (options.forceAdditionalPropertiesFalse && out.type === "object") {
|
|
171
300
|
out.additionalProperties = false;
|
|
@@ -294,21 +423,14 @@ function messageToAnthropicContent(message) {
|
|
|
294
423
|
return blocks;
|
|
295
424
|
}
|
|
296
425
|
function extractAnthropicSystemPrompt(messages, systemPrompt) {
|
|
297
|
-
const
|
|
426
|
+
const explicit = typeof systemPrompt === "string" ? systemPrompt : "";
|
|
427
|
+
const parts = explicit ? [explicit] : [];
|
|
298
428
|
for (const message of messages) {
|
|
299
429
|
if (message.role !== "system") continue;
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (block?.type !== "text" || typeof block.text !== "string") {
|
|
305
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
306
|
-
}
|
|
307
|
-
if (block.text) parts.push(block.text);
|
|
308
|
-
}
|
|
309
|
-
} else {
|
|
310
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
311
|
-
}
|
|
430
|
+
const text = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter(
|
|
431
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
432
|
+
).map((block) => block.text).filter(Boolean).join("\n") : "";
|
|
433
|
+
if (text && text !== explicit) parts.push(text);
|
|
312
434
|
}
|
|
313
435
|
return parts.join("\n");
|
|
314
436
|
}
|
|
@@ -319,6 +441,14 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
319
441
|
const msg = messages[i];
|
|
320
442
|
if (msg.role === "system") continue;
|
|
321
443
|
if (msg.role === "assistant") {
|
|
444
|
+
const replay = anthropicReplayContent(msg.providerMetadata);
|
|
445
|
+
if (replay) {
|
|
446
|
+
formatted.push({
|
|
447
|
+
role: "assistant",
|
|
448
|
+
content: replay
|
|
449
|
+
});
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
322
452
|
const content = [];
|
|
323
453
|
if (msg.content) {
|
|
324
454
|
content.push({ type: "text", text: msg.content });
|
|
@@ -373,6 +503,52 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
373
503
|
};
|
|
374
504
|
}
|
|
375
505
|
|
|
506
|
+
// src/core/anthropic-parameters.ts
|
|
507
|
+
function anthropicMaxTokens(maxTokens, thinking) {
|
|
508
|
+
return maxTokens ?? Math.max(4096, Number(thinking?.budget_tokens ?? 0) + 1);
|
|
509
|
+
}
|
|
510
|
+
function anthropicModelRules(model) {
|
|
511
|
+
const match = /^claude-(opus|sonnet|haiku)-(\d+)(?:-(\d{1,2})(?=-|$))?(?:-|$)/i.exec(
|
|
512
|
+
model
|
|
513
|
+
);
|
|
514
|
+
const family = match?.[1]?.toLowerCase();
|
|
515
|
+
const major = Number(match?.[2] ?? 0);
|
|
516
|
+
const minor = Number(match?.[3] ?? 0);
|
|
517
|
+
const adaptive = major >= 5 || major === 4 && minor >= 6;
|
|
518
|
+
return {
|
|
519
|
+
structured: major >= 5 || major === 4 && minor >= 5,
|
|
520
|
+
thinking: major >= 4 || /^claude-3-7-/.test(model),
|
|
521
|
+
adaptive,
|
|
522
|
+
rejectsSampling: major >= 5 || family === "opus" && major === 4 && minor >= 7
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
function anthropicInputTokens(usage) {
|
|
526
|
+
return (usage?.input_tokens ?? 0) + (usage?.cache_creation_input_tokens ?? 0) + (usage?.cache_read_input_tokens ?? 0);
|
|
527
|
+
}
|
|
528
|
+
function anthropicThinking(model, thinking) {
|
|
529
|
+
if (!thinking) return void 0;
|
|
530
|
+
if (thinking.type === "enabled") {
|
|
531
|
+
if (anthropicModelRules(model).adaptive) {
|
|
532
|
+
console.warn(
|
|
533
|
+
`[llm-sdk] ${model}: using adaptive thinking instead of a legacy token budget.`
|
|
534
|
+
);
|
|
535
|
+
return { type: "adaptive" };
|
|
536
|
+
}
|
|
537
|
+
return { type: "enabled", budget_tokens: thinking.budgetTokens ?? 1e4 };
|
|
538
|
+
}
|
|
539
|
+
return { ...thinking };
|
|
540
|
+
}
|
|
541
|
+
function anthropicTemperature(model, temperature, thinking = false) {
|
|
542
|
+
if (temperature === void 0) return {};
|
|
543
|
+
if (thinking || anthropicModelRules(model).rejectsSampling) {
|
|
544
|
+
console.warn(
|
|
545
|
+
`[llm-sdk] ${model}: omitted temperature because this model or thinking mode does not support it.`
|
|
546
|
+
);
|
|
547
|
+
return {};
|
|
548
|
+
}
|
|
549
|
+
return { temperature };
|
|
550
|
+
}
|
|
551
|
+
|
|
376
552
|
// src/providers/anthropic/provider.ts
|
|
377
553
|
var ANTHROPIC_MODELS = {
|
|
378
554
|
// Claude 4 series
|
|
@@ -482,6 +658,10 @@ function anthropic(modelId, options = {}) {
|
|
|
482
658
|
return client;
|
|
483
659
|
}
|
|
484
660
|
const modelConfig = ANTHROPIC_MODELS[modelId] ?? ANTHROPIC_MODELS["claude-3-5-sonnet-latest"];
|
|
661
|
+
const thinking = anthropicThinking(
|
|
662
|
+
modelId,
|
|
663
|
+
options.thinking && ("enabled" in options.thinking ? options.thinking.enabled ? { type: "enabled", budgetTokens: options.thinking.budgetTokens } : void 0 : options.thinking)
|
|
664
|
+
);
|
|
485
665
|
return {
|
|
486
666
|
provider: "anthropic",
|
|
487
667
|
modelId,
|
|
@@ -489,8 +669,8 @@ function anthropic(modelId, options = {}) {
|
|
|
489
669
|
supportsVision: modelConfig.vision,
|
|
490
670
|
supportsTools: modelConfig.tools,
|
|
491
671
|
supportsStreaming: true,
|
|
492
|
-
supportsJsonMode:
|
|
493
|
-
supportsThinking: modelConfig.thinking,
|
|
672
|
+
supportsJsonMode: anthropicModelRules(modelId).structured,
|
|
673
|
+
supportsThinking: modelConfig.thinking || anthropicModelRules(modelId).thinking,
|
|
494
674
|
supportsPDF: modelConfig.pdf,
|
|
495
675
|
maxTokens: modelConfig.maxTokens,
|
|
496
676
|
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
@@ -500,25 +680,34 @@ function anthropic(modelId, options = {}) {
|
|
|
500
680
|
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
501
681
|
const requestOptions = {
|
|
502
682
|
model: modelId,
|
|
503
|
-
max_tokens: params.maxTokens
|
|
683
|
+
max_tokens: anthropicMaxTokens(params.maxTokens, thinking),
|
|
504
684
|
system: system || void 0,
|
|
505
685
|
messages,
|
|
506
|
-
tools: params.tools
|
|
686
|
+
tools: params.tools,
|
|
687
|
+
...options.cacheControl ? { cache_control: { type: "ephemeral" } } : {}
|
|
507
688
|
};
|
|
508
|
-
|
|
509
|
-
requestOptions
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
type
|
|
514
|
-
|
|
515
|
-
|
|
689
|
+
Object.assign(
|
|
690
|
+
requestOptions,
|
|
691
|
+
anthropicTemperature(
|
|
692
|
+
modelId,
|
|
693
|
+
params.temperature,
|
|
694
|
+
!!thinking && thinking.type !== "disabled"
|
|
695
|
+
)
|
|
696
|
+
);
|
|
697
|
+
if (params.responseFormat?.type === "json_object") {
|
|
698
|
+
requestOptions.system = (system || "") + "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences.";
|
|
516
699
|
}
|
|
700
|
+
if (thinking) requestOptions.thinking = thinking;
|
|
517
701
|
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
518
|
-
if (outputConfig) {
|
|
519
|
-
requestOptions.output_config =
|
|
702
|
+
if (outputConfig || options.effort) {
|
|
703
|
+
requestOptions.output_config = {
|
|
704
|
+
...outputConfig,
|
|
705
|
+
...options.effort ? { effort: options.effort } : {}
|
|
706
|
+
};
|
|
520
707
|
}
|
|
521
|
-
const response = await client2.messages.create(requestOptions
|
|
708
|
+
const response = await client2.messages.create(requestOptions, {
|
|
709
|
+
signal: params.signal
|
|
710
|
+
});
|
|
522
711
|
let text = "";
|
|
523
712
|
const toolCalls = [];
|
|
524
713
|
for (const block of response.content) {
|
|
@@ -532,14 +721,21 @@ function anthropic(modelId, options = {}) {
|
|
|
532
721
|
});
|
|
533
722
|
}
|
|
534
723
|
}
|
|
724
|
+
validateToolCalls(toolCalls);
|
|
725
|
+
if (toolCalls.length && response.stop_reason !== "tool_use")
|
|
726
|
+
throw invalidProviderResponse(
|
|
727
|
+
"Anthropic response ended with incomplete tool calls"
|
|
728
|
+
);
|
|
535
729
|
return {
|
|
536
730
|
text,
|
|
731
|
+
reasoningText: response.content.filter((b) => b.type === "thinking").map((b) => b.thinking).join("") || void 0,
|
|
732
|
+
providerMetadata: anthropicReplay(response.content),
|
|
537
733
|
toolCalls,
|
|
538
734
|
finishReason: mapFinishReason(response.stop_reason),
|
|
539
735
|
usage: {
|
|
540
|
-
promptTokens: response.usage
|
|
736
|
+
promptTokens: anthropicInputTokens(response.usage),
|
|
541
737
|
completionTokens: response.usage?.output_tokens ?? 0,
|
|
542
|
-
totalTokens: (response.usage
|
|
738
|
+
totalTokens: anthropicInputTokens(response.usage) + (response.usage?.output_tokens ?? 0)
|
|
543
739
|
},
|
|
544
740
|
rawResponse: response
|
|
545
741
|
};
|
|
@@ -549,37 +745,47 @@ function anthropic(modelId, options = {}) {
|
|
|
549
745
|
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
550
746
|
const requestOptions = {
|
|
551
747
|
model: modelId,
|
|
552
|
-
max_tokens: params.maxTokens
|
|
748
|
+
max_tokens: anthropicMaxTokens(params.maxTokens, thinking),
|
|
553
749
|
system: system || void 0,
|
|
554
750
|
messages,
|
|
555
|
-
tools: params.tools
|
|
751
|
+
tools: params.tools,
|
|
752
|
+
...options.cacheControl ? { cache_control: { type: "ephemeral" } } : {}
|
|
556
753
|
};
|
|
557
|
-
|
|
558
|
-
requestOptions
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
type
|
|
563
|
-
|
|
564
|
-
|
|
754
|
+
Object.assign(
|
|
755
|
+
requestOptions,
|
|
756
|
+
anthropicTemperature(
|
|
757
|
+
modelId,
|
|
758
|
+
params.temperature,
|
|
759
|
+
!!thinking && thinking.type !== "disabled"
|
|
760
|
+
)
|
|
761
|
+
);
|
|
762
|
+
if (params.responseFormat?.type === "json_object") {
|
|
763
|
+
requestOptions.system = (system || "") + "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences.";
|
|
565
764
|
}
|
|
765
|
+
if (thinking) requestOptions.thinking = thinking;
|
|
566
766
|
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
567
|
-
if (outputConfig) {
|
|
568
|
-
requestOptions.output_config =
|
|
767
|
+
if (outputConfig || options.effort) {
|
|
768
|
+
requestOptions.output_config = {
|
|
769
|
+
...outputConfig,
|
|
770
|
+
...options.effort ? { effort: options.effort } : {}
|
|
771
|
+
};
|
|
569
772
|
}
|
|
570
|
-
const stream = await client2.messages.stream(requestOptions
|
|
773
|
+
const stream = await client2.messages.stream(requestOptions, {
|
|
774
|
+
signal: params.signal
|
|
775
|
+
});
|
|
571
776
|
let currentToolUse = null;
|
|
572
777
|
let inputTokens = 0;
|
|
573
778
|
let outputTokens = 0;
|
|
779
|
+
const content = [];
|
|
780
|
+
const toolCalls = [];
|
|
781
|
+
let stopReason;
|
|
574
782
|
for await (const event of stream) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
783
|
+
collectAnthropicContent(content, event);
|
|
784
|
+
throwIfAborted(params.signal);
|
|
579
785
|
switch (event.type) {
|
|
580
786
|
case "message_start":
|
|
581
787
|
if (event.message?.usage) {
|
|
582
|
-
inputTokens = event.message.usage
|
|
788
|
+
inputTokens = anthropicInputTokens(event.message.usage);
|
|
583
789
|
}
|
|
584
790
|
break;
|
|
585
791
|
case "content_block_start":
|
|
@@ -594,20 +800,19 @@ function anthropic(modelId, options = {}) {
|
|
|
594
800
|
case "content_block_delta":
|
|
595
801
|
if (event.delta?.type === "text_delta") {
|
|
596
802
|
yield { type: "text-delta", text: event.delta.text };
|
|
803
|
+
} else if (event.delta?.type === "thinking_delta") {
|
|
804
|
+
yield { type: "reasoning-delta", text: event.delta.thinking };
|
|
597
805
|
} else if (event.delta?.type === "input_json_delta" && currentToolUse) {
|
|
598
806
|
currentToolUse.input += event.delta.partial_json;
|
|
599
807
|
}
|
|
600
808
|
break;
|
|
601
809
|
case "content_block_stop":
|
|
602
810
|
if (currentToolUse) {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
args: JSON.parse(currentToolUse.input || "{}")
|
|
609
|
-
}
|
|
610
|
-
};
|
|
811
|
+
toolCalls.push({
|
|
812
|
+
id: currentToolUse.id,
|
|
813
|
+
name: currentToolUse.name,
|
|
814
|
+
args: parseToolArguments(currentToolUse.input)
|
|
815
|
+
});
|
|
611
816
|
currentToolUse = null;
|
|
612
817
|
}
|
|
613
818
|
break;
|
|
@@ -616,19 +821,32 @@ function anthropic(modelId, options = {}) {
|
|
|
616
821
|
outputTokens = event.usage.output_tokens ?? 0;
|
|
617
822
|
}
|
|
618
823
|
if (event.delta?.stop_reason) {
|
|
619
|
-
|
|
620
|
-
type: "finish",
|
|
621
|
-
finishReason: mapFinishReason(event.delta.stop_reason),
|
|
622
|
-
usage: {
|
|
623
|
-
promptTokens: inputTokens,
|
|
624
|
-
completionTokens: outputTokens,
|
|
625
|
-
totalTokens: inputTokens + outputTokens
|
|
626
|
-
}
|
|
627
|
-
};
|
|
824
|
+
stopReason = event.delta.stop_reason;
|
|
628
825
|
}
|
|
629
826
|
break;
|
|
630
827
|
}
|
|
631
828
|
}
|
|
829
|
+
throwIfAborted(params.signal);
|
|
830
|
+
if (!stopReason || currentToolUse)
|
|
831
|
+
throw invalidProviderResponse(
|
|
832
|
+
"Anthropic stream ended before its turn completed"
|
|
833
|
+
);
|
|
834
|
+
validateToolCalls(toolCalls);
|
|
835
|
+
if (toolCalls.length && stopReason !== "tool_use")
|
|
836
|
+
throw invalidProviderResponse(
|
|
837
|
+
"Anthropic stream ended with incomplete tool calls"
|
|
838
|
+
);
|
|
839
|
+
for (const toolCall of toolCalls) yield { type: "tool-call", toolCall };
|
|
840
|
+
yield {
|
|
841
|
+
type: "finish",
|
|
842
|
+
finishReason: mapFinishReason(stopReason),
|
|
843
|
+
providerMetadata: anthropicReplay(content),
|
|
844
|
+
usage: {
|
|
845
|
+
promptTokens: inputTokens,
|
|
846
|
+
completionTokens: outputTokens,
|
|
847
|
+
totalTokens: inputTokens + outputTokens
|
|
848
|
+
}
|
|
849
|
+
};
|
|
632
850
|
}
|
|
633
851
|
};
|
|
634
852
|
}
|
|
@@ -646,7 +864,7 @@ function mapFinishReason(reason) {
|
|
|
646
864
|
}
|
|
647
865
|
}
|
|
648
866
|
function formatMessagesForAnthropic2(messages) {
|
|
649
|
-
|
|
867
|
+
const system = extractAnthropicSystemPrompt(messages);
|
|
650
868
|
const formatted = [];
|
|
651
869
|
const pendingToolResults = [];
|
|
652
870
|
const flushToolResults = () => {
|
|
@@ -672,7 +890,6 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
672
890
|
};
|
|
673
891
|
for (const msg of messages) {
|
|
674
892
|
if (msg.role === "system") {
|
|
675
|
-
system += (system ? "\n" : "") + msg.content;
|
|
676
893
|
continue;
|
|
677
894
|
}
|
|
678
895
|
if (msg.role === "assistant" && pendingToolResults.length > 0) {
|
|
@@ -710,6 +927,11 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
710
927
|
formatted.push({ role: "user", content });
|
|
711
928
|
}
|
|
712
929
|
} else if (msg.role === "assistant") {
|
|
930
|
+
const replay = anthropicReplayContent(msg.providerMetadata);
|
|
931
|
+
if (replay) {
|
|
932
|
+
formatted.push({ role: "assistant", content: replay });
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
713
935
|
const content = [];
|
|
714
936
|
if (msg.content) {
|
|
715
937
|
content.push({ type: "text", text: msg.content });
|
|
@@ -765,7 +987,10 @@ var AnthropicAdapter = class {
|
|
|
765
987
|
if (!this.client) {
|
|
766
988
|
const { default: Anthropic } = await import('@anthropic-ai/sdk');
|
|
767
989
|
this.client = new Anthropic({
|
|
768
|
-
apiKey: this.config.apiKey
|
|
990
|
+
apiKey: this.config.apiKey,
|
|
991
|
+
baseURL: this.config.baseUrl,
|
|
992
|
+
timeout: this.config.timeout,
|
|
993
|
+
defaultHeaders: this.config.headers
|
|
769
994
|
});
|
|
770
995
|
}
|
|
771
996
|
return this.client;
|
|
@@ -802,6 +1027,15 @@ var AnthropicAdapter = class {
|
|
|
802
1027
|
lastToolCallIds = [];
|
|
803
1028
|
toolResultIndex = 0;
|
|
804
1029
|
}
|
|
1030
|
+
const replay = anthropicReplayContent(
|
|
1031
|
+
msg.providerMetadata
|
|
1032
|
+
);
|
|
1033
|
+
if (replay) {
|
|
1034
|
+
messages.push({ role: "assistant", content: replay });
|
|
1035
|
+
lastToolCallIds = replay.filter((b) => b.type === "tool_use").map((b) => b.id);
|
|
1036
|
+
toolResultIndex = 0;
|
|
1037
|
+
continue;
|
|
1038
|
+
}
|
|
805
1039
|
const content = [];
|
|
806
1040
|
if (msg.content && typeof msg.content === "string" && msg.content.trim()) {
|
|
807
1041
|
content.push({ type: "text", text: msg.content });
|
|
@@ -977,7 +1211,7 @@ var AnthropicAdapter = class {
|
|
|
977
1211
|
*/
|
|
978
1212
|
buildRequestOptions(request) {
|
|
979
1213
|
const responseFormat = request.config?.responseFormat;
|
|
980
|
-
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text." : "";
|
|
1214
|
+
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text. Do not include Markdown code fences." : "";
|
|
981
1215
|
let systemMessage;
|
|
982
1216
|
let messages;
|
|
983
1217
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
@@ -999,7 +1233,17 @@ var AnthropicAdapter = class {
|
|
|
999
1233
|
const tools = anthropicNativeSearch?.enabled ? this.buildNativeSearchTools(
|
|
1000
1234
|
request.toolDefinitions ?? [],
|
|
1001
1235
|
anthropicNativeSearch.variant
|
|
1002
|
-
) : request.
|
|
1236
|
+
) : request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
|
|
1237
|
+
name: tool.name,
|
|
1238
|
+
description: tool.description,
|
|
1239
|
+
// Keep the original schema. Legacy ActionParameter conversion
|
|
1240
|
+
// cannot represent unions, null, or nested required constraints.
|
|
1241
|
+
input_schema: tool.inputSchema ?? {
|
|
1242
|
+
type: "object",
|
|
1243
|
+
properties: {},
|
|
1244
|
+
required: []
|
|
1245
|
+
}
|
|
1246
|
+
})) : request.actions?.map((action) => ({
|
|
1003
1247
|
name: action.name,
|
|
1004
1248
|
description: action.description,
|
|
1005
1249
|
input_schema: {
|
|
@@ -1041,12 +1285,25 @@ var AnthropicAdapter = class {
|
|
|
1041
1285
|
};
|
|
1042
1286
|
}
|
|
1043
1287
|
}
|
|
1288
|
+
const thinking = anthropicThinking(
|
|
1289
|
+
request.config?.model || this.model,
|
|
1290
|
+
this.config.thinking
|
|
1291
|
+
);
|
|
1044
1292
|
const options = {
|
|
1045
1293
|
model: request.config?.model || this.model,
|
|
1046
|
-
max_tokens:
|
|
1294
|
+
max_tokens: anthropicMaxTokens(
|
|
1295
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1296
|
+
thinking
|
|
1297
|
+
),
|
|
1047
1298
|
system: systemMessage,
|
|
1048
1299
|
messages,
|
|
1049
|
-
tools: tools.length ? tools : void 0
|
|
1300
|
+
tools: tools.length ? tools : void 0,
|
|
1301
|
+
...this.config.cacheControl ? { cache_control: { type: "ephemeral" } } : {},
|
|
1302
|
+
...anthropicTemperature(
|
|
1303
|
+
request.config?.model || this.model,
|
|
1304
|
+
request.config?.temperature ?? this.config.temperature,
|
|
1305
|
+
!!this.config.thinking && this.config.thinking.type !== "disabled"
|
|
1306
|
+
)
|
|
1050
1307
|
};
|
|
1051
1308
|
const anthropicToolOptions = request.providerToolOptions?.anthropic;
|
|
1052
1309
|
if (tools.length > 0 && anthropicToolOptions) {
|
|
@@ -1065,15 +1322,13 @@ var AnthropicAdapter = class {
|
|
|
1065
1322
|
options.server_tool_configuration = serverToolConfiguration;
|
|
1066
1323
|
}
|
|
1067
1324
|
const outputConfig = toAnthropicOutputConfig(responseFormat);
|
|
1068
|
-
if (outputConfig) {
|
|
1069
|
-
options.output_config =
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
options.thinking = {
|
|
1073
|
-
type: "enabled",
|
|
1074
|
-
budget_tokens: this.config.thinking.budgetTokens || 1e4
|
|
1325
|
+
if (outputConfig || this.config.effort) {
|
|
1326
|
+
options.output_config = {
|
|
1327
|
+
...outputConfig,
|
|
1328
|
+
...this.config.effort ? { effort: this.config.effort } : {}
|
|
1075
1329
|
};
|
|
1076
1330
|
}
|
|
1331
|
+
if (thinking) options.thinking = thinking;
|
|
1077
1332
|
return { options, messages };
|
|
1078
1333
|
}
|
|
1079
1334
|
/**
|
|
@@ -1093,7 +1348,9 @@ var AnthropicAdapter = class {
|
|
|
1093
1348
|
nonStreamingOptions,
|
|
1094
1349
|
request.debug
|
|
1095
1350
|
);
|
|
1096
|
-
const response = await client.messages.create(nonStreamingOptions
|
|
1351
|
+
const response = await client.messages.create(nonStreamingOptions, {
|
|
1352
|
+
signal: request.signal
|
|
1353
|
+
});
|
|
1097
1354
|
logProviderPayload(
|
|
1098
1355
|
"anthropic",
|
|
1099
1356
|
"response payload",
|
|
@@ -1116,14 +1373,20 @@ var AnthropicAdapter = class {
|
|
|
1116
1373
|
});
|
|
1117
1374
|
}
|
|
1118
1375
|
}
|
|
1376
|
+
validateToolCalls(toolCalls);
|
|
1377
|
+
if (toolCalls.length && response.stop_reason !== "tool_use")
|
|
1378
|
+
throw invalidProviderResponse(
|
|
1379
|
+
"Anthropic response ended with incomplete tool calls"
|
|
1380
|
+
);
|
|
1119
1381
|
return {
|
|
1120
1382
|
content,
|
|
1383
|
+
providerMetadata: anthropicReplay(response.content),
|
|
1121
1384
|
toolCalls,
|
|
1122
1385
|
thinking: thinking || void 0,
|
|
1123
1386
|
usage: response.usage ? {
|
|
1124
|
-
promptTokens: response.usage
|
|
1387
|
+
promptTokens: anthropicInputTokens(response.usage),
|
|
1125
1388
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
1126
|
-
totalTokens: (response.usage
|
|
1389
|
+
totalTokens: anthropicInputTokens(response.usage) + (response.usage.output_tokens ?? 0)
|
|
1127
1390
|
} : void 0,
|
|
1128
1391
|
rawResponse: response
|
|
1129
1392
|
};
|
|
@@ -1143,28 +1406,33 @@ var AnthropicAdapter = class {
|
|
|
1143
1406
|
options,
|
|
1144
1407
|
request.debug
|
|
1145
1408
|
);
|
|
1146
|
-
const stream = await client.messages.stream(options
|
|
1409
|
+
const stream = await client.messages.stream(options, {
|
|
1410
|
+
signal: request.signal
|
|
1411
|
+
});
|
|
1147
1412
|
let currentToolUse = null;
|
|
1148
1413
|
let isInThinkingBlock = false;
|
|
1414
|
+
const content = [];
|
|
1415
|
+
const toolCalls = [];
|
|
1416
|
+
let stopReason;
|
|
1149
1417
|
const collectedCitations = [];
|
|
1150
1418
|
let citationIndex = 0;
|
|
1151
1419
|
let usage;
|
|
1152
1420
|
for await (const event of stream) {
|
|
1421
|
+
collectAnthropicContent(content, event);
|
|
1153
1422
|
logProviderPayload("anthropic", "stream event", event, request.debug);
|
|
1154
|
-
|
|
1155
|
-
break;
|
|
1156
|
-
}
|
|
1423
|
+
throwIfAborted(request.signal);
|
|
1157
1424
|
switch (event.type) {
|
|
1158
1425
|
case "message_start":
|
|
1159
1426
|
if (event.message?.usage) {
|
|
1160
1427
|
usage = {
|
|
1161
|
-
prompt_tokens: event.message.usage
|
|
1428
|
+
prompt_tokens: anthropicInputTokens(event.message.usage),
|
|
1162
1429
|
completion_tokens: 0,
|
|
1163
|
-
total_tokens: event.message.usage
|
|
1430
|
+
total_tokens: anthropicInputTokens(event.message.usage)
|
|
1164
1431
|
};
|
|
1165
1432
|
}
|
|
1166
1433
|
break;
|
|
1167
1434
|
case "message_delta":
|
|
1435
|
+
if (event.delta?.stop_reason) stopReason = event.delta.stop_reason;
|
|
1168
1436
|
if (event.usage && usage) {
|
|
1169
1437
|
usage.completion_tokens = event.usage.output_tokens;
|
|
1170
1438
|
usage.total_tokens = usage.prompt_tokens + event.usage.output_tokens;
|
|
@@ -1177,13 +1445,6 @@ var AnthropicAdapter = class {
|
|
|
1177
1445
|
name: event.content_block.name,
|
|
1178
1446
|
input: ""
|
|
1179
1447
|
};
|
|
1180
|
-
if (currentToolUse.name !== "web_search") {
|
|
1181
|
-
yield {
|
|
1182
|
-
type: "action:start",
|
|
1183
|
-
id: currentToolUse.id,
|
|
1184
|
-
name: currentToolUse.name
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
1448
|
} else if (event.content_block.type === "web_search_tool_result") {
|
|
1188
1449
|
const webSearchResult = event.content_block;
|
|
1189
1450
|
if (webSearchResult.content && Array.isArray(webSearchResult.content)) {
|
|
@@ -1232,16 +1493,11 @@ var AnthropicAdapter = class {
|
|
|
1232
1493
|
case "content_block_stop":
|
|
1233
1494
|
if (currentToolUse) {
|
|
1234
1495
|
if (currentToolUse.name !== "web_search") {
|
|
1235
|
-
|
|
1236
|
-
type: "action:args",
|
|
1237
|
-
id: currentToolUse.id,
|
|
1238
|
-
args: currentToolUse.input
|
|
1239
|
-
};
|
|
1240
|
-
yield {
|
|
1241
|
-
type: "action:end",
|
|
1496
|
+
toolCalls.push({
|
|
1242
1497
|
id: currentToolUse.id,
|
|
1243
|
-
name: currentToolUse.name
|
|
1244
|
-
|
|
1498
|
+
name: currentToolUse.name,
|
|
1499
|
+
args: parseToolArguments(currentToolUse.input)
|
|
1500
|
+
});
|
|
1245
1501
|
}
|
|
1246
1502
|
currentToolUse = null;
|
|
1247
1503
|
}
|
|
@@ -1254,18 +1510,33 @@ var AnthropicAdapter = class {
|
|
|
1254
1510
|
break;
|
|
1255
1511
|
}
|
|
1256
1512
|
}
|
|
1513
|
+
throwIfAborted(request.signal);
|
|
1514
|
+
if (!stopReason || currentToolUse)
|
|
1515
|
+
throw invalidProviderResponse(
|
|
1516
|
+
"Anthropic stream ended before its turn completed"
|
|
1517
|
+
);
|
|
1518
|
+
validateToolCalls(toolCalls);
|
|
1519
|
+
if (toolCalls.length && stopReason !== "tool_use")
|
|
1520
|
+
throw invalidProviderResponse(
|
|
1521
|
+
"Anthropic stream ended with incomplete tool calls"
|
|
1522
|
+
);
|
|
1523
|
+
for (const call of toolCalls) {
|
|
1524
|
+
yield { type: "action:start", id: call.id, name: call.name };
|
|
1525
|
+
yield {
|
|
1526
|
+
type: "action:args",
|
|
1527
|
+
id: call.id,
|
|
1528
|
+
args: JSON.stringify(call.args)
|
|
1529
|
+
};
|
|
1530
|
+
yield { type: "action:end", id: call.id, name: call.name };
|
|
1531
|
+
}
|
|
1257
1532
|
if (collectedCitations.length > 0) {
|
|
1258
1533
|
const uniqueCitations = deduplicateCitations(collectedCitations);
|
|
1259
1534
|
yield { type: "citation", citations: uniqueCitations };
|
|
1260
1535
|
}
|
|
1261
1536
|
yield { type: "message:end" };
|
|
1262
|
-
yield { type: "done", usage };
|
|
1537
|
+
yield { type: "done", usage, providerMetadata: anthropicReplay(content) };
|
|
1263
1538
|
} catch (error) {
|
|
1264
|
-
yield
|
|
1265
|
-
type: "error",
|
|
1266
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
1267
|
-
code: "ANTHROPIC_ERROR"
|
|
1268
|
-
};
|
|
1539
|
+
yield providerErrorEvent(error, "ANTHROPIC_ERROR");
|
|
1269
1540
|
}
|
|
1270
1541
|
}
|
|
1271
1542
|
};
|
|
@@ -1381,7 +1652,11 @@ function createAnthropic(config = {}) {
|
|
|
1381
1652
|
apiKey,
|
|
1382
1653
|
model: modelId,
|
|
1383
1654
|
baseUrl: config.baseUrl,
|
|
1384
|
-
|
|
1655
|
+
timeout: config.timeout,
|
|
1656
|
+
headers: config.headers,
|
|
1657
|
+
cacheControl: config.cacheControl,
|
|
1658
|
+
thinking: config.thinking ?? (config.thinkingBudget ? { type: "enabled", budgetTokens: config.thinkingBudget } : void 0),
|
|
1659
|
+
effort: config.effort
|
|
1385
1660
|
});
|
|
1386
1661
|
};
|
|
1387
1662
|
const getCapabilities = (modelId) => {
|
|
@@ -1389,7 +1664,7 @@ function createAnthropic(config = {}) {
|
|
|
1389
1664
|
return {
|
|
1390
1665
|
supportsVision: model.vision,
|
|
1391
1666
|
supportsTools: model.tools,
|
|
1392
|
-
supportsThinking:
|
|
1667
|
+
supportsThinking: anthropicModelRules(modelId).thinking,
|
|
1393
1668
|
supportsStreaming: true,
|
|
1394
1669
|
supportsPDF: true,
|
|
1395
1670
|
supportsAudio: false,
|
|
@@ -1401,8 +1676,7 @@ function createAnthropic(config = {}) {
|
|
|
1401
1676
|
"image/gif",
|
|
1402
1677
|
"image/webp"
|
|
1403
1678
|
],
|
|
1404
|
-
|
|
1405
|
-
supportsJsonMode: true,
|
|
1679
|
+
supportsJsonMode: anthropicModelRules(modelId).structured,
|
|
1406
1680
|
supportsSystemMessages: true
|
|
1407
1681
|
};
|
|
1408
1682
|
};
|