@openrouter/ai-sdk-provider 2.0.4 → 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
@@ -2758,13 +2758,14 @@ var OpenRouterNonStreamChatCompletionResponseSchema = z7.union([
2758
2758
  annotations: z7.array(
2759
2759
  z7.union([
2760
2760
  // URL citation from web search
2761
+ // title, start_index, end_index are optional as some upstream providers may omit them
2761
2762
  z7.object({
2762
2763
  type: z7.literal("url_citation"),
2763
2764
  url_citation: z7.object({
2764
- end_index: z7.number(),
2765
- start_index: z7.number(),
2766
- title: z7.string(),
2767
2765
  url: z7.string(),
2766
+ title: z7.string().optional(),
2767
+ start_index: z7.number().optional(),
2768
+ end_index: z7.number().optional(),
2768
2769
  content: z7.string().optional()
2769
2770
  }).passthrough()
2770
2771
  }).passthrough(),
@@ -2841,13 +2842,14 @@ var OpenRouterStreamChatCompletionChunkSchema = z7.union([
2841
2842
  annotations: z7.array(
2842
2843
  z7.union([
2843
2844
  // URL citation from web search
2845
+ // title, start_index, end_index are optional as some upstream providers may omit them
2844
2846
  z7.object({
2845
2847
  type: z7.literal("url_citation"),
2846
2848
  url_citation: z7.object({
2847
- end_index: z7.number(),
2848
- start_index: z7.number(),
2849
- title: z7.string(),
2850
2849
  url: z7.string(),
2850
+ title: z7.string().optional(),
2851
+ start_index: z7.number().optional(),
2852
+ end_index: z7.number().optional(),
2851
2853
  content: z7.string().optional()
2852
2854
  }).passthrough()
2853
2855
  }).passthrough(),
@@ -2994,7 +2996,7 @@ var OpenRouterChatLanguageModel = class {
2994
2996
  return baseArgs;
2995
2997
  }
2996
2998
  async doGenerate(options) {
2997
- 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;
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;
2998
3000
  const providerOptions = options.providerOptions || {};
2999
3001
  const openrouterOptions = providerOptions.openrouter || {};
3000
3002
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3044,7 +3046,8 @@ var OpenRouterChatLanguageModel = class {
3044
3046
  total: (_d = response.usage.completion_tokens) != null ? _d : 0,
3045
3047
  text: void 0,
3046
3048
  reasoning: (_f = (_e = response.usage.completion_tokens_details) == null ? void 0 : _e.reasoning_tokens) != null ? _f : void 0
3047
- }
3049
+ },
3050
+ raw: response.usage
3048
3051
  } : {
3049
3052
  inputTokens: {
3050
3053
  total: 0,
@@ -3056,7 +3059,8 @@ var OpenRouterChatLanguageModel = class {
3056
3059
  total: 0,
3057
3060
  text: void 0,
3058
3061
  reasoning: void 0
3059
- }
3062
+ },
3063
+ raw: void 0
3060
3064
  };
3061
3065
  const reasoningDetails = (_g = choice.message.reasoning_details) != null ? _g : [];
3062
3066
  const reasoning = reasoningDetails.length > 0 ? reasoningDetails.map((detail) => {
@@ -3156,17 +3160,19 @@ var OpenRouterChatLanguageModel = class {
3156
3160
  sourceType: "url",
3157
3161
  id: annotation.url_citation.url,
3158
3162
  url: annotation.url_citation.url,
3159
- title: annotation.url_citation.title,
3163
+ title: (_j = annotation.url_citation.title) != null ? _j : "",
3160
3164
  providerMetadata: {
3161
3165
  openrouter: {
3162
- 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
3163
3169
  }
3164
3170
  }
3165
3171
  });
3166
3172
  }
3167
3173
  }
3168
3174
  }
3169
- const fileAnnotations = (_j = choice.message.annotations) == null ? void 0 : _j.filter(
3175
+ const fileAnnotations = (_n = choice.message.annotations) == null ? void 0 : _n.filter(
3170
3176
  (a) => a.type === "file"
3171
3177
  );
3172
3178
  const hasToolCalls = choice.message.tool_calls && choice.message.tool_calls.length > 0;
@@ -3174,7 +3180,7 @@ var OpenRouterChatLanguageModel = class {
3174
3180
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3175
3181
  );
3176
3182
  const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
3177
- const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_k = choice.finish_reason) != null ? _k : 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);
3178
3184
  return {
3179
3185
  content,
3180
3186
  finishReason: effectiveFinishReason,
@@ -3182,23 +3188,22 @@ var OpenRouterChatLanguageModel = class {
3182
3188
  warnings: [],
3183
3189
  providerMetadata: {
3184
3190
  openrouter: OpenRouterProviderMetadataSchema.parse({
3185
- provider: (_l = response.provider) != null ? _l : "",
3186
- reasoning_details: (_m = choice.message.reasoning_details) != null ? _m : [],
3191
+ provider: (_p = response.provider) != null ? _p : "",
3192
+ reasoning_details: (_q = choice.message.reasoning_details) != null ? _q : [],
3187
3193
  annotations: fileAnnotations && fileAnnotations.length > 0 ? fileAnnotations : void 0,
3188
- usage: __spreadValues(__spreadValues(__spreadValues({
3189
- promptTokens: (_n = usageInfo.inputTokens.total) != null ? _n : 0,
3190
- completionTokens: (_o = usageInfo.outputTokens.total) != null ? _o : 0,
3191
- totalTokens: ((_p = usageInfo.inputTokens.total) != null ? _p : 0) + ((_q = usageInfo.outputTokens.total) != null ? _q : 0),
3192
- cost: (_r = response.usage) == null ? void 0 : _r.cost
3193
- }, ((_t = (_s = response.usage) == null ? void 0 : _s.prompt_tokens_details) == null ? void 0 : _t.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 ? {
3194
3199
  promptTokensDetails: {
3195
3200
  cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3196
3201
  }
3197
- } : {}), ((_v = (_u = response.usage) == null ? void 0 : _u.completion_tokens_details) == null ? void 0 : _v.reasoning_tokens) != null ? {
3202
+ } : {}), ((_z = (_y = response.usage) == null ? void 0 : _y.completion_tokens_details) == null ? void 0 : _z.reasoning_tokens) != null ? {
3198
3203
  completionTokensDetails: {
3199
3204
  reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3200
3205
  }
3201
- } : {}), ((_x = (_w = response.usage) == null ? void 0 : _w.cost_details) == null ? void 0 : _x.upstream_inference_cost) != null ? {
3206
+ } : {}), ((_B = (_A = response.usage) == null ? void 0 : _A.cost_details) == null ? void 0 : _B.upstream_inference_cost) != null ? {
3202
3207
  costDetails: {
3203
3208
  upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3204
3209
  }
@@ -3251,9 +3256,11 @@ var OpenRouterChatLanguageModel = class {
3251
3256
  total: void 0,
3252
3257
  text: void 0,
3253
3258
  reasoning: void 0
3254
- }
3259
+ },
3260
+ raw: void 0
3255
3261
  };
3256
3262
  const openrouterUsage = {};
3263
+ let rawUsage;
3257
3264
  const accumulatedReasoningDetails = [];
3258
3265
  let reasoningDetailsAttachedToToolCall = false;
3259
3266
  const accumulatedFileAnnotations = [];
@@ -3267,7 +3274,10 @@ var OpenRouterChatLanguageModel = class {
3267
3274
  stream: response.pipeThrough(
3268
3275
  new TransformStream({
3269
3276
  transform(chunk, controller) {
3270
- 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
+ }
3271
3281
  if (!chunk.success) {
3272
3282
  finishReason = createFinishReason("error");
3273
3283
  controller.enqueue({ type: "error", error: chunk.error });
@@ -3298,6 +3308,7 @@ var OpenRouterChatLanguageModel = class {
3298
3308
  if (value.usage != null) {
3299
3309
  usage.inputTokens.total = value.usage.prompt_tokens;
3300
3310
  usage.outputTokens.total = value.usage.completion_tokens;
3311
+ rawUsage = value.usage;
3301
3312
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
3302
3313
  if (value.usage.prompt_tokens_details) {
3303
3314
  const cachedInputTokens = (_a17 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a17 : 0;
@@ -3314,7 +3325,9 @@ var OpenRouterChatLanguageModel = class {
3314
3325
  reasoningTokens
3315
3326
  };
3316
3327
  }
3317
- openrouterUsage.cost = value.usage.cost;
3328
+ if (value.usage.cost != null) {
3329
+ openrouterUsage.cost = value.usage.cost;
3330
+ }
3318
3331
  openrouterUsage.totalTokens = value.usage.total_tokens;
3319
3332
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
3320
3333
  if (upstreamInferenceCost != null) {
@@ -3427,10 +3440,12 @@ var OpenRouterChatLanguageModel = class {
3427
3440
  sourceType: "url",
3428
3441
  id: annotation.url_citation.url,
3429
3442
  url: annotation.url_citation.url,
3430
- title: annotation.url_citation.title,
3443
+ title: (_d = annotation.url_citation.title) != null ? _d : "",
3431
3444
  providerMetadata: {
3432
3445
  openrouter: {
3433
- 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
3434
3449
  }
3435
3450
  }
3436
3451
  });
@@ -3446,7 +3461,7 @@ var OpenRouterChatLanguageModel = class {
3446
3461
  }
3447
3462
  if (delta.tool_calls != null) {
3448
3463
  for (const toolCallDelta of delta.tool_calls) {
3449
- const index = (_d = toolCallDelta.index) != null ? _d : toolCalls.length - 1;
3464
+ const index = (_h = toolCallDelta.index) != null ? _h : toolCalls.length - 1;
3450
3465
  if (toolCalls[index] == null) {
3451
3466
  if (toolCallDelta.type !== "function") {
3452
3467
  throw new InvalidResponseDataError({
@@ -3460,7 +3475,7 @@ var OpenRouterChatLanguageModel = class {
3460
3475
  message: `Expected 'id' to be a string.`
3461
3476
  });
3462
3477
  }
3463
- if (((_e = toolCallDelta.function) == null ? void 0 : _e.name) == null) {
3478
+ if (((_i = toolCallDelta.function) == null ? void 0 : _i.name) == null) {
3464
3479
  throw new InvalidResponseDataError({
3465
3480
  data: toolCallDelta,
3466
3481
  message: `Expected 'function.name' to be a string.`
@@ -3471,7 +3486,7 @@ var OpenRouterChatLanguageModel = class {
3471
3486
  type: "function",
3472
3487
  function: {
3473
3488
  name: toolCallDelta.function.name,
3474
- arguments: (_f = toolCallDelta.function.arguments) != null ? _f : ""
3489
+ arguments: (_j = toolCallDelta.function.arguments) != null ? _j : ""
3475
3490
  },
3476
3491
  inputStarted: false,
3477
3492
  sent: false
@@ -3483,7 +3498,7 @@ var OpenRouterChatLanguageModel = class {
3483
3498
  message: `Tool call at index ${index} is missing after creation.`
3484
3499
  });
3485
3500
  }
3486
- 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)) {
3487
3502
  toolCall2.inputStarted = true;
3488
3503
  controller.enqueue({
3489
3504
  type: "tool-input-start",
@@ -3534,18 +3549,18 @@ var OpenRouterChatLanguageModel = class {
3534
3549
  toolName: toolCall.function.name
3535
3550
  });
3536
3551
  }
3537
- if (((_i = toolCallDelta.function) == null ? void 0 : _i.arguments) != null) {
3538
- 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 : "";
3539
3554
  }
3540
3555
  controller.enqueue({
3541
3556
  type: "tool-input-delta",
3542
3557
  id: toolCall.id,
3543
- delta: (_l = toolCallDelta.function.arguments) != null ? _l : ""
3558
+ delta: (_p = toolCallDelta.function.arguments) != null ? _p : ""
3544
3559
  });
3545
- 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)) {
3546
3561
  controller.enqueue({
3547
3562
  type: "tool-call",
3548
- toolCallId: (_o = toolCall.id) != null ? _o : generateId(),
3563
+ toolCallId: (_s = toolCall.id) != null ? _s : generateId(),
3549
3564
  toolName: toolCall.function.name,
3550
3565
  input: toolCall.function.arguments,
3551
3566
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
@@ -3622,6 +3637,7 @@ var OpenRouterChatLanguageModel = class {
3622
3637
  if (accumulatedFileAnnotations.length > 0) {
3623
3638
  openrouterMetadata.annotations = accumulatedFileAnnotations;
3624
3639
  }
3640
+ usage.raw = rawUsage;
3625
3641
  controller.enqueue({
3626
3642
  type: "finish",
3627
3643
  finishReason,
@@ -3749,6 +3765,7 @@ var OpenRouterCompletionChunkSchema = z8.union([
3749
3765
  z8.object({
3750
3766
  id: z8.string().optional(),
3751
3767
  model: z8.string().optional(),
3768
+ provider: z8.string().optional(),
3752
3769
  choices: z8.array(
3753
3770
  z8.object({
3754
3771
  text: z8.string(),
@@ -3856,7 +3873,7 @@ var OpenRouterCompletionLanguageModel = class {
3856
3873
  }, this.config.extraBody), this.settings.extraBody);
3857
3874
  }
3858
3875
  async doGenerate(options) {
3859
- 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;
3860
3877
  const providerOptions = options.providerOptions || {};
3861
3878
  const openrouterOptions = providerOptions.openrouter || {};
3862
3879
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3913,9 +3930,32 @@ var OpenRouterCompletionLanguageModel = class {
3913
3930
  total: (_h = (_g = response.usage) == null ? void 0 : _g.completion_tokens) != null ? _h : 0,
3914
3931
  text: void 0,
3915
3932
  reasoning: (_k = (_j = (_i = response.usage) == null ? void 0 : _i.completion_tokens_details) == null ? void 0 : _j.reasoning_tokens) != null ? _k : void 0
3916
- }
3933
+ },
3934
+ raw: (_l = response.usage) != null ? _l : void 0
3917
3935
  },
3918
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
+ },
3919
3959
  response: {
3920
3960
  headers: responseHeaders
3921
3961
  }
@@ -3955,14 +3995,20 @@ var OpenRouterCompletionLanguageModel = class {
3955
3995
  total: void 0,
3956
3996
  text: void 0,
3957
3997
  reasoning: void 0
3958
- }
3998
+ },
3999
+ raw: void 0
3959
4000
  };
3960
4001
  const openrouterUsage = {};
4002
+ let provider;
4003
+ let rawUsage;
3961
4004
  return {
3962
4005
  stream: response.pipeThrough(
3963
4006
  new TransformStream({
3964
4007
  transform(chunk, controller) {
3965
4008
  var _a16, _b16, _c;
4009
+ if (options.includeRawChunks) {
4010
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
4011
+ }
3966
4012
  if (!chunk.success) {
3967
4013
  finishReason = createFinishReason("error");
3968
4014
  controller.enqueue({ type: "error", error: chunk.error });
@@ -3974,9 +4020,13 @@ var OpenRouterCompletionLanguageModel = class {
3974
4020
  controller.enqueue({ type: "error", error: value.error });
3975
4021
  return;
3976
4022
  }
4023
+ if (value.provider) {
4024
+ provider = value.provider;
4025
+ }
3977
4026
  if (value.usage != null) {
3978
4027
  usage.inputTokens.total = value.usage.prompt_tokens;
3979
4028
  usage.outputTokens.total = value.usage.completion_tokens;
4029
+ rawUsage = value.usage;
3980
4030
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
3981
4031
  if (value.usage.prompt_tokens_details) {
3982
4032
  const cachedInputTokens = (_a16 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a16 : 0;
@@ -3993,7 +4043,9 @@ var OpenRouterCompletionLanguageModel = class {
3993
4043
  reasoningTokens
3994
4044
  };
3995
4045
  }
3996
- openrouterUsage.cost = value.usage.cost;
4046
+ if (value.usage.cost != null) {
4047
+ openrouterUsage.cost = value.usage.cost;
4048
+ }
3997
4049
  openrouterUsage.totalTokens = value.usage.total_tokens;
3998
4050
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
3999
4051
  if (upstreamInferenceCost != null) {
@@ -4015,14 +4067,19 @@ var OpenRouterCompletionLanguageModel = class {
4015
4067
  }
4016
4068
  },
4017
4069
  flush(controller) {
4070
+ usage.raw = rawUsage;
4071
+ const openrouterMetadata = {
4072
+ usage: openrouterUsage
4073
+ };
4074
+ if (provider !== void 0) {
4075
+ openrouterMetadata.provider = provider;
4076
+ }
4018
4077
  controller.enqueue({
4019
4078
  type: "finish",
4020
4079
  finishReason,
4021
4080
  usage,
4022
4081
  providerMetadata: {
4023
- openrouter: {
4024
- usage: openrouterUsage
4025
- }
4082
+ openrouter: openrouterMetadata
4026
4083
  }
4027
4084
  });
4028
4085
  }
@@ -4052,6 +4109,7 @@ var OpenRouterEmbeddingResponseSchema = z9.object({
4052
4109
  object: z9.literal("list"),
4053
4110
  data: z9.array(openrouterEmbeddingDataSchema),
4054
4111
  model: z9.string(),
4112
+ provider: z9.string().optional(),
4055
4113
  usage: openrouterEmbeddingUsageSchema.optional()
4056
4114
  });
4057
4115
 
@@ -4067,7 +4125,7 @@ var OpenRouterEmbeddingModel = class {
4067
4125
  this.config = config;
4068
4126
  }
4069
4127
  async doEmbed(options) {
4070
- var _a16;
4128
+ var _a16, _b16, _c, _d, _e, _f;
4071
4129
  const { values, abortSignal, headers } = options;
4072
4130
  const args = __spreadValues(__spreadValues({
4073
4131
  model: this.modelId,
@@ -4092,13 +4150,16 @@ var OpenRouterEmbeddingModel = class {
4092
4150
  return {
4093
4151
  embeddings: responseValue.data.map((item) => item.embedding),
4094
4152
  usage: responseValue.usage ? { tokens: responseValue.usage.prompt_tokens } : void 0,
4095
- providerMetadata: ((_a16 = responseValue.usage) == null ? void 0 : _a16.cost) ? {
4096
- openrouter: {
4097
- usage: {
4098
- cost: responseValue.usage.cost
4099
- }
4100
- }
4101
- } : 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
+ },
4102
4163
  response: {
4103
4164
  headers: responseHeaders,
4104
4165
  body: responseValue
@@ -4165,27 +4226,188 @@ var OpenRouter = class {
4165
4226
  }
4166
4227
  };
4167
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
+
4168
4369
  // src/utils/remove-undefined.ts
4169
4370
  function removeUndefinedEntries(record) {
4170
4371
  return Object.fromEntries(
4171
- Object.entries(record).filter(([, value]) => value !== null)
4372
+ Object.entries(record).filter(([, value]) => value != null)
4172
4373
  );
4173
4374
  }
4174
4375
 
4175
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
+ }
4176
4393
  function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4177
- const cleanedHeaders = removeUndefinedEntries(
4178
- 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
+ )
4179
4403
  );
4180
- const currentUserAgentHeader = cleanedHeaders["user-agent"] || "";
4181
- const newUserAgent = [currentUserAgentHeader, ...userAgentSuffixParts].filter(Boolean).join(" ");
4182
- return __spreadProps(__spreadValues({}, cleanedHeaders), {
4183
- "user-agent": newUserAgent
4404
+ return __spreadProps(__spreadValues({}, headersWithoutUserAgent), {
4405
+ "user-agent": userAgent
4184
4406
  });
4185
4407
  }
4186
4408
 
4187
4409
  // src/version.ts
4188
- var VERSION2 = false ? "0.0.0-test" : "2.0.4";
4410
+ var VERSION2 = false ? "0.0.0-test" : "2.1.0";
4189
4411
 
4190
4412
  // src/provider.ts
4191
4413
  function createOpenRouter(options = {}) {
@@ -4227,6 +4449,13 @@ function createOpenRouter(options = {}) {
4227
4449
  fetch: options.fetch,
4228
4450
  extraBody: options.extraBody
4229
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
+ });
4230
4459
  const createLanguageModel = (modelId, settings) => {
4231
4460
  if (new.target) {
4232
4461
  throw new Error(
@@ -4247,6 +4476,7 @@ function createOpenRouter(options = {}) {
4247
4476
  provider.completion = createCompletionModel;
4248
4477
  provider.textEmbeddingModel = createEmbeddingModel;
4249
4478
  provider.embedding = createEmbeddingModel;
4479
+ provider.imageModel = createImageModel;
4250
4480
  return provider;
4251
4481
  }
4252
4482
  var openrouter = createOpenRouter({