claude-code-infinite 1.0.28 → 1.0.30

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 (121) hide show
  1. package/README.md +96 -19
  2. package/dist/auto-update.d.ts +2 -0
  3. package/dist/auto-update.d.ts.map +1 -1
  4. package/dist/auto-update.js +4 -0
  5. package/dist/auto-update.js.map +1 -1
  6. package/dist/claude-auth.d.ts +27 -2
  7. package/dist/claude-auth.d.ts.map +1 -1
  8. package/dist/claude-auth.js +76 -4
  9. package/dist/claude-auth.js.map +1 -1
  10. package/dist/claude-install.d.ts +73 -0
  11. package/dist/claude-install.d.ts.map +1 -0
  12. package/dist/claude-install.js +142 -0
  13. package/dist/claude-install.js.map +1 -0
  14. package/dist/claude-plan-warning.d.ts +70 -7
  15. package/dist/claude-plan-warning.d.ts.map +1 -1
  16. package/dist/claude-plan-warning.js +152 -8
  17. package/dist/claude-plan-warning.js.map +1 -1
  18. package/dist/cli-lifecycle.d.ts +45 -1
  19. package/dist/cli-lifecycle.d.ts.map +1 -1
  20. package/dist/cli-lifecycle.js +59 -0
  21. package/dist/cli-lifecycle.js.map +1 -1
  22. package/dist/cli-main.js +136 -29
  23. package/dist/cli-main.js.map +1 -1
  24. package/dist/count-tokens.d.ts +15 -0
  25. package/dist/count-tokens.d.ts.map +1 -1
  26. package/dist/count-tokens.js +23 -1
  27. package/dist/count-tokens.js.map +1 -1
  28. package/dist/diagnostics-schema.d.ts +4 -0
  29. package/dist/diagnostics-schema.d.ts.map +1 -1
  30. package/dist/diagnostics-schema.js +25 -0
  31. package/dist/diagnostics-schema.js.map +1 -1
  32. package/dist/diagnostics.d.ts +24 -1
  33. package/dist/diagnostics.d.ts.map +1 -1
  34. package/dist/diagnostics.js +86 -5
  35. package/dist/diagnostics.js.map +1 -1
  36. package/dist/final-index.d.ts +7 -1
  37. package/dist/final-index.d.ts.map +1 -1
  38. package/dist/final-index.js +10 -3
  39. package/dist/final-index.js.map +1 -1
  40. package/dist/image-refs.d.ts +51 -0
  41. package/dist/image-refs.d.ts.map +1 -0
  42. package/dist/image-refs.js +169 -0
  43. package/dist/image-refs.js.map +1 -0
  44. package/dist/image-tokens.d.ts +37 -0
  45. package/dist/image-tokens.d.ts.map +1 -0
  46. package/dist/image-tokens.js +158 -0
  47. package/dist/image-tokens.js.map +1 -0
  48. package/dist/install-ping.d.ts +54 -0
  49. package/dist/install-ping.d.ts.map +1 -0
  50. package/dist/install-ping.js +177 -0
  51. package/dist/install-ping.js.map +1 -0
  52. package/dist/memtree-body.d.ts +52 -0
  53. package/dist/memtree-body.d.ts.map +1 -0
  54. package/dist/memtree-body.js +99 -0
  55. package/dist/memtree-body.js.map +1 -0
  56. package/dist/memtree-finder.d.ts +2 -1
  57. package/dist/memtree-finder.d.ts.map +1 -1
  58. package/dist/memtree-finder.js +4 -5
  59. package/dist/memtree-finder.js.map +1 -1
  60. package/dist/memtree-mcp.d.ts.map +1 -1
  61. package/dist/memtree-mcp.js +17 -7
  62. package/dist/memtree-mcp.js.map +1 -1
  63. package/dist/memtree-times.d.ts +35 -0
  64. package/dist/memtree-times.d.ts.map +1 -0
  65. package/dist/memtree-times.js +166 -0
  66. package/dist/memtree-times.js.map +1 -0
  67. package/dist/memtree-tools.d.ts +12 -0
  68. package/dist/memtree-tools.d.ts.map +1 -1
  69. package/dist/memtree-tools.js +63 -7
  70. package/dist/memtree-tools.js.map +1 -1
  71. package/dist/memtree.d.ts +77 -3
  72. package/dist/memtree.d.ts.map +1 -1
  73. package/dist/memtree.js +267 -53
  74. package/dist/memtree.js.map +1 -1
  75. package/dist/paused-session.d.ts.map +1 -1
  76. package/dist/paused-session.js +11 -8
  77. package/dist/paused-session.js.map +1 -1
  78. package/dist/postinstall.d.ts +2 -0
  79. package/dist/postinstall.d.ts.map +1 -0
  80. package/dist/postinstall.js +4 -0
  81. package/dist/postinstall.js.map +1 -0
  82. package/dist/prefix-store.d.ts +2 -0
  83. package/dist/prefix-store.d.ts.map +1 -1
  84. package/dist/prefix-store.js +4 -0
  85. package/dist/prefix-store.js.map +1 -1
  86. package/dist/prepared-compression.d.ts +78 -0
  87. package/dist/prepared-compression.d.ts.map +1 -0
  88. package/dist/prepared-compression.js +127 -0
  89. package/dist/prepared-compression.js.map +1 -0
  90. package/dist/proxy.d.ts +370 -13
  91. package/dist/proxy.d.ts.map +1 -1
  92. package/dist/proxy.js +790 -92
  93. package/dist/proxy.js.map +1 -1
  94. package/dist/rate-limit.d.ts +64 -0
  95. package/dist/rate-limit.d.ts.map +1 -0
  96. package/dist/rate-limit.js +126 -0
  97. package/dist/rate-limit.js.map +1 -0
  98. package/dist/reqlog.d.ts +66 -2
  99. package/dist/reqlog.d.ts.map +1 -1
  100. package/dist/reqlog.js.map +1 -1
  101. package/dist/request-sizing.d.ts +21 -2
  102. package/dist/request-sizing.d.ts.map +1 -1
  103. package/dist/request-sizing.js +57 -11
  104. package/dist/request-sizing.js.map +1 -1
  105. package/dist/route-identity.d.ts +27 -0
  106. package/dist/route-identity.d.ts.map +1 -1
  107. package/dist/route-identity.js +88 -8
  108. package/dist/route-identity.js.map +1 -1
  109. package/dist/token-estimate.d.ts +3 -20
  110. package/dist/token-estimate.d.ts.map +1 -1
  111. package/dist/token-estimate.js +9 -50
  112. package/dist/token-estimate.js.map +1 -1
  113. package/dist/tool-output-store.d.ts +12 -0
  114. package/dist/tool-output-store.d.ts.map +1 -0
  115. package/dist/tool-output-store.js +146 -0
  116. package/dist/tool-output-store.js.map +1 -0
  117. package/dist/tool-result-truncation.d.ts +32 -0
  118. package/dist/tool-result-truncation.d.ts.map +1 -0
  119. package/dist/tool-result-truncation.js +135 -0
  120. package/dist/tool-result-truncation.js.map +1 -0
  121. package/package.json +2 -1
@@ -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;AAOnE,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAKhE"}
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"}
@@ -4,19 +4,66 @@ import { stripSystemReminderText } from "./turns.js";
4
4
  // Route installation stores these digests, not the original megabytes of history.
5
5
  const routeHashes = new WeakMap();
6
6
  const stableHashes = new WeakMap();
7
+ const routeMediaFreeHashes = new WeakMap();
8
+ const stableMediaFreeHashes = new WeakMap();
7
9
  /** Hash each incoming message once, then reuse it across route candidates/checks. */
8
10
  export function routeMessageHash(message) {
9
- return messageHash(message, false);
11
+ return messageHash(message, false, false);
10
12
  }
11
13
  /** Stable prefixes span turns in which Claude can omit earlier thinking blocks. */
12
14
  export function stablePrefixMessageHash(message) {
13
- if (message.role !== "assistant" || !Array.isArray(message.content)) {
14
- return routeMessageHash(message);
15
- }
16
- return messageHash(message, true);
15
+ return messageHash(message, stableShape(message), false);
16
+ }
17
+ /** The identities a prefix stores for the messages it stands for. */
18
+ export function prefixIdentity(messages, kind) {
19
+ const exact = kind === "stable" ? stablePrefixMessageHash : routeMessageHash;
20
+ return {
21
+ originalPrefixHashes: messages.map(exact),
22
+ originalMediaFreeHashes: messages.map((m) => mediaFreeHash(m, kind)),
23
+ };
24
+ }
25
+ /**
26
+ * Whether `message` still stands where a prefix's message stood: unchanged, or the same
27
+ * apart from media Claude Code evicted. Past its media caps (count, and bytes in 2.1.310)
28
+ * Claude Code evicts the oldest images and documents from its history: a tool result's
29
+ * becomes a placeholder, a top-level one is dropped, an emptied message becomes the
30
+ * placeholder. That counts only when the message has no media left, so an attachment
31
+ * replaced by another never matches; a removed one is indistinguishable from eviction.
32
+ * Prefixes stored before media-free hashes existed match exactly only.
33
+ */
34
+ export function prefixMessageMatches(message, kind, exact, mediaFree) {
35
+ const hash = kind === "stable" ? stablePrefixMessageHash(message) : routeMessageHash(message);
36
+ if (hash === exact)
37
+ return true;
38
+ return mediaFree !== undefined && !carriesMedia(message.content) &&
39
+ mediaFreeHash(message, kind) === mediaFree;
40
+ }
41
+ /**
42
+ * Whether `newer` carries everything `older` does: every message of `older` after the
43
+ * system prompt (whose billing line changes per call), in place and unchanged apart from
44
+ * media Claude Code evicted since (prefixMessageMatches). Past its media caps every new
45
+ * screenshot evicts an old one, so an exact comparison would never hold there. About
46
+ * 20 ms for a 25 MB history; each message is hashed once.
47
+ */
48
+ export function extendsHistory(newer, older) {
49
+ const a = newer.filter((message) => message.role !== "system");
50
+ const b = older.filter((message) => message.role !== "system");
51
+ return a.length >= b.length && b.every((message, i) => prefixMessageMatches(a[i], "route", routeMessageHash(message), mediaFreeMessageHash(message)));
52
+ }
53
+ /** A message's route identity without its media (Claude Code's eviction keeps it). */
54
+ export function mediaFreeMessageHash(message) {
55
+ return mediaFreeHash(message, "route");
56
+ }
57
+ function mediaFreeHash(message, kind) {
58
+ return messageHash(message, kind === "stable" && stableShape(message), true);
17
59
  }
18
- function messageHash(message, stable) {
19
- const cache = stable ? stableHashes : routeHashes;
60
+ function stableShape(message) {
61
+ return message.role === "assistant" && Array.isArray(message.content);
62
+ }
63
+ function messageHash(message, stable, mediaFree) {
64
+ const cache = mediaFree
65
+ ? (stable ? stableMediaFreeHashes : routeMediaFreeHashes)
66
+ : (stable ? stableHashes : routeHashes);
20
67
  const cached = cache.get(message);
21
68
  if (cached !== undefined)
22
69
  return cached;
@@ -25,7 +72,10 @@ function messageHash(message, stable) {
25
72
  content = content.filter((part) => part?.type !== "thinking" && part?.type !== "redacted_thinking");
26
73
  }
27
74
  const blocks = typeof content === "string" ? [{ type: "text", text: content }] : content;
28
- const normalized = { ...message, content: stripBlockCache(normalizeReminders(blocks)) };
75
+ const reminded = normalizeReminders(blocks);
76
+ const normalized = {
77
+ ...message, content: stripBlockCache(mediaFree ? withoutMedia(reminded) : reminded),
78
+ };
29
79
  const hash = createHash("sha256");
30
80
  updateCanonical(hash, normalized);
31
81
  const digest = hash.digest("hex");
@@ -52,6 +102,36 @@ function normalizeReminders(content) {
52
102
  return part;
53
103
  });
54
104
  }
105
+ /**
106
+ * Claude Code's stand-ins for media it removed from its own history. After the API
107
+ * rejects media it removes a message left empty altogether; that shifts positions and
108
+ * still breaks a prefix (rare, and a recompress follows).
109
+ */
110
+ const MEDIA_PLACEHOLDERS = new Set([
111
+ "[media removed: request limit]", "(media removed \u2014 rejected by API)",
112
+ ]);
113
+ /** Content without media blocks and without Claude Code's placeholders for them. */
114
+ function withoutMedia(content) {
115
+ if (!Array.isArray(content))
116
+ return content;
117
+ return content.filter((part) => !isMediaOrPlaceholder(part)).map((part) => part && typeof part === "object" && part.type === "tool_result"
118
+ ? { ...part, content: withoutMedia(part.content) }
119
+ : part);
120
+ }
121
+ /** Whether any image or document is left, at the top level or in a tool result. */
122
+ function carriesMedia(content) {
123
+ if (!Array.isArray(content))
124
+ return false;
125
+ return content.some((part) => part?.type === "image" || part?.type === "document" ||
126
+ (part?.type === "tool_result" && carriesMedia(part.content)));
127
+ }
128
+ function isMediaOrPlaceholder(part) {
129
+ if (!part || typeof part !== "object")
130
+ return false;
131
+ if (part.type === "image" || part.type === "document")
132
+ return true;
133
+ return part.type === "text" && MEDIA_PLACEHOLDERS.has(part.text);
134
+ }
55
135
  /** Cache metadata on blocks is incidental; identically named tool input keys aren't. */
56
136
  function stripBlockCache(content) {
57
137
  if (Array.isArray(content))
@@ -1 +1 @@
1
- {"version":3,"file":"route-identity.js","sourceRoot":"","sources":["../src/route-identity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route-identity.js","sourceRoot":"","sources":["../src/route-identity.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,3 @@
1
- /**
2
- * Conservative token estimates from request bytes, per model tokenizer family,
3
- * for when no exact Count Tokens result is available.
4
- *
5
- * bytes/4 under-counted Claude 4.7+ by ~1.8x: on 2026-10-15 (request 3bc78182)
6
- * a 3,238,930-byte flattened body was sized at 809,733 tokens and forwarded to
7
- * a 1M window; Anthropic counted 1,342,572 and refused it. These ratios are the
8
- * MemTree server's (polychat/chars_per_token.py): low percentiles of real
9
- * Claude Code and NanoGPT requests counted with Count Tokens, so an estimate
10
- * rarely says a body fits when it does not. Bytes are at least the characters
11
- * the server measures (JSON escapes and UTF-8 only add bytes), so dividing
12
- * bytes by a chars-per-token ratio errs high, never low.
13
- *
14
- * Base64 image data is not text: Anthropic resizes every image to at most
15
- * MAX_IMAGE_TOKENS however many bytes it takes (and a tiny, very compressible
16
- * PNG can still cost the maximum), so each image payload counts as the maximum.
17
- */
18
1
  /** Claude 4.7 and later (Opus 4.7+, Sonnet/Haiku 5+, Fable 5). */
19
2
  export declare const CLAUDE_4_7_PLUS_BYTES_PER_TOKEN = 1.9;
20
3
  /** Claude before 4.7 (4.5, 4.6 and older). */
@@ -28,8 +11,8 @@ export declare function bytesPerTokenForModel(model: string | undefined): number
28
11
  /** Tokens `bytes` of text may cost on `model` (rounded up). */
29
12
  export declare function conservativeTokensFromBytes(bytes: number, model: string | undefined): number;
30
13
  /** Tokens a request body may cost on `model`: its text at the family ratio,
31
- * each image content block (base64 or URL, in a message or a tool_result) at
32
- * one image's maximum.
33
- * A body that does not parse is all text, an over-estimate. */
14
+ * each inline image content block (in a message or a tool_result) at its
15
+ * visual tokens from its header (image-tokens.ts), the tier's maximum when
16
+ * unreadable or not inline. A body that does not parse is all text, an over-estimate. */
34
17
  export declare function conservativeBodyTokens(body: Buffer, model: string | undefined): number;
35
18
  //# sourceMappingURL=token-estimate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-estimate.d.ts","sourceRoot":"","sources":["../src/token-estimate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,kEAAkE;AAClE,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,8CAA8C;AAC9C,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAItC,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CASvE;AAED,+DAA+D;AAC/D,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG5F;AAED;;;+DAG+D;AAC/D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGtF"}
1
+ {"version":3,"file":"token-estimate.d.ts","sourceRoot":"","sources":["../src/token-estimate.ts"],"names":[],"mappings":"AAoBA,kEAAkE;AAClE,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,8CAA8C;AAC9C,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAItC,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CASvE;AAED,+DAA+D;AAC/D,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG5F;AAED;;;yFAGyF;AACzF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGtF"}
@@ -11,10 +11,12 @@
11
11
  * the server measures (JSON escapes and UTF-8 only add bytes), so dividing
12
12
  * bytes by a chars-per-token ratio errs high, never low.
13
13
  *
14
- * Base64 image data is not text: Anthropic resizes every image to at most
15
- * MAX_IMAGE_TOKENS however many bytes it takes (and a tiny, very compressible
16
- * PNG can still cost the maximum), so each image payload counts as the maximum.
14
+ * Base64 image data is not text: Anthropic charges an image by its pixel
15
+ * dimensions (ceil(w/28) * ceil(h/28) after its tier's downscale, at most
16
+ * MAX_IMAGE_TOKENS) however many bytes it takes, so each image counts its
17
+ * visual tokens read from its header (image-tokens.ts).
17
18
  */
19
+ import { bodyImages } from "./image-tokens.js";
18
20
  /** Claude 4.7 and later (Opus 4.7+, Sonnet/Haiku 5+, Fable 5). */
19
21
  export const CLAUDE_4_7_PLUS_BYTES_PER_TOKEN = 1.9;
20
22
  /** Claude before 4.7 (4.5, 4.6 and older). */
@@ -44,54 +46,11 @@ export function conservativeTokensFromBytes(bytes, model) {
44
46
  return Math.ceil(bytes / bytesPerTokenForModel(model));
45
47
  }
46
48
  /** Tokens a request body may cost on `model`: its text at the family ratio,
47
- * each image content block (base64 or URL, in a message or a tool_result) at
48
- * one image's maximum.
49
- * A body that does not parse is all text, an over-estimate. */
49
+ * each inline image content block (in a message or a tool_result) at its
50
+ * visual tokens from its header (image-tokens.ts), the tier's maximum when
51
+ * unreadable or not inline. A body that does not parse is all text, an over-estimate. */
50
52
  export function conservativeBodyTokens(body, model) {
51
- const { imageBytes, imageTokens } = imagePayloads(body);
53
+ const { imageBytes, imageTokens } = bodyImages(body, model);
52
54
  return conservativeTokensFromBytes(body.length - imageBytes, model) + imageTokens;
53
55
  }
54
- function imagePayloads(body) {
55
- const totals = { imageBytes: 0, imageTokens: 0 };
56
- // Most bodies carry no image: skip the parse.
57
- if (!body.includes('"image"'))
58
- return totals;
59
- let parsed;
60
- try {
61
- parsed = JSON.parse(body.toString("utf-8"));
62
- }
63
- catch {
64
- return totals;
65
- }
66
- const messages = parsed?.messages;
67
- if (Array.isArray(messages)) {
68
- for (const message of messages) {
69
- const content = message?.content;
70
- if (Array.isArray(content))
71
- countImageBlocks(content, totals);
72
- }
73
- }
74
- return totals;
75
- }
76
- /** Count image blocks among content blocks: a message's content, and
77
- * recursively a tool_result's content. Image-shaped JSON anywhere else (tool
78
- * inputs, schemas, system, metadata) is ordinary text and stays counted as such. */
79
- function countImageBlocks(blocks, totals) {
80
- for (const item of blocks) {
81
- if (!item || typeof item !== "object")
82
- continue;
83
- const block = item;
84
- const source = block.source;
85
- if (block.type === "image" && source && typeof source === "object") {
86
- totals.imageTokens += MAX_IMAGE_TOKENS;
87
- // Base64 is ASCII and never escaped by JSON, so its length is its byte count.
88
- if (source.type === "base64" && typeof source.data === "string") {
89
- totals.imageBytes += source.data.length;
90
- }
91
- }
92
- else if (block.type === "tool_result" && Array.isArray(block.content)) {
93
- countImageBlocks(block.content, totals);
94
- }
95
- }
96
- }
97
56
  //# sourceMappingURL=token-estimate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-estimate.js","sourceRoot":"","sources":["../src/token-estimate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-estimate.js","sourceRoot":"","sources":["../src/token-estimate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,kEAAkE;AAClE,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,CAAC;AACnD,8CAA8C;AAC9C,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,iBAAiB,GACrB,mFAAmF,CAAC;AAEtF,sEAAsE;AACtE,MAAM,UAAU,qBAAqB,CAAC,KAAyB;IAC7D,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,CAAC,EAAE;QAAE,OAAO,qBAAqB,CAAC;IACtC,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,qBAAqB,CAAC;IACnG,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,OAAO,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,6BAA6B,CAAC;AACtE,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,2BAA2B,CAAC,KAAa,EAAE,KAAyB;IAClF,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;yFAGyF;AACzF,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,KAAyB;IAC5E,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5D,OAAO,2BAA2B,CAAC,IAAI,CAAC,MAAM,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,WAAW,CAAC;AACpF,CAAC"}
@@ -0,0 +1,12 @@
1
+ export declare class ToolOutputStore {
2
+ readonly dir: string;
3
+ private readonly now;
4
+ constructor(dir?: string, now?: () => number);
5
+ /** Save `text` and return its path, or undefined when it could not be written. */
6
+ save(text: string): string | undefined;
7
+ /** The directory exists, is a real directory owned by this user, mode 700. */
8
+ private privateDir;
9
+ /** Drop the oldest files over EVICT_AFTER_MS old until both limits hold. */
10
+ private evict;
11
+ }
12
+ //# sourceMappingURL=tool-output-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-output-store.d.ts","sourceRoot":"","sources":["../src/tool-output-store.ts"],"names":[],"mappings":"AA8BA,qBAAa,eAAe;IAExB,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBADX,GAAG,GAAE,MAAkD,EAC/C,GAAG,GAAE,MAAM,MAAiB;IAG/C,kFAAkF;IAClF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAYtC,8EAA8E;IAC9E,OAAO,CAAC,UAAU;IAYlB,4EAA4E;IAC5E,OAAO,CAAC,KAAK;CASd"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Full copies of tool results the proxy shortened to fit the context window
3
+ * (tool-result-truncation.ts), so the model can read the omitted part
4
+ * verbatim with Claude Code's own Read or Grep tools.
5
+ *
6
+ * One file per distinct output and half hour under
7
+ * ~/.claude-code-infinite/tool-outputs/, named by its content hash and the
8
+ * half hour it was first needed (within a half hour the same output gets the
9
+ * same path, so a repeated truncation sends the same bytes), mode 600 in a
10
+ * private mode-700 directory, at most MAX_FILES files and MAX_BYTES bytes.
11
+ *
12
+ * No lock is needed between ccc processes: a path is only ever returned while
13
+ * its file is under BUCKET_MS old, and eviction only removes files over
14
+ * EVICT_AFTER_MS old, so a path handed out is never removed while the request
15
+ * that points at it is on its way. Rewriting the same name writes the same
16
+ * bytes (an atomic rename), so concurrent saves agree.
17
+ */
18
+ import { createHash, randomBytes } from "node:crypto";
19
+ import fs from "node:fs";
20
+ import path from "node:path";
21
+ import { getConfigDir } from "./config.js";
22
+ const MAX_FILES = 64;
23
+ const MAX_BYTES = 512 * 1024 * 1024;
24
+ const NO_FOLLOW = fs.constants.O_NOFOLLOW ?? 0;
25
+ /** A copy is reused only within the half hour its name carries. */
26
+ const BUCKET_MS = 30 * 60 * 1000;
27
+ /** Only copies older than this (twice a bucket) are ever evicted. */
28
+ const EVICT_AFTER_MS = 2 * BUCKET_MS;
29
+ export class ToolOutputStore {
30
+ dir;
31
+ now;
32
+ constructor(dir = path.join(getConfigDir(), "tool-outputs"), now = Date.now) {
33
+ this.dir = dir;
34
+ this.now = now;
35
+ }
36
+ /** Save `text` and return its path, or undefined when it could not be written. */
37
+ save(text) {
38
+ if (!this.privateDir())
39
+ return undefined;
40
+ const name = createHash("sha256").update(text).digest("hex").slice(0, 32);
41
+ const bucket = Math.floor(this.now() / BUCKET_MS);
42
+ const file = path.join(this.dir, `${name}-${bucket}.txt`);
43
+ if (isOurFile(file))
44
+ return file;
45
+ if (!writeAtomically(this.dir, file, text))
46
+ return undefined;
47
+ stamp(file, this.now());
48
+ this.evict();
49
+ return file;
50
+ }
51
+ /** The directory exists, is a real directory owned by this user, mode 700. */
52
+ privateDir() {
53
+ try {
54
+ fs.mkdirSync(this.dir, { recursive: true, mode: 0o700 });
55
+ const stat = fs.lstatSync(this.dir);
56
+ if (!stat.isDirectory() || !ownedByMe(stat))
57
+ return false;
58
+ if ((stat.mode & 0o777) !== 0o700)
59
+ fs.chmodSync(this.dir, 0o700);
60
+ return true;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ /** Drop the oldest files over EVICT_AFTER_MS old until both limits hold. */
67
+ evict() {
68
+ const old = this.now() - EVICT_AFTER_MS;
69
+ const files = listFiles(this.dir).sort((a, b) => b.mtimeMs - a.mtimeMs);
70
+ let bytes = 0;
71
+ files.forEach((entry, i) => {
72
+ bytes += entry.size;
73
+ if (entry.mtimeMs < old && (i >= MAX_FILES || bytes > MAX_BYTES))
74
+ unlinkQuietly(entry.file);
75
+ });
76
+ }
77
+ }
78
+ function listFiles(dir) {
79
+ let names;
80
+ try {
81
+ names = fs.readdirSync(dir);
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ return names.filter((name) => name.endsWith(".txt")).flatMap((name) => {
87
+ const file = path.join(dir, name);
88
+ try {
89
+ const stat = fs.lstatSync(file);
90
+ return stat.isFile() ? [{ file, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ });
96
+ }
97
+ function isOurFile(file) {
98
+ try {
99
+ const stat = fs.lstatSync(file);
100
+ return stat.isFile() && ownedByMe(stat);
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ }
106
+ /** Set a new copy's mtime to the store's clock (its age for eviction). */
107
+ function stamp(file, nowMs) {
108
+ try {
109
+ const now = new Date(nowMs);
110
+ fs.utimesSync(file, now, now);
111
+ }
112
+ catch {
113
+ // Its real mtime is close enough.
114
+ }
115
+ }
116
+ /** Write through an exclusive, unpredictable temporary file and rename it. */
117
+ function writeAtomically(dir, file, text) {
118
+ const tmp = path.join(dir, `.${randomBytes(12).toString("hex")}.tmp`);
119
+ try {
120
+ const fd = fs.openSync(tmp, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | NO_FOLLOW, 0o600);
121
+ try {
122
+ fs.writeFileSync(fd, text);
123
+ }
124
+ finally {
125
+ fs.closeSync(fd);
126
+ }
127
+ fs.renameSync(tmp, file);
128
+ return true;
129
+ }
130
+ catch {
131
+ unlinkQuietly(tmp);
132
+ return false;
133
+ }
134
+ }
135
+ function ownedByMe(stat) {
136
+ return typeof process.getuid !== "function" || stat.uid === process.getuid();
137
+ }
138
+ function unlinkQuietly(file) {
139
+ try {
140
+ fs.unlinkSync(file);
141
+ }
142
+ catch {
143
+ // Already gone, or not ours to remove.
144
+ }
145
+ }
146
+ //# sourceMappingURL=tool-output-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-output-store.js","sourceRoot":"","sources":["../src/tool-output-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Last-resort fit for a single tool result too large for the window even
3
+ * after compression (polychat docs/context_memory_request_pipeline.md,
4
+ * "Prepared compression"): keep its head and tail word for word and replace
5
+ * the middle with a pointer to the full output, instead of refusing the
6
+ * request. The full output is saved first (`saveFull`, tool-output-store.ts),
7
+ * and the pointer names that file, which the model reads verbatim, page by
8
+ * page, with Claude Code's own Read tool (MemTree indexes the conversation
9
+ * too, but its tail read returns at most 40,000 characters of one message).
10
+ */
11
+ export interface TruncationPlan {
12
+ /** The rewritten body; the input is never mutated. */
13
+ body: Record<string, any>;
14
+ /** Characters of the tool result texts shortened, and of them omitted. */
15
+ originalChars: number;
16
+ omittedChars: number;
17
+ /** Where each shortened text was saved whole. */
18
+ savedAt: string[];
19
+ }
20
+ /**
21
+ * Shorten the tool result texts sent verbatim in the body (every user message's
22
+ * tool_result blocks; a compressed prefix carries none), largest first, until
23
+ * the body loses at least `cutChars` characters (or every text worth
24
+ * shortening keeps only the minimum), or null when there is none or
25
+ * `saveFull` could not save one. `saveFull` stores a whole text, returns where.
26
+ * Every message, not only the newest: Claude Code resends an oversized result
27
+ * on the turns after it, and each is shortened the same way again.
28
+ */
29
+ export declare function truncateToolResults(body: Record<string, any>, cutChars: number, saveFull: (text: string) => string | undefined): TruncationPlan | null;
30
+ /** The pointer that stands for the omitted middle. */
31
+ export declare function pointerText(omittedChars: number, totalChars: number, savedAt: string): string;
32
+ //# sourceMappingURL=tool-result-truncation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-result-truncation.d.ts","sourceRoot":"","sources":["../src/tool-result-truncation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAC7C,cAAc,GAAG,IAAI,CAiBvB;AAkBD,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAK7F"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Last-resort fit for a single tool result too large for the window even
3
+ * after compression (polychat docs/context_memory_request_pipeline.md,
4
+ * "Prepared compression"): keep its head and tail word for word and replace
5
+ * the middle with a pointer to the full output, instead of refusing the
6
+ * request. The full output is saved first (`saveFull`, tool-output-store.ts),
7
+ * and the pointer names that file, which the model reads verbatim, page by
8
+ * page, with Claude Code's own Read tool (MemTree indexes the conversation
9
+ * too, but its tail read returns at most 40,000 characters of one message).
10
+ */
11
+ /** Kept text is a multiple of this, so a slightly different overflow on the
12
+ * next request usually produces the same bytes (a prompt-cache hit). */
13
+ const KEEP_QUANTUM_CHARS = 8_000;
14
+ /** Snap a cut to a line break within this distance, when there is one. */
15
+ const LINE_SNAP_CHARS = 2_000;
16
+ /** Never keep less of the result than this; below it there is nothing to show. */
17
+ const MIN_KEEP_CHARS = 2_000;
18
+ /** The head's share of what is kept (errors and summaries often end a log). */
19
+ const HEAD_SHARE = 0.5;
20
+ /**
21
+ * Shorten the tool result texts sent verbatim in the body (every user message's
22
+ * tool_result blocks; a compressed prefix carries none), largest first, until
23
+ * the body loses at least `cutChars` characters (or every text worth
24
+ * shortening keeps only the minimum), or null when there is none or
25
+ * `saveFull` could not save one. `saveFull` stores a whole text, returns where.
26
+ * Every message, not only the newest: Claude Code resends an oversized result
27
+ * on the turns after it, and each is shortened the same way again.
28
+ */
29
+ export function truncateToolResults(body, cutChars, saveFull) {
30
+ const messages = Array.isArray(body.messages) ? [...body.messages] : [];
31
+ const plan = { originalChars: 0, omittedChars: 0, savedAt: [] };
32
+ for (const site of toolTextSites(messages)) {
33
+ if (plan.omittedChars >= cutChars)
34
+ break;
35
+ const cut = shortenSite(site, cutChars - plan.omittedChars, saveFull);
36
+ if (cut === null)
37
+ continue;
38
+ if (cut === undefined)
39
+ return null;
40
+ const message = messages[site.messageIndex];
41
+ messages[site.messageIndex] = { ...message, content: message.content.map((block, i) => i === site.blockIndex ? withToolText(block, site.partIndex, cut.text) : block) };
42
+ plan.originalChars += site.text.length;
43
+ plan.omittedChars += cut.omitted;
44
+ plan.savedAt.push(cut.savedAt);
45
+ }
46
+ if (!plan.savedAt.length)
47
+ return null;
48
+ return { body: { ...body, messages }, ...plan };
49
+ }
50
+ /**
51
+ * One text cut so it loses about `cutChars` (at most down to the minimum):
52
+ * null when it is too short to shorten, undefined when it could not be saved.
53
+ */
54
+ function shortenSite(site, cutChars, saveFull) {
55
+ const longest = pointerText(site.text.length, site.text.length, "").length + PATH_ALLOWANCE;
56
+ const keep = keptChars(site.text.length, cutChars + longest);
57
+ if (keep === null)
58
+ return null;
59
+ const savedAt = saveFull(site.text);
60
+ if (savedAt === undefined)
61
+ return undefined;
62
+ const pointer = (omitted) => pointerText(omitted, site.text.length, savedAt);
63
+ return { ...cutMiddle(site.text, keep, pointer), savedAt };
64
+ }
65
+ /** The pointer that stands for the omitted middle. */
66
+ export function pointerText(omittedChars, totalChars, savedAt) {
67
+ return `\n\n[… output truncated by MemTree to fit the context window: ` +
68
+ `${omittedChars.toLocaleString("en-US")} of ${totalChars.toLocaleString("en-US")} ` +
69
+ `characters omitted here. The full output is saved at ${savedAt}: read the omitted ` +
70
+ `part with the Read tool (offset and limit) or search it with Grep …]\n\n`;
71
+ }
72
+ /** Room left in the pointer estimate for the saved file's path. */
73
+ const PATH_ALLOWANCE = 512;
74
+ /** Every tool result text of the user messages, largest first (newest first on a tie). */
75
+ function toolTextSites(messages) {
76
+ const sites = [];
77
+ messages.forEach((message, messageIndex) => {
78
+ if (message?.role !== "user" || !Array.isArray(message.content))
79
+ return;
80
+ message.content.forEach((block, blockIndex) => {
81
+ if (block?.type !== "tool_result")
82
+ return;
83
+ for (const [partIndex, text] of toolTexts(block.content)) {
84
+ sites.push({ messageIndex, blockIndex, partIndex, text, toolUseId: block.tool_use_id });
85
+ }
86
+ });
87
+ });
88
+ return sites.sort((a, b) => b.text.length - a.text.length || b.messageIndex - a.messageIndex);
89
+ }
90
+ function toolTexts(content) {
91
+ if (typeof content === "string")
92
+ return [[-1, content]];
93
+ if (!Array.isArray(content))
94
+ return [];
95
+ return content.flatMap((part, i) => part?.type === "text" && typeof part.text === "string" ? [[i, part.text]] : []);
96
+ }
97
+ function withToolText(block, partIndex, text) {
98
+ if (partIndex < 0)
99
+ return { ...block, content: text };
100
+ const parts = block.content.map((part, i) => i === partIndex ? { ...part, text } : part);
101
+ return { ...block, content: parts };
102
+ }
103
+ /**
104
+ * Characters of the original to keep, quantized down; at least MIN_KEEP_CHARS
105
+ * (a cut past that keeps the minimum, and the caller measures whether it is
106
+ * enough); null when the result is too short to shorten at all.
107
+ */
108
+ function keptChars(length, cut) {
109
+ if (length <= MIN_KEEP_CHARS * 2)
110
+ return null;
111
+ const keep = Math.floor((length - cut) / KEEP_QUANTUM_CHARS) * KEEP_QUANTUM_CHARS;
112
+ return Math.max(MIN_KEEP_CHARS, keep);
113
+ }
114
+ function cutMiddle(text, keep, pointer) {
115
+ const headEnd = safeBoundary(text, snapToLine(text, Math.floor(keep * HEAD_SHARE), -1));
116
+ const tailStart = Math.max(headEnd, safeBoundary(text, snapToLine(text, text.length - (keep - headEnd), 1)));
117
+ const omitted = tailStart - headEnd;
118
+ return { text: text.slice(0, headEnd) + pointer(omitted) + text.slice(tailStart), omitted };
119
+ }
120
+ /** Move `at` to just after a nearby line break, toward `direction` first. */
121
+ function snapToLine(text, at, direction) {
122
+ const from = Math.max(0, Math.min(text.length, at));
123
+ const found = direction < 0
124
+ ? text.lastIndexOf("\n", from - 1)
125
+ : text.indexOf("\n", from);
126
+ if (found < 0 || Math.abs(found - from) > LINE_SNAP_CHARS)
127
+ return from;
128
+ return found + 1;
129
+ }
130
+ /** Never split a UTF-16 surrogate pair. */
131
+ function safeBoundary(text, at) {
132
+ const code = text.charCodeAt(at);
133
+ return code >= 0xdc00 && code <= 0xdfff ? at + 1 : at;
134
+ }
135
+ //# sourceMappingURL=tool-result-truncation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-result-truncation.js","sourceRoot":"","sources":["../src/tool-result-truncation.ts"],"names":[],"mappings":"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"}