Commit Graph

1286 Commits

Author SHA1 Message Date
jif-oai
f6845cad4d Merge remote-tracking branch 'origin/main' into jif/review-as-collab 2026-01-21 11:13:24 +00:00
jif-oai
a7a78330af fix merge 2026-01-21 10:48:52 +00:00
jif-oai
b75024c465 feat: async shell snapshot (#9600) 2026-01-21 10:41:13 +00:00
jif-oai
04687201ef Merge remote-tracking branch 'origin/main' into jif/review-as-collab
# Conflicts:
#	codex-rs/core/src/agent/control.rs
#	codex-rs/tui/src/app.rs
2026-01-21 10:31:57 +00:00
Eric Traut
16b9380e99 Added "codex." prefix to "conversation.turn.count" metric name (#9594)
All other metrics names start with "codex.", so I presume this was an
unintended omission.
2026-01-21 10:00:47 +00:00
jif-oai
a22a61e678 feat: display raw command on user shell (#9598) 2026-01-21 09:44:38 +00:00
jif-oai
f1c961d5f7 feat: max threads config (#9483)
# 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.
2026-01-21 09:39:11 +00:00
pakrym-oai
527b7b4c02 Feature to auto-enable websockets transport (#9578) 2026-01-20 20:32:06 -08:00
alexsong-oai
fabc2bcc32 feat: add skill injected counter metric (#9575) 2026-01-20 19:05:37 -08:00
charley-oai
0523a259c8 Reject ask user question tool in Execute and Custom (#9560)
## Summary
- Keep `request_user_input` in the tool list but reject it at runtime in
Execute/Custom modes with a clear model-facing error.
- Add a session accessor for current collaboration mode and enforce the
gate in the request_user_input handler.
- Update core/app-server tests to use Plan mode for success and add
Execute/Custom rejection coverage.
2026-01-20 18:32:17 -08:00
Michael Bolin
f4d55319d1 feat: rename experimental_instructions_file to model_instructions_file (#9555)
A user who has `experimental_instructions_file` set will now see this:

<img width="888" height="660" alt="image"
src="https://github.com/user-attachments/assets/51c98312-eb9b-4881-81f1-bea6677e158d"
/>

And a `codex exec` would include this warning:

<img width="888" height="660" alt="image"
src="https://github.com/user-attachments/assets/a89f62be-1edf-4593-a75e-e0b4a762ed7d"
/>
2026-01-21 02:25:08 +00:00
Jeff Mickey
c14e6813fb [codex-tui] exit when terminal is dumb (#9293)
Using terminal with TERM=dumb specifically mean that TUIs and the like
don't work. Ensure that codex doesn't run in these environments and exit
with odd errors like crossterm's "Error: The cursor position could not
be read within a normal duration"

---------

Co-authored-by: Josh McKinney <joshka@openai.com>
2026-01-20 16:17:38 -08:00
HDCode
80f80181c2 fix(core): require approval for force delete on Windows (#8590)
### What
Implemented detection for dangerous "force delete" commands on Windows
to trigger the user approval prompt when `--ask-for-approval on-request`
is set. This aligns Windows behavior with the existing safety checks for
`rm -rf` on Linux.

### Why
Fixes #8567 - a critical safety gap where destructive Windows commands
could bypass the approval prompt. This prevents accidental data loss by
ensuring the user explicitly confirms operations that would otherwise
suppress the OS's native confirmation prompts.

### How
Updated the Windows command safety module to identify and flag the
following patterns as dangerous:
*   **PowerShell**:
* Detects `Remove-Item` (and aliases `rm`, `ri`, `del`, `erase`, `rd`,
`rmdir`) when used with the `-Force` flag.
* Uses token-based analysis to robustly detect these patterns even
inside script blocks (`{...}`), sub-expression `(...)`, or
semicolon-chained sequences.
*   **CMD**:
    *   Detects `del /f` (force delete files).
    *   Detects `rd /s /q` (recursive delete quiet).
* **Command Chaining**: Added support for analyzing chained commands
(using `&`, `&&`, `|`, `||`) to separate and check individual commands
(e.g., catching `del /f` hidden in `echo log & del /f data`).

### Testing
Added comprehensive unit tests covering:
* **PowerShell**: `Remove-Item -Path 'test' -Recurse -Force` (Exact
reproduction case).
* **Complex Syntax**: Verified detection inside blocks (e.g., `if
($true) { rm -Force }`) and with trailing punctuation.
*   **CMD**:
    *   `del /f` (Flagged).
    *   `rd /s /q` (Flagged).
    *   Chained commands: `echo hi & del /f file` (Flagged).
*   **False Positives**:
    *   `rd /s` (Not flagged - relies on native prompt).
    *   Standard deletions without force flags.

Verified with `cargo test` and `cargo clippy`.

---------

Co-authored-by: Eric Traut <etraut@openai.com>
2026-01-20 15:25:27 -08:00
Ahmed Ibrahim
de4980d2ac Enable remote models (#9554) 2026-01-20 23:17:22 +00:00
charley-oai
be9e55c5fc Add total (non-partial) TextElement placeholder accessors (#9545)
## Summary
- Make `TextElement` placeholders private and add a text-backed accessor
to avoid assuming `Some`.
- Since they are optional in the protocol, we want to make sure any
accessors properly handle the None case (getting the placeholder using
the byte range in the text)
- Preserve placeholders during protocol/app-server conversions using the
accessor fallback.
- Update TUI composer/remap logic and tests to use the new
constructor/accessor.
2026-01-20 14:04:11 -08:00
Ahmed Ibrahim
56fe5e7bea merge remote models (#9547)
We have `models.json` and `/models` response
Behavior:
1. New models from models endpoint gets added
2. Shared models get replaced by remote ones
3. Existing models in `models.json` but not `/models` are kept
4. Mark highest priority as default
2026-01-20 14:02:07 -08:00
Owen Lin
b0049ab644 fix(core): don't update the file's mtime on resume (#9553)
Remove `FileTimes::new().set_modified(SystemTime::now())` when resuming
a thread.

Context: It's awkward in UI built on top of app-server that resuming a
thread bumps the `updated_at` timestamp, even if no message is sent. So
if you open a thread (perhaps to just view its contents), it
automatically reorders it to the top which is almost certainly not what
you want.
2026-01-20 21:39:31 +00:00
Skylar Graika
b236f1c95d fix: prevent repeating interrupted turns (#9043)
## What
Record a model-visible `<turn_aborted>` marker in history when a turn is
interrupted, and treat it as a session prefix.

## Why
When a turn is interrupted, Codex emits `TurnAborted` but previously did
not persist anything model-visible in the conversation history. On the
next user turn, the model can’t tell the previous work was aborted and
may resume/repeat earlier actions (including duplicated side effects
like re-opening PRs).

Fixes: https://github.com/openai/codex/issues/9042

## How
On `TurnAbortReason::Interrupted`, append a hidden user message
containing a `<turn_aborted>…</turn_aborted>` marker and flush.
Treat `<turn_aborted>` like `<environment_context>` for session-prefix
filtering.
Add a regression test to ensure follow-up turns don’t repeat side
effects from an aborted turn.

## Testing
`just fmt`
`just fix -p codex-core`
`cargo test -p codex-core -- --test-threads=1`
`cargo test --all-features -- --test-threads=1`

---------

Co-authored-by: Skylar Graika <sgraika127@gmail.com>
Co-authored-by: jif-oai <jif@openai.com>
Co-authored-by: Eric Traut <etraut@openai.com>
2026-01-20 13:07:28 -08:00
Eric Traut
79c5bf9835 Fixed config merging issue with profiles (#9509)
This PR fixes a small issue with chained (layered) config.toml file
merging. The old logic didn't properly handle profiles.

In particular, if a lower-layer config overrides a profile defined in a
higher-layer config, the override did not take effect. This prevents
users from having project-specific profile overrides and contradicts the
(soon-to-be) documented behavior of config merging.

The change adds a unit test for this case. It also exposes a function
from the config crate that is needed by the app server code paths to
implement support for layered configs.
2026-01-20 12:18:00 -08:00
jif-oai
0b3c802a54 fix: memory leak issue (#9543)
Co-authored-by: Josh McKinney <joshka@openai.com>
2026-01-20 20:14:14 +00:00
jif-oai
65d5cdd99b Always emit exit 2026-01-20 19:12:10 +00:00
Dylan Hurd
714151eb4e feat(personality) introduce model_personality config (#9459)
## Summary
Introduces the concept of a config model_personality. I would consider
this an MVP for testing out the feature. There are a number of
follow-ups to this PR:

- More sophisticated templating with validation
- In-product experience to manage this

## Testing
- [x] Testing locally
2026-01-20 11:06:14 -08:00
jif-oai
2ccb5eb9d7 Merge remote-tracking branch 'origin/main' into jif/review-as-collab 2026-01-20 18:59:42 +00:00
Simon Willison
46a4a03083 Fix typo in feature name from 'Mult-agents' to 'Multi-agents' (#9542)
Fixes a typo in a feature description.
2026-01-20 10:55:36 -08:00
jif-oai
d328d242f2 clippy 2026-01-20 17:41:27 +00:00
Anton Panasenko
7b27aa7707 feat: support proxy for ws connection (#9409)
unfortunately tokio-tungstenite doesn't support proxy configuration
outbox, while https://github.com/snapview/tokio-tungstenite/pull/370 is
in review, we can depend on source code for now.
2026-01-20 09:36:30 -08:00
jif-oai
5e2504cbe8 make sure to close the agent 2026-01-20 15:59:27 +00:00
gt-oai
7351c12999 Only load config from trusted folders (#9533)
Config includes multiple code execution entrypoints. 

Now, we load the config from predetermined locations first
(~/.codex/config.toml etc), use those to learn which folders are
'trusted', and only load additional config from the CWD if it is
trusted.
2026-01-20 15:44:21 +00:00
jif-oai
da12acfd55 fix abort 2026-01-20 14:52:38 +00:00
jif-oai
0f4e0e137e make it better 2026-01-20 14:04:59 +00:00
jif-oai
3a9f436ce0 feat: metrics on shell snapshot (#9527) 2026-01-20 13:18:24 +00:00
jif-oai
6bbf506120 feat: metrics on remote models (#9528) 2026-01-20 13:02:55 +00:00
jif-oai
fd19b638ba drop file 2026-01-20 12:39:27 +00:00
jif-oai
7e10dd25cf Merge remote-tracking branch 'origin/main' into jif/review-as-collab
# Conflicts:
#	codex-rs/core/src/agent/control.rs
#	codex-rs/core/src/codex_delegate.rs
2026-01-20 12:34:32 +00:00
jif-oai
8df6d0d4ee better wiring 2026-01-20 12:33:30 +00:00
jif-oai
483239d861 chore: collab in experimental (#9525) 2026-01-20 10:19:06 +00:00
charley-oai
eb90e20c0b Persist text elements through TUI input and history (#9393)
Continuation of breaking up this PR
https://github.com/openai/codex/pull/9116

## Summary
- Thread user text element ranges through TUI/TUI2 input, submission,
queueing, and history so placeholders survive resume/edit flows.
- Preserve local image attachments alongside text elements and rehydrate
placeholders when restoring drafts.
- Keep model-facing content shapes clean by attaching UI metadata only
to user input/events (no API content changes).

## Key Changes
- TUI/TUI2 composer now captures text element ranges, trims them with
text edits, and restores them when submission is suppressed.
- User history cells render styled spans for text elements and keep
local image paths for future rehydration.
- Initial chat widget bootstraps accept empty `initial_text_elements` to
keep initialization uniform.
- Protocol/core helpers updated to tolerate the new InputText field
shape without changing payloads sent to the API.
2026-01-19 23:49:34 -08:00
Dylan Hurd
675f165c56 fix(core) Preserve base_instructions in SessionMeta (#9427)
## Summary
This PR consolidates base_instructions onto SessionMeta /
SessionConfiguration, so we ensure `base_instructions` is set once per
session and should be (mostly) immutable, unless:
- overridden by config on resume / fork
- sub-agent tasks, like review or collab


In a future PR, we should convert all references to `base_instructions`
to consistently used the typed struct, so it's less likely that we put
other strings there. See #9423. However, this PR is already quite
complex, so I'm deferring that to a follow-up.

## Testing
- [x] Added a resume test to assert that instructions are preserved. In
particular, `resume_switches_models_preserves_base_instructions` fails
against main.

Existing test coverage thats assert base instructions are preserved
across multiple requests in a session:
- Manual compact keeps baseline instructions:
core/tests/suite/compact.rs:199
- Auto-compact keeps baseline instructions:
core/tests/suite/compact.rs:1142
- Prompt caching reuses the same instructions across two requests:
core/tests/suite/prompt_caching.rs:150 and
core/tests/suite/prompt_caching.rs:157
- Prompt caching with explicit expected string across two requests:
core/tests/suite/prompt_caching.rs:213 and
core/tests/suite/prompt_caching.rs:222
- Resume with model switch keeps original instructions:
core/tests/suite/resume.rs:136
- Compact/resume/fork uses request 0 instructions for later expected
payloads: core/tests/suite/compact_resume_fork.rs:215
2026-01-19 21:59:36 -08:00
Shijie Rao
d544adf71a Feat: plan mode prompt update (#9495)
### Summary
* Added instruction on using `request_user_input`
* Added the output to be json with `plan` key and the actual plan as the
value.
* Remove `PLAN.md` write because that gets into sandbox issue. We can
add it back later.
2026-01-19 12:17:29 -08:00
jif-oai
070935d5e8 chore: fix beta VS experimental (#9496) 2026-01-19 19:39:23 +00:00
Ahmed Ibrahim
b11e96fb04 Act on reasoning-included per turn (#9402)
- Reset reasoning-included flag each turn and update compaction test
2026-01-19 11:23:25 -08:00
Shijie Rao
57ec3a8277 Feat: request user input tool (#9472)
### Summary
* Add `requestUserInput` tool that the model can use for gather
feedback/asking question mid turn.


### Tool input schema
```
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "requestUserInput input",
  "type": "object",
  "additionalProperties": false,
  "required": ["questions"],
  "properties": {
    "questions": {
      "type": "array",
      "description": "Questions to show the user (1-3). Prefer 1 unless multiple independent decisions block progress.",
      "minItems": 1,
      "maxItems": 3,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "header", "question"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier for mapping answers (snake_case)."
          },
          "header": {
            "type": "string",
            "description": "Short header label shown in the UI (12 or fewer chars)."
          },
          "question": {
            "type": "string",
            "description": "Single-sentence prompt shown to the user."
          },
          "options": {
            "type": "array",
            "description": "Optional 2-3 mutually exclusive choices. Put the recommended option first and suffix its label with \"(Recommended)\". Only include \"Other\" option if we want to include a free form option. If the question is free form in nature, do not include any option.",
            "minItems": 2,
            "maxItems": 3,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["value", "label", "description"],
              "properties": {
                "value": {
                  "type": "string",
                  "description": "Machine-readable value (snake_case)."
                },
                "label": {
                  "type": "string",
                  "description": "User-facing label (1-5 words)."
                },
                "description": {
                  "type": "string",
                  "description": "One short sentence explaining impact/tradeoff if selected."
                }
              }
            }
          }
        }
      }
    }
  }
}
```

### Tool output schema
```
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "requestUserInput output",
  "type": "object",
  "additionalProperties": false,
  "required": ["answers"],
  "properties": {
    "answers": {
      "type": "object",
      "description": "Map of question id to user answer.",
      "additionalProperties": {
        "type": "object",
        "additionalProperties": false,
        "required": ["selected"],
        "properties": {
          "selected": {
            "type": "array",
            "items": { "type": "string" }
          },
          "other": {
            "type": ["string", "null"]
          }
        }
      }
    }
  }
}
```
2026-01-19 10:17:30 -08:00
jif-oai
e323e905ff feat: review as sub agent 2026-01-19 17:25:02 +00:00
jif-oai
92cf2a1c3a chore: warning metric (#9487) 2026-01-19 17:07:04 +00:00
Eric Traut
264d40efdc Fix invalid input error on Azure endpoint (#9387)
Users of Azure endpoints are reporting that when they use `/review`,
they sometimes see an error "Invalid 'input[3].id". I suspect this is
specific to the Azure implementation of the `responses` API. The Azure
team generally copies the OpenAI code for this endpoint, but they do
have minor differences and sometimes lag in rolling out bug fixes or
updates.

The error appears to be triggered because the `/review` implementation
is using a user ID with a colon in it.

Addresses #9360
2026-01-19 08:21:27 -08:00
jif-oai
3c28c85063 prompt 3 (#9479) 2026-01-19 11:56:38 +00:00
jif-oai
dc1b62acbd feat: detach non-tty childs (#9477)
Thanks to the investigations made by
* @frantic-openai https://github.com/openai/codex/pull/9403
* @kfiramar https://github.com/openai/codex/pull/9388
2026-01-19 11:35:34 +00:00
jif-oai
186794dbb3 feat: close all threads in /new (#9478) 2026-01-19 11:35:03 +00:00
jif-oai
7ebe13f692 feat: timer total turn metrics (#9382) 2026-01-19 10:44:31 +00:00
dependabot[bot]
78a359f7fa chore(deps): bump arc-swap from 1.7.1 to 1.8.0 in /codex-rs (#9468)
Bumps [arc-swap](https://github.com/vorner/arc-swap) from 1.7.1 to
1.8.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/vorner/arc-swap/blob/master/CHANGELOG.md">arc-swap's
changelog</a>.</em></p>
<blockquote>
<h1>1.8.0</h1>
<ul>
<li>Support for Pin (<a
href="https://redirect.github.com/vorner/arc-swap/issues/185">#185</a>,
<a
href="https://redirect.github.com/vorner/arc-swap/issues/183">#183</a>).</li>
<li>Fix (hopefully) crash on ARM (<a
href="https://redirect.github.com/vorner/arc-swap/issues/164">#164</a>).</li>
<li>Fix Miri check (<a
href="https://redirect.github.com/vorner/arc-swap/issues/186">#186</a>,
<a
href="https://redirect.github.com/vorner/arc-swap/issues/156">#156</a>).</li>
<li>Fix support for Rust 1.31.0.</li>
<li>Some minor clippy lints.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2540d266a8"><code>2540d26</code></a>
Version bump to 1.8.0</li>
<li><a
href="9981e3af23"><code>9981e3a</code></a>
Keep &quot;old&quot; Cargo.lock around</li>
<li><a
href="57a8abbfc4"><code>57a8abb</code></a>
Fix documentation links</li>
<li><a
href="346c5b642b"><code>346c5b6</code></a>
Fix some clippy warnings</li>
<li><a
href="0bd349a56b"><code>0bd349a</code></a>
Fix support for Rust 1.31.0</li>
<li><a
href="57aa5224c1"><code>57aa522</code></a>
Merge pull request <a
href="https://redirect.github.com/vorner/arc-swap/issues/185">#185</a>
from SpriteOvO/pin</li>
<li><a
href="4c0c4ab321"><code>4c0c4ab</code></a>
Implement <code>RefCnt</code> for <code>Pin\&lt;Arc&gt;</code> and
<code>Pin\&lt;Rc&gt;</code></li>
<li><a
href="e596275acf"><code>e596275</code></a>
Avoid warnings about hidden lifetimes</li>
<li><a
href="d849a2d17e"><code>d849a2d</code></a>
Use SeqCst in debt-lists</li>
<li><a
href="1f9b221da9"><code>1f9b221</code></a>
Merge pull request <a
href="https://redirect.github.com/vorner/arc-swap/issues/186">#186</a>
from nbdd0121/prov</li>
<li>Additional commits viewable in <a
href="https://github.com/vorner/arc-swap/compare/v1.7.1...v1.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=arc-swap&package-manager=cargo&previous-version=1.7.1&new-version=1.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-18 22:25:23 -08:00