claude-code-infinite 1.0.33 → 1.0.35

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 (105) hide show
  1. package/README.md +60 -2
  2. package/dist/cli-main.js +24 -9
  3. package/dist/cli-main.js.map +1 -1
  4. package/dist/cli.js +23 -10
  5. package/dist/cli.js.map +1 -1
  6. package/dist/hooks.d.ts +20 -0
  7. package/dist/hooks.d.ts.map +1 -1
  8. package/dist/hooks.js +34 -4
  9. package/dist/hooks.js.map +1 -1
  10. package/dist/host-session.d.ts +12 -0
  11. package/dist/host-session.d.ts.map +1 -0
  12. package/dist/host-session.js +12 -0
  13. package/dist/host-session.js.map +1 -0
  14. package/dist/image-refs.d.ts +24 -2
  15. package/dist/image-refs.d.ts.map +1 -1
  16. package/dist/image-refs.js +67 -20
  17. package/dist/image-refs.js.map +1 -1
  18. package/dist/index-wait-413.d.ts +26 -0
  19. package/dist/index-wait-413.d.ts.map +1 -0
  20. package/dist/index-wait-413.js +113 -0
  21. package/dist/index-wait-413.js.map +1 -0
  22. package/dist/memtree-finder.d.ts +70 -6
  23. package/dist/memtree-finder.d.ts.map +1 -1
  24. package/dist/memtree-finder.js +150 -20
  25. package/dist/memtree-finder.js.map +1 -1
  26. package/dist/memtree-handover.d.ts +13 -0
  27. package/dist/memtree-handover.d.ts.map +1 -0
  28. package/dist/memtree-handover.js +231 -0
  29. package/dist/memtree-handover.js.map +1 -0
  30. package/dist/memtree-mcp-config.d.ts +2 -2
  31. package/dist/memtree-mcp-config.d.ts.map +1 -1
  32. package/dist/memtree-mcp-config.js +8 -5
  33. package/dist/memtree-mcp-config.js.map +1 -1
  34. package/dist/memtree-mcp.d.ts +182 -2
  35. package/dist/memtree-mcp.d.ts.map +1 -1
  36. package/dist/memtree-mcp.js +357 -38
  37. package/dist/memtree-mcp.js.map +1 -1
  38. package/dist/memtree-newest.d.ts +31 -5
  39. package/dist/memtree-newest.d.ts.map +1 -1
  40. package/dist/memtree-newest.js +65 -13
  41. package/dist/memtree-newest.js.map +1 -1
  42. package/dist/memtree-times.d.ts +33 -0
  43. package/dist/memtree-times.d.ts.map +1 -1
  44. package/dist/memtree-times.js +77 -0
  45. package/dist/memtree-times.js.map +1 -1
  46. package/dist/memtree-tools.d.ts +19 -5
  47. package/dist/memtree-tools.d.ts.map +1 -1
  48. package/dist/memtree-tools.js +97 -23
  49. package/dist/memtree-tools.js.map +1 -1
  50. package/dist/memtree.d.ts +33 -0
  51. package/dist/memtree.d.ts.map +1 -1
  52. package/dist/memtree.js +92 -4
  53. package/dist/memtree.js.map +1 -1
  54. package/dist/network-failure.d.ts +28 -0
  55. package/dist/network-failure.d.ts.map +1 -0
  56. package/dist/network-failure.js +67 -0
  57. package/dist/network-failure.js.map +1 -0
  58. package/dist/prefix-store.d.ts +4 -0
  59. package/dist/prefix-store.d.ts.map +1 -1
  60. package/dist/prefix-store.js +8 -4
  61. package/dist/prefix-store.js.map +1 -1
  62. package/dist/project-trees.d.ts +15 -7
  63. package/dist/project-trees.d.ts.map +1 -1
  64. package/dist/project-trees.js +20 -9
  65. package/dist/project-trees.js.map +1 -1
  66. package/dist/proxy.d.ts +85 -1
  67. package/dist/proxy.d.ts.map +1 -1
  68. package/dist/proxy.js +552 -44
  69. package/dist/proxy.js.map +1 -1
  70. package/dist/refusal-reason.d.ts +69 -0
  71. package/dist/refusal-reason.d.ts.map +1 -0
  72. package/dist/refusal-reason.js +131 -0
  73. package/dist/refusal-reason.js.map +1 -0
  74. package/dist/reqlog.d.ts +43 -0
  75. package/dist/reqlog.d.ts.map +1 -1
  76. package/dist/reqlog.js.map +1 -1
  77. package/dist/resume-guidance.d.ts +9 -3
  78. package/dist/resume-guidance.d.ts.map +1 -1
  79. package/dist/resume-guidance.js +9 -3
  80. package/dist/resume-guidance.js.map +1 -1
  81. package/dist/route-fallback.d.ts +79 -11
  82. package/dist/route-fallback.d.ts.map +1 -1
  83. package/dist/route-fallback.js +162 -38
  84. package/dist/route-fallback.js.map +1 -1
  85. package/dist/route-identity.d.ts +6 -2
  86. package/dist/route-identity.d.ts.map +1 -1
  87. package/dist/route-identity.js +209 -16
  88. package/dist/route-identity.js.map +1 -1
  89. package/dist/slow-upload.d.ts +40 -0
  90. package/dist/slow-upload.d.ts.map +1 -0
  91. package/dist/slow-upload.js +69 -0
  92. package/dist/slow-upload.js.map +1 -0
  93. package/dist/status-link.d.ts +18 -0
  94. package/dist/status-link.d.ts.map +1 -0
  95. package/dist/status-link.js +103 -0
  96. package/dist/status-link.js.map +1 -0
  97. package/dist/statusline.d.ts +51 -0
  98. package/dist/statusline.d.ts.map +1 -0
  99. package/dist/statusline.js +379 -0
  100. package/dist/statusline.js.map +1 -0
  101. package/dist/subagent-hint.d.ts +28 -0
  102. package/dist/subagent-hint.d.ts.map +1 -1
  103. package/dist/subagent-hint.js +37 -0
  104. package/dist/subagent-hint.js.map +1 -1
  105. package/package.json +1 -1
@@ -9,6 +9,14 @@ export function fitsFallbackBudget(inputTokens, outputTokens, budgetTokens, cont
9
9
  }
10
10
  /** How long a lane may wait for MemTree to finish indexing before refusing. */
11
11
  export const INDEX_WAIT_DEADLINE_MS = 10 * 60_000;
12
+ /**
13
+ * The most a lane waits for an index whose time left the server stated (a 413's
14
+ * Retry-After): longer estimates refuse at once, and later ones extend a wait only to here.
15
+ */
16
+ export const INDEX_WAIT_MAX_MS = 15 * 60_000;
17
+ /** A stated time left is waited for this much longer (estimates run over: 2026-11-09). */
18
+ export const INDEX_WAIT_MARGIN_RATIO = 0.5;
19
+ export const INDEX_WAIT_MARGIN_MS = 2 * 60_000;
12
20
  /** Seconds Claude Code waits between retries while the index catches up. */
13
21
  export const INDEX_WAIT_RETRY_AFTER_SECONDS = 30;
14
22
  export const FINAL_REFUSAL_MESSAGE = "MemTree couldn't fit this request in the model's context window. If MemTree is " +
@@ -25,27 +33,72 @@ export const FINAL_REFUSAL_MESSAGE = "MemTree couldn't fit this request in the m
25
33
  export class RouteFallbackFailures {
26
34
  capacity;
27
35
  indexWaitMs;
36
+ indexWaitMaxMs;
28
37
  failures = new Map();
29
- /** Lane -> when its index wait began (its deadline is fixed from then). */
38
+ /**
39
+ * Lane -> when its index wait began and when it ends; `over` once it ended but the
40
+ * strike table had no room to record the refusal (still refused, never extended).
41
+ */
30
42
  indexWaits = new Map();
31
- constructor(capacity = 128, indexWaitMs = INDEX_WAIT_DEADLINE_MS) {
43
+ /** Lane -> when it was last seen waiting for its index; a delivery does not clear it. */
44
+ indexWaitSeen = new Map();
45
+ constructor(capacity = 128,
46
+ /** A wait's length when the server stated no time left. */
47
+ indexWaitMs = INDEX_WAIT_DEADLINE_MS, indexWaitMaxMs = INDEX_WAIT_MAX_MS) {
32
48
  this.capacity = capacity;
33
49
  this.indexWaitMs = indexWaitMs;
50
+ this.indexWaitMaxMs = indexWaitMaxMs;
34
51
  }
35
52
  fail(lane, context = {}) {
36
53
  if (context.awaitingIndex) {
37
- const waiting = this.waitForIndex(lane, context.now ?? Date.now());
54
+ const waiting = this.waitForIndex(lane, context.now ?? Date.now(), context.indexSecondsLeft, context.refusalMessage);
38
55
  if (waiting)
39
56
  return waiting;
40
57
  }
41
- return this.strike(lane);
58
+ return this.strike(lane, context.refusalMessage);
59
+ }
60
+ /**
61
+ * Note MemTree saying the lane's index is still catching up (a held request's 413):
62
+ * starts the lane's wait, or extends it by the stated time left. False once waiting
63
+ * can no longer pay off (the estimate is past the cap, the wait's deadline passed, or
64
+ * the lane was refused), so a held request stops asking and is refused.
65
+ */
66
+ indexWaitOpen(lane, secondsLeft, now = Date.now()) {
67
+ return this.track(lane, now, secondsLeft) !== "closed";
68
+ }
69
+ /**
70
+ * indexWaitOpen, and when the lane's wait ends: its deadline (Infinity when no slot was
71
+ * free to track it), or undefined once closed.
72
+ */
73
+ indexWaitDeadline(lane, secondsLeft, now = Date.now()) {
74
+ const state = this.track(lane, now, secondsLeft);
75
+ if (state === "closed")
76
+ return undefined;
77
+ return state === "untracked" ? Infinity : this.indexWaits.get(lane).deadline;
78
+ }
79
+ /** Whether the lane is waiting for its index (a wait started, not yet ended). */
80
+ indexWaiting(lane) {
81
+ const wait = this.indexWaits.get(lane);
82
+ return wait !== undefined && !wait.over;
83
+ }
84
+ /** Whether the lane waits for its index now, or did at any time from `since` on. */
85
+ indexWaitSince(lane, since) {
86
+ return this.indexWaiting(lane) || (this.indexWaitSeen.get(lane) ?? -Infinity) >= since;
87
+ }
88
+ /** The time left MemTree last stated for the lane's index wait, if any. */
89
+ indexSecondsLeft(lane) {
90
+ return this.indexWaits.get(lane)?.secondsLeft;
91
+ }
92
+ /** Whether a stated time left is too long to wait for at all (refused at once). */
93
+ hopeless(secondsLeft) {
94
+ return secondsLeft !== undefined && secondsLeft * 1000 > this.indexWaitMaxMs;
42
95
  }
43
96
  succeeded(lane) {
44
97
  this.failures.delete(lane);
45
98
  this.indexWaits.delete(lane);
46
99
  }
47
100
  /** The bounded three-strike episode: 503, 503, then 400 until delivery. */
48
- strike(lane) {
101
+ strike(lane, message) {
49
102
  const previous = this.failures.get(lane);
50
103
  // Fail closed when full rather than evicting a lane and granting it
51
104
  // another retry budget. A successful lane frees its slot.
@@ -54,56 +107,118 @@ export class RouteFallbackFailures {
54
107
  if (previous !== undefined || this.failures.size < this.capacity) {
55
108
  this.failures.set(lane, attempt);
56
109
  }
57
- return attempt <= 2 ? retryError(attempt, "1", RETRY_MESSAGE) : refusal(attempt);
110
+ return attempt <= 2 ? retryError(attempt, "1", RETRY_MESSAGE) : refusal(attempt, message);
58
111
  }
59
112
  /**
60
- * A 503 while the lane's wait is within its deadline; a 400 once it passes.
61
- * The deadline is fixed when the wait starts and only a delivery clears it:
62
- * an expired wait becomes a terminal strike state, and an active wait is
63
- * never evicted. A lane already refused, or arriving while every wait slot
64
- * is active, gets no wait (undefined) and falls back to the strikes.
113
+ * A 503 while the lane's wait is within its deadline; a 400 once it passes, or at once
114
+ * for a stated time left past the cap. The deadline is set when the wait starts (the
115
+ * stated time plus a margin, else indexWaitMs); a later stated time may extend it up to
116
+ * indexWaitMaxMs from the start, and only a delivery clears it: an expired wait becomes
117
+ * a terminal strike state, and an active wait is never evicted. A lane already refused,
118
+ * or arriving while every wait slot is active, gets no wait (undefined) and falls back
119
+ * to the strikes.
65
120
  */
66
- waitForIndex(lane, now) {
121
+ waitForIndex(lane, now, secondsLeft, message) {
122
+ const state = this.track(lane, now, secondsLeft);
123
+ if (state === "untracked")
124
+ return undefined;
125
+ return state === "open" ? this.indexWaitError(lane, secondsLeft) : refusal(3, message);
126
+ }
127
+ /**
128
+ * Start or extend the lane's wait: "open" while the index may still land in time,
129
+ * "closed" once it may not (and the lane is refused until a delivery), "untracked"
130
+ * when every wait slot is taken (the strikes decide).
131
+ */
132
+ track(lane, now, secondsLeft) {
133
+ const state = this.trackWait(lane, now, secondsLeft);
134
+ if (state !== "closed")
135
+ this.seen(lane, now);
136
+ return state;
137
+ }
138
+ /** Note the lane waiting for its index at `now` (bounded: oldest first out). */
139
+ seen(lane, now) {
140
+ this.indexWaitSeen.delete(lane);
141
+ this.indexWaitSeen.set(lane, now);
142
+ if (this.indexWaitSeen.size > this.capacity) {
143
+ this.indexWaitSeen.delete(this.indexWaitSeen.keys().next().value);
144
+ }
145
+ }
146
+ trackWait(lane, now, secondsLeft) {
147
+ if ((this.failures.get(lane) ?? 0) >= 3)
148
+ return "closed";
67
149
  const wait = this.indexWaits.get(lane);
150
+ if (wait?.over)
151
+ return "closed";
152
+ if (this.hopeless(secondsLeft))
153
+ return this.close(lane);
68
154
  if (wait === undefined) {
69
- if ((this.failures.get(lane) ?? 0) >= 3)
70
- return undefined;
71
155
  this.retireExpiredWaits(now);
72
156
  if (this.indexWaits.size >= this.capacity)
73
- return undefined;
74
- this.indexWaits.set(lane, now);
75
- return this.indexWaitError(lane);
157
+ return "untracked";
158
+ this.indexWaits.set(lane, { started: now, deadline: this.deadline(now, now, secondsLeft),
159
+ secondsLeft });
160
+ return "open";
76
161
  }
77
- if (now - wait < this.indexWaitMs)
78
- return this.indexWaitError(lane);
79
- this.retire(lane);
80
- return refusal(3);
162
+ if (secondsLeft !== undefined) {
163
+ wait.secondsLeft = secondsLeft;
164
+ wait.deadline = Math.max(wait.deadline, this.deadline(wait.started, now, secondsLeft));
165
+ }
166
+ return now < wait.deadline ? "open" : this.close(lane);
167
+ }
168
+ /** When a wait begun at `started` ends, given the time left stated at `now`. */
169
+ deadline(started, now, secondsLeft) {
170
+ if (secondsLeft === undefined)
171
+ return started + this.indexWaitMs;
172
+ const ms = secondsLeft * 1000;
173
+ return Math.min(started + this.indexWaitMaxMs, now + ms + ms * INDEX_WAIT_MARGIN_RATIO + INDEX_WAIT_MARGIN_MS);
81
174
  }
82
- indexWaitError(lane) {
83
- return retryError(this.failures.get(lane) ?? 0, String(INDEX_WAIT_RETRY_AFTER_SECONDS), INDEX_WAIT_MESSAGE);
175
+ indexWaitError(lane, secondsLeft) {
176
+ const retryAfter = secondsLeft === undefined ? INDEX_WAIT_RETRY_AFTER_SECONDS
177
+ : Math.max(1, Math.min(INDEX_WAIT_RETRY_AFTER_SECONDS, Math.ceil(secondsLeft)));
178
+ return retryError(this.failures.get(lane) ?? 0, String(retryAfter), indexWaitStatus(secondsLeft));
84
179
  }
85
180
  /** Free the slots of waits past their deadline, keeping them refused. */
86
181
  retireExpiredWaits(now) {
87
- for (const [lane, started] of this.indexWaits) {
88
- if (now - started >= this.indexWaitMs)
89
- this.retire(lane);
182
+ for (const [lane, wait] of this.indexWaits) {
183
+ if (now >= wait.deadline)
184
+ this.close(lane);
90
185
  }
91
186
  }
92
187
  /**
93
- * An expired wait's lane moves to the terminal strike state. If the strike
94
- * table is full the wait keeps its slot instead (still expired, still
95
- * refused), so no lane can be re-admitted with a fresh deadline.
188
+ * End the lane's wait in the terminal strike state. If the strike table is full a wait
189
+ * keeps its slot instead, marked over (still refused, never extended), so no lane can
190
+ * be re-admitted with a fresh deadline; with neither, the refusal stands for this
191
+ * request only.
96
192
  */
97
- retire(lane) {
98
- if (!this.failures.has(lane) && this.failures.size >= this.capacity)
99
- return;
100
- this.failures.set(lane, 3);
101
- this.indexWaits.delete(lane);
193
+ close(lane) {
194
+ if (this.failures.has(lane) || this.failures.size < this.capacity) {
195
+ this.failures.set(lane, 3);
196
+ this.indexWaits.delete(lane);
197
+ }
198
+ else {
199
+ const wait = this.indexWaits.get(lane);
200
+ if (wait)
201
+ wait.over = true;
202
+ }
203
+ return "closed";
102
204
  }
103
205
  }
104
206
  const RETRY_MESSAGE = "MemTree could not produce a usable compressed request; retrying within a bounded limit.";
105
- const INDEX_WAIT_MESSAGE = "MemTree is still indexing this conversation, so it does not fit the model's context " +
106
- "window yet; retrying once indexing catches up.";
207
+ /**
208
+ * The one-line status a waiting turn shows (Claude Code prints a 503's message on its
209
+ * retry line): how long the server expects, when it said.
210
+ */
211
+ export function indexWaitStatus(secondsLeft) {
212
+ const left = secondsLeft === undefined ? ""
213
+ : `, ${timeLeftText(secondsLeft)} left by its estimate`;
214
+ return `MemTree is catching up on this session's index${left}. ` +
215
+ "This turn continues on its own once it's ready.";
216
+ }
217
+ /** "about 1 minute", "about 5 minutes" (whole minutes, rounded up). */
218
+ export function timeLeftText(seconds) {
219
+ const minutes = Math.max(1, Math.ceil(seconds / 60));
220
+ return minutes === 1 ? "about 1 minute" : `about ${minutes} minutes`;
221
+ }
107
222
  /**
108
223
  * The refusal while MemTree is paused (402): only compression could fit the
109
224
  * request, and a retry cannot pay, so it is final at once and outside the
@@ -113,6 +228,15 @@ export function pausedRefusal(message) {
113
228
  return { ...refusal(0), body: { type: "error",
114
229
  error: { type: "invalid_request_error", message } } };
115
230
  }
231
+ /**
232
+ * The refusal while MemTree can't be reached (network-failure.ts): nothing says the request
233
+ * can't fit, so it is retryable and outside the strike episode (attempt 0). No retry-after:
234
+ * Claude Code backs off as for its own connection errors, giving the network time to return.
235
+ */
236
+ export function unreachableRefusal(message) {
237
+ return { status: 503, attempt: 0, headers: { "x-should-retry": "true" },
238
+ body: { type: "error", error: { type: "api_error", message } } };
239
+ }
116
240
  function retryError(attempt, retryAfter, message) {
117
241
  return {
118
242
  status: 503,
@@ -121,14 +245,14 @@ function retryError(attempt, retryAfter, message) {
121
245
  body: { type: "error", error: { type: "api_error", message } },
122
246
  };
123
247
  }
124
- function refusal(attempt) {
248
+ function refusal(attempt, message = FINAL_REFUSAL_MESSAGE) {
125
249
  return {
126
250
  status: 400,
127
251
  attempt,
128
252
  headers: { "x-should-retry": "false" },
129
253
  body: {
130
254
  type: "error",
131
- error: { type: "invalid_request_error", message: FINAL_REFUSAL_MESSAGE },
255
+ error: { type: "invalid_request_error", message },
132
256
  },
133
257
  };
134
258
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route-fallback.js","sourceRoot":"","sources":["../src/route-fallback.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route-fallback.js","sourceRoot":"","sources":["../src/route-fallback.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,8 @@ export declare function stablePrefixMessageHash(message: Message): string;
9
9
  export declare function prefixIdentity(messages: Message[], kind: PrefixIdentity): {
10
10
  originalPrefixHashes: string[];
11
11
  originalMediaFreeHashes: string[];
12
+ originalPortableHashes: string[];
13
+ originalPortableMediaFreeHashes: string[];
12
14
  };
13
15
  /**
14
16
  * Whether `message` still stands where a prefix's message stood: unchanged, or the same
@@ -17,9 +19,11 @@ export declare function prefixIdentity(messages: Message[], kind: PrefixIdentity
17
19
  * becomes a placeholder, a top-level one is dropped, an emptied message becomes the
18
20
  * placeholder. That counts only when the message has no media left, so an attachment
19
21
  * replaced by another never matches; a removed one is indistinguishable from eviction.
20
- * Prefixes stored before media-free hashes existed match exactly only.
22
+ * A newer Claude Code can also render the same history differently on resume (see
23
+ * portableHash), with media kept or (no media left) evicted the same way.
24
+ * Prefixes stored before media-free or portable hashes existed match exactly only.
21
25
  */
22
- export declare function prefixMessageMatches(message: Message, kind: PrefixIdentity, exact: string, mediaFree: string | undefined): boolean;
26
+ export declare function prefixMessageMatches(message: Message, kind: PrefixIdentity, exact: string, mediaFree: string | undefined, portable?: string, portableMediaFree?: string): boolean;
23
27
  /**
24
28
  * Whether `newer` carries everything `older` does: every message of `older` after the
25
29
  * system prompt (whose billing line changes per call), in place and unchanged apart from
@@ -1 +1 @@
1
- {"version":3,"file":"route-identity.d.ts","sourceRoot":"","sources":["../src/route-identity.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AASnE,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhD,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEhE;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,GACxC;IAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAAC,uBAAuB,EAAE,MAAM,EAAE,CAAA;CAAE,CAMvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GACnF,OAAO,CAKT;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAK1E;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE7D"}
1
+ {"version":3,"file":"route-identity.d.ts","sourceRoot":"","sources":["../src/route-identity.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAoBnE,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhD,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEhE;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,GACxC;IACD,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAAC,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClE,sBAAsB,EAAE,MAAM,EAAE,CAAC;IAAC,+BAA+B,EAAE,MAAM,EAAE,CAAC;CAC7E,CAQA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EACpF,QAAQ,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAC5C,OAAO,CAQT;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAK1E;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE7D"}
@@ -2,17 +2,18 @@ import { createHash } from "node:crypto";
2
2
  import { stripSystemReminderText } from "./turns.js";
3
3
  // Request messages are immutable snapshots. Weak keys retain no completed request.
4
4
  // Route installation stores these digests, not the original megabytes of history.
5
- const routeHashes = new WeakMap();
6
- const stableHashes = new WeakMap();
7
- const routeMediaFreeHashes = new WeakMap();
8
- const stableMediaFreeHashes = new WeakMap();
5
+ const hashCaches = new Map();
6
+ /** Each message's tool input JSON strings (jsonStringFields), computed once. */
7
+ const jsonFieldCache = new WeakMap();
8
+ const EXACT = { media: "keep" };
9
+ const MEDIA_FREE = { media: "drop" };
9
10
  /** Hash each incoming message once, then reuse it across route candidates/checks. */
10
11
  export function routeMessageHash(message) {
11
- return messageHash(message, false, false);
12
+ return messageHash(message, false, EXACT);
12
13
  }
13
14
  /** Stable prefixes span turns in which Claude can omit earlier thinking blocks. */
14
15
  export function stablePrefixMessageHash(message) {
15
- return messageHash(message, stableShape(message), false);
16
+ return messageHash(message, stableShape(message), EXACT);
16
17
  }
17
18
  /** The identities a prefix stores for the messages it stands for. */
18
19
  export function prefixIdentity(messages, kind) {
@@ -20,6 +21,8 @@ export function prefixIdentity(messages, kind) {
20
21
  return {
21
22
  originalPrefixHashes: messages.map(exact),
22
23
  originalMediaFreeHashes: messages.map((m) => mediaFreeHash(m, kind)),
24
+ originalPortableHashes: messages.map((m) => portableIdentity(m, kind, "keep")),
25
+ originalPortableMediaFreeHashes: messages.map((m) => portableIdentity(m, kind, "drop")),
23
26
  };
24
27
  }
25
28
  /**
@@ -29,14 +32,21 @@ export function prefixIdentity(messages, kind) {
29
32
  * becomes a placeholder, a top-level one is dropped, an emptied message becomes the
30
33
  * placeholder. That counts only when the message has no media left, so an attachment
31
34
  * replaced by another never matches; a removed one is indistinguishable from eviction.
32
- * Prefixes stored before media-free hashes existed match exactly only.
35
+ * A newer Claude Code can also render the same history differently on resume (see
36
+ * portableHash), with media kept or (no media left) evicted the same way.
37
+ * Prefixes stored before media-free or portable hashes existed match exactly only.
33
38
  */
34
- export function prefixMessageMatches(message, kind, exact, mediaFree) {
39
+ export function prefixMessageMatches(message, kind, exact, mediaFree, portable, portableMediaFree) {
35
40
  const hash = kind === "stable" ? stablePrefixMessageHash(message) : routeMessageHash(message);
36
41
  if (hash === exact)
37
42
  return true;
38
- return mediaFree !== undefined && !carriesMedia(message.content) &&
39
- mediaFreeHash(message, kind) === mediaFree;
43
+ if (portable !== undefined && portableMatches(message, kind, "keep", portable))
44
+ return true;
45
+ if (carriesMedia(message.content))
46
+ return false;
47
+ return (mediaFree !== undefined && mediaFreeHash(message, kind) === mediaFree) ||
48
+ (portableMediaFree !== undefined &&
49
+ portableMatches(message, kind, "drop", portableMediaFree));
40
50
  }
41
51
  /**
42
52
  * Whether `newer` carries everything `older` does: every message of `older` after the
@@ -55,15 +65,84 @@ export function mediaFreeMessageHash(message) {
55
65
  return mediaFreeHash(message, "route");
56
66
  }
57
67
  function mediaFreeHash(message, kind) {
58
- return messageHash(message, kind === "stable" && stableShape(message), true);
68
+ return messageHash(message, kind === "stable" && stableShape(message), MEDIA_FREE);
69
+ }
70
+ /**
71
+ * An identity that also ignores how Claude Code renders unchanged history, which differs
72
+ * between versions (2.1.302 -> 2.1.319 on 2026-11-09): a reminder inside a tool result's
73
+ * text or in a block of its own, a tool result's text as a string or a text block, a tool
74
+ * input value as the JSON string the model sent or the value a newer Claude Code parsed
75
+ * it to. Followed by the digests of the message's tool input JSON strings, so that one
76
+ * still a string is held to the very string stored (portableMatches).
77
+ */
78
+ function portableIdentity(message, kind, media) {
79
+ const fields = jsonStringFields(message);
80
+ const hash = portableHash(message, kind, media);
81
+ return fields.size ? `${hash}|${JSON.stringify([...fields].sort())}` : hash;
82
+ }
83
+ /**
84
+ * Whether `message` matches a stored portableIdentity: the same content as rendered either
85
+ * way, and each tool input it still sends as a JSON string the same string as stored there
86
+ * (so two strings that parse alike never match); one parsed since matches by its value.
87
+ */
88
+ function portableMatches(message, kind, media, stored) {
89
+ const split = stored.indexOf("|");
90
+ const hash = split === -1 ? stored : stored.slice(0, split);
91
+ if (portableHash(message, kind, media) !== hash)
92
+ return false;
93
+ const fields = jsonStringFields(message);
94
+ if (!fields.size)
95
+ return true;
96
+ let storedFields;
97
+ try {
98
+ storedFields = new Map(split === -1 ? [] : JSON.parse(stored.slice(split + 1)));
99
+ }
100
+ catch {
101
+ return false;
102
+ }
103
+ for (const [field, digest] of fields)
104
+ if (storedFields.get(field) !== digest)
105
+ return false;
106
+ return true;
107
+ }
108
+ function portableHash(message, kind, media) {
109
+ return messageHash(message, kind === "stable" && stableShape(message), { media, portable: true });
110
+ }
111
+ /**
112
+ * The message's tool input values that are JSON strings portableContent parses: tool use
113
+ * id and input key -> a digest of the string as sent.
114
+ */
115
+ function jsonStringFields(message) {
116
+ const cached = jsonFieldCache.get(message);
117
+ if (cached)
118
+ return cached;
119
+ const fields = new Map();
120
+ const content = Array.isArray(message.content) ? message.content : [];
121
+ content.forEach((part, index) => {
122
+ if (part?.type !== "tool_use" || !isPlainObject(part.input))
123
+ return;
124
+ for (const [key, value] of Object.entries(part.input)) {
125
+ if (typeof value !== "string" || parsedJson(value) === value)
126
+ continue;
127
+ const digest = createHash("sha256").update(value, "utf16le").digest("hex");
128
+ fields.set(JSON.stringify([part.id ?? `#${index}`, key]), digest);
129
+ }
130
+ });
131
+ jsonFieldCache.set(message, fields);
132
+ return fields;
59
133
  }
60
134
  function stableShape(message) {
61
135
  return message.role === "assistant" && Array.isArray(message.content);
62
136
  }
63
- function messageHash(message, stable, mediaFree) {
64
- const cache = mediaFree
65
- ? (stable ? stableMediaFreeHashes : routeMediaFreeHashes)
66
- : (stable ? stableHashes : routeHashes);
137
+ function hashCache(stable, mode) {
138
+ const key = `${stable}:${mode.media}:${mode.portable === true}`;
139
+ let cache = hashCaches.get(key);
140
+ if (!cache)
141
+ hashCaches.set(key, cache = new WeakMap());
142
+ return cache;
143
+ }
144
+ function messageHash(message, stable, mode) {
145
+ const cache = hashCache(stable, mode);
67
146
  const cached = cache.get(message);
68
147
  if (cached !== undefined)
69
148
  return cached;
@@ -73,8 +152,10 @@ function messageHash(message, stable, mediaFree) {
73
152
  }
74
153
  const blocks = typeof content === "string" ? [{ type: "text", text: content }] : content;
75
154
  const reminded = normalizeReminders(blocks);
155
+ const kept = mode.media === "drop" ? withoutMedia(reminded) : reminded;
76
156
  const normalized = {
77
- ...message, content: stripBlockCache(mediaFree ? withoutMedia(reminded) : reminded),
157
+ ...message,
158
+ content: stripBlockCache(mode.portable ? withoutToolLoadedNotes(portableContent(kept)) : kept),
78
159
  };
79
160
  const hash = createHash("sha256");
80
161
  updateCanonical(hash, normalized);
@@ -102,6 +183,118 @@ function normalizeReminders(content) {
102
183
  return part;
103
184
  });
104
185
  }
186
+ /**
187
+ * Content with rendering choices canonicalized (portableHash): text blocks left empty by
188
+ * reminder removal dropped, a tool result's string as one text block, and tool input
189
+ * values that are JSON strings of an object or array parsed (losslessly: parsedJson).
190
+ */
191
+ function portableContent(content) {
192
+ if (!Array.isArray(content))
193
+ return content;
194
+ return content.filter((part) => !isEmptyText(part)).map((part) => {
195
+ if (!part || typeof part !== "object")
196
+ return part;
197
+ if (part.type === "tool_result") {
198
+ const inner = typeof part.content === "string"
199
+ ? [{ type: "text", text: part.content }] : part.content;
200
+ return { ...part, content: portableContent(inner) };
201
+ }
202
+ if (part.type === "tool_use" && isPlainObject(part.input)) {
203
+ return { ...part, input: parsedJsonValues(part.input) };
204
+ }
205
+ return part;
206
+ });
207
+ }
208
+ /** Claude Code's note after a ToolSearch result that loaded tools; sent or not by model. */
209
+ const TOOL_LOADED_RE = /^Tool loaded\.(?:\n\[id:[^\]\n]+\])*\n?$/;
210
+ /**
211
+ * Top-level content without each "Tool loaded." note that follows the turn's tool
212
+ * results when one of them holds only tool references. On the same Claude Code
213
+ * (2.1.321), Opus 5.5 gets the note and Fable 5.2 does not, so a model switch changed
214
+ * old messages (2026-11-09). Mirrors polychat's rerender_match.portable_message.
215
+ */
216
+ function withoutToolLoadedNotes(content) {
217
+ if (!Array.isArray(content))
218
+ return content;
219
+ return content.filter((part, index) => !(isToolLoadedNote(part) && followsLoadedTools(content, index)));
220
+ }
221
+ function isToolLoadedNote(part) {
222
+ return part?.type === "text" && typeof part.text === "string" &&
223
+ TOOL_LOADED_RE.test(part.text) &&
224
+ Object.keys(part).every((key) => key === "type" || key === "text" || key === "cache_control");
225
+ }
226
+ /**
227
+ * Whether the run of tool results ending just before `index` loads tools. Earlier notes
228
+ * are skipped: two ToolSearch calls in one turn leave two notes.
229
+ */
230
+ function followsLoadedTools(content, index) {
231
+ for (let i = index - 1; i >= 0; i--) {
232
+ const part = content[i];
233
+ if (isToolLoadedNote(part))
234
+ continue;
235
+ if (part?.type !== "tool_result")
236
+ return false;
237
+ if (Array.isArray(part.content) && part.content.length > 0 &&
238
+ part.content.every((inner) => inner?.type === "tool_reference"))
239
+ return true;
240
+ }
241
+ return false;
242
+ }
243
+ function isEmptyText(part) {
244
+ return typeof part === "string" ? part === "" :
245
+ part?.type === "text" && part.text === "" &&
246
+ Object.keys(part).every((key) => key === "type" || key === "text" || key === "cache_control");
247
+ }
248
+ /** Defined properties only (Object.fromEntries keeps an own `__proto__` key as data). */
249
+ function parsedJsonValues(input) {
250
+ return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, parsedJson(value)]));
251
+ }
252
+ /**
253
+ * A string holding a JSON object or array, parsed, when parsing loses nothing: the string
254
+ * is the parse's own serialization apart from whitespace between tokens. Anything lossy
255
+ * (duplicate keys, numbers past double precision or written another way, escapes
256
+ * JSON.stringify would not write) stays the string it is, so it matches only itself.
257
+ */
258
+ function parsedJson(value) {
259
+ if (typeof value !== "string" || !/^\s*[[{]/.test(value))
260
+ return value;
261
+ let parsed;
262
+ try {
263
+ parsed = JSON.parse(value);
264
+ }
265
+ catch {
266
+ return value;
267
+ }
268
+ if (!parsed || typeof parsed !== "object")
269
+ return value;
270
+ return JSON.stringify(parsed) === withoutJsonWhitespace(value) ? parsed : value;
271
+ }
272
+ /** JSON text without the whitespace between its tokens (strings kept as written). */
273
+ function withoutJsonWhitespace(text) {
274
+ let out = "";
275
+ let inString = false;
276
+ for (let i = 0; i < text.length; i++) {
277
+ const ch = text[i];
278
+ if (inString) {
279
+ out += ch;
280
+ if (ch === "\\")
281
+ out += text[++i] ?? "";
282
+ else if (ch === '"')
283
+ inString = false;
284
+ }
285
+ else if (ch === '"') {
286
+ inString = true;
287
+ out += ch;
288
+ }
289
+ else if (ch !== " " && ch !== "\n" && ch !== "\r" && ch !== "\t") {
290
+ out += ch;
291
+ }
292
+ }
293
+ return out;
294
+ }
295
+ function isPlainObject(value) {
296
+ return !!value && typeof value === "object" && !Array.isArray(value);
297
+ }
105
298
  /**
106
299
  * Claude Code's stand-ins for media it removed from its own history. After the API
107
300
  * rejects media it removes a message left empty altogether; that shifts positions and