Commit Graph

18 Commits

  • fix: wrap long exec lines in transcript overlay (#7481)
    What
    -----
    - Fix the Ctrl+T transcript overlay so that very long exec output lines
    are soft‑wrapped to the viewport width instead of being rendered as a
    single truncated row.
    - Add a regression test to `TranscriptOverlay` to ensure long exec
    outputs are rendered on multiple lines in the overlay.
    
    Why
    ----
    - Previously, the transcript overlay rendered extremely long single exec
    lines as one on‑screen row and simply cut them off at the right edge,
    with no horizontal scrolling.
    - This made it impossible to inspect the full content of long tool/exec
    outputs in the transcript view, even though the main TUI view already
    wrapped those lines.
    - Fixes #7454.
    
    How
    ----
    - Update `ExecCell::transcript_lines` to wrap exec output lines using
    the existing `RtOptions`/`word_wrap_line` helpers so that transcript
    rendering is width‑aware.
    - Reuse the existing line utilities to expand the wrapped `Line` values
    into the transcript overlay, preserving styling while respecting the
    current viewport width.
    - Add `transcript_overlay_wraps_long_exec_output_lines` test in
    `pager_overlay.rs` that constructs a long single‑line exec output,
    renders the transcript overlay into a small buffer, and asserts that the
    long marker string spans multiple rendered lines.
  • fix(tui): limit user shell output by screen lines (#7448)
    What
    - Limit the TUI "user shell" output panel by the number of visible
    screen lines rather than by the number of logical lines.
    - Apply middle truncation after wrapping, so a few extremely long lines
    cannot expand into hundreds of visible lines.
    - Add a regression test to guard this behavior.
    
    Why
    When the `ExecCommandSource::UserShell` tool returns a small number of
    very long logical lines, the TUI wraps those lines into many visual
    lines. The existing truncation logic applied
    `USER_SHELL_TOOL_CALL_MAX_LINES` to the number of logical lines *before*
    wrapping.
    
    As a result, a command like:
    
    - `Ran bash -lc "grep -R --line-number 'maskAssetId' ."`
    
    or a synthetic command that prints a single ~50,000‑character line, can
    produce hundreds of screen lines and effectively flood the viewport. The
    intended middle truncation for user shell output does not take effect in
    this scenario.
    
    How
    - In `codex-rs/tui/src/exec_cell/render.rs`, change the `ExecCell`
    rendering path for `ExecCommandSource::UserShell` so that:
    - Each logical line from `CommandOutput::aggregated_output` is first
    wrapped via `word_wrap_line` into multiple screen lines using the
    appropriate `RtOptions` and width from the `EXEC_DISPLAY_LAYOUT`
    configuration.
    - `truncate_lines_middle` is then applied to the wrapped screen lines,
    with `USER_SHELL_TOOL_CALL_MAX_LINES` as the limit. This means the limit
    is enforced on visible screen lines, not logical lines.
    - The existing layout struct (`ExecDisplayLayout`) continues to provide
    `output_max_lines`, so user shell output is subject to both
    `USER_SHELL_TOOL_CALL_MAX_LINES` and the layout-specific
    `output_max_lines` constraint.
    - Keep using `USER_SHELL_TOOL_CALL_MAX_LINES` as the cap, but interpret
    it as a per‑tool‑call limit on screen lines.
    - Add a regression test `user_shell_output_is_limited_by_screen_lines`
    in `codex-rs/tui/src/exec_cell/render.rs` that:
    - Constructs two extremely long logical lines containing a short marker
    (`"Z"`), so each wrapped screen line still contains the marker.
      - Wraps them at a narrow width to generate many screen lines.
    - Asserts that the unbounded wrapped output would exceed
    `USER_SHELL_TOOL_CALL_MAX_LINES` screen lines.
    - Renders an `ExecCell` for `ExecCommandSource::UserShell` at the same
    width and counts rendered lines containing the marker.
    - Asserts `output_screen_lines <= USER_SHELL_TOOL_CALL_MAX_LINES`,
    guarding against regressions where truncation happens before wrapping.
    
    This change keeps user shell output readable while ensuring it cannot
    flood the TUI, even when the tool emits a few extremely long lines.
    
    Tests
    - `cargo test -p codex-tui`
    
    Issue
    - Fixes #7447
  • Added feature switch to disable animations in TUI (#6870)
    This PR adds support for a new feature flag `tui.animations`. By
    default, the TUI uses animations in its welcome screen, "working"
    spinners, and "shimmer" effects. This animations can interfere with
    screen readers, so it's good to provide a way to disable them.
    
    This change is inspired by [a
    PR](https://github.com/openai/codex/pull/4014) contributed by @Orinks.
    That PR has faltered a bit, but I think the core idea is sound. This
    version incorporates feedback from @aibrahim-oai. In particular:
    1. It uses a feature flag (`tui.animations`) rather than the unqualified
    CLI key `no-animations`. Feature flags are the preferred way to expose
    boolean switches. They are also exposed via CLI command switches.
    2. It includes more complete documentation.
    3. It disables a few animations that the other PR omitted.
  • feat: better UI for unified_exec (#6515)
    <img width="376" height="132" alt="Screenshot 2025-11-12 at 17 36 22"
    src="https://github.com/user-attachments/assets/ce693f0d-5ca0-462e-b170-c20811dcc8d5"
    />
  • Add user command event types (#6246)
    adding new user command event, logic in TUI to render user command
    events
  • tui: refactor ChatWidget and BottomPane to use Renderables (#5565)
    - introduce RenderableItem to support both owned and borrowed children
    in composite Renderables
    - refactor some of our gnarlier manual layouts, BottomPane and
    ChatWidget, to use ColumnRenderable
    - Renderable and friends now handle cursor_pos()
  • feature: Add "!cmd" user shell execution (#2471)
    feature: Add "!cmd" user shell execution
    
    This change lets users run local shell commands directly from the TUI by
    prefixing their input with ! (e.g. !ls). Output is truncated to keep the
    exec cell usable, and Ctrl-C cleanly
      interrupts long-running commands (e.g. !sleep 10000).
    
    **Summary of changes**
    
    - Route Op::RunUserShellCommand through a dedicated UserShellCommandTask
    (core/src/tasks/user_shell.rs), keeping the task logic out of codex.rs.
    - Reuse the existing tool router: the task constructs a ToolCall for the
    local_shell tool and relies on ShellHandler, so no manual MCP tool
    lookup is required.
    - Emit exec lifecycle events (ExecCommandBegin/ExecCommandEnd) so the
    TUI can show command metadata, live output, and exit status.
    
    **End-to-end flow**
    
      **TUI handling**
    
    1. ChatWidget::submit_user_message (TUI) intercepts messages starting
    with !.
    2. Non-empty commands dispatch Op::RunUserShellCommand { command };
    empty commands surface a help hint.
    3. No UserInput items are created, so nothing is enqueued for the model.
    
      **Core submission loop**
    4. The submission loop routes the op to handlers::run_user_shell_command
    (core/src/codex.rs).
    5. A fresh TurnContext is created and Session::spawn_user_shell_command
    enqueues UserShellCommandTask.
    
      **Task execution**
    6. UserShellCommandTask::run emits TaskStartedEvent, formats the
    command, and prepares a ToolCall targeting local_shell.
      7. ToolCallRuntime::handle_tool_call dispatches to ShellHandler.
    
      **Shell tool runtime**
    8. ShellHandler::run_exec_like launches the process via the unified exec
    runtime, honoring sandbox and shell policies, and emits
    ExecCommandBegin/End.
    9. Stdout/stderr are captured for the UI, but the task does not turn the
    resulting ToolOutput into a model response.
    
      **Completion**
    10. After ExecCommandEnd, the task finishes without an assistant
    message; the session marks it complete and the exec cell displays the
    final output.
    
      **Conversation context**
    
    - The command and its output never enter the conversation history or the
    model prompt; the flow is local-only.
      - Only exec/task events are emitted for UI rendering.
    
    **Demo video**
    
    
    https://github.com/user-attachments/assets/fcd114b0-4304-4448-a367-a04c43e0b996
  • tui: show aggregated output in display (#5539)
    This shows the aggregated (stdout + stderr) buffer regardless of exit
    code.
    
    Many commands output useful / relevant info on stdout when returning a
    non-zero exit code, or the same on stderr when returning an exit code of
    0. Often, useful info is present on both stdout AND stderr. Also, the
    model sees both. So it is confusing to see commands listed as "(no
    output)" that in fact do have output, just on the stream that doesn't
    match the exit status, or to see some sort of trivial output like "Tests
    failed" but lacking any information about the actual failure.
    
    As such, always display the aggregated output in the display. Transcript
    mode remains unchanged as it was already displaying the text that the
    model sees, which seems correct for transcript mode.
  • fix: the 7 omitted lines issue (#5141)
    Before, the CLI was always showing `... +7 lines` (with the 7 constant)
    due to a double truncation
    
    <img width="263" height="127" alt="Screenshot 2025-10-13 at 10 28 11"
    src="https://github.com/user-attachments/assets/49a92d2b-c28a-4e2f-96d1-1818955470b8"
    />
  • tui: bring the transcript closer to display mode (#4848)
    before
    <img width="1161" height="836" alt="Screenshot 2025-10-06 at 3 06 52 PM"
    src="https://github.com/user-attachments/assets/7622fd6b-9d37-402f-8651-61c2c55dcbc6"
    />
    
    after
    <img width="1161" height="858" alt="Screenshot 2025-10-06 at 3 07 02 PM"
    src="https://github.com/user-attachments/assets/1498f327-1d1a-4630-951f-7ca371ab0139"
    />
  • tui: breathing spinner on true-color terms (#4853)
    uses the same logic as shimmer_spans to render the `•` spinner. on
    terminals without true-color support, fall back to the existing `•/◦`
    blinking logic.
    
    
    
    https://github.com/user-attachments/assets/19db76f2-8fa2-440d-9fde-7bed67f4c4dc
  • add pulsing dot loading state (#4736)
    ## Description 
    Changes default CLI spinner to pulsing dot
    
    
    https://github.com/user-attachments/assets/b81225d6-6655-4ead-8cb1-d6568a603d5b
    
    ## Tests
    Passes CI
    
    ---------
    
    Co-authored-by: Fouad Matin <fouad@openai.com>
  • Show placeholder for commands with no output (#4509)
    ## Summary
    - show a dim “(no output)” placeholder when an executed command produces
    no stdout or stderr so empty runs are visible
    - update TUI snapshots to include the new placeholder in history
    renderings
    
    ## Testing
    - cargo test -p codex-tui
    
    
    ------
    https://chatgpt.com/codex/tasks/task_i_68dc056c1d5883218fe8d9929e9b1657
  • render • as dim (#4467)
    <img width="988" height="686" alt="Screenshot 2025-09-29 at 3 28 30 PM"
    src="https://github.com/user-attachments/assets/634a6e6f-cdc0-49af-97c1-096e871414bb"
    />
  • update composer + user message styling (#4240)
    Changes:
    
    - the composer and user messages now have a colored background that
    stretches the entire width of the terminal.
    - the prompt character was changed from a cyan `▌` to a bold `›`.
    - the "working" shimmer now follows the "dark gray" color of the
    terminal, better matching the terminal's color scheme
    
    | Terminal + Background        | Screenshot |
    |------------------------------|------------|
    | iTerm with dark bg | <img width="810" height="641" alt="Screenshot
    2025-09-25 at 11 44 52 AM"
    src="https://github.com/user-attachments/assets/1317e579-64a9-4785-93e6-98b0258f5d92"
    /> |
    | iTerm with light bg | <img width="845" height="540" alt="Screenshot
    2025-09-25 at 11 46 29 AM"
    src="https://github.com/user-attachments/assets/e671d490-c747-4460-af0b-3f8d7f7a6b8e"
    /> |
    | iTerm with color bg | <img width="825" height="564" alt="Screenshot
    2025-09-25 at 11 47 12 AM"
    src="https://github.com/user-attachments/assets/141cda1b-1164-41d5-87da-3be11e6a3063"
    /> |
    | Terminal.app with dark bg | <img width="577" height="367"
    alt="Screenshot 2025-09-25 at 11 45 22 AM"
    src="https://github.com/user-attachments/assets/93fc4781-99f7-4ee7-9c8e-3db3cd854fe5"
    /> |
    | Terminal.app with light bg | <img width="577" height="367"
    alt="Screenshot 2025-09-25 at 11 46 04 AM"
    src="https://github.com/user-attachments/assets/19bf6a3c-91e0-447b-9667-b8033f512219"
    /> |
    | Terminal.app with color bg | <img width="577" height="367"
    alt="Screenshot 2025-09-25 at 11 45 50 AM"
    src="https://github.com/user-attachments/assets/dd7c4b5b-342e-4028-8140-f4e65752bd0b"
    /> |
  • Show exec output on success with trimmed display (#4113)
    - Refactor Exec Cell into its own module
    - update exec command rendering to inline the first command line
    - limit continuation lines
    - always show trimmed output