Commit Graph

369 Commits

  • make model optional in config (#7769)
    - Make Config.model optional and centralize default-selection logic in
    ModelsManager, including a default_model helper (with
    codex-auto-balanced when available) so sessions now carry an explicit
    chosen model separate from the base config.
    - Resolve `model` once in `core` and `tui` from config. Then store the
    state of it on other structs.
    - Move refreshing models to be before resolving the default model
  • refactoring with_escalated_permissions to use SandboxPermissions instead (#7750)
    helpful in the future if we want more granularity for requesting
    escalated permissions:
    e.g when running in readonly sandbox, model can request to escalate to a
    sandbox that allows writes
  • override instructions using ModelInfo (#7754)
    Making sure we can override base instructions
  • load models from disk and set a ttl and etag (#7722)
    # 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.
  • fix: refine the warning message and docs for deprecated tools config (#7685)
    Issue #7661 revealed that users are confused by deprecation warnings
    like:
    > `tools.web_search` is deprecated. Use `web_search_request` instead.
    
    This message misleadingly suggests renaming the config key from
    `web_search` to `web_search_request`, when the actual required change is
    to **move and rename the configuration from the `[tools]` section to the
    `[features]` section**.
    
    This PR clarifies the warning messages and documentation to make it
    clear that deprecated `[tools]` configurations should be moved to
    `[features]`. Changes made:
    - Updated deprecation warning format in `codex-rs/core/src/codex.rs:520`
    to include `[features].` prefix
    - Updated corresponding test expectations in
    `codex-rs/core/tests/suite/deprecation_notice.rs:39`
    - Improved documentation in `docs/config.md` to clarify upfront that
    `[tools]` options are deprecated in favor of `[features]`
  • Add remote models feature flag (#7648)
    # 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.
  • fix(apply-patch): preserve CRLF line endings on Windows (#7515)
    ## Summary
    This PR is heavily based on #4017, which contains the core logic for the
    fix. To reduce the risk, we are first introducing it only on windows. We
    can then expand to wsl / other environments as needed, and then tackle
    net new files.
    
    ## Testing
    - [x] added unit tests in apply-patch
    - [x] add integration tests to apply_patch_cli.rs
    
    ---------
    
    Co-authored-by: Chase Naples <Cnaples79@gmail.com>
  • Fix unified_exec on windows (#7620)
    Fix unified_exec on windows
    
    Requires removal of PSUEDOCONSOLE_INHERIT_CURSOR flag so child processed
    don't attempt to wait for cursor position response (and timeout).
    
    
    https://github.com/wezterm/wezterm/compare/main...pakrym:wezterm:PSUEDOCONSOLE_INHERIT_CURSOR?expand=1
    
    ---------
    
    Co-authored-by: pakrym-oai <pakrym@openai.com>
  • feat(core) Add login to shell_command tool (#6846)
    ## Summary
    Adds the `login` parameter to the `shell_command` tool - optional,
    defaults to true.
    
    ## Testing
    - [x] Tested locally
  • Wire with_remote_overrides to construct model families (#7621)
    - This PR wires `with_remote_overrides` and make the
    `construct_model_families` an async function
    - Moves getting model family a level above to keep the function `sync`
    - Updates the tests to local, offline, and `sync` helper for model
    families
  • fix: taking plan type from usage endpoint instead of thru auth token (#7610)
    pull plan type from the usage endpoint, persist it in session state /
    tui state, and propagate through rate limit snapshots
  • Call models endpoint in models manager (#7616)
    - Introduce `with_remote_overrides` and update
    `refresh_available_models`
    - Put `auth_manager` instead of `auth_mode` on `models_manager`
    - Remove `ShellType` and `ReasoningLevel` to use already existing
    structs
  • Add models endpoint (#7603)
    - Use the codex-api crate to introduce models endpoint. 
    - Add `models` to codex core tests helpers
    - Add `ModelsInfo` for the endpoint return type
  • remove model_family from `config (#7571)
    - Remove `model_family` from `config`
    - Make sure to still override config elements related to `model_family`
    like supporting reasoning
  • chore(core): test apply_patch_cli on Windows (#7554)
    ## Summary
    These tests pass on windows, let's enable them.
    
    ## Testing
    - [x] These are more tests
  • feat: update sandbox policy to allow TTY (#7580)
    **Change**: Seatbelt now allows file-ioctl on /dev/ttys[0-9]+ even
    without the sandbox extension so pre-created PTYs remain interactive
    (Python REPL, shells).
    
    **Risk**: A seatbelted process that already holds a PTY fd (including
    one it shouldn’t) could issue tty ioctls like TIOCSTI or termios changes
    on that fd. This doesn’t allow opening new PTYs or reading/writing them;
    it only broadens ioctl capability on existing fds.
    
    **Why acceptable**: We already hand the child its PTY for interactive
    use; restoring ioctls is required for isatty() and prompts to work. The
    attack requires being given or inheriting a sensitive PTY fd; by design
    we don’t hand untrusted processes other users’ PTYs (we don't hand them
    any PTYs actually), so the practical exposure is limited to the PTY
    intentionally allocated for the session.
    
    **Validation**:
    Running
    ```
    start a python interpreter and keep it running
    ```
    Followed by:
    * `calculate 1+1 using it` -> works as expected
    * `Use this Python session to run the command just fix in
    /Users/jif/code/codex/codex-rs` -> does not work as expected
  • Refactor execpolicy fallback evaluation (#7544)
    ## Refactor of the `execpolicy` crate
    
    To illustrate why we need this refactor, consider an agent attempting to
    run `apple | rm -rf ./`. Suppose `apple` is allowed by `execpolicy`.
    Before this PR, `execpolicy` would consider `apple` and `pear` and only
    render one rule match: `Allow`. We would skip any heuristics checks on
    `rm -rf ./` and immediately approve `apple | rm -rf ./` to run.
    
    To fix this, we now thread a `fallback` evaluation function into
    `execpolicy` that runs when no `execpolicy` rules match a given command.
    In our example, we would run `fallback` on `rm -rf ./` and prevent
    `apple | rm -rf ./` from being run without approval.
  • whitelist command prefix integration in core and tui (#7033)
    this PR enables TUI to approve commands and add their prefixes to an
    allowlist:
    <img width="708" height="605" alt="Screenshot 2025-11-21 at 4 18 07 PM"
    src="https://github.com/user-attachments/assets/56a19893-4553-4770-a881-becf79eeda32"
    />
    
    note: we only show the option to whitelist the command when 
    1) command is not multi-part (e.g `git add -A && git commit -m 'hello
    world'`)
    2) command is not already matched by an existing rule
  • Migrate codex max (#7566)
    - make codex max the default
    - fix: we were doing some async work in sync function which caused tui
    to panic
  • Migrate model family to models manager (#7565)
    This PR moves `ModelsFamily` to `openai_models`. It also propagates
    `ModelsManager` to session services and use it to drive model family. We
    also make `derive_default_model_family` private because it's a step
    towards what we want: one place that gives model configuration.
    
    This is a second step at having one source of truth for models
    information and config: `ModelsManager`.
    
    Next steps would be to remove `ModelsFamily` from config. That's massive
    because it's being used in 41 occasions mostly pre launching `codex`.
    Also, we need to make `find_family_for_model` private. It's also big
    because it's being used in 21 occasions ~ all tests.
  • Migrate model preset (#7542)
    - Introduce `openai_models` in `/core`
    - Move `PRESETS` under it
    - Move `ModelPreset`, `ModelUpgrade`, `ReasoningEffortPreset`,
    `ReasoningEffortPreset`, and `ReasoningEffortPreset` to `protocol`
    - Introduce `Op::ListModels` and `EventMsg::AvailableModels`
    
    Next steps:
    - migrate `app-server` and `tui` to use the introduced Operation
  • seatbelt: allow openpty() (#7507)
    This allows `openpty(3)` to run in the default sandbox. Also permit
    reading `kern.argmax`, which is the maximum number of arguments to
    exec().
  • feat: retroactive image placeholder to prevent poisoning (#6774)
    If an image can't be read by the API, it will poison the entire history,
    preventing any new turn on the conversation.
    This detect such cases and replace the image by a placeholder
  • fix(unified_exec): use platform default shell when unified_exec shell… (#7486)
    # Unified Exec Shell Selection on Windows
    
    ## Problem
    
    reference issue #7466
    
    The `unified_exec` handler currently deserializes model-provided tool
    calls into the `ExecCommandArgs` struct:
    
    ```rust
    #[derive(Debug, Deserialize)]
    struct ExecCommandArgs {
        cmd: String,
        #[serde(default)]
        workdir: Option<String>,
        #[serde(default = "default_shell")]
        shell: String,
        #[serde(default = "default_login")]
        login: bool,
        #[serde(default = "default_exec_yield_time_ms")]
        yield_time_ms: u64,
        #[serde(default)]
        max_output_tokens: Option<usize>,
        #[serde(default)]
        with_escalated_permissions: Option<bool>,
        #[serde(default)]
        justification: Option<String>,
    }
    ```
    
    The `shell` field uses a hard-coded default:
    
    ```rust
    fn default_shell() -> String {
        "/bin/bash".to_string()
    }
    ```
    
    When the model returns a tool call JSON that only contains `cmd` (which
    is the common case), Serde fills in `shell` with this default value.
    Later, `get_command` uses that value as if it were a model-provided
    shell path:
    
    ```rust
    fn get_command(args: &ExecCommandArgs) -> Vec<String> {
        let shell = get_shell_by_model_provided_path(&PathBuf::from(args.shell.clone()));
        shell.derive_exec_args(&args.cmd, args.login)
    }
    ```
    
    On Unix, this usually resolves to `/bin/bash` and works as expected.
    However, on Windows this behavior is problematic:
    
    - The hard-coded `"/bin/bash"` is not a valid Windows path.
    - `get_shell_by_model_provided_path` treats this as a model-specified
    shell, and tries to resolve it (e.g. via `which::which("bash")`), which
    may or may not exist and may not behave as intended.
    - In practice, this leads to commands being executed under a non-default
    or non-existent shell on Windows (for example, WSL bash), instead of the
    expected Windows PowerShell or `cmd.exe`.
    
    The core of the issue is that **"model did not specify `shell`" is
    currently interpreted as "the model explicitly requested `/bin/bash`"**,
    which is both Unix-specific and wrong on Windows.
    
    ## Proposed Solution
    
    Instead of hard-coding `"/bin/bash"` into `ExecCommandArgs`, we should
    distinguish between:
    
    1. **The model explicitly specifying a shell**, e.g.:
    
       ```json
       {
         "cmd": "echo hello",
         "shell": "pwsh"
       }
       ```
    
    In this case, we *do* want to respect the model’s choice and use
    `get_shell_by_model_provided_path`.
    
    2. **The model omitting the `shell` field entirely**, e.g.:
    
       ```json
       {
         "cmd": "echo hello"
       }
       ```
    
    In this case, we should *not* assume `/bin/bash`. Instead, we should use
    `default_user_shell()` and let the platform decide.
    
    To express this distinction, we can:
    
    1. Change `shell` to be optional in `ExecCommandArgs`:
    
       ```rust
       #[derive(Debug, Deserialize)]
       struct ExecCommandArgs {
           cmd: String,
           #[serde(default)]
           workdir: Option<String>,
           #[serde(default)]
           shell: Option<String>,
           #[serde(default = "default_login")]
           login: bool,
           #[serde(default = "default_exec_yield_time_ms")]
           yield_time_ms: u64,
           #[serde(default)]
           max_output_tokens: Option<usize>,
           #[serde(default)]
           with_escalated_permissions: Option<bool>,
           #[serde(default)]
           justification: Option<String>,
       }
       ```
    
    Here, the absence of `shell` in the JSON is represented as `shell:
    None`, rather than a hard-coded string value.
  • feat: experimental support for skills.md (#7412)
    This change prototypes support for Skills with the CLI. This is an
    **experimental** feature for internal testing.
    
    ---------
    
    Co-authored-by: Gav Verma <gverma@openai.com>
  • fix(apply_patch) tests for shell_command (#7307)
    ## Summary
    Adds test coverage for invocations of apply_patch via shell_command with
    heredoc, to validate behavior.
    
    ## Testing
    - [x] These are tests
  • chore: add cargo-deny configuration (#7119)
    - add GitHub workflow running cargo-deny on push/PR
    - document cargo-deny allowlist with workspace-dep notes and advisory
    ignores
    - align workspace crates to inherit version/edition/license for
    consistent checks
  • fix(windows) support apply_patch parsing in powershell (#7221)
    ## Summary
    Support powershell parsing of apply_patch
    
    ## Testing
    - [x] Enable apply_patch unit tests
    
    ---------
    
    Co-authored-by: jif-oai <jif@openai.com>
  • Account for encrypted reasoning for auto compaction (#7113)
    - The total token used returned from the api doesn't account for the
    reasoning items before the assistant message
    - Account for those for auto compaction
    - Add the encrypted reasoning effort in the common tests utils
    - Add a test to make sure it works as expected
  • refactor: inline sandbox type lookup in process_exec_tool_call (#7122)
    `process_exec_tool_call()` was taking `SandboxType` as a param, but in
    practice, the only place it was constructed was in
    `codex_message_processor.rs` where it was derived from the other
    `sandbox_policy` param, so this PR inlines the logic that decides the
    `SandboxType` into `process_exec_tool_call()`.
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/7122).
    * #7112
    * __->__ #7122
  • fix: read max_output_tokens param from config (#4139)
    Request param `max_output_tokens` is documented in
    `https://github.com/openai/codex/blob/main/docs/config.md`,
    but nowhere uses the item in config, this commit read it from config for
    GPT responses API.
    
    see https://github.com/openai/codex/issues/4138 for issue report.
    
    Signed-off-by: Yorling <shallowcloud@yeah.net>