mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
Merge branch 'main' of https://github.com/openai/codex into dev/mzeng/connectors_codex_cli_1
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# Exit and shutdown flow (tui + tui2)
|
||||
# Exit and shutdown flow (tui)
|
||||
|
||||
This document describes how exit, shutdown, and interruption work in the Rust TUIs (`codex-rs/tui`
|
||||
and `codex-rs/tui2`). It is intended for Codex developers and Codex itself when reasoning about
|
||||
future exit/shutdown changes.
|
||||
This document describes how exit, shutdown, and interruption work in the Rust TUI (`codex-rs/tui`).
|
||||
It is intended for Codex developers and Codex itself when reasoning about future exit/shutdown
|
||||
changes.
|
||||
|
||||
This doc replaces earlier separate history and design notes. High-level history is summarized
|
||||
below; full details are captured in PR #8936.
|
||||
|
||||
@@ -6,12 +6,10 @@ for Windows terminals.
|
||||
Primary implementations:
|
||||
|
||||
- `codex-rs/tui/src/bottom_pane/chat_composer.rs`
|
||||
- `codex-rs/tui2/src/bottom_pane/chat_composer.rs`
|
||||
|
||||
Paste-burst detector:
|
||||
|
||||
- `codex-rs/tui/src/bottom_pane/paste_burst.rs`
|
||||
- `codex-rs/tui2/src/bottom_pane/paste_burst.rs`
|
||||
|
||||
## What problem is being solved?
|
||||
|
||||
@@ -51,6 +49,34 @@ The solution is to detect paste-like _bursts_ and buffer them into a single expl
|
||||
- After handling the key, `sync_popups()` runs so popup visibility/filters stay consistent with the
|
||||
latest text + cursor.
|
||||
|
||||
## Submission flow (Enter/Tab)
|
||||
|
||||
There are multiple submission paths, but they share the same core rules:
|
||||
|
||||
### Normal submit/queue path
|
||||
|
||||
`handle_submission` calls `prepare_submission_text` for both submit and queue. That method:
|
||||
|
||||
1. Expands any pending paste placeholders so element ranges align with the final text.
|
||||
2. Trims whitespace and rebases element ranges to the trimmed buffer.
|
||||
3. Expands `/prompts:` custom prompts:
|
||||
- Named args use key=value parsing.
|
||||
- Numeric args use positional parsing for `$1..$9` and `$ARGUMENTS`.
|
||||
The expansion preserves text elements and yields the final submission payload.
|
||||
4. Prunes attachments so only placeholders that survive expansion are sent.
|
||||
5. Clears pending pastes on success and suppresses submission if the final text is empty and there
|
||||
are no attachments.
|
||||
|
||||
### Numeric auto-submit path
|
||||
|
||||
When the slash popup is open and the first line matches a numeric-only custom prompt with
|
||||
positional args, Enter auto-submits without calling `prepare_submission_text`. That path still:
|
||||
|
||||
- Expands pending pastes before parsing positional args.
|
||||
- Uses expanded text elements for prompt expansion.
|
||||
- Prunes attachments based on expanded placeholders.
|
||||
- Clears pending pastes after a successful auto-submit.
|
||||
|
||||
## Paste burst: concepts and assumptions
|
||||
|
||||
The burst detector is intentionally conservative: it only processes “plain” character input
|
||||
@@ -194,12 +220,6 @@ The `PasteBurst` logic is currently exercised through `ChatComposer` integration
|
||||
- `question_mark_does_not_toggle_during_paste_burst`
|
||||
- `burst_paste_fast_small_buffers_and_flushes_on_stop`
|
||||
- `burst_paste_fast_large_inserts_placeholder_on_flush`
|
||||
- `codex-rs/tui2/src/bottom_pane/chat_composer.rs`
|
||||
- `non_ascii_burst_handles_newline`
|
||||
- `ascii_burst_treats_enter_as_newline`
|
||||
- `question_mark_does_not_toggle_during_paste_burst`
|
||||
- `burst_paste_fast_small_buffers_and_flushes_on_stop`
|
||||
- `burst_paste_fast_large_inserts_placeholder_on_flush`
|
||||
|
||||
This document calls out some additional contracts (like “flush before clearing”) that are not yet
|
||||
fully pinned by dedicated `PasteBurst` unit tests.
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Request user input overlay (TUI)
|
||||
|
||||
This note documents the TUI overlay used to gather answers for
|
||||
`RequestUserInputEvent`.
|
||||
|
||||
## Overview
|
||||
|
||||
The overlay renders one question at a time and collects:
|
||||
|
||||
- A single selected option (when options exist).
|
||||
- Freeform notes (always available).
|
||||
|
||||
When options are present, notes are stored per selected option and the first
|
||||
option is selected by default, so every option question has an answer. If a
|
||||
question has no options and no notes are provided, the answer is submitted as
|
||||
`skipped`.
|
||||
|
||||
## Focus and input routing
|
||||
|
||||
The overlay tracks a small focus state:
|
||||
|
||||
- **Options**: Up/Down move the selection and Space selects.
|
||||
- **Notes**: Text input edits notes for the currently selected option.
|
||||
|
||||
Typing while focused on options switches into notes automatically to reduce
|
||||
friction for freeform input.
|
||||
|
||||
## Navigation
|
||||
|
||||
- Enter advances to the next question.
|
||||
- Enter on the last question submits all answers.
|
||||
- PageUp/PageDown navigate across questions (when multiple are present).
|
||||
- Esc interrupts the run.
|
||||
|
||||
## Layout priorities
|
||||
|
||||
The layout prefers to keep the question and all options visible. Notes and
|
||||
footer hints collapse as space shrinks, with notes falling back to a single-line
|
||||
"Notes: ..." input in tight terminals.
|
||||
@@ -1,97 +0,0 @@
|
||||
# Performance testing (`codex-tui2`)
|
||||
|
||||
This doc captures a repeatable workflow for investigating `codex-tui2` performance issues
|
||||
(especially high idle CPU and high CPU while streaming) and validating optimizations to the draw
|
||||
hot path.
|
||||
|
||||
## Scope (this round)
|
||||
|
||||
The current focus is the transcript draw hot path, specifically the cost of repeatedly rendering
|
||||
the same visible transcript lines via Ratatui’s `Line::render_ref` (notably grapheme segmentation
|
||||
and span layout).
|
||||
|
||||
The intended mitigation is a **rasterization cache**: render a wrapped transcript `Line` into a
|
||||
row of `Cell`s once, cache it, and on subsequent redraws copy cached cells into the frame buffer.
|
||||
|
||||
Key invariants:
|
||||
|
||||
- The cache is width-scoped (invalidate on terminal width changes).
|
||||
- The cache stores **base content** only; selection highlight and copy affordances are applied
|
||||
after rendering, so they don’t pollute cached rows.
|
||||
|
||||
## Roles
|
||||
|
||||
- Human: runs `codex-tui2` in an interactive terminal (e.g. Ghostty), triggers “idle” and
|
||||
“streaming” scenarios, and captures profiles.
|
||||
- Assistant (or a script): reads profile output and extracts hotspots and deltas.
|
||||
|
||||
## Baseline setup
|
||||
|
||||
Build from a clean checkout:
|
||||
|
||||
```sh
|
||||
cd codex-rs
|
||||
cargo build -p codex-tui2
|
||||
```
|
||||
|
||||
Run `codex-tui2` in a terminal and get a PID (macOS):
|
||||
|
||||
```sh
|
||||
pgrep -n codex-tui2
|
||||
```
|
||||
|
||||
Track CPU quickly while reproducing:
|
||||
|
||||
```sh
|
||||
top -pid "$(pgrep -n codex-tui2)"
|
||||
```
|
||||
|
||||
## Capture profiles (macOS)
|
||||
|
||||
Capture both an “idle” and a “streaming” profile so hotspots are not conflated:
|
||||
|
||||
```sh
|
||||
sample "$(pgrep -n codex-tui2)" 1 -file /tmp/tui2.idle.sample.txt
|
||||
sample "$(pgrep -n codex-tui2)" 1 -file /tmp/tui2.streaming.sample.txt
|
||||
```
|
||||
|
||||
For the streaming sample, trigger a response that emits many deltas (e.g. “Tell me a story”) so
|
||||
the stream runs long enough to sample.
|
||||
|
||||
## Quick hotspot extraction
|
||||
|
||||
These `rg` patterns keep the investigation grounded in the data:
|
||||
|
||||
```sh
|
||||
# Buffer diff hot path (idle)
|
||||
rg -n "custom_terminal::diff_buffers|diff_buffers" /tmp/tui2.*.sample.txt | head -n 80
|
||||
|
||||
# Transcript rendering hot path (streaming)
|
||||
rg -n "App::render_transcript_cells|Line::render|render_spans|styled_graphemes|GraphemeCursor::next_boundary" /tmp/tui2.*.sample.txt | head -n 120
|
||||
```
|
||||
|
||||
## Rasterization-cache validation checklist
|
||||
|
||||
After implementing a transcript rasterization cache, re-run the same scenarios and confirm:
|
||||
|
||||
- Streaming sample shifts away from `unicode_segmentation::grapheme::GraphemeCursor::next_boundary`
|
||||
stacks dominating the main thread.
|
||||
- CPU during streaming drops materially vs baseline for the same streaming load.
|
||||
- Idle CPU does not regress (redraw gating changes can mask rendering improvements; always measure
|
||||
both idle and streaming).
|
||||
|
||||
## Notes to record per run
|
||||
|
||||
- Terminal size: width × height
|
||||
- Scenario: idle vs streaming (prompt + approximate response length)
|
||||
- CPU snapshot: `top` (directional)
|
||||
- Profile excerpt: 20–50 relevant lines for the dominant stacks
|
||||
|
||||
## Code pointers
|
||||
|
||||
- `codex-rs/tui2/src/transcript_view_cache.rs`: wrapped transcript memoization + per-line
|
||||
rasterization cache (cached `Cell` rows).
|
||||
- `codex-rs/tui2/src/transcript_render.rs`: incremental helper used by the wrapped-line cache
|
||||
(`append_wrapped_transcript_cell`).
|
||||
- `codex-rs/tui2/src/app.rs`: wiring in `App::render_transcript_cells` (uses cached rows instead of
|
||||
calling `Line::render_ref` every frame).
|
||||
Reference in New Issue
Block a user