feat(runtime): give ArchiveRead search, line reads, and decoded paging - #4380
Open
liugddx wants to merge 3 commits into
Open
feat(runtime): give ArchiveRead search, line reads, and decoded paging#4380liugddx wants to merge 3 commits into
liugddx wants to merge 3 commits into
Conversation
Once a large tool result is archived, retrieving from it was awkward: there was no way to locate a substring without blind character paging, reads were character-only (poor for line-oriented terminal output), `read` sliced the JSON-escaped serialization rather than the decoded text, and `inspect` gave no preview or coordinate space for plain text/object payloads. Extend ArchiveRead within the existing bounded-response invariant: - add a `search` operation — a literal, case-insensitive substring scan returning matched offsets, line numbers, and bounded context snippets, capped per page with `nextOffset` to resume; - add line-based reads (`unit: "line"`) alongside character offsets, trimmed by binary search to the response budget with `nextLineOffset`; - page the DECODED string for text payloads so offsets land on real characters, not JSON escape bytes (structured payloads still page their canonical JSON); - have `inspect` surface a positional index (totalChars/totalLines) and a short preview for text, object, and scalar payloads. Search is literal (never a regex) so it cannot backtrack pathologically, and every response — search, line, char, inspect — stays within TOOL_RESULT_ARCHIVE_MAX_RESPONSE_CHARS, so reading an archive can never itself trigger another archive. Adds six regression tests covering each capability plus an adversarial dense-match search that stays within budget and resumes. Part of apache#4267. Closes apache#4355. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…eRead The ArchiveRead schema now advertises the `search` operation plus the `unit`/`pattern` parameters and updated descriptions. That tool JSON is part of the headless-coding-v1 provider wire contract frozen by `hosted execution freezes the headless coding provider wire contract`, so its SHA256 legitimately changes. Update the expected tools hash to match the new, intended contract. Part of apache#4267. Follow-up to the ArchiveRead retrieval-ergonomics change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The archived-placeholder readInstructions string is hashed into every model-projection transitionId (buildModelProjectionTransition digests the replacement projection, which embeds readInstructions). Extending this string perturbs those content-derived ids and flips the relative ordering of the two rival transitions in the conversation-copy fold test, which asserts on which SHA256 sorts larger. ArchiveRead's new search/line-unit operations are already advertised to the model through the tool description and parameter schema, so the placeholder hint does not need to change. Restore it to the exact upstream bytes to leave transition identities untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Once a large tool result is archived, retrieving content from it was awkward (issue #4355, part of #4267):
readsliced the JSON-escaped serialization — pages landed on escape bytes (\n,\") rather than decoded text;inspectgave no preview or coordinate space for plain-text / object payloads (onlykeysfor objects,valueTypefor scalars).This extends
ArchiveReadwithin the existing ≤TOOL_RESULT_ARCHIVE_MAX_RESPONSE_CHARSbounded-response invariant, so a read can never itself trigger another archive:searchoperation — a literal, case-insensitive substring scan returning matchedoffset,line, and a bounded contextsnippetper hit; capped per page (TOOL_RESULT_ARCHIVE_MAX_SEARCH_MATCHES) withnextOffset/hasMoreto resume.unit: "line"pages whole lines by line offset/limit, trimmed by binary search to the response budget, withnextLineOffset.unitdefaults to"char"so existing callers are unaffected.inspectpositional index + preview — text payloads reporttotalChars/totalLinesand a shortpreview; object/scalar payloads reporttotalCharsand apreview(objects with anitems[]manifest keep their existing shape).Why it's safe
TOOL_RESULT_ARCHIVE_MAX_RESPONSE_CHARS— search stops adding matches, and line reads binary-search their line count, before the envelope overflows.active-tool-result-prune.ts) and the upstream Shell capture/preservation contract are deliberately untouched, per the audit.Tests
Six regression tests in
tool-result-archive-resource.test.ts:inspectsurfaces a positional index + preview for text payloads.readpages the decoded string, not the escaped JSON.readby line range returns whole lines and resumes withnextLineOffset.searchlocates a case-insensitive substring with offsets, line numbers, and snippets.searchstays within the response budget and resumes (nextOffset) under a pathological dense-match input.searchwithout apatternfails closed.Causal proof (fail-without / pass-with): with the production dispatch temporarily reverted to the old char-only / serialized-JSON behavior, all six new tests fail (
# fail 8, the extra two being the pre-existing inspect-manifest tests under the crude stub); with the change restored, the suite is green (# pass 11).Part of #4267. Closes #4355.