core-agent-ide/codex-rs/core
K Bediako ab99df0694
Fix: cap aggregated exec output consistently (#9759)
## WHAT?
- Bias aggregated output toward stderr under contention (2/3 stderr, 1/3
stdout) while keeping the 1 MiB cap.
- Rebalance unused stderr share back to stdout when stderr is tiny to
avoid underfilling.
- Add tests for contention, small-stderr rebalance, and under-cap
ordering (stdout then stderr).

## WHY?
- Review feedback requested stderr priority under contention.
- Avoid underfilled aggregated output when stderr is small while
preserving a consistent cap across exec paths.

## HOW?
- Update `aggregate_output` to compute stdout/stderr shares, then
reassign unused capacity to the other stream.
- Use the helper in both Windows and async exec paths.
- Add regression tests for contention/rebalance and under-cap ordering.

## BEFORE
```rust
// Best-effort aggregate: stdout then stderr (capped).
let mut aggregated = Vec::with_capacity(
    stdout
        .text
        .len()
        .saturating_add(stderr.text.len())
        .min(EXEC_OUTPUT_MAX_BYTES),
);
append_capped(&mut aggregated, &stdout.text, EXEC_OUTPUT_MAX_BYTES);
append_capped(&mut aggregated, &stderr.text, EXEC_OUTPUT_MAX_BYTES);
let aggregated_output = StreamOutput {
    text: aggregated,
    truncated_after_lines: None,
};
```

## AFTER
```rust
fn aggregate_output(
    stdout: &StreamOutput<Vec<u8>>,
    stderr: &StreamOutput<Vec<u8>>,
) -> StreamOutput<Vec<u8>> {
    let total_len = stdout.text.len().saturating_add(stderr.text.len());
    let max_bytes = EXEC_OUTPUT_MAX_BYTES;
    let mut aggregated = Vec::with_capacity(total_len.min(max_bytes));

    if total_len <= max_bytes {
        aggregated.extend_from_slice(&stdout.text);
        aggregated.extend_from_slice(&stderr.text);
        return StreamOutput {
            text: aggregated,
            truncated_after_lines: None,
        };
    }

    // Under contention, reserve 1/3 for stdout and 2/3 for stderr; rebalance unused stderr to stdout.
    let want_stdout = stdout.text.len().min(max_bytes / 3);
    let want_stderr = stderr.text.len();
    let stderr_take = want_stderr.min(max_bytes.saturating_sub(want_stdout));
    let remaining = max_bytes.saturating_sub(want_stdout + stderr_take);
    let stdout_take = want_stdout + remaining.min(stdout.text.len().saturating_sub(want_stdout));

    aggregated.extend_from_slice(&stdout.text[..stdout_take]);
    aggregated.extend_from_slice(&stderr.text[..stderr_take]);

    StreamOutput {
        text: aggregated,
        truncated_after_lines: None,
    }
}
```

## TESTS
- [x] `just fmt`
- [x] `just fix -p codex-core`
- [x] `cargo test -p codex-core aggregate_output_`
- [x] `cargo test -p codex-core`
- [x] `cargo test --all-features`

## FIXES
Fixes #9758
2026-01-27 09:29:12 +00:00
..
src Fix: cap aggregated exec output consistently (#9759) 2026-01-27 09:29:12 +00:00
templates make plan prompt less detailed (#9977) 2026-01-26 21:42:01 -08:00
tests make cached web_search client-side default (#9974) 2026-01-26 21:25:40 -08:00
BUILD.bazel merge remote models (#9547) 2026-01-20 14:02:07 -08:00
Cargo.toml Another round of improvements for config error messages (#9746) 2026-01-23 20:11:09 -08:00
config.schema.json Warn users on enabling underdevelopment features (#9954) 2026-01-27 01:58:05 +00:00
gpt-5.1-codex-max_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt-5.2-codex_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt_5_1_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt_5_2_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
gpt_5_codex_prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
hierarchical_agents_message.md Add hierarchical agent prompt (#8996) 2026-01-09 13:47:37 -08:00
models.json Update models.json (#9726) 2026-01-23 00:44:47 +00:00
prompt.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
prompt_with_apply_patch_instructions.md Assemble sandbox/approval/network prompts dynamically (#8961) 2026-01-12 23:12:59 +00:00
README.md feat: add support for read-only bind mounts in the linux sandbox (#9112) 2026-01-14 08:30:46 -08:00
review_prompt.md docs: Fix markdown list item spacing in codex-rs/core/review_prompt.md (#4144) 2025-10-30 17:39:21 -07:00

codex-core

This crate implements the business logic for Codex. It is designed to be used by the various Codex UIs written in Rust.

Dependencies

Note that codex-core makes some assumptions about certain helper utilities being available in the environment. Currently, this support matrix is:

macOS

Expects /usr/bin/sandbox-exec to be present.

When using the workspace-write sandbox policy, the Seatbelt profile allows writes under the configured writable roots while keeping .git (directory or pointer file), the resolved gitdir: target, and .codex read-only.

Linux

Expects the binary containing codex-core to run the equivalent of codex sandbox linux (legacy alias: codex debug landlock) when arg0 is codex-linux-sandbox. See the codex-arg0 crate for details.

All Platforms

Expects the binary containing codex-core to simulate the virtual apply_patch CLI when arg1 is --codex-run-as-apply-patch. See the codex-arg0 crate for details.