@openrouter/ai-sdk-provider 0.4.1 → 0.4.3
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/README.md +36 -0
- package/dist/index.js +86 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -59
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +86 -59
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +86 -59
- package/dist/internal/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,3 +107,39 @@ There are 3 ways to pass extra body to OpenRouter:
|
|
|
107
107
|
messages: [{ role: 'user', content: 'Hello' }],
|
|
108
108
|
});
|
|
109
109
|
```
|
|
110
|
+
|
|
111
|
+
## Anthropic Prompt Caching
|
|
112
|
+
|
|
113
|
+
You can include Anthropic-specific options directly in your messages when using functions like `streamText`. The OpenRouter provider will automatically convert these messages to the correct format internally.
|
|
114
|
+
|
|
115
|
+
### Basic Usage
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
|
119
|
+
import { streamText } from 'ai';
|
|
120
|
+
|
|
121
|
+
const openrouter = createOpenRouter({ apiKey: 'your-api-key' });
|
|
122
|
+
const model = openrouter('anthropic/<supported-caching-model>');
|
|
123
|
+
|
|
124
|
+
await streamText({
|
|
125
|
+
model,
|
|
126
|
+
messages: [
|
|
127
|
+
{
|
|
128
|
+
role: 'system',
|
|
129
|
+
content: 'You are a helpful assistant.',
|
|
130
|
+
// Add provider options at the message level
|
|
131
|
+
providerMetadata: {
|
|
132
|
+
openrouter: {
|
|
133
|
+
// cache_control also works
|
|
134
|
+
// cache_control: { type: 'ephemeral' }
|
|
135
|
+
cacheControl: { type: 'ephemeral' },
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
role: 'user',
|
|
141
|
+
content: 'Hello, how are you?',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -66,39 +66,61 @@ var import_zod2 = require("zod");
|
|
|
66
66
|
// src/convert-to-openrouter-chat-messages.ts
|
|
67
67
|
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
68
68
|
function convertToOpenRouterChatMessages(prompt) {
|
|
69
|
-
var _a;
|
|
69
|
+
var _a, _b, _c;
|
|
70
70
|
const messages = [];
|
|
71
|
-
|
|
71
|
+
function getCacheControl(providerMetadata) {
|
|
72
|
+
var _a2;
|
|
73
|
+
const anthropic = providerMetadata == null ? void 0 : providerMetadata.anthropic;
|
|
74
|
+
const cacheControlValue = (_a2 = anthropic == null ? void 0 : anthropic.cacheControl) != null ? _a2 : anthropic == null ? void 0 : anthropic.cache_control;
|
|
75
|
+
return cacheControlValue;
|
|
76
|
+
}
|
|
77
|
+
for (const { role, content, providerMetadata } of prompt) {
|
|
72
78
|
switch (role) {
|
|
73
79
|
case "system": {
|
|
74
|
-
messages.push({
|
|
80
|
+
messages.push({
|
|
81
|
+
role: "system",
|
|
82
|
+
content,
|
|
83
|
+
cache_control: getCacheControl(providerMetadata)
|
|
84
|
+
});
|
|
75
85
|
break;
|
|
76
86
|
}
|
|
77
87
|
case "user": {
|
|
78
88
|
if (content.length === 1 && ((_a = content[0]) == null ? void 0 : _a.type) === "text") {
|
|
79
|
-
messages.push({
|
|
89
|
+
messages.push({
|
|
90
|
+
role: "user",
|
|
91
|
+
content: content[0].text,
|
|
92
|
+
cache_control: (_b = getCacheControl(providerMetadata)) != null ? _b : getCacheControl(content[0].providerMetadata)
|
|
93
|
+
});
|
|
80
94
|
break;
|
|
81
95
|
}
|
|
96
|
+
const messageCacheControl = getCacheControl(providerMetadata);
|
|
82
97
|
const contentParts = content.map(
|
|
83
98
|
(part) => {
|
|
84
|
-
var _a2;
|
|
99
|
+
var _a2, _b2, _c2;
|
|
85
100
|
switch (part.type) {
|
|
86
101
|
case "text":
|
|
87
102
|
return {
|
|
88
103
|
type: "text",
|
|
89
|
-
text: part.text
|
|
104
|
+
text: part.text,
|
|
105
|
+
// For text parts, only use part-specific cache control
|
|
106
|
+
cache_control: getCacheControl(part.providerMetadata)
|
|
90
107
|
};
|
|
91
108
|
case "image":
|
|
92
109
|
return {
|
|
93
110
|
type: "image_url",
|
|
94
111
|
image_url: {
|
|
95
|
-
url: part.image instanceof URL ? part.image.toString() : `data:${(_a2 = part.mimeType) != null ? _a2 : "image/jpeg"};base64,${(0, import_provider_utils.convertUint8ArrayToBase64)(
|
|
96
|
-
|
|
112
|
+
url: part.image instanceof URL ? part.image.toString() : `data:${(_a2 = part.mimeType) != null ? _a2 : "image/jpeg"};base64,${(0, import_provider_utils.convertUint8ArrayToBase64)(
|
|
113
|
+
part.image
|
|
114
|
+
)}`
|
|
115
|
+
},
|
|
116
|
+
// For image parts, use part-specific or message-level cache control
|
|
117
|
+
cache_control: (_b2 = getCacheControl(part.providerMetadata)) != null ? _b2 : messageCacheControl
|
|
97
118
|
};
|
|
98
119
|
case "file":
|
|
99
120
|
return {
|
|
100
121
|
type: "text",
|
|
101
|
-
text: part.data instanceof URL ? part.data.toString() : part.data
|
|
122
|
+
text: part.data instanceof URL ? part.data.toString() : part.data,
|
|
123
|
+
cache_control: (_c2 = getCacheControl(part.providerMetadata)) != null ? _c2 : messageCacheControl
|
|
102
124
|
};
|
|
103
125
|
default: {
|
|
104
126
|
const _exhaustiveCheck = part;
|
|
@@ -148,7 +170,8 @@ function convertToOpenRouterChatMessages(prompt) {
|
|
|
148
170
|
messages.push({
|
|
149
171
|
role: "assistant",
|
|
150
172
|
content: text,
|
|
151
|
-
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
173
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
174
|
+
cache_control: getCacheControl(providerMetadata)
|
|
152
175
|
});
|
|
153
176
|
break;
|
|
154
177
|
}
|
|
@@ -157,7 +180,8 @@ function convertToOpenRouterChatMessages(prompt) {
|
|
|
157
180
|
messages.push({
|
|
158
181
|
role: "tool",
|
|
159
182
|
tool_call_id: toolResponse.toolCallId,
|
|
160
|
-
content: JSON.stringify(toolResponse.result)
|
|
183
|
+
content: JSON.stringify(toolResponse.result),
|
|
184
|
+
cache_control: (_c = getCacheControl(providerMetadata)) != null ? _c : getCacheControl(toolResponse.providerMetadata)
|
|
161
185
|
});
|
|
162
186
|
}
|
|
163
187
|
break;
|
|
@@ -204,7 +228,7 @@ function mapOpenRouterFinishReason(finishReason) {
|
|
|
204
228
|
// src/openrouter-error.ts
|
|
205
229
|
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
206
230
|
var import_zod = require("zod");
|
|
207
|
-
var
|
|
231
|
+
var OpenRouterErrorResponseSchema = import_zod.z.object({
|
|
208
232
|
error: import_zod.z.object({
|
|
209
233
|
message: import_zod.z.string(),
|
|
210
234
|
type: import_zod.z.string(),
|
|
@@ -213,7 +237,7 @@ var openAIErrorDataSchema = import_zod.z.object({
|
|
|
213
237
|
})
|
|
214
238
|
});
|
|
215
239
|
var openrouterFailedResponseHandler = (0, import_provider_utils2.createJsonErrorResponseHandler)({
|
|
216
|
-
errorSchema:
|
|
240
|
+
errorSchema: OpenRouterErrorResponseSchema,
|
|
217
241
|
errorToMessage: (data) => data.error.message
|
|
218
242
|
});
|
|
219
243
|
|
|
@@ -309,7 +333,7 @@ var OpenRouterChatLanguageModel = class {
|
|
|
309
333
|
}
|
|
310
334
|
}
|
|
311
335
|
async doGenerate(options) {
|
|
312
|
-
var _b, _c, _d;
|
|
336
|
+
var _b, _c, _d, _e, _f, _g, _h;
|
|
313
337
|
const args = this.getArgs(options);
|
|
314
338
|
const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({
|
|
315
339
|
url: this.config.url({
|
|
@@ -320,17 +344,21 @@ var OpenRouterChatLanguageModel = class {
|
|
|
320
344
|
body: args,
|
|
321
345
|
failedResponseHandler: openrouterFailedResponseHandler,
|
|
322
346
|
successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)(
|
|
323
|
-
|
|
347
|
+
OpenRouterNonStreamChatCompletionResponseSchema
|
|
324
348
|
),
|
|
325
349
|
abortSignal: options.abortSignal,
|
|
326
350
|
fetch: this.config.fetch
|
|
327
351
|
});
|
|
328
352
|
const _a = args, { messages: rawPrompt } = _a, rawSettings = __objRest(_a, ["messages"]);
|
|
329
353
|
const choice = response.choices[0];
|
|
330
|
-
if (choice
|
|
354
|
+
if (!choice) {
|
|
331
355
|
throw new Error("No choice in response");
|
|
332
356
|
}
|
|
333
357
|
return {
|
|
358
|
+
response: {
|
|
359
|
+
id: response.id,
|
|
360
|
+
modelId: response.model
|
|
361
|
+
},
|
|
334
362
|
text: (_b = choice.message.content) != null ? _b : void 0,
|
|
335
363
|
reasoning: (_c = choice.message.reasoning) != null ? _c : void 0,
|
|
336
364
|
toolCalls: (_d = choice.message.tool_calls) == null ? void 0 : _d.map((toolCall) => {
|
|
@@ -344,8 +372,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
344
372
|
}),
|
|
345
373
|
finishReason: mapOpenRouterFinishReason(choice.finish_reason),
|
|
346
374
|
usage: {
|
|
347
|
-
promptTokens: response.usage.prompt_tokens,
|
|
348
|
-
completionTokens: response.usage.completion_tokens
|
|
375
|
+
promptTokens: (_f = (_e = response.usage) == null ? void 0 : _e.prompt_tokens) != null ? _f : 0,
|
|
376
|
+
completionTokens: (_h = (_g = response.usage) == null ? void 0 : _g.completion_tokens) != null ? _h : 0
|
|
349
377
|
},
|
|
350
378
|
rawCall: { rawPrompt, rawSettings },
|
|
351
379
|
rawResponse: { headers: responseHeaders },
|
|
@@ -368,7 +396,7 @@ var OpenRouterChatLanguageModel = class {
|
|
|
368
396
|
}),
|
|
369
397
|
failedResponseHandler: openrouterFailedResponseHandler,
|
|
370
398
|
successfulResponseHandler: (0, import_provider_utils3.createEventSourceResponseHandler)(
|
|
371
|
-
|
|
399
|
+
OpenRouterStreamChatCompletionChunkSchema
|
|
372
400
|
),
|
|
373
401
|
abortSignal: options.abortSignal,
|
|
374
402
|
fetch: this.config.fetch
|
|
@@ -403,6 +431,12 @@ var OpenRouterChatLanguageModel = class {
|
|
|
403
431
|
id: value.id
|
|
404
432
|
});
|
|
405
433
|
}
|
|
434
|
+
if (value.model) {
|
|
435
|
+
controller.enqueue({
|
|
436
|
+
type: "response-metadata",
|
|
437
|
+
modelId: value.model
|
|
438
|
+
});
|
|
439
|
+
}
|
|
406
440
|
if (value.usage != null) {
|
|
407
441
|
usage = {
|
|
408
442
|
promptTokens: value.usage.prompt_tokens,
|
|
@@ -530,7 +564,16 @@ var OpenRouterChatLanguageModel = class {
|
|
|
530
564
|
};
|
|
531
565
|
}
|
|
532
566
|
};
|
|
533
|
-
var
|
|
567
|
+
var OpenRouterChatCompletionBaseResponseSchema = import_zod2.z.object({
|
|
568
|
+
id: import_zod2.z.string().optional(),
|
|
569
|
+
model: import_zod2.z.string().optional(),
|
|
570
|
+
usage: import_zod2.z.object({
|
|
571
|
+
prompt_tokens: import_zod2.z.number(),
|
|
572
|
+
completion_tokens: import_zod2.z.number(),
|
|
573
|
+
total_tokens: import_zod2.z.number()
|
|
574
|
+
}).nullish()
|
|
575
|
+
});
|
|
576
|
+
var OpenRouterNonStreamChatCompletionResponseSchema = OpenRouterChatCompletionBaseResponseSchema.extend({
|
|
534
577
|
choices: import_zod2.z.array(
|
|
535
578
|
import_zod2.z.object({
|
|
536
579
|
message: import_zod2.z.object({
|
|
@@ -565,15 +608,10 @@ var openAIChatResponseSchema = import_zod2.z.object({
|
|
|
565
608
|
}).nullable().optional(),
|
|
566
609
|
finish_reason: import_zod2.z.string().optional().nullable()
|
|
567
610
|
})
|
|
568
|
-
)
|
|
569
|
-
usage: import_zod2.z.object({
|
|
570
|
-
prompt_tokens: import_zod2.z.number(),
|
|
571
|
-
completion_tokens: import_zod2.z.number()
|
|
572
|
-
})
|
|
611
|
+
)
|
|
573
612
|
});
|
|
574
|
-
var
|
|
575
|
-
|
|
576
|
-
id: import_zod2.z.string().optional(),
|
|
613
|
+
var OpenRouterStreamChatCompletionChunkSchema = import_zod2.z.union([
|
|
614
|
+
OpenRouterChatCompletionBaseResponseSchema.extend({
|
|
577
615
|
choices: import_zod2.z.array(
|
|
578
616
|
import_zod2.z.object({
|
|
579
617
|
delta: import_zod2.z.object({
|
|
@@ -609,13 +647,9 @@ var openrouterChatChunkSchema = import_zod2.z.union([
|
|
|
609
647
|
finish_reason: import_zod2.z.string().nullable().optional(),
|
|
610
648
|
index: import_zod2.z.number()
|
|
611
649
|
})
|
|
612
|
-
)
|
|
613
|
-
usage: import_zod2.z.object({
|
|
614
|
-
prompt_tokens: import_zod2.z.number(),
|
|
615
|
-
completion_tokens: import_zod2.z.number()
|
|
616
|
-
}).nullish()
|
|
650
|
+
)
|
|
617
651
|
}),
|
|
618
|
-
|
|
652
|
+
OpenRouterErrorResponseSchema
|
|
619
653
|
]);
|
|
620
654
|
function prepareToolsAndToolChoice(mode) {
|
|
621
655
|
var _a;
|
|
@@ -893,6 +927,7 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
893
927
|
}
|
|
894
928
|
}
|
|
895
929
|
async doGenerate(options) {
|
|
930
|
+
var _b, _c, _d, _e, _f;
|
|
896
931
|
const args = this.getArgs(options);
|
|
897
932
|
const { responseHeaders, value: response } = await (0, import_provider_utils4.postJsonToApi)({
|
|
898
933
|
url: this.config.url({
|
|
@@ -903,22 +938,29 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
903
938
|
body: args,
|
|
904
939
|
failedResponseHandler: openrouterFailedResponseHandler,
|
|
905
940
|
successfulResponseHandler: (0, import_provider_utils4.createJsonResponseHandler)(
|
|
906
|
-
|
|
941
|
+
OpenRouterCompletionChunkSchema
|
|
907
942
|
),
|
|
908
943
|
abortSignal: options.abortSignal,
|
|
909
944
|
fetch: this.config.fetch
|
|
910
945
|
});
|
|
911
946
|
const _a = args, { prompt: rawPrompt } = _a, rawSettings = __objRest(_a, ["prompt"]);
|
|
947
|
+
if ("error" in response) {
|
|
948
|
+
throw new Error(`${response.error.message}`);
|
|
949
|
+
}
|
|
912
950
|
const choice = response.choices[0];
|
|
913
951
|
if (!choice) {
|
|
914
952
|
throw new Error("No choice in OpenRouter completion response");
|
|
915
953
|
}
|
|
916
954
|
return {
|
|
917
|
-
|
|
955
|
+
response: {
|
|
956
|
+
id: response.id,
|
|
957
|
+
modelId: response.model
|
|
958
|
+
},
|
|
959
|
+
text: (_b = choice.text) != null ? _b : "",
|
|
918
960
|
reasoning: choice.reasoning || void 0,
|
|
919
961
|
usage: {
|
|
920
|
-
promptTokens: response.usage.prompt_tokens,
|
|
921
|
-
completionTokens: response.usage.completion_tokens
|
|
962
|
+
promptTokens: (_d = (_c = response.usage) == null ? void 0 : _c.prompt_tokens) != null ? _d : 0,
|
|
963
|
+
completionTokens: (_f = (_e = response.usage) == null ? void 0 : _e.completion_tokens) != null ? _f : 0
|
|
922
964
|
},
|
|
923
965
|
finishReason: mapOpenRouterFinishReason(choice.finish_reason),
|
|
924
966
|
logprobs: mapOpenRouterCompletionLogProbs(choice.logprobs),
|
|
@@ -942,7 +984,7 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
942
984
|
}),
|
|
943
985
|
failedResponseHandler: openrouterFailedResponseHandler,
|
|
944
986
|
successfulResponseHandler: (0, import_provider_utils4.createEventSourceResponseHandler)(
|
|
945
|
-
|
|
987
|
+
OpenRouterCompletionChunkSchema
|
|
946
988
|
),
|
|
947
989
|
abortSignal: options.abortSignal,
|
|
948
990
|
fetch: this.config.fetch
|
|
@@ -1009,29 +1051,14 @@ var OpenRouterCompletionLanguageModel = class {
|
|
|
1009
1051
|
};
|
|
1010
1052
|
}
|
|
1011
1053
|
};
|
|
1012
|
-
var
|
|
1013
|
-
choices: import_zod3.z.array(
|
|
1014
|
-
import_zod3.z.object({
|
|
1015
|
-
text: import_zod3.z.string(),
|
|
1016
|
-
reasoning: import_zod3.z.string().nullish().optional(),
|
|
1017
|
-
finish_reason: import_zod3.z.string(),
|
|
1018
|
-
logprobs: import_zod3.z.object({
|
|
1019
|
-
tokens: import_zod3.z.array(import_zod3.z.string()),
|
|
1020
|
-
token_logprobs: import_zod3.z.array(import_zod3.z.number()),
|
|
1021
|
-
top_logprobs: import_zod3.z.array(import_zod3.z.record(import_zod3.z.string(), import_zod3.z.number())).nullable()
|
|
1022
|
-
}).nullable().optional()
|
|
1023
|
-
})
|
|
1024
|
-
),
|
|
1025
|
-
usage: import_zod3.z.object({
|
|
1026
|
-
prompt_tokens: import_zod3.z.number(),
|
|
1027
|
-
completion_tokens: import_zod3.z.number()
|
|
1028
|
-
})
|
|
1029
|
-
});
|
|
1030
|
-
var openrouterCompletionChunkSchema = import_zod3.z.union([
|
|
1054
|
+
var OpenRouterCompletionChunkSchema = import_zod3.z.union([
|
|
1031
1055
|
import_zod3.z.object({
|
|
1056
|
+
id: import_zod3.z.string().optional(),
|
|
1057
|
+
model: import_zod3.z.string().optional(),
|
|
1032
1058
|
choices: import_zod3.z.array(
|
|
1033
1059
|
import_zod3.z.object({
|
|
1034
1060
|
text: import_zod3.z.string(),
|
|
1061
|
+
reasoning: import_zod3.z.string().nullish().optional(),
|
|
1035
1062
|
finish_reason: import_zod3.z.string().nullish(),
|
|
1036
1063
|
index: import_zod3.z.number(),
|
|
1037
1064
|
logprobs: import_zod3.z.object({
|
|
@@ -1046,7 +1073,7 @@ var openrouterCompletionChunkSchema = import_zod3.z.union([
|
|
|
1046
1073
|
completion_tokens: import_zod3.z.number()
|
|
1047
1074
|
}).optional().nullable()
|
|
1048
1075
|
}),
|
|
1049
|
-
|
|
1076
|
+
OpenRouterErrorResponseSchema
|
|
1050
1077
|
]);
|
|
1051
1078
|
|
|
1052
1079
|
// src/openrouter-facade.ts
|