@openrouter/ai-sdk-provider 2.3.2 → 2.4.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/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +87 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +87 -16
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +1 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.js +80 -11
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +80 -11
- package/dist/internal/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { z } from 'zod/v4';
|
|
|
6
6
|
declare enum ReasoningFormat {
|
|
7
7
|
Unknown = "unknown",
|
|
8
8
|
OpenAIResponsesV1 = "openai-responses-v1",
|
|
9
|
+
AzureOpenAIResponsesV1 = "azure-openai-responses-v1",
|
|
9
10
|
XAIResponsesV1 = "xai-responses-v1",
|
|
10
11
|
AnthropicClaudeV1 = "anthropic-claude-v1",
|
|
11
12
|
GoogleGeminiV1 = "google-gemini-v1"
|
package/dist/internal/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { z } from 'zod/v4';
|
|
|
6
6
|
declare enum ReasoningFormat {
|
|
7
7
|
Unknown = "unknown",
|
|
8
8
|
OpenAIResponsesV1 = "openai-responses-v1",
|
|
9
|
+
AzureOpenAIResponsesV1 = "azure-openai-responses-v1",
|
|
9
10
|
XAIResponsesV1 = "xai-responses-v1",
|
|
10
11
|
AnthropicClaudeV1 = "anthropic-claude-v1",
|
|
11
12
|
GoogleGeminiV1 = "google-gemini-v1"
|
package/dist/internal/index.js
CHANGED
|
@@ -2182,11 +2182,13 @@ function isDefinedOrNotNull(value) {
|
|
|
2182
2182
|
var ReasoningFormat = /* @__PURE__ */ ((ReasoningFormat2) => {
|
|
2183
2183
|
ReasoningFormat2["Unknown"] = "unknown";
|
|
2184
2184
|
ReasoningFormat2["OpenAIResponsesV1"] = "openai-responses-v1";
|
|
2185
|
+
ReasoningFormat2["AzureOpenAIResponsesV1"] = "azure-openai-responses-v1";
|
|
2185
2186
|
ReasoningFormat2["XAIResponsesV1"] = "xai-responses-v1";
|
|
2186
2187
|
ReasoningFormat2["AnthropicClaudeV1"] = "anthropic-claude-v1";
|
|
2187
2188
|
ReasoningFormat2["GoogleGeminiV1"] = "google-gemini-v1";
|
|
2188
2189
|
return ReasoningFormat2;
|
|
2189
2190
|
})(ReasoningFormat || {});
|
|
2191
|
+
var DEFAULT_REASONING_FORMAT = "anthropic-claude-v1" /* AnthropicClaudeV1 */;
|
|
2190
2192
|
|
|
2191
2193
|
// src/schemas/reasoning-details.ts
|
|
2192
2194
|
var CommonReasoningDetailSchema = import_v4.z.object({
|
|
@@ -2339,7 +2341,11 @@ var OpenRouterProviderMetadataSchema = import_v43.z.object({
|
|
|
2339
2341
|
}).catchall(import_v43.z.any());
|
|
2340
2342
|
var OpenRouterProviderOptionsSchema = import_v43.z.object({
|
|
2341
2343
|
openrouter: import_v43.z.object({
|
|
2342
|
-
|
|
2344
|
+
// Use ReasoningDetailArraySchema (with unknown fallback) instead of
|
|
2345
|
+
// z.array(ReasoningDetailUnionSchema) so that a single malformed entry
|
|
2346
|
+
// (e.g., a future format not yet in the enum) is individually dropped
|
|
2347
|
+
// rather than causing the entire array to fail parsing.
|
|
2348
|
+
reasoning_details: ReasoningDetailArraySchema.optional(),
|
|
2343
2349
|
annotations: import_v43.z.array(FileAnnotationSchema).optional()
|
|
2344
2350
|
}).optional()
|
|
2345
2351
|
}).optional();
|
|
@@ -2410,6 +2416,31 @@ function createFinishReason(unified, raw) {
|
|
|
2410
2416
|
return { unified, raw };
|
|
2411
2417
|
}
|
|
2412
2418
|
|
|
2419
|
+
// src/utils/with-stream-error-handling.ts
|
|
2420
|
+
function withStreamErrorHandling(source, onError) {
|
|
2421
|
+
const reader = source.getReader();
|
|
2422
|
+
return new ReadableStream({
|
|
2423
|
+
async pull(controller) {
|
|
2424
|
+
try {
|
|
2425
|
+
const { done, value } = await reader.read();
|
|
2426
|
+
if (done) {
|
|
2427
|
+
controller.close();
|
|
2428
|
+
} else {
|
|
2429
|
+
controller.enqueue(value);
|
|
2430
|
+
}
|
|
2431
|
+
} catch (err) {
|
|
2432
|
+
onError(err);
|
|
2433
|
+
reader.cancel().catch(() => {
|
|
2434
|
+
});
|
|
2435
|
+
controller.close();
|
|
2436
|
+
}
|
|
2437
|
+
},
|
|
2438
|
+
cancel(reason) {
|
|
2439
|
+
reader.cancel(reason);
|
|
2440
|
+
}
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2413
2444
|
// src/utils/reasoning-details-duplicate-tracker.ts
|
|
2414
2445
|
var _seenKeys;
|
|
2415
2446
|
var ReasoningDetailsDuplicateTracker = class {
|
|
@@ -2751,8 +2782,24 @@ function convertToOpenRouterChatMessages(prompt) {
|
|
|
2751
2782
|
const candidateReasoningDetails = messageReasoningDetails && Array.isArray(messageReasoningDetails) && messageReasoningDetails.length > 0 ? messageReasoningDetails : findFirstReasoningDetails(content);
|
|
2752
2783
|
let finalReasoningDetails;
|
|
2753
2784
|
if (candidateReasoningDetails && candidateReasoningDetails.length > 0) {
|
|
2785
|
+
const validDetails = candidateReasoningDetails.filter((detail) => {
|
|
2786
|
+
var _a17;
|
|
2787
|
+
if (detail.type !== "reasoning.text" /* Text */) {
|
|
2788
|
+
return true;
|
|
2789
|
+
}
|
|
2790
|
+
const format = (_a17 = detail.format) != null ? _a17 : DEFAULT_REASONING_FORMAT;
|
|
2791
|
+
if (format !== "anthropic-claude-v1" /* AnthropicClaudeV1 */) {
|
|
2792
|
+
return true;
|
|
2793
|
+
}
|
|
2794
|
+
return !!detail.signature;
|
|
2795
|
+
});
|
|
2796
|
+
if (validDetails.length < candidateReasoningDetails.length) {
|
|
2797
|
+
console.warn(
|
|
2798
|
+
"[openrouter] Some reasoning_details entries were removed because they were missing signatures. See https://github.com/OpenRouterTeam/ai-sdk-provider/issues/423 for more details."
|
|
2799
|
+
);
|
|
2800
|
+
}
|
|
2754
2801
|
const uniqueDetails = [];
|
|
2755
|
-
for (const detail of
|
|
2802
|
+
for (const detail of validDetails) {
|
|
2756
2803
|
if (reasoningDetailsTracker.upsert(detail)) {
|
|
2757
2804
|
uniqueDetails.push(detail);
|
|
2758
2805
|
}
|
|
@@ -2781,6 +2828,7 @@ function convertToOpenRouterChatMessages(prompt) {
|
|
|
2781
2828
|
role: "tool",
|
|
2782
2829
|
tool_call_id: toolResponse.toolCallId,
|
|
2783
2830
|
content: content2,
|
|
2831
|
+
name: toolResponse.toolName,
|
|
2784
2832
|
cache_control: (_h = getCacheControl(providerOptions)) != null ? _h : getCacheControl(toolResponse.providerOptions)
|
|
2785
2833
|
});
|
|
2786
2834
|
}
|
|
@@ -2922,13 +2970,14 @@ function filenameFromUrl(url) {
|
|
|
2922
2970
|
}
|
|
2923
2971
|
}
|
|
2924
2972
|
function findFirstReasoningDetails(content) {
|
|
2925
|
-
var _a16, _b16, _c;
|
|
2973
|
+
var _a16, _b16, _c, _d;
|
|
2926
2974
|
for (const part of content) {
|
|
2927
2975
|
if (part.type === "tool-call") {
|
|
2928
|
-
const
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2976
|
+
const parsed = OpenRouterProviderOptionsSchema.safeParse(
|
|
2977
|
+
part.providerOptions
|
|
2978
|
+
);
|
|
2979
|
+
if (parsed.success && ((_b16 = (_a16 = parsed.data) == null ? void 0 : _a16.openrouter) == null ? void 0 : _b16.reasoning_details) && parsed.data.openrouter.reasoning_details.length > 0) {
|
|
2980
|
+
return parsed.data.openrouter.reasoning_details;
|
|
2932
2981
|
}
|
|
2933
2982
|
}
|
|
2934
2983
|
}
|
|
@@ -2937,7 +2986,7 @@ function findFirstReasoningDetails(content) {
|
|
|
2937
2986
|
const parsed = OpenRouterProviderOptionsSchema.safeParse(
|
|
2938
2987
|
part.providerOptions
|
|
2939
2988
|
);
|
|
2940
|
-
if (parsed.success && ((
|
|
2989
|
+
if (parsed.success && ((_d = (_c = parsed.data) == null ? void 0 : _c.openrouter) == null ? void 0 : _d.reasoning_details) && parsed.data.openrouter.reasoning_details.length > 0) {
|
|
2941
2990
|
return parsed.data.openrouter.reasoning_details;
|
|
2942
2991
|
}
|
|
2943
2992
|
}
|
|
@@ -3442,7 +3491,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3442
3491
|
(d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
|
|
3443
3492
|
);
|
|
3444
3493
|
const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
|
|
3445
|
-
const
|
|
3494
|
+
const mappedFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
|
|
3495
|
+
const effectiveFinishReason = hasToolCalls && mappedFinishReason.unified === "other" ? createFinishReason("tool-calls", mappedFinishReason.raw) : mappedFinishReason;
|
|
3446
3496
|
return {
|
|
3447
3497
|
content,
|
|
3448
3498
|
finishReason: effectiveFinishReason,
|
|
@@ -3506,6 +3556,10 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3506
3556
|
abortSignal: options.abortSignal,
|
|
3507
3557
|
fetch: this.config.fetch
|
|
3508
3558
|
});
|
|
3559
|
+
let streamError;
|
|
3560
|
+
const safeResponse = withStreamErrorHandling(response, (err) => {
|
|
3561
|
+
streamError = err;
|
|
3562
|
+
});
|
|
3509
3563
|
const toolCalls = [];
|
|
3510
3564
|
let finishReason = createFinishReason("other");
|
|
3511
3565
|
const usage = {
|
|
@@ -3534,7 +3588,7 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3534
3588
|
let openrouterResponseId;
|
|
3535
3589
|
let provider;
|
|
3536
3590
|
return {
|
|
3537
|
-
stream:
|
|
3591
|
+
stream: safeResponse.pipeThrough(
|
|
3538
3592
|
new TransformStream({
|
|
3539
3593
|
transform(chunk, controller) {
|
|
3540
3594
|
var _a17, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
|
|
@@ -3856,12 +3910,19 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3856
3910
|
flush(controller) {
|
|
3857
3911
|
var _a17;
|
|
3858
3912
|
const hasToolCalls = toolCalls.length > 0;
|
|
3913
|
+
if (streamError != null) {
|
|
3914
|
+
finishReason = createFinishReason("error");
|
|
3915
|
+
controller.enqueue({ type: "error", error: streamError });
|
|
3916
|
+
}
|
|
3859
3917
|
const hasEncryptedReasoning = accumulatedReasoningDetails.some(
|
|
3860
3918
|
(d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
|
|
3861
3919
|
);
|
|
3862
3920
|
if (hasToolCalls && hasEncryptedReasoning && finishReason.unified === "stop") {
|
|
3863
3921
|
finishReason = createFinishReason("tool-calls", finishReason.raw);
|
|
3864
3922
|
}
|
|
3923
|
+
if (hasToolCalls && finishReason.unified === "other") {
|
|
3924
|
+
finishReason = createFinishReason("tool-calls", finishReason.raw);
|
|
3925
|
+
}
|
|
3865
3926
|
if (finishReason.unified === "tool-calls") {
|
|
3866
3927
|
for (const toolCall of toolCalls) {
|
|
3867
3928
|
if (toolCall && !toolCall.sent) {
|
|
@@ -4247,6 +4308,10 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
4247
4308
|
abortSignal: options.abortSignal,
|
|
4248
4309
|
fetch: this.config.fetch
|
|
4249
4310
|
});
|
|
4311
|
+
let streamError;
|
|
4312
|
+
const safeResponse = withStreamErrorHandling(response, (err) => {
|
|
4313
|
+
streamError = err;
|
|
4314
|
+
});
|
|
4250
4315
|
let finishReason = createFinishReason("other");
|
|
4251
4316
|
const usage = {
|
|
4252
4317
|
inputTokens: {
|
|
@@ -4266,7 +4331,7 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
4266
4331
|
let provider;
|
|
4267
4332
|
let rawUsage;
|
|
4268
4333
|
return {
|
|
4269
|
-
stream:
|
|
4334
|
+
stream: safeResponse.pipeThrough(
|
|
4270
4335
|
new TransformStream({
|
|
4271
4336
|
transform(chunk, controller) {
|
|
4272
4337
|
var _a16, _b16, _c, _d, _e;
|
|
@@ -4330,6 +4395,10 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
4330
4395
|
}
|
|
4331
4396
|
},
|
|
4332
4397
|
flush(controller) {
|
|
4398
|
+
if (streamError != null) {
|
|
4399
|
+
finishReason = createFinishReason("error");
|
|
4400
|
+
controller.enqueue({ type: "error", error: streamError });
|
|
4401
|
+
}
|
|
4333
4402
|
usage.raw = rawUsage;
|
|
4334
4403
|
const openrouterMetadata = {
|
|
4335
4404
|
usage: openrouterUsage
|