claude-code-infinite 1.0.29 → 1.0.31
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/README.md +65 -7
- package/dist/cli-args.d.ts +10 -0
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +30 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-lifecycle.d.ts +45 -1
- package/dist/cli-lifecycle.d.ts.map +1 -1
- package/dist/cli-lifecycle.js +59 -0
- package/dist/cli-lifecycle.js.map +1 -1
- package/dist/cli-main.js +61 -16
- package/dist/cli-main.js.map +1 -1
- package/dist/count-tokens.d.ts +15 -0
- package/dist/count-tokens.d.ts.map +1 -1
- package/dist/count-tokens.js +23 -1
- package/dist/count-tokens.js.map +1 -1
- package/dist/diagnostics-schema.d.ts.map +1 -1
- package/dist/diagnostics-schema.js +5 -0
- package/dist/diagnostics-schema.js.map +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +18 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/final-index.d.ts +7 -1
- package/dist/final-index.d.ts.map +1 -1
- package/dist/final-index.js +10 -3
- package/dist/final-index.js.map +1 -1
- package/dist/hooks.d.ts +24 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +24 -2
- package/dist/hooks.js.map +1 -1
- package/dist/image-refs.d.ts +51 -0
- package/dist/image-refs.d.ts.map +1 -0
- package/dist/image-refs.js +169 -0
- package/dist/image-refs.js.map +1 -0
- package/dist/image-tokens.d.ts +37 -0
- package/dist/image-tokens.d.ts.map +1 -0
- package/dist/image-tokens.js +158 -0
- package/dist/image-tokens.js.map +1 -0
- package/dist/memtree-body.d.ts +52 -0
- package/dist/memtree-body.d.ts.map +1 -0
- package/dist/memtree-body.js +99 -0
- package/dist/memtree-body.js.map +1 -0
- package/dist/memtree-mcp.d.ts.map +1 -1
- package/dist/memtree-mcp.js +4 -0
- package/dist/memtree-mcp.js.map +1 -1
- package/dist/memtree.d.ts +86 -3
- package/dist/memtree.d.ts.map +1 -1
- package/dist/memtree.js +283 -53
- package/dist/memtree.js.map +1 -1
- package/dist/model-context.d.ts +80 -0
- package/dist/model-context.d.ts.map +1 -0
- package/dist/model-context.js +192 -0
- package/dist/model-context.js.map +1 -0
- package/dist/paused-session.d.ts.map +1 -1
- package/dist/paused-session.js +11 -8
- package/dist/paused-session.js.map +1 -1
- package/dist/payment-gate.d.ts +2 -0
- package/dist/payment-gate.d.ts.map +1 -1
- package/dist/payment-gate.js +1 -1
- package/dist/payment-gate.js.map +1 -1
- package/dist/prefix-store.d.ts +2 -0
- package/dist/prefix-store.d.ts.map +1 -1
- package/dist/prefix-store.js +4 -0
- package/dist/prefix-store.js.map +1 -1
- package/dist/prepared-compression.d.ts +78 -0
- package/dist/prepared-compression.d.ts.map +1 -0
- package/dist/prepared-compression.js +127 -0
- package/dist/prepared-compression.js.map +1 -0
- package/dist/proxy.d.ts +370 -14
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +797 -94
- package/dist/proxy.js.map +1 -1
- package/dist/reqlog.d.ts +55 -0
- package/dist/reqlog.d.ts.map +1 -1
- package/dist/reqlog.js.map +1 -1
- package/dist/request-sizing.d.ts +21 -2
- package/dist/request-sizing.d.ts.map +1 -1
- package/dist/request-sizing.js +57 -11
- package/dist/request-sizing.js.map +1 -1
- package/dist/route-identity.d.ts +27 -0
- package/dist/route-identity.d.ts.map +1 -1
- package/dist/route-identity.js +88 -8
- package/dist/route-identity.js.map +1 -1
- package/dist/token-estimate.d.ts +3 -20
- package/dist/token-estimate.d.ts.map +1 -1
- package/dist/token-estimate.js +9 -50
- package/dist/token-estimate.js.map +1 -1
- package/dist/tool-output-store.d.ts +12 -0
- package/dist/tool-output-store.d.ts.map +1 -0
- package/dist/tool-output-store.js +146 -0
- package/dist/tool-output-store.js.map +1 -0
- package/dist/tool-result-truncation.d.ts +32 -0
- package/dist/tool-result-truncation.d.ts.map +1 -0
- package/dist/tool-result-truncation.js +135 -0
- package/dist/tool-result-truncation.js.map +1 -0
- package/package.json +1 -1
package/dist/token-estimate.js
CHANGED
|
@@ -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
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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 (
|
|
48
|
-
*
|
|
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 } =
|
|
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":"AAAA
|
|
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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"}
|