Commit Graph

19 Commits

  • Remove core MCP list tools op (#21281)
    ## Why
    
    The core `Op::ListMcpTools` request path is no longer needed. Keeping it
    around left a dead request/response surface alongside the app-server MCP
    inventory APIs that own current server status listing.
    
    ## What Changed
    
    - Removed `Op::ListMcpTools`, `EventMsg::McpListToolsResponse`, and the
    core handler that built the MCP snapshot response.
    - Removed the now-unused `codex-mcp` snapshot wrapper/export and passive
    event handling arms in rollout and MCP-server consumers.
    - Updated tests that used the old op as a synchronization hook to wait
    on existing startup/skills events, and deleted the plugin test that only
    exercised the removed listing op.
    
    ## Validation
    
    - `cargo test -p codex-protocol`
    - `cargo test -p codex-mcp`
    - `cargo test -p codex-rollout -p codex-rollout-trace -p
    codex-mcp-server`
    - `cargo test -p codex-core --test all
    pending_input::queued_inter_agent_mail`
    - `cargo test -p codex-core --test all
    rmcp_client::stdio_mcp_tool_call_includes_sandbox_state_meta`
    - `cargo test -p codex-core --test all
    rmcp_client::stdio_image_responses`
    - `just fix -p codex-core -p codex-protocol -p codex-mcp -p
    codex-rollout -p codex-rollout-trace -p codex-mcp-server`
  • core tests: build user turns from permission profiles (#20011)
    ## Summary
    - Add `turn_permission_fields()` so tests that construct `Op::UserTurn`
    directly can provide a canonical `PermissionProfile` while still filling
    the required legacy `sandbox_policy` compatibility field.
    - Migrate direct user-turn construction in core integration tests from
    `SandboxPolicy::DangerFullAccess` to `PermissionProfile::Disabled`.
    - Continue reducing direct `SandboxPolicy` usage in
    `codex-rs/core/tests`, from 41 files after #20010 to 32 files in this
    PR.
    
    ## Testing
    - `cargo check -p codex-core --tests`
    - `just fmt`
    - `just fix -p core_test_support`
    - `just fix -p codex-core`
  • permissions: make runtime config profile-backed (#19606)
    ## Why
    
    This supersedes #19391. During stack repair, GitHub marked #19391 as
    merged into a temporary stack branch rather than into `main`, so the
    runtime-config change needed a fresh PR.
    
    `PermissionProfile` is now the canonical permissions shape after #19231
    because it can distinguish `Managed`, `Disabled`, and `External`
    enforcement while also carrying filesystem rules that legacy
    `SandboxPolicy` cannot represent cleanly. Core config and session state
    still needed to accept profile-backed permissions without forcing every
    profile through the strict legacy bridge, which rejected valid runtime
    profiles such as direct write roots.
    
    The unrelated CI/test hardening that previously rode along with this PR
    has been split into #19683 so this PR stays focused on the permissions
    model migration.
    
    ## What Changed
    
    - Adds `Permissions.permission_profile` and
    `SessionConfiguration.permission_profile` as constrained runtime state,
    while keeping `sandbox_policy` as a legacy compatibility projection.
    - Introduces profile setters that keep `PermissionProfile`, split
    filesystem/network policies, and legacy `SandboxPolicy` projections
    synchronized.
    - Uses a compatibility projection for requirement checks and legacy
    consumers instead of rejecting profiles that cannot round-trip through
    `SandboxPolicy` exactly.
    - Updates config loading, config overrides, session updates, turn
    context plumbing, prompt permission text, sandbox tags, and exec request
    construction to carry profile-backed runtime permissions.
    - Preserves configured deny-read entries and `glob_scan_max_depth` when
    command/session profiles are narrowed.
    - Adds `PermissionProfile::read_only()` and
    `PermissionProfile::workspace_write()` presets that match legacy
    defaults.
    
    ## Verification
    
    - `cargo test -p codex-core direct_write_roots`
    - `cargo test -p codex-core runtime_roots_to_legacy_projection`
    - `cargo test -p codex-app-server
    requested_permissions_trust_project_uses_permission_profile_intent`
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19606).
    * #19395
    * #19394
    * #19393
    * #19392
    * __->__ #19606
  • tui: carry permission profiles on user turns (#18285)
    ## Why
    
    Per-turn permission overrides should use the same canonical profile
    abstraction as session configuration. That lets TUI submissions preserve
    exact configured permissions without round-tripping through legacy
    sandbox fields.
    
    ## What changed
    
    This adds `permission_profile` to user-turn operations, threads it
    through TUI/app-server submission paths, fills the new field in existing
    test fixtures, and adds coverage that composer submission includes the
    configured profile.
    
    ## Verification
    
    - `cargo test -p codex-tui permissions -- --nocapture`
    - `cargo test -p codex-core --test all permissions_messages --
    --nocapture`
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18285).
    * #18288
    * #18287
    * #18286
    * __->__ #18285
  • Add turn-scoped environment selections (#18416)
    ## Summary
    - add experimental turn/start.environments params for per-turn
    environment id + cwd selections
    - pass selections through core protocol ops and resolve them with
    EnvironmentManager before TurnContext creation
    - treat omitted selections as default behavior, empty selections as no
    environment, and non-empty selections as first environment/cwd as the
    turn primary
    
    ## Testing
    - ran `just fmt`
    - ran `just write-app-server-schema`
    - not run: unit tests for this stacked PR
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Update models.json (#18586)
    - Replace the active models-manager catalog with the deleted core
    catalog contents.
    - Replace stale hardcoded test model slugs with current bundled model
    slugs.
    - Keep this as a stacked change on top of the cleanup PR.
  • Revert "[codex] drain mailbox only at request boundaries" (#18325)
    ## Summary
    - Reverts PR #17749 so queued inter-agent mail can again preempt after
    reasoning/commentary output item boundaries.
    - Applies the revert to the current `codex/turn.rs` module layout and
    restores the prior pending-input test expectations/snapshots.
    
    ## Testing
    - `just fmt`
    - `cargo test -p codex-core --test all pending_input`
    - `cargo test -p codex-core` failed in unrelated
    `tools::js_repl::tests::js_repl_imported_local_files_can_access_repl_globals`:
    dotslash download hit `mktemp: mkdtemp failed ... Operation not
    permitted` in the sandbox temp dir.
    
    Co-authored-by: Codex <noreply@openai.com>
  • fix: Revert danger-full-access denylist-only mode (#17732)
    ## Summary
    
    - Reverts openai/codex#16946 and removes the danger-full-access
    denylist-only network mode.
    - Removes the corresponding config requirements, app-server
    protocol/schema, config API, TUI debug output, and network proxy
    behavior.
    - Drops stale tests that depended on the reverted mode while preserving
    newer managed allowlist-only coverage.
    
    ## Verification
    
    - `just write-app-server-schema`
    - `just fmt`
    - `cargo test -p codex-config network_requirements`
    - `cargo test -p codex-core network_proxy_spec`
    - `cargo test -p codex-core
    managed_network_proxy_decider_survives_full_access_start`
    - `cargo test -p codex-app-server map_requirements_toml_to_api`
    - `cargo test -p codex-tui debug_config_output`
    - `cargo test -p codex-app-server-protocol`
    - `just fix -p codex-config -p codex-core -p codex-app-server-protocol
    -p codex-app-server -p codex-tui`
    - `git diff --cached --check`
    
    Not run: full workspace `cargo test` (repo instructions ask for
    confirmation before that broader run).
  • [codex] drain mailbox only at request boundaries (#17749)
    This changes multi-agent v2 mailbox handling so incoming inter-agent
    messages no longer preempt an in-flight sampling stream at reasoning or
    commentary output-item boundaries.
  • Forward app-server turn clientMetadata to Responses (#16009)
    ## Summary
    App-server v2 already receives turn-scoped `clientMetadata`, but the
    Rust app-server was dropping it before the outbound Responses request.
    This change keeps the fix lightweight by threading that metadata through
    the existing turn-metadata path rather than inventing a new transport.
    
    ## What we're trying to do and why
    We want turn-scoped metadata from the app-server protocol layer,
    especially fields like Hermes/GAAS run IDs, to survive all the way to
    the actual Responses API request so it is visible in downstream
    websocket request logging and analytics.
    
    The specific bug was:
    - app-server protocol uses camelCase `clientMetadata`
    - Responses transport already has an existing turn metadata carrier:
    `x-codex-turn-metadata`
    - websocket transport already rewrites that header into
    `request.request_body.client_metadata["x-codex-turn-metadata"]`
    - but the Rust app-server never parsed or stored `clientMetadata`, so
    nothing from the app-server request was making it into that existing
    path
    
    This PR fixes that without adding a new header or a second metadata
    channel.
    
    ## How we did it
    ### Protocol surface
    - Add optional `clientMetadata` to v2 `TurnStartParams` and
    `TurnSteerParams`
    - Regenerate the JSON schema / TypeScript fixtures
    - Update app-server docs to describe the field and its behavior
    
    ### Runtime plumbing
    - Add a dedicated core op for app-server user input carrying turn-scoped
    metadata: `Op::UserInputWithClientMetadata`
    - Wire `turn/start` and `turn/steer` through that op / signature path
    instead of dropping the metadata at the message-processor boundary
    - Store the metadata in `TurnMetadataState`
    
    ### Transport behavior
    - Reuse the existing serialized `x-codex-turn-metadata` payload
    - Merge the new app-server `clientMetadata` into that JSON additively
    - Do **not** replace built-in reserved fields already present in the
    turn metadata payload
    - Keep websocket behavior unchanged at the outer shape level: it still
    sends only `client_metadata["x-codex-turn-metadata"]`, but that JSON
    string now contains the merged fields
    - Keep HTTP fallback behavior unchanged except that the existing
    `x-codex-turn-metadata` header now includes the merged fields too
    
    ### Request shape before / after
    Before, a websocket `response.create` looked like:
    ```json
    {
      "type": "response.create",
      "client_metadata": {
        "x-codex-turn-metadata": "{\"session_id\":\"...\",\"turn_id\":\"...\"}"
      }
    }
    ```
    Even if the app-server caller supplied `clientMetadata`, it was not
    represented there.
    
    After, the same request shape is preserved, but the serialized payload
    now includes the new turn-scoped fields:
    ```json
    {
      "type": "response.create",
      "client_metadata": {
        "x-codex-turn-metadata": "{\"session_id\":\"...\",\"turn_id\":\"...\",\"fiber_run_id\":\"fiber-start-123\",\"origin\":\"gaas\"}"
      }
    }
    ```
    
    ## Validation
    ### Targeted tests added / updated
    - protocol round-trip coverage for `clientMetadata` on `turn/start` and
    `turn/steer`
    - protocol round-trip coverage for `Op::UserInputWithClientMetadata`
    - `TurnMetadataState` merge test proving client metadata is added
    without overwriting reserved built-in fields
    - websocket request-shape test proving outbound `response.create`
    contains merged metadata inside
    `client_metadata["x-codex-turn-metadata"]`
    - app-server integration tests proving:
    - `turn/start` forwards `clientMetadata` into the outbound Responses
    request path
      - websocket warmup + real turn request both behave correctly
      - `turn/steer` updates the follow-up request metadata
    
    ### Commands run
    - `just write-app-server-schema`
    - `cargo test -p codex-app-server-protocol`
    - `cargo test -p codex-protocol`
    - `cargo test -p codex-core
    turn_metadata_state_merges_client_metadata_without_replacing_reserved_fields
    --lib`
    - `cargo test -p codex-core --test all
    responses_websocket_preserves_custom_turn_metadata_fields`
    - `cargo test -p codex-app-server --test all client_metadata`
    - `cargo test -p codex-app-server --test all
    turn_start_forwards_client_metadata_to_responses_websocket_request_body_v2
    -- --nocapture`
    - `just fmt`
    - `just fix -p codex-core -p codex-protocol -p codex-app-server-protocol
    -p codex-app-server`
    - `just fix -p codex-exec -p codex-tui-app-server`
    - `just argument-comment-lint`
    
    ### Full suite note
    `cargo test` in `codex-rs` still fails in:
    -
    `suite::v2::turn_interrupt::turn_interrupt_resolves_pending_command_approval_request`
    
    I verified that same failure on a clean detached `HEAD` worktree with an
    isolated `CARGO_TARGET_DIR`, so it is not caused by this patch.
  • [codex] Defer steering until after sampling the model post-compaction (#17163)
    ## Summary
    - keep pending steered input buffered until the active user prompt has
    received a model response
    - keep steering pending across auto-compact when there is real
    model/tool continuation to resume
    - allow queued steering to follow compaction immediately when the prior
    model response was already final
    - keep pending-input follow-up owned by `run_turn` instead of folding it
    into `SamplingRequestResult`
    - add regression coverage for mid-turn compaction, final-response
    compaction, and compaction triggered before the next request after tool
    output
    
    ## Root Cause
    Steered input was drained at the top of every `run_turn` loop. After
    auto-compaction, the loop continued and immediately appended any pending
    steer after the compact summary, making a queued prompt look like the
    newest task instead of letting the model first resume interrupted
    model/tool work.
    
    ## Implementation Notes
    This patch keeps the follow-up signals separated:
    
    - `SamplingRequestResult.needs_follow_up` means model/tool continuation
    is needed
    - `sess.has_pending_input().await` means queued user steering exists
    - `run_turn` computes the combined loop condition from those two signals
    
    In `run_turn`:
    
    ```rust
    let has_pending_input = sess.has_pending_input().await;
    let needs_follow_up = model_needs_follow_up || has_pending_input;
    ```
    
    After auto-compact we choose whether the next request may drain
    steering:
    
    ```rust
    can_drain_pending_input = !model_needs_follow_up;
    ```
    
    That means:
    
    - model/tool continuation + pending steer: compact -> resume once
    without draining steer
    - completed model answer + pending steer: compact -> drain/send the
    steer immediately
    - fresh user prompt: do not drain steering before the model has answered
    the prompt once
    
    The drain is still only `sess.get_pending_input().await`; when
    `can_drain_pending_input` is false, core uses an empty local vec and
    leaves the steer pending in session state.
    
    ## Validation
    - PASS `cargo test -p codex-core --test all steered_user_input --
    --nocapture`
    - PASS `just fmt`
    - PASS `git diff --check`
    - NOT PASSING HERE `just fix -p codex-core` currently stops before
    linting this change on an unrelated mainline test-build error:
    `core/src/tools/spec_tests.rs` initializes `ToolsConfigParams` without
    `image_generation_tool_auth_allowed`; this PR does not touch that file.
  • [codex] reduce module visibility (#16978)
    ## Summary
    - reduce public module visibility across Rust crates, preferring private
    or crate-private modules with explicit crate-root public exports
    - update external call sites and tests to use the intended public crate
    APIs instead of reaching through module trees
    - add the module visibility guideline to AGENTS.md
    
    ## Validation
    - `cargo check --workspace --all-targets --message-format=short` passed
    before the final fix/format pass
    - `just fix` completed successfully
    - `just fmt` completed successfully
    - `git diff --check` passed
  • Preempt mailbox mail after reasoning/commentary items (#16725)
    Send pending mailbox mail after completed reasoning or commentary items
    so follow-up requests can pick it up mid-turn.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • chore: remove codex-core public protocol/shell re-exports (#12432)
    ## Why
    
    `codex-rs/core/src/lib.rs` re-exported a broad set of types and modules
    from `codex-protocol` and `codex-shell-command`. That made it easy for
    workspace crates to import those APIs through `codex-core`, which in
    turn hides dependency edges and makes it harder to reduce compile-time
    coupling over time.
    
    This change removes those public re-exports so call sites must import
    from the source crates directly. Even when a crate still depends on
    `codex-core` today, this makes dependency boundaries explicit and
    unblocks future work to drop `codex-core` dependencies where possible.
    
    ## What Changed
    
    - Removed public re-exports from `codex-rs/core/src/lib.rs` for:
    - `codex_protocol::protocol` and related protocol/model types (including
    `InitialHistory`)
      - `codex_protocol::config_types` (`protocol_config_types`)
    - `codex_shell_command::{bash, is_dangerous_command, is_safe_command,
    parse_command, powershell}`
    - Migrated workspace Rust call sites to import directly from:
      - `codex_protocol::protocol`
      - `codex_protocol::config_types`
      - `codex_protocol::models`
      - `codex_shell_command`
    - Added explicit `Cargo.toml` dependencies (`codex-protocol` /
    `codex-shell-command`) in crates that now import those crates directly.
    - Kept `codex-core` internal modules compiling by using `pub(crate)`
    aliases in `core/src/lib.rs` (internal-only, not part of the public
    API).
    - Updated the two utility crates that can already drop a `codex-core`
    dependency edge entirely:
      - `codex-utils-approval-presets`
      - `codex-utils-cli`
    
    ## Verification
    
    - `cargo test -p codex-utils-approval-presets`
    - `cargo test -p codex-utils-cli`
    - `cargo check --workspace --all-targets`
    - `just clippy`
  • Fix pending input test waiting logic (#11322)
    ## Summary
    - remove redundant user message wait that could time out and cause
    flakiness
    - rely on the existing turn-complete wait to ensure the follow-up
    request is observed
    
    ## Testing
    - Not run (not requested)
  • Persist pending input user events (#10656)
    - Persist user-message events for mid-turn injected input by emitting
    user message turn items when pending input is recorded.
  • Add text element metadata to types (#9235)
    Initial type tweaking PR to make the diff of
    https://github.com/openai/codex/pull/9116 smaller
    
    This should not change any behavior, just adds some fields to types