Commit Graph
13591 Commits
Author SHA1 Message Date
Michael Bolin 9fed43acb7 merge commit for archive created by Sapling 2026-04-27 11:20:19 -07:00
Michael Bolin 5ecd51d093 ci: migrate Bazel setup away from archived setup-bazelisk 2026-04-27 11:20:04 -07:00
Michael Bolin 95b294bf61 Merge 4e902ba021 into sapling-pr-archive-bolinfest 2026-04-27 11:15:58 -07:00
Michael Bolin 4e902ba021 ci: migrate Bazel setup away from archived setup-bazelisk 2026-04-27 11:15:49 -07:00
efrazer-oai 2009f6e894 refactor: make auth loading async (#19762)
## Summary

Auth loading used to expose synchronous construction helpers in several
places even though some auth sources now need async work. This PR makes
the auth-loading surface async and updates the callers to await it.

This is intentionally only plumbing. It does not change how
AgentIdentity tokens are decoded, how task runtime ids are allocated, or
how JWT signatures are verified.

## Stack

1. **This PR:** [refactor: make auth loading
async](https://github.com/openai/codex/pull/19762)
2. [refactor: load AgentIdentity runtime
eagerly](https://github.com/openai/codex/pull/19763)
3. [feat: verify AgentIdentity JWTs with
JWKS](https://github.com/openai/codex/pull/19764)

## Important call sites

| Area | Change |
| --- | --- |
| `codex-login` auth loading | `CodexAuth` and `AuthManager`
construction paths now await auth loading. |
| app-server startup | Auth manager construction is awaited during
initialization. |
| CLI/TUI/exec/MCP/chatgpt callers | Existing auth-loading calls now
await the same behavior. |
| cloud requirements storage loader | The loader becomes async so it can
share the same auth construction path. |
| auth tests | Tests that load auth now run in async contexts. |

## Testing

Tests: targeted Rust auth test compilation, formatter, scoped Clippy
fix, and Bazel lock check.
2026-04-27 11:00:27 -07:00
Michael Bolin 34842da8e8 merge commit for archive created by Sapling 2026-04-27 10:57:37 -07:00
Michael Bolin 015d927617 permissions: remove cwd special path 2026-04-27 10:42:51 -07:00
pakrym-oai 4ed22fc7d2 Streamline plugin, apps, and skills handlers (#19490)
## Why

The plugin, app, and skills handlers had a lot of repeated
`send_error`/`return` branches that made the success path hard to scan.
This slice keeps behavior the same while moving fallible steps into
local response-producing helpers, so the request boundary can send one
result.

## What Changed

- Converted plugin list/install/uninstall handlers in
`codex-rs/app-server/src/codex_message_processor/plugins.rs` to return
`Result<*Response, JSONRPCErrorError>` from helper methods and call
`send_result` once.
- Added local error-mapping helpers for plugin install/uninstall and
marketplace failures.
- Applied the same mechanical shape to app list, skills list/config, and
marketplace add/remove/upgrade handlers in
`codex-rs/app-server/src/codex_message_processor.rs`.

## Verification

- `cargo check -p codex-app-server`
- `cargo test -p codex-app-server --test all v2::app_list --
--test-threads=1`
- `cargo test -p codex-app-server --test all v2::plugin_ --
--test-threads=1`
- `cargo test -p codex-app-server --test all v2::skills_list --
--test-threads=1`
2026-04-27 10:18:25 -07:00
Eric Traut 48dd7b58f0 Render delegated patch approval details (#19709)
## Why

Fixes #19632.

When a delegated agent requests approval for an in-progress file change,
the parent TUI handles that request from an inactive thread. The app
server already sent the `FileChange` item with the proposed diff, but
the inactive-thread approval path was not recovering and rendering it
the same way as the active-thread path.

The result was an inconsistent approval prompt: main-thread edits show a
normal patch preview history item before the approval modal, while
delegated edits did not show that preview in the transcript flow.

## What Changed

- Recover buffered or historical `FileChange` item changes when building
inactive-thread file-change approval requests.
- Reuse the app-server file-change conversion helper for both live
transcript rendering and inactive-thread approvals.
- Render recovered delegated patches as a normal patch preview history
cell before the approval modal.
- Keep apply-patch approval modals focused on the decision prompt and
optional metadata; they do not render a synthetic command line or embed
the diff body.

## Manual Repro And Verification

I manually reproduced the issue using a file under `~/Desktop` so the
write would require approval.

Before the fix:

1. Ask the main thread: `Use apply_patch, not shell redirection or
Python, to create ~/Desktop/bug1.txt with three short lines.`
2. Observe the expected TUI shape: the transcript shows a normal patch
preview such as `• Added ~/Desktop/bug1.txt (+N -0)` above the approval
modal, and the modal contains only the approval prompt/options without a
synthetic command line.
3. Ask for the delegated path: `Spawn a worker. Have it use apply_patch,
not shell redirection or Python, to create ~/Desktop/bug1.txt with four
short lines.`
4. Observe the delegated approval is inconsistent: the parent view does
not render the proposed patch as the normal transcript preview before
the modal, so the diff context is missing from the stream or appears
inside the modal instead of in the history flow.

After the fix:

1. Repeat the delegated worker prompt with `apply_patch`.
2. Confirm the parent view renders the same normal patch preview history
cell (`• Added ~/Desktop/bug1.txt (+N -0)` plus the diff) immediately
before the approval modal.
3. Confirm the approval modal remains focused on the decision prompt.
For delegated approvals it may show the worker thread label, but it
should not show a `$ apply_patch` command line or embed the diff body in
the modal.
2026-04-27 10:07:15 -07:00
Eric Traut 0e2300c02c Persist shell mode commands in prompt history (#19618)
## Why

`!` shell commands are currently surfaced as "Bash mode", which is
misleading for users running shells such as PowerShell or zsh. Those
commands also bypass the persistent prompt history path, so they cannot
be recalled after starting a new session.

Fixes #19613.

## What changed

- Rename the TUI footer label and related test wording from "Bash mode"
to "Shell mode".
- Persist accepted `!` shell commands to prompt history with the leading
`!`, so recall restores the composer into shell mode across sessions.
- Add coverage for immediate and queued shell-command submissions
emitting the prompt-history update.

## Verification

- `cargo test -p codex-tui bang_shell`
- `cargo test -p codex-tui shell_command_uses_shell_accent_style`
- `cargo test -p codex-tui footer_mode_snapshots`
- `cargo insta pending-snapshots --manifest-path tui/Cargo.toml`

Manually verified fix after confirming presence of bug prior to fix.
2026-04-27 09:54:25 -07:00
Eric Traut 6c51bf0c7c Hide rewind preview when no user message exists (#19510)
## Why

Fixes #19508.

In a fresh TUI session, pressing `Esc` twice entered the rewind
transcript overlay even though there was no user message to rewind to.
That produced an empty header-only transcript view and exposed a rewind
flow that could not select a valid target.

## What changed

The backtrack flow now checks whether a user-message rewind target
exists before opening the transcript preview. If no target exists, Codex
stays in the main TUI and shows `No previous message to edit.` instead
of opening an empty overlay.

The same guard applies when starting rewind preview from the transcript
overlay, and the first `Esc` no longer advertises the “edit previous
message” hint when there is no previous message available.

Snapshot coverage was added for the unavailable rewind info message,
along with a small target-detection test.
2026-04-27 09:51:12 -07:00
Michael Bolin 61270b945f merge commit for archive created by Sapling 2026-04-27 09:46:41 -07:00
Michael Bolin c3bceefa7a permissions: store thread sessions as profiles 2026-04-27 09:46:12 -07:00
Michael Bolin b392db1437 permissions: derive snapshot sandbox projections 2026-04-27 09:46:12 -07:00
Michael Bolin cb0186b855 permissions: make SessionConfigured profile-only 2026-04-27 09:46:12 -07:00
Michael Bolin 86504e2b1c permissions: require profiles in TUI thread state 2026-04-27 09:46:12 -07:00
Michael Bolin b1c33f60e4 permissions: derive config defaults as profiles 2026-04-27 09:45:54 -07:00
Michael Bolin c101238e1e merge commit for archive created by Sapling 2026-04-27 09:30:49 -07:00
Michael Bolin 33fb299b17 permissions: store thread sessions as profiles 2026-04-27 09:30:32 -07:00
Michael Bolin 4e3c8ecc07 permissions: derive snapshot sandbox projections 2026-04-27 09:30:32 -07:00
Michael Bolin 347c6f7845 permissions: make SessionConfigured profile-only 2026-04-27 09:30:32 -07:00
Michael Bolin 0519638f62 permissions: require profiles in TUI thread state 2026-04-27 09:30:32 -07:00
Michael Bolin d0c5aa8d76 permissions: derive config defaults as profiles 2026-04-27 09:30:32 -07:00
jif-oai bb83eec825 chore: split memories part 1 (#19818)
Extract memories into 2 different crates
2026-04-27 16:01:05 +02:00
jif-oai f431ec12c9 nit: one more fix (#19813)
Fix this:
https://github.com/openai/codex/pull/19812#discussion_r3147529230
2026-04-27 15:32:31 +02:00
jif-oai 79b4f691a6 Avoid rewriting Phase 2 selection on clean workspace (#19812)
## Why

Phase 2 can now claim the global consolidation lock on startup even when
the git-backed memory workspace is already clean. The clean-workspace
path still finalized through the normal Phase 2 success path, which
clears and re-marks `selected_for_phase2` rows. That made no-op startups
perform avoidable writes to `stage1_outputs`, creating unnecessary DB
I/O and contention when no memory files changed.

## What Changed

- Added a preserving-selection Phase 2 finalizer in `codex-state` that
only marks the global job row as succeeded.
- Kept the existing `mark_global_phase2_job_succeeded` behavior for real
consolidation runs, where the selected Phase 2 snapshot must be
rewritten.
- Switched the `succeeded_no_workspace_changes` branch in
`core/src/memories/phase2.rs` to use the preserving-selection finalizer.
- Added a regression test that installs a SQLite trigger on
`stage1_outputs` and verifies the clean finalizer performs zero updates
there.

## Testing

- `cargo test -p codex-state`
- `cargo test -p codex-core memories::tests::phase2`
2026-04-27 15:14:16 +02:00
jif-oai 5d314f324c Allow Phase 2 memory claims after retry exhaustion (#19809)
## Why

The Phase 2 memories job row is only the global lock for the git-backed
memory workspace. Manual memory edits do not enqueue new Stage 1 work,
so a Phase 2 row with `retry_remaining = 0` could be skipped before the
worker ever claimed the lock and generated `phase2_workspace_diff.md`.

That left workspace-only changes unconsolidated after repeated failures,
even when retry backoff had elapsed and the filesystem had real diffable
work.

## What Changed

- Allow `try_claim_global_phase2_job` to claim the Phase 2 lock after
the retry budget is exhausted, while still respecting active `retry_at`
backoff and fresh running leases.
- Treat `SkippedRetryUnavailable` for Phase 2 as backoff-only, and
update the outcome docs to match.
- Clamp Phase 2 retry bookkeeping at zero when failed attempts are
recorded.

## Verification

- Added
`phase2_global_lock_can_be_claimed_after_retry_budget_is_exhausted` to
cover the exhausted-budget lock claim path.
- Ran `cargo test -p codex-state`.
2026-04-27 14:58:11 +02:00
jif-oaiandCodex 01ab25dbb5 feat: use git-backed workspace diffs for memory consolidation (#18982)
## Why

This PR make the `morpheus` agent (memory phase 2) use a git diff to
start it's consolidation. The workflow is the following:
1. The agent acquire a lock
2. If `.codex/memories` does not exist or is not a git root, initialize
everything (and make a first empty commit)
3. Update `raw_memories.md` and `rollout_summaries/` as before.
Basically we select max N phase 1 memories based on a given policy
4. We use git (`gix`) to get a diff between the current state of
`.codex/memories` and the last commit.
5. Dump the diff in `phase2_workspace_diff.md`
6. Spawn `morpheus` and point it to `phase2_workspace_diff.md`
7. Wait for `morpheus` to be done
8. Re-create a new `.git` and make one single commit on it. We do this
because we don't want to preserve history through `.git` and this is
cheap anyway
9. We release the lock
On top of this, we keep the retry policies etc etc

The goals of this new workflow are:
* Better support of any memory extensions such as `chronicle`
* Allow the user to manually edit memories and this will be considered
by the phase 2 agent
 
As a follow-up we will need to add support for user's edition while
`morpheus` is running

## What Changed

- Added memory workspace helpers that prepare the git baseline, compute
the diff, write `phase2_workspace_diff.md`, and reset the baseline after
successful consolidation.
- Updated Phase 2 to sync current inputs into `raw_memories.md` and
`rollout_summaries/`, prune old extension resources, skip clean
workspaces, and run the consolidation subagent only when the workspace
has changes.
- Tightened Phase 2 job ownership around long-running consolidation with
heartbeats and an ownership check before resetting the baseline.
- Simplified the prompt and state APIs so DB watermarks are bookkeeping,
while workspace dirtiness decides whether consolidation work exists.
- Updated the memory pipeline README and tests for workspace diffs,
extension-resource cleanup, pollution-driven forgetting, selection
ranking, and baseline persistence.

## Verification

- Added/updated coverage in `core/src/memories/tests.rs`,
`core/src/memories/workspace_tests.rs`, `state/src/runtime/memories.rs`,
and `core/tests/suite/memories.rs`.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-27 14:32:44 +02:00
jif-oaiandCodex f8c527e529 multi_agent_v2: move thread cap into feature config (#19792)
## Why

`features.multi_agent_v2.max_concurrent_threads_per_session` is meant to
be the MultiAgentV2-specific session thread cap: it counts the root
thread and all open subagent threads. The previous implementation kept
this surface tied to `agents.max_threads`, which made it a global
subagent-only cap and allowed the legacy setting to coexist with
MultiAgentV2.

## What Changed

- Added `max_concurrent_threads_per_session` to
`[features.multi_agent_v2]` with default `4`.
- Removed the `[agents] max_concurrent_threads_per_session` alias to
`agents.max_threads`.
- When MultiAgentV2 is enabled, reject `agents.max_threads` and derive
the existing internal subagent slot limit as
`max_concurrent_threads_per_session - 1`.
- Regenerated `core/config.schema.json` and added coverage for the new
config semantics.

## Result
```
➜  codex git:(jif/clean-multi-agent-v2-config) codex -c features.multi_agent_v2.enabled=true -c features.multi_agent_v2.max_concurrent_threads_per_session=3
╭────────────────────────────────────────────────────╮
│ >_ OpenAI Codex (v0.0.0)                           │
│                                                    │
│ model:     gpt-5.5 xhigh   fast   /model to change │
│ directory: ~/code/codex                            │
╰────────────────────────────────────────────────────╯

  Tip: Update Required - This version will no longer be supported starting May 8th. Please upgrade to the latest version (https://github.com/openai/codex/releases/latest) using your preferred package manager.

› Can you try to spawn 4 agents


• I’ll try to start four lightweight agents at once and report exactly what the runtime accepts.

• Spawned Russell [no-apps] (gpt-5.5 xhigh)
  └ Spawn probe 1: reply briefly that you started, then wait for further instructions. Do not do any repo work.

• Spawned Descartes [no-apps] (gpt-5.5 xhigh)
  └ Spawn probe 2: reply briefly that you started, then wait for further instructions. Do not do any repo work.

• Agent spawn failed
  └ Spawn probe 3: reply briefly that you started, then wait for further instructions. Do not do any repo work.

• Agent spawn failed
  └ Spawn probe 4: reply briefly that you started, then wait for further instructions. Do not do any repo work.

• The runtime accepted the first two and rejected the next two with agent thread limit reached. I’m checking whether the two accepted probes have returned cleanly, then I’ll close them if needed.
```

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-27 13:31:56 +02:00
Michael Bolin 33f5c355cc merge commit for archive created by Sapling 2026-04-27 00:14:24 -07:00
Michael Bolin 1db629a898 permissions: store thread sessions as profiles 2026-04-27 00:14:15 -07:00
Michael Bolin 6c92cc403f permissions: derive snapshot sandbox projections 2026-04-27 00:14:15 -07:00
Michael Bolin cac068aaea permissions: make SessionConfigured profile-only 2026-04-27 00:14:15 -07:00
Michael Bolin c543c8d681 permissions: require profiles in TUI thread state 2026-04-27 00:14:15 -07:00
Michael Bolin c70c0f5c94 permissions: derive config defaults as profiles 2026-04-27 00:14:15 -07:00
Michael Bolin 6a5caf6fea merge commit for archive created by Sapling 2026-04-27 00:06:57 -07:00
Michael Bolin cdce5b96cd permissions: store thread sessions as profiles 2026-04-27 00:06:46 -07:00
Michael Bolin c9269a0172 permissions: derive snapshot sandbox projections 2026-04-27 00:06:46 -07:00
Michael Bolin 72111af108 permissions: make SessionConfigured profile-only 2026-04-27 00:06:46 -07:00
Michael Bolin dbfac94307 permissions: require profiles in TUI thread state 2026-04-27 00:06:46 -07:00
Michael Bolin c188a22f48 permissions: derive config defaults as profiles 2026-04-27 00:06:46 -07:00
Michael Bolin c8445b0caa merge commit for archive created by Sapling 2026-04-26 23:55:16 -07:00
Michael Bolin 25c6ddbe69 permissions: store thread sessions as profiles 2026-04-26 23:54:56 -07:00
Michael Bolin eddf0715f1 permissions: derive snapshot sandbox projections 2026-04-26 23:54:56 -07:00
Michael Bolin 08769b8684 Merge 8fff5bce53 into sapling-pr-archive-bolinfest 2026-04-26 23:46:08 -07:00
Michael Bolin 241de1c43e permissions: make SessionConfigured profile-only 2026-04-26 23:45:53 -07:00
Michael Bolin 8fff5bce53 permissions: store thread sessions as profiles 2026-04-26 23:45:53 -07:00
Michael Bolin 6af2340e55 permissions: derive snapshot sandbox projections 2026-04-26 23:45:53 -07:00
Michael Bolin ead23dce4c merge commit for archive created by Sapling 2026-04-26 23:36:06 -07:00
Michael Bolin 94e89b575b permissions: store thread sessions as profiles 2026-04-26 23:33:42 -07:00