Commit Graph
36 Commits
Author SHA1 Message Date
Ian MacLeod f3da3861c5 Add a one-time composer starfield for new Astra tasks (#46096)
## What changed

Show a brief starfield in the empty composer when a new task starts with Astra or the user selects Astra through `/model` before entering ordinary prompt content.

- Respect `tui.animations`, `tui.whimsy`, and true-color support; protect the placeholder and cursor and fade out by 15 seconds.
- Preserve eligibility through recognized slash commands, but permanently dismiss it after ordinary draft content, attachments, or work. Carry draft eligibility through startup and disconnected editing.
- Exclude resumed and forked tasks, and verify model-picker changes against the originating task and effective model when applied.
- Hide the effect during overlays or focus loss without restarting its deadline or scheduling hidden animation frames.

## Testing

Add regression tests and snapshots for task eligibility, model-picker transitions, draft and paste handling, history search, overlays, submissions, rendering protection, and animation expiry.

GitOrigin-RevId: 832705543e9cae1d561125ece853a16c4eefe627
2026-09-17 03:27:21 +00:00
Eric Traut 529bcb2fdf Preserve streamed answers and plans when turns terminate (#45549)
## Why

Interrupted or failed turns can discard buffered answer or plan source, leaving incomplete math content missing from the transcript or unable to reflow correctly.

## What changed

Flush and consolidate both answer and plan streams before `finalize_turn` clears streaming state. Reuse the same helper for normal completion, preserving received source for terminal resizing and raw output mode changes.

## Testing

Add regression coverage for interrupted answers and plans, failed plans, and policy errors with unfinished math blocks, with and without a trailing newline. Verify source preservation and stable content across width and raw output mode changes, with narrow transcript snapshots. Update the usage activity test to verify that history insertion waits for stream consolidation.

GitOrigin-RevId: 1ae0c192e2fee00dc0b5ee2ac07f3d5f2313ad1b
2026-09-14 23:52:39 +00:00
Felipe Coury 9ec33e1926 Show streaming reasoning summaries in the TUI status row (#43921)
## What changed

- Update the status heading from the latest usable reasoning line and retain it through tool activity and empty reasoning items. Keep completed reasoning in the expanded transcript only.
- Restore active reasoning after resume, thread switches, and session refreshes, including when earlier events have left the replay buffer.
- Default new embedded TUI threads to `model_reasoning_summary = "detailed"`, honoring explicit summary settings. Keep `concurrent_reasoning_summaries` opt-in and disable it when summaries are `none`.
- Persist the request's captured reasoning summary setting in context updates and local and remote compaction checkpoints.
- Animate status text with a smooth, grapheme-aware shimmer that respects terminal colors and reduced motion.

## Testing

Add regression coverage for reasoning status updates, transcript visibility, resume and buffered replay, outbound summary configuration, and summary settings across all three compaction modes. Add shimmer snapshots and checks for smooth brightness changes and Unicode grapheme preservation.

GitOrigin-RevId: 725c7de20f23166d7a3da6daeca617add5cbc600
2026-09-08 21:41:02 +00:00
Benjamin Carlsson b01c3986fd Add live WebRTC voice conversations to the TUI (#43581)
## What changed

- Add feature-gated `/voice`, `/voice mute`, and `/voice stop` commands with local WebRTC audio and app-server signaling.
- Show live transcripts, conversation status, and microphone and speaker levels. Preserve captions and undelivered answers across thread switches.
- Speak final answers from voice handoffs while keeping delegated reasoning and commentary hidden and typed answers unspoken.
- Retry eligible startup failures once and clean up voice sessions on thread switches and disconnects.
- Stop voice and block late handoffs after a misalignment policy violation. Remove realtime event payloads and spoken text from receipt and debug logs.

## Testing

Add coverage for voice command mapping, rejected starts, disconnect cleanup, delegated final-answer speech, late handoff rejection, and transcript and footer rendering.

GitOrigin-RevId: 11def1f86b0e023b21d0d92072d6636ccad89815
2026-09-07 20:25:30 +00:00
Felipe Coury 333c41eef6 Show completion timestamps after successful TUI turns (#43558)
## What changed

Replace horizontal turn separators with dim completion metadata after the final answer, including plain conversational answers. Show local completion times such as `done 2:32 PM`, adding the date for other days and the year for other years. Retain `Worked for` durations above sixty seconds and runtime metrics, and wrap metadata on narrow terminals.

Restore saved completion metadata when resuming conversations or loading older history. Keep each footer after its turn's items and deduplicate it across repeated notifications and overlapping pages. Only live completions fall back to the current time when a saved timestamp is unavailable. Failed, interrupted, and in-progress turns do not receive success footers.

Avoid submitting queued input or emitting completion notifications while replaying history.

## Testing

Add unit and snapshot coverage for timestamp formatting, duration thresholds, muted styling, narrow layouts, live and replayed completions, missing metadata, and pagination boundaries with overlapping pages.

GitOrigin-RevId: 308c35c6720720da43c9a391aa5a68c1b231c9a5
2026-09-07 19:01:08 +00:00
Eric Traut ff2f01b0c2 Tailor TUI cyber refusal notices to Daybreak eligibility (#42667)
## What changed

- Prefetch ChatGPT account eligibility in the background and cache it across TUI widget replacements.
- Show an application link when Daybreak is available but not enabled, an Astra-specific explanation for unsupported models, and neutral copy when access is already present or eligibility cannot be determined.
- Refresh eligibility after account changes and reconnects without changing the selected model or delaying refusal handling.

## Testing

- Cover eligibility responses, account changes, model-specific notices, fallback behavior, and rendered notice snapshots.

GitOrigin-RevId: 7ae8613a946cb46b8f0b46bf47e5e15ae258ed86
2026-09-04 03:30:21 +00:00
Ian MacLeod 32c303c197 Condense TUI startup warnings (#42609)
## What changed

- Coalesce configuration, skill, sandbox, and MCP startup diagnostics into a single summary below the session header, including MCP and sign-in counts.
- Keep the complete warning text in the transcript and update the summary's transcript shortcut when key bindings change.
- Continue rendering warnings that arrive after work begins as inline history entries.
- Hide the MCP startup status row before a turn while preserving the configured interrupt shortcut.

## Testing

- Add coverage for warning ordering and deduplication, transcript details, MCP sign-in counts, resumed sessions, runtime warnings, reflow, backtracking, and interruption without a visible status row.

GitOrigin-RevId: 009657cf04f1d3a52270cf096eebf9db7513c040
2026-09-03 20:25:59 +00:00
dhruvgupta-oai 5037919777 Add Luna Reserve usage fallback to the TUI (#42372)
## Why

When ordinary included usage is exhausted, eligible users need a way to keep working with the backend-provided Luna Reserve quota and return to their previous model once ordinary usage recovers.

## What changed

- Automatically switch eligible TUI tasks to Luna Reserve after an authoritative account usage read, preserving the prior model and reasoning effort per task.
- Restrict model selection while on Reserve to its supported reasoning levels, keep queued turns on the accepted model, and restore the saved model after a fresh read confirms recovery.
- Surface Reserve usage in the composer and `/status`, and expose `normalModelSlug` in app-server rate-limit snapshots so clients can use the associated model's display metadata without changing the request model.
- Poll account limits more frequently near exhaustion and retain compatibility with app servers that only accept the legacy null request parameters.

## Testing

- Added coverage for Reserve entry, queued-turn handling, task reconstruction, recovery authorization, account changes, model selection, usage rendering, and banner dismissal.

GitOrigin-RevId: 46a435e9531051f8cec3f6a46c4b9f7cfa479747
2026-09-02 21:50:51 +00:00
Eric Traut a526f54b00 Show live context compaction status in the TUI (#42319)
## Why

Context compaction was only reported after it completed, so the TUI did not
show when compaction was actively making room to continue.

## What changed

- Show `Compacting context` as soon as manual or server-driven compaction
  starts, with an elapsed timer independent of the current turn timer.
- Preserve the compaction status across follow-up input and transient activity,
  while still allowing retry errors to take precedence.
- Restore in-progress compaction timing from thread snapshots and add the live
  duration to the completion message.
- Clear stale compaction state when the turn starts, completes, or terminates.

## Testing

Added TUI tests covering manual and server-driven compaction, narrow rendering,
follow-up input, replay and task switching, retry status, timer preservation,
and turn termination.

GitOrigin-RevId: 804e1bc553315da24ff1f99462e8e282818cada3
2026-09-02 18:03:55 +00:00
Ian MacLeod 17e8101699 Preserve TUI status timing when the status row is hidden (#41913)
## Why

Streaming can temporarily hide the status row, but its elapsed time is still
needed when the row returns and when the final `Worked for` duration falls back
to the local clock. Approval prompts must also keep that clock paused.

## What changed

- Own the pause-aware status timer in the bottom pane independently of the
  optional status row.
- Preserve elapsed time and modal pause state while hiding or restoring the row,
  and reset the clock for new turns and Windows sandbox setup.
- Use the independent timer as the fallback for the final turn duration.

## Testing

Add timer unit coverage and TUI tests for hidden rows, outstanding approvals,
fallback turn durations, and fresh Windows sandbox setup clocks.

GitOrigin-RevId: a77931e465d5aedd4a8cd606a3a3117d1bb37ce7
2026-08-31 21:19:22 +00:00
Benjamin Carlsson 32f48598a0 Show successful TUI commands individually (#41893)
## What changed

- Emit a separate history cell for each completed command instead of grouping
  consecutive successes into a `Ran N commands` summary.
- Preserve `Explored` grouping for related file reads, searches, and listings.
- Replay completed commands as individual entries so their output and failure
  status remain visible.

## Testing

- Update TUI tests and snapshots for live exploration and replayed commands.

GitOrigin-RevId: 7dafe0b7846fc89784093791a6be137a1b1ab8ff
2026-08-31 18:34:10 +00:00
stefanstokic-oai 79b04f1ab5 Show actionable rate-limit banners in the TUI (#41742)
## What changed

- Carry optional backend-owned banner and account identity data through
  `account/rateLimits/read`, filtering banners that do not match the authenticated
  account and user.
- Render supported rate-limit notices above the composer with actions for usage,
  credits, resets, owner notifications, and plan management while preserving the
  existing fallback UI for absent or unsupported banners.
- Refresh usage after limit errors, reject stale responses, and keep queued input
  paused until recovery completes. When instructed by the banner, switch to the
  first available fallback model without changing unrelated thread settings.

## Testing

- Add protocol, banner parsing and rendering, CTA, identity filtering, refresh
  ordering, fallback-model, account-change, and queued-input recovery coverage.

GitOrigin-RevId: e03d75a82e425deb87f4b120a71cf2286c0ef6cc
2026-08-31 00:20:06 +00:00
Eric Traut 80e871309a Route cyber Trusted Access links by plan type (#40504)
## What changed

- Send `Free`, `Go`, `Plus`, `Pro`, and `ProLite` ChatGPT users to the individual Trusted Access page when a cybersecurity policy error ends a turn.
- Keep the enterprise Trusted Access application for other plans and sessions without a ChatGPT account or known plan.

## Testing

- Cover individual and enterprise link selection in chat widget tests and history-cell snapshots.

GitOrigin-RevId: a563560d15c401b47f1865a6f58ea4692d31d457
2026-08-25 00:39:27 +00:00
Eric Traut 83d1fe0e67 Remove the Plan mode composer nudge (#40200)
## What changed

- Keep the normal composer footer visible when a draft contains the word `plan`.
- Remove the contextual “Create a plan?” prompt, its Escape dismissal behavior, and its per-thread dismissal state.

## Testing

- Update wide and narrow composer snapshots to cover the standard footer for plan-related drafts.

GitOrigin-RevId: 1a3c8cfce9d4effa2149790975133f652aa7c914
2026-08-23 07:24:57 +00:00
Eric Traut 785ecd7452 Stop TUI chats on misalignment policy violations (#39261)
## Why

When the app server reports a misalignment policy violation, the TUI must stop the affected chat rather than allow more work to continue in it.

## What changed

- Finalize the active turn, clear queued and draft input, disable the composer, and reject further operations and interactive requests for the stopped chat.
- Interrupt an active side conversation when its parent reports the violation, and prevent queued turns, forks, approvals, or goal resumption from restarting work.
- Show a non-dismissible precaution view that directs users to start a new chat or resume another one, with agent command center navigation for remote sessions.

## Testing

Added coverage for stopped-chat behavior, parent/side-thread handling, blocked goal resumption, navigation actions, and narrow and remote-session rendering.

GitOrigin-RevId: 0268c46a19294a17765ea4099f389f15ffaaf030
2026-08-18 18:50:58 +00:00
Eric Traut 1f41cc5d92 Compact successful command activity in the TUI (#38921)
## What changed

- Group consecutive successful agent and unified-exec startup commands into a compact `Ran N commands` entry while preserving their full transcript.
- Flush command groups at interaction boundaries, after failures, and after 32 completed commands. Keep manual shell commands and failed or declined commands visible.
- Apply the same grouping rules when replaying thread history without duplicating command starts or disturbing unrelated active commands.

## Testing

- Add TUI coverage for live and replayed grouping, transcript preservation, failures, overlapping commands, group limits, and interaction boundaries.

GitOrigin-RevId: d6602a20201644012fcff3d6cecf4690024383a9
2026-08-17 00:32:09 +00:00
Eric Traut ca83f7908c Add running-task exit choices to local daemon sessions (#38447)
## What changed

When `Ctrl-C` is pressed with an empty composer while a task is running in a local daemon session, show a menu that lets the user:

- cancel the task and stay in Codex;
- exit Codex while leaving the task running; or
- stop the task and exit Codex.

Do not offer background execution for side-thread tasks or when follow-up messages are queued. Preserve existing `Ctrl-C` behavior for non-daemon sessions, drafts, paste bursts, MCP startup, and returning from an active side thread.

## Testing

Add TUI tests for each exit action, menu dismissal, side threads, queued follow-ups, composer input, MCP startup, and non-daemon sessions.

GitOrigin-RevId: 539c33d3a4ff288a015bddbe9465d2bbdbe018d0
2026-08-13 22:38:46 +00:00
Felipe Coury 1e71e35df6 Add thread usage to TUI status surfaces (#38282)
## What changed

- Add `thread-credits` and `estimated-thread-cost` items to the configurable
  status line and terminal title for Enterprise workspaces.
- Fetch one shared thread usage estimate only when either item is selected,
  omit unavailable values, and refresh the display after turns complete.
- Preserve the last nonzero estimate while usage settles, with bounded delayed
  refreshes and retries for transient failures.

## Testing

- Add coverage for configuration, rendering, previews, plan availability,
  replay handling, retries, and post-turn settlement.

GitOrigin-RevId: dd69ee621c5bca0e5d9edd32b2bba42487eb1500
2026-08-13 00:34:39 +00:00
jif e1895710ad Fix TUI input queue handling during MCP startup (#35957)
## Why

Pending MCP server startup can outlive an agent turn. Treating its shared
running indicator as an active user turn prevents queued follow-ups and slash
commands from advancing after the turn completes.

## What changed

- Allow the input queue to drain while only MCP startup remains active.
- Keep queued input blocked while a review, foreground shell command, or
  compaction is pending or running.
- Resume queue draining after session-selection flows close.

## Testing

Add TUI tests covering queued follow-ups, slash commands, reviews, shell
commands, and compaction while MCP startup is pending.

GitOrigin-RevId: f5684f61c32e3728ff71cf222f0486df637dc3a5
2026-07-29 13:45:58 +00:00
Eric Traut 80f3c3141e Include the final agent message in turn completion summaries (#34777)
## Why

Streamed message deltas can be dropped when the transport is saturated, leaving
clients with a truncated final response.

## What changed

- Include the last non-empty final agent message in successful `turn/completed`
  notifications and mark the items as a summary.
- Treat completed message content as authoritative in the TUI, repairing an
  incomplete stream while avoiding duplicate messages when `item/completed` was
  already received.
- Continue backfilling full turn items for persisted `codex exec` threads when a
  completion contains only the summary view.

## Testing

Added coverage for completion summaries, dropped stream deltas, duplicate item
handling, and directive-only responses.

GitOrigin-RevId: ffe9d36d683d6b6690e4a468ff68aa9189fe6ab7
2026-07-22 15:41:47 +00:00
Eric Traut 0a39ff138e Keep the TUI open when starting a turn fails (#34636)
## What changed

- Handle app-server `turn/start` rejections for pending user turns as turn
  errors instead of exiting the TUI.
- Finalize the pending turn, display the failure in the transcript, and resume
  queued input handling.
- Add coverage that submits a turn to a missing thread and verifies that the
  error is shown while the app continues running.

GitOrigin-RevId: 6d291ba62b9e50d49dd4e3d7c429e98c1f754680
2026-07-21 23:13:12 +00:00
Eric Traut 5c18cc0acc Clear stale Guardian reviews when turns end (#34371)
## Why

Pending Guardian review state could outlive an interrupted or completed turn,
leaving stale review details visible during a following goal turn.

## What changed

- Clear pending Guardian reviews during both turn completion and finalization.
- Restore an active MCP startup header after cleanup, falling back to `Working`
  when no MCP server is starting.

## Testing

Added coverage for interrupted and completed turns, including goal continuation
and overlapping MCP startup status.

GitOrigin-RevId: a15ed81a5d6005e9294089f4424a8dedbc6e9cb5
2026-07-20 16:05:14 +00:00
Charlie Marsh 35eaf3ffb0 Avoid redundant TUI redraws while streaming (#34049)
## What changed

- Redraw assistant and plan stream tails only when a completed line changes the visible tail.
- Cache the first reasoning header and update the status indicator only when its visible state changes, while restoring the cached header if the indicator is recreated.
- Keep regular commit ticks able to clear stale stream tails.

## Testing

- Add coverage for unchanged partial deltas, changed newline-delimited tails, reasoning-header redraws, recreated status indicators, stale plan tails, and history-line draw scheduling.

GitOrigin-RevId: 9016175f97ef2db2edc2fd5ba13a4d731dc2d98c
2026-07-18 18:19:39 +00:00
Felipe Coury 70a0b1eef8 Keep interrupted prompts in conversation history (#33198)
## What changed

- Leave an output-free interrupted prompt in the transcript and open a blank
  composer for the user's next instruction.
- Use the normal interruption notice for both `Esc` and `Ctrl-C` interrupts.
- Track safety-buffering prompts separately so failed retries can still restore
  the prompt, including after switching between threads.

## Testing

- Cover output-free `Esc` and `Ctrl-C` interrupts, failed safety-buffer retries,
  and restoration of safety-buffer state from thread snapshots.

GitOrigin-RevId: 30b368d00dfdb981d06d4c95ce3f252389b7917c
2026-07-15 01:07:29 +00:00
Felipe Coury f46b53bd85 fix(tui): hide empty reasoning summaries (#31652)
## Why

Reasoning summaries can contain an empty HTML comment placeholder, `<!--
-->`, when a generated summary part has no prose. The TUI treated that
placeholder as visible summary content, so it leaked into both the
completed conversation history and persisted transcript. Multi-part
empty summaries could also leave later generated status headings visible
as orphaned transcript content.

## What

- Strip the empty reasoning-summary placeholder at the shared
`ReasoningSummaryCell` boundary.
- Suppress the cell when removing placeholders leaves only generated
bold status headings.
- Cover the multi-part placeholder-only shape with a rendering
regression test for both normal history and transcript output.

## How to Test

1. Start Codex TUI with reasoning summaries visible, for example with
`hide_agent_reasoning = false` and `model_reasoning_summary =
"detailed"`.
2. Run a turn that receives an empty generated reasoning-summary part.
3. Confirm that the in-progress status heading may appear while the turn
is running, but the completed history and transcript contain neither
literal `<!-- -->` tokens nor orphaned reasoning headings.
4. Confirm that a reasoning summary with actual prose still renders
normally.

The model output is nondeterministic, so the targeted regression covers
the exact multi-part placeholder shape from the report:

- `just test -p codex-tui
reasoning_summary_block_hides_empty_html_comment_parts`
2026-07-09 16:27:50 +00:00
Francis Chalissery 78df1237d1 Handle bio policy errors in Codex (#31439)
## Summary

- Treat streamed Responses `bio_policy` failures as terminal invalid
requests instead of retryable stream errors.
- Recognize the new biology policy code and message in the TUI while
preserving the legacy `invalid_prompt` contract.
- Keep the existing dedicated biology safety notice and add
regression/snapshot coverage for all supported error shapes.

## Why

[openai/openai#1068559](https://github.com/openai/openai/pull/1068559)
gates a Responses API contract change from `invalid_prompt` and the
legacy message to `bio_policy` and new biology copy.

Without this compatibility change, streamed blocks are retried as
transient failures and the OSS TUI falls back to a generic/raw error
instead of the dedicated safety notice.

## Validation

- `just test -p codex-api` — 137 passed
- `just test -p codex-tui
app_server_safety_access_errors_render_dedicated_notice` — passed
- `just fix -p codex-api`
- `just fix -p codex-tui`
- `just fmt`
- `just test -p codex-tui` — 2,957 passed; two reproducible failures
remain in untouched Guardian feature-flag persistence tests:
-
`update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`
-
`update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`
2026-07-07 10:33:42 -07:00
Felipe Coury 850da19dc4 fix(tui): clear completed safety buffering prompt (#30490)
## Why

The safety-buffering prompt is a modal TUI view, but the normal
successful-turn path only hid the running status indicator. If the turn
completed while the prompt was open, the stale modal remained over the
composer until the user dismissed it or another turn started.

This aligns the TUI with the app behavior: keep the safety notice
visible while the turn is active, then remove it when the turn becomes
terminal. It also prevents the stale retry action from changing the
model and reasoning effort for a future turn after the buffered turn has
already completed.

| New copy |
|---|
| <img width="1014" height="313" alt="CleanShot 2026-06-28 at 20 27 18"
src="https://github.com/user-attachments/assets/f0f37359-5d77-442f-add2-9d1874bdc422"
/> |

## What changed

- Clear the active safety-buffering view and retry state when a turn
completes successfully.
- Update the retry-capable message to say “Hang tight or retry with a
faster model”.
- Extend the safety-buffering regression coverage to verify that the
prompt remains visible after assistant output starts and disappears when
the turn completes.
- Update the TUI snapshot for the revised copy.

This is a follow-up to #29919.

## How to Test

1. Start a TUI turn that receives `model/safetyBuffering/updated` with
`showBufferingUi: true` and a `fasterModel`.
2. Confirm the prompt says “Hang tight or retry with a faster model”.
3. Let the turn continue and confirm the prompt remains visible while
the turn is active.
4. Let the turn finish successfully and confirm the prompt disappears
and the composer is restored without requiring an extra keypress.
5. Confirm a buffering update without a faster model still shows the
shorter non-retry message.

Targeted automated coverage:

- `just test -p codex-tui safety_buffering` — 4 passed.
- `just test -p codex-tui` — 2,951 passed; two unrelated Guardian
feature-flag tests failed identically on `main` in this environment.

The argument-comment lint was also audited manually. The workspace Bazel
invocation was blocked by a missing external LLVM `compiler-rt` BUILD
file, and the packaged per-crate fallback uses a nightly older than the
current `sqlx` minimum Rust version.
2026-06-28 20:55:53 -03:00
Eric Traut 6801941cfe TUI support for buffer experience (#29919) 2026-06-24 19:50:50 -07:00
jay f8f5a6e78f feat(tui): add rate-limit reset redemption to /usage (#28154)
## Why

Codex users can earn personal rate-limit reset credits, but the CLI does
not currently provide a way to view or redeem them. The `/usage` command
restored in #27925 is intended to be the entry point for usage-related
actions, so reset redemption belongs there rather than in a separate
dashed slash command.

Depends on #28143 for the app-server and backend-client reset-credit
APIs.

## What changed

- Turn bare `/usage` into a menu with entries for token activity and
earned rate-limit resets while preserving `/usage daily`, `/usage
weekly`, and `/usage cumulative`.
- Add loading, empty, confirmation, success, retry, and error states
with a caller-generated UUID idempotency key reused across retries of
the same logical reset.
- Show an availability hint only for backend-classified rate-limit
errors with credits available.
- Hide the reset entry for workspace accounts.

## Validation

- `just test -p codex-tui chatwidget::tests::usage` — 19 passed.
- `just fix -p codex-tui` — passed.
- `just fmt` — passed.
- `cargo insta pending-snapshots` from `codex-rs/tui` — no pending
snapshots.

## Examples
<img width="1168" height="304" alt="image"
src="https://github.com/user-attachments/assets/caa4c1e3-e996-494d-ae17-50b521f5dce8"
/>
<img width="908" height="260" alt="image"
src="https://github.com/user-attachments/assets/e38a726b-77cc-4bd0-9ea8-9f3ad21c5768"
/>


### Reset flow
<img width="1509" height="312" alt="image"
src="https://github.com/user-attachments/assets/d987013c-78a5-48a2-ad8d-c61ad267a327"
/>
<img width="585" height="190" alt="image"
src="https://github.com/user-attachments/assets/de32be19-79b9-4a3e-8574-6f1c208c98ae"
/>
<img width="600" height="210" alt="image"
src="https://github.com/user-attachments/assets/88a165cf-796d-4fdc-a7bc-ea89917573da"
/>

<img width="512" height="193" alt="image"
src="https://github.com/user-attachments/assets/d2353998-5aa8-442e-a5f8-3a8a5b832753"
/>
2026-06-16 17:59:40 +00:00
Felipe Coury c884536d84 feat(tui): reland token activity command (#27925)
## Why

[#25345](https://github.com/openai/codex/pull/25345) was approved,
green, and squash-merged into its stacked base branch,
`fcoury/tokenmaxxing-api`. Four minutes later, that base branch was
force-pushed back to an API-only rebased head while preparing
[#25344](https://github.com/openai/codex/pull/25344) for `main`. As a
result, the squash commit from #25345 was orphaned and the TUI command
never reached `main` or a release.

This PR relands the orphaned TUI change from
[`411410b8`](https://github.com/openai/codex/commit/411410b85c2d8eb050d441f17396c5c4048d866f)
on current `main`.

## What changed

- Add `/usage`, `/usage daily`, `/usage weekly`, and `/usage cumulative`
for account token activity.
- Fetch account usage asynchronously through the existing
`account/usage/read` app-server RPC.
- Render daily, weekly, and cumulative activity with theme-aware
terminal palettes and bounded transient cards.
- Preserve transcript ordering while assistant streams, history
consolidations, active cells, and hooks complete.
- Hide `/usage` from completion when backend auth is unavailable while
keeping typed-command guidance.
- Carry current-main behavior forward for cwd-aware Markdown parsing,
Windows Terminal color detection, and personal access token auth.
- Clear pending usage cards on thread rollback and delay completed cards
until live hook output is committed.
- Add focused regression and snapshot coverage for loading, auth errors,
invalid views, rollback, hook ordering, layout, and charts.

## Prior review

The original implementation was approved by Eric Traut in #25345 after
testing multiple themes and light/dark terminals. This PR preserves that
reviewed implementation while adapting it to current `main` and adding
regression coverage for newer rollback and hook lifecycle behavior.

## Validation

- `just test -p codex-tui token_activity palette renderable
usage_command` — 37 passed.
- Focused rollback, hook-ordering, and error snapshot tests — 4 passed.
- `just fix -p codex-tui` — passed.
- `UV_CACHE_DIR=/private/tmp/codex-uv-cache just fmt` — passed.
- `cargo insta pending-snapshots` — no pending snapshots.
- `just test -p codex-tui` — 2,870 passed; two unrelated guardian
feature-flag tests failed because their expected `OverrideTurnContext`
event was absent:
-
`update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`
-
`update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`
- `just argument-comment-lint` could not complete because the local
Bazel LLVM `compiler-rt` repository is missing `include/sanitizer/*.h`.
The touched Rust diff was manually inspected and no missing
opaque-literal argument comments were found.
2026-06-12 17:33:43 -07:00
Mitsuhiro Kotake 44403dd3dd tui: clear stale hook row after turn completion (#27619)
Fixes #27210.

## Why
When the app server reports a visible `HookStarted` event for a
`PostToolUse` hook but the turn reaches `TurnCompleted` before a
matching hook completion event arrives, the TUI can leave the transient
`Running PostToolUse hook` row visible after the agent is done.
Interrupted and failed turn cleanup already drops transient live hook
rows; the normal completion path did not.

## What Changed
- Added `ChatWidget::clear_active_hook_cell()` for dropping transient
live hook status without writing it to history.
- Call that cleanup from normal task completion, while reusing it for
the existing start/finalize cleanup paths.
- Added `completed_turn_clears_visible_running_hook` snapshot coverage
for the reported `PostToolUse` case.

## Tests
- `just test -p codex-tui completed_turn_clears_visible_running_hook`
- `just test -p codex-tui` (fails on current `main` in unrelated
guardian tests:
`update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`
and
`update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`)
2026-06-12 09:15:04 +09:00
Eric Traut e5af672d73 Render code comment directives in TUI replay (#26554)
## Summary

Resumed Codex App or VS Code review sessions can contain
`::code-comment` directives that the TUI previously displayed verbatim
because only rich clients interpret them.

This change rewrites valid line-start directives into readable Markdown
during assistant-message parsing, using the session working directory
for relative file paths. The fallback is applied consistently to live
messages, replayed transcripts, and resume previews while preserving
malformed directives and existing `::git-*` parsing.

## Before

The TUI exposed the raw client directive:

```text
::code-comment{title="Fix body= parsing" body="Keep role=\"tab\", ::git-stage{cwd=/tmp}, file=, and \n literal." file="/repo/src/app.ts" start=10 end=12 priority="P2"}
```

## After

The same directive is rendered as readable review feedback:

```text
- [P2] Fix body= parsing — src/app.ts:10-12
  Keep role="tab", ::git-stage{cwd=/tmp}, file=, and \n literal.
```

Fixes #25658
2026-06-05 08:34:34 -07:00
Felipe Coury c0ea566bb5 feat(tui): restore output-free cancelled prompts (#25316)
## TL;DR

When you press Esc or Ctrl+C after sending a prompt but before any
output was rendering, it restores the last composer and the message.

## Summary

Cancelling a prompt immediately after submission should behave like
returning to edit that prompt, not like discarding the user's draft.
Today, pressing `Esc` or `Ctrl+C` before Codex responds leaves the
submitted prompt in the transcript and returns an empty composer,
forcing the user to recall or retype it.

When an interrupted turn has not produced substantive visible output,
restore its submitted prompt directly into the composer and roll back
that latest turn. This also covers the first prompt in a fresh thread,
before the TUI has retained a local user-history cell. The restored
draft keeps its text, image attachments, and active collaboration mode
so it can be edited and resubmitted in place.

Restoration is intentionally suppressed once the turn has produced
user-visible activity such as assistant output, tool work, hooks, or
patches. A transient thinking status does not make the prompt
ineligible. Rollback also rebuilds terminal scrollback from the retained
transcript cells so repeated cancellations and terminal resizes do not
duplicate history.

## How to Test

1. Start the TUI with `cargo run -p codex-cli --bin codex`.
2. In a fresh thread, submit the first prompt and press `Esc` before
Codex emits substantive output. Confirm that the prompt returns to the
composer for editing and its submitted transcript row is removed.
3. Repeat with `Ctrl+C`, then repeat after at least one completed turn.
Confirm the same behavior.
4. Submit a prompt, wait for assistant output or tool activity, then
cancel. Confirm that the transcript remains intact and the prompt is not
restored into the composer.
5. Cancel several output-free prompts and resize the terminal between
attempts. Confirm that the startup banner, tip, and transcript history
do not duplicate in scrollback.

Targeted tests:
- `just test -p codex-tui cancelled_turn_edit_restores_prompt`
- `just test -p codex-tui
output_free_interrupted_turn_requests_prompt_restore`
- `just test -p codex-tui
visible_output_prevents_cancelled_turn_prompt_restore`
- `just test -p codex-tui
thinking_status_keeps_cancelled_turn_prompt_restore_eligible`
- `just test -p codex-tui
patch_activity_prevents_cancelled_turn_prompt_restore`

The full `just test -p codex-tui` run completed with `2746` passing
tests and two unrelated existing guardian feature-flag failures. `just
argument-comment-lint` remains blocked locally by the existing Bazel
LLVM `compiler-rt` sanitizer-header glob failure; the touched Rust diff
was manually audited for positional literal comments.
2026-06-01 11:49:14 -03:00
Eric Traut deb159d9ff Fix TUI stream cleanup after turn errors (#23128)
## Summary

Fixes #22726.

After a Responses stream disconnect, the live TUI could keep accepting
prompts while leaving partially streamed assistant output in its
transient streaming-cell form. That made fenced diffs or SVG/XML-like
content appear as raw transcript text until the user closed the TUI and
resumed the same session, which rebuilt the transcript from saved
history.

This change finalizes the active answer stream before generic
failed-turn cleanup clears the stream controller, so the live transcript
takes the same source-backed markdown consolidation path as a successful
turn.

## Reviewer repro

1. Start a local Codex TUI session.
2. Trigger an assistant turn that streams markdown content, especially a
fenced diff or SVG/XML-like block.
3. Force or encounter a non-retry stream disconnect before the turn
completes.
4. Continue using the same still-open TUI session.
5. Before this fix, the live history can stay raw/plain even though
`codex resume` renders the same session normally.
6. After this fix, the failed-turn path consolidates the partial stream
before rendering the error, so the live TUI keeps normal transcript
rendering.
2026-05-18 09:00:57 -07:00
canvrno-oai 66af217865 Fix /review mode MCP startup render issue (#21624)
This change fixes the case where the UI can sit on _"Starting MCP
servers"_ even though the review work is already running or has already
completed.

- MCP startup status header is visible when a `/review` turn starts with
enabled MCP server startups
- Restore the underlying _Working..._ status after MCP startup completes
or fails
- Add regression coverage for overlapping startup/turn flows and status
restoration

_De-scoped from a broader thread-scoped MCP status change that would
have made it easier to route MCP startup statuses to the appropriate
thread (parent vs. review). These changes address the UI regression
without requiring more significant changes across app-server & core._

Fixes #18792.
2026-05-14 17:25:32 -07:00
Eric Traut 8fe0ecb045 Refactor chatwidget protocol flows into modules (phase 3) (#22433)
## Why

`chatwidget.rs` is still carrying too many unrelated responsibilities in
one file. #22269 started a five-phase cleanup to move coherent behavior
domains into focused modules while keeping `chatwidget.rs` as the
composition layer. #22407 completed phase 2 by extracting input and
submission flow.

This PR is phase 3. It keeps moving high-churn event handling out of the
central widget by extracting protocol, replay, streaming, and tool
lifecycle handling without changing the visible behavior those flows
already provide. This is once again just a mechanical movement of
existing functions. No functional changes.

## What Changed

- Added focused modules for protocol request dispatch, replay rendering,
assistant/plan/reasoning streaming, turn runtime bookkeeping, hook
lifecycle handling, command lifecycle handling, tool lifecycle
rendering, and interactive tool request prompts.
- Kept active-cell grouping, transcript invalidation, interrupt
deferral, and final-message separator behavior in the same flows, just
moved into smaller files.
- Added module header comments to the new files so the ownership
boundaries are explicit.
- Left `codex-rs/tui/src/chatwidget.rs` as the registration and
orchestration surface for these extracted behaviors.

## Cleanup Phases

The five-phase cleanup plan from #22269 is:

1. Phase 1: mechanical helper and state moves. Completed in #22269.
2. Phase 2: extract input and submission flow, including queued user
messages, shell prompt submission, pending steer restoration, and thread
input snapshot/restore behavior. Completed in #22407.
3. Phase 3: extract protocol, replay, streaming, and tool lifecycle
handling, while preserving active-cell grouping, transcript
invalidation, interrupt deferral, and final-message separator behavior.
This PR.
4. Phase 4: extract settings, popups, and status surfaces, including
model/reasoning/collaboration/personality popups, permission prompts,
rate-limit UI, and connectors helpers.
5. Phase 5: clean up the remaining constructor and orchestration code
once the larger behavior domains have moved out, leaving `chatwidget.rs`
as the composition layer.
2026-05-13 08:52:56 -07:00