@openrouter/ai-sdk-provider 2.3.3 → 2.4.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.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
  }
@@ -3499,7 +3525,8 @@ var OpenRouterChatLanguageModel = class {
3499
3525
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3500
3526
  );
3501
3527
  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);
3528
+ const mappedFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3529
+ const effectiveFinishReason = hasToolCalls && mappedFinishReason.unified === "other" ? createFinishReason("tool-calls", mappedFinishReason.raw) : mappedFinishReason;
3503
3530
  return {
3504
3531
  content,
3505
3532
  finishReason: effectiveFinishReason,
@@ -3563,6 +3590,10 @@ var OpenRouterChatLanguageModel = class {
3563
3590
  abortSignal: options.abortSignal,
3564
3591
  fetch: this.config.fetch
3565
3592
  });
3593
+ let streamError;
3594
+ const safeResponse = withStreamErrorHandling(response, (err) => {
3595
+ streamError = err;
3596
+ });
3566
3597
  const toolCalls = [];
3567
3598
  let finishReason = createFinishReason("other");
3568
3599
  const usage = {
@@ -3591,7 +3622,7 @@ var OpenRouterChatLanguageModel = class {
3591
3622
  let openrouterResponseId;
3592
3623
  let provider;
3593
3624
  return {
3594
- stream: response.pipeThrough(
3625
+ stream: safeResponse.pipeThrough(
3595
3626
  new TransformStream({
3596
3627
  transform(chunk, controller) {
3597
3628
  var _a17, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
@@ -3913,12 +3944,19 @@ var OpenRouterChatLanguageModel = class {
3913
3944
  flush(controller) {
3914
3945
  var _a17;
3915
3946
  const hasToolCalls = toolCalls.length > 0;
3947
+ if (streamError != null) {
3948
+ finishReason = createFinishReason("error");
3949
+ controller.enqueue({ type: "error", error: streamError });
3950
+ }
3916
3951
  const hasEncryptedReasoning = accumulatedReasoningDetails.some(
3917
3952
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3918
3953
  );
3919
3954
  if (hasToolCalls && hasEncryptedReasoning && finishReason.unified === "stop") {
3920
3955
  finishReason = createFinishReason("tool-calls", finishReason.raw);
3921
3956
  }
3957
+ if (hasToolCalls && finishReason.unified === "other") {
3958
+ finishReason = createFinishReason("tool-calls", finishReason.raw);
3959
+ }
3922
3960
  if (finishReason.unified === "tool-calls") {
3923
3961
  for (const toolCall of toolCalls) {
3924
3962
  if (toolCall && !toolCall.sent) {
@@ -4304,6 +4342,10 @@ var OpenRouterCompletionLanguageModel = class {
4304
4342
  abortSignal: options.abortSignal,
4305
4343
  fetch: this.config.fetch
4306
4344
  });
4345
+ let streamError;
4346
+ const safeResponse = withStreamErrorHandling(response, (err) => {
4347
+ streamError = err;
4348
+ });
4307
4349
  let finishReason = createFinishReason("other");
4308
4350
  const usage = {
4309
4351
  inputTokens: {
@@ -4323,7 +4365,7 @@ var OpenRouterCompletionLanguageModel = class {
4323
4365
  let provider;
4324
4366
  let rawUsage;
4325
4367
  return {
4326
- stream: response.pipeThrough(
4368
+ stream: safeResponse.pipeThrough(
4327
4369
  new TransformStream({
4328
4370
  transform(chunk, controller) {
4329
4371
  var _a16, _b16, _c, _d, _e;
@@ -4387,6 +4429,10 @@ var OpenRouterCompletionLanguageModel = class {
4387
4429
  }
4388
4430
  },
4389
4431
  flush(controller) {
4432
+ if (streamError != null) {
4433
+ finishReason = createFinishReason("error");
4434
+ controller.enqueue({ type: "error", error: streamError });
4435
+ }
4390
4436
  usage.raw = rawUsage;
4391
4437
  const openrouterMetadata = {
4392
4438
  usage: openrouterUsage
@@ -4500,17 +4546,19 @@ var OpenRouter = class {
4500
4546
  this.apiKey = options.apiKey;
4501
4547
  this.headers = options.headers;
4502
4548
  this.api_keys = options.api_keys;
4549
+ this.appName = options.appName;
4550
+ this.appUrl = options.appUrl;
4503
4551
  }
4504
4552
  get baseConfig() {
4505
4553
  return {
4506
4554
  baseURL: this.baseURL,
4507
- headers: () => __spreadValues(__spreadValues({
4555
+ headers: () => __spreadValues(__spreadValues(__spreadValues(__spreadValues({
4508
4556
  Authorization: `Bearer ${loadApiKey({
4509
4557
  apiKey: this.apiKey,
4510
4558
  environmentVariableName: "OPENROUTER_API_KEY",
4511
4559
  description: "OpenRouter"
4512
4560
  })}`
4513
- }, this.headers), this.api_keys && Object.keys(this.api_keys).length > 0 && {
4561
+ }, 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
4562
  "X-Provider-API-Keys": JSON.stringify(this.api_keys)
4515
4563
  })
4516
4564
  };
@@ -4747,7 +4795,7 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4747
4795
  }
4748
4796
 
4749
4797
  // src/version.ts
4750
- var VERSION2 = false ? "0.0.0-test" : "2.3.3";
4798
+ var VERSION2 = false ? "0.0.0-test" : "2.4.0";
4751
4799
 
4752
4800
  // src/provider.ts
4753
4801
  function createOpenRouter(options = {}) {
@@ -4755,13 +4803,13 @@ function createOpenRouter(options = {}) {
4755
4803
  const baseURL = (_b16 = withoutTrailingSlash((_a16 = options.baseURL) != null ? _a16 : options.baseUrl)) != null ? _b16 : "https://openrouter.ai/api/v1";
4756
4804
  const compatibility = (_c = options.compatibility) != null ? _c : "compatible";
4757
4805
  const getHeaders = () => withUserAgentSuffix2(
4758
- __spreadValues(__spreadValues({
4806
+ __spreadValues(__spreadValues(__spreadValues(__spreadValues({
4759
4807
  Authorization: `Bearer ${loadApiKey({
4760
4808
  apiKey: options.apiKey,
4761
4809
  environmentVariableName: "OPENROUTER_API_KEY",
4762
4810
  description: "OpenRouter"
4763
4811
  })}`
4764
- }, options.headers), options.api_keys && Object.keys(options.api_keys).length > 0 && {
4812
+ }, 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
4813
  "X-Provider-API-Keys": JSON.stringify(options.api_keys)
4766
4814
  }),
4767
4815
  `ai-sdk/openrouter/${VERSION2}`