Commit Graph

10 Commits

  • [codex] add configurable token budget compaction reminder (#29255)
    ## Why
    
    The token-budget feature reports coarse remaining-context milestones,
    but it does not give the model a configurable wrap-up prompt before
    automatic compaction. A strict threshold-crossing check can also miss
    resumed or reconfigured windows that are already inside the threshold.
    
    ## What changed
    
    - Add structured `[features.token_budget]` configuration for an absolute
    `reminder_threshold_tokens` and bounded `reminder_message_template`;
    `{n_remaining}` is expanded when the reminder is delivered.
    - Compute remaining tokens against the next effective auto-compaction
    boundary, including scoped `body_after_prefix` accounting and the full
    context-window limit.
    - Make reminder delivery level-triggered before and after sampling, with
    one-shot state owned by `AutoCompactWindow` and re-armed on compaction,
    `new_context`, restore, or history replacement.
    - Leave the existing initial full-window token-budget context, 25/50/75%
    notices, and token-budget tools unchanged.
    - Persist the resolved feature configuration in the session config lock
    and regenerate the config schema.
    
    ## Validation
    
    - `just test -p codex-core token_budget`
    - `just test -p codex-core
    token_budget_reminder_emits_after_crossing_compaction_threshold`
    - `just test -p codex-core auto_compact_window`
    - `just test -p codex-core
    lock_contains_prompts_and_materializes_features`
    - `just test -p codex-features`
    - `just test -p codex-config`
  • Add Config for Time Reminders (varlatency 1/n) (#28822)
    ## Summary
    
    Example:
    
    > [features.current_time_reminder]
    enabled = true
    reminder_interval_model_requests = 1
    clock_source = "system"
    
    ## Testing
    
    - `just test -p codex-core varlatency`
    - `just test -p codex-core
    lock_contains_prompts_and_materializes_features`
    - `just fix -p codex-core -p codex-config -p codex-features`
  • [codex] add rollout token budget configuration (varlength 1/N) (#28746)
    ## What
    
    This PR defines the structured configuration contract for shared rollout
    token budgets (across ALL agent threads under 1 rollout).
    
    ```toml
    [features.rollout_budget]
    enabled = true
    limit_tokens = 100000
    reminder_interval_tokens = 10000
    sampling_token_weight = 1.0
    prefill_token_weight = 0.1
    ```
    
    The reminder interval defaults to 10% of the rollout limit. Sampling and
    prefill weights default to `1.0`.
    
    ## Scope
    
    This PR only defines and validates configuration. It does not track
    usage, inject reminders, or stop a rollout. Accounting and reminders are
    implemented in the stacked follow-up #28494.
    
    The existing `token_budget` feature remains unchanged. `rollout_budget`
    has its own feature key and configuration type.
    
    ## Tests
    
    The config test verifies that the structured fields resolve into
    `RolloutBudgetConfig` and do not enable the existing `token_budget`
    feature.
    
    Local checks:
    
    - `just write-config-schema`
    - `just test -p codex-core load_config_resolves_rollout_budget`
    - `cargo check -p codex-thread-manager-sample`
    - `git diff --check`
    
    The full workspace test suite was not run locally.
  • Use plugin-service MCP as the hosted plugin runtime (#27198)
    ## Stack
    
    - Base: #27191
    - This PR is the third vertical and should be reviewed against
    `jif/external-plugins-2`, not `main`.
    
    ## Why
    
    #27191 moves the host-owned Apps MCP registration behind an extension
    contributor, but deliberately preserves the existing endpoint-selection
    feature while that contribution contract lands. App-server can therefore
    resolve the server through extensions, yet the hosted plugin endpoint is
    still selected through temporary `apps_mcp_path_override` plumbing.
    
    That is not the long-term plugin model. A plugin can bundle skills,
    connectors, MCP servers, and hooks, and those components do not all need
    the same source or execution environment. In particular, an
    authenticated HTTP MCP server can expose plugin capabilities directly
    from a backend without an executor or an orchestrator filesystem.
    
    This PR completes that hosted vertical. App-server's MCP extension now
    owns the aggregate hosted plugin runtime at `/ps/mcp`. Connector actions
    continue to arrive as MCP tools, while backend-provided skills arrive as
    MCP resources and use Codex's existing resource list/read paths. No
    second backend client, skill filesystem, or generic plugin activation
    framework is introduced.
    
    The backend route remains the hosted implementation. This change
    replaces Codex's temporary endpoint-selection mechanism, not the service
    behind the endpoint.
    
    ## What changed
    
    ### Hosted plugin runtime
    
    The MCP extension now contributes `codex_apps` as the hosted plugin
    runtime rather than as a configurable Apps endpoint:
    
    - `https://chatgpt.com` resolves to
    `https://chatgpt.com/backend-api/ps/mcp`;
    - a bare custom ChatGPT base resolves to `/api/codex/ps/mcp`;
    - the existing product-SKU header and ChatGPT authentication behavior
    are preserved;
    - executor availability is never consulted for this streamable HTTP
    transport.
    
    The same MCP connection carries both component shapes supported by the
    hosted endpoint:
    
    - connector actions are discovered and invoked as MCP tools;
    - hosted skills are enumerated and read as MCP resources through the
    existing `list_mcp_resources` and `read_mcp_resource` paths.
    
    This keeps component access in the subsystem that already owns the
    protocol instead of downloading backend skills into an orchestrator
    filesystem or inventing a parallel hosted-skill client.
    
    ### Explicit runtime ordering
    
    `McpManager` now resolves the reserved `codex_apps` entry in three
    ordered phases:
    
    1. install the legacy Apps fallback for compatibility;
    2. apply ordered extension `Set` or `Remove` overlays;
    3. apply the final ChatGPT-auth gate without synthesizing the server
    again.
    
    This ordering is important:
    
    - an ordinary configured or plugin MCP server cannot claim the
    auth-bearing `codex_apps` name;
    - an extension-contributed hosted runtime wins over the fallback;
    - an extension `Remove` remains authoritative;
    - a host without the MCP extension retains the legacy Apps endpoint and
    current local-only behavior.
    
    The temporary `legacy_apps_mcp_loader_enabled` coordination flag is no
    longer needed.
    
    ### Remove the path override
    
    The `apps_mcp_path_override` feature and its runtime plumbing are
    removed, including:
    
    - the feature registry entry and structured feature config;
    - `Config` and `McpConfig` fields;
    - config schema output;
    - config-lock materialization;
    - URL override handling in `codex-mcp`.
    
    Existing boolean and structured forms still deserialize as ignored
    compatibility input. They are omitted from new serialized config, and
    config-lock comparison normalizes the removed input so older locks
    remain replayable.
    
    ### App-server coverage
    
    App-server MCP fixtures now serve the hosted route at
    `/api/codex/ps/mcp`. Existing resource-read and tool/elicitation flows
    therefore exercise the extension-owned endpoint rather than succeeding
    through the legacy fallback.
    
    The stack also adds the missing `codex_chatgpt::connectors` re-export
    for the manager-backed connector helper introduced in #27191.
    
    ## Compatibility
    
    - App-server installs the extension and uses `/ps/mcp` for the hosted
    runtime.
    - CLI and other hosts that do not install the extension retain the
    legacy Apps endpoint.
    - Apps disabled or non-ChatGPT authentication removes `codex_apps` from
    the effective runtime view.
    - Existing local plugins, local skills, executor-selected skills,
    configured MCP servers, and MCP OAuth behavior are otherwise unchanged.
    - Backend plugin enablement remains account/workspace state owned by the
    hosted endpoint; this PR does not add thread-local backend plugin
    selection.
    
    ## Architectural fit
    
    The stack now proves two independent runtime shapes:
    
    1. #27184 resolves filesystem-backed skills through the executor that
    owns a selected root.
    2. #27191 and this PR resolve a backend-hosted HTTP MCP through an
    extension with no executor.
    
    Together they preserve the intended separation:
    
    - selection identifies a plugin/root when explicit selection is needed;
    - each component's owning extension resolves its concrete access
    mechanism;
    - execution stays with the runtime required by that component;
    - existing skills, MCP, connector, and hook subsystems remain the
    downstream consumers.
    
    ## Planned follow-ups
    
    1. **Executor stdio MCP:** selecting an executor plugin registers a
    manifest-declared stdio MCP server and executes it in the environment
    that owns the plugin.
    2. **Optional backend selection:** only if CCA needs thread-local
    selection distinct from backend account/workspace enablement, add a
    concrete backend-owned capability location and surface those selected
    skills through the skills catalog.
    3. **Connector metadata and hooks:** activate those plugin components
    through their existing owning subsystems, with executor hooks remaining
    environment-bound.
    4. **Propagation and persistence:** define explicit resume, fork,
    subagent, refresh, and environment-removal semantics once selected roots
    have multiple real consumers.
    5. **Local convergence:** migrate legacy local skill, MCP, connector,
    and hook paths behind their owning extensions one vertical at a time,
    then remove duplicate core managers and compatibility plumbing after
    parity.
    
    ## Verification
    
    Coverage in this change exercises:
    
    - extension-owned `/backend-api/ps/mcp` registration without an
    executor;
    - preservation of the legacy endpoint in hosts without the extension;
    - extension `Set` and `Remove` precedence over the legacy fallback;
    - ChatGPT-auth gating for the reserved server;
    - hosted MCP resource reads with and without an active thread;
    - connector tool invocation and MCP elicitation through the hosted
    route;
    - ignored boolean and structured forms of the removed path override;
    - config-lock replay compatibility for the removed feature.
    
    `cargo check -p codex-features -p codex-mcp-extension -p
    codex-app-server` passes. Tests and Clippy were not run locally under
    the current development instruction; CI provides the full validation
    pass.
  • core: allow excluding tool namespaces from code mode (#26320)
    ## Why
    
    Research and training setups need to control which tool namespaces
    appear inside code mode's nested `tools` surface without disabling those
    tools entirely. This makes it possible to train against a deliberately
    reduced nested-tool setup while preserving the normal direct and
    deferred tool paths.
    
    ## What
    
    - Extend `features.code_mode` to accept structured configuration while
    preserving the existing boolean syntax.
    - Add an exact `excluded_tool_namespaces` list under
    `[features.code_mode]`:
    
      ```toml
      [features.code_mode]
      enabled = true
      excluded_tool_namespaces = ["mcp__codex_apps", "multi_agent_v1"]
      ```
    
    - Filter matching canonical `ToolName` namespaces when constructing code
    mode's nested router and code-mode-specific direct tool descriptions.
    - Keep excluded tools registered, directly exposed in mixed code mode,
    and discoverable through top-level `tool_search` when otherwise
    eligible.
    - Derive deferred nested-tool guidance after namespace filtering so the
    `exec` description does not advertise excluded-only deferred tools.
    - Preserve the boolean/table representation when materializing config
    locks and update the generated config schema.
    
    ## Testing
    
    - `just test -p codex-features`
    - `just test -p codex-config`
    - `just test -p codex-core load_config_resolves_code_mode_config`
    - `just test -p codex-core
    lock_contains_prompts_and_materializes_features`
    - `just test -p codex-core
    excluded_deferred_namespaces_do_not_enable_nested_tool_guidance`
    - `just test -p codex-core
    code_mode_excludes_configured_nested_tool_namespaces`
    - `cargo check -p codex-thread-manager-sample`
  • Uprev Rust toolchain pins to 1.95.0 (#24684)
    ## Summary
    - Bump the workspace Rust toolchain from `1.93.0` to `1.95.0` across
    Cargo, Bazel, CI, release workflows, devcontainers, and the Codex
    environment config.
    - Refresh `MODULE.bazel.lock` so the Bazel Rust toolchain artifacts
    match the new version.
    - Leave purpose-specific toolchains unchanged, including the
    `argument-comment-lint` nightly and the upstream `rusty_v8` `1.91.0`
    build pin.
    - Includes fixes for new lints from `just fix` and a few codex-authored
    fixes for lints without a suggestion.
  • feat: add network proxy feature flag (#20147)
    ## Why
    
    The permissions migration is making
    `permissions.<profile>.network.enabled` the canonical sandbox network
    bit, while proxy startup is a separate concern. Enabling network access
    should not implicitly start the proxy, and users who are still on legacy
    sandbox modes need a separate place to opt into proxy startup and
    provide proxy-specific settings.
    
    This follow-up to #19900 gives the network proxy its own feature surface
    instead of overloading permission-profile network semantics.
    
    ## What changed
    
    - Add an experimental `network_proxy` feature with a configurable
    `[features.network_proxy]` table.
    - Overlay `features.network_proxy` settings onto the configured proxy
    state after permission-profile selection, so the proxy only starts when
    the active `NetworkSandboxPolicy` already allows network access.
    - Preserve `[experimental_network]` startup behavior independently of
    the new feature flag.
    
    ## Behavior and examples
    
    There are now three related knobs:
    
    - `permissions.<profile>.network.enabled` controls whether the active
    permission profile has network access at all.
    - `features.network_proxy` enables proxy restrictions for an
    already-network-enabled profile.
    - Legacy `sandbox_mode` plus `[sandbox_workspace_write].network_access`
    still control whether legacy `workspace-write` has network access at
    all.
    
    The rule is:
    
    - network off + proxy flag on -> network stays off, proxy is a no-op
    - network on + proxy flag off -> unrestricted direct network
    - network on + proxy flag on -> network stays on, with proxy
    restrictions applied
    
    For permission profiles, the feature toggle adds proxy restrictions only
    when network access is already enabled:
    
    ```toml
    default_permissions = "workspace"
    
    [permissions.workspace.filesystem]
    ":minimal" = "read"
    
    [permissions.workspace.network]
    enabled = true
    
    [features]
    network_proxy = true
    ```
    
    If `network.enabled = false`, the same feature flag is a no-op: network
    remains off and the proxy does not start.
    
    For legacy sandbox config, `network_access` remains the master switch:
    
    ```toml
    sandbox_mode = "workspace-write"
    
    [sandbox_workspace_write]
    network_access = true
    
    [features]
    network_proxy = true
    ```
    
    That keeps legacy `workspace-write` network access on, but routes it
    through the proxy policy. If `network_access = false`, the proxy feature
    is a no-op and legacy `workspace-write` remains offline.
    
    The same proxy opt-in can be supplied from the CLI:
    
    ```bash
    codex -c 'features.network_proxy=true'
    ```
    
    Additional proxy settings can be supplied when a table is needed:
    
    ```bash
    codex \
      -c 'features.network_proxy.enabled=true' \
      -c 'features.network_proxy.enable_socks5=false'
    ```
    
    The intended behavior matrix is:
    
    | Config surface | Network setting | `features.network_proxy` | Direct
    sandbox network | Proxy |
    | --- | --- | --- | --- | --- |
    | Permission profile | `network.enabled = false` | off | restricted |
    off |
    | Permission profile | `network.enabled = false` | on | restricted | off
    |
    | Permission profile | `network.enabled = true` | off | enabled | off |
    | Permission profile | `network.enabled = true` | on | enabled | on |
    | Legacy `workspace-write` | `network_access = false` | off | restricted
    | off |
    | Legacy `workspace-write` | `network_access = false` | on | restricted
    | off |
    | Legacy `workspace-write` | `network_access = true` | off | enabled |
    off |
    | Legacy `workspace-write` | `network_access = true` | on | enabled | on
    |
    
    `[experimental_network]` requirements remain separate from the user
    feature toggle and still start the proxy on their own.
    
    Relevant code:
    -
    [`features/src/feature_configs.rs`](https://github.com/openai/codex/blob/43785aff47/codex-rs/features/src/feature_configs.rs#L58-L117)
    defines the feature-specific proxy config.
    -
    [`core/src/config/mod.rs`](https://github.com/openai/codex/blob/43785aff47/codex-rs/core/src/config/mod.rs#L1959-L1964)
    reads the feature table, and [later applies it only when network access
    is already
    enabled](https://github.com/openai/codex/blob/43785aff47/codex-rs/core/src/config/mod.rs#L2448-L2458).
    
    ## Verification
    
    Added focused coverage for:
    - keeping the proxy off when `features.network_proxy` is enabled but
    sandbox network access is disabled
    - the full permission-profile and legacy `workspace-write` matrix above
    - preserving `[experimental_network]` startup without the feature
    - reusing profile-supplied proxy settings when the feature is enabled
    
    Ran:
    - `cargo test -p codex-features`
    - `cargo test -p codex-core network_proxy_feature`
    - `cargo test -p codex-core
    experimental_network_requirements_enable_proxy_without_feature`
  • [apps] Add apps MCP path override (#20231)
    Summary
    
    - Add `[features.apps_mcp_path_override]` config with a `path` field for
    overriding only the built-in apps MCP path.
    - Keep existing host/base URL derivation unchanged and append the
    configured path after that base.
    - Regenerate the config schema with the custom feature-config case.
    
    Test Plan
    
    - Not run for latest revision; only `just fmt` and `just
    write-config-schema` were run.
    - Earlier revision: `cargo test -p codex-features`
    - Earlier revision: `cargo test -p codex-mcp`
  • Configure multi_agent_v2 spawn agent hints (#17071)
    Allow multi_agent_v2 features to have its own temporary configuration
    under `[features.multi_agent_v2]`
    
    ```
    [features.multi_agent_v2]
    enabled = true
    usage_hint_enabled = false
    usage_hint_text = "Custom delegation guidance."
    hide_spawn_agent_metadata = true
    ```
    
    Absent `usage_hint_text` means use the default hint.
    
    ```
    [features]
    multi_agent_v2 = true
    ```
    
    still works as the boolean shorthand.
  • Refactor config types into a separate crate (#16962)
    Move config types into a separate crate because their macros expand into
    a lot of new code.