claude-code-cache-fix 2.0.1 → 2.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/preload.mjs +28 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-cache-fix",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Fixes prompt cache regression in Claude Code that causes up to 20x cost increase on resumed sessions",
5
5
  "type": "module",
6
6
  "exports": "./preload.mjs",
package/preload.mjs CHANGED
@@ -752,9 +752,10 @@ function normalizeToolUseInputsInBody(body) {
752
752
  //
753
753
  // This sticky extension maintains per-session state tracking where markers
754
754
  // have appeared in prior turns, and reinstates them on future turns as
755
- // additive preservation. Up to 3 historical message-level markers are
755
+ // additive preservation. Up to 2 historical message-level markers are
756
756
  // tracked (Anthropic's hard limit is 4 cache_control markers total — 1 for
757
- // system[2] + 3 for message-level breakpoints). When a historical position
757
+ // system[2] + 1 canonical from cache_control_normalize + 2 historical from
758
+ // sticky = 4). When a historical position
758
759
  // would exceed the cap, the oldest tracked entry is dropped (LRU).
759
760
  //
760
761
  // Messages are identified by a stable hash so that compaction rewrites /
@@ -772,7 +773,10 @@ function normalizeToolUseInputsInBody(body) {
772
773
  // --------------------------------------------------------------------------
773
774
 
774
775
  const CACHE_CONTROL_STICKY_DIR = join(homedir(), ".claude", "cache-fix-state");
775
- const CACHE_CONTROL_STICKY_MAX_POSITIONS = 3;
776
+ // Anthropic hard limit: 4 cache_control markers total per request.
777
+ // CC uses 1 on system[2] + cache_control_normalize places 1 on last user msg = 2 reserved.
778
+ // Sticky can use at most 2 historical positions to stay within the 4-marker cap.
779
+ const CACHE_CONTROL_STICKY_MAX_POSITIONS = 2;
776
780
  const CACHE_CONTROL_STICKY_DEFAULT_MARKER = { type: "ephemeral", ttl: "1h" };
777
781
 
778
782
  /**
@@ -938,10 +942,30 @@ function updateCacheControlStickyState(body, priorState) {
938
942
  capped = capped.slice(capped.length - CACHE_CONTROL_STICKY_MAX_POSITIONS);
939
943
  }
940
944
 
945
+ // Count existing cache_control markers across the entire body (system +
946
+ // messages) so sticky never pushes the total past Anthropic's hard limit
947
+ // of 4. CC may use 2 or 3 of those slots itself depending on version.
948
+ const ANTHROPIC_MARKER_LIMIT = 4;
949
+ let existingMarkers = 0;
950
+ if (Array.isArray(body.system)) {
951
+ for (const b of body.system) {
952
+ if (b && typeof b === "object" && b.cache_control) existingMarkers++;
953
+ }
954
+ }
955
+ for (const msg of body.messages) {
956
+ if (!msg || !Array.isArray(msg.content)) continue;
957
+ for (const b of msg.content) {
958
+ if (b && typeof b === "object" && b.cache_control) existingMarkers++;
959
+ }
960
+ }
961
+ const stickyBudget = Math.max(0, ANTHROPIC_MARKER_LIMIT - existingMarkers);
962
+
941
963
  // Compute mutations: for each tracked hash present in this body, if the
942
964
  // message doesn't already have any marker, add one at its last block.
965
+ // Stop once the sticky budget is exhausted.
943
966
  const mutations = [];
944
967
  for (const pos of capped) {
968
+ if (mutations.length >= stickyBudget) break;
945
969
  const msgIdx = hashToMsgIdx.get(pos.msg_hash);
946
970
  if (msgIdx === undefined) continue;
947
971
  const msg = body.messages[msgIdx];
@@ -2354,7 +2378,7 @@ globalThis.fetch = async function (url, options) {
2354
2378
  // the tail of each new user turn, the previous position loses the ~43
2355
2379
  // bytes of cache_control framing — a tail-of-message byte drift that
2356
2380
  // breaks every downstream cached block. This extension tracks marker
2357
- // positions by stable message-hash across turns (up to 3) and re-adds
2381
+ // positions by stable message-hash across turns (up to 2) and re-adds
2358
2382
  // them on future bodies. Runs AFTER cache_control_normalize (when
2359
2383
  // present) so normalize pins the canonical tail-marker first and
2360
2384
  // sticky re-adds the historical ones. State file is per-project at