@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
package/dist/index.mjs
CHANGED
|
@@ -2183,11 +2183,13 @@ function isDefinedOrNotNull(value) {
|
|
|
2183
2183
|
var ReasoningFormat = /* @__PURE__ */ ((ReasoningFormat2) => {
|
|
2184
2184
|
ReasoningFormat2["Unknown"] = "unknown";
|
|
2185
2185
|
ReasoningFormat2["OpenAIResponsesV1"] = "openai-responses-v1";
|
|
2186
|
+
ReasoningFormat2["AzureOpenAIResponsesV1"] = "azure-openai-responses-v1";
|
|
2186
2187
|
ReasoningFormat2["XAIResponsesV1"] = "xai-responses-v1";
|
|
2187
2188
|
ReasoningFormat2["AnthropicClaudeV1"] = "anthropic-claude-v1";
|
|
2188
2189
|
ReasoningFormat2["GoogleGeminiV1"] = "google-gemini-v1";
|
|
2189
2190
|
return ReasoningFormat2;
|
|
2190
2191
|
})(ReasoningFormat || {});
|
|
2192
|
+
var DEFAULT_REASONING_FORMAT = "anthropic-claude-v1" /* AnthropicClaudeV1 */;
|
|
2191
2193
|
|
|
2192
2194
|
// src/schemas/reasoning-details.ts
|
|
2193
2195
|
var CommonReasoningDetailSchema = z.object({
|
|
@@ -2340,7 +2342,11 @@ var OpenRouterProviderMetadataSchema = z3.object({
|
|
|
2340
2342
|
}).catchall(z3.any());
|
|
2341
2343
|
var OpenRouterProviderOptionsSchema = z3.object({
|
|
2342
2344
|
openrouter: z3.object({
|
|
2343
|
-
|
|
2345
|
+
// Use ReasoningDetailArraySchema (with unknown fallback) instead of
|
|
2346
|
+
// z.array(ReasoningDetailUnionSchema) so that a single malformed entry
|
|
2347
|
+
// (e.g., a future format not yet in the enum) is individually dropped
|
|
2348
|
+
// rather than causing the entire array to fail parsing.
|
|
2349
|
+
reasoning_details: ReasoningDetailArraySchema.optional(),
|
|
2344
2350
|
annotations: z3.array(FileAnnotationSchema).optional()
|
|
2345
2351
|
}).optional()
|
|
2346
2352
|
}).optional();
|
|
@@ -2411,6 +2417,31 @@ function createFinishReason(unified, raw) {
|
|
|
2411
2417
|
return { unified, raw };
|
|
2412
2418
|
}
|
|
2413
2419
|
|
|
2420
|
+
// src/utils/with-stream-error-handling.ts
|
|
2421
|
+
function withStreamErrorHandling(source, onError) {
|
|
2422
|
+
const reader = source.getReader();
|
|
2423
|
+
return new ReadableStream({
|
|
2424
|
+
async pull(controller) {
|
|
2425
|
+
try {
|
|
2426
|
+
const { done, value } = await reader.read();
|
|
2427
|
+
if (done) {
|
|
2428
|
+
controller.close();
|
|
2429
|
+
} else {
|
|
2430
|
+
controller.enqueue(value);
|
|
2431
|
+
}
|
|
2432
|
+
} catch (err) {
|
|
2433
|
+
onError(err);
|
|
2434
|
+
reader.cancel().catch(() => {
|
|
2435
|
+
});
|
|
2436
|
+
controller.close();
|
|
2437
|
+
}
|
|
2438
|
+
},
|
|
2439
|
+
cancel(reason) {
|
|
2440
|
+
reader.cancel(reason);
|
|
2441
|
+
}
|
|
2442
|
+
});
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2414
2445
|
// src/utils/reasoning-details-duplicate-tracker.ts
|
|
2415
2446
|
var _seenKeys;
|
|
2416
2447
|
var ReasoningDetailsDuplicateTracker = class {
|
|
@@ -2752,8 +2783,24 @@ function convertToOpenRouterChatMessages(prompt) {
|
|
|
2752
2783
|
const candidateReasoningDetails = messageReasoningDetails && Array.isArray(messageReasoningDetails) && messageReasoningDetails.length > 0 ? messageReasoningDetails : findFirstReasoningDetails(content);
|
|
2753
2784
|
let finalReasoningDetails;
|
|
2754
2785
|
if (candidateReasoningDetails && candidateReasoningDetails.length > 0) {
|
|
2786
|
+
const validDetails = candidateReasoningDetails.filter((detail) => {
|
|
2787
|
+
var _a17;
|
|
2788
|
+
if (detail.type !== "reasoning.text" /* Text */) {
|
|
2789
|
+
return true;
|
|
2790
|
+
}
|
|
2791
|
+
const format = (_a17 = detail.format) != null ? _a17 : DEFAULT_REASONING_FORMAT;
|
|
2792
|
+
if (format !== "anthropic-claude-v1" /* AnthropicClaudeV1 */) {
|
|
2793
|
+
return true;
|
|
2794
|
+
}
|
|
2795
|
+
return !!detail.signature;
|
|
2796
|
+
});
|
|
2797
|
+
if (validDetails.length < candidateReasoningDetails.length) {
|
|
2798
|
+
console.warn(
|
|
2799
|
+
"[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."
|
|
2800
|
+
);
|
|
2801
|
+
}
|
|
2755
2802
|
const uniqueDetails = [];
|
|
2756
|
-
for (const detail of
|
|
2803
|
+
for (const detail of validDetails) {
|
|
2757
2804
|
if (reasoningDetailsTracker.upsert(detail)) {
|
|
2758
2805
|
uniqueDetails.push(detail);
|
|
2759
2806
|
}
|
|
@@ -2782,6 +2829,7 @@ function convertToOpenRouterChatMessages(prompt) {
|
|
|
2782
2829
|
role: "tool",
|
|
2783
2830
|
tool_call_id: toolResponse.toolCallId,
|
|
2784
2831
|
content: content2,
|
|
2832
|
+
name: toolResponse.toolName,
|
|
2785
2833
|
cache_control: (_h = getCacheControl(providerOptions)) != null ? _h : getCacheControl(toolResponse.providerOptions)
|
|
2786
2834
|
});
|
|
2787
2835
|
}
|
|
@@ -2923,13 +2971,14 @@ function filenameFromUrl(url) {
|
|
|
2923
2971
|
}
|
|
2924
2972
|
}
|
|
2925
2973
|
function findFirstReasoningDetails(content) {
|
|
2926
|
-
var _a16, _b16, _c;
|
|
2974
|
+
var _a16, _b16, _c, _d;
|
|
2927
2975
|
for (const part of content) {
|
|
2928
2976
|
if (part.type === "tool-call") {
|
|
2929
|
-
const
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2977
|
+
const parsed = OpenRouterProviderOptionsSchema.safeParse(
|
|
2978
|
+
part.providerOptions
|
|
2979
|
+
);
|
|
2980
|
+
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) {
|
|
2981
|
+
return parsed.data.openrouter.reasoning_details;
|
|
2933
2982
|
}
|
|
2934
2983
|
}
|
|
2935
2984
|
}
|
|
@@ -2938,7 +2987,7 @@ function findFirstReasoningDetails(content) {
|
|
|
2938
2987
|
const parsed = OpenRouterProviderOptionsSchema.safeParse(
|
|
2939
2988
|
part.providerOptions
|
|
2940
2989
|
);
|
|
2941
|
-
if (parsed.success && ((
|
|
2990
|
+
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) {
|
|
2942
2991
|
return parsed.data.openrouter.reasoning_details;
|
|
2943
2992
|
}
|
|
2944
2993
|
}
|
|
@@ -3443,7 +3492,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3443
3492
|
(d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
|
|
3444
3493
|
);
|
|
3445
3494
|
const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
|
|
3446
|
-
const
|
|
3495
|
+
const mappedFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
|
|
3496
|
+
const effectiveFinishReason = hasToolCalls && mappedFinishReason.unified === "other" ? createFinishReason("tool-calls", mappedFinishReason.raw) : mappedFinishReason;
|
|
3447
3497
|
return {
|
|
3448
3498
|
content,
|
|
3449
3499
|
finishReason: effectiveFinishReason,
|
|
@@ -3507,6 +3557,10 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3507
3557
|
abortSignal: options.abortSignal,
|
|
3508
3558
|
fetch: this.config.fetch
|
|
3509
3559
|
});
|
|
3560
|
+
let streamError;
|
|
3561
|
+
const safeResponse = withStreamErrorHandling(response, (err) => {
|
|
3562
|
+
streamError = err;
|
|
3563
|
+
});
|
|
3510
3564
|
const toolCalls = [];
|
|
3511
3565
|
let finishReason = createFinishReason("other");
|
|
3512
3566
|
const usage = {
|
|
@@ -3535,7 +3589,7 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3535
3589
|
let openrouterResponseId;
|
|
3536
3590
|
let provider;
|
|
3537
3591
|
return {
|
|
3538
|
-
stream:
|
|
3592
|
+
stream: safeResponse.pipeThrough(
|
|
3539
3593
|
new TransformStream({
|
|
3540
3594
|
transform(chunk, controller) {
|
|
3541
3595
|
var _a17, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
|
|
@@ -3857,12 +3911,19 @@ var OpenRouterChatLanguageModel = class {
|
|
|
3857
3911
|
flush(controller) {
|
|
3858
3912
|
var _a17;
|
|
3859
3913
|
const hasToolCalls = toolCalls.length > 0;
|
|
3914
|
+
if (streamError != null) {
|
|
3915
|
+
finishReason = createFinishReason("error");
|
|
3916
|
+
controller.enqueue({ type: "error", error: streamError });
|
|
3917
|
+
}
|
|
3860
3918
|
const hasEncryptedReasoning = accumulatedReasoningDetails.some(
|
|
3861
3919
|
(d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
|
|
3862
3920
|
);
|
|
3863
3921
|
if (hasToolCalls && hasEncryptedReasoning && finishReason.unified === "stop") {
|
|
3864
3922
|
finishReason = createFinishReason("tool-calls", finishReason.raw);
|
|
3865
3923
|
}
|
|
3924
|
+
if (hasToolCalls && finishReason.unified === "other") {
|
|
3925
|
+
finishReason = createFinishReason("tool-calls", finishReason.raw);
|
|
3926
|
+
}
|
|
3866
3927
|
if (finishReason.unified === "tool-calls") {
|
|
3867
3928
|
for (const toolCall of toolCalls) {
|
|
3868
3929
|
if (toolCall && !toolCall.sent) {
|
|
@@ -4248,6 +4309,10 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
4248
4309
|
abortSignal: options.abortSignal,
|
|
4249
4310
|
fetch: this.config.fetch
|
|
4250
4311
|
});
|
|
4312
|
+
let streamError;
|
|
4313
|
+
const safeResponse = withStreamErrorHandling(response, (err) => {
|
|
4314
|
+
streamError = err;
|
|
4315
|
+
});
|
|
4251
4316
|
let finishReason = createFinishReason("other");
|
|
4252
4317
|
const usage = {
|
|
4253
4318
|
inputTokens: {
|
|
@@ -4267,7 +4332,7 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
4267
4332
|
let provider;
|
|
4268
4333
|
let rawUsage;
|
|
4269
4334
|
return {
|
|
4270
|
-
stream:
|
|
4335
|
+
stream: safeResponse.pipeThrough(
|
|
4271
4336
|
new TransformStream({
|
|
4272
4337
|
transform(chunk, controller) {
|
|
4273
4338
|
var _a16, _b16, _c, _d, _e;
|
|
@@ -4331,6 +4396,10 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
4331
4396
|
}
|
|
4332
4397
|
},
|
|
4333
4398
|
flush(controller) {
|
|
4399
|
+
if (streamError != null) {
|
|
4400
|
+
finishReason = createFinishReason("error");
|
|
4401
|
+
controller.enqueue({ type: "error", error: streamError });
|
|
4402
|
+
}
|
|
4334
4403
|
usage.raw = rawUsage;
|
|
4335
4404
|
const openrouterMetadata = {
|
|
4336
4405
|
usage: openrouterUsage
|
|
@@ -4444,17 +4513,19 @@ var OpenRouter = class {
|
|
|
4444
4513
|
this.apiKey = options.apiKey;
|
|
4445
4514
|
this.headers = options.headers;
|
|
4446
4515
|
this.api_keys = options.api_keys;
|
|
4516
|
+
this.appName = options.appName;
|
|
4517
|
+
this.appUrl = options.appUrl;
|
|
4447
4518
|
}
|
|
4448
4519
|
get baseConfig() {
|
|
4449
4520
|
return {
|
|
4450
4521
|
baseURL: this.baseURL,
|
|
4451
|
-
headers: () => __spreadValues(__spreadValues({
|
|
4522
|
+
headers: () => __spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
4452
4523
|
Authorization: `Bearer ${loadApiKey({
|
|
4453
4524
|
apiKey: this.apiKey,
|
|
4454
4525
|
environmentVariableName: "OPENROUTER_API_KEY",
|
|
4455
4526
|
description: "OpenRouter"
|
|
4456
4527
|
})}`
|
|
4457
|
-
}, this.headers), this.api_keys && Object.keys(this.api_keys).length > 0 && {
|
|
4528
|
+
}, this.appName && { "X-OpenRouter-Title": this.appName }), this.appUrl && { "HTTP-Referer": this.appUrl }), this.headers), this.api_keys && Object.keys(this.api_keys).length > 0 && {
|
|
4458
4529
|
"X-Provider-API-Keys": JSON.stringify(this.api_keys)
|
|
4459
4530
|
})
|
|
4460
4531
|
};
|
|
@@ -4691,7 +4762,7 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
|
|
|
4691
4762
|
}
|
|
4692
4763
|
|
|
4693
4764
|
// src/version.ts
|
|
4694
|
-
var VERSION2 = false ? "0.0.0-test" : "2.
|
|
4765
|
+
var VERSION2 = false ? "0.0.0-test" : "2.4.0";
|
|
4695
4766
|
|
|
4696
4767
|
// src/provider.ts
|
|
4697
4768
|
function createOpenRouter(options = {}) {
|
|
@@ -4699,13 +4770,13 @@ function createOpenRouter(options = {}) {
|
|
|
4699
4770
|
const baseURL = (_b16 = withoutTrailingSlash((_a16 = options.baseURL) != null ? _a16 : options.baseUrl)) != null ? _b16 : "https://openrouter.ai/api/v1";
|
|
4700
4771
|
const compatibility = (_c = options.compatibility) != null ? _c : "compatible";
|
|
4701
4772
|
const getHeaders = () => withUserAgentSuffix2(
|
|
4702
|
-
__spreadValues(__spreadValues({
|
|
4773
|
+
__spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
4703
4774
|
Authorization: `Bearer ${loadApiKey({
|
|
4704
4775
|
apiKey: options.apiKey,
|
|
4705
4776
|
environmentVariableName: "OPENROUTER_API_KEY",
|
|
4706
4777
|
description: "OpenRouter"
|
|
4707
4778
|
})}`
|
|
4708
|
-
}, options.headers), options.api_keys && Object.keys(options.api_keys).length > 0 && {
|
|
4779
|
+
}, options.appName && { "X-OpenRouter-Title": options.appName }), options.appUrl && { "HTTP-Referer": options.appUrl }), options.headers), options.api_keys && Object.keys(options.api_keys).length > 0 && {
|
|
4709
4780
|
"X-Provider-API-Keys": JSON.stringify(options.api_keys)
|
|
4710
4781
|
}),
|
|
4711
4782
|
`ai-sdk/openrouter/${VERSION2}`
|