Skip to content

Commit 733b665

Browse files
committed
refactor(read-file): resume large reads by same-path offset only
Drop the dual footer and live-cursor reuse so continuation is a single stateless path+offset notice, matching the single-way resume direction. Pre-existing cursor tests become same-URI+offset chains; the truncation 10k exemption keys on the offset footer only. Paging mechanics untouched.
1 parent 48231b0 commit 733b665

3 files changed

Lines changed: 15 additions & 25 deletions

File tree

‎src/plugins/read-file-guard-plugin.test.ts‎

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -389,41 +389,34 @@ describe("CL-8979 large-file pagination", () => {
389389
);
390390
}, 120_000);
391391

392-
test("chains cursor resumption on a blob past the scan ceiling without re-scanning", async () => {
392+
test("chains same-URI+offset continuation on a blob past the scan ceiling without re-scanning", async () => {
393393
const rows = Array.from({ length: BIG_LINES }, (_, i) => bigRow(i));
394394
const bytes = new TextEncoder().encode(`${rows.join("\n")}\n`);
395395
const run = blobChainRunner(async (key) => {
396396
if (key === "cl8979-blob") return bytes;
397397
throw new Error(`missing ${key}`);
398398
});
399399
const collected: string[] = [];
400-
let path = "tool-output:///cl8979-blob";
400+
const path = "tool-output:///cl8979-blob";
401+
let offset = 0;
401402
let hops = 0;
402403
let sawOffsetFooter = false;
403-
let sawCursorAlias = false;
404404
for (;;) {
405-
const result = await run(`blob-${hops}`, { path, limit: 200 });
405+
const result = await run(`blob-${hops}`, { path, limit: 200, offset });
406406
hops += 1;
407407
const content = String(result.content);
408408
expect(result.isError).toBeFalsy();
409409
expect(content).not.toContain("scan limit");
410410
collected.push(...bodyRows(content));
411-
const cursor = /Use path="(tool-output:\/\/\/[^"]+)"/.exec(content);
412-
const offset = continueOffset(content);
413-
if (offset !== null) {
414-
sawOffsetFooter = true;
415-
path = "tool-output:///cl8979-blob";
416-
}
417-
if (cursor !== null) {
418-
sawCursorAlias = true;
419-
path = cursor[1] as string;
420-
}
421-
if (offset === null && cursor === null) break;
411+
const next = continueOffset(content);
412+
if (next === null) break;
413+
sawOffsetFooter = true;
414+
expect(next).toBeGreaterThan(offset);
415+
offset = next;
422416
expect(hops).toBeLessThan(2000);
423417
}
424418
expect(hops).toBeGreaterThan(1);
425419
expect(sawOffsetFooter).toBe(true);
426-
expect(sawCursorAlias).toBe(true);
427420
expect(collected.length).toBe(BIG_LINES);
428421
expect(collected[BIG_LINES - 1]).toBe(bigRow(BIG_LINES - 1));
429422
}, 120_000);

‎src/plugins/read-file-guard-plugin.ts‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ export const READ_FILE_MAX_SCAN_BYTES = 8 * 1024 * 1024;
3030
/** Refuse tool-output blobs larger than this before bounded paging. */
3131
export const READ_FILE_MAX_TOOL_OUTPUT_BYTES = READ_FILE_MAX_SCAN_BYTES;
3232
// Headroom reserved out of the byte budget for the continuation notice, so the
33-
// returned payload including the notice stays under READ_FILE_MAX_BYTES. Sized
34-
// for a dual footer: the plain `Use offset=` continuation plus the appended
35-
// single-use cursor alias on byte/scan-limit pages.
36-
const NOTICE_RESERVE_BYTES = 384;
33+
// returned payload including the notice stays under READ_FILE_MAX_BYTES.
34+
const NOTICE_RESERVE_BYTES = 256;
3735

3836
const LINE_TRUNC_SUFFIX = ` ... [line truncated at ${READ_FILE_MAX_LINE_LENGTH} chars; full line remains in the file — use grep to match within the line]`;
3937
const TOOL_OUTPUT_CHUNK_BYTES = 64 * 1024;

‎src/plugins/result-truncation-plugin.ts‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,12 +294,11 @@ export async function applyToolResultTruncation(
294294
}
295295

296296
// A read_file page already carries its own continuation contract (a plain
297-
// `Use offset=` footer, a single-use cursor alias, or both). Re-cutting it at
298-
// the 10k leisure cap would slice the footer off the page boundary and strand
299-
// the pagination chain, so footer-bearing read_file pages pass through intact.
297+
// `Use offset=` footer). Re-cutting it at the 10k leisure cap would slice the
298+
// footer off the page boundary and strand the pagination chain, so
299+
// footer-bearing read_file pages pass through intact.
300300
// Pages without a footer take the normal path.
301-
const READ_FILE_CONTINUATION_RE =
302-
/Use offset=\d+ to continue\.|Use path="tool-output:\/\/\//;
301+
const READ_FILE_CONTINUATION_RE = /Use offset=\d+ to continue\./;
303302

304303
function isPagedReadFilePage(
305304
toolName: string | undefined,

0 commit comments

Comments
 (0)