docs(codemode): clarify output byte budget

This commit is contained in:
Aiden Cline 2026-07-08 13:50:31 -05:00
parent b2f5c07fd1
commit f3c28008de
4 changed files with 11 additions and 8 deletions

View file

@ -265,7 +265,7 @@ The limits are exactly three knobs:
| ---------------- | -------------------: | -------------------------------------------------------------------- |
| `timeoutMs` | none - no timeout | Wall-clock execution time. |
| `maxToolCalls` | none - unlimited | Tool calls admitted during the execution. |
| `maxOutputBytes` | none - no truncation | Model-facing output: result value, unhandled rejections, and logs. |
| `maxOutputBytes` | none - no truncation | Retained payload: result value, unhandled rejections, and logs. |
No limit has a default, on purpose: execution budgets are host policy, not library policy - a host that wants a bound sets one; a host that can interrupt the execution fiber (as OpenCode does on user cancel) may set no timeout, and a host with its own tool-output truncation (as OpenCode has) may leave `maxOutputBytes` unset. A host with neither should set `maxOutputBytes`, or oversized results silently flood model context.
@ -283,6 +283,8 @@ const runtime = CodeMode.make({
Limits are safe integers. `timeoutMs` must be at least `1`; the others may be `0`. Invalid configuration throws a `RangeError` when `CodeMode.make` or `CodeMode.execute` is called. An explicitly `undefined` value is the same as leaving the limit unset.
`maxOutputBytes` is a payload budget, not a strict byte cap on the final rendered tool message. It counts the serialized result value, retained rejection diagnostics, and retained log lines. Fixed truncation notices and framing added by a host when it renders the structured result are additional and may make the final message exceed the configured number.
Exceeding a configured `maxOutputBytes` never fails the execution. An oversized result value is replaced by its truncated serialized text plus an explanatory marker, leading unhandled rejections and logs are kept within the remaining budget, omitted entries receive a summary marker, and the result carries `truncated: true`.
When configured, the timeout interrupts in-flight tool Effects, including eagerly started calls the program has not awaited (their fibers are supervised by the execution). The interpreter yields cooperatively between steps, so the timeout also interrupts pure busy loops (`while (true) {}`) - no separate work budget exists. Tool implementations remain responsible for making their external operations interruptible or independently bounded.

View file

@ -73,7 +73,8 @@ fibers instead. At most eight tool calls execute concurrently.
The public execution-policy knobs are `timeoutMs`, `maxToolCalls`, and `maxOutputBytes`. The package supplies no
defaults because budgets are host policy. The interpreter also enforces fixed internal boundaries for tool-call
concurrency and data nesting depth.
concurrency and data nesting depth. `maxOutputBytes` bounds retained payload bytes, not the complete rendered message;
fixed truncation notices and host-added framing are intentionally outside the budget.
### Data, files, and failures

View file

@ -17,7 +17,7 @@ export type ExecutionLimits = {
readonly timeoutMs?: number
/** Maximum number of tool calls admitted by the runtime. No default: absent means unlimited. */
readonly maxToolCalls?: number
/** Maximum UTF-8 bytes of model-facing output. No default: absent means no truncation. */
/** Maximum UTF-8 bytes retained from output payloads. Fixed truncation notices and host formatting are additional. */
readonly maxOutputBytes?: number
}

View file

@ -3557,11 +3557,11 @@ const utf8Truncate = (value: string, maxBytes: number): string => {
}
/**
* Bounds the model-facing output (serialized result value plus logs) to `maxOutputBytes`.
* Oversized values are replaced by their truncated serialized text with an explanatory marker,
* and logs are kept from the start until the remaining budget is exhausted. Truncation never
* fails the execution; `truncated: true` marks affected results. Only runs when the host set
* `maxOutputBytes` - with the limit absent, output passes through unbounded.
* Bounds retained payload bytes (serialized result value, rejection diagnostics, and logs) to
* `maxOutputBytes`. Fixed truncation notices are added outside that payload budget, as is any
* framing added when a host renders the structured result. Truncation never fails the execution;
* `truncated: true` marks affected results. Only runs when the host set `maxOutputBytes` - with
* the limit absent, output passes through unbounded.
*/
const boundOutput = (result: Result, maxOutputBytes: number): Result => {
let truncated = false