@jambonz/llm 0.6.4 → 0.6.6

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.cjs CHANGED
@@ -131,6 +131,9 @@ async function* streamFromOpenAI(client, req, options) {
131
131
  if (req.cacheKey && options.includeCacheKey !== false) {
132
132
  body.prompt_cache_key = req.cacheKey;
133
133
  }
134
+ if (req.cacheKey && options.openRouterAutoCache && /^~?anthropic\//.test(req.model)) {
135
+ body.cache_control = { type: "ephemeral" };
136
+ }
134
137
  const effectiveMaxTokens = req.maxTokens ?? options.defaultMaxTokens;
135
138
  if (effectiveMaxTokens !== void 0) {
136
139
  const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
@@ -184,12 +187,20 @@ async function* streamFromOpenAI(client, req, options) {
184
187
  throw new Error(`OpenAI-compatible stream returned an error: ${message}`);
185
188
  }
186
189
  if (chunk.usage) {
187
- const cachedTokens = chunk.usage.prompt_tokens_details?.cached_tokens;
190
+ const details = chunk.usage.prompt_tokens_details;
191
+ const cachedTokens = details?.cached_tokens;
192
+ const cacheWriteTokens = details?.cache_write_tokens;
188
193
  usage = {
189
- ...chunk.usage.prompt_tokens !== void 0 ? { inputTokens: chunk.usage.prompt_tokens - (cachedTokens ?? 0) } : {},
194
+ ...chunk.usage.prompt_tokens !== void 0 ? {
195
+ inputTokens: Math.max(
196
+ 0,
197
+ chunk.usage.prompt_tokens - (cachedTokens ?? 0) - (cacheWriteTokens ?? 0)
198
+ )
199
+ } : {},
190
200
  ...chunk.usage.completion_tokens !== void 0 ? { outputTokens: chunk.usage.completion_tokens } : {},
191
201
  ...chunk.usage.total_tokens !== void 0 ? { totalTokens: chunk.usage.total_tokens } : {},
192
- ...cachedTokens !== void 0 ? { cacheReadTokens: cachedTokens } : {}
202
+ ...cachedTokens !== void 0 ? { cacheReadTokens: cachedTokens } : {},
203
+ ...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {}
193
204
  };
194
205
  }
195
206
  const choice = chunk.choices?.[0];
@@ -555,10 +566,13 @@ var OpenAIAdapter = class {
555
566
  vendor = openAIManifest.vendor;
556
567
  acceptedAuth = ["apiKey"];
557
568
  client;
569
+ /** baseURL is OpenRouter: enables its automatic prompt caching for Anthropic models. */
570
+ isOpenRouter = false;
558
571
  init(auth, client) {
559
572
  if (!auth.apiKey) {
560
573
  throw new Error("OpenAIAdapter: apiKey is required");
561
574
  }
575
+ this.isOpenRouter = /(^|\/\/|\.)openrouter\.ai(\/|:|$)/i.test(auth.baseURL ?? "");
562
576
  this.client = new import_openai.default({
563
577
  apiKey: auth.apiKey,
564
578
  ...auth.baseURL ? { baseURL: auth.baseURL } : {},
@@ -570,7 +584,8 @@ var OpenAIAdapter = class {
570
584
  return streamFromOpenAI(this.ensureClient(), req, {
571
585
  knownModels: this.knownModels(),
572
586
  vendorMetadataExtractor: OPENAI_METADATA_EXTRACTOR,
573
- includeCacheKey: this.forwardCacheKey()
587
+ includeCacheKey: this.forwardCacheKey(),
588
+ openRouterAutoCache: this.isOpenRouter
574
589
  });
575
590
  }
576
591
  appendAssistantToolCall(history, toolCalls, assistantText) {