Commit Graph

3287 Commits

  • TUI: Render request_user_input results in history and simplify interrupt handling (#10064)
    ## Summary
    This PR improves the TUI experience for `request_user_input` by
    rendering submitted question/answer sets directly in conversation
    history with clear, structured formatting.
    
    It also intentionally simplifies interrupt behavior for now: on `Esc` /
    `Ctrl+C`, the questions overlay interrupts the turn without attempting
    to submit partial answers.
    
    <img width="1344" height="573" alt="Screenshot 2026-02-02 at 4 51 40 PM"
    src="https://github.com/user-attachments/assets/ff752131-7060-44c1-9ded-af061969a533"
    />
    
    ## Scope
    - TUI-only changes.
    - No core/protocol/app-server behavior changes in this PR.
    - Resume reconstruction of interrupted question sets is out of scope for
    this PR.
    
    ## What Changed
    - Added a new history cell: `RequestUserInputResultCell` in
    `codex-rs/tui/src/history_cell.rs`.
    - On normal `request_user_input` submission, TUI now inserts that
    history cell immediately after sending `Op::UserInputAnswer`.
    - Rendering includes a `Questions` header with `answered/total` count.
    - Rendering shows each question as a bullet item.
    - Rendering styles submitted answer lines in cyan.
    - Rendering styles notes (for option questions) as `note:` lines in
    cyan.
    - Rendering styles freeform text (for no-option questions) as `answer:`
    lines in cyan.
    - Rendering dims only the `(unanswered)` suffix.
    - Rendering can include an interrupted suffix and summary text when the
    cell is marked interrupted.
    - Rendering redacts secret questions as `••••••` instead of showing raw
    values.
    - Added `wrap_with_prefix(...)` in `history_cell.rs` for wrapped
    prefixed lines.
    - Added `split_request_user_input_answer(...)` in `history_cell.rs` for
    decoding `"user_note: ..."` entries.
    
    ## Interrupt Behavior (Intentional for this PR)
    - `Esc` / `Ctrl+C` in the questions overlay now performs `Op::Interrupt`
    and exits the overlay.
    - It does **not** submit partial/committed answers on interrupt.
    - Added TODO comments in `request_user_input` overlay interrupt paths
    indicating where interrupted partial result emission should be
    reintroduced once core support is finalized.
    - Queued `request_user_input` overlays are discarded on interrupt in the
    current behavior.
    
    ## Tests Updated
    - Updated/added overlay tests in
    `codex-rs/tui/src/bottom_pane/request_user_input/mod.rs` to reflect
    interrupt-only behavior.
    - Added helper assertion for interrupt-only event expectation.
    - Existing submission-path tests now validate history insertion behavior
    and expected answer maps.
    
    ## Behavior Notes
    - Completed question flows now produce a readable `Questions` block in
    transcript history.
    - Interrupted flows currently do not persist partial answers to
    model-visible tool output.
    
    ## Follow-ups
    - Reintroduce partial-answer-on-interrupt semantics once core can
    persist/sequence interrupted `request_user_input` outputs safely.
    - Optionally add replay/resume rendering for interrupted question sets
    as a separate PR.
    
    ## Codex author
    `codex fork 019bfb8d-2a65-7313-9be2-ea7100d19a61`
  • 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.
  • Add codex app macOS launcher (#10418)
    - Add `codex app <path>` to launch the Codex Desktop app.
    - On macOS, auto-downloads the DMG if missing; non-macOS prints a link
    to chatgpt.com/codex.
  • make codex better at git (#10145)
    adds basic git context to the session prefix so the model can anchor git
    actions and be a bit more version-aware. structured it in a
    multiroot-friendly shape even though we only have one root today
  • feat: Read personal skills from .agents/skills (#10437)
    - Issue: https://github.com/agentskills/agentskills/issues/15
    - Follow-up to https://github.com/openai/codex/pull/10317 (for team/repo
    skills)
    - This change now also loads personal/user skills from
    `$HOME/.agents/skills` (or `~/.agents/skills`) in addition to loading
    from `.agents/skills` inside of git repos.
    - The location of `.system` skills remains unchanged.
    - Keeping backwards compatibility with `~/.codex/skills` for now until
    we fully deprecate.
    
    With skills in both personal folders:
    <img width="831" height="421" alt="image"
    src="https://github.com/user-attachments/assets/ad8ac918-bfe6-4a2d-8a8e-d608c9d3d701"
    />
    
    We load from both places:
    <img width="607" height="236" alt="image"
    src="https://github.com/user-attachments/assets/480f4db0-ae64-4dc1-bdf5-c5de98c16f5c"
    />
  • [feat] persist thread_dynamic_tools in db (#10252)
    Persist thread_dynamic_tools in sqlite and read first from it. Fall back
    to rollout files if it's not found. Persist dynamic tools to both sqlite
    and rollout files.
    
    Saw that new sessions get populated to db correctly & old sessions get
    backfilled correctly at startup:
    ```
    celia@com-92114 codex-rs % sqlite3 ~/.codex/state.sqlite \      "select thread_id, position,name,description,input_schema from thread_dynamic_tools;"
    019c0cad-ec0d-74b2-a787-e8b33a349117|0|geo_lookup|lookup a city|{"properties":{"city":{"type":"string"}},"required":["city"],"type":"object"}
    ....
    019c10ca-aa4b-7620-ae40-c0919fbd7ea7|0|geo_lookup|lookup a city|{"properties":{"city":{"type":"string"}},"required":["city"],"type":"object"}
    ```
  • chore(tui) /personalities tip (#10377)
    ## Summary
    We have /personality now.
    
    ## Testing
    - [x] tested locally
  • emit a separate metric when the user cancels UAT during elevated setup (#10399)
    Currently this shows up as elevated setup failure, which isn't quite
    accurate.
  • fix: unsafe auto-approval of git commands (#10258)
    fixes https://github.com/openai/codex/issues/10160 and some more.
    
    ## Description
    
    Hardens Git command safety to prevent approval bypasses for destructive
    or write-capable invocations (branch delete, risky push forms,
    output/config-override flags), so these commands no longer auto-run as
    “safe.”
    
    - `git branch -d` variants (especially in worktrees / with global
    options like -C / -c)
    - `git show|diff|log --output` ... style file-write flags
    - risky Git config override flags (-c, --config-env) that can trigger
    external execution
    - dangerous push forms that weren’t fully caught (`--force*`,
    `--delete`, `+refspec`, `:refspec`)
    - grouped short-flag delete forms (e.g. stacked branch flags containing
    `d/D`)
    
    will fast follow with a common git policy to bring windows to parity.
    
    ---------
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • feat: add --experimental to generate-ts (#10402)
    Adding a `--experimental` flag to the `generate-ts` fct in the
    app-sever.
    
    It can be called through one of those 2 command
    ```
    just write-app-server-schema --experimental
    codex app-server generate-ts --experimental
    ```
  • 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`
  • feat: add MCP protocol types and rmcp adapters (#10356)
    Currently, types from our custom `mcp-types` crate are part of some of
    our APIs:
    
    
    https://github.com/openai/codex/blob/03fcd12e77fedf4fa327af27e2e476e1ebc5f651/codex-rs/app-server-protocol/src/protocol/v2.rs#L43-L46
    
    To eliminate this crate in #10349 by switching to `rmcp`, we need our
    own wrappers for the `rmcp` types that we can use in our API, which is
    what this PR does.
    
    Note this PR introduces the new API types, but we do not make use of
    them until #10349.
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/10356).
    * #10357
    * #10349
    * __->__ #10356
  • feat: experimental flags (#10231)
    ## Problem being solved
    - We need a single, reliable way to mark app-server API surface as
    experimental so that:
      1. the runtime can reject experimental usage unless the client opts in
    2. generated TS/JSON schemas can exclude experimental methods/fields for
    stable clients.
    
    Right now that’s easy to drift or miss when done ad-hoc.
    
    ## How to declare experimental methods and fields
    - **Experimental method**: add `#[experimental("method/name")]` to the
    `ClientRequest` variant in `client_request_definitions!`.
    - **Experimental field**: on the params struct, derive `ExperimentalApi`
    and annotate the field with `#[experimental("method/name.field")]` + set
    `inspect_params: true` for the method variant so
    `ClientRequest::experimental_reason()` inspects params for experimental
    fields.
    
    ## How the macro solves it
    - The new derive macro lives in
    `codex-rs/codex-experimental-api-macros/src/lib.rs` and is used via
    `#[derive(ExperimentalApi)]` plus `#[experimental("reason")]`
    attributes.
    - **Structs**:
    - Generates `ExperimentalApi::experimental_reason(&self)` that checks
    only annotated fields.
      - The “presence” check is type-aware:
        - `Option<T>`: `is_some_and(...)` recursively checks inner.
        - `Vec`/`HashMap`/`BTreeMap`: must be non-empty.
        - `bool`: must be `true`.
        - Other types: considered present (returns `true`).
    - Registers each experimental field in an `inventory` with `(type_name,
    serialized field name, reason)` and exposes `EXPERIMENTAL_FIELDS` for
    that type. Field names are converted from `snake_case` to `camelCase`
    for schema/TS filtering.
    - **Enums**:
    - Generates an exhaustive `match` returning `Some(reason)` for annotated
    variants and `None` otherwise (no wildcard arm).
    - **Wiring**:
    - Runtime gating uses `ExperimentalApi::experimental_reason()` in
    `codex-rs/app-server/src/message_processor.rs` to reject requests unless
    `InitializeParams.capabilities.experimental_api == true`.
    - Schema/TS export filters use the inventory list and
    `EXPERIMENTAL_CLIENT_METHODS` from `client_request_definitions!` to
    strip experimental methods/fields when `experimental_api` is false.
  • Session picker shows thread_name if set (#10340)
    - shows names of threads in the ResumePicker used by `/resume` and
    `codex resume` if set, default to preview (previous behaviour) if none
    - adds a `find_thread_names_by_ids` that maps names to IDs in
    `codex-rs/core/src/rollout/session_index.rs`. It reads sequentially in
    normal (instead of reverse order in `codex resume <name>`) the index
    mapping file. This function is called from a list of session (default
    page is 25, pages loaded depends of height of terminal), for which most
    of them will always have at least one session unnamed and require the
    whole file to be read therefore. Could be better and sqlite integration
    will make this better
    - those reads won't be needed when leveraging sqlite
     
    
    Opened questions:
    - We could rename the TUI "Conversation" column to "Name" or "Thread"
    that would feel more accurate. Could be a fast-follow if we implement
    auto-naming as it'll always be a name instead?
  • feat: vendor app-server protocol schema fixtures (#10371)
    Similar to what @sayan-oai did in openai/codex#8956 for
    `config.schema.json`, this PR updates the repo so that it includes the
    output of `codex app-server generate-json-schema` and `codex app-server
    generate-ts` and adds a test to verify it is in sync with the current
    code.
    
    Motivation:
    - This makes any schema changes introduced by a PR transparent during
    code review.
    - In particular, this should help us catch PRs that would introduce a
    non-backwards-compatible change to the app schema (eventually, this
    should also be enforced by tooling).
    - Once https://github.com/openai/codex/pull/10231 is in to formalize the
    notion of "experimental" fields, we can work on ensuring the
    non-experimental bits are backwards-compatible.
    
    `codex-rs/app-server-protocol/tests/schema_fixtures.rs` was added as the
    test and `just write-app-server-schema` can be use to generate the
    vendored schema files.
    
    Incidentally, when I run:
    
    ```
    rg _ codex-rs/app-server-protocol/schema/typescript/v2
    ```
    
    I see a number of `snake_case` names that should be `camelCase`.
  • fix(personality) prompt patch (#10375)
    ## Summary
    We had 2 typos in #10373
    
    ## Testing
    - [x] unit tests pass
  • chore(core) gpt-5.2-codex personality template (#10373)
    ## Summary
    Consolidate prompts
    
    ## Testing
    - [x] Existing tests pass
  • fix(core) Deduplicate prefix_rules before appending (#10309)
    ## Summary
    We ideally shouldn't make it to this point in the first place, but if we
    do try to append a rule that already exists, we shouldn't append the
    same rule twice.
    
    ## Testing
    - [x] Added unit test for this case
  • fix(rules) Limit rules listed in conversation (#10351)
    ## Summary
    We should probably warn users that they have a million rules, and help
    clean them up. But for now, we should handle this unbounded case.
    
    Limit rules listed in conversations, with shortest / broadest rules
    first.
    
    ## Testing
    - [x] Updated unit tests
  • fix: System skills marker includes nested folders recursively (#10350)
    Updated system skills bundled with Codex were not correctly replacing
    the user's skills in their .system folder.
    
    - Fix `.codex-system-skills.marker` not updating by hashing embedded
    system skills recursively (nested dirs + file contents), so updates
    trigger a reinstall.
    - Added a build Cargo hook to rerun if there are changes in
    `src/skills/assets/samples/*`, ensuring embedded skill updates rebuild
    correctly under caching.
    - Add a small unit test to ensure nested entries are included in the
    fingerprint.
  • Bump thread updated_at on unarchive to refresh sidebar ordering (#10280)
    ## Summary
    - Touch restored rollout files on `thread/unarchive` so `updatedAt`
    reflects the unarchive time.
    - Add a regression test to ensure unarchiving bumps `updated_at` from an
    old mtime.
    
    ## Notes
    This fixes the UX issue where unarchived old threads don’t reappear near
    the top of recent threads.
  • Improve plan mode interaction rules (#10329)
    ## Summary
    - Replace the “Hard interaction rule” with a clearer “Response
    constraints” section that enumerates the allowed exceptions for Plan
    Mode replies.
    - Remove the stray Phase 1 exception line about simple questions.
    - Update plan content requirements to ask for a brief summary section
    and generalize API/type wording.
  • fix(config) config schema newline (#10323)
    ## Summary
    Looks like we may have introduced a formatting issue in recent PRs.
    
    ## Testing
    - [x] ran `just write-config-schema`
  • chore(features) Personality => Stable (#10310)
    ## Summary
    Bump `/personality` to stable
    
    ## Testing
     - [x] unit tests pass
  • chore(config) Rename config setting to personality (#10314)
    ## Summary
    Let's make the setting name consistent with the SlashCommand!
    
    ## Testing
    - [x] Updated tests
  • Add websocket telemetry metrics and labels (#10316)
    Summary
    - expose websocket telemetry hooks through the responses client so
    request durations and event processing can be reported
    - record websocket request/event metrics and emit runtime telemetry
    events that the history UI now surfaces
    - improve tests to cover websocket telemetry reporting and guard runtime
    summary updates
    
    
    <img width="824" height="79" alt="Screenshot 2026-01-31 at 5 28 12 PM"
    src="https://github.com/user-attachments/assets/ea9a7965-d8b4-4e3c-a984-ef4fdc44c81d"
    />
  • Make skills prompt explicit about relative-path lookup (#10282)
    Fix cases where the model tries to locate skill scripts from the cwd and
    fails.
  • feat: Support loading skills from .agents/skills (#10317)
    This PR adds support for loading
    [skills](https://developers.openai.com/codex/skills) from
    `.agents/skills/`.
    - Issue: https://github.com/agentskills/agentskills/issues/15
    - Motivation: When skills live on the filesystem, sharing them across
    agents is awkward and often ends up requiring symlinks/duplication. A
    single location under `.agents/` makes it easier to share skills.
    - Loading from `.codex/skills/` will remain but will be deprecated soon.
    The change only applies to the [REPO
    scope](https://developers.openai.com/codex/skills#where-to-save-skills).
    - Documentation will be updated before this change is live.
    
    Testing with skills in two locations of this repo:
    <img width="960" height="152" alt="image"
    src="https://github.com/user-attachments/assets/28975ff9-7363-46dd-ad40-f4c7bfdb8234"
    />
    
    When starting Codex with CWD in `$repo_root` (should only pick up at
    root):
    <img width="513" height="143" alt="image"
    src="https://github.com/user-attachments/assets/389e1ea7-020c-481e-bda0-ce58562db59f"
    />
    
    When starting Codex with CWD in `$repo_root/codex-rs` (should pick up at
    cwd and crawl up to root):
    <img width="552" height="177" alt="image"
    src="https://github.com/user-attachments/assets/a5beb8de-11b4-45ed-8660-80707c77006a"
    />
  • enable plan mode (#10313)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • feat(core,tui,app-server) personality migration (#10307)
    ## Summary
    Keep existing users on Pragmatic, to preserve behavior while new users
    default to Friendly
    
    ## Testing
    - [x] Tested locally
    - [x] add integration tests
  • chore(core) Default to friendly personality (#10305)
    ## Summary
    Update default personality to friendly
    
    ## Testing
    - [x] Unit tests pass
  • plan mode prompt (#10308)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • chore(app-server) add personality update test (#10306)
    ## Summary
    Add some additional validation to ensure app-server handles Personality
    changes
    
    ## Testing
    - [x] These are tests
  • Fix npm README image link (#10303)
    ### Motivation
    - The image referenced in the package README was 404ing on the npm
    package page because it used a relative file path that doesn't resolve
    on npm, so the splash image needs a GitHub-hosted URL to render
    correctly.
    
    ### Description
    - Update `README.md` to replace the relative image path
    `./.github/codex-cli-splash.png` with the GitHub-hosted URL
    `https://github.com/openai/codex/blob/main/.github/codex-cli-splash.png`.
    
    ### Testing
    - No automated tests were run because this is a docs-only change and
    does not affect code or test behavior.
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_697e58dbce34832d87c7847779e8f4a5)
  • chore(features) remove Experimental tag from UTF8 (#10296)
    ## Summary
    This has been default on for some time, it should now be the default.
    
    ## Testing
    - [x] Existing tests pass
  • fix(nix): update flake for newer Rust toolchain requirements (#10302)
    ## Summary
    
    - Add rust-overlay input to provide newer Rust versions (rama crates
    require rustc 1.91.0+)
    - Add devShells output with complete development environment
    - Add missing git dependency hashes to codex-rs/default.nix
    
    ## Changes
    
    **flake.nix:**
    - Added `rust-overlay` input to get newer Rust toolchains
    - Updated `packages` output to use `rust-bin.stable.latest.minimal` for
    builds
    - Added `devShells` output with:
      - Rust with `rust-src` and `rust-analyzer` extensions for IDE support
    - Required build dependencies: `pkg-config`, `openssl`, `cmake`,
    `libclang`
      - Environment variables: `PKG_CONFIG_PATH`, `LIBCLANG_PATH`
    
    **codex-rs/default.nix:**
    - Added missing `outputHashes` for git dependencies:
      - `nucleo-0.5.0`, `nucleo-matcher-0.3.1`
      - `runfiles-0.1.0`
      - `tokio-tungstenite-0.28.0`, `tungstenite-0.28.0`
    
    ## Test Plan
    
    - [x] `nix develop` enters shell successfully
    - [x] `nix develop -c rustc --version` shows 1.93.0
    - [x] `nix develop -c cargo build` completes successfully
  • display promo message in usage error (#10285)
    If a promo message is attached to a rate limit response, then display it
    in the error message.