Commit Graph

97 Commits

  • fix: remove unnecessary flush() calls (#2873)
    Because we are writing to a pipe, these `flush()` calls are unnecessary,
    so removing these saves us one syscall per write in these two cases.
  • fix: switch to unbounded channel (#2874)
    #2747 encouraged me to audit our codebase for similar issues, as now I
    am particularly suspicious that our flaky tests are due to a racy
    deadlock.
    
    I asked Codex to audit our code, and one of its suggestions was this:
    
    > **High-Risk Patterns**
    >
    > All `send_*` methods await on a bounded
    `mpsc::Sender<OutgoingMessage>`. If the writer blocks, the channel fills
    and the processor task blocks on send, stops draining incoming requests,
    and stdin reader eventually blocks on its send. This creates a
    backpressure deadlock cycle across the three tasks.
    >
    > **Recommendations**
    > * Server outgoing path: break the backpressure cycle
    > * Option A (minimal risk): Change `OutgoingMessageSender` to use an
    unbounded channel to decouple producer from stdout. Add rate logging so
    floods are visible.
    > * Option B (bounded + drop policy): Change `send_*` to try_send and
    drop messages (or coalesce) when the queue is full, logging a warning.
    This prevents processor stalls at the cost of losing messages under
    extreme backpressure.
    > * Option C (two-stage buffer): Keep bounded channel, but have a
    dedicated “egress” task that drains an unbounded internal queue, writing
    to stdout with retries and a shutdown timeout. This centralizes
    backpressure policy.
    
    So this PR is Option A.
    
    Indeed, we previously used a bounded channel with a capacity of `128`,
    but as we discovered recently with #2776, there are certainly cases
    where we can get flooded with events.
    
    That said, `test_shell_command_approval_triggers_elicitation` just
    failed one one build when I put up this PR, so clearly we are not out of
    the woods yet...
    
    **Update:** I think I found the true source of the deadlock! See
    https://github.com/openai/codex/pull/2876
  • Bug fix: clone of incoming_tx can lead to deadlock (#2747)
    POC code
    
    ```rust
    use tokio::sync::mpsc;
    use std::time::Duration;
    
    #[tokio::main]
    async fn main() {
        println!("=== Test 1: Simulating original MCP server pattern ===");
        test_original_pattern().await;
    }
    
    async fn test_original_pattern() {
        println!("Testing the original pattern from MCP server...");
        
        // Create channel - this simulates the original incoming_tx/incoming_rx
        let (tx, mut rx) = mpsc::channel::<String>(10);
        
        // Task 1: Simulates stdin reader that will naturally terminate
        let stdin_task = tokio::spawn({
            let tx_clone = tx.clone();
            async move {
                println!("  stdin_task: Started, will send 3 messages then exit");
                for i in 0..3 {
                    let msg = format!("Message {}", i);
                    if tx_clone.send(msg.clone()).await.is_err() {
                        println!("  stdin_task: Receiver dropped, exiting");
                        break;
                    }
                    println!("  stdin_task: Sent {}", msg);
                    tokio::time::sleep(Duration::from_millis(300)).await;
                }
                println!("  stdin_task: Finished (simulating EOF)");
                // tx_clone is dropped here
            }
        });
        
        // Task 2: Simulates message processor
        let processor_task = tokio::spawn(async move {
            println!("  processor_task: Started, waiting for messages");
            while let Some(msg) = rx.recv().await {
                println!("  processor_task: Processing {}", msg);
                tokio::time::sleep(Duration::from_millis(100)).await;
            }
            println!("  processor_task: Finished (channel closed)");
        });
        
        // Task 3: Simulates stdout writer or other background task
        let background_task = tokio::spawn(async move {
            for i in 0..2 {
                tokio::time::sleep(Duration::from_millis(500)).await;
                println!("  background_task: Tick {}", i);
            }
            println!("  background_task: Finished");
        });
        
        println!("  main: Original tx is still alive here");
        println!("  main: About to call tokio::join! - will this deadlock?");
        
        // This is the pattern from the original code
        let _ = tokio::join!(stdin_task, processor_task, background_task);
    }
    
    ```
    
    ---------
    
    Co-authored-by: Michael Bolin <bolinfest@gmail.com>
  • Following up on #2371 post commit feedback (#2852)
    - Introduce websearch end to complement the begin 
    - Moves the logic of adding the sebsearch tool to
    create_tools_json_for_responses_api
    - Making it the client responsibility to toggle the tool on or off 
    - Other misc in #2371 post commit feedback
    - Show the query:
    
    <img width="1392" height="151" alt="image"
    src="https://github.com/user-attachments/assets/8457f1a6-f851-44cf-bcca-0d4fe460ce89"
    />
  • Custom /prompts (#2696)
    Adds custom `/prompts` to `~/.codex/prompts/<command>.md`.
    
    <img width="239" height="107" alt="Screenshot 2025-08-25 at 6 22 42 PM"
    src="https://github.com/user-attachments/assets/fe6ebbaa-1bf6-49d3-95f9-fdc53b752679"
    />
    
    ---
    
    Details:
    
    1. Adds `Op::ListCustomPrompts` to core.
    2. Returns `ListCustomPromptsResponse` with list of `CustomPrompt`
    (name, content).
    3. TUI calls the operation on load, and populates the custom prompts
    (excluding prompts that collide with builtins).
    4. Selecting the custom prompt automatically sends the prompt to the
    agent.
  • chore: require uninlined_format_args from clippy (#2845)
    - added `uninlined_format_args` to `[workspace.lints.clippy]` in the
    `Cargo.toml` for the workspace
    - ran `cargo clippy --tests --fix`
    - ran `just fmt`
  • Add "View Image" tool (#2723)
    Adds a "View Image" tool so Codex can find and see images by itself:
    
    <img width="1772" height="420" alt="Screenshot 2025-08-26 at 10 40
    04 AM"
    src="https://github.com/user-attachments/assets/7a459c7b-0b86-4125-82d9-05fbb35ade03"
    />
  • [mcp-server] Add GetConfig endpoint (#2725)
    ## Summary
    Adds a GetConfig request to the MCP Protocol, so MCP clients can
    evaluate the resolved config.toml settings which the harness is using.
    
    ## Testing
    - [x] Added an end to end test of the endpoint
  • send context window with task started (#2752)
    - Send context window with task started
    - Accounting for changing the model per turn
  • Add web search tool (#2371)
    Adds web_search tool, enabling the model to use Responses API web_search
    tool.
    - Disabled by default, enabled by --search flag
    - When --search is passed, exposes web_search_request function tool to
    the model, which triggers user approval. When approved, the model can
    use the web_search tool for the remainder of the turn
    <img width="1033" height="294" alt="image"
    src="https://github.com/user-attachments/assets/62ac6563-b946-465c-ba5d-9325af28b28f"
    />
    
    ---------
    
    Co-authored-by: easong-openai <easong@openai.com>
  • fork conversation from a previous message (#2575)
    This can be the underlying logic in order to start a conversation from a
    previous message. will need some love in the UI.
    
    Base for building this: #2588
  • Add AuthManager and enhance GetAuthStatus command (#2577)
    This PR adds a central `AuthManager` struct that manages the auth
    information used across conversations and the MCP server. Prior to this,
    each conversation and the MCP server got their own private snapshots of
    the auth information, and changes to one (such as a logout or token
    refresh) were not seen by others.
    
    This is especially problematic when multiple instances of the CLI are
    run. For example, consider the case where you start CLI 1 and log in to
    ChatGPT account X and then start CLI 2 and log out and then log in to
    ChatGPT account Y. The conversation in CLI 1 is still using account X,
    but if you create a new conversation, it will suddenly (and
    unexpectedly) switch to account Y.
    
    With the `AuthManager`, auth information is read from disk at the time
    the `ConversationManager` is constructed, and it is cached in memory.
    All new conversations use this same auth information, as do any token
    refreshes.
    
    The `AuthManager` is also used by the MCP server's GetAuthStatus
    command, which now returns the auth method currently used by the MCP
    server.
    
    This PR also includes an enhancement to the GetAuthStatus command. It
    now accepts two new (optional) input parameters: `include_token` and
    `refresh_token`. Callers can use this to request the in-use auth token
    and can optionally request to refresh the token.
    
    The PR also adds tests for the login and auth APIs that I recently added
    to the MCP server.
  • Added new auth-related methods and events to mcp server (#2496)
    This PR adds the following:
    * A getAuthStatus method on the mcp server. This returns the auth method
    currently in use (chatgpt or apikey) or none if the user is not
    authenticated. It also returns the "preferred auth method" which
    reflects the `preferred_auth_method` value in the config.
    * A logout method on the mcp server. If called, it logs out the user and
    deletes the `auth.json` file — the same behavior in the cli's `/logout`
    command.
    * An `authStatusChange` event notification that is sent when the auth
    status changes due to successful login or logout operations.
    * Logic to pass command-line config overrides to the mcp server at
    startup time. This allows use cases like `codex mcp -c
    preferred_auth_method=apikey`.
  • [tui] Support /mcp command (#2430)
    ## Summary
    Adds a `/mcp` command to list active tools. We can extend this command
    to allow configuration of MCP tools, but for now a simple list command
    will help debug if your config.toml and your tools are working as
    expected.
  • fix: remove shutdown_flag param to run_login_server() (#2399)
    In practice, this was always passed in as `None`, so eliminated the
    param and updated all the call sites.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2399).
    * __->__ #2399
    * #2398
    * #2396
    * #2395
    * #2394
    * #2393
    * #2389
  • fix: make ShutdownHandle a private field of LoginServer (#2396)
    Folds the top-level `shutdown()` function into a method of
    `ShutdownHandle` and then simply stores `ShutdownHandle` on
    `LoginServer` since the two fields it contains were always being used
    together, anyway.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2396).
    * #2399
    * #2398
    * __->__ #2396
    * #2395
    * #2394
    * #2393
    * #2389
  • fix: eliminate ServerOptions.login_timeout and have caller use tokio::time::timeout() instead (#2395)
    https://github.com/openai/codex/pull/2373 introduced
    `ServerOptions.login_timeout` and `spawn_timeout_watcher()` to use an
    extra thread to manage the timeout for the login server. Now that we
    have asyncified the login stack, we can use `tokio::time::timeout()`
    from "outside" the login library to manage the timeout rather than
    having to a commit to a specific "timeout" concept from within.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2395).
    * #2399
    * #2398
    * #2396
    * __->__ #2395
    * #2394
    * #2393
    * #2389
  • fix: async-ify login flow (#2393)
    This replaces blocking I/O with async/non-blocking I/O in a number of
    cases. This facilitates the use of `tokio::sync::Notify` and
    `tokio::select!` in #2394.
    
    
    
    
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2393).
    * #2399
    * #2398
    * #2396
    * #2395
    * #2394
    * __->__ #2393
    * #2389
  • chore: move mcp-server/src/wire_format.rs to protocol/src/mcp_protocol.rs (#2423)
    The existing `wire_format.rs` should share more types with the
    `codex-protocol` crate (like `AskForApproval` instead of maintaining a
    parallel `CodexToolCallApprovalPolicy` enum), so this PR moves
    `wire_format.rs` into `codex-protocol`, renaming it as
    `mcp-protocol.rs`. We also de-dupe types, where appropriate.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2423).
    * #2424
    * __->__ #2423
  • fix: introduce EventMsg::TurnAborted (#2365)
    Introduces `EventMsg::TurnAborted` that should be sent in response to
    `Op::Interrupt`.
    
    In the MCP server, updates the handling of a
    `ClientRequest::InterruptConversation` request such that it sends the
    `Op::Interrupt` but does not respond to the request until it sees an
    `EventMsg::TurnAborted`.
  • Added MCP server command to enable authentication using ChatGPT (#2373)
    This PR adds two new APIs for the MCP server: 1) loginChatGpt, and 2)
    cancelLoginChatGpt. The first starts a login server and returns a local
    URL that allows for browser-based authentication, and the second
    provides a way to cancel the login attempt. If the login attempt
    succeeds, a notification (in the form of an event) is sent to a
    subscriber.
    
    I also added a timeout mechanism for the existing login server. The
    loginChatGpt code path uses a 10-minute timeout by default, so if the
    user fails to complete the login flow in that timeframe, the login
    server automatically shuts down. I tested the timeout code by manually
    setting the timeout to a much lower number and confirming that it works
    as expected when used e2e.
  • feat: introduce ClientRequest::SendUserTurn (#2345)
    This adds a new request type, `SendUserTurn`, that makes it possible to
    submit a `Op::UserTurn` operation (introduced in #2329) to a
    conversation. This PR also adds a new integration test that verifies
    that changing from `AskForApproval::UnlessTrusted` to
    `AskForApproval::Never` mid-conversation ensures that an elicitation is
    no longer sent for running `python3 -c print(42)`.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2345).
    * __->__ #2345
    * #2329
    * #2343
    * #2340
    * #2338
  • [tools] Add apply_patch tool (#2303)
    ## Summary
    We've been seeing a number of issues and reports with our synthetic
    `apply_patch` tool, e.g. #802. Let's make this a real tool - in my
    anecdotal testing, it's critical for GPT-OSS models, but I'd like to
    make it the standard across GPT-5 and codex models as well.
    
    ## Testing
    - [x] Tested locally
    - [x] Integration test
  • Added allow-expect-in-tests / allow-unwrap-in-tests (#2328)
    This PR:
    * Added the clippy.toml to configure allowable expect / unwrap usage in
    tests
    * Removed as many expect/allow lines as possible from tests
    * moved a bunch of allows to expects where possible
    
    Note: in integration tests, non `#[test]` helper functions are not
    covered by this so we had to leave a few lingering `expect(expect_used`
    checks around
  • Tag InputItem (#2304)
    Instead of:
    ```
    { Text: { text: string } }
    ```
    
    It is now:
    ```
    { type: "text", data: { text: string } }
    ```
    which makes for cleaner discriminated unions
  • feat: add support for an InterruptConversation request (#2287)
    This adds `ClientRequest::InterruptConversation`, which effectively maps
    directly to `Op::Interrupt`.
    
    ---
    
    * __->__  #2287
    * #2286
    * #2285
  • fix: add support for exec and apply_patch approvals in the new wire format (#2286)
    Now when `CodexMessageProcessor` receives either a
    `EventMsg::ApplyPatchApprovalRequest` or a
    `EventMsg::ExecApprovalRequest`, it sends the appropriate request from
    the server to the client. When it gets a response, it forwards it on to
    the `CodexConversation`.
    
    Note this takes a lot of code from:
    
    
    https://github.com/openai/codex/blob/main/codex-rs/mcp-server/src/conversation_loop.rs
    
    https://github.com/openai/codex/blob/main/codex-rs/mcp-server/src/exec_approval.rs
    
    https://github.com/openai/codex/blob/main/codex-rs/mcp-server/src/patch_approval.rs
    
    I am copy/pasting for now because I am trying to consolidate around the
    new `wire_format.rs`, so I plan to delete these other files soon.
    
    Now that we have requests going both from client-to-server and
    server-to-client, I renamed `CodexRequest` to `ClientRequest`.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2286).
    * #2287
    * __->__ #2286
    * #2285
  • fix: verify notifications are sent with the conversationId set (#2278)
    This updates `CodexMessageProcessor` so that each notification it sends
    for a `EventMsg` from a `CodexConversation` such that:
    
    - The `params` always has an appropriate `conversationId` field.
    - The `method` is now includes the name of the `EventMsg` type rather
    than using `codex/event` as the `method` type for all notifications. (We
    currently prefix the method name with `codex/event/`, but I think that
    should go away once we formalize the notification schema in
    `wire_format.rs`.)
    
    As part of this, we update `test_codex_jsonrpc_conversation_flow()` to
    verify that the `task_finished` notification has made it through the
    system instead of sleeping for 5s and "hoping" the server finished
    processing the task. Note we have seen some flakiness in some of our
    other, similar integration tests, and I expect adding a similar check
    would help in those cases, as well.
  • feat: support traditional JSON-RPC request/response in MCP server (#2264)
    This introduces a new set of request types that our `codex mcp`
    supports. Note that these do not conform to MCP tool calls so that
    instead of having to send something like this:
    
    ```json
    {
      "jsonrpc": "2.0",
      "method": "tools/call",
      "id": 42,
      "params": {
        "name": "newConversation",
        "arguments": {
          "model": "gpt-5",
          "approvalPolicy": "on-request"
        }
      }
    }
    ```
    
    we can send something like this:
    
    
    ```json
    {
      "jsonrpc": "2.0",
      "method": "newConversation",
      "id": 42,
      "params": {
        "model": "gpt-5",
        "approvalPolicy": "on-request"
      }
    }
    ```
    
    Admittedly, this new format is not a valid MCP tool call, but we are OK
    with that right now. (That is, not everything we might want to request
    of `codex mcp` is something that is appropriate for an autonomous agent
    to do.)
    
    To start, this introduces four request types:
    
    - `newConversation`
    - `sendUserMessage`
    - `addConversationListener`
    - `removeConversationListener`
    
    The new `mcp-server/tests/codex_message_processor_flow.rs` shows how
    these can be used.
    
    The types are defined on the `CodexRequest` enum, so we introduce a new
    `CodexMessageProcessor` that is responsible for dealing with requests
    from this enum. The top-level `MessageProcessor` has been updated so
    that when `process_request()` is called, it first checks whether the
    request conforms to `CodexRequest` and dispatches it to
    `CodexMessageProcessor` if so.
    
    Note that I also decided to use `camelCase` for the on-the-wire format,
    as that seems to be the convention for MCP.
    
    For the moment, the new protocol is defined in `wire_format.rs` within
    the `mcp-server` crate, but in a subsequent PR, I will probably move it
    to its own crate to ensure the protocol has minimal dependencies and
    that we can codegen a schema from it.
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2264).
    * #2278
    * __->__ #2264
  • fix: update OutgoingMessageSender::send_response() to take Serialize (#2263)
    This makes `send_response()` easier to work with.
  • chore: introduce ConversationManager as a clearinghouse for all conversations (#2240)
    This PR does two things because after I got deep into the first one I
    started pulling on the thread to the second:
    
    - Makes `ConversationManager` the place where all in-memory
    conversations are created and stored. Previously, `MessageProcessor` in
    the `codex-mcp-server` crate was doing this via its `session_map`, but
    this is something that should be done in `codex-core`.
    - It unwinds the `ctrl_c: tokio::sync::Notify` that was threaded
    throughout our code. I think this made sense at one time, but now that
    we handle Ctrl-C within the TUI and have a proper `Op::Interrupt` event,
    I don't think this was quite right, so I removed it. For `codex exec`
    and `codex proto`, we now use `tokio::signal::ctrl_c()` directly, but we
    no longer make `Notify` a field of `Codex` or `CodexConversation`.
    
    Changes of note:
    
    - Adds the files `conversation_manager.rs` and `codex_conversation.rs`
    to `codex-core`.
    - `Codex` and `CodexSpawnOk` are no longer exported from `codex-core`:
    other crates must use `CodexConversation` instead (which is created via
    `ConversationManager`).
    - `core/src/codex_wrapper.rs` has been deleted in favor of
    `ConversationManager`.
    - `ConversationManager::new_conversation()` returns `NewConversation`,
    which is in line with the `new_conversation` tool we want to add to the
    MCP server. Note `NewConversation` includes `SessionConfiguredEvent`, so
    we eliminate checks in cases like `codex-rs/core/tests/client.rs` to
    verify `SessionConfiguredEvent` is the first event because that is now
    internal to `ConversationManager`.
    - Quite a bit of code was deleted from
    `codex-rs/mcp-server/src/message_processor.rs` since it no longer has to
    manage multiple conversations itself: it goes through
    `ConversationManager` instead.
    - `core/tests/live_agent.rs` has been deleted because I had to update a
    bunch of tests and all the tests in here were ignored, and I don't think
    anyone ever ran them, so this was just technical debt, at this point.
    - Removed `notify_on_sigint()` from `util.rs` (and in a follow-up, I
    hope to refactor the blandly-named `util.rs` into more descriptive
    files).
    - In general, I started replacing local variables named `codex` as
    `conversation`, where appropriate, though admittedly I didn't do it
    through all the integration tests because that would have added a lot of
    noise to this PR.
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2240).
    * #2264
    * #2263
    * __->__ #2240
  • Re-add markdown streaming (#2029)
    Wait for newlines, then render markdown on a line by line basis. Word wrap it for the current terminal size and then spit it out line by line into the UI. Also adds tests and fixes some UI regressions.
  • [mcp-server] Support CodexToolCallApprovalPolicy::OnRequest (#2187)
    ## Summary
    #1865 added `AskForApproval::OnRequest`, but missed adding it to our
    custom struct in `mcp-server`. This adds the missing configuration
    
    ## Testing
    - [x] confirmed locally
  • [1/3] Parse exec commands and format them more nicely in the UI (#2095)
    # Note for reviewers
    The bulk of this PR is in in the new file, `parse_command.rs`. This file
    is designed to be written TDD and implemented with Codex. Do not worry
    about reviewing the code, just review the unit tests (if you want). If
    any cases are missing, we'll add more tests and have Codex fix them.
    
    I think the best approach will be to land and iterate. I have some
    follow-ups I want to do after this lands. The next PR after this will
    let us merge (and dedupe) multiple sequential cells of the same such as
    multiple read commands. The deduping will also be important because the
    model often reads the same file multiple times in a row in chunks
    
    ===
    
    This PR formats common commands like reading, formatting, testing, etc
    more nicely:
    
    It tries to extract things like file names, tests and falls back to the
    cmd if it doesn't. It also only shows stdout/err if the command failed.
    
    <img width="770" height="238" alt="CleanShot 2025-08-09 at 16 05 15"
    src="https://github.com/user-attachments/assets/0ead179a-8910-486b-aa3d-7d26264d751e"
    />
    <img width="348" height="158" alt="CleanShot 2025-08-09 at 16 05 32"
    src="https://github.com/user-attachments/assets/4302681b-5e87-4ff3-85b4-0252c6c485a9"
    />
    <img width="834" height="324" alt="CleanShot 2025-08-09 at 16 05 56 2"
    src="https://github.com/user-attachments/assets/09fb3517-7bd6-40f6-a126-4172106b700f"
    />
    
    Part 2: https://github.com/openai/codex/pull/2097
    Part 3: https://github.com/openai/codex/pull/2110
  • chore: remove unnecessary default_ prefix (#1854)
    This prefix is not inline with the other fields on the `ConfigOverrides`
    struct.
  • Introduce --oss flag to use gpt-oss models (#1848)
    This adds support for easily running Codex backed by a local Ollama
    instance running our new open source models. See
    https://github.com/openai/gpt-oss for details.
    
    If you pass in `--oss` you'll be prompted to install/launch ollama, and
    it will automatically download the 20b model and attempt to use it.
    
    We'll likely want to expand this with some options later to make the
    experience smoother for users who can't run the 20b or want to run the
    120b.
    
    Co-authored-by: Michael Bolin <mbolin@openai.com>
  • Rescue chat completion changes (#1846)
    https://github.com/openai/codex/pull/1835 has some messed up history.
    
    This adds support for streaming chat completions, which is useful for ollama. We should probably take a very skeptical eye to the code introduced in this PR.
    
    ---------
    
    Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
  • Add a TurnDiffTracker to create a unified diff for an entire turn (#1770)
    This lets us show an accumulating diff across all patches in a turn.
    Refer to the docs for TurnDiffTracker for implementation details.
    
    There are multiple ways this could have been done and this felt like the
    right tradeoff between reliability and completeness:
    *Pros*
    * It will pick up all changes to files that the model touched including
    if they prettier or another command that updates them.
    * It will not pick up changes made by the user or other agents to files
    it didn't modify.
    
    *Cons*
    * It will pick up changes that the user made to a file that the model
    also touched
    * It will not pick up changes to codegen or files that were not modified
    with apply_patch
  • Fix flaky test_shell_command_approval_triggers_elicitation test (#1802)
    This doesn't flake very often but this should fix it.
  • MCP: add conversation.create tool [Stack 2/2] (#1783)
    Introduce conversation.create handler (handle_create_conversation) and
    wire it in MessageProcessor.
    
    Stack:
    Top: #1783 
    Bottom: #1784
    
    ---------
    
    Co-authored-by: Gabriel Peal <gpeal@users.noreply.github.com>
  • Add Error variant to ConversationCreateResult [Stack 1/2] (#1784)
    Switch ConversationCreateResult from a struct to a tagged enum (Ok |
    Error)
    
    Stack:
    Top: #1783 
    Bottom: #1784
  • feat: stream exec stdout events (#1786)
    ## Summary
    - stream command stdout as `ExecCommandStdout` events
    - forward streamed stdout to clients and ignore in human output
    processor
    - adjust call sites for new streaming API