@openrouter/ai-sdk-provider 1.4.0 → 1.5.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
@@ -1036,6 +1036,19 @@ function mapOpenRouterFinishReason(finishReason) {
1036
1036
  }
1037
1037
  }
1038
1038
 
1039
+ // src/types/openrouter-chat-completions-input.ts
1040
+ var OPENROUTER_AUDIO_FORMATS = [
1041
+ "wav",
1042
+ "mp3",
1043
+ "aiff",
1044
+ "aac",
1045
+ "ogg",
1046
+ "flac",
1047
+ "m4a",
1048
+ "pcm16",
1049
+ "pcm24"
1050
+ ];
1051
+
1039
1052
  // src/chat/is-url.ts
1040
1053
  function isUrl({
1041
1054
  url,
@@ -1077,6 +1090,34 @@ function getBase64FromDataUrl(dataUrl) {
1077
1090
  const match = dataUrl.match(/^data:[^;]*;base64,(.+)$/);
1078
1091
  return match ? match[1] : dataUrl;
1079
1092
  }
1093
+ var MIME_TO_FORMAT = {
1094
+ // MP3 variants
1095
+ mpeg: "mp3",
1096
+ mp3: "mp3",
1097
+ // WAV variants
1098
+ "x-wav": "wav",
1099
+ wave: "wav",
1100
+ wav: "wav",
1101
+ // OGG variants
1102
+ ogg: "ogg",
1103
+ vorbis: "ogg",
1104
+ // AAC variants
1105
+ aac: "aac",
1106
+ "x-aac": "aac",
1107
+ // M4A variants
1108
+ m4a: "m4a",
1109
+ "x-m4a": "m4a",
1110
+ mp4: "m4a",
1111
+ // AIFF variants
1112
+ aiff: "aiff",
1113
+ "x-aiff": "aiff",
1114
+ // FLAC
1115
+ flac: "flac",
1116
+ "x-flac": "flac",
1117
+ // PCM variants
1118
+ pcm16: "pcm16",
1119
+ pcm24: "pcm24"
1120
+ };
1080
1121
  function getInputAudioData(part) {
1081
1122
  const fileData = getFileUrl({
1082
1123
  part,
@@ -1101,19 +1142,14 @@ Learn more: https://openrouter.ai/docs/features/multimodal/audio`
1101
1142
  }
1102
1143
  const data = getBase64FromDataUrl(fileData);
1103
1144
  const mediaType = part.mediaType || "audio/mpeg";
1104
- let format = mediaType.replace("audio/", "");
1105
- if (format === "mpeg" || format === "mp3") {
1106
- format = "mp3";
1107
- } else if (format === "x-wav" || format === "wave" || format === "wav") {
1108
- format = "wav";
1109
- }
1110
- if (format !== "mp3" && format !== "wav") {
1145
+ const rawFormat = mediaType.replace("audio/", "");
1146
+ const format = MIME_TO_FORMAT[rawFormat];
1147
+ if (format === void 0) {
1148
+ const supportedList = OPENROUTER_AUDIO_FORMATS.join(", ");
1111
1149
  throw new Error(
1112
1150
  `Unsupported audio format: "${mediaType}"
1113
1151
 
1114
- OpenRouter only supports MP3 and WAV audio formats.
1115
- \u2022 For MP3: use "audio/mpeg" or "audio/mp3"
1116
- \u2022 For WAV: use "audio/wav" or "audio/x-wav"
1152
+ OpenRouter supports the following audio formats: ${supportedList}
1117
1153
 
1118
1154
  Learn more: https://openrouter.ai/docs/features/multimodal/audio`
1119
1155
  );
@@ -1608,7 +1644,16 @@ var OpenRouterChatLanguageModel = class {
1608
1644
  presence_penalty: presencePenalty,
1609
1645
  seed,
1610
1646
  stop: stopSequences,
1611
- response_format: responseFormat,
1647
+ response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? responseFormat.schema != null ? {
1648
+ type: "json_schema",
1649
+ json_schema: __spreadValues({
1650
+ schema: responseFormat.schema,
1651
+ strict: true,
1652
+ name: (_a15 = responseFormat.name) != null ? _a15 : "response"
1653
+ }, responseFormat.description && {
1654
+ description: responseFormat.description
1655
+ })
1656
+ } : { type: "json_object" } : void 0,
1612
1657
  top_k: topK,
1613
1658
  // messages:
1614
1659
  messages: convertToOpenRouterChatMessages(prompt),
@@ -1624,20 +1669,6 @@ var OpenRouterChatLanguageModel = class {
1624
1669
  // Debug settings:
1625
1670
  debug: this.settings.debug
1626
1671
  }, this.config.extraBody), this.settings.extraBody);
1627
- if ((responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null) {
1628
- return __spreadProps(__spreadValues({}, baseArgs), {
1629
- response_format: {
1630
- type: "json_schema",
1631
- json_schema: __spreadValues({
1632
- schema: responseFormat.schema,
1633
- strict: true,
1634
- name: (_a15 = responseFormat.name) != null ? _a15 : "response"
1635
- }, responseFormat.description && {
1636
- description: responseFormat.description
1637
- })
1638
- }
1639
- });
1640
- }
1641
1672
  if (tools && tools.length > 0) {
1642
1673
  const mappedTools = tools.filter(
1643
1674
  (tool) => tool.type === "function"
@@ -2640,6 +2671,78 @@ var OpenRouterCompletionLanguageModel = class {
2640
2671
  }
2641
2672
  };
2642
2673
 
2674
+ // src/embedding/schemas.ts
2675
+ import { z as z9 } from "zod/v4";
2676
+ var openrouterEmbeddingUsageSchema = z9.object({
2677
+ prompt_tokens: z9.number(),
2678
+ total_tokens: z9.number(),
2679
+ cost: z9.number().optional()
2680
+ });
2681
+ var openrouterEmbeddingDataSchema = z9.object({
2682
+ object: z9.literal("embedding"),
2683
+ embedding: z9.array(z9.number()),
2684
+ index: z9.number().optional()
2685
+ });
2686
+ var OpenRouterEmbeddingResponseSchema = z9.object({
2687
+ id: z9.string().optional(),
2688
+ object: z9.literal("list"),
2689
+ data: z9.array(openrouterEmbeddingDataSchema),
2690
+ model: z9.string(),
2691
+ usage: openrouterEmbeddingUsageSchema.optional()
2692
+ });
2693
+
2694
+ // src/embedding/index.ts
2695
+ var OpenRouterEmbeddingModel = class {
2696
+ constructor(modelId, settings, config) {
2697
+ this.specificationVersion = "v2";
2698
+ this.provider = "openrouter";
2699
+ this.maxEmbeddingsPerCall = void 0;
2700
+ this.supportsParallelCalls = true;
2701
+ this.modelId = modelId;
2702
+ this.settings = settings;
2703
+ this.config = config;
2704
+ }
2705
+ async doEmbed(options) {
2706
+ var _a15;
2707
+ const { values, abortSignal, headers } = options;
2708
+ const args = __spreadValues(__spreadValues({
2709
+ model: this.modelId,
2710
+ input: values,
2711
+ user: this.settings.user,
2712
+ provider: this.settings.provider
2713
+ }, this.config.extraBody), this.settings.extraBody);
2714
+ const { value: responseValue, responseHeaders } = await postJsonToApi({
2715
+ url: this.config.url({
2716
+ path: "/embeddings",
2717
+ modelId: this.modelId
2718
+ }),
2719
+ headers: combineHeaders(this.config.headers(), headers),
2720
+ body: args,
2721
+ failedResponseHandler: openrouterFailedResponseHandler,
2722
+ successfulResponseHandler: createJsonResponseHandler(
2723
+ OpenRouterEmbeddingResponseSchema
2724
+ ),
2725
+ abortSignal,
2726
+ fetch: this.config.fetch
2727
+ });
2728
+ return {
2729
+ embeddings: responseValue.data.map((item) => item.embedding),
2730
+ usage: responseValue.usage ? { tokens: responseValue.usage.prompt_tokens } : void 0,
2731
+ providerMetadata: ((_a15 = responseValue.usage) == null ? void 0 : _a15.cost) ? {
2732
+ openrouter: {
2733
+ usage: {
2734
+ cost: responseValue.usage.cost
2735
+ }
2736
+ }
2737
+ } : void 0,
2738
+ response: {
2739
+ headers: responseHeaders,
2740
+ body: responseValue
2741
+ }
2742
+ };
2743
+ }
2744
+ };
2745
+
2643
2746
  // src/facade.ts
2644
2747
  var OpenRouter = class {
2645
2748
  /**
@@ -2650,17 +2753,20 @@ var OpenRouter = class {
2650
2753
  this.baseURL = (_b = withoutTrailingSlash((_a15 = options.baseURL) != null ? _a15 : options.baseUrl)) != null ? _b : "https://openrouter.ai/api/v1";
2651
2754
  this.apiKey = options.apiKey;
2652
2755
  this.headers = options.headers;
2756
+ this.api_keys = options.api_keys;
2653
2757
  }
2654
2758
  get baseConfig() {
2655
2759
  return {
2656
2760
  baseURL: this.baseURL,
2657
- headers: () => __spreadValues({
2761
+ headers: () => __spreadValues(__spreadValues({
2658
2762
  Authorization: `Bearer ${loadApiKey({
2659
2763
  apiKey: this.apiKey,
2660
2764
  environmentVariableName: "OPENROUTER_API_KEY",
2661
2765
  description: "OpenRouter"
2662
2766
  })}`
2663
- }, this.headers)
2767
+ }, this.headers), this.api_keys && Object.keys(this.api_keys).length > 0 && {
2768
+ "X-Provider-API-Keys": JSON.stringify(this.api_keys)
2769
+ })
2664
2770
  };
2665
2771
  }
2666
2772
  chat(modelId, settings = {}) {
@@ -2679,6 +2785,19 @@ var OpenRouter = class {
2679
2785
  url: ({ path }) => `${this.baseURL}${path}`
2680
2786
  }));
2681
2787
  }
2788
+ textEmbeddingModel(modelId, settings = {}) {
2789
+ return new OpenRouterEmbeddingModel(modelId, settings, __spreadProps(__spreadValues({
2790
+ provider: "openrouter.embedding"
2791
+ }, this.baseConfig), {
2792
+ url: ({ path }) => `${this.baseURL}${path}`
2793
+ }));
2794
+ }
2795
+ /**
2796
+ * @deprecated Use textEmbeddingModel instead
2797
+ */
2798
+ embedding(modelId, settings = {}) {
2799
+ return this.textEmbeddingModel(modelId, settings);
2800
+ }
2682
2801
  };
2683
2802
 
2684
2803
  // src/utils/remove-undefined.ts
@@ -2701,7 +2820,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
2701
2820
  }
2702
2821
 
2703
2822
  // src/version.ts
2704
- var VERSION = false ? "0.0.0-test" : "1.4.0";
2823
+ var VERSION = false ? "0.0.0-test" : "1.5.0";
2705
2824
 
2706
2825
  // src/provider.ts
2707
2826
  function createOpenRouter(options = {}) {
@@ -2709,13 +2828,15 @@ function createOpenRouter(options = {}) {
2709
2828
  const baseURL = (_b = withoutTrailingSlash((_a15 = options.baseURL) != null ? _a15 : options.baseUrl)) != null ? _b : "https://openrouter.ai/api/v1";
2710
2829
  const compatibility = (_c = options.compatibility) != null ? _c : "compatible";
2711
2830
  const getHeaders = () => withUserAgentSuffix(
2712
- __spreadValues({
2831
+ __spreadValues(__spreadValues({
2713
2832
  Authorization: `Bearer ${loadApiKey({
2714
2833
  apiKey: options.apiKey,
2715
2834
  environmentVariableName: "OPENROUTER_API_KEY",
2716
2835
  description: "OpenRouter"
2717
2836
  })}`
2718
- }, options.headers),
2837
+ }, options.headers), options.api_keys && Object.keys(options.api_keys).length > 0 && {
2838
+ "X-Provider-API-Keys": JSON.stringify(options.api_keys)
2839
+ }),
2719
2840
  `ai-sdk/openrouter/${VERSION}`
2720
2841
  );
2721
2842
  const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
@@ -2734,6 +2855,13 @@ function createOpenRouter(options = {}) {
2734
2855
  fetch: options.fetch,
2735
2856
  extraBody: options.extraBody
2736
2857
  });
2858
+ const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
2859
+ provider: "openrouter.embedding",
2860
+ url: ({ path }) => `${baseURL}${path}`,
2861
+ headers: getHeaders,
2862
+ fetch: options.fetch,
2863
+ extraBody: options.extraBody
2864
+ });
2737
2865
  const createLanguageModel = (modelId, settings) => {
2738
2866
  if (new.target) {
2739
2867
  throw new Error(
@@ -2752,15 +2880,38 @@ function createOpenRouter(options = {}) {
2752
2880
  provider.languageModel = createLanguageModel;
2753
2881
  provider.chat = createChatModel;
2754
2882
  provider.completion = createCompletionModel;
2883
+ provider.textEmbeddingModel = createEmbeddingModel;
2884
+ provider.embedding = createEmbeddingModel;
2755
2885
  return provider;
2756
2886
  }
2757
2887
  var openrouter = createOpenRouter({
2758
2888
  compatibility: "strict"
2759
2889
  // strict for OpenRouter API
2760
2890
  });
2891
+
2892
+ // src/toon/index.ts
2893
+ async function getToonModule() {
2894
+ try {
2895
+ return await import("@toon-format/toon");
2896
+ } catch (e) {
2897
+ throw new Error(
2898
+ "The @toon-format/toon package is required for TOON encoding/decoding. Install it with: npm install @toon-format/toon"
2899
+ );
2900
+ }
2901
+ }
2902
+ async function encodeToon(value, options) {
2903
+ const toon = await getToonModule();
2904
+ return toon.encode(value, options);
2905
+ }
2906
+ async function decodeToon(input, options) {
2907
+ const toon = await getToonModule();
2908
+ return toon.decode(input, options);
2909
+ }
2761
2910
  export {
2762
2911
  OpenRouter,
2763
2912
  createOpenRouter,
2913
+ decodeToon,
2914
+ encodeToon,
2764
2915
  openrouter
2765
2916
  };
2766
2917
  //# sourceMappingURL=index.mjs.map