@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.js CHANGED
@@ -2791,13 +2791,14 @@ var OpenRouterNonStreamChatCompletionResponseSchema = import_v46.z.union([
2791
2791
  annotations: import_v46.z.array(
2792
2792
  import_v46.z.union([
2793
2793
  // URL citation from web search
2794
+ // title, start_index, end_index are optional as some upstream providers may omit them
2794
2795
  import_v46.z.object({
2795
2796
  type: import_v46.z.literal("url_citation"),
2796
2797
  url_citation: import_v46.z.object({
2797
- end_index: import_v46.z.number(),
2798
- start_index: import_v46.z.number(),
2799
- title: import_v46.z.string(),
2800
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(),
2801
2802
  content: import_v46.z.string().optional()
2802
2803
  }).passthrough()
2803
2804
  }).passthrough(),
@@ -2874,13 +2875,14 @@ var OpenRouterStreamChatCompletionChunkSchema = import_v46.z.union([
2874
2875
  annotations: import_v46.z.array(
2875
2876
  import_v46.z.union([
2876
2877
  // URL citation from web search
2878
+ // title, start_index, end_index are optional as some upstream providers may omit them
2877
2879
  import_v46.z.object({
2878
2880
  type: import_v46.z.literal("url_citation"),
2879
2881
  url_citation: import_v46.z.object({
2880
- end_index: import_v46.z.number(),
2881
- start_index: import_v46.z.number(),
2882
- title: import_v46.z.string(),
2883
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(),
2884
2886
  content: import_v46.z.string().optional()
2885
2887
  }).passthrough()
2886
2888
  }).passthrough(),
@@ -3027,7 +3029,7 @@ var OpenRouterChatLanguageModel = class {
3027
3029
  return baseArgs;
3028
3030
  }
3029
3031
  async doGenerate(options) {
3030
- 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;
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;
3031
3033
  const providerOptions = options.providerOptions || {};
3032
3034
  const openrouterOptions = providerOptions.openrouter || {};
3033
3035
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3077,7 +3079,8 @@ var OpenRouterChatLanguageModel = class {
3077
3079
  total: (_d = response.usage.completion_tokens) != null ? _d : 0,
3078
3080
  text: void 0,
3079
3081
  reasoning: (_f = (_e = response.usage.completion_tokens_details) == null ? void 0 : _e.reasoning_tokens) != null ? _f : void 0
3080
- }
3082
+ },
3083
+ raw: response.usage
3081
3084
  } : {
3082
3085
  inputTokens: {
3083
3086
  total: 0,
@@ -3089,7 +3092,8 @@ var OpenRouterChatLanguageModel = class {
3089
3092
  total: 0,
3090
3093
  text: void 0,
3091
3094
  reasoning: void 0
3092
- }
3095
+ },
3096
+ raw: void 0
3093
3097
  };
3094
3098
  const reasoningDetails = (_g = choice.message.reasoning_details) != null ? _g : [];
3095
3099
  const reasoning = reasoningDetails.length > 0 ? reasoningDetails.map((detail) => {
@@ -3189,17 +3193,19 @@ var OpenRouterChatLanguageModel = class {
3189
3193
  sourceType: "url",
3190
3194
  id: annotation.url_citation.url,
3191
3195
  url: annotation.url_citation.url,
3192
- title: annotation.url_citation.title,
3196
+ title: (_j = annotation.url_citation.title) != null ? _j : "",
3193
3197
  providerMetadata: {
3194
3198
  openrouter: {
3195
- 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
3196
3202
  }
3197
3203
  }
3198
3204
  });
3199
3205
  }
3200
3206
  }
3201
3207
  }
3202
- const fileAnnotations = (_j = choice.message.annotations) == null ? void 0 : _j.filter(
3208
+ const fileAnnotations = (_n = choice.message.annotations) == null ? void 0 : _n.filter(
3203
3209
  (a) => a.type === "file"
3204
3210
  );
3205
3211
  const hasToolCalls = choice.message.tool_calls && choice.message.tool_calls.length > 0;
@@ -3207,7 +3213,7 @@ var OpenRouterChatLanguageModel = class {
3207
3213
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3208
3214
  );
3209
3215
  const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
3210
- const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_k = choice.finish_reason) != null ? _k : 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);
3211
3217
  return {
3212
3218
  content,
3213
3219
  finishReason: effectiveFinishReason,
@@ -3215,23 +3221,22 @@ var OpenRouterChatLanguageModel = class {
3215
3221
  warnings: [],
3216
3222
  providerMetadata: {
3217
3223
  openrouter: OpenRouterProviderMetadataSchema.parse({
3218
- provider: (_l = response.provider) != null ? _l : "",
3219
- reasoning_details: (_m = choice.message.reasoning_details) != null ? _m : [],
3224
+ provider: (_p = response.provider) != null ? _p : "",
3225
+ reasoning_details: (_q = choice.message.reasoning_details) != null ? _q : [],
3220
3226
  annotations: fileAnnotations && fileAnnotations.length > 0 ? fileAnnotations : void 0,
3221
- usage: __spreadValues(__spreadValues(__spreadValues({
3222
- promptTokens: (_n = usageInfo.inputTokens.total) != null ? _n : 0,
3223
- completionTokens: (_o = usageInfo.outputTokens.total) != null ? _o : 0,
3224
- totalTokens: ((_p = usageInfo.inputTokens.total) != null ? _p : 0) + ((_q = usageInfo.outputTokens.total) != null ? _q : 0),
3225
- cost: (_r = response.usage) == null ? void 0 : _r.cost
3226
- }, ((_t = (_s = response.usage) == null ? void 0 : _s.prompt_tokens_details) == null ? void 0 : _t.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 ? {
3227
3232
  promptTokensDetails: {
3228
3233
  cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3229
3234
  }
3230
- } : {}), ((_v = (_u = response.usage) == null ? void 0 : _u.completion_tokens_details) == null ? void 0 : _v.reasoning_tokens) != null ? {
3235
+ } : {}), ((_z = (_y = response.usage) == null ? void 0 : _y.completion_tokens_details) == null ? void 0 : _z.reasoning_tokens) != null ? {
3231
3236
  completionTokensDetails: {
3232
3237
  reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3233
3238
  }
3234
- } : {}), ((_x = (_w = response.usage) == null ? void 0 : _w.cost_details) == null ? void 0 : _x.upstream_inference_cost) != null ? {
3239
+ } : {}), ((_B = (_A = response.usage) == null ? void 0 : _A.cost_details) == null ? void 0 : _B.upstream_inference_cost) != null ? {
3235
3240
  costDetails: {
3236
3241
  upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3237
3242
  }
@@ -3284,9 +3289,11 @@ var OpenRouterChatLanguageModel = class {
3284
3289
  total: void 0,
3285
3290
  text: void 0,
3286
3291
  reasoning: void 0
3287
- }
3292
+ },
3293
+ raw: void 0
3288
3294
  };
3289
3295
  const openrouterUsage = {};
3296
+ let rawUsage;
3290
3297
  const accumulatedReasoningDetails = [];
3291
3298
  let reasoningDetailsAttachedToToolCall = false;
3292
3299
  const accumulatedFileAnnotations = [];
@@ -3300,7 +3307,10 @@ var OpenRouterChatLanguageModel = class {
3300
3307
  stream: response.pipeThrough(
3301
3308
  new TransformStream({
3302
3309
  transform(chunk, controller) {
3303
- 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
+ }
3304
3314
  if (!chunk.success) {
3305
3315
  finishReason = createFinishReason("error");
3306
3316
  controller.enqueue({ type: "error", error: chunk.error });
@@ -3331,6 +3341,7 @@ var OpenRouterChatLanguageModel = class {
3331
3341
  if (value.usage != null) {
3332
3342
  usage.inputTokens.total = value.usage.prompt_tokens;
3333
3343
  usage.outputTokens.total = value.usage.completion_tokens;
3344
+ rawUsage = value.usage;
3334
3345
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
3335
3346
  if (value.usage.prompt_tokens_details) {
3336
3347
  const cachedInputTokens = (_a17 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a17 : 0;
@@ -3347,7 +3358,9 @@ var OpenRouterChatLanguageModel = class {
3347
3358
  reasoningTokens
3348
3359
  };
3349
3360
  }
3350
- openrouterUsage.cost = value.usage.cost;
3361
+ if (value.usage.cost != null) {
3362
+ openrouterUsage.cost = value.usage.cost;
3363
+ }
3351
3364
  openrouterUsage.totalTokens = value.usage.total_tokens;
3352
3365
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
3353
3366
  if (upstreamInferenceCost != null) {
@@ -3460,10 +3473,12 @@ var OpenRouterChatLanguageModel = class {
3460
3473
  sourceType: "url",
3461
3474
  id: annotation.url_citation.url,
3462
3475
  url: annotation.url_citation.url,
3463
- title: annotation.url_citation.title,
3476
+ title: (_d = annotation.url_citation.title) != null ? _d : "",
3464
3477
  providerMetadata: {
3465
3478
  openrouter: {
3466
- 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
3467
3482
  }
3468
3483
  }
3469
3484
  });
@@ -3479,7 +3494,7 @@ var OpenRouterChatLanguageModel = class {
3479
3494
  }
3480
3495
  if (delta.tool_calls != null) {
3481
3496
  for (const toolCallDelta of delta.tool_calls) {
3482
- const index = (_d = toolCallDelta.index) != null ? _d : toolCalls.length - 1;
3497
+ const index = (_h = toolCallDelta.index) != null ? _h : toolCalls.length - 1;
3483
3498
  if (toolCalls[index] == null) {
3484
3499
  if (toolCallDelta.type !== "function") {
3485
3500
  throw new InvalidResponseDataError({
@@ -3493,7 +3508,7 @@ var OpenRouterChatLanguageModel = class {
3493
3508
  message: `Expected 'id' to be a string.`
3494
3509
  });
3495
3510
  }
3496
- if (((_e = toolCallDelta.function) == null ? void 0 : _e.name) == null) {
3511
+ if (((_i = toolCallDelta.function) == null ? void 0 : _i.name) == null) {
3497
3512
  throw new InvalidResponseDataError({
3498
3513
  data: toolCallDelta,
3499
3514
  message: `Expected 'function.name' to be a string.`
@@ -3504,7 +3519,7 @@ var OpenRouterChatLanguageModel = class {
3504
3519
  type: "function",
3505
3520
  function: {
3506
3521
  name: toolCallDelta.function.name,
3507
- arguments: (_f = toolCallDelta.function.arguments) != null ? _f : ""
3522
+ arguments: (_j = toolCallDelta.function.arguments) != null ? _j : ""
3508
3523
  },
3509
3524
  inputStarted: false,
3510
3525
  sent: false
@@ -3516,7 +3531,7 @@ var OpenRouterChatLanguageModel = class {
3516
3531
  message: `Tool call at index ${index} is missing after creation.`
3517
3532
  });
3518
3533
  }
3519
- 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)) {
3520
3535
  toolCall2.inputStarted = true;
3521
3536
  controller.enqueue({
3522
3537
  type: "tool-input-start",
@@ -3567,18 +3582,18 @@ var OpenRouterChatLanguageModel = class {
3567
3582
  toolName: toolCall.function.name
3568
3583
  });
3569
3584
  }
3570
- if (((_i = toolCallDelta.function) == null ? void 0 : _i.arguments) != null) {
3571
- 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 : "";
3572
3587
  }
3573
3588
  controller.enqueue({
3574
3589
  type: "tool-input-delta",
3575
3590
  id: toolCall.id,
3576
- delta: (_l = toolCallDelta.function.arguments) != null ? _l : ""
3591
+ delta: (_p = toolCallDelta.function.arguments) != null ? _p : ""
3577
3592
  });
3578
- 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)) {
3579
3594
  controller.enqueue({
3580
3595
  type: "tool-call",
3581
- toolCallId: (_o = toolCall.id) != null ? _o : generateId(),
3596
+ toolCallId: (_s = toolCall.id) != null ? _s : generateId(),
3582
3597
  toolName: toolCall.function.name,
3583
3598
  input: toolCall.function.arguments,
3584
3599
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
@@ -3655,6 +3670,7 @@ var OpenRouterChatLanguageModel = class {
3655
3670
  if (accumulatedFileAnnotations.length > 0) {
3656
3671
  openrouterMetadata.annotations = accumulatedFileAnnotations;
3657
3672
  }
3673
+ usage.raw = rawUsage;
3658
3674
  controller.enqueue({
3659
3675
  type: "finish",
3660
3676
  finishReason,
@@ -3782,6 +3798,7 @@ var OpenRouterCompletionChunkSchema = import_v47.z.union([
3782
3798
  import_v47.z.object({
3783
3799
  id: import_v47.z.string().optional(),
3784
3800
  model: import_v47.z.string().optional(),
3801
+ provider: import_v47.z.string().optional(),
3785
3802
  choices: import_v47.z.array(
3786
3803
  import_v47.z.object({
3787
3804
  text: import_v47.z.string(),
@@ -3889,7 +3906,7 @@ var OpenRouterCompletionLanguageModel = class {
3889
3906
  }, this.config.extraBody), this.settings.extraBody);
3890
3907
  }
3891
3908
  async doGenerate(options) {
3892
- 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;
3893
3910
  const providerOptions = options.providerOptions || {};
3894
3911
  const openrouterOptions = providerOptions.openrouter || {};
3895
3912
  const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
@@ -3946,9 +3963,32 @@ var OpenRouterCompletionLanguageModel = class {
3946
3963
  total: (_h = (_g = response.usage) == null ? void 0 : _g.completion_tokens) != null ? _h : 0,
3947
3964
  text: void 0,
3948
3965
  reasoning: (_k = (_j = (_i = response.usage) == null ? void 0 : _i.completion_tokens_details) == null ? void 0 : _j.reasoning_tokens) != null ? _k : void 0
3949
- }
3966
+ },
3967
+ raw: (_l = response.usage) != null ? _l : void 0
3950
3968
  },
3951
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
+ },
3952
3992
  response: {
3953
3993
  headers: responseHeaders
3954
3994
  }
@@ -3988,14 +4028,20 @@ var OpenRouterCompletionLanguageModel = class {
3988
4028
  total: void 0,
3989
4029
  text: void 0,
3990
4030
  reasoning: void 0
3991
- }
4031
+ },
4032
+ raw: void 0
3992
4033
  };
3993
4034
  const openrouterUsage = {};
4035
+ let provider;
4036
+ let rawUsage;
3994
4037
  return {
3995
4038
  stream: response.pipeThrough(
3996
4039
  new TransformStream({
3997
4040
  transform(chunk, controller) {
3998
4041
  var _a16, _b16, _c;
4042
+ if (options.includeRawChunks) {
4043
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
4044
+ }
3999
4045
  if (!chunk.success) {
4000
4046
  finishReason = createFinishReason("error");
4001
4047
  controller.enqueue({ type: "error", error: chunk.error });
@@ -4007,9 +4053,13 @@ var OpenRouterCompletionLanguageModel = class {
4007
4053
  controller.enqueue({ type: "error", error: value.error });
4008
4054
  return;
4009
4055
  }
4056
+ if (value.provider) {
4057
+ provider = value.provider;
4058
+ }
4010
4059
  if (value.usage != null) {
4011
4060
  usage.inputTokens.total = value.usage.prompt_tokens;
4012
4061
  usage.outputTokens.total = value.usage.completion_tokens;
4062
+ rawUsage = value.usage;
4013
4063
  openrouterUsage.promptTokens = value.usage.prompt_tokens;
4014
4064
  if (value.usage.prompt_tokens_details) {
4015
4065
  const cachedInputTokens = (_a16 = value.usage.prompt_tokens_details.cached_tokens) != null ? _a16 : 0;
@@ -4026,7 +4076,9 @@ var OpenRouterCompletionLanguageModel = class {
4026
4076
  reasoningTokens
4027
4077
  };
4028
4078
  }
4029
- openrouterUsage.cost = value.usage.cost;
4079
+ if (value.usage.cost != null) {
4080
+ openrouterUsage.cost = value.usage.cost;
4081
+ }
4030
4082
  openrouterUsage.totalTokens = value.usage.total_tokens;
4031
4083
  const upstreamInferenceCost = (_c = value.usage.cost_details) == null ? void 0 : _c.upstream_inference_cost;
4032
4084
  if (upstreamInferenceCost != null) {
@@ -4048,14 +4100,19 @@ var OpenRouterCompletionLanguageModel = class {
4048
4100
  }
4049
4101
  },
4050
4102
  flush(controller) {
4103
+ usage.raw = rawUsage;
4104
+ const openrouterMetadata = {
4105
+ usage: openrouterUsage
4106
+ };
4107
+ if (provider !== void 0) {
4108
+ openrouterMetadata.provider = provider;
4109
+ }
4051
4110
  controller.enqueue({
4052
4111
  type: "finish",
4053
4112
  finishReason,
4054
4113
  usage,
4055
4114
  providerMetadata: {
4056
- openrouter: {
4057
- usage: openrouterUsage
4058
- }
4115
+ openrouter: openrouterMetadata
4059
4116
  }
4060
4117
  });
4061
4118
  }
@@ -4085,6 +4142,7 @@ var OpenRouterEmbeddingResponseSchema = import_v48.z.object({
4085
4142
  object: import_v48.z.literal("list"),
4086
4143
  data: import_v48.z.array(openrouterEmbeddingDataSchema),
4087
4144
  model: import_v48.z.string(),
4145
+ provider: import_v48.z.string().optional(),
4088
4146
  usage: openrouterEmbeddingUsageSchema.optional()
4089
4147
  });
4090
4148
 
@@ -4100,7 +4158,7 @@ var OpenRouterEmbeddingModel = class {
4100
4158
  this.config = config;
4101
4159
  }
4102
4160
  async doEmbed(options) {
4103
- var _a16;
4161
+ var _a16, _b16, _c, _d, _e, _f;
4104
4162
  const { values, abortSignal, headers } = options;
4105
4163
  const args = __spreadValues(__spreadValues({
4106
4164
  model: this.modelId,
@@ -4125,13 +4183,16 @@ var OpenRouterEmbeddingModel = class {
4125
4183
  return {
4126
4184
  embeddings: responseValue.data.map((item) => item.embedding),
4127
4185
  usage: responseValue.usage ? { tokens: responseValue.usage.prompt_tokens } : void 0,
4128
- providerMetadata: ((_a16 = responseValue.usage) == null ? void 0 : _a16.cost) ? {
4129
- openrouter: {
4130
- usage: {
4131
- cost: responseValue.usage.cost
4132
- }
4133
- }
4134
- } : 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
+ },
4135
4196
  response: {
4136
4197
  headers: responseHeaders,
4137
4198
  body: responseValue
@@ -4198,27 +4259,188 @@ var OpenRouter = class {
4198
4259
  }
4199
4260
  };
4200
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
+
4201
4402
  // src/utils/remove-undefined.ts
4202
4403
  function removeUndefinedEntries(record) {
4203
4404
  return Object.fromEntries(
4204
- Object.entries(record).filter(([, value]) => value !== null)
4405
+ Object.entries(record).filter(([, value]) => value != null)
4205
4406
  );
4206
4407
  }
4207
4408
 
4208
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
+ }
4209
4426
  function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4210
- const cleanedHeaders = removeUndefinedEntries(
4211
- 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
+ )
4212
4436
  );
4213
- const currentUserAgentHeader = cleanedHeaders["user-agent"] || "";
4214
- const newUserAgent = [currentUserAgentHeader, ...userAgentSuffixParts].filter(Boolean).join(" ");
4215
- return __spreadProps(__spreadValues({}, cleanedHeaders), {
4216
- "user-agent": newUserAgent
4437
+ return __spreadProps(__spreadValues({}, headersWithoutUserAgent), {
4438
+ "user-agent": userAgent
4217
4439
  });
4218
4440
  }
4219
4441
 
4220
4442
  // src/version.ts
4221
- var VERSION2 = false ? "0.0.0-test" : "2.0.4";
4443
+ var VERSION2 = false ? "0.0.0-test" : "2.1.0";
4222
4444
 
4223
4445
  // src/provider.ts
4224
4446
  function createOpenRouter(options = {}) {
@@ -4260,6 +4482,13 @@ function createOpenRouter(options = {}) {
4260
4482
  fetch: options.fetch,
4261
4483
  extraBody: options.extraBody
4262
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
+ });
4263
4492
  const createLanguageModel = (modelId, settings) => {
4264
4493
  if (new.target) {
4265
4494
  throw new Error(
@@ -4280,6 +4509,7 @@ function createOpenRouter(options = {}) {
4280
4509
  provider.completion = createCompletionModel;
4281
4510
  provider.textEmbeddingModel = createEmbeddingModel;
4282
4511
  provider.embedding = createEmbeddingModel;
4512
+ provider.imageModel = createImageModel;
4283
4513
  return provider;
4284
4514
  }
4285
4515
  var openrouter = createOpenRouter({