@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
|
@@ -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;
|
|
@@ -292,21 +421,14 @@ function messageToAnthropicContent(message) {
|
|
|
292
421
|
return blocks;
|
|
293
422
|
}
|
|
294
423
|
function extractAnthropicSystemPrompt(messages, systemPrompt) {
|
|
295
|
-
const
|
|
424
|
+
const explicit = typeof systemPrompt === "string" ? systemPrompt : "";
|
|
425
|
+
const parts = explicit ? [explicit] : [];
|
|
296
426
|
for (const message of messages) {
|
|
297
427
|
if (message.role !== "system") continue;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (block?.type !== "text" || typeof block.text !== "string") {
|
|
303
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
304
|
-
}
|
|
305
|
-
if (block.text) parts.push(block.text);
|
|
306
|
-
}
|
|
307
|
-
} else {
|
|
308
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
309
|
-
}
|
|
428
|
+
const text = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter(
|
|
429
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
430
|
+
).map((block) => block.text).filter(Boolean).join("\n") : "";
|
|
431
|
+
if (text && text !== explicit) parts.push(text);
|
|
310
432
|
}
|
|
311
433
|
return parts.join("\n");
|
|
312
434
|
}
|
|
@@ -317,6 +439,14 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
317
439
|
const msg = messages[i];
|
|
318
440
|
if (msg.role === "system") continue;
|
|
319
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
|
+
}
|
|
320
450
|
const content = [];
|
|
321
451
|
if (msg.content) {
|
|
322
452
|
content.push({ type: "text", text: msg.content });
|
|
@@ -371,6 +501,52 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
371
501
|
};
|
|
372
502
|
}
|
|
373
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
|
+
|
|
374
550
|
// src/providers/anthropic/provider.ts
|
|
375
551
|
var ANTHROPIC_MODELS = {
|
|
376
552
|
// Claude 4 series
|
|
@@ -480,6 +656,10 @@ function anthropic(modelId, options = {}) {
|
|
|
480
656
|
return client;
|
|
481
657
|
}
|
|
482
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
|
+
);
|
|
483
663
|
return {
|
|
484
664
|
provider: "anthropic",
|
|
485
665
|
modelId,
|
|
@@ -487,8 +667,8 @@ function anthropic(modelId, options = {}) {
|
|
|
487
667
|
supportsVision: modelConfig.vision,
|
|
488
668
|
supportsTools: modelConfig.tools,
|
|
489
669
|
supportsStreaming: true,
|
|
490
|
-
supportsJsonMode:
|
|
491
|
-
supportsThinking: modelConfig.thinking,
|
|
670
|
+
supportsJsonMode: anthropicModelRules(modelId).structured,
|
|
671
|
+
supportsThinking: modelConfig.thinking || anthropicModelRules(modelId).thinking,
|
|
492
672
|
supportsPDF: modelConfig.pdf,
|
|
493
673
|
maxTokens: modelConfig.maxTokens,
|
|
494
674
|
supportedImageTypes: modelConfig.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : []
|
|
@@ -498,25 +678,34 @@ function anthropic(modelId, options = {}) {
|
|
|
498
678
|
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
499
679
|
const requestOptions = {
|
|
500
680
|
model: modelId,
|
|
501
|
-
max_tokens: params.maxTokens
|
|
681
|
+
max_tokens: anthropicMaxTokens(params.maxTokens, thinking),
|
|
502
682
|
system: system || void 0,
|
|
503
683
|
messages,
|
|
504
|
-
tools: params.tools
|
|
684
|
+
tools: params.tools,
|
|
685
|
+
...options.cacheControl ? { cache_control: { type: "ephemeral" } } : {}
|
|
505
686
|
};
|
|
506
|
-
|
|
507
|
-
requestOptions
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
type
|
|
512
|
-
|
|
513
|
-
|
|
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.";
|
|
514
697
|
}
|
|
698
|
+
if (thinking) requestOptions.thinking = thinking;
|
|
515
699
|
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
516
|
-
if (outputConfig) {
|
|
517
|
-
requestOptions.output_config =
|
|
700
|
+
if (outputConfig || options.effort) {
|
|
701
|
+
requestOptions.output_config = {
|
|
702
|
+
...outputConfig,
|
|
703
|
+
...options.effort ? { effort: options.effort } : {}
|
|
704
|
+
};
|
|
518
705
|
}
|
|
519
|
-
const response = await client2.messages.create(requestOptions
|
|
706
|
+
const response = await client2.messages.create(requestOptions, {
|
|
707
|
+
signal: params.signal
|
|
708
|
+
});
|
|
520
709
|
let text = "";
|
|
521
710
|
const toolCalls = [];
|
|
522
711
|
for (const block of response.content) {
|
|
@@ -530,14 +719,21 @@ function anthropic(modelId, options = {}) {
|
|
|
530
719
|
});
|
|
531
720
|
}
|
|
532
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
|
+
);
|
|
533
727
|
return {
|
|
534
728
|
text,
|
|
729
|
+
reasoningText: response.content.filter((b) => b.type === "thinking").map((b) => b.thinking).join("") || void 0,
|
|
730
|
+
providerMetadata: anthropicReplay(response.content),
|
|
535
731
|
toolCalls,
|
|
536
732
|
finishReason: mapFinishReason(response.stop_reason),
|
|
537
733
|
usage: {
|
|
538
|
-
promptTokens: response.usage
|
|
734
|
+
promptTokens: anthropicInputTokens(response.usage),
|
|
539
735
|
completionTokens: response.usage?.output_tokens ?? 0,
|
|
540
|
-
totalTokens: (response.usage
|
|
736
|
+
totalTokens: anthropicInputTokens(response.usage) + (response.usage?.output_tokens ?? 0)
|
|
541
737
|
},
|
|
542
738
|
rawResponse: response
|
|
543
739
|
};
|
|
@@ -547,37 +743,47 @@ function anthropic(modelId, options = {}) {
|
|
|
547
743
|
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
548
744
|
const requestOptions = {
|
|
549
745
|
model: modelId,
|
|
550
|
-
max_tokens: params.maxTokens
|
|
746
|
+
max_tokens: anthropicMaxTokens(params.maxTokens, thinking),
|
|
551
747
|
system: system || void 0,
|
|
552
748
|
messages,
|
|
553
|
-
tools: params.tools
|
|
749
|
+
tools: params.tools,
|
|
750
|
+
...options.cacheControl ? { cache_control: { type: "ephemeral" } } : {}
|
|
554
751
|
};
|
|
555
|
-
|
|
556
|
-
requestOptions
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
type
|
|
561
|
-
|
|
562
|
-
|
|
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.";
|
|
563
762
|
}
|
|
763
|
+
if (thinking) requestOptions.thinking = thinking;
|
|
564
764
|
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
565
|
-
if (outputConfig) {
|
|
566
|
-
requestOptions.output_config =
|
|
765
|
+
if (outputConfig || options.effort) {
|
|
766
|
+
requestOptions.output_config = {
|
|
767
|
+
...outputConfig,
|
|
768
|
+
...options.effort ? { effort: options.effort } : {}
|
|
769
|
+
};
|
|
567
770
|
}
|
|
568
|
-
const stream = await client2.messages.stream(requestOptions
|
|
771
|
+
const stream = await client2.messages.stream(requestOptions, {
|
|
772
|
+
signal: params.signal
|
|
773
|
+
});
|
|
569
774
|
let currentToolUse = null;
|
|
570
775
|
let inputTokens = 0;
|
|
571
776
|
let outputTokens = 0;
|
|
777
|
+
const content = [];
|
|
778
|
+
const toolCalls = [];
|
|
779
|
+
let stopReason;
|
|
572
780
|
for await (const event of stream) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
781
|
+
collectAnthropicContent(content, event);
|
|
782
|
+
throwIfAborted(params.signal);
|
|
577
783
|
switch (event.type) {
|
|
578
784
|
case "message_start":
|
|
579
785
|
if (event.message?.usage) {
|
|
580
|
-
inputTokens = event.message.usage
|
|
786
|
+
inputTokens = anthropicInputTokens(event.message.usage);
|
|
581
787
|
}
|
|
582
788
|
break;
|
|
583
789
|
case "content_block_start":
|
|
@@ -592,20 +798,19 @@ function anthropic(modelId, options = {}) {
|
|
|
592
798
|
case "content_block_delta":
|
|
593
799
|
if (event.delta?.type === "text_delta") {
|
|
594
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 };
|
|
595
803
|
} else if (event.delta?.type === "input_json_delta" && currentToolUse) {
|
|
596
804
|
currentToolUse.input += event.delta.partial_json;
|
|
597
805
|
}
|
|
598
806
|
break;
|
|
599
807
|
case "content_block_stop":
|
|
600
808
|
if (currentToolUse) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
args: JSON.parse(currentToolUse.input || "{}")
|
|
607
|
-
}
|
|
608
|
-
};
|
|
809
|
+
toolCalls.push({
|
|
810
|
+
id: currentToolUse.id,
|
|
811
|
+
name: currentToolUse.name,
|
|
812
|
+
args: parseToolArguments(currentToolUse.input)
|
|
813
|
+
});
|
|
609
814
|
currentToolUse = null;
|
|
610
815
|
}
|
|
611
816
|
break;
|
|
@@ -614,19 +819,32 @@ function anthropic(modelId, options = {}) {
|
|
|
614
819
|
outputTokens = event.usage.output_tokens ?? 0;
|
|
615
820
|
}
|
|
616
821
|
if (event.delta?.stop_reason) {
|
|
617
|
-
|
|
618
|
-
type: "finish",
|
|
619
|
-
finishReason: mapFinishReason(event.delta.stop_reason),
|
|
620
|
-
usage: {
|
|
621
|
-
promptTokens: inputTokens,
|
|
622
|
-
completionTokens: outputTokens,
|
|
623
|
-
totalTokens: inputTokens + outputTokens
|
|
624
|
-
}
|
|
625
|
-
};
|
|
822
|
+
stopReason = event.delta.stop_reason;
|
|
626
823
|
}
|
|
627
824
|
break;
|
|
628
825
|
}
|
|
629
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
|
+
};
|
|
630
848
|
}
|
|
631
849
|
};
|
|
632
850
|
}
|
|
@@ -644,7 +862,7 @@ function mapFinishReason(reason) {
|
|
|
644
862
|
}
|
|
645
863
|
}
|
|
646
864
|
function formatMessagesForAnthropic2(messages) {
|
|
647
|
-
|
|
865
|
+
const system = extractAnthropicSystemPrompt(messages);
|
|
648
866
|
const formatted = [];
|
|
649
867
|
const pendingToolResults = [];
|
|
650
868
|
const flushToolResults = () => {
|
|
@@ -670,7 +888,6 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
670
888
|
};
|
|
671
889
|
for (const msg of messages) {
|
|
672
890
|
if (msg.role === "system") {
|
|
673
|
-
system += (system ? "\n" : "") + msg.content;
|
|
674
891
|
continue;
|
|
675
892
|
}
|
|
676
893
|
if (msg.role === "assistant" && pendingToolResults.length > 0) {
|
|
@@ -708,6 +925,11 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
708
925
|
formatted.push({ role: "user", content });
|
|
709
926
|
}
|
|
710
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
|
+
}
|
|
711
933
|
const content = [];
|
|
712
934
|
if (msg.content) {
|
|
713
935
|
content.push({ type: "text", text: msg.content });
|
|
@@ -763,7 +985,10 @@ var AnthropicAdapter = class {
|
|
|
763
985
|
if (!this.client) {
|
|
764
986
|
const { default: Anthropic } = await import('@anthropic-ai/sdk');
|
|
765
987
|
this.client = new Anthropic({
|
|
766
|
-
apiKey: this.config.apiKey
|
|
988
|
+
apiKey: this.config.apiKey,
|
|
989
|
+
baseURL: this.config.baseUrl,
|
|
990
|
+
timeout: this.config.timeout,
|
|
991
|
+
defaultHeaders: this.config.headers
|
|
767
992
|
});
|
|
768
993
|
}
|
|
769
994
|
return this.client;
|
|
@@ -800,6 +1025,15 @@ var AnthropicAdapter = class {
|
|
|
800
1025
|
lastToolCallIds = [];
|
|
801
1026
|
toolResultIndex = 0;
|
|
802
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
|
+
}
|
|
803
1037
|
const content = [];
|
|
804
1038
|
if (msg.content && typeof msg.content === "string" && msg.content.trim()) {
|
|
805
1039
|
content.push({ type: "text", text: msg.content });
|
|
@@ -975,7 +1209,7 @@ var AnthropicAdapter = class {
|
|
|
975
1209
|
*/
|
|
976
1210
|
buildRequestOptions(request) {
|
|
977
1211
|
const responseFormat = request.config?.responseFormat;
|
|
978
|
-
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." : "";
|
|
979
1213
|
let systemMessage;
|
|
980
1214
|
let messages;
|
|
981
1215
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
@@ -997,7 +1231,17 @@ var AnthropicAdapter = class {
|
|
|
997
1231
|
const tools = anthropicNativeSearch?.enabled ? this.buildNativeSearchTools(
|
|
998
1232
|
request.toolDefinitions ?? [],
|
|
999
1233
|
anthropicNativeSearch.variant
|
|
1000
|
-
) : 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) => ({
|
|
1001
1245
|
name: action.name,
|
|
1002
1246
|
description: action.description,
|
|
1003
1247
|
input_schema: {
|
|
@@ -1039,12 +1283,25 @@ var AnthropicAdapter = class {
|
|
|
1039
1283
|
};
|
|
1040
1284
|
}
|
|
1041
1285
|
}
|
|
1286
|
+
const thinking = anthropicThinking(
|
|
1287
|
+
request.config?.model || this.model,
|
|
1288
|
+
this.config.thinking
|
|
1289
|
+
);
|
|
1042
1290
|
const options = {
|
|
1043
1291
|
model: request.config?.model || this.model,
|
|
1044
|
-
max_tokens:
|
|
1292
|
+
max_tokens: anthropicMaxTokens(
|
|
1293
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1294
|
+
thinking
|
|
1295
|
+
),
|
|
1045
1296
|
system: systemMessage,
|
|
1046
1297
|
messages,
|
|
1047
|
-
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
|
+
)
|
|
1048
1305
|
};
|
|
1049
1306
|
const anthropicToolOptions = request.providerToolOptions?.anthropic;
|
|
1050
1307
|
if (tools.length > 0 && anthropicToolOptions) {
|
|
@@ -1063,15 +1320,13 @@ var AnthropicAdapter = class {
|
|
|
1063
1320
|
options.server_tool_configuration = serverToolConfiguration;
|
|
1064
1321
|
}
|
|
1065
1322
|
const outputConfig = toAnthropicOutputConfig(responseFormat);
|
|
1066
|
-
if (outputConfig) {
|
|
1067
|
-
options.output_config =
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
options.thinking = {
|
|
1071
|
-
type: "enabled",
|
|
1072
|
-
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 } : {}
|
|
1073
1327
|
};
|
|
1074
1328
|
}
|
|
1329
|
+
if (thinking) options.thinking = thinking;
|
|
1075
1330
|
return { options, messages };
|
|
1076
1331
|
}
|
|
1077
1332
|
/**
|
|
@@ -1091,7 +1346,9 @@ var AnthropicAdapter = class {
|
|
|
1091
1346
|
nonStreamingOptions,
|
|
1092
1347
|
request.debug
|
|
1093
1348
|
);
|
|
1094
|
-
const response = await client.messages.create(nonStreamingOptions
|
|
1349
|
+
const response = await client.messages.create(nonStreamingOptions, {
|
|
1350
|
+
signal: request.signal
|
|
1351
|
+
});
|
|
1095
1352
|
logProviderPayload(
|
|
1096
1353
|
"anthropic",
|
|
1097
1354
|
"response payload",
|
|
@@ -1114,14 +1371,20 @@ var AnthropicAdapter = class {
|
|
|
1114
1371
|
});
|
|
1115
1372
|
}
|
|
1116
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
|
+
);
|
|
1117
1379
|
return {
|
|
1118
1380
|
content,
|
|
1381
|
+
providerMetadata: anthropicReplay(response.content),
|
|
1119
1382
|
toolCalls,
|
|
1120
1383
|
thinking: thinking || void 0,
|
|
1121
1384
|
usage: response.usage ? {
|
|
1122
|
-
promptTokens: response.usage
|
|
1385
|
+
promptTokens: anthropicInputTokens(response.usage),
|
|
1123
1386
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
1124
|
-
totalTokens: (response.usage
|
|
1387
|
+
totalTokens: anthropicInputTokens(response.usage) + (response.usage.output_tokens ?? 0)
|
|
1125
1388
|
} : void 0,
|
|
1126
1389
|
rawResponse: response
|
|
1127
1390
|
};
|
|
@@ -1141,28 +1404,33 @@ var AnthropicAdapter = class {
|
|
|
1141
1404
|
options,
|
|
1142
1405
|
request.debug
|
|
1143
1406
|
);
|
|
1144
|
-
const stream = await client.messages.stream(options
|
|
1407
|
+
const stream = await client.messages.stream(options, {
|
|
1408
|
+
signal: request.signal
|
|
1409
|
+
});
|
|
1145
1410
|
let currentToolUse = null;
|
|
1146
1411
|
let isInThinkingBlock = false;
|
|
1412
|
+
const content = [];
|
|
1413
|
+
const toolCalls = [];
|
|
1414
|
+
let stopReason;
|
|
1147
1415
|
const collectedCitations = [];
|
|
1148
1416
|
let citationIndex = 0;
|
|
1149
1417
|
let usage;
|
|
1150
1418
|
for await (const event of stream) {
|
|
1419
|
+
collectAnthropicContent(content, event);
|
|
1151
1420
|
logProviderPayload("anthropic", "stream event", event, request.debug);
|
|
1152
|
-
|
|
1153
|
-
break;
|
|
1154
|
-
}
|
|
1421
|
+
throwIfAborted(request.signal);
|
|
1155
1422
|
switch (event.type) {
|
|
1156
1423
|
case "message_start":
|
|
1157
1424
|
if (event.message?.usage) {
|
|
1158
1425
|
usage = {
|
|
1159
|
-
prompt_tokens: event.message.usage
|
|
1426
|
+
prompt_tokens: anthropicInputTokens(event.message.usage),
|
|
1160
1427
|
completion_tokens: 0,
|
|
1161
|
-
total_tokens: event.message.usage
|
|
1428
|
+
total_tokens: anthropicInputTokens(event.message.usage)
|
|
1162
1429
|
};
|
|
1163
1430
|
}
|
|
1164
1431
|
break;
|
|
1165
1432
|
case "message_delta":
|
|
1433
|
+
if (event.delta?.stop_reason) stopReason = event.delta.stop_reason;
|
|
1166
1434
|
if (event.usage && usage) {
|
|
1167
1435
|
usage.completion_tokens = event.usage.output_tokens;
|
|
1168
1436
|
usage.total_tokens = usage.prompt_tokens + event.usage.output_tokens;
|
|
@@ -1175,13 +1443,6 @@ var AnthropicAdapter = class {
|
|
|
1175
1443
|
name: event.content_block.name,
|
|
1176
1444
|
input: ""
|
|
1177
1445
|
};
|
|
1178
|
-
if (currentToolUse.name !== "web_search") {
|
|
1179
|
-
yield {
|
|
1180
|
-
type: "action:start",
|
|
1181
|
-
id: currentToolUse.id,
|
|
1182
|
-
name: currentToolUse.name
|
|
1183
|
-
};
|
|
1184
|
-
}
|
|
1185
1446
|
} else if (event.content_block.type === "web_search_tool_result") {
|
|
1186
1447
|
const webSearchResult = event.content_block;
|
|
1187
1448
|
if (webSearchResult.content && Array.isArray(webSearchResult.content)) {
|
|
@@ -1230,16 +1491,11 @@ var AnthropicAdapter = class {
|
|
|
1230
1491
|
case "content_block_stop":
|
|
1231
1492
|
if (currentToolUse) {
|
|
1232
1493
|
if (currentToolUse.name !== "web_search") {
|
|
1233
|
-
|
|
1234
|
-
type: "action:args",
|
|
1235
|
-
id: currentToolUse.id,
|
|
1236
|
-
args: currentToolUse.input
|
|
1237
|
-
};
|
|
1238
|
-
yield {
|
|
1239
|
-
type: "action:end",
|
|
1494
|
+
toolCalls.push({
|
|
1240
1495
|
id: currentToolUse.id,
|
|
1241
|
-
name: currentToolUse.name
|
|
1242
|
-
|
|
1496
|
+
name: currentToolUse.name,
|
|
1497
|
+
args: parseToolArguments(currentToolUse.input)
|
|
1498
|
+
});
|
|
1243
1499
|
}
|
|
1244
1500
|
currentToolUse = null;
|
|
1245
1501
|
}
|
|
@@ -1252,18 +1508,33 @@ var AnthropicAdapter = class {
|
|
|
1252
1508
|
break;
|
|
1253
1509
|
}
|
|
1254
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
|
+
}
|
|
1255
1530
|
if (collectedCitations.length > 0) {
|
|
1256
1531
|
const uniqueCitations = deduplicateCitations(collectedCitations);
|
|
1257
1532
|
yield { type: "citation", citations: uniqueCitations };
|
|
1258
1533
|
}
|
|
1259
1534
|
yield { type: "message:end" };
|
|
1260
|
-
yield { type: "done", usage };
|
|
1535
|
+
yield { type: "done", usage, providerMetadata: anthropicReplay(content) };
|
|
1261
1536
|
} catch (error) {
|
|
1262
|
-
yield
|
|
1263
|
-
type: "error",
|
|
1264
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
1265
|
-
code: "ANTHROPIC_ERROR"
|
|
1266
|
-
};
|
|
1537
|
+
yield providerErrorEvent(error, "ANTHROPIC_ERROR");
|
|
1267
1538
|
}
|
|
1268
1539
|
}
|
|
1269
1540
|
};
|
|
@@ -1379,7 +1650,11 @@ function createAnthropic(config = {}) {
|
|
|
1379
1650
|
apiKey,
|
|
1380
1651
|
model: modelId,
|
|
1381
1652
|
baseUrl: config.baseUrl,
|
|
1382
|
-
|
|
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
|
|
1383
1658
|
});
|
|
1384
1659
|
};
|
|
1385
1660
|
const getCapabilities = (modelId) => {
|
|
@@ -1387,7 +1662,7 @@ function createAnthropic(config = {}) {
|
|
|
1387
1662
|
return {
|
|
1388
1663
|
supportsVision: model.vision,
|
|
1389
1664
|
supportsTools: model.tools,
|
|
1390
|
-
supportsThinking:
|
|
1665
|
+
supportsThinking: anthropicModelRules(modelId).thinking,
|
|
1391
1666
|
supportsStreaming: true,
|
|
1392
1667
|
supportsPDF: true,
|
|
1393
1668
|
supportsAudio: false,
|
|
@@ -1399,8 +1674,7 @@ function createAnthropic(config = {}) {
|
|
|
1399
1674
|
"image/gif",
|
|
1400
1675
|
"image/webp"
|
|
1401
1676
|
],
|
|
1402
|
-
|
|
1403
|
-
supportsJsonMode: true,
|
|
1677
|
+
supportsJsonMode: anthropicModelRules(modelId).structured,
|
|
1404
1678
|
supportsSystemMessages: true
|
|
1405
1679
|
};
|
|
1406
1680
|
};
|