Commit Graph

190 Commits

  • codex-tools: introduce named tool definitions (#15953)
    ## Why
    
    This continues the `codex-tools` migration by moving one more piece of
    generic tool-definition bookkeeping out of `codex-core`.
    
    The earlier extraction steps moved shared schema parsing into
    `codex-tools`, but `core/src/tools/spec.rs` still had to supply tool
    names separately and perform ad hoc rewrites for deferred MCP aliases.
    That meant the crate boundary was still awkward: the parsed shape coming
    back from `codex-tools` was missing part of the definition that
    `codex-core` ultimately needs to assemble a `ResponsesApiTool`.
    
    This change introduces a named `ToolDefinition` in `codex-tools` so both
    MCP tools and dynamic tools cross the crate boundary in the same
    reusable model. `codex-core` still owns the final `ResponsesApiTool`
    assembly, but less of the generic tool-definition shaping logic stays
    behind in `core`.
    
    ## What changed
    
    - replaced `ParsedToolDefinition` with a named `ToolDefinition` in
    `codex-rs/tools/src/tool_definition.rs`
    - added `codex-rs/tools/src/tool_definition_tests.rs` for `renamed()`
    and `into_deferred()`
    - updated `parse_dynamic_tool()` and `parse_mcp_tool()` to return
    `ToolDefinition`
    - simplified `codex-rs/core/src/tools/spec.rs` so it adapts
    `ToolDefinition` into `ResponsesApiTool` instead of rewriting names and
    deferred fields inline
    - updated parser tests and `codex-rs/tools/README.md` to reflect the
    named tool-definition model
    
    ## Test plan
    
    - `cargo test -p codex-tools`
    - `cargo test -p codex-core --lib tools::spec::`
  • codex-tools: extract dynamic tool adapters (#15944)
    ## Why
    
    `codex-tools` already owned the shared JSON schema parser and the MCP
    tool schema adapter, but `core/src/tools/spec.rs` still parsed dynamic
    tools directly.
    
    That left the tool-schema boundary split in two different ways:
    
    - MCP tools flowed through `codex-tools`, while dynamic tools were still
    parsed in `codex-core`
    - the extracted dynamic-tool path initially introduced a
    dynamic-specific parsed shape even though `codex-tools` already had very
    similar MCP adapter output
    
    This change finishes that extraction boundary in one step. `codex-core`
    still owns `ResponsesApiTool` assembly, but both MCP tools and dynamic
    tools now enter that layer through `codex-tools` using the same parsed
    tool-definition shape.
    
    ## What changed
    
    - added `tools/src/dynamic_tool.rs` and sibling
    `tools/src/dynamic_tool_tests.rs`
    - introduced `parse_dynamic_tool()` in `codex-tools` and switched
    `core/src/tools/spec.rs` to use it for dynamic tools
    - added `tools/src/parsed_tool_definition.rs` so both MCP and dynamic
    adapters return the same `ParsedToolDefinition`
    - updated `core/src/tools/spec.rs` to build `ResponsesApiTool` through a
    shared local adapter helper instead of separate MCP and dynamic assembly
    paths
    - expanded `core/src/tools/spec_tests.rs` so the dynamic-tool adapter
    test asserts the full converted `ResponsesApiTool`, including
    `defer_loading`
    - updated `codex-rs/tools/README.md` to reflect the shared parsed
    tool-definition boundary
    
    ## Test plan
    
    - `cargo test -p codex-tools`
    - `cargo test -p codex-core --lib tools::spec::`
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15944).
    * #15953
    * __->__ #15944
  • codex-tools: extract MCP schema adapters (#15928)
    ## Why
    
    `codex-tools` already owns the shared tool input schema model and parser
    from the first extraction step, but `core/src/tools/spec.rs` still owned
    the MCP-specific adapter that normalizes `rmcp::model::Tool` schemas and
    wraps `structuredContent` into the call result output schema.
    
    Keeping that adapter in `codex-core` means the reusable MCP schema path
    is still split across crates, and the unit tests for that logic stay
    anchored in `codex-core` even though the runtime orchestration does not
    need to move yet.
    
    This change takes the next small step by moving the reusable MCP schema
    adapter into `codex-tools` while leaving `ResponsesApiTool` assembly in
    `codex-core`.
    
    ## What changed
    
    - added `tools/src/mcp_tool.rs` and sibling
    `tools/src/mcp_tool_tests.rs`
    - introduced `ParsedMcpTool`, `parse_mcp_tool()`, and
    `mcp_call_tool_result_output_schema()` in `codex-tools`
    - updated `core/src/tools/spec.rs` to consume parsed MCP tool parts from
    `codex-tools`
    - removed the now-redundant MCP schema unit tests from
    `core/src/tools/spec_tests.rs`
    - expanded `codex-rs/tools/README.md` to describe this second migration
    step
    
    ## Test plan
    
    - `cargo test -p codex-tools`
    - `cargo test -p codex-core --lib tools::spec::`
  • codex-tools: extract shared tool schema parsing (#15923)
    ## Why
    
    `parse_tool_input_schema` and the supporting `JsonSchema` model were
    living in `core/src/tools/spec.rs`, but they already serve callers
    outside `codex-core`.
    
    Keeping that shared schema parsing logic inside `codex-core` makes the
    crate boundary harder to reason about and works against the guidance in
    `AGENTS.md` to avoid growing `codex-core` when reusable code can live
    elsewhere.
    
    This change takes the first extraction step by moving the schema parsing
    primitive into its own crate while keeping the rest of the tool-spec
    assembly in `codex-core`.
    
    ## What changed
    
    - added a new `codex-tools` crate under `codex-rs/tools`
    - moved the shared tool input schema model and sanitizer/parser into
    `tools/src/json_schema.rs`
    - kept `tools/src/lib.rs` exports-only, with the module-level unit tests
    split into `json_schema_tests.rs`
    - updated `codex-core` to use `codex-tools::JsonSchema` and re-export
    `parse_tool_input_schema`
    - updated `codex-app-server` dynamic tool validation to depend on
    `codex-tools` directly instead of reaching through `codex-core`
    - wired the new crate into the Cargo workspace and Bazel build graph
  • feat: clean spawn v1 (#15861)
    Avoid the usage of path in the v1 spawn
  • [apps][tool_suggest] Remove tool_suggest's dependency on tool search. (#14856)
    - [x] Remove tool_suggest's dependency on tool search.
  • chore: remove grep_files handler (#15775)
    # 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.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • [plugins] Add a flag for tool search. (#15722)
    - [x] Add a flag for tool search.
  • [plugins] Additional gating for tool suggest and apps. (#15573)
    - [x] Additional gating for tool suggest and apps.
  • feat: communication pattern v2 (#15647)
    See internal communication
  • feat: list agents for sub-agent v2 (#15621)
    Add a `list_agents` for multi-agent v2, optionally path based
    
    This return the task and status of each agent in the matched path
  • feat: custom watcher for multi-agent v2 (#15576)
    The new wait tool just returns `Wait timed out.` or `Wait completed.`.
    The actual content is done through the notification watcher
  • Code mode on v8 (#15276)
    Moves Code Mode to a new crate with no dependencies on codex. This
    create encodes the code mode semantics that we want for lifetime,
    mounting, tool calling.
    
    The model-facing surface is mostly unchanged. `exec` still runs raw
    JavaScript, `wait` still resumes or terminates a `cell_id`, nested tools
    are still available through `tools.*`, and helpers like `text`, `image`,
    `store`, `load`, `notify`, `yield_control`, and `exit` still exist.
    
    The major change is underneath that surface:
    
    - Old code mode was an external Node runtime.
    - New code mode is an in-process V8 runtime embedded directly in Rust.
    - Old code mode managed cells inside a long-lived Node runner process.
    - New code mode manages cells in Rust, with one V8 runtime thread per
    active `exec`.
    - Old code mode used JSON protocol messages over child stdin/stdout plus
    Node worker-thread messages.
    - New code mode uses Rust channels and direct V8 callbacks/events.
    
    This PR also fixes the two migration regressions that fell out of that
    substrate change:
    
    - `wait { terminate: true }` now waits for the V8 runtime to actually
    stop before reporting termination.
    - synchronous top-level `exit()` now succeeds again instead of surfacing
    as a script error.
    
    ---
    
    - `core/src/tools/code_mode/*` is now mostly an adapter layer for the
    public `exec` / `wait` tools.
    - `code-mode/src/service.rs` owns cell sessions and async control flow
    in Rust.
    - `code-mode/src/runtime/*.rs` owns the embedded V8 isolate and
    JavaScript execution.
    - each `exec` spawns a dedicated runtime thread plus a Rust
    session-control task.
    - helper globals are installed directly into the V8 context instead of
    being injected through a source prelude.
    - helper modules like `tools.js` and `@openai/code_mode` are synthesized
    through V8 module resolution callbacks in Rust.
    
    ---
    
    Also added a benchmark for showing the speed of init and use of a code
    mode env:
    ```
    $ cargo bench -p codex-code-mode --bench exec_overhead -- --samples 30 --warm-iterations 25 --tool-counts 0,32,128
    Finished [`bench` profile [optimized]](https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles) target(s) in 0.18s
         Running benches/exec_overhead.rs (target/release/deps/exec_overhead-008c440d800545ae)
    exec_overhead: samples=30, warm_iterations=25, tool_counts=[0, 32, 128]
    scenario       tools samples    warmups      iters      mean/exec       p95/exec       rssΔ p50       rssΔ max
    cold_exec          0      30          0          1         1.13ms         1.20ms        8.05MiB        8.06MiB
    warm_exec          0      30          1         25       473.43us       512.49us      912.00KiB        1.33MiB
    cold_exec         32      30          0          1         1.03ms         1.15ms        8.08MiB        8.11MiB
    warm_exec         32      30          1         25       509.73us       545.76us      960.00KiB        1.30MiB
    cold_exec        128      30          0          1         1.14ms         1.19ms        8.30MiB        8.34MiB
    warm_exec        128      30          1         25       575.08us       591.03us      736.00KiB      864.00KiB
    memory uses a fresh-process max RSS delta for each scenario
    ```
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat: change multi-agent to use path-like system instead of uuids (#15313)
    This PR add an URI-based system to reference agents within a tree. This
    comes from a sync between research and engineering.
    
    The main agent (the one manually spawned by a user) is always called
    `/root`. Any sub-agent spawned by it will be `/root/agent_1` for example
    where `agent_1` is chosen by the model.
    
    Any agent can contact any agents using the path.
    
    Paths can be used either in absolute or relative to the calling agents
    
    Resume is not supported for now on this new path
  • Split features into codex-features crate (#15253)
    - Split the feature system into a new `codex-features` crate.
    - Cut `codex-core` and workspace consumers over to the new config and
    warning APIs.
    
    Co-authored-by: Ahmed Ibrahim <219906144+aibrahim-oai@users.noreply.github.com>
    Co-authored-by: Codex <noreply@openai.com>
  • add specific tool guidance for Windows destructive commands (#15207)
    updated Windows shell/unified_exec tool descriptions:
    
    `exec_command`
    ```text
    Runs a command in a PTY, returning output or a session ID for ongoing interaction.
    
    Windows safety rules:
    - Do not compose destructive filesystem commands across shells. Do not enumerate paths in PowerShell and then pass them to `cmd /c`, batch builtins, or another shell for deletion or moving. Use one shell end-to-end, prefer native PowerShell cmdlets such as `Remove-Item` / `Move-Item` with `-LiteralPath`, and avoid string-built shell commands for file operations.
    - Before any recursive delete or move on Windows, verify the resolved absolute target paths stay within the intended workspace or explicitly named target directory. Never issue a recursive delete or move against a computed path if the final target has not been checked.
    ```
    
    `shell`
    ```text
    Runs a Powershell command (Windows) and returns its output. Arguments to `shell` will be passed to CreateProcessW(). Most commands should be prefixed with ["powershell.exe", "-Command"].
    
    Examples of valid command strings:
    
    - ls -a (show hidden): ["powershell.exe", "-Command", "Get-ChildItem -Force"]
    - recursive find by name: ["powershell.exe", "-Command", "Get-ChildItem -Recurse -Filter *.py"]
    - recursive grep: ["powershell.exe", "-Command", "Get-ChildItem -Path C:\\myrepo -Recurse | Select-String -Pattern 'TODO' -CaseSensitive"]
    - ps aux | grep python: ["powershell.exe", "-Command", "Get-Process | Where-Object { $_.ProcessName -like '*python*' }"]
    - setting an env var: ["powershell.exe", "-Command", "$env:FOO='bar'; echo $env:FOO"]
    - running an inline Python script: ["powershell.exe", "-Command", "@'\nprint('Hello, world!')\n'@ | python -"]
    
    Windows safety rules:
    - Do not compose destructive filesystem commands across shells. Do not enumerate paths in PowerShell and then pass them to `cmd /c`, batch builtins, or another shell for deletion or moving. Use one shell end-to-end, prefer native PowerShell cmdlets such as `Remove-Item` / `Move-Item` with `-LiteralPath`, and avoid string-built shell commands for file operations.
    - Before any recursive delete or move on Windows, verify the resolved absolute target paths stay within the intended workspace or explicitly named target directory. Never issue a recursive delete or move against a computed path if the final target has not been checked.
    ```
    
    `shell_command`
    ```text
    Runs a Powershell command (Windows) and returns its output.
    
    Examples of valid command strings:
    
    - ls -a (show hidden): "Get-ChildItem -Force"
    - recursive find by name: "Get-ChildItem -Recurse -Filter *.py"
    - recursive grep: "Get-ChildItem -Path C:\\myrepo -Recurse | Select-String -Pattern 'TODO' -CaseSensitive"
    - ps aux | grep python: "Get-Process | Where-Object { $_.ProcessName -like '*python*' }"
    - setting an env var: "$env:FOO='bar'; echo $env:FOO"
    - running an inline Python script: "@'\nprint('Hello, world!')\n'@ | python -"
    
    Windows safety rules:
    - Do not compose destructive filesystem commands across shells. Do not enumerate paths in PowerShell and then pass them to `cmd /c`, batch builtins, or another shell for deletion or moving. Use one shell end-to-end, prefer native PowerShell cmdlets such as `Remove-Item` / `Move-Item` with `-LiteralPath`, and avoid string-built shell commands for file operations.
    - Before any recursive delete or move on Windows, verify the resolved absolute target paths stay within the intended workspace or explicitly named target directory. Never issue a recursive delete or move against a computed path if the final target has not been checked.
    ```
  • feat: add graph representation of agent network (#15056)
    Add a representation of the agent graph. This is now used for:
    * Cascade close agents (when I close a parent, it close the kids)
    * Cascade resume (oposite)
    
    Later, this will also be used for post-compaction stuffing of the
    context
    
    Direct fix for: https://github.com/openai/codex/issues/14458
  • Return image URL from view_image tool (#15072)
    Cleanup image semantics in code mode.
    
    `view_image` now returns `{image_url:string, details?: string}` 
    
    `image()` now allows both string parameter and `{image_url:string,
    details?: string}`
  • Rename exec_wait tool to wait (#14983)
    Summary
    - document that code mode only exposes `exec` and the renamed `wait`
    tool
    - update code mode tool spec and descriptions to match the new tool name
    - rename tests and helper references from `exec_wait` to `wait`
    
    Testing
    - Not run (not requested)
  • [plugins] Support plugin installation elicitation. (#14896)
    It now supports:
    
    - Connectors that are from installed and enabled plugins that are not
    installed yet
    - Plugins that are on the allowlist that are not installed yet.
  • Apply argument comment lint across codex-rs (#14652)
    ## Why
    
    Once the repo-local lint exists, `codex-rs` needs to follow the
    checked-in convention and CI needs to keep it from drifting. This commit
    applies the fallback `/*param*/` style consistently across existing
    positional literal call sites without changing those APIs.
    
    The longer-term preference is still to avoid APIs that require comments
    by choosing clearer parameter types and call shapes. This PR is
    intentionally the mechanical follow-through for the places where the
    existing signatures stay in place.
    
    After rebasing onto newer `main`, the rollout also had to cover newly
    introduced `tui_app_server` call sites. That made it clear the first cut
    of the CI job was too expensive for the common path: it was spending
    almost as much time installing `cargo-dylint` and re-testing the lint
    crate as a representative test job spends running product tests. The CI
    update keeps the full workspace enforcement but trims that extra
    overhead from ordinary `codex-rs` PRs.
    
    ## What changed
    
    - keep a dedicated `argument_comment_lint` job in `rust-ci`
    - mechanically annotate remaining opaque positional literals across
    `codex-rs` with exact `/*param*/` comments, including the rebased
    `tui_app_server` call sites that now fall under the lint
    - keep the checked-in style aligned with the lint policy by using
    `/*param*/` and leaving string and char literals uncommented
    - cache `cargo-dylint`, `dylint-link`, and the relevant Cargo
    registry/git metadata in the lint job
    - split changed-path detection so the lint crate's own `cargo test` step
    runs only when `tools/argument-comment-lint/*` or `rust-ci.yml` changes
    - continue to run the repo wrapper over the `codex-rs` workspace, so
    product-code enforcement is unchanged
    
    Most of the code changes in this commit are intentionally mechanical
    comment rewrites or insertions driven by the lint itself.
    
    ## Verification
    
    - `./tools/argument-comment-lint/run.sh --workspace`
    - `cargo test -p codex-tui-app-server -p codex-tui`
    - parsed `.github/workflows/rust-ci.yml` locally with PyYAML
    
    ---
    
    * -> #14652
    * #14651
  • [apps] Add tool call meta. (#14647)
    - [x] Add resource_uri and other things to _meta to shortcut resource
    lookup and speed things up.
  • refactor: make unified-exec zsh-fork state explicit (#14633)
    ## Why
    
    The unified-exec path was carrying zsh-fork state in a partially
    flattened way.
    
    First, the decision about whether zsh-fork was active came from feature
    selection in `ToolsConfig`, while the real prerequisites lived in
    session state. That left the handler and runtime defending against
    partially configured cases later.
    
    Second, once zsh-fork was active, its two runtime-only paths were
    threaded through the runtime as separate arguments even though they form
    one coherent piece of configuration.
    
    This change keeps unified-exec on a single session-derived source of
    truth and bundles the zsh-fork-specific paths into a named config type
    so the runtime can pass them around as one unit.
    
    In particular, this PR introduces this enum so the `ZshFork` variant can
    carry the appropriate state with it:
    
    ```rust
    #[derive(Debug, Clone, Eq, PartialEq)]
    pub enum UnifiedExecShellMode {
        Direct,
        ZshFork(ZshForkConfig),
    }
    
    #[derive(Debug, Clone, Eq, PartialEq)]
    pub struct ZshForkConfig {
        pub(crate) shell_zsh_path: AbsolutePathBuf,
        pub(crate) main_execve_wrapper_exe: AbsolutePathBuf,
    }
    ```
    
    This cleanup was done in preparation for
    https://github.com/openai/codex/pull/13432.
    
    ## What Changed
    
    - Replaced the feature-only `UnifiedExecBackendConfig` split with
    `UnifiedExecShellMode` in `codex-rs/core/src/tools/spec.rs`.
    - Derived the unified-exec mode from session-backed inputs when building
    turn `ToolsConfig`, and preserved that mode across model switches and
    review turns.
    - Introduced `ZshForkConfig`, which stores the resolved zsh-fork
    `AbsolutePathBuf` values for the configured `zsh` binary and `execve`
    wrapper.
    - Threaded `ZshForkConfig` through unified-exec command construction and
    the zsh-fork preparation path so zsh-fork-specific runtime code consumes
    a single config object instead of separate path arguments.
    - Added focused tests for constructing zsh-fork mode only when session
    prerequisites are available, and updated the zsh-fork expectations to be
    target-platform aware.
    
    ## Testing
    
    - `cargo test -p codex-core zsh_fork --lib`
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/14633).
    * #13432
    * __->__ #14633
  • Rename multi-agent wait tool to wait_agent (#14631)
    - rename the multi-agent tool name the model sees to wait_agent
    - update the model-facing prompts and tool descriptions to match
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Add code_mode_only feature (#14617)
    Summary
    - add the code_mode_only feature flag/config schema and wire its
    dependency on code_mode
    - update code mode tool descriptions to list nested tools with detailed
    headers
    - restrict available tools for prompt and exec descriptions when
    code_mode_only is enabled and test the behavior
    
    Testing
    - Not run (not requested)
  • code_mode: Move exec params from runtime declarations to @pragma (#14511)
    This change moves code_mode exec session settings out of the runtime API
    and into an optional first-line pragma, so instead of calling runtime
    helpers like set_yield_time() or set_max_output_tokens_per_exec_call(),
    the model can write // @exec: {"yield_time_ms": ...,
    "max_output_tokens": ...} at the top of the freeform exec source. Rust
    now parses that pragma before building the source, validates it, and
    passes the values directly in the exec start message to the code-mode
    broker, which applies them at session start without any worker-runtime
    mutation path. The @openai/code_mode module no longer exposes those
    setter functions, the docs and grammar were updated to describe the
    pragma form, and the existing code_mode tests were converted to use
    pragma-based configuration instead.
  • Add typed multi-agent tool outputs (#14536)
    ## Summary
    - return typed `ToolOutput` values from the multi-agent handlers instead
    of plain `FunctionToolOutput`
    - keep the regular function-call response shape as JSON text while
    exposing structured values to code mode
    - add output schemas for `spawn_agent`, `send_input`, `resume_agent`,
    `wait`, and `close_agent`
    
    ## Verification
    - `just fmt`
    - focused multi-agent and integration tests passed earlier in this
    branch during iteration
    - after the final edit, I only reran formatting before opening this PR
  • Split multi-agent handlers per tool (#14535)
    Summary
    - move the existing multi-agent handler logic into each tool-specific
    handler and inline helper implementations
    - remove the old central dispatcher now that each handler encapsulates
    its own behavior
    - adjust handler specs and tests to match the new structure without
    macros
    
    Testing
    - Not run (not requested)
  • Rename exec session IDs to cell IDs (#14510)
    - Update the code-mode executor, wait handler, and protocol plumbing to
    use cell IDs instead of session IDs for node communication
    - Switch tool metadata, wait description, and suite tests to refer to
    cell IDs so user-visible messages match the new terminology
    
    **Testing**
    - Not run (not requested)
  • Do not allow unified_exec for sandboxed scenarios on Windows (#14398)
    as reported in https://github.com/openai/codex/issues/14367 users can
    explicitly enable unified_exec which will bypass the sandbox even when
    it should be enabled.
    
    Until we support unified_exec with the Windows Sandbox, we will disallow
    it unless the sandbox is disabled
  • Cleanup code_mode tool descriptions (#14480)
    Move to separate files and clarify a bit.
  • Move code mode tool files under tools/code_mode and split functionality (#14476)
    - **Summary**
    - migrate the code mode handler, service, worker, process, runner, and
    bridge assets into the `tools/code_mode` module tree
    - split Execution, protocol, and handler logic into dedicated files and
    relocate the tool definition into `code_mode/spec.rs`
    - update core references and tests to stitch the new organization
    together
    - **Testing**
      - Not run (not requested)
  • fix: move inline codex-rs/core unit tests into sibling files (#14444)
    ## Why
    PR #13783 moved the `codex.rs` unit tests into `codex_tests.rs`. This
    applies the same extraction pattern across the rest of `codex-rs/core`
    so the production modules stay focused on runtime code instead of large
    inline test blocks.
    
    Keeping the tests in sibling files also makes follow-up edits easier to
    review because product changes no longer have to share a file with
    hundreds or thousands of lines of test scaffolding.
    
    ## What changed
    - replaced each inline `mod tests { ... }` in `codex-rs/core/src/**`
    with a path-based module declaration
    - moved each extracted unit test module into a sibling `*_tests.rs`
    file, using `mod_tests.rs` for `mod.rs` modules
    - preserved the existing `cfg(...)` guards and module-local structure so
    the refactor remains structural rather than behavioral
    
    ## Testing
    - `cargo test -p codex-core --lib` (`1653 passed; 0 failed; 5 ignored`)
    - `just fix -p codex-core`
    - `cargo fmt --check`
    - `cargo shear`
  • Support waiting for code_mode sessions (#14295)
    ## Summary
    - persist the code mode runner process in the session-scoped code mode
    store
    - switch the runner protocol from `init` to `start` with explicit
    session ids
    - handle runner-side session processing without the init waiter queue
    
    ## Validation
    - just fmt
    - cargo check -p codex-core
    - node --check codex-rs/core/src/tools/code_mode_runner.cjs
  • Clarify spawn agent authorization (#14432)
    - Clarify that spawn_agent requires explicit user permission for
    delegation or parallel agent work.
    - Add a regression test covering the new description text.
  • [apps] Add tool_suggest tool. (#14287)
    - [x] Add tool_suggest tool.
    - [x] Move chatgpt/src/connectors.rs and core/src/connectors.rs into a
    dedicated mod so that we have all the logic and global cache in one
    place.
    - [x] Update TUI app link view to support rendering the installation
    view for mcp elicitation.
    
    ---------
    
    Co-authored-by: Shaqayeq <shaqayeq@openai.com>
    Co-authored-by: Eric Traut <etraut@openai.com>
    Co-authored-by: pakrym-oai <pakrym@openai.com>
    Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
    Co-authored-by: guinness-oai <guinness@openai.com>
    Co-authored-by: Eugene Brevdo <ebrevdo@users.noreply.github.com>
    Co-authored-by: Charlie Guo <cguo@openai.com>
    Co-authored-by: Fouad Matin <fouad@openai.com>
    Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
    Co-authored-by: xl-openai <xl@openai.com>
    Co-authored-by: alexsong-oai <alexsong@openai.com>
    Co-authored-by: Owen Lin <owenlin0@gmail.com>
    Co-authored-by: sdcoffey <stevendcoffey@gmail.com>
    Co-authored-by: Codex <noreply@openai.com>
    Co-authored-by: Won Park <won@openai.com>
    Co-authored-by: Dylan Hurd <dylan.hurd@openai.com>
    Co-authored-by: celia-oai <celia@openai.com>
    Co-authored-by: gabec-openai <gabec@openai.com>
    Co-authored-by: joeytrasatti-openai <joey.trasatti@openai.com>
    Co-authored-by: Leo Shimonaka <leoshimo@openai.com>
    Co-authored-by: Rasmus Rygaard <rasmus@openai.com>
    Co-authored-by: maja-openai <163171781+maja-openai@users.noreply.github.com>
    Co-authored-by: pash-openai <pash@openai.com>
    Co-authored-by: Josh McKinney <joshka@openai.com>
  • feat: search_tool migrate to bring you own tool of Responses API (#14274)
    ## Why
    
    to support a new bring your own search tool in Responses
    API(https://developers.openai.com/api/docs/guides/tools-tool-search#client-executed-tool-search)
    we migrating our bm25 search tool to use official way to execute search
    on client and communicate additional tools to the model.
    
    ## What
    - replace the legacy `search_tool_bm25` flow with client-executed
    `tool_search`
    - add protocol, SSE, history, and normalization support for
    `tool_search_call` and `tool_search_output`
    - return namespaced Codex Apps search results and wire namespaced
    follow-up tool calls back into MCP dispatch
  • Let models opt into original image detail (#14175)
    ## Summary
    
    This PR narrows original image detail handling to a single opt-in
    feature:
    
    - `image_detail_original` lets the model request `detail: "original"` on
    supported models
    - Omitting `detail` preserves the default resized behavior
    
    The model only sees `detail: "original"` guidance when the active model
    supports it:
    
    - JS REPL instructions include the guidance and examples only on
    supported models
    - `view_image` only exposes a `detail` parameter when the feature and
    model can use it
    
    The image detail API is intentionally narrow and consistent across both
    paths:
    
    - `view_image.detail` supports only `"original"`; otherwise omit the
    field
    - `codex.emitImage(..., detail)` supports only `"original"`; otherwise
    omit the field
    - Unsupported explicit values fail clearly at the API boundary instead
    of being silently reinterpreted
    - Unsupported explicit `detail: "original"` requests fall back to normal
    behavior when the feature is disabled or the model does not support
    original detail
  • spawn prompt (#14362)
    # 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.