Commit Graph

1111 Commits

  • Change forking to read the rollout from file (#3440)
    This PR changes get history op to get path. Then, forking will use a
    path. This will help us have one unified codepath for resuming/forking
    conversations. Will also help in having rollout history in order. It
    also fixes a bug where you won't see the UI when resuming after forking.
  • replace tui_markdown with a custom markdown renderer (#3396)
    Also, simplify the streaming behavior.
    
    This fixes a number of display issues with streaming markdown, and paves
    the way for better markdown features (e.g. customizable styles, syntax
    highlighting, markdown-aware wrapping).
    
    Not currently supported:
    - footnotes
    - tables
    - reference-style links
  • Added images to UserMessageEvent (#3400)
    This PR adds an `images` field to the existing `UserMessageEvent` so we
    can encode zero or more images associated with a user message. This
    allows images to be restored when conversations are restored.
  • Introduce rollout items (#3380)
    This PR introduces Rollout items. This enable us to rollout eventmsgs
    and session meta.
    
    This is mostly #3214 with rebase on main
  • alt+delete deletes the word to the right of the cursor (delete_forward_word) (#3394)
    This mirrors alt+backspace, which deletes to the left of the cursor.
  • Replace config.responses_originator_header_internal_override with CODEX_INTERNAL_ORIGINATOR_OVERRIDE_ENV_VAR (#3388)
    The previous config approach had a few issues:
    1. It is part of the config but not designed to be used externally
    2. It had to be wired through many places (look at the +/- on this PR
    3. It wasn't guaranteed to be set consistently everywhere because we
    don't have a super well defined way that configs stack. For example, the
    extension would configure during newConversation but anything that
    happened outside of that (like login) wouldn't get it.
    
    This env var approach is cleaner and also creates one less thing we have
    to deal with when coming up with a better holistic story around configs.
    
    One downside is that I removed the unit test testing for the override
    because I don't want to deal with setting the global env or spawning
    child processes and figuring out how to introspect their originator
    header. The new code is sufficiently simple and I tested it e2e that I
    feel as if this is still worth it.
  • fix: include rollout_path in NewConversationResponse (#3352)
    Adding the `rollout_path` to the `NewConversationResponse` makes it so a
    client can perform subsequent operations on a `(ConversationId,
    PathBuf)` pair. #3353 will introduce support for `ArchiveConversation`.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/3352).
    * #3353
    * __->__ #3352
  • Generate more typescript types and return conversation id with ConversationSummary (#3219)
    This PR does multiple things that are necessary for conversation resume
    to work from the extension. I wanted to make sure everything worked so
    these changes wound up in one PR:
    1. Generate more ts types
    2. Resume rollout history files rather than create a new one every time
    it is resumed so you don't see a duplicate conversation in history for
    every resume. Chatted with @aibrahim-oai to verify this
    3. Return conversation_id in conversation summaries
    4. [Cleanup] Use serde and strong types for a lot of the rollout file
    parsing
  • Format large numbers in a more readable way. (#2046)
    - In the bottom line of the TUI, print the number of tokens to 3 sigfigs
      with an SI suffix, e.g. "1.23K".
    - Elsewhere where we print a number, I figure it's worthwhile to print
      the exact number, because e.g. it's a summary of your session. Here we print
      the numbers comma-separated.
  • Highlight Proposed Command preview (#3319)
    #### Summary
    - highlight proposed command previews with the shared bash syntax
    highlighter
    - keep the Proposed Command section consistent with other execution
    renderings
  • tui: paste with ctrl+v checks file_list (#3211)
    I found that pasting images from Finder with Ctrl+V was resulting in
    incorrect results; this seems to work better.
  • Use ConversationId instead of raw Uuids (#3282)
    We're trying to migrate from `session_id: Uuid` to `conversation_id:
    ConversationId`. Not only does this give us more type safety but it
    unifies our terminology across Codex and with the implementation of
    session resuming, a conversation (which can span multiple sessions) is
    more appropriate.
    
    I started this impl on https://github.com/openai/codex/pull/3219 as part
    of getting resume working in the extension but it's big enough that it
    should be broken out.
  • Clear non-empty prompts with ctrl + c (#3285)
    This updates the ctrl + c behavior to clear the current prompt if there
    is text and you press ctrl + c.
    
    I also updated the ctrl + c hint text to show `^c to interrupt` instead
    of `^c to quit` if there is an active conversation.
    
    Two things I don't love:
    1. You can currently interrupt a conversation with escape or ctrl + c
    (not related to this PR and maybe fine)
    2. The bottom row hint text always says `^c to quit` but this PR doesn't
    really make that worse.
    
    
    
    
    https://github.com/user-attachments/assets/6eddadec-0d84-4fa7-abcb-d6f5a04e5748
    
    
    Fixes https://github.com/openai/codex/issues/3126
  • Move token usage/context information to session level (#3221)
    Move context information into the main loop so it can be used to
    interrupt the loop or start auto-compaction.
  • Added CLI version to /status output (#3223)
    This PR adds the CLI version to the `/status` output.
    
    This addresses feature request #2767
  • feat(tui): show minutes/hours in thinking timer (#3220)
    What
      
    - Show compact elapsed time in the TUI status indicator: Xs, MmSSs,
    HhMMmSSs.
      - Add private helper fmt_elapsed_compact with a unit test.
      
      Why
      
    - Seconds‑only becomes hard to read during longer runs; minutes/hours
    improve clarity without extra noise.
      
      How
      
      - Implemented in codex-rs/tui/src/status_indicator_widget.rs only.
    - The helper is used when rendering the existing “Working/Thinking”
    timer.
    - No changes to codex-common::elapsed::format_duration or other crates.
      
      Scope/Impact
      
      - TUI‑only; no public API changes; minimal risk.
      - Snapshot tests should remain unchanged (most show “0s”).
      
      Before/After
      
    - Working (65s • Esc to interrupt) → Working (1m05s • Esc to interrupt)
      - Working (3723s • …) → Working (1h02m03s • …)
      
      Tests
      
      - Unit: fmt_elapsed_compact_formats_seconds_minutes_hours.
    - Local checks: cargo fmt --all, cargo clippy -p codex-tui -- -D
    warnings, cargo test -p codex-tui.
      
      Notes
      
    - Open to adjusting the exact format or moving the helper if maintainers
    prefer a shared location.
    
    Signed-off-by: Enrique Moreno Tent <enriquemorenotent@gmail.com>
  • hide resume until it's complete (#3218)
    Hide resume functionality until it's fully done.
  • Never store requests (#3212)
    When item ids are sent to Responses API it will load them from the
    database ignoring the provided values. This adds extra latency.
    
    Not having the mode to store requests also allows us to simplify the
    code.
    
    ## Breaking change
    
    The `disable_response_storage` configuration option is removed.
  • syntax-highlight bash lines (#3142)
    i'm not yet convinced i have the best heuristics for what to highlight,
    but this feels like a useful step towards something a bit easier to
    read, esp. when the model is producing large commands.
    
    <img width="669" height="589" alt="Screenshot 2025-09-03 at 8 21 56 PM"
    src="https://github.com/user-attachments/assets/b9cbcc43-80e8-4d41-93c8-daa74b84b331"
    />
    
    also a fairly significant refactor of our line wrapping logic.
  • refactor: remove AttachImage tui event (#3191)
    TuiEvent is supposed to be purely events that come from the "driver",
    i.e. events from the terminal. Everything app-specific should be an
    AppEvent. In this case, it didn't need to be an event at all.
  • tui: fix approval dialog for large commands (#3087)
    #### Summary
    - Emit a “Proposed Command” history cell when an ExecApprovalRequest
    arrives (parity with proposed patches).
    - Simplify the approval dialog: show only the reason/instructions; move
    the command preview into history.
    - Make approval/abort decision history concise:
      - Single line snippet; if multiline, show first line + " ...".
      - Truncate to 80 graphemes with ellipsis for very long commands.
    
    #### Details
    - History
    - Add `new_proposed_command` to render a header and indented command
    preview.
      - Use shared `prefix_lines` helper for first/subsequent line prefixes.
    - Approval UI
    - `UserApprovalWidget` no longer renders the command in the modal; shows
    optional `reason` text only.
      - Decision history renders an inline, dimmed snippet per rules above.
    - Tests (snapshot-based)
      - Proposed/decision flow for short command.
      - Proposed multi-line + aborted decision snippet with “ ...”.
      - Very long one-line command -> truncated snippet with “…”.
      - Updated existing exec approval snapshots and test reasons.
    
    <img width="1053" height="704" alt="Screenshot 2025-09-03 at 11 57
    35 AM"
    src="https://github.com/user-attachments/assets/9ed4c316-9daf-4ac1-80ff-7ae1f481dd10"
    />
    
    after approving:
    
    <img width="1053" height="704" alt="Screenshot 2025-09-03 at 11 58
    18 AM"
    src="https://github.com/user-attachments/assets/a44e243f-eb9d-42ea-87f4-171b3fb481e7"
    />
    
    rejection:
    
    <img width="1053" height="207" alt="Screenshot 2025-09-03 at 11 58
    45 AM"
    src="https://github.com/user-attachments/assets/a022664b-ae0e-4b70-a388-509208707934"
    />
    
    big command:
    
    
    https://github.com/user-attachments/assets/2dd976e5-799f-4af7-9682-a046e66cc494
  • Correctly calculate remaining context size (#3190)
    We had multiple issues with context size calculation:
    1. `initial_prompt_tokens` calculation based on cache size is not
    reliable, cache misses might set it to much higher value. For now
    hardcoded to a safer constant.
    2. Input context size for GPT-5 is 272k (that's where 33% came from).
    
    Fixes.
  • Pause status timer while modals are open (#3131)
    Summary:
    - pause the status timer while waiting on approval modals
    - expose deterministic pause/resume helpers to avoid sleep-based tests
    - simplify bottom pane timer handling now that the widget owns the clock
  • tui: pager pins scroll to bottom (#3167)
    when the pager is scrolled to the bottom of the buffer, keep it there.
    
    this should make transcript mode feel a bit more "alive". i've also seen
    some confusion about what transcript mode does/doesn't show that i think
    has been related to it not pinning scroll.
  • Use ⌥⇧⌃ glyphs for key hints on mac (#3143)
    #### Summary
    - render the edit queued message shortcut with the ⌥ modifier on macOS
    builds
    - add a helper for status indicator snapshot suffixes
    - record macOS-specific snapshots for the status indicator widget
  • [codex] improve handling of reasoning summary (#3138)
    <img width="1474" height="289" alt="Screenshot 2025-09-03 at 5 27 19 PM"
    src="https://github.com/user-attachments/assets/d6febcdd-fd9c-488c-9e82-348600b1f757"
    />
    
    Fallback to standard behavior when there is no summary in cot, and also
    added tests to codify this behavior.
  • tui: avoid panic when active exec cell area is zero height (#3133)
    #### Summary
    Avoid a potential panic when rendering the active execution cell when
    the allocated area has zero height.
    
    #### Changes
    - Guard rendering with `active_cell_area.height > 0` and presence of
    `active_exec_cell`.
    - Use `saturating_add(1)` for the Y offset to avoid overflow.
    - Render via `active_exec_cell.as_ref().unwrap().render_ref(...)` after
    the explicit `is_some` check.
  • TUI: Add session resume picker (--resume) and quick resume (--continue) (#3135)
    Adds a TUI resume flow with an interactive picker and quick resume.
    
    - CLI: 
      - --resume / -r: open picker to resume a prior session
      - --continue   / -l: resume the most recent session (no picker)
    - Behavior on resume: initial history is replayed, welcome banner
    hidden, and the first redraw is suppressed to avoid flicker.
    - Implementation:
    - New tui/src/resume_picker.rs (paginated listing via
    RolloutRecorder::list_conversations)
      - App::run accepts ResumeSelection; resumes from disk when requested
    - ChatWidget refactor with ChatWidgetInit and new_from_existing; replays
    initial messages
    - Tests: cover picker sorting/preview extraction and resumed-history
    rendering.
    - Docs: getting-started updated with flags and picker usage.
    
    
    
    https://github.com/user-attachments/assets/1bb6469b-e5d1-42f6-bec6-b1ae6debda3b
  • Dividing UserMsgs into categories to send it back to the tui (#3127)
    This PR does the following:
    
    - divides user msgs into 3 categories: plain, user instructions, and
    environment context
    - Centralizes adding user instructions and environment context to a
    degree
    - Improve the integration testing
    
    Building on top of #3123
    
    Specifically this
    [comment](https://github.com/openai/codex/pull/3123#discussion_r2319885089).
    We need to send the user message while ignoring the User Instructions
    and Environment Context we attach.
  • Replay EventMsgs from Response Items when resuming a session with history. (#3123)
    ### Overview
    
    This PR introduces the following changes:
    	1.	Adds a unified mechanism to convert ResponseItem into EventMsg.
    2. Ensures that when a session is initialized with initial history, a
    vector of EventMsg is sent along with the session configuration. This
    allows clients to re-render the UI accordingly.
    	3. 	Added integration testing
    
    ### Caveats
    
    This implementation does not send every EventMsg that was previously
    dispatched to clients. The excluded events fall into two categories:
    	•	“Arguably” rolled-out events
    Examples include tool calls and apply-patch calls. While these events
    are conceptually rolled out, we currently only roll out ResponseItems.
    These events are already being handled elsewhere and transformed into
    EventMsg before being sent.
    	•	Non-rolled-out events
    Certain events such as TurnDiff, Error, and TokenCount are not rolled
    out at all.
    
    ### Future Directions
    
    At present, resuming a session involves maintaining two states:
    	•	UI State
    Clients can replay most of the important UI from the provided EventMsg
    history.
    	•	Model State
    The model receives the complete session history to reconstruct its
    internal state.
    
    This design provides a solid foundation. If, in the future, more precise
    UI reconstruction is needed, we have two potential paths:
    1. Introduce a third data structure that allows us to derive both
    ResponseItems and EventMsgs.
    2. Clearly divide responsibilities: the core system ensures the
    integrity of the model state, while clients are responsible for
    reconstructing the UI.
  • Include originator in authentication URL parameters (#3117)
    Associates the client with an authentication session.
  • [tui] Update /mcp output (#3134)
    # Summary
    Quick update to clean up MCP output
    
    ## Testing
    - [x] Ran locally, confirmed output looked good
  • Add a common way to create HTTP client (#3110)
    Ensure User-Agent and originator are always sent.
  • feat: add Android/Termux support by gating arboard dependency (#2895)
    ## Summary
    
    This PR enables Codex to build and run on Android/Termux environments by
    conditionally gating the arboard clipboard dependency for Android
    targets.
    
    ## Key Changes
    
    - **Android Compatibility**: Gate arboard dependency for Android targets
    where clipboard access may be restricted
    - **Build Fixes**: Add missing tempfile::Builder import for image
    clipboard operations
    - **Code Cleanup**: Remove unnecessary parentheses to resolve formatting
    warnings
    
    ## Technical Details
    
    ### Clipboard Dependency Gating
    - Uses conditional compilation to exclude arboard on Android targets
    - Maintains full clipboard functionality on other platforms
    - Prevents build failures on Android/Termux where system clipboard
    access is limited
    
    ### Import Fixes
    - Adds missing tempfile::Builder import that was causing compilation
    errors
    - Ensures image clipboard operations work correctly when clipboard is
    available
    
    ## Platform Support
    
    -  **Linux/macOS/Windows**: Full clipboard functionality maintained
    -  **Android/Termux**: Builds successfully without clipboard dependency
    -  **Other Unix platforms**: Unchanged behavior
    
    ## Testing
    
    -  Builds successfully on Android/Termux
    -  Maintains clipboard functionality on supported platforms  
    -  No regression in existing functionality
    
    This addresses the Android/Termux compatibility issues while keeping
    clipboard functionality intact for platforms that support it.
  • TUI: fix MCP docs hyperlink in empty_mcp_output (#2907)
    - Summary:
    - Updated the hardcoded hyperlink shown when no MCP servers are
    configured to point at the canonical docs section:
        - From: codex-rs/config.md#mcp_servers (moved/obsolete)
        - To: docs/config.md#mcp_servers (correct GitHub path)
    - Rationale:
    - The TUI link was pointing to a file that only redirects; this makes
    the link accurate and reduces user confusion.
    - Validation:
    - Verified that the target anchor exists at:
    https://github.com/openai/codex/blob/main/docs/config.md#mcp_servers
    - UI behavior unchanged otherwise (rendering of link text remains “MCP
    docs”).
    - Impact:
    - One-line change in TUI display logic; no functional behavior change.
    
    Co-authored-by: Michael Bolin <mbolin@openai.com>
  • [feat] use experimental reasoning summary (#3071)
    <img width="1512" height="442" alt="Screenshot 2025-09-02 at 3 49 46 PM"
    src="https://github.com/user-attachments/assets/26c3c1cf-b7ed-4520-a12a-8d38a8e0c318"
    />
  • Move CodexAuth and AuthManager to the core crate (#3074)
    Fix a long standing layering issue.
  • Show loading state when @ search results are pending (#3061)
    ## Summary
    - allow selection popups to specify their empty state message
    - show a "loading..." placeholder in the file search popup while matches
    are pending
    - update other popup call sites to continue using a "no matches" message
    
    ## Testing
    - just fmt
    - just fix -p codex-tui
    - cargo test -p codex-tui
    
    ------
    https://chatgpt.com/codex/tasks/task_i_68b73e956e90832caf4d04a75fcc9c46
  • prefer ratatui Stylized for constructing lines/spans (#3068)
    no functional change, just simplifying ratatui styling and adding
    guidance in AGENTS.md for future.
  • tui: fix occasional UI flicker (#2918)
    occasionally i was seeing some minor flickering when adding history
    lines. hopefully this clears it up.
  • tui: catch get_cursor_position errors (#2870)
    still seeing errors with reading back the cursor position in some cases;
    adding catches everywhere we might run into this.
  • tui: fix extra blank lines in streamed agent messages (#3065)
    Fixes excessive blank lines appearing during agent message streaming.
    
    - Only insert a separator blank line for new, non-streaming history
    cells.
    - Streaming continuations now append without adding a spacer,
    eliminating extra gaps between chunks.
    
    Affected area: TUI display of agent messages (tui/src/app.rs).
  • tui: hide '/init' suggestion when AGENTS.md exists (#3038)
    Hide the “/init” suggestion in the new-session banner when an
    `AGENTS.md` exists anywhere from the repo root down to the current
    working directory.
    
    Changes
    - Conditional suggestion: use `discover_project_doc_paths(config)` to
    suppress `/init` when agents docs are present.
    - TUI style cleanup: switch banner construction to `Stylize` helpers
    (`.bold()`, `.dim()`, `.into()`), avoiding `Span::styled`/`Span::raw`.
    - Fixture update: remove `/init` line in
    `tui/tests/fixtures/ideal-binary-response.txt` to match the new banner.
    
    Validation
    - Ran formatting and scoped lint fixes: `just fmt` and `just fix -p
    codex-tui`.
    - Tests: `cargo test -p codex-tui` passed (`176 passed, 0 failed`).
    
    Notes
    - No change to the `/init` command itself; only the welcome banner now
    adapts based on presence of `AGENTS.md`.
  • Bug fix: ignore Enter on empty input to avoid queuing blank messages (#3047)
    ## Summary
    Pressing Enter with an empty composer was treated as a submission, which
    queued a blank message while a task was running. This PR suppresses
    submission when there is no text and no attachments.
    
    ## Root Cause
    
    - ChatComposer returned Submitted even when the trimmed text was empty.
    ChatWidget then queued it during a running task, leading to an empty
    item appearing in the queued list and being popped later with no effect.
    
    ## Changes
    - ChatComposer Enter handling: if trimmed text is empty and there are no
    attached images, return None instead of Submitted.
    - No changes to ChatWidget; behavior naturally stops queuing blanks at
    the source.
    
    ## Code Paths
    
    - Modified: `tui/src/bottom_pane/chat_composer.rs`
    - Tests added:
        - `tui/src/bottom_pane/chat_composer.rs`: `empty_enter_returns_none`
    - `tui/src/chatwidget/tests.rs`:
    `empty_enter_during_task_does_not_queue`
    
    ## Result
    
    ### Before
    
    
    https://github.com/user-attachments/assets/a40e2f6d-42ba-4a82-928b-8f5458f5884d
    
    ### After
    
    
    
    https://github.com/user-attachments/assets/958900b7-a566-44fc-b16c-b80380739c92
  • remove extra quote from disabled-command message (#3035)
    there was an extra ' floating around for some reason.
  • fix: specify --profile to cargo clippy in CI (#2871)
    Today we had a breakage in the release build that went unnoticed by CI.
    Here is what happened:
    
    - https://github.com/openai/codex/pull/2242 originally added some logic
    to do release builds to prevent this from happening
    - https://github.com/openai/codex/pull/2276 undid that change to try to
    speed things up by removing the step to build all the individual crates
    in release mode, assuming the `cargo check` call was sufficient
    coverage, which it would have been, had it specified `--profile`
    
    This PR adds `--profile` to the `cargo check` step so we should get the
    desired coverage from our build matrix.
    
    Indeed, enabling this in our CI uncovered a warning that is only present
    in release mode that was going unnoticed.