@openrouter/ai-sdk-provider 2.0.2 → 2.1.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.js CHANGED
@@ -2478,7 +2478,7 @@ function getCacheControl(providerMetadata) {
2478
2478
  return (_c = (_b16 = (_a16 = openrouter2 == null ? void 0 : openrouter2.cacheControl) != null ? _a16 : openrouter2 == null ? void 0 : openrouter2.cache_control) != null ? _b16 : anthropic == null ? void 0 : anthropic.cacheControl) != null ? _c : anthropic == null ? void 0 : anthropic.cache_control;
2479
2479
  }
2480
2480
  function convertToOpenRouterChatMessages(prompt) {
2481
- var _a16, _b16, _c, _d, _e, _f, _g;
2481
+ var _a16, _b16, _c, _d, _e, _f, _g, _h;
2482
2482
  const messages = [];
2483
2483
  for (const { role, content, providerOptions } of prompt) {
2484
2484
  switch (role) {
@@ -2507,42 +2507,46 @@ function convertToOpenRouterChatMessages(prompt) {
2507
2507
  break;
2508
2508
  }
2509
2509
  const messageCacheControl = getCacheControl(providerOptions);
2510
+ let lastTextPartIndex = -1;
2511
+ for (let i = content.length - 1; i >= 0; i--) {
2512
+ if (((_c = content[i]) == null ? void 0 : _c.type) === "text") {
2513
+ lastTextPartIndex = i;
2514
+ break;
2515
+ }
2516
+ }
2510
2517
  const contentParts = content.map(
2511
- (part) => {
2512
- var _a17, _b17, _c2, _d2, _e2, _f2, _g2;
2513
- const cacheControl = (_a17 = getCacheControl(part.providerOptions)) != null ? _a17 : messageCacheControl;
2518
+ (part, index) => {
2519
+ var _a17, _b17, _c2, _d2, _e2, _f2;
2520
+ const isLastTextPart = part.type === "text" && index === lastTextPartIndex;
2521
+ const partCacheControl = getCacheControl(part.providerOptions);
2522
+ const cacheControl = part.type === "text" ? partCacheControl != null ? partCacheControl : isLastTextPart ? messageCacheControl : void 0 : partCacheControl;
2514
2523
  switch (part.type) {
2515
2524
  case "text":
2516
- return {
2525
+ return __spreadValues({
2517
2526
  type: "text",
2518
- text: part.text,
2519
- // For text parts, only use part-specific cache control
2520
- cache_control: cacheControl
2521
- };
2527
+ text: part.text
2528
+ }, cacheControl && { cache_control: cacheControl });
2522
2529
  case "file": {
2523
- if ((_b17 = part.mediaType) == null ? void 0 : _b17.startsWith("image/")) {
2530
+ if ((_a17 = part.mediaType) == null ? void 0 : _a17.startsWith("image/")) {
2524
2531
  const url = getFileUrl({
2525
2532
  part,
2526
2533
  defaultMediaType: "image/jpeg"
2527
2534
  });
2528
- return {
2535
+ return __spreadValues({
2529
2536
  type: "image_url",
2530
2537
  image_url: {
2531
2538
  url
2532
- },
2533
- // For image parts, use part-specific or message-level cache control
2534
- cache_control: cacheControl
2535
- };
2539
+ }
2540
+ }, cacheControl && { cache_control: cacheControl });
2536
2541
  }
2537
- if ((_c2 = part.mediaType) == null ? void 0 : _c2.startsWith("audio/")) {
2538
- return {
2542
+ if ((_b17 = part.mediaType) == null ? void 0 : _b17.startsWith("audio/")) {
2543
+ return __spreadValues({
2539
2544
  type: "input_audio",
2540
- input_audio: getInputAudioData(part),
2541
- cache_control: cacheControl
2542
- };
2545
+ input_audio: getInputAudioData(part)
2546
+ }, cacheControl && { cache_control: cacheControl });
2543
2547
  }
2544
2548
  const fileName = String(
2545
- (_g2 = (_f2 = (_e2 = (_d2 = part.providerOptions) == null ? void 0 : _d2.openrouter) == null ? void 0 : _e2.filename) != null ? _f2 : part.filename) != null ? _g2 : ""
2549
+ (_f2 = (_e2 = (_d2 = (_c2 = part.providerOptions) == null ? void 0 : _c2.openrouter) == null ? void 0 : _d2.filename) != null ? _e2 : part.filename) != null ? _f2 : ""
2546
2550
  );
2547
2551
  const fileData = getFileUrl({
2548
2552
  part,
@@ -2560,21 +2564,19 @@ function convertToOpenRouterChatMessages(prompt) {
2560
2564
  }
2561
2565
  };
2562
2566
  }
2563
- return {
2567
+ return __spreadValues({
2564
2568
  type: "file",
2565
2569
  file: {
2566
2570
  filename: fileName,
2567
2571
  file_data: fileData
2568
- },
2569
- cache_control: cacheControl
2570
- };
2572
+ }
2573
+ }, cacheControl && { cache_control: cacheControl });
2571
2574
  }
2572
2575
  default: {
2573
- return {
2576
+ return __spreadValues({
2574
2577
  type: "text",
2575
- text: "",
2576
- cache_control: cacheControl
2577
- };
2578
+ text: ""
2579
+ }, cacheControl && { cache_control: cacheControl });
2578
2580
  }
2579
2581
  }
2580
2582
  }
@@ -2618,8 +2620,8 @@ function convertToOpenRouterChatMessages(prompt) {
2618
2620
  }
2619
2621
  }
2620
2622
  const parsedProviderOptions = OpenRouterProviderOptionsSchema.safeParse(providerOptions);
2621
- const messageReasoningDetails = parsedProviderOptions.success ? (_d = (_c = parsedProviderOptions.data) == null ? void 0 : _c.openrouter) == null ? void 0 : _d.reasoning_details : void 0;
2622
- const messageAnnotations = parsedProviderOptions.success ? (_f = (_e = parsedProviderOptions.data) == null ? void 0 : _e.openrouter) == null ? void 0 : _f.annotations : void 0;
2623
+ const messageReasoningDetails = parsedProviderOptions.success ? (_e = (_d = parsedProviderOptions.data) == null ? void 0 : _d.openrouter) == null ? void 0 : _e.reasoning_details : void 0;
2624
+ const messageAnnotations = parsedProviderOptions.success ? (_g = (_f = parsedProviderOptions.data) == null ? void 0 : _f.openrouter) == null ? void 0 : _g.annotations : void 0;
2623
2625
  const finalReasoningDetails = messageReasoningDetails && Array.isArray(messageReasoningDetails) && messageReasoningDetails.length > 0 ? messageReasoningDetails : findFirstReasoningDetails(content);
2624
2626
  messages.push({
2625
2627
  role: "assistant",
@@ -2642,7 +2644,7 @@ function convertToOpenRouterChatMessages(prompt) {
2642
2644
  role: "tool",
2643
2645
  tool_call_id: toolResponse.toolCallId,
2644
2646
  content: content2,
2645
- cache_control: (_g = getCacheControl(providerOptions)) != null ? _g : getCacheControl(toolResponse.providerOptions)
2647
+ cache_control: (_h = getCacheControl(providerOptions)) != null ? _h : getCacheControl(toolResponse.providerOptions)
2646
2648
  });
2647
2649
  }
2648
2650
  break;
@@ -2782,20 +2784,21 @@ var OpenRouterNonStreamChatCompletionResponseSchema = import_v46.z.union([
2782
2784
  type: import_v46.z.literal("function"),
2783
2785
  function: import_v46.z.object({
2784
2786
  name: import_v46.z.string(),
2785
- arguments: import_v46.z.string()
2787
+ arguments: import_v46.z.string().optional()
2786
2788
  }).passthrough()
2787
2789
  }).passthrough()
2788
2790
  ).optional(),
2789
2791
  annotations: import_v46.z.array(
2790
2792
  import_v46.z.union([
2791
2793
  // URL citation from web search
2794
+ // title, start_index, end_index are optional as some upstream providers may omit them
2792
2795
  import_v46.z.object({
2793
2796
  type: import_v46.z.literal("url_citation"),
2794
2797
  url_citation: import_v46.z.object({
2795
- end_index: import_v46.z.number(),
2796
- start_index: import_v46.z.number(),
2797
- title: import_v46.z.string(),
2798
2798
  url: import_v46.z.string(),
2799
+ title: import_v46.z.string().optional(),
2800
+ start_index: import_v46.z.number().optional(),
2801
+ end_index: import_v46.z.number().optional(),
2799
2802
  content: import_v46.z.string().optional()
2800
2803
  }).passthrough()
2801
2804
  }).passthrough(),
@@ -2872,13 +2875,14 @@ var OpenRouterStreamChatCompletionChunkSchema = import_v46.z.union([
2872
2875
  annotations: import_v46.z.array(
2873
2876
  import_v46.z.union([
2874
2877
  // URL citation from web search
2878
+ // title, start_index, end_index are optional as some upstream providers may omit them
2875
2879
  import_v46.z.object({
2876
2880
  type: import_v46.z.literal("url_citation"),
2877
2881
  url_citation: import_v46.z.object({
2878
- end_index: import_v46.z.number(),
2879
- start_index: import_v46.z.number(),
2880
- title: import_v46.z.string(),
2881
2882
  url: import_v46.z.string(),
2883
+ title: import_v46.z.string().optional(),
2884
+ start_index: import_v46.z.number().optional(),
2885
+ end_index: import_v46.z.number().optional(),
2882
2886
  content: import_v46.z.string().optional()
2883
2887
  }).passthrough()
2884
2888
  }).passthrough(),
@@ -3025,7 +3029,7 @@ var OpenRouterChatLanguageModel = class {
3025
3029
  return baseArgs;
3026
3030
  }
3027
3031
  async doGenerate(options) {
3028
- var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
3032
+ var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
3029
3033
  const providerOptions = options.providerOptions || {};
3030
3034
  const openrouterOptions = providerOptions.openrouter || {};
3031
3035
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3075,7 +3079,8 @@ var OpenRouterChatLanguageModel = class {
3075
3079
  total: (_d = response.usage.completion_tokens) != null ? _d : 0,
3076
3080
  text: void 0,
3077
3081
  reasoning: (_f = (_e = response.usage.completion_tokens_details) == null ? void 0 : _e.reasoning_tokens) != null ? _f : void 0
3078
- }
3082
+ },
3083
+ raw: response.usage
3079
3084
  } : {
3080
3085
  inputTokens: {
3081
3086
  total: 0,
@@ -3087,7 +3092,8 @@ var OpenRouterChatLanguageModel = class {
3087
3092
  total: 0,
3088
3093
  text: void 0,
3089
3094
  reasoning: void 0
3090
- }
3095
+ },
3096
+ raw: void 0
3091
3097
  };
3092
3098
  const reasoningDetails = (_g = choice.message.reasoning_details) != null ? _g : [];
3093
3099
  const reasoning = reasoningDetails.length > 0 ? reasoningDetails.map((detail) => {
@@ -3160,7 +3166,7 @@ var OpenRouterChatLanguageModel = class {
3160
3166
  type: "tool-call",
3161
3167
  toolCallId: (_h = toolCall.id) != null ? _h : generateId(),
3162
3168
  toolName: toolCall.function.name,
3163
- input: toolCall.function.arguments,
3169
+ input: (_i = toolCall.function.arguments) != null ? _i : "{}",
3164
3170
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
3165
3171
  openrouter: {
3166
3172
  reasoning_details: reasoningDetails
@@ -3187,17 +3193,19 @@ var OpenRouterChatLanguageModel = class {
3187
3193
  sourceType: "url",
3188
3194
  id: annotation.url_citation.url,
3189
3195
  url: annotation.url_citation.url,
3190
- title: annotation.url_citation.title,
3196
+ title: (_j = annotation.url_citation.title) != null ? _j : "",
3191
3197
  providerMetadata: {
3192
3198
  openrouter: {
3193
- content: annotation.url_citation.content || ""
3199
+ content: (_k = annotation.url_citation.content) != null ? _k : "",
3200
+ startIndex: (_l = annotation.url_citation.start_index) != null ? _l : 0,
3201
+ endIndex: (_m = annotation.url_citation.end_index) != null ? _m : 0
3194
3202
  }
3195
3203
  }
3196
3204
  });
3197
3205
  }
3198
3206
  }
3199
3207
  }
3200
- const fileAnnotations = (_i = choice.message.annotations) == null ? void 0 : _i.filter(
3208
+ const fileAnnotations = (_n = choice.message.annotations) == null ? void 0 : _n.filter(
3201
3209
  (a) => a.type === "file"
3202
3210
  );
3203
3211
  const hasToolCalls = choice.message.tool_calls && choice.message.tool_calls.length > 0;
@@ -3205,7 +3213,7 @@ var OpenRouterChatLanguageModel = class {
3205
3213
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3206
3214
  );
3207
3215
  const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
3208
- const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3216
+ const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_o = choice.finish_reason) != null ? _o : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3209
3217
  return {
3210
3218
  content,
3211
3219
  finishReason: effectiveFinishReason,
@@ -3213,23 +3221,22 @@ var OpenRouterChatLanguageModel = class {
3213
3221
  warnings: [],
3214
3222
  providerMetadata: {
3215
3223
  openrouter: OpenRouterProviderMetadataSchema.parse({
3216
- provider: (_k = response.provider) != null ? _k : "",
3217
- reasoning_details: (_l = choice.message.reasoning_details) != null ? _l : [],
3224
+ provider: (_p = response.provider) != null ? _p : "",
3225
+ reasoning_details: (_q = choice.message.reasoning_details) != null ? _q : [],
3218
3226
  annotations: fileAnnotations && fileAnnotations.length > 0 ? fileAnnotations : void 0,
3219
- usage: __spreadValues(__spreadValues(__spreadValues({
3220
- promptTokens: (_m = usageInfo.inputTokens.total) != null ? _m : 0,
3221
- completionTokens: (_n = usageInfo.outputTokens.total) != null ? _n : 0,
3222
- totalTokens: ((_o = usageInfo.inputTokens.total) != null ? _o : 0) + ((_p = usageInfo.outputTokens.total) != null ? _p : 0),
3223
- cost: (_q = response.usage) == null ? void 0 : _q.cost
3224
- }, ((_s = (_r = response.usage) == null ? void 0 : _r.prompt_tokens_details) == null ? void 0 : _s.cached_tokens) != null ? {
3227
+ usage: __spreadValues(__spreadValues(__spreadValues(__spreadValues({
3228
+ promptTokens: (_r = usageInfo.inputTokens.total) != null ? _r : 0,
3229
+ completionTokens: (_s = usageInfo.outputTokens.total) != null ? _s : 0,
3230
+ totalTokens: ((_t = usageInfo.inputTokens.total) != null ? _t : 0) + ((_u = usageInfo.outputTokens.total) != null ? _u : 0)
3231
+ }, ((_v = response.usage) == null ? void 0 : _v.cost) != null ? { cost: response.usage.cost } : {}), ((_x = (_w = response.usage) == null ? void 0 : _w.prompt_tokens_details) == null ? void 0 : _x.cached_tokens) != null ? {
3225
3232
  promptTokensDetails: {
3226
3233
  cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3227
3234
  }
3228
- } : {}), ((_u = (_t = response.usage) == null ? void 0 : _t.completion_tokens_details) == null ? void 0 : _u.reasoning_tokens) != null ? {
3235
+ } : {}), ((_z = (_y = response.usage) == null ? void 0 : _y.completion_tokens_details) == null ? void 0 : _z.reasoning_tokens) != null ? {
3229
3236
  completionTokensDetails: {
3230
3237
  reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3231
3238
  }
3232
- } : {}), ((_w = (_v = response.usage) == null ? void 0 : _v.cost_details) == null ? void 0 : _w.upstream_inference_cost) != null ? {
3239
+ } : {}), ((_B = (_A = response.usage) == null ? void 0 : _A.cost_details) == null ? void 0 : _B.upstream_inference_cost) != null ? {
3233
3240
  costDetails: {
3234
3241
  upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3235
3242
  }
@@ -3282,9 +3289,11 @@ var OpenRouterChatLanguageModel = class {
3282
3289
  total: void 0,
3283
3290
  text: void 0,
3284
3291
  reasoning: void 0
3285
- }
3292
+ },
3293
+ raw: void 0
3286
3294
  };
3287
3295
  const openrouterUsage = {};
3296
+ let rawUsage;
3288
3297
  const accumulatedReasoningDetails = [];
3289
3298
  let reasoningDetailsAttachedToToolCall = false;
3290
3299
  const accumulatedFileAnnotations = [];
@@ -3298,7 +3307,10 @@ var OpenRouterChatLanguageModel = class {
3298
3307
  stream: response.pipeThrough(
3299
3308
  new TransformStream({
3300
3309
  transform(chunk, controller) {
3301
- var _a17, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
3310
+ var _a17, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
3311
+ if (options.includeRawChunks) {
3312
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
3313
+ }
3302
3314
  if (!chunk.success) {
3303
3315
  finishReason = createFinishReason("error");
3304
3316
  controller.enqueue({ type: "error", error: chunk.error });
@@ -3329,6 +3341,7 @@ var OpenRouterChatLanguageModel = class {
3329
3341
  if (value.usage != null) {
3330
3342
  usage.inputTokens.total = value.usage.prompt_tokens;
3331
3343
  usage.outputTokens.total = value.usage.completion_tokens;
3344
+ rawUsage = value.usage;
3332
3345
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
3333
3346
  if (value.usage.prompt_tokens_details) {
3334
3347
  const cachedInputTokens = (_a17 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a17 : 0;
@@ -3345,7 +3358,9 @@ var OpenRouterChatLanguageModel = class {
3345
3358
  reasoningTokens
3346
3359
  };
3347
3360
  }
3348
- openrouterUsage.cost = value.usage.cost;
3361
+ if (value.usage.cost != null) {
3362
+ openrouterUsage.cost = value.usage.cost;
3363
+ }
3349
3364
  openrouterUsage.totalTokens = value.usage.total_tokens;
3350
3365
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
3351
3366
  if (upstreamInferenceCost != null) {
@@ -3458,10 +3473,12 @@ var OpenRouterChatLanguageModel = class {
3458
3473
  sourceType: "url",
3459
3474
  id: annotation.url_citation.url,
3460
3475
  url: annotation.url_citation.url,
3461
- title: annotation.url_citation.title,
3476
+ title: (_d = annotation.url_citation.title) != null ? _d : "",
3462
3477
  providerMetadata: {
3463
3478
  openrouter: {
3464
- content: annotation.url_citation.content || ""
3479
+ content: (_e = annotation.url_citation.content) != null ? _e : "",
3480
+ startIndex: (_f = annotation.url_citation.start_index) != null ? _f : 0,
3481
+ endIndex: (_g = annotation.url_citation.end_index) != null ? _g : 0
3465
3482
  }
3466
3483
  }
3467
3484
  });
@@ -3477,7 +3494,7 @@ var OpenRouterChatLanguageModel = class {
3477
3494
  }
3478
3495
  if (delta.tool_calls != null) {
3479
3496
  for (const toolCallDelta of delta.tool_calls) {
3480
- const index = (_d = toolCallDelta.index) != null ? _d : toolCalls.length - 1;
3497
+ const index = (_h = toolCallDelta.index) != null ? _h : toolCalls.length - 1;
3481
3498
  if (toolCalls[index] == null) {
3482
3499
  if (toolCallDelta.type !== "function") {
3483
3500
  throw new InvalidResponseDataError({
@@ -3491,7 +3508,7 @@ var OpenRouterChatLanguageModel = class {
3491
3508
  message: `Expected 'id' to be a string.`
3492
3509
  });
3493
3510
  }
3494
- if (((_e = toolCallDelta.function) == null ? void 0 : _e.name) == null) {
3511
+ if (((_i = toolCallDelta.function) == null ? void 0 : _i.name) == null) {
3495
3512
  throw new InvalidResponseDataError({
3496
3513
  data: toolCallDelta,
3497
3514
  message: `Expected 'function.name' to be a string.`
@@ -3502,7 +3519,7 @@ var OpenRouterChatLanguageModel = class {
3502
3519
  type: "function",
3503
3520
  function: {
3504
3521
  name: toolCallDelta.function.name,
3505
- arguments: (_f = toolCallDelta.function.arguments) != null ? _f : ""
3522
+ arguments: (_j = toolCallDelta.function.arguments) != null ? _j : ""
3506
3523
  },
3507
3524
  inputStarted: false,
3508
3525
  sent: false
@@ -3514,7 +3531,7 @@ var OpenRouterChatLanguageModel = class {
3514
3531
  message: `Tool call at index ${index} is missing after creation.`
3515
3532
  });
3516
3533
  }
3517
- if (((_g = toolCall2.function) == null ? void 0 : _g.name) != null && ((_h = toolCall2.function) == null ? void 0 : _h.arguments) != null && isParsableJson(toolCall2.function.arguments)) {
3534
+ if (((_k = toolCall2.function) == null ? void 0 : _k.name) != null && ((_l = toolCall2.function) == null ? void 0 : _l.arguments) != null && isParsableJson(toolCall2.function.arguments)) {
3518
3535
  toolCall2.inputStarted = true;
3519
3536
  controller.enqueue({
3520
3537
  type: "tool-input-start",
@@ -3565,18 +3582,18 @@ var OpenRouterChatLanguageModel = class {
3565
3582
  toolName: toolCall.function.name
3566
3583
  });
3567
3584
  }
3568
- if (((_i = toolCallDelta.function) == null ? void 0 : _i.arguments) != null) {
3569
- toolCall.function.arguments += (_k = (_j = toolCallDelta.function) == null ? void 0 : _j.arguments) != null ? _k : "";
3585
+ if (((_m = toolCallDelta.function) == null ? void 0 : _m.arguments) != null) {
3586
+ toolCall.function.arguments += (_o = (_n = toolCallDelta.function) == null ? void 0 : _n.arguments) != null ? _o : "";
3570
3587
  }
3571
3588
  controller.enqueue({
3572
3589
  type: "tool-input-delta",
3573
3590
  id: toolCall.id,
3574
- delta: (_l = toolCallDelta.function.arguments) != null ? _l : ""
3591
+ delta: (_p = toolCallDelta.function.arguments) != null ? _p : ""
3575
3592
  });
3576
- if (((_m = toolCall.function) == null ? void 0 : _m.name) != null && ((_n = toolCall.function) == null ? void 0 : _n.arguments) != null && isParsableJson(toolCall.function.arguments)) {
3593
+ if (((_q = toolCall.function) == null ? void 0 : _q.name) != null && ((_r = toolCall.function) == null ? void 0 : _r.arguments) != null && isParsableJson(toolCall.function.arguments)) {
3577
3594
  controller.enqueue({
3578
3595
  type: "tool-call",
3579
- toolCallId: (_o = toolCall.id) != null ? _o : generateId(),
3596
+ toolCallId: (_s = toolCall.id) != null ? _s : generateId(),
3580
3597
  toolName: toolCall.function.name,
3581
3598
  input: toolCall.function.arguments,
3582
3599
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
@@ -3653,6 +3670,7 @@ var OpenRouterChatLanguageModel = class {
3653
3670
  if (accumulatedFileAnnotations.length > 0) {
3654
3671
  openrouterMetadata.annotations = accumulatedFileAnnotations;
3655
3672
  }
3673
+ usage.raw = rawUsage;
3656
3674
  controller.enqueue({
3657
3675
  type: "finish",
3658
3676
  finishReason,
@@ -3780,6 +3798,7 @@ var OpenRouterCompletionChunkSchema = import_v47.z.union([
3780
3798
  import_v47.z.object({
3781
3799
  id: import_v47.z.string().optional(),
3782
3800
  model: import_v47.z.string().optional(),
3801
+ provider: import_v47.z.string().optional(),
3783
3802
  choices: import_v47.z.array(
3784
3803
  import_v47.z.object({
3785
3804
  text: import_v47.z.string(),
@@ -3887,7 +3906,7 @@ var OpenRouterCompletionLanguageModel = class {
3887
3906
  }, this.config.extraBody), this.settings.extraBody);
3888
3907
  }
3889
3908
  async doGenerate(options) {
3890
- var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3909
+ var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
3891
3910
  const providerOptions = options.providerOptions || {};
3892
3911
  const openrouterOptions = providerOptions.openrouter || {};
3893
3912
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3944,9 +3963,32 @@ var OpenRouterCompletionLanguageModel = class {
3944
3963
  total: (_h = (_g = response.usage) == null ? void 0 : _g.completion_tokens) != null ? _h : 0,
3945
3964
  text: void 0,
3946
3965
  reasoning: (_k = (_j = (_i = response.usage) == null ? void 0 : _i.completion_tokens_details) == null ? void 0 : _j.reasoning_tokens) != null ? _k : void 0
3947
- }
3966
+ },
3967
+ raw: (_l = response.usage) != null ? _l : void 0
3948
3968
  },
3949
3969
  warnings: [],
3970
+ providerMetadata: {
3971
+ openrouter: OpenRouterProviderMetadataSchema.parse({
3972
+ provider: (_m = response.provider) != null ? _m : "",
3973
+ usage: __spreadValues(__spreadValues(__spreadValues(__spreadValues({
3974
+ promptTokens: (_o = (_n = response.usage) == null ? void 0 : _n.prompt_tokens) != null ? _o : 0,
3975
+ completionTokens: (_q = (_p = response.usage) == null ? void 0 : _p.completion_tokens) != null ? _q : 0,
3976
+ totalTokens: ((_s = (_r = response.usage) == null ? void 0 : _r.prompt_tokens) != null ? _s : 0) + ((_u = (_t = response.usage) == null ? void 0 : _t.completion_tokens) != null ? _u : 0)
3977
+ }, ((_v = response.usage) == null ? void 0 : _v.cost) != null ? { cost: response.usage.cost } : {}), ((_x = (_w = response.usage) == null ? void 0 : _w.prompt_tokens_details) == null ? void 0 : _x.cached_tokens) != null ? {
3978
+ promptTokensDetails: {
3979
+ cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3980
+ }
3981
+ } : {}), ((_z = (_y = response.usage) == null ? void 0 : _y.completion_tokens_details) == null ? void 0 : _z.reasoning_tokens) != null ? {
3982
+ completionTokensDetails: {
3983
+ reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3984
+ }
3985
+ } : {}), ((_B = (_A = response.usage) == null ? void 0 : _A.cost_details) == null ? void 0 : _B.upstream_inference_cost) != null ? {
3986
+ costDetails: {
3987
+ upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3988
+ }
3989
+ } : {})
3990
+ })
3991
+ },
3950
3992
  response: {
3951
3993
  headers: responseHeaders
3952
3994
  }
@@ -3986,14 +4028,20 @@ var OpenRouterCompletionLanguageModel = class {
3986
4028
  total: void 0,
3987
4029
  text: void 0,
3988
4030
  reasoning: void 0
3989
- }
4031
+ },
4032
+ raw: void 0
3990
4033
  };
3991
4034
  const openrouterUsage = {};
4035
+ let provider;
4036
+ let rawUsage;
3992
4037
  return {
3993
4038
  stream: response.pipeThrough(
3994
4039
  new TransformStream({
3995
4040
  transform(chunk, controller) {
3996
4041
  var _a16, _b16, _c;
4042
+ if (options.includeRawChunks) {
4043
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
4044
+ }
3997
4045
  if (!chunk.success) {
3998
4046
  finishReason = createFinishReason("error");
3999
4047
  controller.enqueue({ type: "error", error: chunk.error });
@@ -4005,9 +4053,13 @@ var OpenRouterCompletionLanguageModel = class {
4005
4053
  controller.enqueue({ type: "error", error: value.error });
4006
4054
  return;
4007
4055
  }
4056
+ if (value.provider) {
4057
+ provider = value.provider;
4058
+ }
4008
4059
  if (value.usage != null) {
4009
4060
  usage.inputTokens.total = value.usage.prompt_tokens;
4010
4061
  usage.outputTokens.total = value.usage.completion_tokens;
4062
+ rawUsage = value.usage;
4011
4063
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
4012
4064
  if (value.usage.prompt_tokens_details) {
4013
4065
  const cachedInputTokens = (_a16 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a16 : 0;
@@ -4024,7 +4076,9 @@ var OpenRouterCompletionLanguageModel = class {
4024
4076
  reasoningTokens
4025
4077
  };
4026
4078
  }
4027
- openrouterUsage.cost = value.usage.cost;
4079
+ if (value.usage.cost != null) {
4080
+ openrouterUsage.cost = value.usage.cost;
4081
+ }
4028
4082
  openrouterUsage.totalTokens = value.usage.total_tokens;
4029
4083
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
4030
4084
  if (upstreamInferenceCost != null) {
@@ -4046,14 +4100,19 @@ var OpenRouterCompletionLanguageModel = class {
4046
4100
  }
4047
4101
  },
4048
4102
  flush(controller) {
4103
+ usage.raw = rawUsage;
4104
+ const openrouterMetadata = {
4105
+ usage: openrouterUsage
4106
+ };
4107
+ if (provider !== void 0) {
4108
+ openrouterMetadata.provider = provider;
4109
+ }
4049
4110
  controller.enqueue({
4050
4111
  type: "finish",
4051
4112
  finishReason,
4052
4113
  usage,
4053
4114
  providerMetadata: {
4054
- openrouter: {
4055
- usage: openrouterUsage
4056
- }
4115
+ openrouter: openrouterMetadata
4057
4116
  }
4058
4117
  });
4059
4118
  }
@@ -4083,6 +4142,7 @@ var OpenRouterEmbeddingResponseSchema = import_v48.z.object({
4083
4142
  object: import_v48.z.literal("list"),
4084
4143
  data: import_v48.z.array(openrouterEmbeddingDataSchema),
4085
4144
  model: import_v48.z.string(),
4145
+ provider: import_v48.z.string().optional(),
4086
4146
  usage: openrouterEmbeddingUsageSchema.optional()
4087
4147
  });
4088
4148
 
@@ -4098,7 +4158,7 @@ var OpenRouterEmbeddingModel = class {
4098
4158
  this.config = config;
4099
4159
  }
4100
4160
  async doEmbed(options) {
4101
- var _a16;
4161
+ var _a16, _b16, _c, _d, _e, _f;
4102
4162
  const { values, abortSignal, headers } = options;
4103
4163
  const args = __spreadValues(__spreadValues({
4104
4164
  model: this.modelId,
@@ -4123,13 +4183,16 @@ var OpenRouterEmbeddingModel = class {
4123
4183
  return {
4124
4184
  embeddings: responseValue.data.map((item) => item.embedding),
4125
4185
  usage: responseValue.usage ? { tokens: responseValue.usage.prompt_tokens } : void 0,
4126
- providerMetadata: ((_a16 = responseValue.usage) == null ? void 0 : _a16.cost) ? {
4127
- openrouter: {
4128
- usage: {
4129
- cost: responseValue.usage.cost
4130
- }
4131
- }
4132
- } : void 0,
4186
+ providerMetadata: {
4187
+ openrouter: OpenRouterProviderMetadataSchema.parse({
4188
+ provider: (_a16 = responseValue.provider) != null ? _a16 : "",
4189
+ usage: __spreadValues({
4190
+ promptTokens: (_c = (_b16 = responseValue.usage) == null ? void 0 : _b16.prompt_tokens) != null ? _c : 0,
4191
+ completionTokens: 0,
4192
+ totalTokens: (_e = (_d = responseValue.usage) == null ? void 0 : _d.total_tokens) != null ? _e : 0
4193
+ }, ((_f = responseValue.usage) == null ? void 0 : _f.cost) != null ? { cost: responseValue.usage.cost } : {})
4194
+ })
4195
+ },
4133
4196
  response: {
4134
4197
  headers: responseHeaders,
4135
4198
  body: responseValue
@@ -4196,27 +4259,188 @@ var OpenRouter = class {
4196
4259
  }
4197
4260
  };
4198
4261
 
4262
+ // src/image/schemas.ts
4263
+ var import_v49 = require("zod/v4");
4264
+ var OpenRouterImageResponseSchema = import_v49.z.object({
4265
+ id: import_v49.z.string().optional(),
4266
+ object: import_v49.z.string().optional(),
4267
+ created: import_v49.z.number().optional(),
4268
+ model: import_v49.z.string(),
4269
+ choices: import_v49.z.array(
4270
+ import_v49.z.object({
4271
+ index: import_v49.z.number(),
4272
+ message: import_v49.z.object({
4273
+ role: import_v49.z.string(),
4274
+ content: import_v49.z.string().nullable().optional(),
4275
+ images: import_v49.z.array(
4276
+ import_v49.z.object({
4277
+ type: import_v49.z.literal("image_url"),
4278
+ image_url: import_v49.z.object({
4279
+ url: import_v49.z.string()
4280
+ })
4281
+ }).passthrough()
4282
+ ).optional()
4283
+ }).passthrough(),
4284
+ finish_reason: import_v49.z.string().nullable().optional()
4285
+ }).passthrough()
4286
+ ),
4287
+ usage: import_v49.z.object({
4288
+ prompt_tokens: import_v49.z.number(),
4289
+ completion_tokens: import_v49.z.number(),
4290
+ total_tokens: import_v49.z.number()
4291
+ }).passthrough().optional()
4292
+ }).passthrough();
4293
+
4294
+ // src/image/index.ts
4295
+ var OpenRouterImageModel = class {
4296
+ constructor(modelId, settings, config) {
4297
+ this.specificationVersion = "v3";
4298
+ this.provider = "openrouter";
4299
+ this.maxImagesPerCall = 1;
4300
+ this.modelId = modelId;
4301
+ this.settings = settings;
4302
+ this.config = config;
4303
+ }
4304
+ async doGenerate(options) {
4305
+ var _a16;
4306
+ const {
4307
+ prompt,
4308
+ n,
4309
+ size,
4310
+ aspectRatio,
4311
+ seed,
4312
+ files,
4313
+ mask,
4314
+ abortSignal,
4315
+ headers,
4316
+ providerOptions
4317
+ } = options;
4318
+ const openrouterOptions = (providerOptions == null ? void 0 : providerOptions.openrouter) || {};
4319
+ const warnings = [];
4320
+ if (files !== void 0 && files.length > 0) {
4321
+ throw new UnsupportedFunctionalityError({
4322
+ functionality: "image editing (files parameter)"
4323
+ });
4324
+ }
4325
+ if (mask !== void 0) {
4326
+ throw new UnsupportedFunctionalityError({
4327
+ functionality: "image inpainting (mask parameter)"
4328
+ });
4329
+ }
4330
+ if (n > 1) {
4331
+ warnings.push({
4332
+ type: "unsupported",
4333
+ feature: "n > 1",
4334
+ details: `OpenRouter image generation returns 1 image per call. Requested ${n} images.`
4335
+ });
4336
+ }
4337
+ if (size !== void 0) {
4338
+ warnings.push({
4339
+ type: "unsupported",
4340
+ feature: "size",
4341
+ details: "Use aspectRatio instead. Size parameter is not supported by OpenRouter image generation."
4342
+ });
4343
+ }
4344
+ const imageConfig = aspectRatio !== void 0 ? { aspect_ratio: aspectRatio } : void 0;
4345
+ const body = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
4346
+ model: this.modelId,
4347
+ messages: [
4348
+ {
4349
+ role: "user",
4350
+ content: prompt != null ? prompt : ""
4351
+ }
4352
+ ],
4353
+ modalities: ["image", "text"]
4354
+ }, imageConfig !== void 0 && { image_config: imageConfig }), seed !== void 0 && { seed }), this.settings.user !== void 0 && { user: this.settings.user }), this.settings.provider !== void 0 && {
4355
+ provider: this.settings.provider
4356
+ }), this.config.extraBody), this.settings.extraBody), openrouterOptions);
4357
+ const { value: responseValue, responseHeaders } = await postJsonToApi({
4358
+ url: this.config.url({
4359
+ path: "/chat/completions",
4360
+ modelId: this.modelId
4361
+ }),
4362
+ headers: combineHeaders(this.config.headers(), headers),
4363
+ body,
4364
+ failedResponseHandler: openrouterFailedResponseHandler,
4365
+ successfulResponseHandler: createJsonResponseHandler(
4366
+ OpenRouterImageResponseSchema
4367
+ ),
4368
+ abortSignal,
4369
+ fetch: this.config.fetch
4370
+ });
4371
+ const choice = responseValue.choices[0];
4372
+ if (!choice) {
4373
+ throw new NoContentGeneratedError({
4374
+ message: "No choice in response"
4375
+ });
4376
+ }
4377
+ const images = [];
4378
+ if ((_a16 = choice.message) == null ? void 0 : _a16.images) {
4379
+ for (const image of choice.message.images) {
4380
+ const dataUrl = image.image_url.url;
4381
+ images.push(getBase64FromDataUrl(dataUrl));
4382
+ }
4383
+ }
4384
+ const usage = responseValue.usage ? {
4385
+ inputTokens: responseValue.usage.prompt_tokens,
4386
+ outputTokens: responseValue.usage.completion_tokens,
4387
+ totalTokens: responseValue.usage.total_tokens
4388
+ } : void 0;
4389
+ return {
4390
+ images,
4391
+ warnings,
4392
+ response: {
4393
+ timestamp: /* @__PURE__ */ new Date(),
4394
+ modelId: responseValue.model,
4395
+ headers: responseHeaders
4396
+ },
4397
+ usage
4398
+ };
4399
+ }
4400
+ };
4401
+
4199
4402
  // src/utils/remove-undefined.ts
4200
4403
  function removeUndefinedEntries(record) {
4201
4404
  return Object.fromEntries(
4202
- Object.entries(record).filter(([, value]) => value !== null)
4405
+ Object.entries(record).filter(([, value]) => value != null)
4203
4406
  );
4204
4407
  }
4205
4408
 
4206
4409
  // src/utils/with-user-agent-suffix.ts
4410
+ function normalizeHeaders2(headers) {
4411
+ if (!headers) {
4412
+ return {};
4413
+ }
4414
+ if (headers instanceof Headers) {
4415
+ return Object.fromEntries(headers.entries());
4416
+ }
4417
+ if (Array.isArray(headers)) {
4418
+ return Object.fromEntries(headers);
4419
+ }
4420
+ return headers;
4421
+ }
4422
+ function findHeaderKey(headers, targetKey) {
4423
+ const lowerTarget = targetKey.toLowerCase();
4424
+ return Object.keys(headers).find((key) => key.toLowerCase() === lowerTarget);
4425
+ }
4207
4426
  function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4208
- const cleanedHeaders = removeUndefinedEntries(
4209
- headers != null ? headers : {}
4427
+ const normalizedHeaders = normalizeHeaders2(headers);
4428
+ const cleanedHeaders = removeUndefinedEntries(normalizedHeaders);
4429
+ const existingUserAgentKey = findHeaderKey(cleanedHeaders, "user-agent");
4430
+ const existingUserAgentValue = existingUserAgentKey ? cleanedHeaders[existingUserAgentKey] : void 0;
4431
+ const userAgent = (existingUserAgentValue == null ? void 0 : existingUserAgentValue.trim()) ? existingUserAgentValue : userAgentSuffixParts.filter(Boolean).join(" ");
4432
+ const headersWithoutUserAgent = Object.fromEntries(
4433
+ Object.entries(cleanedHeaders).filter(
4434
+ ([key]) => key.toLowerCase() !== "user-agent"
4435
+ )
4210
4436
  );
4211
- const currentUserAgentHeader = cleanedHeaders["user-agent"] || "";
4212
- const newUserAgent = [currentUserAgentHeader, ...userAgentSuffixParts].filter(Boolean).join(" ");
4213
- return __spreadProps(__spreadValues({}, cleanedHeaders), {
4214
- "user-agent": newUserAgent
4437
+ return __spreadProps(__spreadValues({}, headersWithoutUserAgent), {
4438
+ "user-agent": userAgent
4215
4439
  });
4216
4440
  }
4217
4441
 
4218
4442
  // src/version.ts
4219
- var VERSION2 = false ? "0.0.0-test" : "2.0.2";
4443
+ var VERSION2 = false ? "0.0.0-test" : "2.1.0";
4220
4444
 
4221
4445
  // src/provider.ts
4222
4446
  function createOpenRouter(options = {}) {
@@ -4258,6 +4482,13 @@ function createOpenRouter(options = {}) {
4258
4482
  fetch: options.fetch,
4259
4483
  extraBody: options.extraBody
4260
4484
  });
4485
+ const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
4486
+ provider: "openrouter.image",
4487
+ url: ({ path }) => `${baseURL}${path}`,
4488
+ headers: getHeaders,
4489
+ fetch: options.fetch,
4490
+ extraBody: options.extraBody
4491
+ });
4261
4492
  const createLanguageModel = (modelId, settings) => {
4262
4493
  if (new.target) {
4263
4494
  throw new Error(
@@ -4278,6 +4509,7 @@ function createOpenRouter(options = {}) {
4278
4509
  provider.completion = createCompletionModel;
4279
4510
  provider.textEmbeddingModel = createEmbeddingModel;
4280
4511
  provider.embedding = createEmbeddingModel;
4512
+ provider.imageModel = createImageModel;
4281
4513
  return provider;
4282
4514
  }
4283
4515
  var openrouter = createOpenRouter({