feat(core): allow disabling tool output truncation#28907
Conversation
Resolve conflict in packages/opencode/src/tool/shell/prompt.ts to combine truncationGuidance helper (which omits the truncation note when truncation is disabled) with the configurable defaultTimeoutMs from origin/dev. Fix typecheck in tool/truncate.ts by narrowing the tool_output union before reading max_lines and max_bytes.
Replace the `{ enabled: boolean; maxLines: number; maxBytes: number }`
shape with `Option<{ maxLines: number; maxBytes: number }>` so the absence
of limits is represented by the type system instead of a boolean flag with
dead numeric fields.
- Truncate.limits() now returns Effect<Option<Limits>>.
- Truncate.output() short-circuits on None instead of checking .enabled.
- shell tool gates rolling buffer, disk spill, and tail truncation on
Option.isSome(limits); behavior unchanged when truncation is enabled.
- ShellPrompt.render and helpers accept Option<Limits>; the truncation
guidance line is omitted when None.
- Tests updated to assert Option.isSome / Option.isNone.
|
/review |
|
/review |
| if (target.tool_output.truncate !== false && source.tool_output.truncate !== false) return merged | ||
|
|
||
| // Disabled truncation and custom limits are separate config modes; the later layer selects the mode. | ||
| merged.tool_output = source.tool_output |
There was a problem hiding this comment.
Suggestion: this replacement handles layered config loads, but the update and updateGlobal write paths later in this file still use raw mergeDeep. If an existing config has tool_output.max_lines or tool_output.max_bytes and the API writes { tool_output: { truncate: false } }, the persisted JSON can keep the old thresholds beside truncate: false, which this schema now rejects on the next load. Consider applying the same replacement semantics in those write paths when either side changes tool_output mode.
|
/review |
| @@ -499,7 +502,7 @@ export const ShellTool = Tool.define( | |||
| sink?.write(chunk) | |||
There was a problem hiding this comment.
Suggestion: when tool_output is false, this condition prevents writing to disk, but full += chunk still runs on every chunk even though full is never read in the disabled path (the final output comes from list/raw). For large outputs this keeps a second copy of the whole stream in memory. Consider skipping the full buffer entirely when limits is None so disabled truncation only stores the one buffer needed to return the untruncated output.
Summary
tool_output: falseto disable shared tool output truncation while keeping{ max_lines, max_bytes }for custom thresholdshttps://opencode.ai/config.jsonselectively rather than advocate disabling truncationConfiguration
{ "tool_output": false }Or configure thresholds while truncation is enabled:
{ "tool_output": { "max_lines": 200, "max_bytes": 8192 } }Using
falserather than a disabled object variant allows ordinary config merging and updates to switch between disabled truncation and configured limits without producing an invalid combined shape.Verification
bun test test/config/config.test.ts test/tool/truncation.test.ts test/tool/shell.test.tsfrompackages/opencodebun typecheckfrompackages/opencodebun run buildfrompackages/web./packages/sdk/js/script/build.tsgit diff --checkAddresses the configuration and documentation portions of #13770. Other reported behavior concerns in that issue remain separate.
Closes: #11313