You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(read-file): page large read_file responses through to the end
Large-file pages used to dead-end: the scan ceiling fired while unread
content remained, overlong lines were grep-only, and the 10k re-cut
mangled footer-bearing pages. Resume now seeks to the stored point,
pages carry both offset and cursor continuations, and footer-bearing
pages pass the truncation layer untouched.
// Headroom reserved out of the byte budget for the continuation notice, so the
32
-
// returned payload including the notice stays under READ_FILE_MAX_BYTES.
33
-
constNOTICE_RESERVE_BYTES=256;
35
+
// returned payload including the notice stays under READ_FILE_MAX_BYTES. Sized
36
+
// for a dual footer: the plain `Use offset=` continuation plus the appended
37
+
// single-use cursor alias on byte/scan-limit pages.
38
+
constNOTICE_RESERVE_BYTES=384;
34
39
35
40
constLINE_TRUNC_SUFFIX=` ... [line truncated at ${READ_FILE_MAX_LINE_LENGTH} chars; full line remains in the file — use grep to match within the line]`;
return`Use path="${TOOL_OUTPUT_URI_PREFIX}///${id}" (same tool, no offset needed) to continue reading the remainder — a fresh, working handle, not the original path.]`;
104
+
}
105
+
83
106
functionmintCursor(
84
107
content: string,
85
108
cursors: Map<string,ReadCursor>,
@@ -90,6 +113,19 @@ function mintCursor(
90
113
constmatch=CONTINUE_OFFSET_RE.exec(content);
91
114
if(match===null)returncontent;
92
115
constoffset=Number(match[1]);
116
+
// Re-reading an unconsumed resumption point reuses its live cursor, so two
117
+
// independent reads of the same page carry the same handle and the page
`Use path="${TOOL_OUTPUT_URI_PREFIX}///${cursorId}" (same tool, no offset needed) to continue reading the remainder — a fresh, working handle, not the original path.]`,
109
-
);
142
+
constalias=cursorAlias(cursorId);
143
+
if(LINE_LIMIT_NOTICE_RE.test(content)){
144
+
returncontent.replace(CONTINUE_OFFSET_RE,alias);
145
+
}
146
+
return`${content.slice(0,-1)} Or ${alias}`;
110
147
}
111
148
112
149
// Bound the source shown in a stale-cursor message: an adversarial or
@@ -161,6 +198,13 @@ function mapFilesystemStreamError(
161
198
* When `wrapLongLines` is set, overlong lines are split into successive numbered
162
199
* windows instead of being truncated and dropped — so a giant JSON line can be
163
200
* paged through with the same offset/cursor protocol as a multi-line file.
201
+
* When `windowHugeLines` is set instead, only single lines that on their own
202
+
* exceed the output budget are windowed; ordinary lines keep their numbers, so
"Read a file and return its content with line numbers. The path argument accepts either a filesystem path or a tool-output URI of the form tool-output:///{callId} that references a prior tool result.",
45
+
"Read a file and return its content with line numbers. The path argument accepts either a filesystem path or a tool-output URI of the form tool-output:///{callId} that references a prior tool result. Large files are returned one page at a time: pass offset and limit to page through the file, then follow the `Use offset=N to continue.` footer to read the next page through to the end.",
0 commit comments