@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.js CHANGED
@@ -86,6 +86,9 @@ async function* streamFromOpenAI(client, req, options) {
86
86
  if (req.cacheKey && options.includeCacheKey !== false) {
87
87
  body.prompt_cache_key = req.cacheKey;
88
88
  }
89
+ if (req.cacheKey && options.openRouterAutoCache && /^~?anthropic\//.test(req.model)) {
90
+ body.cache_control = { type: "ephemeral" };
91
+ }
89
92
  const effectiveMaxTokens = req.maxTokens ?? options.defaultMaxTokens;
90
93
  if (effectiveMaxTokens !== void 0) {
91
94
  const param = options.tokensParam ?? (needsMaxCompletionTokens(req.model) ? "max_completion_tokens" : "max_tokens");
@@ -139,12 +142,20 @@ async function* streamFromOpenAI(client, req, options) {
139
142
  throw new Error(`OpenAI-compatible stream returned an error: ${message}`);
140
143
  }
141
144
  if (chunk.usage) {
142
- const cachedTokens = chunk.usage.prompt_tokens_details?.cached_tokens;
145
+ const details = chunk.usage.prompt_tokens_details;
146
+ const cachedTokens = details?.cached_tokens;
147
+ const cacheWriteTokens = details?.cache_write_tokens;
143
148
  usage = {
144
- ...chunk.usage.prompt_tokens !== void 0 ? { inputTokens: chunk.usage.prompt_tokens - (cachedTokens ?? 0) } : {},
149
+ ...chunk.usage.prompt_tokens !== void 0 ? {
150
+ inputTokens: Math.max(
151
+ 0,
152
+ chunk.usage.prompt_tokens - (cachedTokens ?? 0) - (cacheWriteTokens ?? 0)
153
+ )
154
+ } : {},
145
155
  ...chunk.usage.completion_tokens !== void 0 ? { outputTokens: chunk.usage.completion_tokens } : {},
146
156
  ...chunk.usage.total_tokens !== void 0 ? { totalTokens: chunk.usage.total_tokens } : {},
147
- ...cachedTokens !== void 0 ? { cacheReadTokens: cachedTokens } : {}
157
+ ...cachedTokens !== void 0 ? { cacheReadTokens: cachedTokens } : {},
158
+ ...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {}
148
159
  };
149
160
  }
150
161
  const choice = chunk.choices?.[0];
@@ -510,10 +521,13 @@ var OpenAIAdapter = class {
510
521
  vendor = openAIManifest.vendor;
511
522
  acceptedAuth = ["apiKey"];
512
523
  client;
524
+ /** baseURL is OpenRouter: enables its automatic prompt caching for Anthropic models. */
525
+ isOpenRouter = false;
513
526
  init(auth, client) {
514
527
  if (!auth.apiKey) {
515
528
  throw new Error("OpenAIAdapter: apiKey is required");
516
529
  }
530
+ this.isOpenRouter = /(^|\/\/|\.)openrouter\.ai(\/|:|$)/i.test(auth.baseURL ?? "");
517
531
  this.client = new OpenAI({
518
532
  apiKey: auth.apiKey,
519
533
  ...auth.baseURL ? { baseURL: auth.baseURL } : {},
@@ -525,7 +539,8 @@ var OpenAIAdapter = class {
525
539
  return streamFromOpenAI(this.ensureClient(), req, {
526
540
  knownModels: this.knownModels(),
527
541
  vendorMetadataExtractor: OPENAI_METADATA_EXTRACTOR,
528
- includeCacheKey: this.forwardCacheKey()
542
+ includeCacheKey: this.forwardCacheKey(),
543
+ openRouterAutoCache: this.isOpenRouter
529
544
  });
530
545
  }
531
546
  appendAssistantToolCall(history, toolCalls, assistantText) {