@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.mjs CHANGED
@@ -2445,7 +2445,7 @@ function getCacheControl(providerMetadata) {
2445
2445
  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;
2446
2446
  }
2447
2447
  function convertToOpenRouterChatMessages(prompt) {
2448
- var _a16, _b16, _c, _d, _e, _f, _g;
2448
+ var _a16, _b16, _c, _d, _e, _f, _g, _h;
2449
2449
  const messages = [];
2450
2450
  for (const { role, content, providerOptions } of prompt) {
2451
2451
  switch (role) {
@@ -2474,42 +2474,46 @@ function convertToOpenRouterChatMessages(prompt) {
2474
2474
  break;
2475
2475
  }
2476
2476
  const messageCacheControl = getCacheControl(providerOptions);
2477
+ let lastTextPartIndex = -1;
2478
+ for (let i = content.length - 1; i >= 0; i--) {
2479
+ if (((_c = content[i]) == null ? void 0 : _c.type) === "text") {
2480
+ lastTextPartIndex = i;
2481
+ break;
2482
+ }
2483
+ }
2477
2484
  const contentParts = content.map(
2478
- (part) => {
2479
- var _a17, _b17, _c2, _d2, _e2, _f2, _g2;
2480
- const cacheControl = (_a17 = getCacheControl(part.providerOptions)) != null ? _a17 : messageCacheControl;
2485
+ (part, index) => {
2486
+ var _a17, _b17, _c2, _d2, _e2, _f2;
2487
+ const isLastTextPart = part.type === "text" && index === lastTextPartIndex;
2488
+ const partCacheControl = getCacheControl(part.providerOptions);
2489
+ const cacheControl = part.type === "text" ? partCacheControl != null ? partCacheControl : isLastTextPart ? messageCacheControl : void 0 : partCacheControl;
2481
2490
  switch (part.type) {
2482
2491
  case "text":
2483
- return {
2492
+ return __spreadValues({
2484
2493
  type: "text",
2485
- text: part.text,
2486
- // For text parts, only use part-specific cache control
2487
- cache_control: cacheControl
2488
- };
2494
+ text: part.text
2495
+ }, cacheControl && { cache_control: cacheControl });
2489
2496
  case "file": {
2490
- if ((_b17 = part.mediaType) == null ? void 0 : _b17.startsWith("image/")) {
2497
+ if ((_a17 = part.mediaType) == null ? void 0 : _a17.startsWith("image/")) {
2491
2498
  const url = getFileUrl({
2492
2499
  part,
2493
2500
  defaultMediaType: "image/jpeg"
2494
2501
  });
2495
- return {
2502
+ return __spreadValues({
2496
2503
  type: "image_url",
2497
2504
  image_url: {
2498
2505
  url
2499
- },
2500
- // For image parts, use part-specific or message-level cache control
2501
- cache_control: cacheControl
2502
- };
2506
+ }
2507
+ }, cacheControl && { cache_control: cacheControl });
2503
2508
  }
2504
- if ((_c2 = part.mediaType) == null ? void 0 : _c2.startsWith("audio/")) {
2505
- return {
2509
+ if ((_b17 = part.mediaType) == null ? void 0 : _b17.startsWith("audio/")) {
2510
+ return __spreadValues({
2506
2511
  type: "input_audio",
2507
- input_audio: getInputAudioData(part),
2508
- cache_control: cacheControl
2509
- };
2512
+ input_audio: getInputAudioData(part)
2513
+ }, cacheControl && { cache_control: cacheControl });
2510
2514
  }
2511
2515
  const fileName = String(
2512
- (_g2 = (_f2 = (_e2 = (_d2 = part.providerOptions) == null ? void 0 : _d2.openrouter) == null ? void 0 : _e2.filename) != null ? _f2 : part.filename) != null ? _g2 : ""
2516
+ (_f2 = (_e2 = (_d2 = (_c2 = part.providerOptions) == null ? void 0 : _c2.openrouter) == null ? void 0 : _d2.filename) != null ? _e2 : part.filename) != null ? _f2 : ""
2513
2517
  );
2514
2518
  const fileData = getFileUrl({
2515
2519
  part,
@@ -2527,21 +2531,19 @@ function convertToOpenRouterChatMessages(prompt) {
2527
2531
  }
2528
2532
  };
2529
2533
  }
2530
- return {
2534
+ return __spreadValues({
2531
2535
  type: "file",
2532
2536
  file: {
2533
2537
  filename: fileName,
2534
2538
  file_data: fileData
2535
- },
2536
- cache_control: cacheControl
2537
- };
2539
+ }
2540
+ }, cacheControl && { cache_control: cacheControl });
2538
2541
  }
2539
2542
  default: {
2540
- return {
2543
+ return __spreadValues({
2541
2544
  type: "text",
2542
- text: "",
2543
- cache_control: cacheControl
2544
- };
2545
+ text: ""
2546
+ }, cacheControl && { cache_control: cacheControl });
2545
2547
  }
2546
2548
  }
2547
2549
  }
@@ -2585,8 +2587,8 @@ function convertToOpenRouterChatMessages(prompt) {
2585
2587
  }
2586
2588
  }
2587
2589
  const parsedProviderOptions = OpenRouterProviderOptionsSchema.safeParse(providerOptions);
2588
- const messageReasoningDetails = parsedProviderOptions.success ? (_d = (_c = parsedProviderOptions.data) == null ? void 0 : _c.openrouter) == null ? void 0 : _d.reasoning_details : void 0;
2589
- const messageAnnotations = parsedProviderOptions.success ? (_f = (_e = parsedProviderOptions.data) == null ? void 0 : _e.openrouter) == null ? void 0 : _f.annotations : void 0;
2590
+ const messageReasoningDetails = parsedProviderOptions.success ? (_e = (_d = parsedProviderOptions.data) == null ? void 0 : _d.openrouter) == null ? void 0 : _e.reasoning_details : void 0;
2591
+ const messageAnnotations = parsedProviderOptions.success ? (_g = (_f = parsedProviderOptions.data) == null ? void 0 : _f.openrouter) == null ? void 0 : _g.annotations : void 0;
2590
2592
  const finalReasoningDetails = messageReasoningDetails && Array.isArray(messageReasoningDetails) && messageReasoningDetails.length > 0 ? messageReasoningDetails : findFirstReasoningDetails(content);
2591
2593
  messages.push({
2592
2594
  role: "assistant",
@@ -2609,7 +2611,7 @@ function convertToOpenRouterChatMessages(prompt) {
2609
2611
  role: "tool",
2610
2612
  tool_call_id: toolResponse.toolCallId,
2611
2613
  content: content2,
2612
- cache_control: (_g = getCacheControl(providerOptions)) != null ? _g : getCacheControl(toolResponse.providerOptions)
2614
+ cache_control: (_h = getCacheControl(providerOptions)) != null ? _h : getCacheControl(toolResponse.providerOptions)
2613
2615
  });
2614
2616
  }
2615
2617
  break;
@@ -2749,20 +2751,21 @@ var OpenRouterNonStreamChatCompletionResponseSchema = z7.union([
2749
2751
  type: z7.literal("function"),
2750
2752
  function: z7.object({
2751
2753
  name: z7.string(),
2752
- arguments: z7.string()
2754
+ arguments: z7.string().optional()
2753
2755
  }).passthrough()
2754
2756
  }).passthrough()
2755
2757
  ).optional(),
2756
2758
  annotations: z7.array(
2757
2759
  z7.union([
2758
2760
  // URL citation from web search
2761
+ // title, start_index, end_index are optional as some upstream providers may omit them
2759
2762
  z7.object({
2760
2763
  type: z7.literal("url_citation"),
2761
2764
  url_citation: z7.object({
2762
- end_index: z7.number(),
2763
- start_index: z7.number(),
2764
- title: z7.string(),
2765
2765
  url: z7.string(),
2766
+ title: z7.string().optional(),
2767
+ start_index: z7.number().optional(),
2768
+ end_index: z7.number().optional(),
2766
2769
  content: z7.string().optional()
2767
2770
  }).passthrough()
2768
2771
  }).passthrough(),
@@ -2839,13 +2842,14 @@ var OpenRouterStreamChatCompletionChunkSchema = z7.union([
2839
2842
  annotations: z7.array(
2840
2843
  z7.union([
2841
2844
  // URL citation from web search
2845
+ // title, start_index, end_index are optional as some upstream providers may omit them
2842
2846
  z7.object({
2843
2847
  type: z7.literal("url_citation"),
2844
2848
  url_citation: z7.object({
2845
- end_index: z7.number(),
2846
- start_index: z7.number(),
2847
- title: z7.string(),
2848
2849
  url: z7.string(),
2850
+ title: z7.string().optional(),
2851
+ start_index: z7.number().optional(),
2852
+ end_index: z7.number().optional(),
2849
2853
  content: z7.string().optional()
2850
2854
  }).passthrough()
2851
2855
  }).passthrough(),
@@ -2992,7 +2996,7 @@ var OpenRouterChatLanguageModel = class {
2992
2996
  return baseArgs;
2993
2997
  }
2994
2998
  async doGenerate(options) {
2995
- var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
2999
+ 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;
2996
3000
  const providerOptions = options.providerOptions || {};
2997
3001
  const openrouterOptions = providerOptions.openrouter || {};
2998
3002
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3042,7 +3046,8 @@ var OpenRouterChatLanguageModel = class {
3042
3046
  total: (_d = response.usage.completion_tokens) != null ? _d : 0,
3043
3047
  text: void 0,
3044
3048
  reasoning: (_f = (_e = response.usage.completion_tokens_details) == null ? void 0 : _e.reasoning_tokens) != null ? _f : void 0
3045
- }
3049
+ },
3050
+ raw: response.usage
3046
3051
  } : {
3047
3052
  inputTokens: {
3048
3053
  total: 0,
@@ -3054,7 +3059,8 @@ var OpenRouterChatLanguageModel = class {
3054
3059
  total: 0,
3055
3060
  text: void 0,
3056
3061
  reasoning: void 0
3057
- }
3062
+ },
3063
+ raw: void 0
3058
3064
  };
3059
3065
  const reasoningDetails = (_g = choice.message.reasoning_details) != null ? _g : [];
3060
3066
  const reasoning = reasoningDetails.length > 0 ? reasoningDetails.map((detail) => {
@@ -3127,7 +3133,7 @@ var OpenRouterChatLanguageModel = class {
3127
3133
  type: "tool-call",
3128
3134
  toolCallId: (_h = toolCall.id) != null ? _h : generateId(),
3129
3135
  toolName: toolCall.function.name,
3130
- input: toolCall.function.arguments,
3136
+ input: (_i = toolCall.function.arguments) != null ? _i : "{}",
3131
3137
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
3132
3138
  openrouter: {
3133
3139
  reasoning_details: reasoningDetails
@@ -3154,17 +3160,19 @@ var OpenRouterChatLanguageModel = class {
3154
3160
  sourceType: "url",
3155
3161
  id: annotation.url_citation.url,
3156
3162
  url: annotation.url_citation.url,
3157
- title: annotation.url_citation.title,
3163
+ title: (_j = annotation.url_citation.title) != null ? _j : "",
3158
3164
  providerMetadata: {
3159
3165
  openrouter: {
3160
- content: annotation.url_citation.content || ""
3166
+ content: (_k = annotation.url_citation.content) != null ? _k : "",
3167
+ startIndex: (_l = annotation.url_citation.start_index) != null ? _l : 0,
3168
+ endIndex: (_m = annotation.url_citation.end_index) != null ? _m : 0
3161
3169
  }
3162
3170
  }
3163
3171
  });
3164
3172
  }
3165
3173
  }
3166
3174
  }
3167
- const fileAnnotations = (_i = choice.message.annotations) == null ? void 0 : _i.filter(
3175
+ const fileAnnotations = (_n = choice.message.annotations) == null ? void 0 : _n.filter(
3168
3176
  (a) => a.type === "file"
3169
3177
  );
3170
3178
  const hasToolCalls = choice.message.tool_calls && choice.message.tool_calls.length > 0;
@@ -3172,7 +3180,7 @@ var OpenRouterChatLanguageModel = class {
3172
3180
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3173
3181
  );
3174
3182
  const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
3175
- const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3183
+ const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_o = choice.finish_reason) != null ? _o : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3176
3184
  return {
3177
3185
  content,
3178
3186
  finishReason: effectiveFinishReason,
@@ -3180,23 +3188,22 @@ var OpenRouterChatLanguageModel = class {
3180
3188
  warnings: [],
3181
3189
  providerMetadata: {
3182
3190
  openrouter: OpenRouterProviderMetadataSchema.parse({
3183
- provider: (_k = response.provider) != null ? _k : "",
3184
- reasoning_details: (_l = choice.message.reasoning_details) != null ? _l : [],
3191
+ provider: (_p = response.provider) != null ? _p : "",
3192
+ reasoning_details: (_q = choice.message.reasoning_details) != null ? _q : [],
3185
3193
  annotations: fileAnnotations && fileAnnotations.length > 0 ? fileAnnotations : void 0,
3186
- usage: __spreadValues(__spreadValues(__spreadValues({
3187
- promptTokens: (_m = usageInfo.inputTokens.total) != null ? _m : 0,
3188
- completionTokens: (_n = usageInfo.outputTokens.total) != null ? _n : 0,
3189
- totalTokens: ((_o = usageInfo.inputTokens.total) != null ? _o : 0) + ((_p = usageInfo.outputTokens.total) != null ? _p : 0),
3190
- cost: (_q = response.usage) == null ? void 0 : _q.cost
3191
- }, ((_s = (_r = response.usage) == null ? void 0 : _r.prompt_tokens_details) == null ? void 0 : _s.cached_tokens) != null ? {
3194
+ usage: __spreadValues(__spreadValues(__spreadValues(__spreadValues({
3195
+ promptTokens: (_r = usageInfo.inputTokens.total) != null ? _r : 0,
3196
+ completionTokens: (_s = usageInfo.outputTokens.total) != null ? _s : 0,
3197
+ totalTokens: ((_t = usageInfo.inputTokens.total) != null ? _t : 0) + ((_u = usageInfo.outputTokens.total) != null ? _u : 0)
3198
+ }, ((_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 ? {
3192
3199
  promptTokensDetails: {
3193
3200
  cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3194
3201
  }
3195
- } : {}), ((_u = (_t = response.usage) == null ? void 0 : _t.completion_tokens_details) == null ? void 0 : _u.reasoning_tokens) != null ? {
3202
+ } : {}), ((_z = (_y = response.usage) == null ? void 0 : _y.completion_tokens_details) == null ? void 0 : _z.reasoning_tokens) != null ? {
3196
3203
  completionTokensDetails: {
3197
3204
  reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3198
3205
  }
3199
- } : {}), ((_w = (_v = response.usage) == null ? void 0 : _v.cost_details) == null ? void 0 : _w.upstream_inference_cost) != null ? {
3206
+ } : {}), ((_B = (_A = response.usage) == null ? void 0 : _A.cost_details) == null ? void 0 : _B.upstream_inference_cost) != null ? {
3200
3207
  costDetails: {
3201
3208
  upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3202
3209
  }
@@ -3249,9 +3256,11 @@ var OpenRouterChatLanguageModel = class {
3249
3256
  total: void 0,
3250
3257
  text: void 0,
3251
3258
  reasoning: void 0
3252
- }
3259
+ },
3260
+ raw: void 0
3253
3261
  };
3254
3262
  const openrouterUsage = {};
3263
+ let rawUsage;
3255
3264
  const accumulatedReasoningDetails = [];
3256
3265
  let reasoningDetailsAttachedToToolCall = false;
3257
3266
  const accumulatedFileAnnotations = [];
@@ -3265,7 +3274,10 @@ var OpenRouterChatLanguageModel = class {
3265
3274
  stream: response.pipeThrough(
3266
3275
  new TransformStream({
3267
3276
  transform(chunk, controller) {
3268
- var _a17, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
3277
+ var _a17, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
3278
+ if (options.includeRawChunks) {
3279
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
3280
+ }
3269
3281
  if (!chunk.success) {
3270
3282
  finishReason = createFinishReason("error");
3271
3283
  controller.enqueue({ type: "error", error: chunk.error });
@@ -3296,6 +3308,7 @@ var OpenRouterChatLanguageModel = class {
3296
3308
  if (value.usage != null) {
3297
3309
  usage.inputTokens.total = value.usage.prompt_tokens;
3298
3310
  usage.outputTokens.total = value.usage.completion_tokens;
3311
+ rawUsage = value.usage;
3299
3312
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
3300
3313
  if (value.usage.prompt_tokens_details) {
3301
3314
  const cachedInputTokens = (_a17 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a17 : 0;
@@ -3312,7 +3325,9 @@ var OpenRouterChatLanguageModel = class {
3312
3325
  reasoningTokens
3313
3326
  };
3314
3327
  }
3315
- openrouterUsage.cost = value.usage.cost;
3328
+ if (value.usage.cost != null) {
3329
+ openrouterUsage.cost = value.usage.cost;
3330
+ }
3316
3331
  openrouterUsage.totalTokens = value.usage.total_tokens;
3317
3332
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
3318
3333
  if (upstreamInferenceCost != null) {
@@ -3425,10 +3440,12 @@ var OpenRouterChatLanguageModel = class {
3425
3440
  sourceType: "url",
3426
3441
  id: annotation.url_citation.url,
3427
3442
  url: annotation.url_citation.url,
3428
- title: annotation.url_citation.title,
3443
+ title: (_d = annotation.url_citation.title) != null ? _d : "",
3429
3444
  providerMetadata: {
3430
3445
  openrouter: {
3431
- content: annotation.url_citation.content || ""
3446
+ content: (_e = annotation.url_citation.content) != null ? _e : "",
3447
+ startIndex: (_f = annotation.url_citation.start_index) != null ? _f : 0,
3448
+ endIndex: (_g = annotation.url_citation.end_index) != null ? _g : 0
3432
3449
  }
3433
3450
  }
3434
3451
  });
@@ -3444,7 +3461,7 @@ var OpenRouterChatLanguageModel = class {
3444
3461
  }
3445
3462
  if (delta.tool_calls != null) {
3446
3463
  for (const toolCallDelta of delta.tool_calls) {
3447
- const index = (_d = toolCallDelta.index) != null ? _d : toolCalls.length - 1;
3464
+ const index = (_h = toolCallDelta.index) != null ? _h : toolCalls.length - 1;
3448
3465
  if (toolCalls[index] == null) {
3449
3466
  if (toolCallDelta.type !== "function") {
3450
3467
  throw new InvalidResponseDataError({
@@ -3458,7 +3475,7 @@ var OpenRouterChatLanguageModel = class {
3458
3475
  message: `Expected 'id' to be a string.`
3459
3476
  });
3460
3477
  }
3461
- if (((_e = toolCallDelta.function) == null ? void 0 : _e.name) == null) {
3478
+ if (((_i = toolCallDelta.function) == null ? void 0 : _i.name) == null) {
3462
3479
  throw new InvalidResponseDataError({
3463
3480
  data: toolCallDelta,
3464
3481
  message: `Expected 'function.name' to be a string.`
@@ -3469,7 +3486,7 @@ var OpenRouterChatLanguageModel = class {
3469
3486
  type: "function",
3470
3487
  function: {
3471
3488
  name: toolCallDelta.function.name,
3472
- arguments: (_f = toolCallDelta.function.arguments) != null ? _f : ""
3489
+ arguments: (_j = toolCallDelta.function.arguments) != null ? _j : ""
3473
3490
  },
3474
3491
  inputStarted: false,
3475
3492
  sent: false
@@ -3481,7 +3498,7 @@ var OpenRouterChatLanguageModel = class {
3481
3498
  message: `Tool call at index ${index} is missing after creation.`
3482
3499
  });
3483
3500
  }
3484
- if (((_g = toolCall2.function) == null ? void 0 : _g.name) != null && ((_h = toolCall2.function) == null ? void 0 : _h.arguments) != null && isParsableJson(toolCall2.function.arguments)) {
3501
+ if (((_k = toolCall2.function) == null ? void 0 : _k.name) != null && ((_l = toolCall2.function) == null ? void 0 : _l.arguments) != null && isParsableJson(toolCall2.function.arguments)) {
3485
3502
  toolCall2.inputStarted = true;
3486
3503
  controller.enqueue({
3487
3504
  type: "tool-input-start",
@@ -3532,18 +3549,18 @@ var OpenRouterChatLanguageModel = class {
3532
3549
  toolName: toolCall.function.name
3533
3550
  });
3534
3551
  }
3535
- if (((_i = toolCallDelta.function) == null ? void 0 : _i.arguments) != null) {
3536
- toolCall.function.arguments += (_k = (_j = toolCallDelta.function) == null ? void 0 : _j.arguments) != null ? _k : "";
3552
+ if (((_m = toolCallDelta.function) == null ? void 0 : _m.arguments) != null) {
3553
+ toolCall.function.arguments += (_o = (_n = toolCallDelta.function) == null ? void 0 : _n.arguments) != null ? _o : "";
3537
3554
  }
3538
3555
  controller.enqueue({
3539
3556
  type: "tool-input-delta",
3540
3557
  id: toolCall.id,
3541
- delta: (_l = toolCallDelta.function.arguments) != null ? _l : ""
3558
+ delta: (_p = toolCallDelta.function.arguments) != null ? _p : ""
3542
3559
  });
3543
- if (((_m = toolCall.function) == null ? void 0 : _m.name) != null && ((_n = toolCall.function) == null ? void 0 : _n.arguments) != null && isParsableJson(toolCall.function.arguments)) {
3560
+ if (((_q = toolCall.function) == null ? void 0 : _q.name) != null && ((_r = toolCall.function) == null ? void 0 : _r.arguments) != null && isParsableJson(toolCall.function.arguments)) {
3544
3561
  controller.enqueue({
3545
3562
  type: "tool-call",
3546
- toolCallId: (_o = toolCall.id) != null ? _o : generateId(),
3563
+ toolCallId: (_s = toolCall.id) != null ? _s : generateId(),
3547
3564
  toolName: toolCall.function.name,
3548
3565
  input: toolCall.function.arguments,
3549
3566
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
@@ -3620,6 +3637,7 @@ var OpenRouterChatLanguageModel = class {
3620
3637
  if (accumulatedFileAnnotations.length > 0) {
3621
3638
  openrouterMetadata.annotations = accumulatedFileAnnotations;
3622
3639
  }
3640
+ usage.raw = rawUsage;
3623
3641
  controller.enqueue({
3624
3642
  type: "finish",
3625
3643
  finishReason,
@@ -3747,6 +3765,7 @@ var OpenRouterCompletionChunkSchema = z8.union([
3747
3765
  z8.object({
3748
3766
  id: z8.string().optional(),
3749
3767
  model: z8.string().optional(),
3768
+ provider: z8.string().optional(),
3750
3769
  choices: z8.array(
3751
3770
  z8.object({
3752
3771
  text: z8.string(),
@@ -3854,7 +3873,7 @@ var OpenRouterCompletionLanguageModel = class {
3854
3873
  }, this.config.extraBody), this.settings.extraBody);
3855
3874
  }
3856
3875
  async doGenerate(options) {
3857
- var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3876
+ 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;
3858
3877
  const providerOptions = options.providerOptions || {};
3859
3878
  const openrouterOptions = providerOptions.openrouter || {};
3860
3879
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3911,9 +3930,32 @@ var OpenRouterCompletionLanguageModel = class {
3911
3930
  total: (_h = (_g = response.usage) == null ? void 0 : _g.completion_tokens) != null ? _h : 0,
3912
3931
  text: void 0,
3913
3932
  reasoning: (_k = (_j = (_i = response.usage) == null ? void 0 : _i.completion_tokens_details) == null ? void 0 : _j.reasoning_tokens) != null ? _k : void 0
3914
- }
3933
+ },
3934
+ raw: (_l = response.usage) != null ? _l : void 0
3915
3935
  },
3916
3936
  warnings: [],
3937
+ providerMetadata: {
3938
+ openrouter: OpenRouterProviderMetadataSchema.parse({
3939
+ provider: (_m = response.provider) != null ? _m : "",
3940
+ usage: __spreadValues(__spreadValues(__spreadValues(__spreadValues({
3941
+ promptTokens: (_o = (_n = response.usage) == null ? void 0 : _n.prompt_tokens) != null ? _o : 0,
3942
+ completionTokens: (_q = (_p = response.usage) == null ? void 0 : _p.completion_tokens) != null ? _q : 0,
3943
+ 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)
3944
+ }, ((_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 ? {
3945
+ promptTokensDetails: {
3946
+ cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3947
+ }
3948
+ } : {}), ((_z = (_y = response.usage) == null ? void 0 : _y.completion_tokens_details) == null ? void 0 : _z.reasoning_tokens) != null ? {
3949
+ completionTokensDetails: {
3950
+ reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3951
+ }
3952
+ } : {}), ((_B = (_A = response.usage) == null ? void 0 : _A.cost_details) == null ? void 0 : _B.upstream_inference_cost) != null ? {
3953
+ costDetails: {
3954
+ upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3955
+ }
3956
+ } : {})
3957
+ })
3958
+ },
3917
3959
  response: {
3918
3960
  headers: responseHeaders
3919
3961
  }
@@ -3953,14 +3995,20 @@ var OpenRouterCompletionLanguageModel = class {
3953
3995
  total: void 0,
3954
3996
  text: void 0,
3955
3997
  reasoning: void 0
3956
- }
3998
+ },
3999
+ raw: void 0
3957
4000
  };
3958
4001
  const openrouterUsage = {};
4002
+ let provider;
4003
+ let rawUsage;
3959
4004
  return {
3960
4005
  stream: response.pipeThrough(
3961
4006
  new TransformStream({
3962
4007
  transform(chunk, controller) {
3963
4008
  var _a16, _b16, _c;
4009
+ if (options.includeRawChunks) {
4010
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
4011
+ }
3964
4012
  if (!chunk.success) {
3965
4013
  finishReason = createFinishReason("error");
3966
4014
  controller.enqueue({ type: "error", error: chunk.error });
@@ -3972,9 +4020,13 @@ var OpenRouterCompletionLanguageModel = class {
3972
4020
  controller.enqueue({ type: "error", error: value.error });
3973
4021
  return;
3974
4022
  }
4023
+ if (value.provider) {
4024
+ provider = value.provider;
4025
+ }
3975
4026
  if (value.usage != null) {
3976
4027
  usage.inputTokens.total = value.usage.prompt_tokens;
3977
4028
  usage.outputTokens.total = value.usage.completion_tokens;
4029
+ rawUsage = value.usage;
3978
4030
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
3979
4031
  if (value.usage.prompt_tokens_details) {
3980
4032
  const cachedInputTokens = (_a16 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a16 : 0;
@@ -3991,7 +4043,9 @@ var OpenRouterCompletionLanguageModel = class {
3991
4043
  reasoningTokens
3992
4044
  };
3993
4045
  }
3994
- openrouterUsage.cost = value.usage.cost;
4046
+ if (value.usage.cost != null) {
4047
+ openrouterUsage.cost = value.usage.cost;
4048
+ }
3995
4049
  openrouterUsage.totalTokens = value.usage.total_tokens;
3996
4050
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
3997
4051
  if (upstreamInferenceCost != null) {
@@ -4013,14 +4067,19 @@ var OpenRouterCompletionLanguageModel = class {
4013
4067
  }
4014
4068
  },
4015
4069
  flush(controller) {
4070
+ usage.raw = rawUsage;
4071
+ const openrouterMetadata = {
4072
+ usage: openrouterUsage
4073
+ };
4074
+ if (provider !== void 0) {
4075
+ openrouterMetadata.provider = provider;
4076
+ }
4016
4077
  controller.enqueue({
4017
4078
  type: "finish",
4018
4079
  finishReason,
4019
4080
  usage,
4020
4081
  providerMetadata: {
4021
- openrouter: {
4022
- usage: openrouterUsage
4023
- }
4082
+ openrouter: openrouterMetadata
4024
4083
  }
4025
4084
  });
4026
4085
  }
@@ -4050,6 +4109,7 @@ var OpenRouterEmbeddingResponseSchema = z9.object({
4050
4109
  object: z9.literal("list"),
4051
4110
  data: z9.array(openrouterEmbeddingDataSchema),
4052
4111
  model: z9.string(),
4112
+ provider: z9.string().optional(),
4053
4113
  usage: openrouterEmbeddingUsageSchema.optional()
4054
4114
  });
4055
4115
 
@@ -4065,7 +4125,7 @@ var OpenRouterEmbeddingModel = class {
4065
4125
  this.config = config;
4066
4126
  }
4067
4127
  async doEmbed(options) {
4068
- var _a16;
4128
+ var _a16, _b16, _c, _d, _e, _f;
4069
4129
  const { values, abortSignal, headers } = options;
4070
4130
  const args = __spreadValues(__spreadValues({
4071
4131
  model: this.modelId,
@@ -4090,13 +4150,16 @@ var OpenRouterEmbeddingModel = class {
4090
4150
  return {
4091
4151
  embeddings: responseValue.data.map((item) => item.embedding),
4092
4152
  usage: responseValue.usage ? { tokens: responseValue.usage.prompt_tokens } : void 0,
4093
- providerMetadata: ((_a16 = responseValue.usage) == null ? void 0 : _a16.cost) ? {
4094
- openrouter: {
4095
- usage: {
4096
- cost: responseValue.usage.cost
4097
- }
4098
- }
4099
- } : void 0,
4153
+ providerMetadata: {
4154
+ openrouter: OpenRouterProviderMetadataSchema.parse({
4155
+ provider: (_a16 = responseValue.provider) != null ? _a16 : "",
4156
+ usage: __spreadValues({
4157
+ promptTokens: (_c = (_b16 = responseValue.usage) == null ? void 0 : _b16.prompt_tokens) != null ? _c : 0,
4158
+ completionTokens: 0,
4159
+ totalTokens: (_e = (_d = responseValue.usage) == null ? void 0 : _d.total_tokens) != null ? _e : 0
4160
+ }, ((_f = responseValue.usage) == null ? void 0 : _f.cost) != null ? { cost: responseValue.usage.cost } : {})
4161
+ })
4162
+ },
4100
4163
  response: {
4101
4164
  headers: responseHeaders,
4102
4165
  body: responseValue
@@ -4163,27 +4226,188 @@ var OpenRouter = class {
4163
4226
  }
4164
4227
  };
4165
4228
 
4229
+ // src/image/schemas.ts
4230
+ import { z as z10 } from "zod/v4";
4231
+ var OpenRouterImageResponseSchema = z10.object({
4232
+ id: z10.string().optional(),
4233
+ object: z10.string().optional(),
4234
+ created: z10.number().optional(),
4235
+ model: z10.string(),
4236
+ choices: z10.array(
4237
+ z10.object({
4238
+ index: z10.number(),
4239
+ message: z10.object({
4240
+ role: z10.string(),
4241
+ content: z10.string().nullable().optional(),
4242
+ images: z10.array(
4243
+ z10.object({
4244
+ type: z10.literal("image_url"),
4245
+ image_url: z10.object({
4246
+ url: z10.string()
4247
+ })
4248
+ }).passthrough()
4249
+ ).optional()
4250
+ }).passthrough(),
4251
+ finish_reason: z10.string().nullable().optional()
4252
+ }).passthrough()
4253
+ ),
4254
+ usage: z10.object({
4255
+ prompt_tokens: z10.number(),
4256
+ completion_tokens: z10.number(),
4257
+ total_tokens: z10.number()
4258
+ }).passthrough().optional()
4259
+ }).passthrough();
4260
+
4261
+ // src/image/index.ts
4262
+ var OpenRouterImageModel = class {
4263
+ constructor(modelId, settings, config) {
4264
+ this.specificationVersion = "v3";
4265
+ this.provider = "openrouter";
4266
+ this.maxImagesPerCall = 1;
4267
+ this.modelId = modelId;
4268
+ this.settings = settings;
4269
+ this.config = config;
4270
+ }
4271
+ async doGenerate(options) {
4272
+ var _a16;
4273
+ const {
4274
+ prompt,
4275
+ n,
4276
+ size,
4277
+ aspectRatio,
4278
+ seed,
4279
+ files,
4280
+ mask,
4281
+ abortSignal,
4282
+ headers,
4283
+ providerOptions
4284
+ } = options;
4285
+ const openrouterOptions = (providerOptions == null ? void 0 : providerOptions.openrouter) || {};
4286
+ const warnings = [];
4287
+ if (files !== void 0 && files.length > 0) {
4288
+ throw new UnsupportedFunctionalityError({
4289
+ functionality: "image editing (files parameter)"
4290
+ });
4291
+ }
4292
+ if (mask !== void 0) {
4293
+ throw new UnsupportedFunctionalityError({
4294
+ functionality: "image inpainting (mask parameter)"
4295
+ });
4296
+ }
4297
+ if (n > 1) {
4298
+ warnings.push({
4299
+ type: "unsupported",
4300
+ feature: "n > 1",
4301
+ details: `OpenRouter image generation returns 1 image per call. Requested ${n} images.`
4302
+ });
4303
+ }
4304
+ if (size !== void 0) {
4305
+ warnings.push({
4306
+ type: "unsupported",
4307
+ feature: "size",
4308
+ details: "Use aspectRatio instead. Size parameter is not supported by OpenRouter image generation."
4309
+ });
4310
+ }
4311
+ const imageConfig = aspectRatio !== void 0 ? { aspect_ratio: aspectRatio } : void 0;
4312
+ const body = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
4313
+ model: this.modelId,
4314
+ messages: [
4315
+ {
4316
+ role: "user",
4317
+ content: prompt != null ? prompt : ""
4318
+ }
4319
+ ],
4320
+ modalities: ["image", "text"]
4321
+ }, imageConfig !== void 0 && { image_config: imageConfig }), seed !== void 0 && { seed }), this.settings.user !== void 0 && { user: this.settings.user }), this.settings.provider !== void 0 && {
4322
+ provider: this.settings.provider
4323
+ }), this.config.extraBody), this.settings.extraBody), openrouterOptions);
4324
+ const { value: responseValue, responseHeaders } = await postJsonToApi({
4325
+ url: this.config.url({
4326
+ path: "/chat/completions",
4327
+ modelId: this.modelId
4328
+ }),
4329
+ headers: combineHeaders(this.config.headers(), headers),
4330
+ body,
4331
+ failedResponseHandler: openrouterFailedResponseHandler,
4332
+ successfulResponseHandler: createJsonResponseHandler(
4333
+ OpenRouterImageResponseSchema
4334
+ ),
4335
+ abortSignal,
4336
+ fetch: this.config.fetch
4337
+ });
4338
+ const choice = responseValue.choices[0];
4339
+ if (!choice) {
4340
+ throw new NoContentGeneratedError({
4341
+ message: "No choice in response"
4342
+ });
4343
+ }
4344
+ const images = [];
4345
+ if ((_a16 = choice.message) == null ? void 0 : _a16.images) {
4346
+ for (const image of choice.message.images) {
4347
+ const dataUrl = image.image_url.url;
4348
+ images.push(getBase64FromDataUrl(dataUrl));
4349
+ }
4350
+ }
4351
+ const usage = responseValue.usage ? {
4352
+ inputTokens: responseValue.usage.prompt_tokens,
4353
+ outputTokens: responseValue.usage.completion_tokens,
4354
+ totalTokens: responseValue.usage.total_tokens
4355
+ } : void 0;
4356
+ return {
4357
+ images,
4358
+ warnings,
4359
+ response: {
4360
+ timestamp: /* @__PURE__ */ new Date(),
4361
+ modelId: responseValue.model,
4362
+ headers: responseHeaders
4363
+ },
4364
+ usage
4365
+ };
4366
+ }
4367
+ };
4368
+
4166
4369
  // src/utils/remove-undefined.ts
4167
4370
  function removeUndefinedEntries(record) {
4168
4371
  return Object.fromEntries(
4169
- Object.entries(record).filter(([, value]) => value !== null)
4372
+ Object.entries(record).filter(([, value]) => value != null)
4170
4373
  );
4171
4374
  }
4172
4375
 
4173
4376
  // src/utils/with-user-agent-suffix.ts
4377
+ function normalizeHeaders2(headers) {
4378
+ if (!headers) {
4379
+ return {};
4380
+ }
4381
+ if (headers instanceof Headers) {
4382
+ return Object.fromEntries(headers.entries());
4383
+ }
4384
+ if (Array.isArray(headers)) {
4385
+ return Object.fromEntries(headers);
4386
+ }
4387
+ return headers;
4388
+ }
4389
+ function findHeaderKey(headers, targetKey) {
4390
+ const lowerTarget = targetKey.toLowerCase();
4391
+ return Object.keys(headers).find((key) => key.toLowerCase() === lowerTarget);
4392
+ }
4174
4393
  function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4175
- const cleanedHeaders = removeUndefinedEntries(
4176
- headers != null ? headers : {}
4394
+ const normalizedHeaders = normalizeHeaders2(headers);
4395
+ const cleanedHeaders = removeUndefinedEntries(normalizedHeaders);
4396
+ const existingUserAgentKey = findHeaderKey(cleanedHeaders, "user-agent");
4397
+ const existingUserAgentValue = existingUserAgentKey ? cleanedHeaders[existingUserAgentKey] : void 0;
4398
+ const userAgent = (existingUserAgentValue == null ? void 0 : existingUserAgentValue.trim()) ? existingUserAgentValue : userAgentSuffixParts.filter(Boolean).join(" ");
4399
+ const headersWithoutUserAgent = Object.fromEntries(
4400
+ Object.entries(cleanedHeaders).filter(
4401
+ ([key]) => key.toLowerCase() !== "user-agent"
4402
+ )
4177
4403
  );
4178
- const currentUserAgentHeader = cleanedHeaders["user-agent"] || "";
4179
- const newUserAgent = [currentUserAgentHeader, ...userAgentSuffixParts].filter(Boolean).join(" ");
4180
- return __spreadProps(__spreadValues({}, cleanedHeaders), {
4181
- "user-agent": newUserAgent
4404
+ return __spreadProps(__spreadValues({}, headersWithoutUserAgent), {
4405
+ "user-agent": userAgent
4182
4406
  });
4183
4407
  }
4184
4408
 
4185
4409
  // src/version.ts
4186
- var VERSION2 = false ? "0.0.0-test" : "2.0.2";
4410
+ var VERSION2 = false ? "0.0.0-test" : "2.1.0";
4187
4411
 
4188
4412
  // src/provider.ts
4189
4413
  function createOpenRouter(options = {}) {
@@ -4225,6 +4449,13 @@ function createOpenRouter(options = {}) {
4225
4449
  fetch: options.fetch,
4226
4450
  extraBody: options.extraBody
4227
4451
  });
4452
+ const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
4453
+ provider: "openrouter.image",
4454
+ url: ({ path }) => `${baseURL}${path}`,
4455
+ headers: getHeaders,
4456
+ fetch: options.fetch,
4457
+ extraBody: options.extraBody
4458
+ });
4228
4459
  const createLanguageModel = (modelId, settings) => {
4229
4460
  if (new.target) {
4230
4461
  throw new Error(
@@ -4245,6 +4476,7 @@ function createOpenRouter(options = {}) {
4245
4476
  provider.completion = createCompletionModel;
4246
4477
  provider.textEmbeddingModel = createEmbeddingModel;
4247
4478
  provider.embedding = createEmbeddingModel;
4479
+ provider.imageModel = createImageModel;
4248
4480
  return provider;
4249
4481
  }
4250
4482
  var openrouter = createOpenRouter({