@rulvar/anthropic 1.131.0 → 1.133.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.ts CHANGED
@@ -172,6 +172,13 @@ interface TurnMapping {
172
172
  * request of a pause_turn absorption (RV905).
173
173
  */
174
174
  responseId?: string;
175
+ /**
176
+ * The SEGMENT's own normalized usage (RV1003): a paused segment
177
+ * yields no finish, so this is how its counts reach the adapter's
178
+ * whole-turn accumulation. The terminal finish EVENT carries the turn
179
+ * total (usagePrior folded in); this field stays segment-only.
180
+ */
181
+ usage: Usage;
175
182
  }
176
183
  /**
177
184
  * Maps one Messages API stream into ChatEvents, yielding each canonical
@@ -203,6 +210,17 @@ declare function mapAnthropicStream(stream: AsyncIterable<AnthropicStreamEvent>,
203
210
  wirePrior?: {
204
211
  responseIds: Array<string | undefined>;
205
212
  };
213
+ /**
214
+ * Accumulated usage of the PRIOR pause_turn segments of this turn
215
+ * (RV1003): the terminal finish must speak for the WHOLE logical
216
+ * turn, because core sums the per-segment mid-stream reports and
217
+ * verifies them against the finish total; a finish carrying only
218
+ * the last segment's counts turns a legitimate absorption into a
219
+ * usage-invariant kill and loses the paid segments from the money.
220
+ * Absent on the first segment, so an unsegmented finish stays
221
+ * byte-identical.
222
+ */
223
+ usagePrior?: Usage;
206
224
  }): AsyncGenerator<ChatEvent, TurnMapping>;
207
225
  /**
208
226
  * Projects an SDK/API error into the retryable WireError vocabulary:
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import Anthropic from "@anthropic-ai/sdk";
2
- import { ConfigError, createCanonicalIdMinter, isStrictCompatibleSchema } from "@rulvar/core";
2
+ import { ConfigError, createCanonicalIdMinter, isStrictCompatibleSchema, sumUsage } from "@rulvar/core";
3
3
  //#region src/caps.ts
4
4
  const ALL_EFFORTS = [
5
5
  "low",
@@ -490,7 +490,13 @@ async function* mapAnthropicStream(stream, ids, options) {
490
490
  const mapping = {
491
491
  assistantContent: [],
492
492
  pauseTurn: false,
493
- finished: false
493
+ finished: false,
494
+ usage: {
495
+ inputTokens: 0,
496
+ outputTokens: 0,
497
+ cacheReadTokens: 0,
498
+ cacheWriteTokens: 0
499
+ }
494
500
  };
495
501
  let usage = {
496
502
  inputTokens: 0,
@@ -620,6 +626,7 @@ async function* mapAnthropicStream(stream, ids, options) {
620
626
  const mapped = mapStopReason(stopReason, stopDetails);
621
627
  if (mapped.pauseTurn) {
622
628
  mapping.pauseTurn = true;
629
+ mapping.usage = usage;
623
630
  if (responseId !== void 0) mapping.responseId = responseId;
624
631
  return mapping;
625
632
  }
@@ -636,15 +643,17 @@ async function* mapAnthropicStream(stream, ids, options) {
636
643
  yield {
637
644
  type: "finish",
638
645
  finish: mapped.finish ?? { reason: "stop" },
639
- usage,
646
+ usage: options?.usagePrior === void 0 ? usage : sumUsage(options.usagePrior, usage),
640
647
  providerMetadata
641
648
  };
642
649
  mapping.finished = true;
650
+ mapping.usage = usage;
643
651
  if (responseId !== void 0) mapping.responseId = responseId;
644
652
  return mapping;
645
653
  }
646
654
  default: break;
647
655
  }
656
+ mapping.usage = usage;
648
657
  return mapping;
649
658
  }
650
659
  /**
@@ -835,7 +844,9 @@ function anthropic(options = {}) {
835
844
  },
836
845
  async *stream(req, signal) {
837
846
  const info = infoFor(req.model);
838
- const pauseCap = typeof req.providerOptions?.anthropic?.pauseTurnMaxContinuations === "number" ? req.providerOptions.anthropic.pauseTurnMaxContinuations : 5;
847
+ const rawPauseCap = req.providerOptions?.anthropic?.pauseTurnMaxContinuations;
848
+ if (rawPauseCap !== void 0 && (typeof rawPauseCap !== "number" || !Number.isSafeInteger(rawPauseCap) || rawPauseCap < 0)) throw new ConfigError(`pauseTurnMaxContinuations must be a nonnegative safe integer, got ${typeof rawPauseCap === "number" ? String(rawPauseCap) : typeof rawPauseCap === "string" ? `'${rawPauseCap}'` : JSON.stringify(rawPauseCap) ?? "a non-numeric value"}; an invalid cap never disarms the continuation bound, because every absorbed continuation is a paid wire request`);
849
+ const pauseCap = rawPauseCap ?? 5;
839
850
  let params = buildAnthropicParams(req, {
840
851
  ids,
841
852
  maxOutputTokens: info.caps.maxOutputTokens,
@@ -844,6 +855,7 @@ function anthropic(options = {}) {
844
855
  let continuations = 0;
845
856
  const carryRetained = [];
846
857
  const priorSegmentIds = [];
858
+ let absorbedUsage;
847
859
  while (true) {
848
860
  let stream;
849
861
  try {
@@ -861,7 +873,8 @@ function anthropic(options = {}) {
861
873
  }
862
874
  const mapper = mapAnthropicStream(stream, ids, {
863
875
  carryRetained,
864
- ...priorSegmentIds.length === 0 ? {} : { wirePrior: { responseIds: priorSegmentIds } }
876
+ ...priorSegmentIds.length === 0 ? {} : { wirePrior: { responseIds: priorSegmentIds } },
877
+ ...absorbedUsage === void 0 ? {} : { usagePrior: absorbedUsage }
865
878
  });
866
879
  let mapping;
867
880
  try {
@@ -897,6 +910,7 @@ function anthropic(options = {}) {
897
910
  }
898
911
  carryRetained.push(...mapping.assistantContent.filter((block) => block.type === "thinking" || block.type === "redacted_thinking"));
899
912
  priorSegmentIds.push(mapping.responseId);
913
+ absorbedUsage = absorbedUsage === void 0 ? mapping.usage : sumUsage(absorbedUsage, mapping.usage);
900
914
  continuations += 1;
901
915
  if (continuations > pauseCap) {
902
916
  yield {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/anthropic",
3
- "version": "1.131.0",
3
+ "version": "1.133.0",
4
4
  "description": "Rulvar first-class provider adapter over @anthropic-ai/sdk.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -23,13 +23,13 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@anthropic-ai/sdk": "^0.115.0",
26
- "@rulvar/core": "1.131.0"
26
+ "@rulvar/core": "1.133.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^22.20.1",
30
30
  "tsdown": "^0.22.14",
31
31
  "typescript": "~6.0.3",
32
- "@rulvar/testing": "1.131.0"
32
+ "@rulvar/testing": "1.133.0"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",