@juspay/neurolink 12.23.1 → 12.23.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.
@@ -215,9 +215,19 @@ export async function runNativeGenerateLoop(args, toolExecutionSummaries) {
215
215
  rawFinishReason = shaped.raw ?? rawFinishReason;
216
216
  }
217
217
  const usage = res.usage;
218
- inputTokens += readTotal(usage?.inputTokens);
219
218
  outputTokens += readTotal(usage?.outputTokens);
220
219
  const inShaped = usage?.inputTokens;
220
+ // `total` on the shaped input-tokens object is cache-INCLUSIVE (noCache +
221
+ // cacheRead + cacheWrite). Accumulating it into `inputTokens` — while ALSO
222
+ // accumulating cacheRead/cacheWrite below — double-billed every cached
223
+ // token: once folded into `input`, once again as the flat cache fields
224
+ // `calculateCost` prices separately. `noCache` is the disjoint figure
225
+ // `calculateCost` expects; fall back to the inclusive total only when a
226
+ // provider hasn't populated `noCache` (i.e. it never reports cache usage).
227
+ inputTokens +=
228
+ typeof inShaped?.noCache === "number"
229
+ ? inShaped.noCache
230
+ : readTotal(usage?.inputTokens);
221
231
  cacheReadTokens += inShaped?.cacheRead ?? 0;
222
232
  cacheWriteTokens += inShaped?.cacheWrite ?? 0;
223
233
  const calls = parts.filter((p) => p.type === "tool-call");
@@ -1564,7 +1564,13 @@ export class AnthropicProvider extends BaseProvider {
1564
1564
  usage: {
1565
1565
  input: loop.inputTokens,
1566
1566
  output: loop.outputTokens,
1567
- total: loop.inputTokens + loop.outputTokens,
1567
+ // `inputTokens` is now the disjoint (uncached) figure, so cache
1568
+ // tokens must be added back in to keep `total` billing-complete —
1569
+ // they are additive on top of input under Anthropic's convention.
1570
+ total: loop.inputTokens +
1571
+ loop.outputTokens +
1572
+ loop.cacheReadTokens +
1573
+ loop.cacheWriteTokens,
1568
1574
  ...(loop.cacheReadTokens
1569
1575
  ? { cacheReadTokens: loop.cacheReadTokens }
1570
1576
  : {}),
@@ -1055,7 +1055,14 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
1055
1055
  usage: {
1056
1056
  input: inputTokens,
1057
1057
  output: outputTokens,
1058
- total: inputTokens + outputTokens,
1058
+ // `inputTokens` is the disjoint (uncached) figure — doGenerate
1059
+ // already subtracts the overlapping prompt_tokens_details.cached_tokens
1060
+ // subset before handing it to the loop — so cache tokens must be
1061
+ // added back in here to keep `total` billing-complete.
1062
+ total: inputTokens +
1063
+ outputTokens +
1064
+ loop.cacheReadTokens +
1065
+ loop.cacheWriteTokens,
1059
1066
  // doGenerate reads prompt_tokens_details.cached_tokens, and the loop
1060
1067
  // carries the counters out; discarding them here billed cached input
1061
1068
  // at the full rate in calculateCost and made cache effectiveness
@@ -1492,10 +1499,18 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
1492
1499
  if (!loopPromise) {
1493
1500
  const input = part.usage.inputTokens.total ?? 0;
1494
1501
  const output = part.usage.outputTokens.total ?? 0;
1502
+ // `total` is cache-INCLUSIVE (OpenAI-style prompt_tokens), so the
1503
+ // cached portion has to be split out here the same way
1504
+ // doGenerate/toDeferredUsage do — otherwise this branch bills the
1505
+ // cached tokens at the full input rate instead of the cheaper
1506
+ // cacheRead rate. Clamped like the other call sites in this file
1507
+ // in case a gateway reports cacheRead > total.
1508
+ const cacheRead = Math.min(part.usage.inputTokens.cacheRead ?? 0, input);
1495
1509
  resolveUsage({
1496
- promptTokens: input,
1510
+ promptTokens: input - cacheRead,
1497
1511
  completionTokens: output,
1498
1512
  totalTokens: input + output,
1513
+ ...(cacheRead > 0 ? { cacheReadTokens: cacheRead } : {}),
1499
1514
  });
1500
1515
  resolveFinish(part.finishReason.unified);
1501
1516
  }