@openrouter/ai-sdk-provider 2.2.4 → 2.3.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
@@ -151,6 +151,25 @@ type OpenRouterChatSettings = {
151
151
  */
152
152
  engine?: Engine;
153
153
  };
154
+ /**
155
+ * Enable Anthropic automatic prompt caching by setting a top-level cache_control
156
+ * directive on the request body. When set to `{ type: 'ephemeral' }`, Anthropic
157
+ * will automatically cache eligible content in your prompts.
158
+ *
159
+ * Only works with Anthropic models through OpenRouter.
160
+ *
161
+ * @see https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching
162
+ * @see https://openrouter.ai/docs
163
+ */
164
+ cache_control?: {
165
+ type: 'ephemeral';
166
+ /**
167
+ * Optional time-to-live for the cache entry.
168
+ * - `'5m'` — 5 minutes (default when omitted)
169
+ * - `'1h'` — 1 hour
170
+ */
171
+ ttl?: '5m' | '1h';
172
+ };
154
173
  /**
155
174
  * Debug options for troubleshooting API requests.
156
175
  * Only works with streaming requests.
package/dist/index.d.ts CHANGED
@@ -151,6 +151,25 @@ type OpenRouterChatSettings = {
151
151
  */
152
152
  engine?: Engine;
153
153
  };
154
+ /**
155
+ * Enable Anthropic automatic prompt caching by setting a top-level cache_control
156
+ * directive on the request body. When set to `{ type: 'ephemeral' }`, Anthropic
157
+ * will automatically cache eligible content in your prompts.
158
+ *
159
+ * Only works with Anthropic models through OpenRouter.
160
+ *
161
+ * @see https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching
162
+ * @see https://openrouter.ai/docs
163
+ */
164
+ cache_control?: {
165
+ type: 'ephemeral';
166
+ /**
167
+ * Optional time-to-live for the cache entry.
168
+ * - `'5m'` — 5 minutes (default when omitted)
169
+ * - `'1h'` — 1 hour
170
+ */
171
+ ttl?: '5m' | '1h';
172
+ };
154
173
  /**
155
174
  * Debug options for troubleshooting API requests.
156
175
  * Only works with streaming requests.
package/dist/index.js CHANGED
@@ -2282,9 +2282,58 @@ var OpenRouterErrorResponseSchema = import_v42.z.object({
2282
2282
  param: import_v42.z.any().nullable().optional().default(null)
2283
2283
  }).passthrough()
2284
2284
  }).passthrough();
2285
+ function extractErrorMessage(data) {
2286
+ const error = data.error;
2287
+ const metadata = error.metadata;
2288
+ if (!metadata) {
2289
+ return data.error.message;
2290
+ }
2291
+ const parts = [];
2292
+ if (typeof metadata.provider_name === "string" && metadata.provider_name) {
2293
+ parts.push(`[${metadata.provider_name}]`);
2294
+ }
2295
+ const raw = metadata.raw;
2296
+ const rawMessage = extractRawMessage(raw);
2297
+ if (rawMessage && rawMessage !== data.error.message) {
2298
+ parts.push(rawMessage);
2299
+ } else {
2300
+ parts.push(data.error.message);
2301
+ }
2302
+ return parts.join(" ");
2303
+ }
2304
+ function extractRawMessage(raw) {
2305
+ if (typeof raw === "string") {
2306
+ try {
2307
+ const parsed = JSON.parse(raw);
2308
+ if (typeof parsed === "object" && parsed !== null) {
2309
+ return extractRawMessage(parsed);
2310
+ }
2311
+ return raw;
2312
+ } catch (e) {
2313
+ return raw;
2314
+ }
2315
+ }
2316
+ if (typeof raw !== "object" || raw === null) {
2317
+ return void 0;
2318
+ }
2319
+ const obj = raw;
2320
+ for (const field of ["message", "error", "detail", "details", "msg"]) {
2321
+ const value = obj[field];
2322
+ if (typeof value === "string" && value.length > 0) {
2323
+ return value;
2324
+ }
2325
+ if (typeof value === "object" && value !== null) {
2326
+ const nested = extractRawMessage(value);
2327
+ if (nested) {
2328
+ return nested;
2329
+ }
2330
+ }
2331
+ }
2332
+ return void 0;
2333
+ }
2285
2334
  var openrouterFailedResponseHandler = createJsonErrorResponseHandler({
2286
2335
  errorSchema: OpenRouterErrorResponseSchema,
2287
- errorToMessage: (data) => data.error.message
2336
+ errorToMessage: extractErrorMessage
2288
2337
  });
2289
2338
 
2290
2339
  // src/schemas/provider-metadata.ts
@@ -3130,7 +3179,9 @@ var OpenRouterChatLanguageModel = class {
3130
3179
  // Provider routing settings:
3131
3180
  provider: this.settings.provider,
3132
3181
  // Debug settings:
3133
- debug: this.settings.debug
3182
+ debug: this.settings.debug,
3183
+ // Anthropic automatic caching:
3184
+ cache_control: this.settings.cache_control
3134
3185
  }, this.config.extraBody), this.settings.extraBody);
3135
3186
  if (tools && tools.length > 0) {
3136
3187
  const mappedTools = tools.filter(
@@ -3151,10 +3202,11 @@ var OpenRouterChatLanguageModel = class {
3151
3202
  return baseArgs;
3152
3203
  }
3153
3204
  async doGenerate(options) {
3154
- var _a16, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
3205
+ var _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
3155
3206
  const providerOptions = options.providerOptions || {};
3156
3207
  const openrouterOptions = providerOptions.openrouter || {};
3157
- const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
3208
+ const _a16 = openrouterOptions, { cacheControl } = _a16, restOpenrouterOptions = __objRest(_a16, ["cacheControl"]);
3209
+ const args = __spreadValues(__spreadValues(__spreadValues({}, this.getArgs(options)), restOpenrouterOptions), cacheControl != null && !("cache_control" in restOpenrouterOptions) ? { cache_control: cacheControl } : {});
3158
3210
  const { value: responseValue, responseHeaders } = await postJsonToApi({
3159
3211
  url: this.config.url({
3160
3212
  path: "/chat/completions",
@@ -3191,7 +3243,7 @@ var OpenRouterChatLanguageModel = class {
3191
3243
  });
3192
3244
  }
3193
3245
  const usageInfo = response.usage ? computeTokenUsage(response.usage) : emptyUsage();
3194
- const reasoningDetails = (_a16 = choice.message.reasoning_details) != null ? _a16 : [];
3246
+ const reasoningDetails = (_b16 = choice.message.reasoning_details) != null ? _b16 : [];
3195
3247
  const reasoning = reasoningDetails.length > 0 ? reasoningDetails.map((detail) => {
3196
3248
  switch (detail.type) {
3197
3249
  case "reasoning.text" /* Text */: {
@@ -3260,9 +3312,9 @@ var OpenRouterChatLanguageModel = class {
3260
3312
  for (const toolCall of choice.message.tool_calls) {
3261
3313
  content.push({
3262
3314
  type: "tool-call",
3263
- toolCallId: (_b16 = toolCall.id) != null ? _b16 : generateId(),
3315
+ toolCallId: (_c = toolCall.id) != null ? _c : generateId(),
3264
3316
  toolName: toolCall.function.name,
3265
- input: (_c = toolCall.function.arguments) != null ? _c : "{}",
3317
+ input: (_d = toolCall.function.arguments) != null ? _d : "{}",
3266
3318
  providerMetadata: !reasoningDetailsAttachedToToolCall ? {
3267
3319
  openrouter: {
3268
3320
  reasoning_details: reasoningDetails
@@ -3289,19 +3341,19 @@ var OpenRouterChatLanguageModel = class {
3289
3341
  sourceType: "url",
3290
3342
  id: annotation.url_citation.url,
3291
3343
  url: annotation.url_citation.url,
3292
- title: (_d = annotation.url_citation.title) != null ? _d : "",
3344
+ title: (_e = annotation.url_citation.title) != null ? _e : "",
3293
3345
  providerMetadata: {
3294
3346
  openrouter: {
3295
- content: (_e = annotation.url_citation.content) != null ? _e : "",
3296
- startIndex: (_f = annotation.url_citation.start_index) != null ? _f : 0,
3297
- endIndex: (_g = annotation.url_citation.end_index) != null ? _g : 0
3347
+ content: (_f = annotation.url_citation.content) != null ? _f : "",
3348
+ startIndex: (_g = annotation.url_citation.start_index) != null ? _g : 0,
3349
+ endIndex: (_h = annotation.url_citation.end_index) != null ? _h : 0
3298
3350
  }
3299
3351
  }
3300
3352
  });
3301
3353
  }
3302
3354
  }
3303
3355
  }
3304
- const fileAnnotations = (_h = choice.message.annotations) == null ? void 0 : _h.filter(
3356
+ const fileAnnotations = (_i = choice.message.annotations) == null ? void 0 : _i.filter(
3305
3357
  (a) => a.type === "file"
3306
3358
  );
3307
3359
  const hasToolCalls = choice.message.tool_calls && choice.message.tool_calls.length > 0;
@@ -3309,7 +3361,7 @@ var OpenRouterChatLanguageModel = class {
3309
3361
  (d) => d.type === "reasoning.encrypted" /* Encrypted */ && d.data
3310
3362
  );
3311
3363
  const shouldOverrideFinishReason = hasToolCalls && hasEncryptedReasoning && choice.finish_reason === "stop";
3312
- const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_i = choice.finish_reason) != null ? _i : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3364
+ const effectiveFinishReason = shouldOverrideFinishReason ? createFinishReason("tool-calls", (_j = choice.finish_reason) != null ? _j : void 0) : mapOpenRouterFinishReason(choice.finish_reason);
3313
3365
  return {
3314
3366
  content,
3315
3367
  finishReason: effectiveFinishReason,
@@ -3317,22 +3369,22 @@ var OpenRouterChatLanguageModel = class {
3317
3369
  warnings: [],
3318
3370
  providerMetadata: {
3319
3371
  openrouter: OpenRouterProviderMetadataSchema.parse({
3320
- provider: (_j = response.provider) != null ? _j : "",
3321
- reasoning_details: (_k = choice.message.reasoning_details) != null ? _k : [],
3372
+ provider: (_k = response.provider) != null ? _k : "",
3373
+ reasoning_details: (_l = choice.message.reasoning_details) != null ? _l : [],
3322
3374
  annotations: fileAnnotations && fileAnnotations.length > 0 ? fileAnnotations : void 0,
3323
3375
  usage: __spreadValues(__spreadValues(__spreadValues(__spreadValues({
3324
- promptTokens: (_l = usageInfo.inputTokens.total) != null ? _l : 0,
3325
- completionTokens: (_m = usageInfo.outputTokens.total) != null ? _m : 0,
3326
- totalTokens: ((_n = usageInfo.inputTokens.total) != null ? _n : 0) + ((_o = usageInfo.outputTokens.total) != null ? _o : 0)
3327
- }, ((_p = response.usage) == null ? void 0 : _p.cost) != null ? { cost: response.usage.cost } : {}), ((_r = (_q = response.usage) == null ? void 0 : _q.prompt_tokens_details) == null ? void 0 : _r.cached_tokens) != null ? {
3376
+ promptTokens: (_m = usageInfo.inputTokens.total) != null ? _m : 0,
3377
+ completionTokens: (_n = usageInfo.outputTokens.total) != null ? _n : 0,
3378
+ totalTokens: ((_o = usageInfo.inputTokens.total) != null ? _o : 0) + ((_p = usageInfo.outputTokens.total) != null ? _p : 0)
3379
+ }, ((_q = response.usage) == null ? void 0 : _q.cost) != null ? { cost: response.usage.cost } : {}), ((_s = (_r = response.usage) == null ? void 0 : _r.prompt_tokens_details) == null ? void 0 : _s.cached_tokens) != null ? {
3328
3380
  promptTokensDetails: {
3329
3381
  cachedTokens: response.usage.prompt_tokens_details.cached_tokens
3330
3382
  }
3331
- } : {}), ((_t = (_s = response.usage) == null ? void 0 : _s.completion_tokens_details) == null ? void 0 : _t.reasoning_tokens) != null ? {
3383
+ } : {}), ((_u = (_t = response.usage) == null ? void 0 : _t.completion_tokens_details) == null ? void 0 : _u.reasoning_tokens) != null ? {
3332
3384
  completionTokensDetails: {
3333
3385
  reasoningTokens: response.usage.completion_tokens_details.reasoning_tokens
3334
3386
  }
3335
- } : {}), ((_v = (_u = response.usage) == null ? void 0 : _u.cost_details) == null ? void 0 : _v.upstream_inference_cost) != null ? {
3387
+ } : {}), ((_w = (_v = response.usage) == null ? void 0 : _v.cost_details) == null ? void 0 : _w.upstream_inference_cost) != null ? {
3336
3388
  costDetails: {
3337
3389
  upstreamInferenceCost: response.usage.cost_details.upstream_inference_cost
3338
3390
  }
@@ -3348,10 +3400,11 @@ var OpenRouterChatLanguageModel = class {
3348
3400
  };
3349
3401
  }
3350
3402
  async doStream(options) {
3351
- var _a16;
3403
+ var _b16;
3352
3404
  const providerOptions = options.providerOptions || {};
3353
3405
  const openrouterOptions = providerOptions.openrouter || {};
3354
- const args = __spreadValues(__spreadValues({}, this.getArgs(options)), openrouterOptions);
3406
+ const _a16 = openrouterOptions, { cacheControl } = _a16, restOpenrouterOptions = __objRest(_a16, ["cacheControl"]);
3407
+ const args = __spreadValues(__spreadValues(__spreadValues({}, this.getArgs(options)), restOpenrouterOptions), cacheControl != null && !("cache_control" in restOpenrouterOptions) ? { cache_control: cacheControl } : {});
3355
3408
  const { value: response, responseHeaders } = await postJsonToApi({
3356
3409
  url: this.config.url({
3357
3410
  path: "/chat/completions",
@@ -3363,7 +3416,7 @@ var OpenRouterChatLanguageModel = class {
3363
3416
  // only include stream_options when in strict compatibility mode:
3364
3417
  stream_options: this.config.compatibility === "strict" ? __spreadValues({
3365
3418
  include_usage: true
3366
- }, ((_a16 = this.settings.usage) == null ? void 0 : _a16.include) ? { include_usage: true } : {}) : void 0
3419
+ }, ((_b16 = this.settings.usage) == null ? void 0 : _b16.include) ? { include_usage: true } : {}) : void 0
3367
3420
  }),
3368
3421
  failedResponseHandler: openrouterFailedResponseHandler,
3369
3422
  successfulResponseHandler: createEventSourceResponseHandler(
@@ -3403,7 +3456,7 @@ var OpenRouterChatLanguageModel = class {
3403
3456
  stream: response.pipeThrough(
3404
3457
  new TransformStream({
3405
3458
  transform(chunk, controller) {
3406
- var _a17, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
3459
+ var _a17, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
3407
3460
  if (options.includeRawChunks) {
3408
3461
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
3409
3462
  }
@@ -3440,7 +3493,7 @@ var OpenRouterChatLanguageModel = class {
3440
3493
  Object.assign(usage.outputTokens, computed.outputTokens);
3441
3494
  rawUsage = value.usage;
3442
3495
  const promptTokens = (_a17 = value.usage.prompt_tokens) != null ? _a17 : 0;
3443
- const completionTokens = (_b16 = value.usage.completion_tokens) != null ? _b16 : 0;
3496
+ const completionTokens = (_b17 = value.usage.completion_tokens) != null ? _b17 : 0;
3444
3497
  openrouterUsage.promptTokens = promptTokens;
3445
3498
  if (value.usage.prompt_tokens_details) {
3446
3499
  openrouterUsage.promptTokensDetails = {
@@ -4556,7 +4609,7 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4556
4609
  }
4557
4610
 
4558
4611
  // src/version.ts
4559
- var VERSION2 = false ? "0.0.0-test" : "2.2.4";
4612
+ var VERSION2 = false ? "0.0.0-test" : "2.3.0";
4560
4613
 
4561
4614
  // src/provider.ts
4562
4615
  function createOpenRouter(options = {}) {