Commit Graph

461 Commits

Author SHA1 Message Date
sayan-oai
5d2702f6b8 fix(tui): conditionally restore status indicator using message phase (#10947)
TLDR: use new message phase field emitted by preamble-supported models
to determine whether an AgentMessage is mid-turn commentary. if so,
restore the status indicator afterwards to indicate the turn has not
completed.

### Problem
`commit_tick` hides the status indicator while streaming assistant text.
For preamble-capable models, that text can be commentary mid-turn, so
hiding was correct during streaming but restore timing mattered:
- restoring too aggressively caused jitter/flashing
- not restoring caused indicator to stay hidden before subsequent work
(tool calls, web search, etc.)

### Fix
- Add optional `phase` to `AgentMessageItem` and propagate it from
`ResponseItem::Message`
- Keep indicator hidden during streamed commit ticks, restore only when:
  - assistant item completes as `phase=commentary`, and
  - stream queues are idle + task is still running.
- Treat `phase=None` as final-answer behavior (no restore) to keep
existing behavior for non-preamble models

### Tests
Add/update tests for:
- no idle-tick restore without commentary completion
- commentary completion restoring status before tool begin
- snapshot coverage for preamble/status behavior

---------

Co-authored-by: Josh McKinney <joshka@openai.com>
2026-02-07 02:39:52 +00:00
daniel-oai
84bce2b8e6 TUI/Core: preserve duplicate skill/app mention selection across submit + resume (#10855)
## What changed

- In `codex-rs/core/src/skills/injection.rs`, we now honor explicit
`UserInput::Skill { name, path }` first, then fall back to text mentions
only when safe.
- In `codex-rs/tui/src/bottom_pane/chat_composer.rs`, mention selection
is now token-bound (selected mention is tied to the specific inserted
`$token`), and we snapshot bindings at submit time so selection is not
lost.
- In `codex-rs/tui/src/chatwidget.rs` and
`codex-rs/tui/src/bottom_pane/mod.rs`, submit/queue paths now consume
the submit-time mention snapshot (instead of rereading cleared composer
state).
- In `codex-rs/tui/src/mention_codec.rs` and
`codex-rs/tui/src/bottom_pane/chat_composer_history.rs`, history now
round-trips mention targets so resume restores the same selected
duplicate.
- In `codex-rs/tui/src/bottom_pane/skill_popup.rs` and
`codex-rs/tui/src/bottom_pane/chat_composer.rs`, duplicate labels are
normalized to `[Repo]` / `[App]`, app rows no longer show `Connected -`,
and description space is a bit wider.

<img width="550" height="163" alt="Screenshot 2026-02-05 at 9 56 56 PM"
src="https://github.com/user-attachments/assets/346a7eb2-a342-4a49-aec8-68dfec0c7d89"
/>
<img width="550" height="163" alt="Screenshot 2026-02-05 at 9 57 09 PM"
src="https://github.com/user-attachments/assets/5e04d9af-cccf-4932-98b3-c37183e445ed"
/>


## Before vs now

- Before: selecting a duplicate could still submit the default/repo
match, and resume could lose which duplicate was originally selected.
- Now: the exact selected target (skill path or app id) is preserved
through submit, queue/restore, and resume.

## Manual test

1. Build and run this branch locally:
   - `cd /Users/daniels/code/codex/codex-rs`
   - `cargo build -p codex-cli --bin codex`
   - `./target/debug/codex`
2. Open mention picker with `$` and pick a duplicate entry (not the
first one).
3. Confirm duplicate UI:
   - repo duplicate rows show `[Repo]`
   - app duplicate rows show `[App]`
   - app description does **not** start with `Connected -`
4. Submit the prompt, then press Up to restore draft and submit again.  
   Expected: it keeps the same selected duplicate target.
5. Use `/resume` to reopen the session and send again.  
Expected: restored mention still resolves to the same duplicate target.
2026-02-06 15:59:00 -08:00
alexsong-oai
daeef06bec add originator to otel (#10826) 2026-02-06 15:13:56 -08:00
Charley Cunningham
b7ecd166a6 Queue nudges while plan generating (#10457)
## Summary

This PR fixes a UI/streaming race when nudged or steer-enabled messages
are queued during an active Plan stream.

Previously, `submit_user_message_with_mode` switched collaboration mode
immediately (via `set_collaboration_mask`) even when the message was
queued. If that happened mid-Plan stream, `active_mode_kind` could flip
away from Plan before the turn finished, causing subsequent
`on_plan_delta` updates to be ignored in the UI.

Now, mode switching is deferred until the queued message is actually
submitted.

## What changed

- Added a per-message deferred mode override on `UserMessage`:
  - `collaboration_mode_override: Option<CollaborationModeMask>`
- Updated `submit_user_message_with_mode` to:
  - create a `UserMessage` carrying the mode override
- queue or submit that message without mutating global mode immediately
- Updated `submit_user_message` to:
- apply `collaboration_mode_override` just before constructing/sending
`Op::UserTurn`
- Kept queueing condition scoped to active Plan stream rendering:
- queue only while plan output is actively streaming in TUI
(`plan_stream_controller.is_some()`)

## Why

This preserves Plan mode for the remainder of the in-flight Plan turn,
so streamed plan deltas continue rendering correctly, while still
ensuring the follow-up queued message is sent with the intended
collaboration mode.

## Behavior after this change

- If a nudged/steer submission happens while Plan output is actively
streaming:
  - message is queued
  - UI stays in Plan mode for the running turn
- once dequeued/submitted, mode override is applied and the message is
sent in the intended mode
- If no Plan stream is active:
- submission proceeds immediately and mode override is applied as before

## Tests

Added/updated coverage in `tui/src/chatwidget/tests.rs`:

- `submit_user_message_with_mode_queues_while_plan_stream_is_active`
  - asserts mode remains Plan while queued
- asserts mode switches to Code when queued message is actually
submitted
- `submit_user_message_with_mode_submits_when_plan_stream_is_not_active`
- `steer_enter_queues_while_plan_stream_is_active`
- `steer_enter_submits_when_plan_stream_is_not_active`

Also updated existing `UserMessage { ... }` test fixtures to include the
new field.

## Codex author
`codex fork 019c1047-d5d5-7c92-a357-6009604dc7e8`
2026-02-06 09:43:00 -08:00
Eric Traut
f61226d32a Personality setting is no longer available in experimental menu (#10852)
This PR removes the inaccurate "Disable in /experimental." statement now
that the "personality" feature flag is no longer experimental.

This addresses #10850
2026-02-05 22:19:09 -08:00
Anton Panasenko
4ee039744e feat: expose detailed metrics to runtime metrics (#10699) 2026-02-05 18:22:30 -08:00
Felipe Coury
b0e5a6305b feat(tui): add /statusline command for interactive status line configuration (#10546)
## Summary
- Adds a new `/statusline` command to configure TUI footer status line
- Introduces reusable `MultiSelectPicker` component with keyboard
navigation, optional ordering and toggle support
- Implement status line setup modal that persist configuration to
config.toml

  ## Status Line Items
  The following items can be displayed in the status line:
  - **Model**: Current model name (with optional reasoning level)
  - **Context**: Remaining/used context window percentage
  - **Rate Limits**: 5-day and weekly usage limits
  - **Git**: Current branch (with optimized lookups)
  - **Tokens**: Used tokens, input/output token counts
  - **Session**: Session ID (full or shortened prefix)
  - **Paths**: Current directory, project root
  - **Version**: Codex version

  ## Features
  - Live preview while configuring status line items
  - Fuzzy search filtering in the picker
  - Intelligent truncation when items don't fit
  - Items gracefully omit when data is unavailable
  - Configuration persists to `config.toml`
  - Validates and warns about invalid status line items

  ## Test plan
  - [x] Run `/statusline` and verify picker UI appears
  - [x] Toggle items on/off and verify live preview updates
  - [x] Confirm selection persists after restart
  - [x] Verify truncation behavior with many items selected
  - [x] Test git branch detection in and out of git repos

---------

Co-authored-by: Josh McKinney <joshka@openai.com>
2026-02-05 08:50:21 -08:00
jif-oai
fe1cbd0f38 chore: handle shutdown correctly in tui (#10756) 2026-02-05 16:07:50 +00:00
pap-openai
b2424cb635 adding fork information (UI) when forking (#10246)
- shows `/fork` command that ran in prev session
- shows `session forked from name (uuid) || uuid (if name is not set)` as an event in new session
2026-02-05 13:24:55 +00:00
Dylan Hurd
a05aadfa1b chore(config) Default Personality Pragmatic (#10705)
## Summary
Switch back to Pragmatic personality

## Testing
- [x] Updated unit tests
2026-02-04 21:22:47 -08:00
sayan-oai
4ed8d74aab fix: ensure status indicator present earlier in exec path (#10700)
ensure status indicator present in all classifications of exec tool.
fixes indicator disappearing after preambles, will look into using
`phase` to avoid this class of error in a few hours.

commands parsed as unknown faced this issue

tested locally, added test for specific failure flow
2026-02-05 03:56:50 +00:00
Josh McKinney
d876f3b94f fix(tui): restore working shimmer after preamble output (#10701)
## Problem
When a turn streamed a preamble line before any tool activity,
`ChatWidget` hid the status row while committing streamed lines and did
not restore it until a later event (commonly `ExecCommandBegin`). During
that idle gap, the UI looked finished even though the turn was still
active.

## Mental model
The bottom status row and transcript stream are separate progress
affordances:
- transcript stream shows committed output
- status row (spinner/shimmer + header) shows liveness of an active turn

While stream output is actively committing, hiding the status row is
acceptable to avoid redundant visual noise. Once stream controllers go
idle, an active turn must restore the status row immediately so liveness
remains visible across preamble-to-tool gaps.

## Non-goals
- No changes to streaming chunking policy or pacing.
- No changes to final completion behavior (status still hides when task
actually ends).
- No refactor of status lifecycle ownership between `ChatWidget` and
`BottomPane`.

## Tradeoffs
- We keep the existing behavior of hiding the status row during active
stream commits.
- We add explicit restoration on the idle boundary when the task is
still running.
- This introduces one extra status update on idle transitions, which is
small overhead but makes liveness semantics consistent.

## Architecture
`run_commit_tick_with_scope` in `chatwidget.rs` now documents and
enforces a two-phase contract:
1. For each committed streamed cell, hide status and append transcript
output.
2. If controllers are present and all idle, restore status iff task is
still running, preserving the current header.

This keeps status ownership in `ChatWidget` while relying on
`BottomPane` helpers:
- `hide_status_indicator()` during active stream commits
- `ensure_status_indicator()` +
`set_status_header(current_status_header)` at stream-idle boundary

Documentation pass additions:
- Clarified the function-level contract and lifecycle intent in
`run_commit_tick_with_scope`.
- Added an explicit regression snapshot test comment describing the
failing sequence.

## Observability
Signal that the fix is present:
- In the preamble-idle state, rendered output still includes `• Working
(… esc to interrupt)`.
- New snapshot:
`codex_tui__chatwidget__tests__preamble_keeps_working_status.snap`.

Debug path for future regressions:
- Start at `run_commit_tick_with_scope` for hide/restore transitions.
- Verify `bottom_pane.is_task_running()` at idle transition.
- Confirm `current_status_header` continuity when status is recreated.
- Use the new snapshot and targeted test sequence to reproduce
deterministic preamble-idle behavior.

## Tests
- Updated regression assertion:
- `streaming_final_answer_keeps_task_running_state` now expects status
widget to remain present while turn is running.
- Renamed/updated behavioral regression:
  - `preamble_keeps_status_indicator_visible_until_exec_begin`.
- Added snapshot regression coverage:
  - `preamble_keeps_working_status_snapshot`.
- Snapshot file:
`tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__preamble_keeps_working_status.snap`.

Commands run:
- `just fmt`
- `cargo test -p codex-tui
preamble_keeps_status_indicator_visible_until_exec_begin`
- `cargo test -p codex-tui preamble_keeps_working_status_snapshot`

## Risks / Inconsistencies
- Status visibility policy is still split across multiple event paths
(`commit tick`, `turn complete`, `exec begin`), so future regressions
can reintroduce ordering gaps.
- Restoration depends on `is_task_running()` correctness; if task
lifecycle flags drift, status behavior will drift too.
- Snapshot proves rendered state, not animation cadence; cadence still
relies on frame scheduling behavior elsewhere.
2026-02-04 19:28:13 -08:00
Josh McKinney
aec58ac29b feat(tui): pace catch-up stream chunking with hysteresis (#10461)
## Summary
- preserve baseline streaming behavior (smooth mode still commits one
line per 50ms tick)
- extract adaptive chunking policy and commit-tick orchestration from
ChatWidget into `streaming/chunking.rs` and `streaming/commit_tick.rs`
- add hysteresis-based catch-up behavior with bounded batch draining to
reduce queue lag without bursty single-frame jumps
- document policy behavior, tuning guidance, and debug flow in rustdoc +
docs

## Testing
- just fmt
- cargo test -p codex-tui
2026-02-03 15:01:51 -08:00
Charley Cunningham
d509df676b Cleanup collaboration mode variants (#10404)
## Summary

This PR simplifies collaboration modes to the visible set `default |
plan`, while preserving backward compatibility for older partners that
may still send legacy mode
names.

Specifically:
- Renames the old Code behavior to **Default**.
- Keeps **Plan** as-is.
- Removes **Custom** mode behavior (fallbacks now resolve to Default).
- Keeps `PairProgramming` and `Execute` internally for compatibility
plumbing, while removing them from schema/API and UI visibility.
- Adds legacy input aliasing so older clients can still send old mode
names.

## What Changed

1. Mode enum and compatibility
- `ModeKind` now uses `Plan` + `Default` as active/public modes.
- `ModeKind::Default` deserialization accepts legacy values:
  - `code`
  - `pair_programming`
  - `execute`
  - `custom`
- `PairProgramming` and `Execute` variants remain in code but are hidden
from protocol/schema generation.
- `Custom` variant is removed; previous custom fallbacks now map to
`Default`.

2. Collaboration presets and templates
- Built-in presets now return only:
  - `Plan`
  - `Default`
- Template rename:
  - `core/templates/collaboration_mode/code.md` -> `default.md`
- `execute.md` and `pair_programming.md` remain on disk but are not
surfaced in visible preset lists.

3. TUI updates
- Updated user-facing naming and prompts from “Code” to “Default”.
- Updated mode-cycle and indicator behavior to reflect only visible
`Plan` and `Default`.
- Updated corresponding tests and snapshots.

4. request_user_input behavior
- `request_user_input` remains allowed only in `Plan` mode.
- Rejection messaging now consistently treats non-plan modes as
`Default`.

5. Schemas
- Regenerated config and app-server schemas.
- Public schema types now advertise mode values as:
  - `plan`
  - `default`

## Backward Compatibility Notes

- Incoming legacy mode names (`code`, `pair_programming`, `execute`,
`custom`) are accepted and coerced to `default`.
- Outgoing/public schema surfaces intentionally expose only `plan |
default`.
- This allows tolerant ingestion of older partner payloads while
standardizing new integrations on the reduced mode set.

## Codex author
`codex fork 019c1fae-693b-7840-b16e-9ad38ea0bd00`
2026-02-03 09:23:53 -08:00
pakrym-oai
bf87468c2b Restore status after preamble (#10465) 2026-02-02 20:35:50 -08:00
Colin Young
7e07ec8f73 [Codex][CLI] Gate image inputs by model modalities (#10271)
###### Summary

- Add input_modalities to model metadata so clients can determine
supported input types.
- Gate image paste/attach in TUI when the selected model does not
support images.
- Block submits that include images for unsupported models and show a
clear warning.
- Propagate modality metadata through app-server protocol/model-list
responses.
  - Update related tests/fixtures.

  ###### Rationale

  - Models support different input modalities.
- Clients need an explicit capability signal to prevent unsupported
requests.
- Backward-compatible defaults preserve existing behavior when modality
metadata is absent.

  ###### Scope

  - codex-rs/protocol, codex-rs/core, codex-rs/tui
  - codex-rs/app-server-protocol, codex-rs/app-server
  - Generated app-server types / schema fixtures

  ###### Trade-offs

- Default behavior assumes text + image when field is absent for
compatibility.
  - Server-side validation remains the source of truth.

  ###### Follow-up

- Non-TUI clients should consume input_modalities to disable unsupported
attachments.
- Model catalogs should explicitly set input_modalities for text-only
models.

  ###### Testing

  - cargo fmt --all
  - cargo test -p codex-tui
  - env -u GITHUB_APP_KEY cargo test -p codex-core --lib
  - just write-app-server-schema
- cargo run -p codex-cli --bin codex -- app-server generate-ts --out
app-server-types
  - test against local backend
  
<img width="695" height="199" alt="image"
src="https://github.com/user-attachments/assets/d22dd04f-5eba-4db9-a7c5-a2506f60ec44"
/>

---------

Co-authored-by: Josh McKinney <joshka@openai.com>
2026-02-02 18:56:39 -08:00
Michael Bolin
66447d5d2c feat: replace custom mcp-types crate with equivalents from rmcp (#10349)
We started working with MCP in Codex before
https://crates.io/crates/rmcp was mature, so we had our own crate for
MCP types that was generated from the MCP schema:


8b95d3e082/codex-rs/mcp-types/README.md

Now that `rmcp` is more mature, it makes more sense to use their MCP
types in Rust, as they handle details (like the `_meta` field) that our
custom version ignored. Though one advantage that our custom types had
is that our generated types implemented `JsonSchema` and `ts_rs::TS`,
whereas the types in `rmcp` do not. As such, part of the work of this PR
is leveraging the adapters between `rmcp` types and the serializable
types that are API for us (app server and MCP) introduced in #10356.

Note this PR results in a number of changes to
`codex-rs/app-server-protocol/schema`, which merit special attention
during review. We must ensure that these changes are still
backwards-compatible, which is possible because we have:

```diff
- export type CallToolResult = { content: Array<ContentBlock>, isError?: boolean, structuredContent?: JsonValue, };
+ export type CallToolResult = { content: Array<JsonValue>, structuredContent?: JsonValue, isError?: boolean, _meta?: JsonValue, };
```

so `ContentBlock` has been replaced with the more general `JsonValue`.
Note that `ContentBlock` was defined as:

```typescript
export type ContentBlock = TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource;
```

so the deletion of those individual variants should not be a cause of
great concern.

Similarly, we have the following change in
`codex-rs/app-server-protocol/schema/typescript/Tool.ts`:

```
- export type Tool = { annotations?: ToolAnnotations, description?: string, inputSchema: ToolInputSchema, name: string, outputSchema?: ToolOutputSchema, title?: string, };
+ export type Tool = { name: string, title?: string, description?: string, inputSchema: JsonValue, outputSchema?: JsonValue, annotations?: JsonValue, icons?: Array<JsonValue>, _meta?: JsonValue, };
```

so:

- `annotations?: ToolAnnotations` ➡️ `JsonValue`
- `inputSchema: ToolInputSchema` ➡️ `JsonValue`
- `outputSchema?: ToolOutputSchema` ➡️ `JsonValue`

and two new fields: `icons?: Array<JsonValue>, _meta?: JsonValue`

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/10349).
* #10357
* __->__ #10349
* #10356
2026-02-02 17:41:55 -08:00
Charley Cunningham
1096d6453c Fix plan implementation prompt reappearing after /agent thread switch (#10447)
## Summary

This fixes a UX bug (https://github.com/openai/codex/issues/10442) where
the **"Implement this plan?"** prompt could reappear after switching
agents with `/agent` and then switching back to the original agent
during plan execution.

## Root Cause

On thread switch, the TUI rebuilds `ChatWidget`, replays buffered thread
events, then drains any queued live events.

In this flow, a `TurnComplete` can be handled twice for the same logical
turn:
1. replayed (`from_replay = true`)
2. then live (`from_replay = false`)

`ChatWidget` used `saw_plan_item_this_turn` to decide whether to show
the plan implementation prompt, but that flag was only reset on
`TurnStarted`.
If duplicate completion events occurred, stale `saw_plan_item_this_turn
= true` could cause the prompt to re-trigger unexpectedly.

## Fix

- Clear `saw_plan_item_this_turn` at the end of `on_task_complete`,
after prompt gating runs.
- This keeps the flag truly turn-scoped and prevents duplicate
`TurnComplete` handling from reopening the prompt.
2026-02-02 17:40:05 -08:00
pakrym-oai
74327fa59c Select experimental features with space (#10281) 2026-02-02 11:35:11 -08:00
Charley Cunningham
3392c5af24 Nicer highlighting of slash commands, /plan accepts prompt args and pasted images (#10269)
## Summary
- Make typed slash commands become text elements when the user hits
space, including paste‑burst spaces.
- Enable `/plan` to accept inline args and submit them in plan mode,
mirroring `/review` behavior and blocking submission while a task is
running.
- Preserve text elements/attachments for slash commands that take args.

<img width="1510" height="500" alt="image"
src="https://github.com/user-attachments/assets/446024df-b69a-4249-85db-1a85110e07f1"
/>

## Changes
- Add safe helper to insert element ranges in the textarea.
- Extend command‑with‑args pipeline to carry text elements and reuse
submission prep.
- Update `/plan` dispatch to switch to plan mode then submit prompt +
elements.
- Document new composer behavior and add tests.

## Notes
- `/plan` is blocked during active tasks (same as `/review`).
- Slash‑command elementization recognizes built‑ins and `/prompts:`
custom commands only.

## Codex author
`codex fork 019c16d3-4520-7bb0-9b9d-48720d40a8ab`
2026-02-02 09:53:29 -08:00
Charley Cunningham
ec4a2d07e4 Plan mode: stream proposed plans, emit plan items, and render in TUI (#9786)
## Summary
- Stream proposed plans in Plan Mode using `<proposed_plan>` tags parsed
in core, emitting plan deltas plus a plan `ThreadItem`, while stripping
tags from normal assistant output.
- Persist plan items and rebuild them on resume so proposed plans show
in thread history.
- Wire plan items/deltas through app-server protocol v2 and render a
dedicated proposed-plan view in the TUI, including the “Implement this
plan?” prompt only when a plan item is present.

## Changes

### Core (`codex-rs/core`)
- Added a generic, line-based tag parser that buffers each line until it
can disprove a tag prefix; implements auto-close on `finish()` for
unterminated tags. `codex-rs/core/src/tagged_block_parser.rs`
- Refactored proposed plan parsing to wrap the generic parser.
`codex-rs/core/src/proposed_plan_parser.rs`
- In plan mode, stream assistant deltas as:
  - **Normal text** → `AgentMessageContentDelta`
  - **Plan text** → `PlanDelta` + `TurnItem::Plan` start/completion  
  (`codex-rs/core/src/codex.rs`)
- Final plan item content is derived from the completed assistant
message (authoritative), not necessarily the concatenated deltas.
- Strips `<proposed_plan>` blocks from assistant text in plan mode so
tags don’t appear in normal messages.
(`codex-rs/core/src/stream_events_utils.rs`)
- Persist `ItemCompleted` events only for plan items for rollout replay.
(`codex-rs/core/src/rollout/policy.rs`)
- Guard `update_plan` tool in Plan Mode with a clear error message.
(`codex-rs/core/src/tools/handlers/plan.rs`)
- Updated Plan Mode prompt to:  
  - keep `<proposed_plan>` out of non-final reasoning/preambles  
  - require exact tag formatting  
  - allow only one `<proposed_plan>` block per turn  
  (`codex-rs/core/templates/collaboration_mode/plan.md`)

### Protocol / App-server protocol
- Added `TurnItem::Plan` and `PlanDeltaEvent` to core protocol items.
(`codex-rs/protocol/src/items.rs`, `codex-rs/protocol/src/protocol.rs`)
- Added v2 `ThreadItem::Plan` and `PlanDeltaNotification` with
EXPERIMENTAL markers and note that deltas may not match the final plan
item. (`codex-rs/app-server-protocol/src/protocol/v2.rs`)
- Added plan delta route in app-server protocol common mapping.
(`codex-rs/app-server-protocol/src/protocol/common.rs`)
- Rebuild plan items from persisted `ItemCompleted` events on resume.
(`codex-rs/app-server-protocol/src/protocol/thread_history.rs`)

### App-server
- Forward plan deltas to v2 clients and map core plan items to v2 plan
items. (`codex-rs/app-server/src/bespoke_event_handling.rs`,
`codex-rs/app-server/src/codex_message_processor.rs`)
- Added v2 plan item tests.
(`codex-rs/app-server/tests/suite/v2/plan_item.rs`)

### TUI
- Added a dedicated proposed plan history cell with special background
and padding, and moved “• Proposed Plan” outside the highlighted block.
(`codex-rs/tui/src/history_cell.rs`, `codex-rs/tui/src/style.rs`)
- Only show “Implement this plan?” when a plan item exists.
(`codex-rs/tui/src/chatwidget.rs`,
`codex-rs/tui/src/chatwidget/tests.rs`)

<img width="831" height="847" alt="Screenshot 2026-01-29 at 7 06 24 PM"
src="https://github.com/user-attachments/assets/69794c8c-f96b-4d36-92ef-c1f5c3a8f286"
/>

### Docs / Misc
- Updated protocol docs to mention plan deltas.
(`codex-rs/docs/protocol_v1.md`)
- Minor plumbing updates in exec/debug clients to tolerate plan deltas.
(`codex-rs/debug-client/src/reader.rs`, `codex-rs/exec/...`)

## Tests
- Added core integration tests:
  - Plan mode strips plan from agent messages.
  - Missing `</proposed_plan>` closes at end-of-message.  
  (`codex-rs/core/tests/suite/items.rs`)
- Added unit tests for generic tag parser (prefix buffering, non-tag
lines, auto-close). (`codex-rs/core/src/tagged_block_parser.rs`)
- Existing app-server plan item tests in v2.
(`codex-rs/app-server/tests/suite/v2/plan_item.rs`)

## Notes / Behavior
- Plan output no longer appears in standard assistant text in Plan Mode;
it streams via `PlanDelta` and completes as a `TurnItem::Plan`.
- The final plan item content is authoritative and may diverge from
streamed deltas (documented as experimental).
- Reasoning summaries are not filtered; prompt instructs the model not
to include `<proposed_plan>` outside the final plan message.

## Codex Author
`codex fork 019bec2d-b09d-7450-b292-d7bcdddcdbfb`
2026-01-30 18:59:30 +00:00
pap-openai
1ef5455eb6 Conversation naming (#8991)
Session renaming:
- `/rename my_session`
- `/rename` without arg and passing an argument in `customViewPrompt`
- AppExitInfo shows resume hint using the session name if set instead of
uuid, defaults to uuid if not set
- Names are stored in `CODEX_HOME/sessions.jsonl`

Session resuming:
- codex resume <name> lookup for `CODEX_HOME/sessions.jsonl` first entry
matching the name and resumes the session

---------

Co-authored-by: jif-oai <jif@openai.com>
2026-01-30 10:40:09 +00:00
jif-oai
a270a28a06 feat: add output to /ps (#10154)
<img width="599" height="238" alt="Screenshot 2026-01-29 at 13 24 57"
src="https://github.com/user-attachments/assets/1e9a5af2-f649-476c-b310-ae4938814538"
/>
2026-01-30 09:00:44 +01:00
Josh McKinney
36f2fe8af9 feat(tui): route employee feedback follow-ups to internal link (#10198)
## Problem
OpenAI employees were sent to the public GitHub issue flow after
`/feedback`, which is the wrong follow-up path internally.

## Mental model
After feedback upload completes, we render a follow-up link/message.
That link should be audience-aware but must not change the upload
pipeline itself.

## Non-goals
- Changing how feedback is captured or uploaded
- Changing external user behavior

## Tradeoffs
We detect employees via the authenticated account email suffix
(`@openai.com`). If the email is unavailable (e.g., API key auth), we
default to the external behavior.

## Architecture
- Introduce `FeedbackAudience` and thread it from `App` -> `ChatWidget`
-> `FeedbackNoteView`
- Gate internal messaging/links on `FeedbackAudience::OpenAiEmployee`
- Internal follow-up link is now `http://go/codex-feedback-internal`
- External GitHub URL remains byte-for-byte identical

## Observability
No new telemetry; this only changes rendered follow-up instructions.

## Tests
- `just fmt`
- `cargo test -p codex-tui --lib`
2026-01-30 02:12:46 +00:00
Charley Cunningham
11958221a3 tui: add feature-gated /plan slash command to switch to Plan mode (#10103)
## Summary
Adds a simple `/plan` slash command in the TUI that switches the active
collaboration mode to Plan mode. The command is only available when the
`collaboration_modes` feature is enabled.

## Changes
- Add `plan_mask` helper in `codex-rs/tui/src/collaboration_modes.rs`
- Add `SlashCommand::Plan` metadata in
`codex-rs/tui/src/slash_command.rs`
- Implement and hard-gate `/plan` dispatch in
`codex-rs/tui/src/chatwidget.rs`
- Hide `/plan` when collaboration modes are disabled in
`codex-rs/tui/src/bottom_pane/slash_commands.rs`
- Update command popup tests in
`codex-rs/tui/src/bottom_pane/command_popup.rs`
- Add a focused unit test for `/plan` in
`codex-rs/tui/src/chatwidget/tests.rs`

## Behavior notes
- `/plan` is now a no-op if `Feature::CollaborationModes` is disabled.
- When enabled, `/plan` switches directly to Plan mode without opening
the picker.

## Codex author
`codex resume 019c05da-d7c3-7322-ae2c-3ca38d0ef702`
2026-01-29 16:40:43 -08:00
Colin Young
b79bf69af6 [Codex][CLI] Show model-capacity guidance on 429 (#10118)
###### Problem
Users get generic 429s with no guidance when a model is at capacity.
###### Solution
Detect model-cap headers, surface a clear “try a different model”
message, and keep behavior non‑intrusive (no auto‑switch).
###### Scope
CLI/TUI only; protocol + error mapping updated to carry model‑cap info.
###### Tests
      - just fmt
      - cargo test -p codex-tui
- cargo test -p codex-core --lib
shell_snapshot::tests::try_new_creates_and_deletes_snapshot_file --
--nocapture (ran in isolated env)
      - validate local build with backend
     
<img width="719" height="845" alt="image"
src="https://github.com/user-attachments/assets/1470b33d-0974-4b1f-b8e6-d11f892f4b54"
/>
2026-01-29 14:59:07 -08:00
Matthew Zeng
b9cd089d1f [connectors] Support connectors part 2 - slash command and tui (#9728)
- [x] Support `/apps` slash command to browse the apps in tui.
- [x] Support inserting apps to prompt using `$`.
- [x] Lots of simplification/renaming from connectors to apps.
2026-01-28 19:51:58 -08:00
Dylan Hurd
ce3d764ae1 chore(config) personality as a feature (#10116)
## Summary
Sets up an explicit Feature flag for `/personality`, so users can now
opt in to it via `/experimental`. #10114 also updates the config

## Testing
- [x] Tested locally
2026-01-28 17:58:28 -07:00
Matthew Zeng
3bb8e69dd3 [skills] Auto install MCP dependencies when running skils with dependency specs. (#9982)
Auto install MCP dependencies when running skils with dependency specs.
2026-01-27 19:02:45 -08:00
Charley Cunningham
add648df82 Restore image attachments/text elements when recalling input history (Up/Down) (#9628)
**Summary**
- Up/Down input history now restores image attachments and text elements
for local entries.
- Composer history stores rich local entries (text + text elements +
local image paths) while persistent history remains text-only.
- Added tests to verify history recall rehydrates image placeholders and
attachments in both `tui` and `tui2`.

**Changes**
- `tui/src/bottom_pane/chat_composer_history.rs`: store `HistoryEntry`
(text + elements + image paths) for local history; adapt navigation +
tests.
- `tui2/src/bottom_pane/chat_composer_history.rs`: same as above.
- `tui/src/bottom_pane/chat_composer.rs`: record rich history entries
and restore them on Up/Down; update Ctrl+C history and tests.
- `tui2/src/bottom_pane/chat_composer.rs`: same as above.
2026-01-27 18:39:59 -08:00
iceweasel-oai
c40ad65bd8 remove sandbox globals. (#9797)
Threads sandbox updates through OverrideTurnContext for active turn
Passes computed sandbox type into safety/exec
2026-01-27 11:04:23 -08:00
Charley Cunningham
538e1059a3 TUI footer: right-align context and degrade shortcut summary + mode cleanly (#9944)
## Summary
Refines the bottom footer layout to keep `% context left` right-aligned
while making the left side degrade cleanly

## Behavior with empty textarea
Full width:
<img width="607" height="62" alt="Screenshot 2026-01-26 at 2 59 59 PM"
src="https://github.com/user-attachments/assets/854f33b7-d714-40be-8840-a52eb3bda442"
/>
Less:
<img width="412" height="66" alt="Screenshot 2026-01-26 at 2 59 48 PM"
src="https://github.com/user-attachments/assets/9c501788-c3a2-4b34-8f0b-8ec4395b44fe"
/>
Min width:
<img width="218" height="77" alt="Screenshot 2026-01-26 at 2 59 33 PM"
src="https://github.com/user-attachments/assets/0bed2385-bdbf-4254-8ae4-ab3452243628"
/>

## Behavior with message in textarea and agent running (steer enabled)
Full width:
<img width="753" height="63" alt="Screenshot 2026-01-26 at 4 33 54 PM"
src="https://github.com/user-attachments/assets/1856b352-914a-44cf-813d-1cb50c7f183b"
/>

Less:
<img width="353" height="61" alt="Screenshot 2026-01-26 at 4 30 12 PM"
src="https://github.com/user-attachments/assets/d951c4d5-f3e7-4116-8fe1-6a6c712b3d48"
/>

Less:
<img width="304" height="64" alt="Screenshot 2026-01-26 at 4 30 51 PM"
src="https://github.com/user-attachments/assets/1433e994-5cbc-4e20-a98a-79eee13c8699"
/>

Less:
<img width="235" height="61" alt="Screenshot 2026-01-26 at 4 30 56 PM"
src="https://github.com/user-attachments/assets/e216c3c6-84cd-40fc-ae4d-83bf28947f0e"
/>

Less:
<img width="165" height="59" alt="Screenshot 2026-01-26 at 4 31 08 PM"
src="https://github.com/user-attachments/assets/027de5de-7185-47ce-b1cc-5363ea33d9b1"
/>

## Notes / Edge Cases
- In steer mode while typing, the queue hint no longer replaces the mode
label; it renders as `tab to queue message · {Mode}`.
- Collapse priorities differ by state:
- With the queue hint active, `% context left` is hidden before
shortening or dropping the queue hint.
- In the empty + non-running state, `? for shortcuts` is dropped first,
and `% context left` is only shown if `(shift+tab to
cycle)` can also fit.
- Transient instructional states (`?` overlay, Esc hint, Ctrl+C/D
reminders, and flash/override hints) intentionally suppress the
mode label (and context) to focus the next action.

## Implementation Notes
- Renamed the base footer modes to make the state explicit:
`ComposerEmpty` and `ComposerHasDraft`, and compute the base mode
directly from emptiness.
- Unified collapse behavior in `single_line_footer_layout` for both base
modes, with:
- Queue-hint behavior that prefers keeping the queue hint over context.
- A cycle-hint guard that prevents context from reappearing after
`(shift+tab to cycle)` is dropped.
- Kept rendering responsibilities explicit:
  - `single_line_footer_layout` decides what fits.
  - `render_footer_line` renders a chosen line.
- `render_footer_from_props` renders the canonical mode-to-text mapping.
- Expanded snapshot coverage:
- Added `footer_collapse_snapshots` in `chat_composer.rs` to lock the
distinct collapse states across widths.
- Consolidated the width-aware snapshot helper usage (e.g.,
`snapshot_composer_state_with_width`,
`snapshot_footer_with_mode_indicator`).
2026-01-27 17:43:09 +00:00
Eric Traut
b77bf4d36d Aligned feature stage names with public feature maturity stages (#9929)
We've recently standardized a [feature maturity
model](https://developers.openai.com/codex/feature-maturity) that we're
using in our docs and support forums to communicate expectations to
users. This PR updates the internal stage names and descriptions to
match.

This change involves a simple internal rename and updates to a few
user-visible strings. No functional change.
2026-01-26 11:43:36 -08:00
Dylan Hurd
031bafd1fb feat(tui) /personality (#9718)
## Summary
Adds /personality selector in the TUI, which leverages the new core
interface in #9644

Notes:
- We are doing some of our own state management for model_info loading
here, but not sure if that's ideal. open to opinions on simpler
approach, but would like to avoid blocking on a larger refactor
- Right now, the `/personality` selector just hides when the model
doesn't support it. we can update this behavior down the line

## Testing
- [x] Tested locally
- [x] Added snapshot tests
2026-01-25 21:59:42 -08:00
Ahmed Ibrahim
cb2bbe5cba Adjust modes masks (#9868) 2026-01-25 12:44:17 -08:00
Ahmed Ibrahim
58450ba2a1 Use collaboration mode masks without mutating base settings (#9806)
Keep an unmasked base collaboration mode and apply the active mask on
demand. Simplify the TUI mask helpers and update tests/docs to match the
mask contract.
2026-01-25 07:35:31 +00:00
jif-oai
83775f4df1 feat: ephemeral threads (#9765)
Add ephemeral threads capabilities. Only exposed through the
`app-server` v2

The idea is to disable the rollout recorder for those threads.
2026-01-24 14:57:40 +00:00
Ahmed Ibrahim
b3127e2eeb Have a coding mode and only show coding and plan (#9802) 2026-01-23 19:28:49 -08:00
Ahmed Ibrahim
69cfc73dc6 change collaboration mode to struct (#9793)
Shouldn't cause behavioral change
2026-01-23 17:00:23 -08:00
jif-oai
f30f39b28b feat: tui beta for collab (#9690)
https://github.com/user-attachments/assets/1ca07e7a-3d82-40da-a5b0-8ab2eef0bb69
2026-01-23 13:57:59 +01:00
charley-oai
0e79d239ed TUI: prompt to implement plan and switch to Execute (#9712)
## Summary
- Replace the plan‑implementation prompt with a standard selection
popup.
- “Yes” submits a user turn in Execute via a dedicated app event to
preserve normal transcript behavior.
- “No” simply dismisses the popup.

<img width="977" height="433" alt="Screenshot 2026-01-22 at 2 00 54 PM"
src="https://github.com/user-attachments/assets/91fad06f-7b7a-4cd8-9051-f28a19b750b2"
/>

## Changes
- Add a plan‑implementation popup using `SelectionViewParams`.
- Add `SubmitUserMessageWithMode` so “Yes” routes through
`submit_user_message` (ensures user history + separator state).
- Track `saw_plan_update_this_turn` so the prompt appears even when only
`update_plan` is emitted.
- Suppress the plan popup on replayed turns, when messages are queued,
or when a rate‑limit prompt is pending.
- Add `execute_mode` helper for collaboration modes.
- Add tests for replay/queued/rate‑limit guards and plan update without
final message.
- Add snapshots for both the default and “No”‑selected popup states.
2026-01-23 00:25:50 +00:00
Dylan Hurd
8b3521ee77 feat(core) update Personality on turn (#9644)
## Summary
Support updating Personality mid-Thread via UserTurn/OverwriteTurn. This
is explicitly unused by the clients so far, to simplify PRs - app-server
and tui implementations will be follow-ups.

## Testing
- [x] added integration tests
2026-01-22 12:04:23 -08:00
Dylan Hurd
038b78c915 feat(tui) /permissions flow (#9561)
## Summary
Adds the `/permissions` command, with a (usually) shorter set of
permissions. `/approvals` still exists, for backwards compatibility.

<img width="863" height="309" alt="Screenshot 2026-01-20 at 4 12 51 PM"
src="https://github.com/user-attachments/assets/c49b5ba5-bc47-46dd-9067-e1a5670328fe"
/>


## Testing
- [x] updated unit tests
- [x] Tested locally
2026-01-21 21:38:46 -08:00
xl-openai
577ba3a4ca Add UI for skill enable/disable. (#9627)
"/skill" will now allow you to enable/disable skills:
<img width="658" height="199" alt="image"
src="https://github.com/user-attachments/assets/bf8994c8-d6c1-462f-8bbb-f1ee9241caa4"
/>
2026-01-21 18:21:12 -08:00
Dylan Hurd
f1240ff4fe fix(tui) turn timing incremental (#9599)
## Summary
When we send multiple assistant messages, reset the timer so "Worked for
2m 36s" is the time since the last time we showed the message, rather
than an ever-increasing number.

We could instead change the copy so it's more clearly a running counter.

## Testing
- [x] ran locally

<img width="903" height="732" alt="Screenshot 2026-01-21 at 1 42 51 AM"
src="https://github.com/user-attachments/assets/bb4d827b-3a0e-48ba-bd6a-d8cd65d8e892"
/>
2026-01-21 15:59:56 -08:00
iceweasel-oai
f81dd128a2 define/emit some metrics for windows sandbox setup (#9573)
This should give us visibility into how users are using the elevated
sandbox nux flow, and the timing of the elevated setup.
2026-01-21 11:07:26 -08:00
jif-oai
338f2d634b nit: ui on interruption (#9606) 2026-01-21 14:09:15 +00:00
jif-oai
13358fa131 fix: nit tui on terminal interactions (#9602) 2026-01-21 11:30:34 +00:00
Ahmed Ibrahim
5f55ed666b Add request-user-input overlay (#9585)
- Add request-user-input overlay and routing in the TUI
2026-01-21 00:19:35 -08:00
Ahmed Ibrahim
de4980d2ac Enable remote models (#9554) 2026-01-20 23:17:22 +00:00