Commit Graph

1488 Commits

  • Fix: Claude models return incomplete responses due to empty finish_reason handling (#6728)
    ## Summary
    Fixes streaming issue where Claude models return only 1-4 characters
    instead of full responses when used through certain API
    providers/proxies.
    
    ## Environment
    - **OS**: Windows
    - **Models affected**: Claude models (e.g., claude-haiku-4-5-20251001)
    - **API Provider**: AAAI API proxy (https://api.aaai.vip/v1)
    - **Working models**: GLM, Google models work correctly
    
    ## Problem
    When using Claude models in both TUI and exec modes, only 1-4 characters
    are displayed despite the backend receiving the full response. Debug
    logs revealed that some API providers send SSE chunks with an empty
    string finish_reason during active streaming, rather than null or
    omitting the field entirely.
    
    The current code treats any non-null finish_reason as a termination
    signal, causing the stream to exit prematurely after the first chunk.
    The problematic chunks contain finish_reason with an empty string
    instead of null.
    
    ## Solution
    Fix empty finish_reason handling in chat_completions.rs by adding a
    check to only process non-empty finish_reason values. This ensures empty
    strings are ignored and streaming continues normally.
    
    ## Testing
    - Tested on Windows with Claude Haiku model via AAAI API proxy
    - Full responses now received and displayed correctly in both TUI and
    exec modes
    - Other models (GLM, Google) continue to work as expected
    - No regression in existing functionality
    
    ## Impact
    - Improves compatibility with API providers that send empty
    finish_reason during streaming
    - Enables Claude models to work correctly in Windows environment
    - No breaking changes to existing functionality
    
    ## Related Issues
    This fix resolves the issue where Claude models appeared to return
    incomplete responses. The root cause was identified as a compatibility
    issue in parsing SSE responses from certain API providers/proxies,
    rather than a model-specific problem. This change improves overall
    robustness when working with various API endpoints.
    
    ---------
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • Fix AltGr/backslash input on Windows Codex terminal (#6720)
    ### Summary
    
    - Treat AltGr chords (Ctrl+Alt) as literal character input in the Codex
    TUI textarea so Windows terminals that report
        backslash and other characters via AltGr insert correctly.
    - Add regression test altgr_ctrl_alt_char_inserts_literal to ensure
    Ctrl+Alt char events append the character and
        advance the cursor.
    
     ### Motivation
    
    On US/UK keyboard layouts, backslash is produced by a plain key, so
    Ctrl+Alt handling is never exercised and the
    bug isn’t visible. On many non‑US layouts (e.g., German), backslash and
    other symbols require AltGr, which terminals
    report as Ctrl+Alt+<char>. Our textarea previously filtered these chords
    like navigation bindings, so AltGr input was
    dropped on affected layouts. This change treats AltGr chords as literal
    input so backslash and similar symbols work on
      Windows terminals.
    
    This fixes multiple reported Issues where the \ symbol got cut off.
    Like:
    C:\Users\Admin
    became
    C:UsersAdmin
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • fix: resolve Windows MCP server execution for script-based tools (#3828)
    ## What?
    
    Fixes MCP server initialization failures on Windows when using
    script-based tools like `npx`, `pnpm`, and `yarn` that rely on
    `.cmd`/`.bat` files rather than `.exe` binaries.
    
    Fixes #2945
    
    ## Why?
    
    Windows users encounter "program not found" errors when configuring MCP
    servers with commands like `npx` in their `~/.codex/config.toml`. This
    happens because:
    
    - Tools like `npx` are batch scripts (`npx.cmd`) on Windows, not
    executable binaries
    - Rust's `std::process::Command` bypasses the shell and cannot execute
    these scripts directly
    - The Windows shell normally handles this by checking `PATHEXT` for
    executable extensions
    
    Without this fix, Windows users must specify full paths or add `.cmd`
    extensions manually, which breaks cross-platform compatibility.
    
    ## How?
    
    Added platform-specific program resolution using the `which` crate to
    find the correct executable path:
    
    - **Windows**: Resolves programs through PATH/PATHEXT to find
    `.cmd`/`.bat` scripts
    - **Unix**: Returns the program unchanged (no-op, as Unix handles
    scripts natively)
    
    ### Changes
    
    - Added `which = "6"` dependency to `mcp-client/Cargo.toml`
    - Implemented `program_resolver` module in `mcp_client.rs` with
    platform-specific resolution
    - Added comprehensive tests for both Windows and Unix behavior
    
    ### Testing
    
    Added platform-specific tests to verify:
    - Unix systems execute scripts without extensions
    - Windows fails without proper extensions
    - Windows succeeds with explicit extensions
    - Cross-platform resolution enables successful execution
    
    **Tested on:**
    - Windows 11 (NT 10.0.26100.0 x64)
    - PowerShell 5.1 & 7+, CMD, Git Bash
    - MCP servers: playwright, context7, supabase
    - WSL (verified no regression)
    
    **Local checks passed:**
    ```bash
    cargo test && cargo clippy --tests && cargo fmt -- --config imports_granularity=Item
    ```
    
    ### Results
    
    **Before:**
    ```
    🖐 MCP client for `playwright` failed to start: program not found
    ```
    
    **After:**
    ```
    🖐 MCP client for `playwright` failed to start: request timed out
    ```
    
    Windows users can now use simple commands like `npx` in their config
    without specifying full paths or extensions. The timeout issue is a
    separate concern that will be addressed in a follow-up PR.
    
    ---------
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • Improve compact (#6692)
    This PR does the following:
    - Add compact prefix to the summary
    - Change the compaction prompt
    - Allow multiple compaction for long running tasks
    - Filter out summary messages on the following compaction
    
    Considerations:
    - Filtering out the summary message isn't the most clean
    - Theoretically, we can end up in infinite compaction loop if the user
    messages > compaction limit . However, that's not possible in today's
    code because we have hard cap on user messages.
    - We need to address having multiple user messages because it confuses
    the model.
    
    Testing:
    - Making sure that after compact we always end up with one user message
    (task) and one summary, even on multiple compaction.
  • Refactor truncation helpers into its own file (#6683)
    That's to centralize the truncation in one place. Next step would be to
    make only two methods public: one with bytes/lines and one with tokens.
  • Handle "Don't Trust" directory selection in onboarding (#4941)
    Fixes #4940
    Fixes #4892
    
    When selecting "No, ask me to approve edits and commands" during
    onboarding, the code wasn't applying the correct approval policy,
    causing Codex to block all write operations instead of requesting
    approval.
    
    This PR fixes the issue by persisting the "DontTrust" decision in
    config.toml as `trust_level = "untrusted"` and handling it in the
    sandbox and approval policy logic, so Codex correctly asks for approval
    before making changes.
    
    ## Before (bug)
    <img width="709" height="500" alt="bef"
    src="https://github.com/user-attachments/assets/5aced26d-d810-4754-879a-89d9e4e0073b"
    />
    
    ## After (fixed)
    <img width="713" height="359" alt="aft"
    src="https://github.com/user-attachments/assets/9887bbcb-a9a5-4e54-8e76-9125a782226b"
    />
    
    ---------
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • Order outputs before inputs (#6691)
    For better caching performance all output items should be rendered in
    the order they were produced before all new input items (for example,
    all function_call before all function_call_output).
  • feat: add app-server-test-client crate for internal use (#5391)
    For app-server development it's been helpful to be able to trigger some
    test flows end-to-end and print the JSON-RPC messages sent between
    client and server.
  • fix codex detection, add new security-focused smoketests. (#6682)
    Fix 'codex' detection to look for debug build, then release build, then
    installed.
    
    Adds more smoketests around security from @viyatb-oai
  • Add test timeout (#6612)
    Add an overall test timeout of 30s.
  • Enable TUI notifications by default (#6633)
    ## Summary
    - default the `tui.notifications` setting to enabled so desktop
    notifications work out of the box
    - update configuration tests and documentation to reflect the new
    default
    
    ## Testing
    - `cargo test -p codex-core` *(fails:
    `exec::tests::kill_child_process_group_kills_grandchildren_on_timeout`
    is flaky in this sandbox because the spawned grandchild process stays
    alive)*
    - `cargo test -p codex-core
    exec::tests::kill_child_process_group_kills_grandchildren_on_timeout`
    *(fails: same sandbox limitation as above)*
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_69166f811144832c9e8aaf8ee2642373)
  • [App server] add mcp tool call item started/completed events (#6642)
    this PR does two things:
    1. refactor `apply_bespoke_event_handling` into a separate file as it's
    getting kind of long;
    2. add mcp tool call `item/started` and `item/completed` events. To roll
    out app server events asap we didn't properly migrate mcp core events to
    use TurnItem for mcp tool calls - this will be a follow-up PR.
    
    real events generated in log:
    ```
    {
      "method": "codex/event/mcp_tool_call_end",
      "params": {
        "conversationId": "019a8021-26af-7c20-83db-21ca81e44d68",
        "id": "0",
        "msg": {
          "call_id": "call_7EjRQkD9HnfyMWf7tGrT9FKA",
          "duration": {
            "nanos": 92708,
            "secs": 0
          },
          "invocation": {
            "arguments": {
              "server": ""
            },
            "server": "codex",
            "tool": "list_mcp_resources"
          },
          "result": {
            "Ok": {
              "content": [
                {
                  "text": "{\"resources\":[]}",
                  "type": "text"
                }
              ],
              "isError": false
            }
          },
          "type": "mcp_tool_call_end"
        }
      }
    }
    
    {
      "method": "item/completed",
      "params": {
        "item": {
          "arguments": {
            "server": ""
          },
          "error": null,
          "id": "call_7EjRQkD9HnfyMWf7tGrT9FKA",
          "result": {
            "content": [
              {
                "text": "{\"resources\":[]}",
                "type": "text"
              }
            ],
            "structuredContent": null
          },
          "server": "codex",
          "status": "completed",
          "tool": "list_mcp_resources",
          "type": "mcpToolCall"
        }
      }
    }
    ```
  • feat: better UI for unified_exec (#6515)
    <img width="376" height="132" alt="Screenshot 2025-11-12 at 17 36 22"
    src="https://github.com/user-attachments/assets/ce693f0d-5ca0-462e-b170-c20811dcc8d5"
    />
  • Promote shared helpers for suite tests (#6460)
    ## Summary
    - add `TestCodex::submit_turn_with_policies` and extend the response
    helpers with reusable tool-call utilities
    - update the grep_files, read_file, list_dir, shell_serialization, and
    tools suites to rely on the shared helpers instead of local copies
    - make the list_dir helper return `anyhow::Result` so clippy no longer
    warns about `expect`
    
    ## Testing
    - `just fix -p codex-core`
    - `cargo test -p codex-core --test all
    suite::grep_files::grep_files_tool_collects_matches`
    - `cargo test -p codex-core
    suite::grep_files::grep_files_tool_collects_matches -- --ignored`
    (filter requests ignored tests so nothing runs, but the build stays
    clean)
    
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_69112d53abac83219813cab4d7cb6446)
  • Use shared network gating helper in chat completion tests (#6461)
    ## Summary
    - replace the bespoke network check in the chat completion payload and
    SSE tests with the existing `skip_if_no_network!` helper so they follow
    the same gating convention as the rest of the suite
    
    ## Testing
    - `just fmt`
    
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_69112d4cb9f08321ba773e8ccf39778e)
  • Avoid double truncation (#6631)
    1. Avoid double truncation by giving 10% above the tool default constant
    2. Add tests that fails when const = 1
  • [app-server] small fixes for JSON schema export and one-of types (#6614)
    A partner is consuming our generated JSON schema bundle for app-server
    and identified a few issues:
    - not all polymorphic / one-of types have a type descriminator
    - `"$ref": "#/definitions/v2/SandboxPolicy"` is missing
    - "Option<>" is an invalid schema name, and also unnecessary
    
    This PR:
    - adds the type descriminator to the various types that are missing it
    except for `SessionSource` and `SubAgentSource` because they are
    serialized to disk (adding this would break backwards compat for
    resume), and they should not be necessary to consume for an integration
    with app-server.
    - removes the special handling in `export.rs` of various types like
    SandboxPolicy, which turned out to be unnecessary and incorrect
    - filters out `Option<>` which was auto-generated for request params
    that don't need a body
    
    For context, we currently pull in wayyy more types than we need through
    the `EventMsg` god object which we are **not** planning to expose in API
    v2 (this is how I suspect `SessionSource` and `SubAgentSource` are being
    pulled in). But until we have all the necessary v2 notifications in
    place that will allow us to remove `EventMsg`, we will keep exporting it
    for now.
  • [App-server] add new v2 events:item/reasoning/delta, item/agentMessage/delta & item/reasoning/summaryPartAdded (#6559)
    core event to app server event mapping:
    1. `codex/event/reasoning_content_delta` ->
    `item/reasoning/summaryTextDelta`.
    2. `codex/event/reasoning_raw_content_delta` ->
    `item/reasoning/textDelta`
    3. `codex/event/agent_message_content_delta` →
    `item/agentMessage/delta`.
    4. `codex/event/agent_reasoning_section_break` ->
    `item/reasoning/summaryPartAdded`.
    
    Also added a change in core to pass down content index, summary index
    and item id from events.
    
    Tested with the `git checkout owen/app_server_test_client && cargo run
    -p codex-app-server-test-client -- send-message-v2 "hello"` and verified
    that new events are emitted correctly.
  • chore(core) Consolidate apply_patch tests (#6545)
    ## Summary
    Consolidates our apply_patch tests into one suite, and ensures each test
    case tests the various ways the harness supports apply_patch:
    1. Freeform custom tool call
    2. JSON function tool
    3. Simple shell call
    4. Heredoc shell call
    
    There are a few test cases that are specific to a particular variant,
    I've left those alone.
    
    ## Testing
    - [x] This adds a significant number of tests
  • feat: Add support for --add-dir to exec and TypeScript SDK (#6565)
    ## Summary
    
    Adds support for specifying additional directories in the TypeScript SDK
    through a new `additionalDirectories` option in `ThreadOptions`.
    
    ## Changes
    
    - Added `additionalDirectories` parameter to `ThreadOptions` interface
    - Updated `CodexExec` to accept and pass through additional directories
    via the `--config` flag for `sandbox_workspace_write.writable_roots`
    - Added comprehensive test coverage for the new functionality
    
    ## Test plan
    
    - Added test case that verifies `additionalDirectories` is correctly
    passed as repeated flags
    - Existing tests continue to pass
    
    ---------
    
    Co-authored-by: Claude <noreply@anthropic.com>
  • Update default yield time (#6610)
    10s for exec and 250ms for write_stdin
  • Overhaul shell detection and centralize command generation for unified exec (#6577)
    This fixes command display for unified exec. All `cd`s and `ls`es are
    now parsed.
    
    <img width="452" height="237" alt="image"
    src="https://github.com/user-attachments/assets/ce92d81f-f74c-485a-9b34-1eaa29290ec6"
    />
    
    Deletes a ton of tests that were doing nothing from shell.rs.
    
    ---------
    
    Co-authored-by: Pavel Krymets <pavel@krymets.com>
  • fix model picker wrapping (#6589)
    Previously the popup measured rows using the full content width while
    the renderer drew them with 2 columns of padding, so at certain widths
    the layout allocated too little vertical space and hid the third option.
    Now both desired_height and render call a shared helper that subtracts
    the padding before measuring, so the height we reserve always matches
    what we draw and the menu doesn't drops entries.
    
    
    https://github.com/user-attachments/assets/59058fd9-1e34-4325-b5fe-fc888dfcb6bc
  • chore(core) Update prompt for gpt-5.1 (#6588)
    ## Summary
    Updates the prompt for GPT-5.1
  • Reasoning level update (#6586)
    Automatically update reasoning levels when migrating between models
  • Avoid hang when tool's process spawns grandchild that shares stderr/stdout (#6575)
    We've received many reports of codex hanging when calling certain tools.
    [Here](https://github.com/openai/codex/issues/3204) is one example. This
    is likely a major cause. The problem occurs when
    `consume_truncated_output` waits for `stdout` and `stderr` to be closed
    once the child process terminates. This normally works fine, but it
    doesn't handle the case where the child has spawned grandchild processes
    that inherits `stdout` and `stderr`.
    
    The fix was originally written by @md-oai in [this
    PR](https://github.com/openai/codex/pull/1852), which has gone stale.
    I've copied the original fix (which looks sound to me) and added an
    integration test to prevent future regressions.
  • Change model picker to include gpt5.1 (#6569)
    - Change the presets
    - Change the tests that make sure we keep the list of tools updated
    - Filter out deprecated models
  • Set verbosity to low for 5.1 (#6568)
    And improve test coverage
  • NUX for gpt5.1 (#6561)
    - Introducing a screen to inform users of model changes. 
    - Config name is being passed to be able to reuse this component in the
    future for future models
  • [app-server] feat: thread/resume supports history, path, and overrides (#6483)
    This updates `thread/resume` to be at parity with v1's
    `ResumeConversationParams`. Turns out history is useful for codex cloud
    and path is useful for the VSCode extension. And config overrides are
    always useful.
  • Fixed status output to use auth information from AuthManager (#6529)
    This PR addresses https://github.com/openai/codex/issues/6360. The root
    problem is that the TUI was directly loading the `auth.json` file to
    access the auth information. It should instead be using the AuthManager,
    which records the current auth information. The `auth.json` file can be
    overwritten at any time by other instances of the CLI or extension, so
    its information can be out of sync with the current instance. The
    `/status` command should always report the auth information associated
    with the current instance.
    
    An alternative fix for this bug was submitted by @chojs23 in [this
    PR](https://github.com/openai/codex/pull/6495). That approach was only a
    partial fix.