Commit Graph

8 Commits

  • Enable model upgrade popup even when selected model is no longer in picker (#8802)
    With `config.toml`:
    ```
    model = "gpt-5.1-codex"
    ```
    (where `gpt-5.1-codex` has `show_in_picker: false` in
    [`model_presets.rs`](https://github.com/openai/codex/blob/main/codex-rs/core/src/models_manager/model_presets.rs);
    this happens if the user hasn't used codex in a while so they didn't see
    the popup before their model was changed to `show_in_picker: false`)
    
    The upgrade picker used to not show (because `gpt-5.1-codex` was
    filtered out of the model list in code). Now, the filtering is done
    downstream in tui and app-server, so the model upgrade popup shows:
    
    <img width="1503" height="227" alt="Screenshot 2026-01-06 at 5 04 37 PM"
    src="https://github.com/user-attachments/assets/26144cc2-0b3f-4674-ac17-e476781ec548"
    />
  • Clear copy pill background and add snapshot test (#8777)
    ### Motivation
    - Fix a visual bug where transcript text could bleed through the
    on-screen copy "pill" overlay.
    - Ensure the copy affordance fully covers the underlying buffer so the
    pill background is solid and consistent with styling.
    - Document the approach in-code to make the background-clearing
    rationale explicit.
    
    ### Description
    - Clear the pill area before drawing by iterating `Rect::positions()`
    and calling `cell.set_symbol(" ")` and `cell.set_style(base_style)` in
    `render_copy_pill` in `transcript_copy_ui.rs`.
    - Added an explanatory comment for why the pill background is explicitly
    cleared.
    - Added a unit test `copy_pill_clears_background` and committed the
    corresponding snapshot file to validate the rendering behavior.
    
    ### Testing
    - Ran `just fmt` (formatting completed; non-blocking environment warning
    may appear).
    - Ran `just fix -p codex-tui2` to apply lints/fixes (completed). 
    - Ran `cargo test -p codex-tui2` and all tests passed (snapshot updated
    and tests succeeded).
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_695c9b23e9b8832997d5a457c4d83410)
  • tui2: stop baking streaming wraps; reflow agent markdown (#8761)
    Background
    Streaming assistant prose in tui2 was being rendered with viewport-width
    wrapping during streaming, then stored in history cells as already split
    `Line`s. Those width-derived breaks became indistinguishable from hard
    newlines, so the transcript could not "un-split" on resize. This also
    degraded copy/paste, since soft wraps looked like hard breaks.
    
    What changed
    - Introduce width-agnostic `MarkdownLogicalLine` output in
    `tui2/src/markdown_render.rs`, preserving markdown wrap semantics:
    initial/subsequent indents, per-line style, and a preformatted flag.
    - Update the streaming collector (`tui2/src/markdown_stream.rs`) to emit
    logical lines (newline-gated) and remove any captured viewport width.
    - Update streaming orchestration (`tui2/src/streaming/*`) to queue and
    emit logical lines, producing `AgentMessageCell::new_logical(...)`.
    - Make `AgentMessageCell` store logical lines and wrap at render time in
    `HistoryCell::transcript_lines_with_joiners(width)`, emitting joiners so
    copy/paste can join soft-wrap continuations correctly.
    
    Overlay deferral
    When an overlay is active, defer *cells* (not rendered `Vec<Line>`) and
    render them at overlay close time. This avoids baking width-derived
    wraps based on a stale width.
    
    Tests + docs
    - Add resize/reflow regression tests + snapshots for streamed agent
    output.
    - Expand module/API docs for the new logical-line streaming pipeline and
    clarify joiner semantics.
    - Align scrollback-related docs/comments with current tui2 behavior
    (main draw loop does not flush queued "history lines" to the terminal).
    
    More details
    See `codex-rs/tui2/docs/streaming_wrapping_design.md` for the full
    problem statement and solution approach, and
    `codex-rs/tui2/docs/tui_viewport_and_history.md` for viewport vs printed
    output behavior.
  • [tui] add optional details to TUI status header (#8293)
    ### What
    
    Add optional `details` field to TUI's status indicator header. `details`
    is shown under the header with text wrapping and a max height of 3
    lines.
    
    Duplicated changes to `tui2`.
    
    ### Why
    
    Groundwork for displaying error details under `Reconnecting...` for
    clarity with retryable errors.
    
    Basic examples
    <img width="1012" height="326" alt="image"
    src="https://github.com/user-attachments/assets/dd751ceb-b179-4fb2-8fd1-e4784d6366fb"
    />
    
    <img width="1526" height="358" alt="image"
    src="https://github.com/user-attachments/assets/bbe466fc-faff-4a78-af7f-3073ccdd8e34"
    />
    
    Truncation example
    <img width="936" height="189" alt="image"
    src="https://github.com/user-attachments/assets/f3f1b5dd-9050-438b-bb07-bd833c03e889"
    />
    
    ### Tests
    Tested locally, added tests for truncation.
  • tui: improve rendering of search cell (#8273)
    before:
    
    <img width="795" height="150" alt="Screenshot 2025-12-18 at 10 48 01 AM"
    src="https://github.com/user-attachments/assets/6f4d8856-b4c2-4e2a-b60a-b86f82b956a0"
    />
    
    after:
    
    <img width="795" height="150" alt="Screenshot 2025-12-18 at 10 48 39 AM"
    src="https://github.com/user-attachments/assets/dd0d167a-5d09-4bb7-9d36-95a2eb1aaa83"
    />
  • caribou (#8265)
    Welcome caribou
    
    <img width="1536" height="1024" alt="image"
    src="https://github.com/user-attachments/assets/2a67b21f-40cf-4518-aee4-691af331ab50"
    />
  • Sync tui2 with tui and keep dual-run glue (#7965)
    - Copy latest tui sources into tui2
    - Restore notifications, tests, and styles
    - Keep codex-tui interop conversions and snapshots
    
    The expected changes that are necessary to make this work are still in
    place:
    
    diff -ru codex-rs/tui codex-rs/tui2 --exclude='*.snap'
    --exclude='*.snap.new'
    
    ```diff
    diff -ru --ex codex-rs/tui/Cargo.toml codex-rs/tui2/Cargo.toml
    --- codex-rs/tui/Cargo.toml	2025-12-12 16:39:12
    +++ codex-rs/tui2/Cargo.toml	2025-12-12 17:31:01
    @@ -1,15 +1,15 @@
     [package]
    -name = "codex-tui"
    +name = "codex-tui2"
     version.workspace = true
     edition.workspace = true
     license.workspace = true
     
     [[bin]]
    -name = "codex-tui"
    +name = "codex-tui2"
     path = "src/main.rs"
     
     [lib]
    -name = "codex_tui"
    +name = "codex_tui2"
     path = "src/lib.rs"
     
     [features]
    @@ -42,6 +42,7 @@
     codex-login = { workspace = true }
     codex-protocol = { workspace = true }
     codex-utils-absolute-path = { workspace = true }
    +codex-tui = { workspace = true }
     color-eyre = { workspace = true }
     crossterm = { workspace = true, features = ["bracketed-paste", "event-stream"] }
     derive_more = { workspace = true, features = ["is_variant"] }
    diff -ru --ex codex-rs/tui/src/app.rs codex-rs/tui2/src/app.rs
    --- codex-rs/tui/src/app.rs	2025-12-12 16:39:05
    +++ codex-rs/tui2/src/app.rs	2025-12-12 17:30:36
    @@ -69,6 +69,16 @@
         pub update_action: Option<UpdateAction>,
     }
     
    +impl From<AppExitInfo> for codex_tui::AppExitInfo {
    +    fn from(info: AppExitInfo) -> Self {
    +        codex_tui::AppExitInfo {
    +            token_usage: info.token_usage,
    +            conversation_id: info.conversation_id,
    +            update_action: info.update_action.map(Into::into),
    +        }
    +    }
    +}
    +
     fn session_summary(
         token_usage: TokenUsage,
         conversation_id: Option<ConversationId>,
    Only in codex-rs/tui/src/bin: md-events.rs
    Only in codex-rs/tui2/src/bin: md-events2.rs
    diff -ru --ex codex-rs/tui/src/cli.rs codex-rs/tui2/src/cli.rs
    --- codex-rs/tui/src/cli.rs	2025-11-19 13:40:42
    +++ codex-rs/tui2/src/cli.rs	2025-12-12 17:30:43
    @@ -88,3 +88,28 @@
         #[clap(skip)]
         pub config_overrides: CliConfigOverrides,
     }
    +
    +impl From<codex_tui::Cli> for Cli {
    +    fn from(cli: codex_tui::Cli) -> Self {
    +        Self {
    +            prompt: cli.prompt,
    +            images: cli.images,
    +            resume_picker: cli.resume_picker,
    +            resume_last: cli.resume_last,
    +            resume_session_id: cli.resume_session_id,
    +            resume_show_all: cli.resume_show_all,
    +            model: cli.model,
    +            oss: cli.oss,
    +            oss_provider: cli.oss_provider,
    +            config_profile: cli.config_profile,
    +            sandbox_mode: cli.sandbox_mode,
    +            approval_policy: cli.approval_policy,
    +            full_auto: cli.full_auto,
    +            dangerously_bypass_approvals_and_sandbox: cli.dangerously_bypass_approvals_and_sandbox,
    +            cwd: cli.cwd,
    +            web_search: cli.web_search,
    +            add_dir: cli.add_dir,
    +            config_overrides: cli.config_overrides,
    +        }
    +    }
    +}
    diff -ru --ex codex-rs/tui/src/main.rs codex-rs/tui2/src/main.rs
    --- codex-rs/tui/src/main.rs	2025-12-12 16:39:05
    +++ codex-rs/tui2/src/main.rs	2025-12-12 16:39:06
    @@ -1,8 +1,8 @@
     use clap::Parser;
     use codex_arg0::arg0_dispatch_or_else;
     use codex_common::CliConfigOverrides;
    -use codex_tui::Cli;
    -use codex_tui::run_main;
    +use codex_tui2::Cli;
    +use codex_tui2::run_main;
     
     #[derive(Parser, Debug)]
     struct TopCli {
    diff -ru --ex codex-rs/tui/src/update_action.rs codex-rs/tui2/src/update_action.rs
    --- codex-rs/tui/src/update_action.rs	2025-11-19 11:11:47
    +++ codex-rs/tui2/src/update_action.rs	2025-12-12 17:30:48
    @@ -9,6 +9,20 @@
         BrewUpgrade,
     }
     
    +impl From<UpdateAction> for codex_tui::update_action::UpdateAction {
    +    fn from(action: UpdateAction) -> Self {
    +        match action {
    +            UpdateAction::NpmGlobalLatest => {
    +                codex_tui::update_action::UpdateAction::NpmGlobalLatest
    +            }
    +            UpdateAction::BunGlobalLatest => {
    +                codex_tui::update_action::UpdateAction::BunGlobalLatest
    +            }
    +            UpdateAction::BrewUpgrade => codex_tui::update_action::UpdateAction::BrewUpgrade,
    +        }
    +    }
    +}
    +
     impl UpdateAction {
         /// Returns the list of command-line arguments for invoking the update.
         pub fn command_args(self) -> (&'static str, &'static [&'static str]) {
    ```
  • feat(tui2): copy tui crate and normalize snapshots (#7833)
    Introduce a full codex-tui source snapshot under the new codex-tui2
    crate so viewport work can be replayed in isolation.
    
    This change copies the entire codex-rs/tui/src tree into
    codex-rs/tui2/src in one atomic step, rather than piecemeal, to keep
    future diffs vs the original viewport bookmark easy to reason about.
    
    The goal is for codex-tui2 to render identically to the existing TUI
    behind the `features.tui2` flag while we gradually port the
    viewport/history commits from the joshka/viewport bookmark onto this
    forked tree.
    
    While on this baseline change, we also ran the codex-tui2 snapshot test
    suite and accepted all insta snapshots for the new crate, so the
    snapshot files now use the codex-tui2 naming scheme and encode the
    unmodified legacy TUI behavior. This keeps later viewport commits
    focused on intentional behavior changes (and their snapshots) rather
    than on mechanical snapshot renames.