Skip to content

Commit 5d929f7

Browse files
committed
refactor(opencode): simplify tool output disable config
1 parent d4f83ba commit 5d929f7

7 files changed

Lines changed: 14 additions & 42 deletions

File tree

packages/opencode/src/config/config.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,7 @@ const log = Log.create({ service: "config" })
4949
// Custom merge function that concatenates array fields instead of replacing them
5050
// Keep remeda's deep conditional merge type out of hot config-loading paths; TS profiling showed it dominates here.
5151
function mergeConfig(target: Info, source: Info): Info {
52-
const merged = mergeDeep(target, source) as Info
53-
if (!target.tool_output || !source.tool_output) return merged
54-
if (target.tool_output.truncate !== false && source.tool_output.truncate !== false) return merged
55-
56-
// Disabled truncation and custom limits are separate config modes; the later layer selects the mode.
57-
merged.tool_output = source.tool_output
58-
return merged
52+
return mergeDeep(target, source) as Info
5953
}
6054

6155
function mergeConfigConcatArrays(target: Info, source: Info): Info {
@@ -260,13 +254,8 @@ export const Info = Schema.Struct({
260254
),
261255
tool_output: Schema.optional(
262256
Schema.Union([
257+
Schema.Literal(false).annotate({ description: "Disable tool output truncation" }),
263258
Schema.Struct({
264-
truncate: Schema.Literal(false).annotate({ description: "Disable tool output truncation" }),
265-
}).annotate({ parseOptions: { onExcessProperty: "error" } }),
266-
Schema.Struct({
267-
truncate: Schema.optional(Schema.Literal(true)).annotate({
268-
description: "Enable truncating tool output that exceeds the configured limits (default: true)",
269-
}),
270259
max_lines: Schema.optional(PositiveInt).annotate({
271260
description: "Maximum lines of tool output before it is truncated and saved to disk (default: 2000)",
272261
}),

packages/opencode/src/tool/truncate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export interface Interface {
4242
readonly output: (text: string, options?: Options, agent?: Agent.Info) => Effect.Effect<Result>
4343
/**
4444
* Resolved truncation limits from `tool_output` in opencode config.
45-
* Returns `None` when the user has disabled truncation (`tool_output.truncate: false`),
45+
* Returns `None` when the user has disabled truncation (`tool_output: false`),
4646
* in which case callers should pass output through without enforcing thresholds.
4747
*/
4848
readonly limits: () => Effect.Effect<Option.Option<Limits>>
@@ -81,7 +81,7 @@ export const layer = Layer.effect(
8181
if (Option.isNone(configSvc)) return Option.some({ maxLines: MAX_LINES, maxBytes: MAX_BYTES })
8282
const cfg = yield* configSvc.value.get().pipe(Effect.catch(() => Effect.succeed(undefined)))
8383
const tool_output = cfg?.tool_output
84-
if (tool_output?.truncate === false) return Option.none<Limits>()
84+
if (tool_output === false) return Option.none<Limits>()
8585
return Option.some({
8686
maxLines: tool_output?.max_lines ?? MAX_LINES,
8787
maxBytes: tool_output?.max_bytes ?? MAX_BYTES,

packages/opencode/test/config/config.test.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,25 +1292,20 @@ test("config parser preserves permission order while rejecting unknown top-level
12921292
}
12931293
})
12941294

1295-
test("tool_output only accepts thresholds when truncation is enabled", () => {
1296-
expect(ConfigParse.schema(Config.Info, { tool_output: { truncate: false } }, "test").tool_output).toEqual({
1297-
truncate: false,
1298-
})
1295+
test("tool_output accepts thresholds or disables truncation", () => {
1296+
expect(ConfigParse.schema(Config.Info, { tool_output: false }, "test").tool_output).toBe(false)
12991297
expect(
13001298
ConfigParse.schema(Config.Info, { tool_output: { max_lines: 200, max_bytes: 8192 } }, "test").tool_output,
13011299
).toEqual({
13021300
max_lines: 200,
13031301
max_bytes: 8192,
13041302
})
1305-
expect(() =>
1306-
ConfigParse.schema(Config.Info, { tool_output: { truncate: false, max_lines: 200, max_bytes: 8192 } }, "test"),
1307-
).toThrow()
13081303
})
13091304

13101305
it.effect("project tool_output limits replace disabled global truncation", () =>
13111306
withConfigTree(
13121307
{
1313-
global: { tool_output: { truncate: false } },
1308+
global: { tool_output: false },
13141309
project: { tool_output: { max_lines: 200 } },
13151310
},
13161311
Effect.gen(function* () {
@@ -1323,10 +1318,10 @@ it.effect("project disabled tool_output replaces global limits", () =>
13231318
withConfigTree(
13241319
{
13251320
global: { tool_output: { max_lines: 200, max_bytes: 8192 } },
1326-
project: { tool_output: { truncate: false } },
1321+
project: { tool_output: false },
13271322
},
13281323
Effect.gen(function* () {
1329-
expect((yield* Config.use.get()).tool_output).toEqual({ truncate: false })
1324+
expect((yield* Config.use.get()).tool_output).toBe(false)
13301325
}),
13311326
),
13321327
)

packages/opencode/test/tool/shell.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ describe("tool.shell truncation", () => {
12071207

12081208
it.live("does not truncate output when tool_output is disabled", () =>
12091209
Effect.gen(function* () {
1210-
const tmp = yield* tmpdirScoped({ config: { tool_output: { truncate: false } } })
1210+
const tmp = yield* tmpdirScoped({ config: { tool_output: false } })
12111211
yield* runIn(
12121212
tmp,
12131213
Effect.gen(function* () {

packages/opencode/test/tool/truncation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ describe("Truncate", () => {
166166
}),
167167
)
168168

169-
const disabledIt = configuredIt({ tool_output: { truncate: false } })
169+
const disabledIt = configuredIt({ tool_output: false })
170170
disabledIt.live("does not truncate output when disabled", () =>
171171
Effect.gen(function* () {
172172
const content = "a".repeat(Truncate.MAX_BYTES + 1)

packages/sdk/js/src/v2/gen/types.gen.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,14 +1298,8 @@ export type Config = {
12981298
* Configure tool output truncation. When output exceeds either limit, the full text is written to the truncation directory and a preview is returned.
12991299
*/
13001300
tool_output?:
1301+
| false
13011302
| {
1302-
/**
1303-
* Disable tool output truncation
1304-
*/
1305-
truncate: false
1306-
}
1307-
| {
1308-
truncate?: true
13091303
max_lines?: number
13101304
max_bytes?: number
13111305
}

packages/web/src/content/docs/config.mdx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,32 +361,26 @@ You can control when tool output is truncated using the `tool_output` option. Wh
361361
{
362362
"$schema": "https://opencode.ai/config.json",
363363
"tool_output": {
364-
"truncate": true,
365364
"max_lines": 2000,
366365
"max_bytes": 51200
367366
}
368367
}
369368
```
370369

371-
- `truncate` - Truncate tool output when it exceeds a configured threshold (default: `true`).
372370
- `max_lines` - Maximum number of lines before output is truncated (default: `2000`).
373371
- `max_bytes` - Maximum size in bytes before output is truncated (default: `51200`).
374372

375373
These thresholds apply to output handled by OpenCode's shared truncation layer, including MCP and plugin tool output. Individual tools that page or cap their own results can have separate limits.
376374

377-
To disable shared tool output truncation, set `truncate` to `false`:
375+
To disable shared tool output truncation, set `tool_output` to `false`:
378376

379377
```json title="opencode.json"
380378
{
381379
"$schema": "https://opencode.ai/config.json",
382-
"tool_output": {
383-
"truncate": false
384-
}
380+
"tool_output": false
385381
}
386382
```
387383

388-
`truncate: false` cannot be combined with `max_lines` or `max_bytes`; thresholds only apply when truncation is enabled.
389-
390384
---
391385

392386
### Models

0 commit comments

Comments
 (0)