mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
4e4bffce72fd2a69e7912ecdd00d2c3d877356b8
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
12779c7c07 |
fix(tui): show in-flight coalesced tool calls in transcript overlay (#8246)
### Problem Ctrl+T transcript overlay can omit in-flight coalesced tool calls because it renders only committed transcript cells while the main viewport can render the current in-flight ChatWidget.active_cell immediately. ### Mental model The UI has both committed transcript cells (finalized HistoryCell entries) and an in-flight active cell that can mutate in place while streaming, often representing a coalesced exec/tool group. The transcript overlay renders committed cells plus a render-only live tail derived from the current active cell. The live tail is cached and only recomputed when its cache key changes, which is derived from terminal width (wrapping), active-cell revision (in-place mutations), stream continuation (spacing), and animation tick (time-based visuals). ### Non-goals This does not change coalescing rules, flush boundaries, or when active cells become committed. It does not change tool-call semantics or transcript persistence; it is a rendering-only improvement for the overlay. ### Tradeoffs This adds cache invalidation complexity: correctness depends on bumping an active-cell revision (and/or providing an animation tick) when the active cell mutates in place. The mechanism is implemented in both codex-tui and codex-tui2, which keeps behavior consistent but risks drift if future changes are not applied in lockstep. ### Architecture App special-cases transcript overlay draws to sync a live tail from ChatWidget into TranscriptOverlay. TranscriptOverlay remains the owner of committed transcript cells; the live tail is an optional appended renderable. HistoryCell::transcript_animation_tick() allows time-dependent transcript output (spinner/shimmer) to invalidate the cached tail without requiring data mutation. ### Observability Manual verification is to open Ctrl+T while an exploring/coalesced active cell is still in-flight and confirm the overlay includes the same in-flight tool-call group the main viewport shows. The overlay is kept in sync by App passing an active-cell key and transcript lines into TranscriptOverlay::sync_live_tail; the key must change when the active cell mutates or animates. ### Tests Snapshot tests validate that the transcript overlay renders a live tail appended after committed cells and that identical keys short-circuit recomputation. Unit tests validate that active-cell revision bumps occur on specific in-place mutations (e.g. unified exec wait cell command display becoming known late) so cached tails are invalidated. ## Documentation patches (module, type, function) ### Module-level docs (invariants + mechanisms) - codex-rs/tui/src/app_backtrack.rs:1 - codex-rs/tui/src/chatwidget.rs:1 - codex-rs/tui/src/pager_overlay.rs:1 - codex-rs/tui/src/history_cell.rs:1 - codex-rs/tui2/src/app_backtrack.rs:1 - codex-rs/tui2/src/chatwidget.rs:1 - codex-rs/tui2/src/pager_overlay.rs:1 - codex-rs/tui2/src/history_cell.rs:1 ### Type-level docs (cache key + invariants) - codex-rs/tui/src/chatwidget.rs (ChatWidget.active_cell_revision, ActiveCellTranscriptKey) - codex-rs/tui/src/pager_overlay.rs (TranscriptOverlay live tail storage model) - codex-rs/tui/src/history_cell.rs (HistoryCell::transcript_animation_tick, UnifiedExecWaitCell::update_command_display) - Mirrored in codex-rs/tui2/src/chatwidget.rs, codex-rs/tui2/src/pager_overlay.rs, codex-rs/tui2/src/history_cell.rs ### Function-level docs (why/when/guarantees/pitfalls) - codex-rs/tui/src/app_backtrack.rs (overlay_forward_event) - codex-rs/tui/src/chatwidget.rs (active_cell_transcript_key, active_cell_transcript_lines) - codex-rs/tui/src/pager_overlay.rs (sync_live_tail, take_live_tail_renderable) - codex-rs/tui/src/history_cell.rs (transcript_animation_tick, UnifiedExecWaitCell::update_command_display) - Mirrored in codex-rs/tui2 equivalents where present ### Validation performed - cd codex-rs && just fmt - cd codex-rs && cargo test -p codex-tui - cd codex-rs && cargo test -p codex-tui2 ## Design inconsistencies / risks - Cache invalidation is a distributed responsibility: any future in-place active cell transcript mutation that forgets to bump active_cell_revision (or expose an animation tick) can leave the transcript overlay live tail out of sync with the main viewport. - TranscriptOverlay tail handling assumes a structural invariant that the live tail, when present, is exactly one trailing renderable after the committed cell renderables; if renderable construction changes in a way that violates that assumption, tail insertion/removal logic becomes incorrect. - codex-tui and codex-tui2 duplicate the live-tail mechanism; the documentation is aligned, but the implementation can still drift unless changes continue to be applied in lockstep. |
||
|
|
3389465c8d |
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" /> |
||
|
|
a0b2d03302 |
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)
|
||
|
|
c92dbea7c1 |
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. |
||
|
|
53eb2e9f27 |
[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. |
||
|
|
be274cbe62 |
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" /> |
||
|
|
f084e5264b |
caribou (#8265)
Welcome caribou <img width="1536" height="1024" alt="image" src="https://github.com/user-attachments/assets/2a67b21f-40cf-4518-aee4-691af331ab50" /> |
||
|
|
6ec2831b91 |
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]) {
```
|
||
|
|
90f262e9a4 |
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. |