Commit Graph
8002 Commits
Author SHA1 Message Date
Michael Bolin 1980c974e9 feat: introduce Reject variant of AskForApproval 2026-02-19 10:12:02 -08:00
Michael Bolin e94731388c merge commit for archive created by Sapling 2026-02-19 10:06:58 -08:00
Michael Bolin a28a1c3176 feat: introduce Reject variant of AskForApproval 2026-02-19 10:06:51 -08:00
Jack Mousseau 3a951f8096 Restore phase when loading from history (#12244) 2026-02-19 09:56:56 -08:00
Charley Cunningham f2d5842ed1 Move previous turn context tracking into ContextManager history (#12179)
## Summary
- add `previous_context_item: Option<TurnContextItem>` to
`ContextManager`
- expose session/state accessors for reading and updating the stored
previous context item
- switch settings diffing to use `TurnContextItem` instead of
`TurnContext`
- remove submission-loop local `previous_context` and persist the
previous context item in history

## Testing
- `just fmt`
- `just fix -p codex-core`
- `cargo test -p codex-core --test all model_switching::`
- `cargo test -p codex-core --test all collaboration_instructions::`
- `cargo test -p codex-core --test all personality::`
- `cargo test -p codex-core --test all
permissions_messages::permissions_message_not_added_when_no_change`
2026-02-19 09:56:20 -08:00
colby-oai f6fd4cb3f5 Adjust MCP tool approval handling for custom servers (#11787)
Summary
This PR expands MCP client-side approval behavior beyond codex_apps and
tightens elicitation capability signaling.

- Removed the codex_apps-only gate in MCP tool approval checks, so
local/custom MCP servers are now eligible for the same client-side
approval prompt flow when tool annotations indicate side effects.
- Updated approval memory keying to support tools without a connector ID
(connector_id: Option<String>), allowing “Approve this Session” to be
remembered even when connector metadata is missing.
- Updated prompt text for non-codex_apps tools to identify origin as The
<server> MCP server instead of This app.
- Added MCP initialization capability policy so only codex_apps
advertises MCP elicitation capability; other servers advertise no
elicitation support.
- Added regression tests for:
server-specific prompt copy behavior
codex-apps-only elicitation capability advertisement

Testing
- Not run (not requested)
2026-02-19 12:52:42 -05:00
jif-oai 547f462385 feat: add configurable write_stdin timeout (#12228)
Add max timeout as config for `write_stdin`. This is only used for empty
`write_stdin`.

Also increased the default value from 30s to 5mins.
2026-02-19 17:22:13 +00:00
viyatb-oai f595e11723 docs: add codex security policy (#12193)
## Summary
Adds SECURITY.MD with Codex security policy and Bugcrowd reporting
guidance
2026-02-19 09:12:59 -08:00
jif-oai 743caea3a6 feat: add shell snapshot failure reason (#12233) 2026-02-19 13:49:12 +00:00
jif-oai 2daa3fd44f feat: sub-agent injection (#12152)
This PR adds parent-thread sub-agent completion notifications and change
the prompt of the model to prevent if from being confused
2026-02-19 11:32:10 +00:00
jif-oai f298c48cc6 Adjust memories rollout defaults (#12231)
- Summary
- raise `DEFAULT_MEMORIES_MAX_ROLLOUTS_PER_STARTUP` to 16 so more
rollouts are allowed per startup
- lower `DEFAULT_MEMORIES_MIN_ROLLOUT_IDLE_HOURS` to 6 to make rollouts
eligible sooner
- Testing
  - Not run (not requested)
2026-02-19 10:52:43 +00:00
Eric Traut 227352257c Update docs links for feature flag notice (#12164)
Summary
- replace the stale `docs/config.md#feature-flags` reference in the
legacy feature notice with the canonical published URL
- align the deprecation notice test to expect the new link

This addresses #12123
2026-02-19 00:00:44 -08:00
viyatb-oai 4fe99b086f fix(linux-sandbox): mount /dev in bwrap sandbox (#12081)
## Summary
- Updates the Linux bubblewrap sandbox args to mount a minimal `/dev`
using `--dev /dev` instead of only binding `/dev/null`. tools needing
entropy (git, crypto libs, etc.) can fail.

- Changed mount order so `--dev /dev` is added before writable-root
`--bind` mounts, preserving writable `/dev/*` submounts like `/dev/shm`

## Why
Fixes sandboxed command failures when reading `/dev/urandom` (and
similar standard device-node access).


Fixes https://github.com/openai/codex/issues/12056
2026-02-18 23:27:32 -08:00
Matthew Zeng 18eb640a47 [apps] Update apps allowlist. (#12211)
- [x] Update apps allowlist.
2026-02-18 23:21:32 -08:00
Charley Cunningham 16c3c47535 Stabilize app-server detached review and running-resume tests (#12203)
## Summary
- stabilize
`thread_resume_rejoins_running_thread_even_with_override_mismatch` by
using a valid delayed second SSE response instead of an intentionally
truncated stream
- set `RUST_MIN_STACK=4194304` for spawned app-server test processes in
`McpProcess` to avoid stack-sensitive CI overflows in detached review
tests

## Why
- the thread-resume assertion could race with a mocked stream-disconnect
error and intermittently observe `systemError`
- detached review startup is stack-sensitive in some CI environments;
pinning a larger stack in the test harness removes that flake without
changing product behavior

## Validation
- `just fmt`
- `cargo test -p codex-app-server --test all
suite::v2::thread_resume::thread_resume_rejoins_running_thread_even_with_override_mismatch`
- `cargo test -p codex-app-server --test all
suite::v2::review::review_start_with_detached_delivery_returns_new_thread_id`
2026-02-18 19:05:35 -08:00
Michael Bolin b431a46048 merge commit for archive created by Sapling 2026-02-18 17:32:08 -08:00
Michael Bolin c132a8701b feat: introduce Reject variant of AskForApproval 2026-02-18 17:31:50 -08:00
Michael Bolin ffa94dcb27 merge commit for archive created by Sapling 2026-02-18 17:21:24 -08:00
Michael Bolin 34f85fbf8c feat: introduce Reject variant of AskForApproval 2026-02-18 17:20:41 -08:00
Charley Cunningham 7f3dbaeb25 state: enforce 10 MiB log caps for thread and threadless process logs (#12038)
## Summary
- enforce a 10 MiB cap per `thread_id` in state log storage
- enforce a 10 MiB cap per `process_uuid` for threadless (`thread_id IS
NULL`) logs
- scope pruning to only keys affected by the current insert batch
- add a cheap per-key `SUM(...)` precheck so windowed prune queries only
run for keys that are currently over the cap
- add SQLite indexes used by the pruning queries
- add focused runtime tests covering both pruning behaviors

## Why
This keeps log growth bounded by the intended partition semantics while
preserving a small, readable implementation localized to the existing
insert path.

## Local Latency Snapshot (No Truncation-Pressure Run)
Collected from session `019c734f-1d16-7002-9e00-c966c9fbbcae` using
local-only (uncommitted) instrumentation, while not specifically
benchmarking the truncation-heavy regime.

### Percentiles By Query (ms)
| query | count | p50 | p90 | p95 | p99 | max |
|---|---:|---:|---:|---:|---:|---:|
| `insert_logs.insert_batch` | 110 | 0.332 | 0.999 | 1.811 | 2.978 |
3.493 |
| `insert_logs.precheck.process` | 106 | 0.074 | 0.152 | 0.206 | 0.258 |
0.426 |
| `insert_logs.precheck.thread` | 73 | 0.118 | 0.206 | 0.253 | 1.025 |
1.025 |
| `insert_logs.prune.process` | 58 | 0.291 | 0.576 | 0.607 | 1.088 |
1.088 |
| `insert_logs.prune.thread` | 44 | 0.318 | 0.467 | 0.728 | 0.797 |
0.797 |
| `insert_logs.prune_total` | 110 | 0.488 | 0.976 | 1.237 | 1.593 |
1.684 |
| `insert_logs.total` | 110 | 1.315 | 2.889 | 3.623 | 5.739 | 5.961 |
| `insert_logs.tx_begin` | 110 | 0.133 | 0.235 | 0.282 | 0.412 | 0.546 |
| `insert_logs.tx_commit` | 110 | 0.259 | 0.689 | 0.772 | 1.065 | 1.080
|

### `insert_logs.total` Histogram (ms)
| bucket | count |
|---|---:|
| `<= 0.100` | 0 |
| `<= 0.250` | 0 |
| `<= 0.500` | 7 |
| `<= 1.000` | 33 |
| `<= 2.000` | 40 |
| `<= 5.000` | 28 |
| `<= 10.000` | 2 |
| `<= 20.000` | 0 |
| `<= 50.000` | 0 |
| `<= 100.000` | 0 |
| `> 100.000` | 0 |

## Local Latency Snapshot (Truncation-Heavy / Cap-Hit Regime)
Collected from a run where cap-hit behavior was frequent (`135/180`
insert calls), using local-only (uncommitted) instrumentation and a
temporary local cap of `10_000` bytes for stress testing (not the merged
`10 MiB` cap).

### Percentiles By Query (ms)
| query | count | p50 | p90 | p95 | p99 | max |
|---|---:|---:|---:|---:|---:|---:|
| `insert_logs.insert_batch` | 180 | 0.524 | 1.645 | 2.163 | 3.424 |
3.777 |
| `insert_logs.precheck.process` | 171 | 0.086 | 0.235 | 0.373 | 0.758 |
1.147 |
| `insert_logs.precheck.thread` | 100 | 0.105 | 0.251 | 0.291 | 1.176 |
1.622 |
| `insert_logs.prune.process` | 109 | 0.386 | 0.839 | 1.146 | 1.548 |
2.588 |
| `insert_logs.prune.thread` | 56 | 0.253 | 0.550 | 1.148 | 2.484 |
2.484 |
| `insert_logs.prune_total` | 180 | 0.511 | 1.221 | 1.695 | 4.548 |
5.512 |
| `insert_logs.total` | 180 | 1.631 | 3.902 | 5.103 | 8.901 | 9.095 |
| `insert_logs.total_cap_hit` | 135 | 1.876 | 4.501 | 5.547 | 8.902 |
9.096 |
| `insert_logs.total_no_cap_hit` | 45 | 0.520 | 1.700 | 2.079 | 3.294 |
3.294 |
| `insert_logs.tx_begin` | 180 | 0.109 | 0.253 | 0.287 | 1.088 | 1.406 |
| `insert_logs.tx_commit` | 180 | 0.267 | 0.813 | 1.170 | 2.497 | 2.574
|

### `insert_logs.total` Histogram (ms)
| bucket | count |
|---|---:|
| `<= 0.100` | 0 |
| `<= 0.250` | 0 |
| `<= 0.500` | 16 |
| `<= 1.000` | 39 |
| `<= 2.000` | 60 |
| `<= 5.000` | 54 |
| `<= 10.000` | 11 |
| `<= 20.000` | 0 |
| `<= 50.000` | 0 |
| `<= 100.000` | 0 |
| `> 100.000` | 0 |

### `insert_logs.total` Histogram When Cap Was Hit (ms)
| bucket | count |
|---|---:|
| `<= 0.100` | 0 |
| `<= 0.250` | 0 |
| `<= 0.500` | 0 |
| `<= 1.000` | 22 |
| `<= 2.000` | 51 |
| `<= 5.000` | 51 |
| `<= 10.000` | 11 |
| `<= 20.000` | 0 |
| `<= 50.000` | 0 |
| `<= 100.000` | 0 |
| `> 100.000` | 0 |

### Performance Takeaways
- Even in a cap-hit-heavy run (`75%` cap-hit calls), `insert_logs.total`
stays sub-10ms at p99 (`8.901ms`) and max (`9.095ms`).
- Calls that did **not** hit the cap are materially cheaper
(`insert_logs.total_no_cap_hit` p95 `2.079ms`) than cap-hit calls
(`insert_logs.total_cap_hit` p95 `5.547ms`).
- Compared to the earlier non-truncation-pressure run, overall
`insert_logs.total` rose from p95 `3.623ms` to p95 `5.103ms`
(+`1.48ms`), indicating bounded overhead when pruning is active.
- This truncation-heavy run used an intentionally low local cap for
stress testing; with the real 10 MiB cap, cap-hit frequency should be
much lower in normal sessions.

## Testing
- `just fmt` (in `codex-rs`)
- `cargo test -p codex-state` (in `codex-rs`)
2026-02-18 17:08:08 -08:00
Michael Bolin 2d91c019d9 merge commit for archive created by Sapling 2026-02-18 17:06:43 -08:00
Michael Bolin 973bec038f feat: introduce Reject variant of AskForApproval 2026-02-18 17:05:40 -08:00
Michael Bolin 034b10c7af merge commit for archive created by Sapling 2026-02-18 16:41:26 -08:00
Michael Bolin 9ca73c6874 feat: introduce Reject variant of AskForApproval 2026-02-18 16:41:20 -08:00
Michael Bolin a3dddacce3 merge commit for archive created by Sapling 2026-02-18 16:33:08 -08:00
Michael Bolin be16f6798d feat: introduce Reject variant of AskForApproval 2026-02-18 16:33:02 -08:00
Michael Bolin eafb479598 merge commit for archive created by Sapling 2026-02-18 16:20:39 -08:00
Michael Bolin 4fd55c18cd feat: introduce Reject variant of AskForApproval 2026-02-18 16:20:31 -08:00
Michael Bolin e6457af0a5 merge commit for archive created by Sapling 2026-02-18 16:07:35 -08:00
Michael Bolin 06b63627c7 feat: introduce Reject variant of AskForApproval 2026-02-18 16:07:27 -08:00
Ruslan Nigmatullin 1f54496c48 app-server: expose loaded thread status via read/list and notifications (#11786)
Motivation
- Today, a newly connected client has no direct way to determine the
current runtime status of threads from read/list responses alone.
- This forces clients to infer state from transient events, which can
lead to stale or inconsistent UI when reconnecting or attaching late.

Changes
- Add `status` to `thread/read` responses.
- Add `statuses` to `thread/list` responses.
- Emit `thread/status/changed` notifications with `threadId` and the new
status.
- Track runtime status for all loaded threads and default unknown
threads to `idle`.
- Update protocol/docs/tests/schema fixtures for the revised API.

Testing
- Validated protocol API changes with automated protocol tests and
regenerated schema/type fixtures.
- Validated app-server behavior with unit and integration test suites,
including status transitions and notifications.
2026-02-18 15:20:03 -08:00
Matthew Zeng 216fe7f2ef [apps] Temporary app block. (#12180)
- [x] Temporary app block.
2026-02-18 15:09:30 -08:00
zuxin-oai f8ee18c8cf fix: Remove citation (#12187)
Remove citation requirement until we figure out a better visualization
2026-02-18 21:13:33 +00:00
iceweasel-oai 292542616a app-server support for Windows sandbox setup. (#12025)
app-server support for initiating Windows sandbox setup.
server responds quickly to setup request and makes a future RPC call
back to client when the setup finishes.

The TUI implementation is unaffected but in a future PR I'll update the
TUI to use the shared setup helper
(`windows_sandbox.run_windows_sandbox_setup`)
2026-02-18 13:03:16 -08:00
Curtis 'Fjord' Hawthorne cc248e4681 js_repl: canonicalize paths for node_modules boundary checks (#12177)
## Summary

Fix `js_repl` package-resolution boundary checks for macOS temp
directory path aliasing (`/var` vs `/private/var`).

## Problem

`js_repl` verifies that resolved bare-package imports stay inside a
configured `node_modules` root.
On macOS, temp directories are commonly exposed as `/var/...` but
canonicalize to `/private/var/...`.
Because the boundary check compared raw paths with `path.relative(...)`,
valid resolutions under temp dirs could be misclassified as escaping the
allowed base, causing false `Module not found` errors.

## Changes

- Add `fs` import in the JS kernel.
- Add `canonicalizePath()` using `fs.realpathSync.native(...)` (with
safe fallback).
- Canonicalize both `base` and `resolvedPath` before running the
`node_modules` containment check.

## Impact

- Fixes false-negative boundary checks for valid package resolutions in
macOS temp-dir scenarios.
- Keeps the existing security boundary behavior intact.
- Scope is limited to `js_repl` kernel module path validation logic.



#### [git stack](https://github.com/magus/git-stack-cli)
- 👉 `1` https://github.com/openai/codex/pull/12177
- ⏳ `2` https://github.com/openai/codex/pull/10673
2026-02-18 11:56:45 -08:00
zuxin-oai 82d82d9ca5 memories: bump rollout summary slug cap to 60 (#12167)
## Summary
Increase the rollout summary filename slug cap from 20 to 60 characters
in memory storage.

## What changed
- Updated `ROLLOUT_SLUG_MAX_LEN` from `20` to `60` in:
  - `codex-rs/core/src/memories/storage.rs`
- Updated slug truncation test to verify 60-char behavior.

## Why
This preserves more semantic context in rollout summary filenames while
keeping existing normalization behavior unchanged.

## Testing
- `just fmt`
- `cargo test -p codex-core
memories::storage::tests::rollout_summary_file_stem_sanitizes_and_truncates_slug
-- --exact`
2026-02-18 19:15:07 +00:00
jif-oai f675bf9334 fix: file watcher (#12105)
The issue was that the file_watcher never unsubscribe a file watch. All
of them leave in the owning of the ThreadManager. As a result, for each
newly created thread we create a new file watcher but this one never get
deleted even if we close the thread. On Unix system, a file watcher uses
an `inotify` and after some time we end up having consumed all of them.

This PR adds a mechanism to unsubscribe a file watcher when a thread is
dropped
2026-02-18 18:28:34 +00:00
Eric Traut 999576f7b8 Fixed a hole in token refresh logic for app server (#11802)
We've continued to receive reports from users that they're seeing the
error message "Your access token could not be refreshed because your
refresh token was already used. Please log out and sign in again." This
PR fixes two holes in the token refresh logic that lead to this
condition.

Background: A previous change in token refresh introduced the
`UnauthorizedRecovery` object. It implements a state machine in the core
agent loop that first performs a load of the on-disk auth information
guarded by a check for matching account ID. If it finds that the on-disk
version has been updated by another instance of codex, it uses the
reloaded auth tokens. If the on-disk version hasn't been updated, it
issues a refresh request from the token authority.

There are two problems that this PR addresses:

Problem 1: We weren't doing the same thing for the code path used by the
app server interface. This PR effectively replicates the
`UnauthorizedRecovery` logic for that code path.

Problem 2: The `UnauthorizedRecovery` logic contained a hole in the
`ReloadOutcome::Skipped` case. Here's the scenario. A user starts two
instances of the CLI. Instance 1 is active (working on a task), instance
2 is idle. Both instances have the same in-memory cached tokens. The
user then runs `codex logout` or `codex login` to log in to a separate
account, which overwrites the `auth.json` file. Instance 1 receives a
401 and refreshes its token, but it doesn't write the new token to the
`auth.json` file because the account ID doesn't match. Instance 2 is
later activated and presented with a new task. It immediately hits a 401
and attempts to refresh its token but fails because its cached refresh
token is now invalid. To avoid this situation, I've changed the logic to
immediately fail a token refresh if the user has since logged out or
logged in to another account. This will still be seen as an error by the
user, but the cause will be clearer.

I also took this opportunity to clean up the names of existing functions
to make their roles clearer.
* `try_refresh_token` is renamed `request_chatgpt_token_refresh`
* the existing `refresh_token` is renamed `refresh_token_from_authority`
(there's a new higher-level function named `refresh_token` now)
* `refresh_tokens` is renamed `refresh_and_persist_chatgpt_token`, and
it now implicitly reloads
* `update_tokens` is renamed `persist_tokens`
2026-02-18 09:27:04 -08:00
jif-oai 9f5b17de0d Disable collab tools during review delegation (#12157)
Summary
- prevent delegated review agents from re-enabling blocked tools by
explicitly disabling the Collab feature alongside web search and view
image controls

Testing
- Not run (not requested)
2026-02-18 17:02:49 +00:00
jif-oai 18206a9c1e feat: better slug for rollout summaries (#12135) 2026-02-18 16:39:38 +00:00
Michael Bolin e4539eaf4d merge commit for archive created by Sapling 2026-02-18 08:09:16 -08:00
Michael Bolin 91e650c466 feat: introduce Reject variant of AskForApproval 2026-02-18 08:09:07 -08:00
Michael Bolin e7912a3411 merge commit for archive created by Sapling 2026-02-18 08:02:45 -08:00
Michael Bolin 70e03482bd feat: introduce Reject variant of AskForApproval 2026-02-18 08:02:32 -08:00
Curtis 'Fjord' Hawthorne 491b4946ae Stop filtering model tools in js_repl_tools_only mode (#12069)
## Summary
This change removes tool-list filtering in `js_repl_tools_only` mode and
relies on the normal model tool descriptions, while still enforcing that
tool execution must go through `js_repl` + `codex.tool(...)`.

## Motivation
The previous `js_repl_tools_only` filtering hid most tools from the
model request, which diverged from standard tool-list behavior and made
signatures less discoverable. I tested that this filtering is not
needed, and the model can follow the prompt to only call tools via
`js_repl`.

## What Changed
- `filter_tools_for_model(...)` in `core/src/tools/spec.rs` is now a
pass-through (no filtering when `js_repl_tools_only` is enabled).
- Updated tests to assert that model tools are not filtered in
`js_repl_tools_only` mode.
- Updated dynamic-tool test to assert dynamic tools remain visible in
model tool specs.
- Removed obsolete test helper used only by the old filtering
assertions.

## Safety / Behavior
- This commit does **not** relax execution policy.
- Direct model tool calls remain blocked in `js_repl_tools_only` mode
(except internal `js_repl` tools), and callers are instructed to use
`js_repl` + `codex.tool(...)`.

## Testing
- `cargo test -p codex-core js_repl_tools_only`
- Manual rollout validation showed the model can follow the `js_repl`
routing instructions without needing filtered tool lists.



#### [git stack](https://github.com/magus/git-stack-cli)
- 👉 `1` https://github.com/openai/codex/pull/12069
- ⏳ `2` https://github.com/openai/codex/pull/10673
- ⏳ `3` https://github.com/openai/codex/pull/10670
2026-02-18 07:31:15 -08:00
jif-oai cc3bbd7852 nit: change model for phase 1 (#12137) 2026-02-18 13:55:30 +00:00
jif-oai 7b65b05e87 feat: validate agent config file paths (#12133) 2026-02-18 13:48:52 +00:00
jif-oai a9f5f633b2 feat: memory usage metrics (#12120) 2026-02-18 12:45:19 +00:00
jif-oai 2293ab0e21 feat: phase 2 usage (#12121) 2026-02-18 11:33:55 +00:00
jif-oai f0ee2d9f67 feat: phase 1 and phase 2 e2e latencies (#12124) 2026-02-18 11:30:20 +00:00