@openrouter/ai-sdk-provider 2.3.3 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -677,6 +677,16 @@ interface OpenRouterProviderSettings {
677
677
  * Maps provider slugs (e.g. "anthropic", "openai") to their respective API keys.
678
678
  */
679
679
  api_keys?: Record<string, string>;
680
+ /**
681
+ * Your app's display name. Sets the `X-OpenRouter-Title` header on
682
+ * every request for app attribution on the openrouter.ai dashboard.
683
+ */
684
+ appName?: string;
685
+ /**
686
+ * Your app's URL or identifier. Sets the `HTTP-Referer` header on every request,
687
+ * used to identify your app on the openrouter.ai dashboard.
688
+ */
689
+ appUrl?: string;
680
690
  }
681
691
  /**
682
692
  Create an OpenRouter provider instance.
@@ -709,6 +719,14 @@ declare class OpenRouter {
709
719
  * Record of provider slugs to API keys for injecting into provider routing.
710
720
  */
711
721
  readonly api_keys?: Record<string, string>;
722
+ /**
723
+ * App display name for the `X-OpenRouter-Title` header.
724
+ */
725
+ readonly appName?: string;
726
+ /**
727
+ * App URL for the `HTTP-Referer` header.
728
+ */
729
+ readonly appUrl?: string;
712
730
  /**
713
731
  * Creates a new OpenRouter provider instance.
714
732
  */
package/dist/index.d.ts CHANGED
@@ -677,6 +677,16 @@ interface OpenRouterProviderSettings {
677
677
  * Maps provider slugs (e.g. "anthropic", "openai") to their respective API keys.
678
678
  */
679
679
  api_keys?: Record<string, string>;
680
+ /**
681
+ * Your app's display name. Sets the `X-OpenRouter-Title` header on
682
+ * every request for app attribution on the openrouter.ai dashboard.
683
+ */
684
+ appName?: string;
685
+ /**
686
+ * Your app's URL or identifier. Sets the `HTTP-Referer` header on every request,
687
+ * used to identify your app on the openrouter.ai dashboard.
688
+ */
689
+ appUrl?: string;
680
690
  }
681
691
  /**
682
692
  Create an OpenRouter provider instance.
@@ -709,6 +719,14 @@ declare class OpenRouter {
709
719
  * Record of provider slugs to API keys for injecting into provider routing.
710
720
  */
711
721
  readonly api_keys?: Record<string, string>;
722
+ /**
723
+ * App display name for the `X-OpenRouter-Title` header.
724
+ */
725
+ readonly appName?: string;
726
+ /**
727
+ * App URL for the `HTTP-Referer` header.
728
+ */
729
+ readonly appUrl?: string;
712
730
  /**
713
731
  * Creates a new OpenRouter provider instance.
714
732
  */
package/dist/index.js CHANGED
@@ -2450,6 +2450,31 @@ function createFinishReason(unified, raw) {
2450
2450
  return { unified, raw };
2451
2451
  }
2452
2452
 
2453
+ // src/utils/with-stream-error-handling.ts
2454
+ function withStreamErrorHandling(source, onError) {
2455
+ const reader = source.getReader();
2456
+ return new ReadableStream({
2457
+ async pull(controller) {
2458
+ try {
2459
+ const { done, value } = await reader.read();
2460
+ if (done) {
2461
+ controller.close();
2462
+ } else {
2463
+ controller.enqueue(value);
2464
+ }
2465
+ } catch (err) {
2466
+ onError(err);
2467
+ reader.cancel().catch(() => {
2468
+ });
2469
+ controller.close();
2470
+ }
2471
+ },
2472
+ cancel(reason) {
2473
+ reader.cancel(reason);
2474
+ }
2475
+ });
2476
+ }
2477
+
2453
2478
  // src/utils/reasoning-details-duplicate-tracker.ts
2454
2479
  var _seenKeys;
2455
2480
  var ReasoningDetailsDuplicateTracker = class {
@@ -2837,6 +2862,7 @@ function convertToOpenRouterChatMessages(prompt) {
2837
2862
  role: "tool",
2838
2863
  tool_call_id: toolResponse.toolCallId,
2839
2864
  content: content2,
2865
+ name: toolResponse.toolName,
2840
2866
  cache_control: (_h = getCacheControl(providerOptions)) != null ? _h : getCacheControl(toolResponse.providerOptions)
2841
2867
  });
2842
2868
  }
@@ -3413,17 +3439,6 @@ var OpenRouterChatLanguageModel = class {
3413
3439
  break;
3414
3440
  }
3415
3441
  case "reasoning.encrypted" /* Encrypted */: {
3416
- if (detail.data) {
3417
- return {
3418
- type: "reasoning",
3419
- text: "[REDACTED]",
3420
- providerMetadata: {
3421
- openrouter: {
3422
- reasoning_details: [detail]
3423
- }
3424
- }
3425
- };
3426
- }
3427
3442
  break;
3428
3443
  }
3429
3444
  default: {
@@ -3499,7 +3514,8 @@ var OpenRouterChatLanguageModel = class {
3499
3514
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3500
3515
  );
3501
3516
  const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
3502
- const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3517
+ const mappedFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3518
+ const effectiveFinishReason = hasToolCalls && mappedFinishReason.unified === "other" ? createFinishReason("tool-calls", mappedFinishReason.raw) : mappedFinishReason;
3503
3519
  return {
3504
3520
  content,
3505
3521
  finishReason: effectiveFinishReason,
@@ -3563,6 +3579,10 @@ var OpenRouterChatLanguageModel = class {
3563
3579
  abortSignal: options.abortSignal,
3564
3580
  fetch: this.config.fetch
3565
3581
  });
3582
+ let streamError;
3583
+ const safeResponse = withStreamErrorHandling(response, (err) => {
3584
+ streamError = err;
3585
+ });
3566
3586
  const toolCalls = [];
3567
3587
  let finishReason = createFinishReason("other");
3568
3588
  const usage = {
@@ -3591,7 +3611,7 @@ var OpenRouterChatLanguageModel = class {
3591
3611
  let openrouterResponseId;
3592
3612
  let provider;
3593
3613
  return {
3594
- stream: response.pipeThrough(
3614
+ stream: safeResponse.pipeThrough(
3595
3615
  new TransformStream({
3596
3616
  transform(chunk, controller) {
3597
3617
  var _a17, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
@@ -3707,9 +3727,6 @@ var OpenRouterChatLanguageModel = class {
3707
3727
  break;
3708
3728
  }
3709
3729
  case "reasoning.encrypted" /* Encrypted */: {
3710
- if (detail.data) {
3711
- emitReasoningChunk("[REDACTED]", reasoningMetadata);
3712
- }
3713
3730
  break;
3714
3731
  }
3715
3732
  case "reasoning.summary" /* Summary */: {
@@ -3913,12 +3930,19 @@ var OpenRouterChatLanguageModel = class {
3913
3930
  flush(controller) {
3914
3931
  var _a17;
3915
3932
  const hasToolCalls = toolCalls.length > 0;
3933
+ if (streamError != null) {
3934
+ finishReason = createFinishReason("error");
3935
+ controller.enqueue({ type: "error", error: streamError });
3936
+ }
3916
3937
  const hasEncryptedReasoning = accumulatedReasoningDetails.some(
3917
3938
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3918
3939
  );
3919
3940
  if (hasToolCalls && hasEncryptedReasoning && finishReason.unified === "stop") {
3920
3941
  finishReason = createFinishReason("tool-calls", finishReason.raw);
3921
3942
  }
3943
+ if (hasToolCalls && finishReason.unified === "other") {
3944
+ finishReason = createFinishReason("tool-calls", finishReason.raw);
3945
+ }
3922
3946
  if (finishReason.unified === "tool-calls") {
3923
3947
  for (const toolCall of toolCalls) {
3924
3948
  if (toolCall && !toolCall.sent) {
@@ -4304,6 +4328,10 @@ var OpenRouterCompletionLanguageModel = class {
4304
4328
  abortSignal: options.abortSignal,
4305
4329
  fetch: this.config.fetch
4306
4330
  });
4331
+ let streamError;
4332
+ const safeResponse = withStreamErrorHandling(response, (err) => {
4333
+ streamError = err;
4334
+ });
4307
4335
  let finishReason = createFinishReason("other");
4308
4336
  const usage = {
4309
4337
  inputTokens: {
@@ -4323,7 +4351,7 @@ var OpenRouterCompletionLanguageModel = class {
4323
4351
  let provider;
4324
4352
  let rawUsage;
4325
4353
  return {
4326
- stream: response.pipeThrough(
4354
+ stream: safeResponse.pipeThrough(
4327
4355
  new TransformStream({
4328
4356
  transform(chunk, controller) {
4329
4357
  var _a16, _b16, _c, _d, _e;
@@ -4387,6 +4415,10 @@ var OpenRouterCompletionLanguageModel = class {
4387
4415
  }
4388
4416
  },
4389
4417
  flush(controller) {
4418
+ if (streamError != null) {
4419
+ finishReason = createFinishReason("error");
4420
+ controller.enqueue({ type: "error", error: streamError });
4421
+ }
4390
4422
  usage.raw = rawUsage;
4391
4423
  const openrouterMetadata = {
4392
4424
  usage: openrouterUsage
@@ -4500,17 +4532,19 @@ var OpenRouter = class {
4500
4532
  this.apiKey = options.apiKey;
4501
4533
  this.headers = options.headers;
4502
4534
  this.api_keys = options.api_keys;
4535
+ this.appName = options.appName;
4536
+ this.appUrl = options.appUrl;
4503
4537
  }
4504
4538
  get baseConfig() {
4505
4539
  return {
4506
4540
  baseURL: this.baseURL,
4507
- headers: () => __spreadValues(__spreadValues({
4541
+ headers: () => __spreadValues(__spreadValues(__spreadValues(__spreadValues({
4508
4542
  Authorization: `Bearer ${loadApiKey({
4509
4543
  apiKey: this.apiKey,
4510
4544
  environmentVariableName: "OPENROUTER_API_KEY",
4511
4545
  description: "OpenRouter"
4512
4546
  })}`
4513
- }, this.headers), this.api_keys && Object.keys(this.api_keys).length > 0 && {
4547
+ }, this.appName && { "X-OpenRouter-Title": this.appName }), this.appUrl && { "HTTP-Referer": this.appUrl }), this.headers), this.api_keys && Object.keys(this.api_keys).length > 0 && {
4514
4548
  "X-Provider-API-Keys": JSON.stringify(this.api_keys)
4515
4549
  })
4516
4550
  };
@@ -4747,7 +4781,7 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4747
4781
  }
4748
4782
 
4749
4783
  // src/version.ts
4750
- var VERSION2 = false ? "0.0.0-test" : "2.3.3";
4784
+ var VERSION2 = false ? "0.0.0-test" : "2.4.1";
4751
4785
 
4752
4786
  // src/provider.ts
4753
4787
  function createOpenRouter(options = {}) {
@@ -4755,13 +4789,13 @@ function createOpenRouter(options = {}) {
4755
4789
  const baseURL = (_b16 = withoutTrailingSlash((_a16 = options.baseURL) != null ? _a16 : options.baseUrl)) != null ? _b16 : "https://openrouter.ai/api/v1";
4756
4790
  const compatibility = (_c = options.compatibility) != null ? _c : "compatible";
4757
4791
  const getHeaders = () => withUserAgentSuffix2(
4758
- __spreadValues(__spreadValues({
4792
+ __spreadValues(__spreadValues(__spreadValues(__spreadValues({
4759
4793
  Authorization: `Bearer ${loadApiKey({
4760
4794
  apiKey: options.apiKey,
4761
4795
  environmentVariableName: "OPENROUTER_API_KEY",
4762
4796
  description: "OpenRouter"
4763
4797
  })}`
4764
- }, options.headers), options.api_keys && Object.keys(options.api_keys).length > 0 && {
4798
+ }, options.appName && { "X-OpenRouter-Title": options.appName }), options.appUrl && { "HTTP-Referer": options.appUrl }), options.headers), options.api_keys && Object.keys(options.api_keys).length > 0 && {
4765
4799
  "X-Provider-API-Keys": JSON.stringify(options.api_keys)
4766
4800
  }),
4767
4801
  `ai-sdk/openrouter/${VERSION2}`