fix: cap oversized tool results - #786
Conversation
luisangelrod
left a comment
There was a problem hiding this comment.
The hard-cap behavior here is well specified: the marker is deducted from contentBudget, and the tests assert result.length === maxLength at both the helper and call-site levels. I traced the normal, optimized MessageBuilder, ACP/plain (through processToolUse), and direct subagent paths; the coverage matches the issue's intended choke points while leaving structured payloads intact.
One merge-order concern: #777 adds a second shared 40/60 head-tail helper (truncateHeadAndTail) for the two existing 2,000-character call sites. Its limit means “retained source characters,” so its returned string exceeds the limit once the marker is added; this PR's truncateToolResult correctly treats the limit as a hard ceiling. If both land unchanged, the repo will have two near-identical helpers with incompatible budget semantics.
I recommend coordinating the two PRs so there is one explicit contract: either make #777 reuse this hard-cap helper (with a configurable/actionable marker if needed), or keep the specialized helper but name/document its retained-content semantics clearly. For the global cap, I would preserve this PR's exact-length behavior.
CI confirms type, format, lint, build, dependency, audit, and security checks are green. The unit-test job is red, matching the unrelated settings-tab baseline failure disclosed in the PR; I did not reproduce the full suite locally because the checkout's frozen install currently reports a patchedDependencies/lockfile mismatch.
|
Hey @RealBhupesh! Thanks for this. Picking Two things before I can merge it. Structured results bypass the cap entirely. The PR caps const output =
msg.structuredContent !== undefined
? ({type: 'json', value: msg.structuredContent} as const)
: ({type: 'text', value: msg.content} as const);When a tool returns structured output the capped text is discarded and the uncapped JSON is what actually reaches the model, so the cap is a no-op on exactly those calls. Right now only There is now a duplicate helper. This is my fault for not sequencing the issues better: #777 landed earlier today and added Worth saying that yours is the better of the two and should be the one that survives. You subtract the marker from the budget before splitting; #777's does not: So the consolidation I'd like is to keep your marker-aware budgeting and move #777's two call sites ( Separately, this branch is 53 commits behind |
f9c61bc to
7786a76
Compare
|
Thanks for the careful review. All requested blockers are addressed in the rebased branch:
Focused changed-area suites pass (126 tests), and format, lint, Knip, audit, and diff checks pass locally. The three red workflow jobs now reproduce on current |
Summary
Closes #769
Part of #772
Root cause
Tool results enter model context through several execution paths. Structured results also replace text in the AI SDK converter, so capping only
contentleft diagnostics and future MCP JSON unbounded.Validation
pnpm run test:formatpnpm run test:lintpnpm run test:knippnpm run test:auditgit diff --checkCurrent type/build/unit CI failures are inherited from the ACP SDK regression on
main; prerequisite fix: #830.