Commit Graph

398 Commits

  • Use a unified shell tell to not break cache (#3814)
    Currently, we change the tool description according to the sandbox
    policy and approval policy. This breaks the cache when the user hits
    `/approvals`. This PR does the following:
    - Always use the shell with escalation parameter:
    - removes `create_shell_tool_for_sandbox` and always uses unified tool
    via `create_shell_tool`
    - Reject the func call when the model uses escalation parameter when it
    cannot.
  • fix: update try_parse_word_only_commands_sequence() to return commands in order (#3881)
    Incidentally, we had a test for this in
    `accepts_multiple_commands_with_allowed_operators()`, but it was
    verifying the bad behavior. Oops!
  • fix: ensure cwd for conversation and sandbox are separate concerns (#3874)
    Previous to this PR, both of these functions take a single `cwd`:
    
    
    https://github.com/openai/codex/blob/71038381aa0f51aa62e1a2bcc7cbf26a05b141f3/codex-rs/core/src/seatbelt.rs#L19-L25
    
    
    https://github.com/openai/codex/blob/71038381aa0f51aa62e1a2bcc7cbf26a05b141f3/codex-rs/core/src/landlock.rs#L16-L23
    
    whereas `cwd` and `sandbox_cwd` should be set independently (fixed in
    this PR).
    
    Added `sandbox_distinguishes_command_and_policy_cwds()` to
    `codex-rs/exec/tests/suite/sandbox.rs` to verify this.
  • feat: /review (#3774)
    Adds `/review` action in TUI
    
    <img width="637" height="370" alt="Screenshot 2025-09-17 at 12 41 19 AM"
    src="https://github.com/user-attachments/assets/b1979a6e-844a-4b97-ab20-107c185aec1d"
    />
  • chore: use tokio mutex and async function to prevent blocking a worker (#3850)
    ### Why Use `tokio::sync::Mutex`
    
    `std::sync::Mutex` are not _async-aware_. As a result, they will block
    the entire thread instead of just yielding the task. Furthermore they
    can be poisoned which is not the case of `tokio` Mutex.
    This allows the Tokio runtime to continue running other tasks while
    waiting for the lock, preventing deadlocks and performance bottlenecks.
    
    In general, this is preferred in async environment
  • fix: some nit Rust reference issues (#3849)
    Fix some small references issue. No behavioural change. Just making the
    code cleaner
  • Make ESC button work when auto-compaction (#3857)
    Only emit a task finished when the compaction comes from a `/compact`
  • bug: Ignore tests for now (#3777)
    Ignore flaky / long tests for now
  • Add dev message upon review out (#3758)
    Proposal: We want to record a dev message like so:
    
    ```
    {
          "type": "message",
          "role": "user",
          "content": [
            {
              "type": "input_text",
              "text": "<user_action>
      <context>User initiated a review task. Here's the full review output from reviewer model. User may select one or more comments to resolve.</context>
      <action>review</action>
      <results>
      {findings_str}
      </results>
    </user_action>"
            }
          ]
        },
    ```
    
    Without showing in the chat transcript.
    
    Rough idea, but it fixes issue where the user finishes a review thread,
    and asks the parent "fix the rest of the review issues" thinking that
    the parent knows about it.
    
    ### Question: Why not a tool call?
    
    Because the agent didn't make the call, it was a human. + we haven't
    implemented sub-agents yet, and we'll need to think about the way we
    represent these human-led tool calls for the agent.
  • Review mode core updates (#3701)
    1. Adds the environment prompt (including cwd) to review thread
    2. Prepends the review prompt as a user message (temporary fix so the
    instructions are not replaced on backend)
    3. Sets reasoning to low
    4. Sets default review model to `gpt-5-codex`
  • fix: Record EnvironmentContext in SendUserTurn (#3678)
    ## Summary
    SendUserTurn has not been correctly handling updates to policies. While
    the tui protocol handles this in `Op::OverrideTurnContext`, the
    SendUserTurn should be appending `EnvironmentContext` messages when the
    sandbox settings change. MCP client behavior should match the cli
    behavior, so we update `SendUserTurn` message to match.
    
    ## Testing
    - [x] Added prompt caching tests
  • Persist search items (#3745)
    Let's record the search items because they are part of the history.
  • fix: read-only escalations (#3673)
    ## Summary
    Splitting out this smaller fix from #2694 - fixes the sandbox
    permissions so Chat / read-only mode tool definition matches
    expectations
    
    ## Testing 
    - [x] Tested locally
    
    <img width="1271" height="629" alt="Screenshot 2025-09-15 at 2 51 19 PM"
    src="https://github.com/user-attachments/assets/fcb247e4-30b6-4199-80d7-a2876d79ad7d"
    />
  • notifications on approvals and turn end (#3329)
    uses OSC 9 to notify when a turn ends or approval is required. won't
    work in vs code or terminal.app but iterm2/kitty/wezterm supports it :)
  • fix: race condition unified exec (#3644)
    Fix race condition without storing an rx in the session
  • feat: tighten preset filter, tame storage load logs, enable rollout prompt by default (#3628)
    Summary
    - common: use exact equality for Swiftfox exclusion to avoid hiding
    future slugs that merely contain the substring
    - core: treat missing internal_storage.json as expected (debug), warn
    only on real IO/parse errors
    - tui: drop DEBUG_HIGH gate; always consider showing rollout prompt, but
    suppress under ApiKey auth mode
  • Show abort in the resume (#3629)
    Show abort error when resuming a session
  • initial mcp add interface (#3543)
    Adds `codex mcp add`, `codex mcp list`, `codex mcp remove`. Currently writes to global config.
  • Revert "refactor transcript view to handle HistoryCells" (#3614)
    Reverts openai/codex#3538
    It panics on forking first message. It also calculates the index in a
    wrong way.
  • When logging in using ChatGPT, make sure to overwrite API key (#3611)
    When logging in using ChatGPT using the `codex login` command, a
    successful login should write a new `auth.json` file with the ChatGPT
    token information. The old code attempted to retain the API key and
    merge the token information into the existing `auth.json` file. With the
    new simplified login mechanism, `auth.json` should have auth information
    for only ChatGPT or API Key, not both.
    
    The `codex login --api-key <key>` code path was already doing the right
    thing here, but the `codex login` command was incorrect. This PR fixes
    the problem and adds test cases for both commands.
  • fix: model family and apply_patch consistency (#3603)
    ## Summary
    Resolves a merge conflict between #3597 and #3560, and adds tests to
    double check our apply_patch configuration.
    
    ## Testing
    - [x] Added unit tests
    
    ---------
    
    Co-authored-by: dedrisian-oai <dedrisian@openai.com>
  • fix(core): flaky test completed_commands_do_not_persist_sessions (#3596)
    Fix flaky test:
    ```
            FAIL [   2.641s] codex-core unified_exec::tests::completed_commands_do_not_persist_sessions
      stdout ───
    
        running 1 test
        test unified_exec::tests::completed_commands_do_not_persist_sessions ... FAILED
    
        failures:
    
        failures:
            unified_exec::tests::completed_commands_do_not_persist_sessions
    
        test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 235 filtered out; finished in 2.63s
        
      stderr ───
    
        thread 'unified_exec::tests::completed_commands_do_not_persist_sessions' panicked at core/src/unified_exec/mod.rs:582:9:
        assertion failed: result.output.contains("codex")
    ```
  • Only one branch for swiftfox (#3601)
    Make each model family have a single branch.
  • enable-resume (#3537)
    Adding the ability to resume conversations.
    we have one verb `resume`. 
    
    Behavior:
    
    `tui`:
    `codex resume`: opens session picker
    `codex resume --last`: continue last message
    `codex resume <session id>`: continue conversation with `session id`
    
    `exec`:
    `codex resume --last`: continue last conversation
    `codex resume <session id>`: continue conversation with `session id`
    
    Implementation:
    - I added a function to find the path in `~/.codex/sessions/` with a
    `UUID`. This is helpful in resuming with session id.
    - Added the above mentioned flags
    - Added lots of testing
  • Fix swiftfox model selector (#3598)
    The model shouldn't be saved with a suffix. The effort is a separate
    field.
  • Add per-model-family prompts (#3597)
    Allows more flexibility in defining prompts.
  • Include command output when sending timeout to model (#3576)
    Being able to see the output helps the model decide how to handle the
    timeout.
  • Handle resuming/forking after compact (#3533)
    We need to construct the history different when compact happens. For
    this, we need to just consider the history after compact and convert
    compact to a response item.
    
    This needs to change and use `build_compact_history` when this #3446 is
    merged.
  • refactor transcript view to handle HistoryCells (#3538)
    No (intended) functional change.
    
    This refactors the transcript view to hold a list of HistoryCells
    instead of a list of Lines. This simplifies and makes much of the logic
    more robust, as well as laying the groundwork for future changes, e.g.
    live-updating history cells in the transcript.
    
    Similar to #2879 in goal. Fixes #2755.
  • w
  • Always request encrypted cot (#3539)
    Otherwise future requests will fail with 500
  • Review Mode (Core) (#3401)
    ## 📝 Review Mode -- Core
    
    This PR introduces the Core implementation for Review mode:
    
    - New op `Op::Review { prompt: String }:` spawns a child review task
    with isolated context, a review‑specific system prompt, and a
    `Config.review_model`.
    - `EnteredReviewMode`: emitted when the child review session starts.
    Every event from this point onwards reflects the review session.
    - `ExitedReviewMode(Option<ReviewOutputEvent>)`: emitted when the review
    finishes or is interrupted, with optional structured findings:
    
    ```json
    {
      "findings": [
        {
          "title": "<≤ 80 chars, imperative>",
          "body": "<valid Markdown explaining *why* this is a problem; cite files/lines/functions>",
          "confidence_score": <float 0.0-1.0>,
          "priority": <int 0-3>,
          "code_location": {
            "absolute_file_path": "<file path>",
            "line_range": {"start": <int>, "end": <int>}
          }
        }
      ],
      "overall_correctness": "patch is correct" | "patch is incorrect",
      "overall_explanation": "<1-3 sentence explanation justifying the overall_correctness verdict>",
      "overall_confidence_score": <float 0.0-1.0>
    }
    ```
    
    ## Questions
    
    ### Why separate out its own message history?
    
    We want the review thread to match the training of our review models as
    much as possible -- that means using a custom prompt, removing user
    instructions, and starting a clean chat history.
    
    We also want to make sure the review thread doesn't leak into the parent
    thread.
    
    ### Why do this as a mode, vs. sub-agents?
    
    1. We want review to be a synchronous task, so it's fine for now to do a
    bespoke implementation.
    2. We're still unclear about the final structure for sub-agents. We'd
    prefer to land this quickly and then refactor into sub-agents without
    rushing that implementation.
  • fix: NIT None reasoning effort (#3536)
    Fix the reasoning effort not being set to None in the UI
  • core: expand default sandbox (#3483)
    this adds some more capabilities to the default sandbox which I feel are
    safe. Most are in the
    [renderer.sb](https://source.chromium.org/chromium/chromium/src/+/main:sandbox/policy/mac/renderer.sb)
    sandbox for chrome renderers, which i feel is fair game for codex
    commands.
    
    Specific changes:
    
    1. Allow processes in the sandbox to send signals to any other process
    in the same sandbox (e.g. child processes or daemonized processes),
    instead of just themselves.
    2. Allow user-preference-read
    3. Allow process-info* to anything in the same sandbox. This is a bit
    wider than Chromium allows, but it seems OK to me to allow anything in
    the sandbox to get details about other processes in the same sandbox.
    Bazel uses these to e.g. wait for another process to exit.
    4. Allow all CPU feature detection, this seems harmless to me. It's
    wider than Chromium, but Chromium is concerned about fingerprinting, and
    tightly controls what CPU features they actually care about, and we
    don't have either that restriction or that advantage.
    5. Allow new sysctl-reads:
       ```
         (sysctl-name "vm.loadavg")
         (sysctl-name-prefix "kern.proc.pgrp.")
         (sysctl-name-prefix "kern.proc.pid.")
         (sysctl-name-prefix "net.routetable.")
       ```
    bazel needs these for waiting on child processes and for communicating
    with its local build server, i believe. I wonder if we should just allow
    all (sysctl-read), as reading any arbitrary info about the system seems
    fine to me.
    6. Allow iokit-open on RootDomainUserClient. This has to do with power
    management I believe, and Chromium allows renderers to do this, so okay.
    Bazel needs it to boot successfully, possibly for sleep/wake callbacks?
    7. Mach lookup to `com.apple.system.opendirectoryd.libinfo`, which has
    to do with user data, and which Chrome allows.
    8. Mach lookup to `com.apple.PowerManagement.control`. Chromium allows
    its GPU process to do this, but not its renderers. Bazel needs this to
    boot, probably relatedly to sleep/wake stuff.
  • Add Azure Responses API workaround (#3528)
    Azure Responses API doesn't work well with store:false and response
    items.
    
    If store = false and id is sent an error is thrown that ID is not found
    If store = false and id is not sent an error is thrown that ID is
    required
    
    Add detection for Azure urls and add a workaround to preserve reasoning
    item IDs and send store:true
  • feat: context compaction (#3446)
    ## Compact feature:
    1. Stops the model when the context window become too large
    2. Add a user turn, asking for the model to summarize
    3. Build a bridge that contains all the previous user message + the
    summary. Rendered from a template
    4. Start sampling again from a clean conversation with only that bridge
  • feat: reasoning effort as optional (#3527)
    Allow the reasoning effort to be optional
  • feat: change the behavior of SetDefaultModel RPC so None clears the value. (#3529)
    It turns out that we want slightly different behavior for the
    `SetDefaultModel` RPC because some models do not work with reasoning
    (like GPT-4.1), so we should be able to explicitly clear this value.
    
    Verified in `codex-rs/mcp-server/tests/suite/set_default_model.rs`.
  • standardize shell description (#3514)
    ## Summary
    Standardizes the shell description across sandbox_types, since we cover
    this in the prompt, and have moved necessary details (like
    network_access and writeable workspace roots) to EnvironmentContext
    messages.
    
    ## Test Plan
    - [x] updated unit tests
  • bug: fix model save (#3525)
    Fix those 2 behaviors:
    1. The model does not get saved if we don't CTRL + S
    2. The reasoning effort get saved
  • feat: added SetDefaultModel to JSON-RPC server (#3512)
    This adds `SetDefaultModel`, which takes `model` and `reasoning_effort`
    as optional fields. If set, the field will overwrite what is in the
    user's `config.toml`.
    
    This reuses logic that was added to support the `/model` command in the
    TUI: https://github.com/openai/codex/pull/2799.
  • feat: include reasoning_effort in NewConversationResponse (#3506)
    `ClientRequest::NewConversation` picks up the reasoning level from the user's defaults in `config.toml`, so it should be reported in `NewConversationResponse`.