Commit Graph
2037 Commits
Author SHA1 Message Date
Jeremy RoseandGitHub fac3158c2a Add thread recencyAt for sidebar ordering (#27910)
## Summary

Add a server-owned `recencyAt` timestamp and `recency_at` thread-list
sort key for product recency ordering while preserving the existing
meaning of `updatedAt` as the latest persisted thread mutation.

This is the server-side alternative to #27697. Rather than narrowing
`updatedAt`, clients can sort the sidebar by `recency_at` and continue
treating `updatedAt` as mutation time.

Paired Codex Apps PR:
[openai/openai#1024599](https://github.com/openai/openai/pull/1024599)

## Contract

- `recencyAt` initializes when a thread is created.
- A turn start advances `recencyAt` monotonically.
- Commentary, agent output, tool results, token/accounting updates, turn
completion, archive, unarchive, resume, and generic metadata writes do
not advance it.
- `updatedAt` retains its existing behavior and continues to advance for
persisted thread mutations.
- Current servers populate `recencyAt`; the response field is optional
in generated TypeScript so clients connected to older servers can fall
back to `updatedAt`.
- Filesystem-only fallback uses existing updated/mtime ordering when
SQLite is unavailable.

## Persistence and compatibility

Migration 0038 adds second- and millisecond-precision recency columns,
backfills them from the existing updated timestamp, creates list
indexes, and includes an insert trigger so older binaries writing to a
migrated database seed recency without causing later mutations to
advance it.

Generic metadata upserts preserve existing recency values. Turn-start
updates use a dedicated monotonic touch, and process-local allocation
keeps millisecond cursor values unique. State DB list, search, read,
filtered-list repair, rollout fallback propagation, and app-server
conversions all carry the new field.

## API

`Thread` responses include:

```ts
recencyAt?: number
```

`thread/list` and `thread/search` accept:

```json
{ "sortKey": "recency_at" }
```

Generated TypeScript and JSON schemas are included.

## Validation

- `just test -p codex-state` — 146 passed
- `just test -p codex-rollout` — 69 passed
- `just test -p codex-thread-store` — 81 passed
- `just test -p codex-app-server-protocol` — 231 passed
- Focused app-server list ordering, response mapping, archive/unarchive,
and resume lifecycle tests passed
- Scoped `just fix` for state, rollout, thread-store,
app-server-protocol, and app-server
- `just fmt`
- `git diff --check`
- Independent correctness, simplicity, elegance, security, and
test-quality reviews; actionable ordering, lifecycle, query-projection,
and timestamp-uniqueness findings were addressed
2026-06-16 17:06:22 -07:00
Adam Perry @ OpenAIandGitHub 322b83de5e Clarify model-generated and legacy app path types (#28577)
## Why

`ApiPathString` kind of implies that it can be used anywhere we pull a
path out of JSON, but it's not really appropriate for tool arguments
when the model might generate relative paths.

Prefer `String` for model-generated paths and we can handle the
conversion per feature for now and define a shared abstraction later if
it makes sense.

# What

Rename `ApiPathString` to `AppLegacyPathString` to clarify its role.

Expand the `path-types` skill to tell the model to leave tool args as
bare strings.
2026-06-16 20:47:43 +00:00
jayandGitHub f8f5a6e78f feat(tui): add rate-limit reset redemption to /usage (#28154)
## Why

Codex users can earn personal rate-limit reset credits, but the CLI does
not currently provide a way to view or redeem them. The `/usage` command
restored in #27925 is intended to be the entry point for usage-related
actions, so reset redemption belongs there rather than in a separate
dashed slash command.

Depends on #28143 for the app-server and backend-client reset-credit
APIs.

## What changed

- Turn bare `/usage` into a menu with entries for token activity and
earned rate-limit resets while preserving `/usage daily`, `/usage
weekly`, and `/usage cumulative`.
- Add loading, empty, confirmation, success, retry, and error states
with a caller-generated UUID idempotency key reused across retries of
the same logical reset.
- Show an availability hint only for backend-classified rate-limit
errors with credits available.
- Hide the reset entry for workspace accounts.

## Validation

- `just test -p codex-tui chatwidget::tests::usage` — 19 passed.
- `just fix -p codex-tui` — passed.
- `just fmt` — passed.
- `cargo insta pending-snapshots` from `codex-rs/tui` — no pending
snapshots.

## Examples
<img width="1168" height="304" alt="image"
src="https://github.com/user-attachments/assets/caa4c1e3-e996-494d-ae17-50b521f5dce8"
/>
<img width="908" height="260" alt="image"
src="https://github.com/user-attachments/assets/e38a726b-77cc-4bd0-9ea8-9f3ad21c5768"
/>


### Reset flow
<img width="1509" height="312" alt="image"
src="https://github.com/user-attachments/assets/d987013c-78a5-48a2-ad8d-c61ad267a327"
/>
<img width="585" height="190" alt="image"
src="https://github.com/user-attachments/assets/de32be19-79b9-4a3e-8574-6f1c208c98ae"
/>
<img width="600" height="210" alt="image"
src="https://github.com/user-attachments/assets/88a165cf-796d-4fdc-a7bc-ea89917573da"
/>

<img width="512" height="193" alt="image"
src="https://github.com/user-attachments/assets/d2353998-5aa8-442e-a5f8-3a8a5b832753"
/>
2026-06-16 17:59:40 +00:00
Felipe CouryandGitHub 3ded846488 fix(tui): highlight C++ module files (#28554)
## Why

Codex syntax-highlights diffs for conventional C++ extensions such as
`.cpp` and `.cxx`, but C++ module interface files using `.cppm`, `.ixx`,
or `.cxxm` fall back to plain diff coloring. The bundled syntax set
already includes C++, but it does not resolve those module extensions by
itself.

Closes #28223.

## What changed

- map `.cppm`, `.ixx`, and `.cxxm` to the existing `cpp` syntax in
`render/highlight.rs`
- extend alias-resolution coverage for all three module extensions
- verify `.cpp`, `.cppm`, `.ixx`, and `.cxxm` diffs produce
syntax-highlighted RGB spans while unknown extensions retain the plain
fallback
- snapshot the syntax-colored token segmentation for the supported C++
module extensions

## How to Test

1. Ask Codex to create or modify a C++ module interface file using
`.cppm`, `.ixx`, or `.cxxm`.
2. Confirm C++ tokens in the rendered diff receive syntax colors instead
of only the red/green diff treatment.
3. Modify an equivalent `.cpp` file and confirm its existing
highlighting remains unchanged.
4. Modify a file with an unknown extension and confirm it still uses the
plain diff fallback.

Targeted tests:

- `just test -p codex-tui -E
'test(find_syntax_resolves_languages_and_aliases) |
test(cpp_module_extensions_use_cpp_highlighting) |
test(unknown_extension_falls_back_without_syntax_highlighting)'`
2026-06-16 17:33:13 +00:00
jifandGitHub a544f5a612 chore: side prompt (#28553)
Fix side bug with prompt
2026-06-16 19:05:03 +02:00
Felipe CouryandGitHub 76135cbe7e fix(tui): restore TUI after suspend (#28342)
## Why

On Linux, suspending Codex with `Ctrl+Z` and returning with `fg` can
leave the composer misaligned or inject terminal response bytes such as
focus reports into the prompt. Shell job-control output moves the cursor
while Codex is suspended, and terminal input polling can race with the
responses used to restore the inline viewport.

Fixes #26564.

## What changed

- preserve and restore keyboard reporting without disturbing the parent
terminal stack
- pause terminal event polling while Codex is suspended and flush
buffered input before resuming it
- force crossterm's cached raw-mode state back in sync after the shell
completes its `fg` handoff
- probe the actual post-`fg` cursor position with the tolerant
terminal-response parser, then realign the inline viewport before
redrawing

## How to Test

1. On Linux, start the development TUI with `just c`.
2. Type text into the composer without submitting it.
3. Press `Ctrl+Z`, run any harmless shell command, then run `fg`.
4. Confirm the composer redraws below the shell output, the draft text
is preserved, and no raw escape sequences appear.
5. Repeat the suspend/resume cycle and confirm normal typing still
works.

Targeted tests:

- `cargo test -p codex-tui --lib parses_cursor_position_as_zero_based -j
1`
- `cargo test -p codex-tui --lib tui::event_stream::tests -j 1`
2026-06-16 09:09:24 -07:00
Celia ChenandGitHub 12aaeb7bf8 [codex] expose Bedrock credential source in account/read (#27751)
## Why

`account/read` currently reports only `type: "amazonBedrock"`, so
clients cannot distinguish a Codex-managed Bedrock API key from
credentials supplied by AWS. The app UI needs that distinction to render
the appropriate account state without duplicating provider-auth logic.

Credential-source selection belongs to the Bedrock model provider
because it already owns the precedence between managed Bedrock auth and
the external AWS credential path. This builds on #27443 and #27689.

## What changed

- Added `AmazonBedrockCredentialSource` with `codexManaged` and
`awsManaged` values.
- Included the selected credential source in
`ProviderAccount::AmazonBedrock` and the app-server `Account` response.
- Made `AmazonBedrockModelProvider::account_state()` classify the source
from its managed-auth state.
- Regenerated the app-server JSON and TypeScript schemas.
- Updated app-server account documentation and downstream TUI matches.

`codexManaged` means the provider found a managed Bedrock API key.
`awsManaged` identifies the provider's external AWS credential path; it
does not assert that the AWS credential chain has been validated.

## Testing

- Added model-provider coverage for Codex-managed precedence and
AWS-managed fallback.
- Added app-server protocol serialization coverage for both wire values.
- Added app-server integration coverage for both `account/read`
responses.
- `just test -p codex-protocol -p codex-model-provider -p
codex-app-server-protocol` (497 tests passed).

After rebasing onto #27711, the `codex-app-server` test target compiled
past the image-generation `PathUri` migration. Local linking was then
interrupted by disk exhaustion (`No space left on device`).
2026-06-16 07:14:53 +00:00
charlesgong-openaiandGitHub 314fa3d25b [codex] Record external agent import results (#28396)
## Summary
- restore `externalAgentConfig/import/progress` notifications while
keeping `externalAgentConfig/import/completed` as the must-deliver event
- persist completed external-agent config imports in state DB by
`importId`, including concrete success/failure details for config,
AGENTS.md, skills, plugins, MCP servers, subagents, hooks, commands, and
sessions
- add `externalAgentConfig/import/readHistories` so clients can recover
persisted import results after missing the live completion notification
- include `errorType` on import failures in protocol
responses/notifications and persisted DB JSON so future code can
classify failures without another wire/storage shape change

## Validation
- `git diff --check`
- `just test -p codex-state external_agent_config_imports`
- `just test -p codex-app-server-protocol`
- `CODEX_SQLITE_HOME=/private/tmp/codex-app-server-sqlite-read-details
just test -p codex-app-server
external_agent_config_import_sends_completion_notification_for_sync_only_import`

Also ran earlier broader checks before publishing:
- `just test -p codex-state`
-
`CODEX_SQLITE_HOME=/private/tmp/codex-app-server-external-agent-test-sqlite
just test -p codex-app-server external_agent_config`
- `just test -p codex-external-agent-migration`
2026-06-15 23:17:24 -07:00
pakrym-oaiandGitHub e752f7b4ae [codex] Use expect in integration tests (#28441)
The workspace denies `clippy::expect_used` in production. Although
`clippy.toml` allows `expect` in tests, Bazel Clippy compiles
integration-test helper code in a way that does not receive that
exemption, which encouraged verbose `unwrap_or_else(... panic!(...))`
and equivalent `match`/`let else` forms.

This allows `clippy::expect_used` once at each integration-test crate
root (including aggregated suites and test-support libraries), then
replaces manual panic-based Result and Option unwraps with
`expect`/`expect_err`. Standalone `tests/*.rs` files remain their own
crate roots. Intentional assertion and unexpected-variant panics remain
unchanged, and the production `expect_used = "deny"` lint remains in
place.

The cleanup is mechanical and net-negative in line count.
2026-06-15 21:53:47 -07:00
pakrym-oaiandGitHub 08901fc8e1 [codex] Add interruptible sleep tool (#28429)
## Why

Models sometimes need to pause briefly while waiting for external work,
but using a shell command for that delay ties the wait to a process and
does not naturally resume when new turn input arrives.

## What changed

- add a built-in `sleep` tool behind the under-development `sleep_tool`
feature
- accept a bounded `duration_ms` argument, matching the millisecond
convention used by unified exec
- end the sleep early when either steered user input or mailbox input
arrives
- include elapsed wall-clock time in completed and interrupted outputs
- emit a dedicated core `SleepItem` through `item/started` and
`item/completed`
- expose the sleep item as app-server v2 `ThreadItem::Sleep` and retain
it in reconstructed thread history
- regenerate the configuration schema for the new feature flag
- regenerate app-server JSON and TypeScript schema fixtures

## Test plan

- `just test -p codex-core sleep_tool_follows_feature_gate`
- `just test -p codex-core any_new_input_interrupts_sleep`
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
sleep_emits_started_and_completed_items`
2026-06-15 21:39:21 -07:00
Adam Perry @ OpenAIandGitHub ecfe174d5f Use ApiPathString in app-server filesystem permission paths (#28367)
## Why

Clients running an app-server on one OS and an exec-server on another OS
need to be able to pass sandbox config to app-server that refers to
resources on the executor's foreign OS.

## What

`AbsolutePathBuf` can't represent these paths and we don't want users to
be exposed to `PathUri` yet, so this moves the public app-server API to
be expressed in terms of `ApiPathString`.

Stacked on #28165.

- change app-server v2 filesystem permission paths, including legacy
read/write roots, to `ApiPathString`
- localize API paths through `PathUri` when converting into the current
native core permission types
- make path-bearing permission conversions fallible and surface
localization failures instead of silently treating malformed grants as
ordinary denials
- propagate conversion failures through app-server and TUI approval
handling
- regenerate the app-server JSON and TypeScript schemas
- leave migration TODOs on native-path conversions so they can be
removed once core permission paths use `PathUri`
2026-06-15 19:25:54 -07:00
felixxia-oaiandGitHub 02dce8eb8d [codex] Load API curated marketplace by auth (#28383)
## Summary
- choose the local OpenAI curated marketplace manifest based on auth:
Codex backend auth gets the existing marketplace, direct provider auth
gets `api_marketplace.json`
- include Bedrock API key auth in the direct-provider API marketplace
path
- safely skip the API marketplace when `api_marketplace.json` is absent

## Validation
- `just fmt`
- `git diff --check origin/main...HEAD`
- CI should run the full validation

## Manual Testing

### - New api marketplace not available for API key sign
1. Safely not display anything from api marketplace
<img width="1161" height="289" alt="Screenshot 2026-06-15 at 21 37 43"
src="https://github.com/user-attachments/assets/a5f16642-8a20-4ac1-a0de-1274a4c7b5b2"
/>

### - New api marketplace for API key sign in
1. Setup api_marketplace.json
```
{
  "name": "openai-curated",
  "interface": {
    "displayName": "Codex official"
  },
  "plugins": [
    {
      "name": "linear",
      "source": {
        "source": "local",
        "path": "./plugins/linear"
      },
      "policy": {
        "installation": "AVAILABLE",
        "authentication": "ON_INSTALL"
      },
      "category": "Productivity"
    }
  ]
}
```

2. Log in with API key, observe that only the defined plugin from
api_marketplace.json is available from "Codex Official" (outside of
local testing marketplaces)
<img width="1167" height="446" alt="Screenshot 2026-06-15 at 21 16 53"
src="https://github.com/user-attachments/assets/7cf61477-d826-4ef6-bc05-0a23ac1c0259"
/>

also checked functionality on codex app

### - SiWC users 
Still uses 'default' marketplace.json and renders all plugins
<img width="1171" height="502" alt="Screenshot 2026-06-15 at 21 40 25"
src="https://github.com/user-attachments/assets/d212ea9b-0aa5-470b-8ea4-450efe65bb2b"
/>

also checked functionality on codex app


## Notes
- `just test -p codex-core-plugins` was started locally before splitting
branches, but I stopped relying on local tests per follow-up and left
final validation to PR CI.
2026-06-16 01:16:11 +00:00
Owen LinandGitHub 040dafa32d feat(core): add metadata field to ResponseItem (#28355)
## Description

This PR adds an optional `metadata` field to `ResponseItem` for
Responses API calls. Only mechanical plumbing, no actual values
populated and sent yet. Turns out just adding a new field to
`ResponseItem` has quite a large blast radius already.

This change is backwards compatible because `metadata` is optional and
omitted when absent, so existing response items and rollout history
without it still deserialize and requests that do not set it keep the
same wire shape. For provider compatibility, we strip out `metadata`
before non-OpenAI Responses requests so Azure and AWS Bedrock never see
this field.

My followup PR here will actually make use of it to start storing and
passing along `turn_id`: https://github.com/openai/codex/pull/28360

## What changed

- Added `ResponseItemMetadata` with optional `turn_id`, plus optional
`metadata` on Responses API item variants and inter-agent communication.
- Preserved item metadata through response-item rewrites such as
truncation, missing tool-output synthesis, compaction history
rebuilding, visible-history conversion, rollout/resume, and generated
app-server schemas/types.
- Strip item metadata from non-OpenAI Responses requests while
preserving it for OpenAI-shaped requests.
- Updated the mechanical fixture/test construction churn required by the
new optional field.
2026-06-15 15:05:28 -07:00
jayandGitHub bef99f861b feat(app-server): expose rate-limit reset credits (#28143)
## Why

Codex users can earn personal rate-limit reset credits, but app-server
clients do not currently have an API for reading or redeeming them. This
adds the backend and protocol foundation used by the `/usage` TUI flow
in #28154.

## What changed

- Extend `account/rateLimits/read` with a nullable
`rateLimitResetCredits` summary sourced from the existing usage
response.
- Add backend-client and app-server support for consuming a reset with a
caller-generated idempotency key. A UUID is recommended, and clients
reuse the same key when retrying the same logical reset.
- Return only the consume `outcome`; clients refetch
`account/rateLimits/read` for updated window state.
- Document the response field and each consume outcome, and regenerate
the JSON and TypeScript schema fixtures.
- Clarify in `AGENTS.md` that new app-server string enum values use
camelCase on the wire.
- Update the existing TUI response fixture for the expanded protocol
shape.
- Add coverage for authentication, response mapping, backend failures,
consume outcomes, and request timeout behavior.

## Validation

- `just test -p codex-app-server-protocol` — 231 passed.
- `just test -p codex-backend-client` — 14 passed.
- Focused `codex-app-server` reset-credit tests — 5 passed.
- Focused `codex-tui` protocol response fixture test — passed.
- `just fix -p codex-backend-client -p codex-app-server-protocol -p
codex-app-server` — passed.
- `just fmt` — passed.
2026-06-15 21:54:01 +00:00
Shijie RaoandGitHub 1b81365926 Add request user input auto-resolution timer (#28235)
## Summary
- Add TUI auto-resolution handling for `request_user_input` prompts when
`autoResolutionMs` is present.
- Use a 60s hidden grace period followed by a 60s visible countdown,
then submit an empty answer response if the user does not interact.
- Snooze auto-resolution on key or paste interaction and add
snapshot/test coverage for the countdown UI.

## Notes
- The TUI currently treats `autoResolutionMs` as an enable signal and
intentionally does not use the provided duration value for the countdown
policy.

### Auto resolution


https://github.com/user-attachments/assets/5323152f-2ece-4aba-b75d-c32aa776f544


### Snooze after interaction


https://github.com/user-attachments/assets/100d54c4-3a41-4c6c-9c07-cd28075a0d62
2026-06-15 11:49:19 -07:00
canvrno-oaiandGitHub 29224d945b TUI Plugin Sharing 2 - add remote plugin section plumbing (#26702)
This adds the background plumbing for remote-backed plugin catalog
sections while leaving the fuller directory presentation to the next PR.
The TUI can fetch section-specific remote marketplace results, keep
local plugin data available, and carry section errors forward for later
rendering.

- Fetches explicit remote marketplace kinds for curated, workspace, and
shared-with-me sections.
- Gates shared-with-me loading on the plugin sharing feature flag.
- Adds section-level error state and user-actionable error copy.
- Merges remote marketplace results into the cached plugin list without
discarding local results.
2026-06-15 10:25:37 -07:00
Eric TrautandGitHub 8a6a039f26 Remove terminal resize reflow flag gates (#27794)
## Why

`terminal_resize_reflow` is now stable and should behave as always on.
Keeping the disabled runtime paths around made the feature look
configurable even though the rollout is complete, and old config could
still suggest there was a supported off mode.

## What Changed

- Marked `terminal_resize_reflow` as `Stage::Removed` while keeping it
default-enabled for compatibility.
- Ignored `[features].terminal_resize_reflow` config entries so stale
`false` settings no longer affect the effective feature set.
- Removed TUI branches that depended on the flag being disabled, so
draw, replay buffering, stream finalization, and resize scheduling all
assume resize reflow is active.
- Simplified resize smoke coverage to exercise the always-on behavior
only.

## Verification

- `just test -p codex-features`
- `just test -p codex-tui resize_reflow`
- `just test -p codex-tui initial_replay_buffer
thread_switch_replay_buffer`
2026-06-15 08:23:02 -07:00
Brent TrautandGitHub dfd03ea01b feat(app-server): filter threads by parent (#26662)
## Why

Clients that display or coordinate spawned subagents need an
authoritative snapshot of a thread's immediate spawned children when
they connect to app-server or recover after missing live events.
`thread/list` cannot query by parent, so clients must otherwise scan
unrelated threads or reconstruct relationships from rollout history and
transient events.

The direct spawn relationship already exists in persisted
`thread_spawn_edges` state. Review and Guardian threads do not
participate in that lifecycle and are intentionally outside this
filter's scope.

## What changed

This adds an experimental `parentThreadId` filter to `thread/list`.
Parent-filtered requests return direct spawned children from persisted
state while preserving the existing response shape, explicit filters,
sorting, and timestamp-only cursor behavior. The lookup does not read
rollout transcripts or recursively return descendants.

Supersedes #25112 with the narrower `thread/list` filter approach.

## How it works

1. An experimental client passes a valid thread ID as `parentThreadId`.
2. App-server routes the list through the existing thread-store and
state-database boundaries.
3. SQLite selects threads whose IDs have a direct persisted spawn edge
from that parent.
4. Omitted provider and source filters include all values; explicit
filters keep ordinary `thread/list` semantics.
5. Grandchildren, Review threads, and Guardian threads are excluded.

## Verification

State (144 tests), rollout (69 tests), and focused app-server
thread-list (31 tests) suites passed. Scoped Clippy checks and
repository formatting also passed. Coverage includes direct spawned
children, omitted grandchildren, pagination, malformed IDs, mixed source
kinds, explicit filters, and operation without rollout files.
2026-06-14 00:14:26 -07:00
Adam Perry @ OpenAIandGitHub 740c4f269d build: run buildifier from just fmt (#28125)
## Intent

Keep Bazel and Starlark files consistently formatted without requiring
contributors to install or version buildifier themselves.

## Implementation

- Add a SHA-256-pinned, cross-platform DotSlash manifest for buildifier
v8.5.1.
- Run buildifier from the shared `just fmt` and `just fmt-check` driver,
with Windows-safe explicit DotSlash invocation.
- Provision DotSlash in formatting CI and contributor devcontainers, and
document the source-build prerequisite.
- Apply the initial mechanical buildifier formatting baseline.
2026-06-13 21:43:39 -07:00
Anton PanasenkoandGitHub b9dc3b7a8b feat(app-server): enforce managed remote control disable (#27961)
## Why

Managed deployments need a reliable deny gate for remote control.
Persisted enablement and explicit startup requests currently remain able
to start the transport, while the removed `features.remote_control` key
is intentionally only a compatibility no-op.

This adds a dedicated requirement that administrators can use to force
remote control off without deleting the user's persisted preference.
Removing the requirement and restarting restores the prior choice.

## What Changed

- Added top-level `allow_remote_control` requirements parsing, sourced
layer precedence, debug output, and `configRequirements/read` exposure
as `allowRemoteControl`.
- Added a typed transport policy captured from the startup requirements
snapshot. Managed disable forces the initial state to disabled and
prevents enrollment, refresh, connection, and persisted-preference
mutation.
- Rejected every `remoteControl/*` RPC before parameter deserialization
with JSON-RPC `-32600` and `remote control is disabled by managed
requirements`.
- Preserved the existing disabled status notification and the previous
behavior when the requirement is `true` or omitted.
- Regenerated app-server protocol schemas and documented the new
requirement.

## Verification

- Confirmed all remote-control RPCs, including a malformed request,
return the managed-policy error while the initial status notification
remains `disabled`.
- Confirmed explicit ephemeral startup and persisted enablement make no
backend connection and leave the SQLite preference unchanged.
- Confirmed `allow_remote_control = true` does not enable or block
remote control and `configRequirements/read` returns
`allowRemoteControl: false` for the deny policy.

Related issue: N/A (managed-policy hardening).
2026-06-12 20:10:12 -07:00
Felipe CouryandGitHub c884536d84 feat(tui): reland token activity command (#27925)
## Why

[#25345](https://github.com/openai/codex/pull/25345) was approved,
green, and squash-merged into its stacked base branch,
`fcoury/tokenmaxxing-api`. Four minutes later, that base branch was
force-pushed back to an API-only rebased head while preparing
[#25344](https://github.com/openai/codex/pull/25344) for `main`. As a
result, the squash commit from #25345 was orphaned and the TUI command
never reached `main` or a release.

This PR relands the orphaned TUI change from
[`411410b8`](https://github.com/openai/codex/commit/411410b85c2d8eb050d441f17396c5c4048d866f)
on current `main`.

## What changed

- Add `/usage`, `/usage daily`, `/usage weekly`, and `/usage cumulative`
for account token activity.
- Fetch account usage asynchronously through the existing
`account/usage/read` app-server RPC.
- Render daily, weekly, and cumulative activity with theme-aware
terminal palettes and bounded transient cards.
- Preserve transcript ordering while assistant streams, history
consolidations, active cells, and hooks complete.
- Hide `/usage` from completion when backend auth is unavailable while
keeping typed-command guidance.
- Carry current-main behavior forward for cwd-aware Markdown parsing,
Windows Terminal color detection, and personal access token auth.
- Clear pending usage cards on thread rollback and delay completed cards
until live hook output is committed.
- Add focused regression and snapshot coverage for loading, auth errors,
invalid views, rollback, hook ordering, layout, and charts.

## Prior review

The original implementation was approved by Eric Traut in #25345 after
testing multiple themes and light/dark terminals. This PR preserves that
reviewed implementation while adapting it to current `main` and adding
regression coverage for newer rollback and hook lifecycle behavior.

## Validation

- `just test -p codex-tui token_activity palette renderable
usage_command` — 37 passed.
- Focused rollback, hook-ordering, and error snapshot tests — 4 passed.
- `just fix -p codex-tui` — passed.
- `UV_CACHE_DIR=/private/tmp/codex-uv-cache just fmt` — passed.
- `cargo insta pending-snapshots` — no pending snapshots.
- `just test -p codex-tui` — 2,870 passed; two unrelated guardian
feature-flag tests failed because their expected `OverrideTurnContext`
event was absent:
-
`update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`
-
`update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`
- `just argument-comment-lint` could not complete because the local
Bazel LLVM `compiler-rt` repository is missing `include/sanitizer/*.h`.
The touched Rust diff was manually inspected and no missing
opaque-literal argument comments were found.
2026-06-12 17:33:43 -07:00
Eric TrautandGitHub 9e07892253 [3 of 3] Support images in TUI goals (#27510)
## Stack

1. [1 of 3] Support long raw TUI goal objectives - #27508
2. [2 of 3] Support long pasted text in TUI goals - #27509
3. **[3 of 3] Support images in TUI goals** - this PR

## Why

The first two PRs make goal definitions resilient to long text, but
`/goal` still dropped image inputs from the composer. That meant a user
could attach images while defining a goal and the resulting goal
continuation would not have any useful reference to those images.

Goal state still persists only objective text, so image inputs need to
become paths or URLs that the agent can read later.

## What Changed

- Extends TUI `GoalDraft` with local image attachments and remote image
URLs.
- Copies local goal images through the app-server filesystem layer into
the managed goal attachment directory, then rewrites active image
placeholders to file references.
- Appends unplaced local images and remote image URLs to the objective
as referenced image files or URLs.
- Preserves goal image metadata through live `/goal` submission and
queued `/goal` dispatch.

## Verification

- Added goal materialization coverage for local image files and remote
image URLs.
- Added/updated TUI slash-command coverage showing `/goal` drafts
include attached images instead of dropping them.

## Manual Testing

- Attached an image by bracketed-pasting its local path into a live
`/goal` composer. The `[Image #1]` placeholder became a server-host
`image-1.png` reference, copied bytes matched exactly, and no attachment
was written under the TUI's local home.
- Deleted an image placeholder before submitting a small goal and
verified no image was copied.
- Attached PNG and JPEG files to the same goal. Placeholder order was
preserved as `image-1.png` and `image-2.jpg`, and both remote copies
matched their source bytes.
- Tried extensionless, malformed-extension, and
extension/content-mismatched paths; the composer rejected them as image
attachments before goal dispatch rather than creating misleading managed
image files.
- Combined a local image, a large pasted block, and enough raw text to
exceed 4,000 characters. The remote attachment directory contained the
image, paste sidecar, and `goal-objective.md`; all embedded references
used server-host paths and both payloads matched their sources.
- Submitted an image replacement while a goal was active, verified no
image was copied before confirmation, then canceled and confirmed the
attachment count was unchanged.
2026-06-12 17:14:27 -07:00
canvrno-oaiandGitHub 1bd6b4c41a Promote TUI unified mentions in composer to default mentions feature (#27499)
## Summary

This PR promotes Mentions 2.0 (unified TUI mention popup) to stable and
enables it by default.

- Keep `mentions_v2` as a temporary rollback path to the legacy split
popups (`--disable mentions_v2`).
- Add feature-default and snapshot coverage for the default experience.

## Prior work

- [#19068 — Unified mentions in
TUI](https://github.com/openai/codex/pull/19068)
- [#22375 — Use plugin/list to get plugins for
mentions](https://github.com/openai/codex/pull/22375)
- [#23363 — Unified mentions tweaks and rendering
polish](https://github.com/openai/codex/pull/23363)

## Test plan

- Launch Codex without any feature overrides.
- Type `@` in the TUI composer.
- Confirm the unified mentions menu opens and displays filesystem,
plugin, and skill results.
2026-06-12 16:29:40 -07:00
Eric TrautandGitHub c0f1ec5afd [2 of 3] Support long pasted text in TUI goals (#27509)
## Stack

1. [1 of 3] Support long raw TUI goal objectives - #27508
2. **[2 of 3] Support long pasted text in TUI goals** - this PR
3. [3 of 3] Support images in TUI goals - #27510

## Why

Large text pasted into the TUI composer is represented as a paste
placeholder plus pending paste metadata. For `/goal`, preserving only
the visible placeholder is not enough: the agent would see a short
placeholder string instead of the actual pasted text, and the long-text
support from the first PR would never see the payload.

The TUI also needs to avoid writing stale sidecar files when a user
pastes a large block and then deletes its placeholder before submitting
the goal.

## What Changed

- Introduces a TUI `GoalDraft` for goal submissions so `/goal`, `/goal
edit`, and queued goal commands can carry objective text plus text
elements and pending paste payloads.
- Materializes active pasted-text placeholders to `pasted-text-N.txt`
files through the app-server filesystem path introduced in #27508.
- Rewrites active paste placeholders in the persisted objective to file
references, while leaving literal placeholder-looking text alone.
- Filters out deleted paste placeholders so otherwise-small goals do not
require `$CODEX_HOME` or remote filesystem writes.
- Preserves pending paste metadata when a `/goal` command is queued
before a thread exists.

## Verification

- Added goal materialization tests for active paste placeholders,
deleted paste placeholders, and whitespace-only paste payloads.
- Added/updated TUI slash-command tests for large pasted text, queued
`/goal` commands before thread start, and queued oversized goal
behavior.

## Manual Testing

- Used real terminal bracketed-paste sequences through a remote TUI
session. A 1,228-byte multiline paste became `pasted-text-1.txt`; its
first/last lines and byte count matched exactly, and the persisted
objective referenced the server-host path.
- Pasted a large block, deleted its placeholder, and submitted a small
replacement objective. No new directory or sidecar file was created.
- Added two same-length large pastes to one goal. The composer
disambiguated their visible placeholders, and materialization preserved
order and contents in `pasted-text-1.txt` and `pasted-text-2.txt`.
- Submitted a whitespace-only large paste and verified the goal was
rejected as empty without writing a file.
- Submitted a pasted-text replacement while another goal was active,
verified no file was written before confirmation, then canceled and
confirmed the original goal remained unchanged.
- Combined a large paste with enough raw text to exceed 4,000 characters
after placeholder rewriting. The paste sidecar and `goal-objective.md`
were created in the same remote attachment directory, and `/goal edit`
restored the rewritten objective with its sidecar reference.
2026-06-12 15:34:04 -07:00
Celia ChenandGitHub 56c97e3b5c feat: use encrypted local secrets for CLI auth (#27539)
## Why

Windows Credential Manager limits generic credential blobs to 2,560
bytes. Large serialized ChatGPT auth payloads can exceed that limit, so
keyring-mode CLI auth needs a backend that keeps only the encryption key
in the OS keyring and stores the payload in Codex's encrypted
local-secrets file.

This is the third PR in the encrypted-auth stack:

1. #27504 — feature and config selection
2. #27535 — auth-specific local-secrets namespaces
3. This PR — CLI auth implementation and activation
4. MCP OAuth implementation and activation

## What Changed

- Added encrypted CLI-auth storage using the `CliAuth` secrets
namespace.
- Preserved direct keyring storage for platforms/configurations where it
remains selected.
- Selected the backend consistently for login, logout, refresh,
device-code login, auth loading, and login restrictions.
- Threaded resolved bootstrap/full config through CLI, exec, TUI,
app-server account handling, cloud config, and cloud tasks.
- Removed stale `auth.json` fallback data after successful encrypted
saves and removed encrypted, direct-keyring, and fallback data during
logout.
- Added storage and integration coverage for both direct and encrypted
keyring modes.

MCP OAuth persistence is intentionally left to the next PR.

## Validation

- `just test -p codex-login` — 131 passed
- `just test -p codex-cli` — 280 passed
- `just test -p codex-app-server v2::account` — 25 passed
- `just test -p codex-cloud-config service` — 21 passed, 7 skipped
- `just fix -p codex-login`
- `just fix -p codex-cli`
- `just fmt`
2026-06-12 21:23:50 +00:00
Eric TrautandGitHub 576f603440 Remove TUI realtime voice support (#27801)
## Why

Removes the realtime audio support from TUI.

## What Changed

- Removed the TUI `/realtime` and realtime `/settings` command paths.
- Deleted TUI voice capture/playback, WebRTC session handling,
audio-device selection UI, and recording-meter code.
- Removed TUI realtime tests and snapshots that covered the deleted
surfaces.
- Dropped the TUI-only `cpal` and `codex-realtime-webrtc` dependencies
and refreshed the Rust/Bazel locks.
2026-06-12 14:20:55 -07:00
Won ParkandGitHub b6baa77eec Handle standalone image generation failures as terminal items (#27920)
## Why

Standalone image generation emitted a started item but no terminal item
when the backend failed. Clients could leave the operation unresolved or
render it as successful.

## What changed

- Emit a terminal image-generation item with `status: "failed"` when
generation or editing fails.
- Skip image persistence for failed terminal items.
- Render failed image generation distinctly in TUI history.
- Preserve the status when handling live and replayed terminal items.

## Looks for TUI, App-Side change needed 

<img width="867" height="89" alt="image"
src="https://github.com/user-attachments/assets/9e32342f-a982-411e-8498-456639fc468a"
/>

## Validation

- `just test -p codex-image-generation-extension`
- App-server image-generation tests
- Core stream-event tests
- TUI image-generation lifecycle and snapshot tests
- Scoped Clippy and formatting
2026-06-12 11:57:22 -07:00
Eric NingandGitHub 9600afb1a1 [codex] expose remote plugin share URL (#27890)
## Summary

- expose the remote plugin detail endpoint's `share_url` as nullable
`PluginDetail.shareUrl`
- preserve existing `PluginSummary.shareContext` behavior for local and
workspace sharing flows
- regenerate the app-server TypeScript and JSON schema fixtures

## Why

The remote plugin detail response already includes a canonical
`share_url`, but that value was not surfaced by `plugin/read` for global
plugins. Global plugins intentionally have no `shareContext`, so using
that model for the URL would change the semantics consumed by the
existing share modal.

## User impact

Codex clients can use `PluginDetail.shareUrl` for a remote plugin's
copy-link action, including when the plugin is disabled by an
administrator, without changing existing share-modal or ownership
behavior.

## Validation

- `cargo test -p codex-app-server
plugin_read_includes_share_url_for_admin_disabled_remote_plugin`
- `cargo test -p codex-app-server-protocol
typescript_schema_fixtures_match_generated`
- `cargo test -p codex-app-server-protocol
json_schema_fixtures_match_generated`
- `cargo fmt --all`
2026-06-12 11:53:55 -07:00
Brent TrautandGitHub d735ef162f tui: Allow extra o's in /goal command (#27814)
## Why

The TUI rejected playful `/goal` spellings such as `/goooooooooooal`,
even though Codex Apps accepts them for the World Cup promotion. This
keeps the TUI behavior consistent without changing how the canonical
command is presented.

## How it works

Built-in command lookup recognizes lowercase `go+al` as the existing
`goal` command after normal exact-name parsing fails. The command
catalog remains unchanged, so autocomplete continues to advertise
`/goal` normally.

## Verification

Added lookup-level and end-to-end TUI coverage for the flexible
spelling. The focused tests, scoped Clippy checks, and formatting pass.
The full `codex-tui` suite passed 2,833 of 2,835 tests; the two failing
guardian feature-flag tests reproduce unchanged on fresh `origin/main`.
2026-06-12 09:30:25 -07:00
Eric TrautandGitHub 096e5e76a2 Persist update dismissal without cache (#27783)
## Summary

Choosing “Don’t remind me” can silently fail when `version.json`
disappears before dismissal because `dismiss_version` returns success
without writing anything. The same update can then reappear on the next
launch.

Initialize a minimal `VersionInfo` from the selected version when the
cache cannot be read, then persist the dismissal through the existing
write path.

Fixes #27147
2026-06-12 09:26:08 -07:00
Eric TrautandGitHub 5b8e3c6d40 Reject transcript backtrack in side conversations (#27791)
## Why

Fixes #27735.

Side conversations are ephemeral forks, and thread rollback currently
requires persisted thread history. The normal backtrack path already
rejected editing previous prompts in side conversations, but
transcript-mode backtrack could still call the rollback path and surface
the core `thread/rollback` failure as a TUI error.

## What changed

- Moved the existing side-conversation edit rejection message into
`app_backtrack.rs` so backtrack rollback code can reuse it.
- Added a side-conversation guard in `apply_backtrack_rollback` so
transcript-mode confirmation is rejected before submitting
`thread/rollback`.

## Verification

- `just test -p codex-tui
app::tests::side_backtrack_rejection_reports_unavailable_message_snapshot`
2026-06-12 08:58:08 -07:00
stefanstokic-oaiandGitHub 743a4147d9 [codex] restore source-specific import copy (#27703)
## Summary

- restore source-specific wording across the `/import` picker, lifecycle
messages, diagnostics, and help text
- update the matching Unix and Windows snapshots
- leave import behavior unchanged

## Why

The import path currently supports one source, so the UI should identify
that source directly instead of presenting the flow as
provider-agnostic.

## Validation

- `just test -p codex-tui external_agent_config_migration` (12 passed)
- `just fix -p codex-tui`
- `just fmt`
2026-06-12 10:19:17 -04:00
Shijie RaoandGitHub 216ce03031 Add request_user_input auto-resolution window contract (#27256)
## Why

`request_user_input` is moving beyond its original plan-mode-only
workflow, and future default/goal-mode usage needs a way for the model
to ask helpful but non-blocking questions without forcing the turn to
wait forever. This PR adds an explicit `autoResolutionMs` contract so a
later client/runtime change can auto-resolve unanswered prompts after a
bounded window while leaving truly blocking questions unchanged.

This is contract plumbing only; it does not implement the client-side
timer or auto-selection behavior, and the model-facing description
treats the field as reserved unless the current runtime explicitly
supports auto-resolution.

## What Changed

- Added optional `autoResolutionMs` to the model-facing
`request_user_input` args and core `RequestUserInputEvent`.
- Added model-facing schema text for `autoResolutionMs` while marking it
reserved for runtimes that explicitly support auto-resolution.
- Bounds `autoResolutionMs` to `60_000..=240_000` ms during argument
normalization by clamping out-of-range model-provided values.
- Propagated the field through app-server v2
`ToolRequestUserInputParams`, app-server request forwarding, generated
TypeScript, and JSON schema fixtures.
- Updated app-server, core, protocol, and TUI call sites/tests so
omitted values preserve existing `None`/`null` behavior and coverage
verifies a `Some(60_000)` round trip.

## Verification

- `just test -p codex-app-server-protocol`
- `just test -p codex-core request_user_input`
- `just test -p codex-app-server request_user_input_round_trip`
- `just test -p codex-tui request_user_input`
- `just test -p codex-protocol`
2026-06-11 22:30:41 -07:00
Eric TrautandGitHub 78bab04116 [1 of 3] Support long raw TUI goal objectives (#27508)
## Stack

1. **[1 of 3] Support long raw TUI goal objectives** - this PR
2. [2 of 3] Support long pasted text in TUI goals - #27509
3. [3 of 3] Support images in TUI goals - #27510

## Why

`thread/goal/set` limits persisted objective text to 4000 characters.
The TUI used to reject raw `/goal` objectives above that limit, even
though the client can make them usable by writing the long text to a
file and storing a short objective that points at that file.

This also needs to work for remote app-server sessions: filesystem API
calls must create files on the app-server host, and the stored path must
be meaningful to the agent on that host.

## What Changed

- Adds an app-server-host path helper so TUI code can build paths that
are resolved on the app-server host rather than the TUI host.
- Adds TUI app-server session helpers for `fs/createDirectory`,
`fs/writeFile`, `fs/readFile`, and `fs/remove` that work for embedded
and remote app-server sessions without changing the app-server protocol.
- Materializes oversized raw `/goal` objectives into
`$CODEX_HOME/attachments/<uuid>/goal-objective.md` through the
app-server filesystem APIs, then stores a short, readable objective that
directs the agent to that file.
- Reads managed objective files back for `/goal edit`. Other goal UI
renders the readable stored objective normally, without
managed-file-specific presentation logic.
- Recognizes managed references only when they name the expected
generated file under the app server's reported `$CODEX_HOME`, and cleans
up newly materialized files when goal replacement or setting does not
complete.

## Verification

- Added/updated TUI tests for raw oversized `/goal` submission, large
inline-paste expansion, queued oversized goals, app-facing
materialization before `thread/goal/set`, managed-path validation,
editing, and cleanup.
- Added/updated app-server-client remote coverage for initialized remote
Codex home handling.

## Manual Testing

- Ran the real TUI against a Unix-socket app server with different local
and server `$CODEX_HOME` directories. Oversized goals wrote only under
the server home, and persisted references used the server-canonical path
rather than the TUI path.
- Exercised 3,999-, 4,000-, and 4,001-character raw objectives. The
first two stayed inline without new files; the 4,001-character objective
became a managed objective file.
- Submitted a larger 8,275-character objective, verified its full
contents on the app-server host, and observed the goal continuation open
the referenced server-side file.
- Opened `/goal edit` for a managed objective and verified the full text
was restored through remote `fs/readFile`.
- Submitted an oversized replacement while a goal was active, verified
no file was written before confirmation, then canceled and confirmed
that the existing goal and attachment count were unchanged.
2026-06-11 22:26:31 -07:00
Adam Perry @ OpenAIandGitHub 5a56caf18c [codex] Remove async_trait from first-party code (#27475)
## Why

First-party async traits should expose their `Send` contracts explicitly
without requiring `async_trait`. This completes the migration pattern
established in #27303 and #27304.

## What changed

- Replaced the remaining first-party `async_trait` traits with native
return-position `impl Future + Send` where statically dispatched and
explicit boxed `Send` futures where object safety is required.
- Kept implementations behavior-preserving, outlining existing async
bodies into inherent methods where that keeps the diff reviewable.
- Removed all direct first-party `async-trait` dependencies and the
workspace dependency declaration.
- Added a cargo-deny policy that permits `async-trait` only through the
remaining transitive wrapper crates.
- Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and
keep the full cargo-deny check passing.

## Validation

- `just test -p codex-exec-server`: 216 passed, 2 skipped.
- `just test -p codex-model-provider`: 39 passed.
- `just test -p codex-core` and `just test`: changed tests passed;
remaining failures are environment-sensitive suites unrelated to this
migration.
- `cargo deny check`
- `just fix`
- `just fmt`
- `cargo shear`
- `just bazel-lock-check`
2026-06-11 18:16:39 -07:00
Mitsuhiro KotakeandGitHub 44403dd3dd tui: clear stale hook row after turn completion (#27619)
Fixes #27210.

## Why
When the app server reports a visible `HookStarted` event for a
`PostToolUse` hook but the turn reaches `TurnCompleted` before a
matching hook completion event arrives, the TUI can leave the transient
`Running PostToolUse hook` row visible after the agent is done.
Interrupted and failed turn cleanup already drops transient live hook
rows; the normal completion path did not.

## What Changed
- Added `ChatWidget::clear_active_hook_cell()` for dropping transient
live hook status without writing it to history.
- Call that cleanup from normal task completion, while reusing it for
the existing start/finalize cleanup paths.
- Added `completed_turn_clears_visible_running_hook` snapshot coverage
for the reported `PostToolUse` case.

## Tests
- `just test -p codex-tui completed_turn_clears_visible_running_hook`
- `just test -p codex-tui` (fails on current `main` in unrelated
guardian tests:
`update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`
and
`update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`)
2026-06-12 09:15:04 +09:00
Adam Perry @ OpenAIandGitHub 236b50125d [codex] Load user instructions through an injected provider (#27101)
## Why

We want to remove implicit use of `$CODEX_HOME` from `codex-core` and
make embedders responsible for supplying user-level instructions. This
also ensures user instructions load when no primary environment is
selected.

## What changed

Stacked on #27415, which makes `codex exec` surface thread-scoped
runtime warnings.

- Added `UserInstructionsProvider` to `codex-extension-api`, with
absolute source attribution and recoverable loading warnings.
- Added `codex-home` with the filesystem-backed provider for
`AGENTS.override.md` and `AGENTS.md`, preserving precedence, fallback,
trimming, lossy UTF-8 handling, and the existing uncapped global
instruction size.
- Removed global instruction loading from `Config` and require
`ThreadManager` callers to inject a provider.
- Load provider instructions once for each fresh root runtime, including
runtimes without a primary environment. Running sessions retain their
snapshot, while child agents inherit the parent snapshot without
invoking the provider.
- Keep provider instructions separate while loading project `AGENTS.md`,
then assemble the model-visible instructions with the existing ordering,
source attribution, warning, and turn-context behavior.
- Wired the Codex home provider through the CLI, app server, MCP server,
core facade, and thread-manager sample.

## Validation

- `just test -p codex-home -p codex-extension-api`
- `just test -p codex-core agents_md`
- `just test -p codex-core guardian`
- `just test -p codex-app-server
thread_start_without_selected_environment_includes_only_global_instruction_source`
- `just test -p codex-exec warning`
- `just bazel-lock-check`
2026-06-11 19:28:47 +00:00
charlesgong-openaiandGitHub eb76336f60 [codex] Propagate plugin app categories (#27420)
## What
- Parse optional `.app.json` `category` overrides for plugin apps.
- Add nullable `category` to `AppSummary` and `AppTemplateSummary` in
the app-server protocol.
- Fall back from `branding.category` to the first non-empty
`app_metadata.categories` value when building app/template summaries.
- Regenerate schema/type fixtures and update plugin read/install tests.

## Why
The plugin details UI needs a normalized per-app category. Some apps
only provide their default category in metadata, while others need a
local `.app.json` override.
2026-06-11 10:34:41 -07:00
Eric TrautandGitHub 9d88e299a7 Print TUI session info on fatal exits (#27417)
## Summary

TUI exits printed the resume/session summary only after checking the
exit reason. On fatal exits, both CLI wrappers wrote the error and
called `process::exit(1)` immediately, so an active session that ended
on a fatal error could skip the session information entirely.

This change prints the normal exit summary before returning the fatal
nonzero exit code. If a fatal exit has a known thread id but no
resumable rollout hint, it prints `Session ID: <id>` instead of staying
silent. It also flushes stdout before `process::exit(1)` so the summary
line is not lost during process teardown.

## Implementation

- Apply the fatal-exit ordering fix in both `codex` and standalone
`codex-tui`.
- Keep normal user-requested exit behavior unchanged.
- Preserve the existing resume hint when a rollout is resumable, and use
the raw thread id only as a fatal-exit fallback.
2026-06-11 09:56:09 -07:00
Eric TrautandGitHub 1e5b87b4d7 Remove TUI legacy Windows sandbox dependency (#27490)
## Why

This is part of an ongoing attempt to eliminate the TUI's direct
dependency on core features. When we moved the TUI to the app server, we
left a `legacy_core` shim that re-exported some remaining core symbols
for the TUI. The intent was to eventually remove all of these.

In this PR, we remove the symbols related to the Windows sandbox.

The change should be behavior-neutral and low risk because it's just
refactoring and removal of code that is now effectively dead.

When working on this PR, I noticed a big existing problem that affects
mixed-platform remoting. For example, if you run the TUI on a Linux box
and remote into a Windows box, the TUI logic doesn't properly handle
Windows sandbox setup properly. Fixing this is beyond the scope of this
PR, but I've left a TODO comment in place so we don't forget.

## What changed

- Move the remaining TUI-specific sandbox level, setup, telemetry, and
read-root helpers into `codex-tui`, calling `codex-windows-sandbox`
directly.
- Remove the Windows sandbox namespace and read-root grant re-exports
from the client-side `legacy_core` facade.
- Remove the dormant pre-elevation prompt fallback guarded by the
permanently enabled `ELEVATED_SANDBOX_NUX_ENABLED` switch. The reachable
elevated and non-elevated setup flows remain unchanged.
2026-06-11 09:23:08 -07:00
Celia ChenandGitHub 06afd63f4a feat: add Bedrock API key as a managed auth mode (#27443)
## Why

Codex needs to manage Amazon Bedrock API key credentials through the
existing auth lifecycle instead of introducing a separate auth manager
or provider-specific credential file. Treating Bedrock API key login as
a primary auth mode gives it the same persistence, keyring, reload, and
logout behavior as the existing OpenAI API key and ChatGPT modes.

The credential is valid only for the `amazon-bedrock` model provider.
OpenAI-compatible providers must reject this auth mode rather than
treating the Bedrock key as an OpenAI bearer token.

## What changed

- Added `bedrockApiKey` as an app-server `AuthMode` and
`CodexAuth::BedrockApiKey` as a primary `AuthManager` mode.
- Added `BedrockApiKeyAuth`, containing the API key and AWS region, to
the existing `AuthDotJson` payload stored in `$CODEX_HOME/auth.json` or
the configured keyring backend.
- Added `login_with_bedrock_api_key(...)`, parallel to
`login_with_api_key(...)`, which replaces the current stored login with
Bedrock credentials.
- Reused generic auth reload and logout behavior instead of adding a
Bedrock-specific auth manager or logout path.
- Updated login restrictions, status reporting, diagnostics, telemetry
classification, generated app-server schemas, and auth fixtures for the
new mode.
- Added explicit errors when Bedrock API key auth is selected with an
OpenAI-compatible model provider.

This PR establishes managed storage and auth-mode behavior. Routing the
managed key and region into Amazon Bedrock requests will be in follow-up
PRs.
2026-06-10 20:42:38 -07:00
Eric TrautandGitHub ab4ce40042 Trim TUI legacy telemetry and migration dependencies (#27487)
## Why

The TUI still reached through `codex-app-server-client::legacy_core` for
process telemetry setup and personality migration, exposing core-only
details after the TUI moved onto the app-server layer.

This is part of our ongoing efforts to whittle away at the legacy_core
shim that was left over after migrating the TUI to the app server.

This change is just a refactor/rename and should be behavior-neutral and
low risk.

## What changed

- expose OTEL provider construction through the app-server client and
keep the small process/SQLite telemetry adapters local to the TUI
- collapse personality migration results to the config-reload decision
the TUI needs
- remove the `legacy_core::otel_init` and
`legacy_core::personality_migration` subnamespaces
2026-06-10 19:50:57 -07:00
Eric TrautandGitHub 9d87b771ce Add session delete commands in CLI and TUI (#27476)
## Summary

The app server exposes `thread/delete`, but users cannot invoke it from
the CLI or TUI. Because deletion is irreversible, the user-facing
commands need deliberate confirmation and safer handling of name-based
targets.

- Add `codex delete <SESSION>` with interactive confirmation,
restricting `--force` to UUID targets.
- Resolve exact names across active and archived sessions, including
renamed sessions, and validate prompted UUID targets before
confirmation.
- Add a `/delete` command with a confirmation popup that warns the
current session and its subagent threads will be permanently deleted.

## Manual testing

- Deleted by UUID with `--force` and verified the rollout, session-index
entry, and database row were removed.
- Exercised name-based confirmation for both cancellation and
affirmative deletion; cancellation preserved the session and
confirmation removed it.
- Verified deletion refuses to proceed without `--force`, while
`--force` rejects names, including duplicate names.
- Verified duplicate-name confirmation displays the concrete UUID
selected.
- Deleted an archived session by name.
- Verified an already-missing UUID fails before displaying a
confirmation prompt.
- Exercised `/delete` in the TUI: the popup defaults to No, cancellation
preserves the session, and confirmation deletes the session and exits.
- Verified that `codex delete` works for both archived and non-archived
sessions.
2026-06-10 18:04:02 -07:00
Eric TrautandGitHub 36fc79c6f4 Remove TUI legacy core test_support dependencies (#27484)
## Why

The TUI now sits on the app-server layer, but
`app-server-client::legacy_core` still exposed core test helpers solely
for TUI tests. We've been whittling away the remaining dependencies.
This is the next step on that journey.

There is no functional change — just a refactor, and this affects only
test code, so it should be low risk.

## What changed

- remove the `legacy_core::test_support` re-export and call
model-manager test helpers directly
- keep the bundled model-preset cache local to TUI test support
- import constraint types directly from `codex-config`
2026-06-10 17:55:49 -07:00
xl-openaiandGitHub 1a9efd473b [codex] Remove redundant plugin app auth state (#27465)
## Summary

- remove the redundant `needsAuth` field from `AppSummary` and generated
app-server schemas
- stop `plugin/read` from querying Apps MCP solely to hydrate unused
connector auth state
- preserve `plugin/install.appsNeedingAuth` membership and
`app/list.isAccessible` as the authentication signals

## Why

Codex App and TUI do not consume `plugin/read.plugin.apps[].needsAuth`.
Hydrating it could establish an Apps MCP connection and discover tools
on a cold `plugin/read` request, adding avoidable latency. The plugin
APIs are still marked under development, so removing this wire field is
preferable to retaining a misleading default.

## Verification

- `just write-app-server-schema`
- `just fmt`
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
plugin_install_uses_remote_apps_needing_auth_response`
- `just test -p codex-app-server
plugin_install_returns_apps_needing_auth`
- `just test -p codex-app-server
plugin_read_returns_plugin_details_with_bundle_contents`
- `just test -p codex-tui
plugin_detail_popup_snapshot_shows_install_actions_and_capability_summaries`
- `$xin-build` simplify and debug reviews
2026-06-10 17:33:56 -07:00
stefanstokic-oaiandGitHub b4445f2758 [codex] add /import for external agents (#27071)
## Why

External-agent import should be discoverable and deliberate without
blocking startup or claiming the public `codex [PROMPT]` CLI namespace.
The slash command keeps the flow local to the interactive TUI and reuses
the existing app-server import API.

## What changed

- add the user-facing `/import` slash command
- detect external-agent importable items only when the command is
invoked
- run imports through the embedded local app-server
- show start and completion messages, refresh configuration, and block
duplicate imports while one is pending
- reject the flow for unsupported remote and local-daemon sessions

## Validation

- `just test -p codex-tui external_agent_config_migration` (10 passed)
- manually exercised an isolated TUI fixture with existing
external-agent setup and session data using a fresh `CODEX_HOME`
- verified picker customization, plugin and session detection, import
completion, repeated invocation, and imported-session resume context
- the broader `just test -p codex-tui` run passed 2,805 tests, with 2
unrelated guardian feature-flag failures and 4 skipped tests

## Draft follow-ups

- review whether completion messaging should remain attached to the
initiating chat if the user switches chats during an import
- review shutdown semantics for an in-progress background import

## Stack

1. [#27064](https://github.com/openai/codex/pull/27064): remove the
startup migration flow
2. [#27065](https://github.com/openai/codex/pull/27065): extract the
picker renderer
3. [#27070](https://github.com/openai/codex/pull/27070): add the
external-agent import picker UX
4. [#27071](https://github.com/openai/codex/pull/27071): expose the flow
through `/import`

**This PR is stack item 4.** Draft while the lower stack dependencies
are reviewed.
2026-06-10 15:53:15 -04:00
stefanstokic-oaiandGitHub e3528434cd [codex] add external agent import picker UX (#27070)
## Why

Users need to understand what external-agent data Codex detected, what
is selected, and how to proceed before an import begins. The updated
picker makes focus, selection state, and the submission path explicit
while preserving the existing import backend.

## What changed

- replace the old migration prompt with a two-step external-agent import
picker
- add a customize view with explicit item focus, selection state,
counts, and a review action
- separate detected import data into a view model
- add Unix and Windows snapshots for prompt, item-focus, and
action-focus states

## Validation

- `just test -p codex-tui external_agent_config_migration` (10 passed)
- manually exercised an isolated TUI fixture covering customization,
selection toggles, review, import, repeated invocation, and session
resume
- the broader `just test -p codex-tui` run passed 2,805 tests, with 2
unrelated guardian feature-flag failures and 4 skipped tests

## Review note

This is the largest layer in the stack because the interaction state,
rendering changes, and required snapshots move together. It remains a
draft in case reviewers prefer a further presentation/state split.

## Stack

1. [#27064](https://github.com/openai/codex/pull/27064): remove the
startup migration flow
2. [#27065](https://github.com/openai/codex/pull/27065): extract the
picker renderer
3. [#27070](https://github.com/openai/codex/pull/27070): add the
external-agent import picker UX
4. [#27071](https://github.com/openai/codex/pull/27071): expose the flow
through `/import`

**This PR is stack item 3.** Draft while the lower stack dependencies
are reviewed.
2026-06-10 15:19:37 -04:00
stefanstokic-oaiandGitHub 72667f4f41 [codex] extract external agent import picker renderer (#27065)
## Why

The external-agent import picker is easier to review when its rendering
refactor lands separately from new state and interaction behavior. This
layer is intended to be behavior-neutral.

## What changed

- extract external-agent migration rendering into a dedicated `render`
module
- preserve existing behavior while separating presentation from
interaction logic
- establish a smaller foundation for the import picker UX in the next PR

## Validation

- `just test -p codex-tui external_agent_config_migration` (10 passed)

## Stack

1. [#27064](https://github.com/openai/codex/pull/27064): remove the
startup migration flow
2. [#27065](https://github.com/openai/codex/pull/27065): extract the
picker renderer
3. [#27070](https://github.com/openai/codex/pull/27070): add the
external-agent import picker UX
4. [#27071](https://github.com/openai/codex/pull/27071): expose the flow
through `/import`

**This PR is stack item 2.** Draft while the lower stack dependency is
reviewed.
2026-06-10 14:48:30 -04:00
stefanstokic-oaiandGitHub 636cc11398 [codex] remove blocking external agent migration flow (#27064)
## Why

External-agent import should be initiated deliberately instead of
interrupting eligible TUI startups. This cleanup removes the blocking
startup flow before the replacement import experience is introduced
later in the stack.

## What changed

- remove the startup-blocking external-agent migration prompt
- remove the now-unused external migration feature gate
- remove the obsolete TUI app-server migration wrappers
- retain the dormant picker behind a module-scoped dead-code allowance
until the next stack item wires it back in
- keep normal TUI startup focused on entering Codex immediately

## Validation

- `bazel build --config=clippy //codex-rs/tui:tui
//codex-rs/tui:tui-unit-tests-bin`
- `just test -p codex-tui external_agent_config_migration` (8 passed)
- `just test -p codex-tui` (2,786 passed, 12 unrelated local
environment-sensitive failures, 4 skipped)
- `just fix -p codex-tui`
- `just fmt`

## Stack

1. [#27064](https://github.com/openai/codex/pull/27064): remove the
startup migration flow
2. [#27065](https://github.com/openai/codex/pull/27065): extract the
picker renderer
3. [#27070](https://github.com/openai/codex/pull/27070): add the
external-agent import picker UX
4. [#27071](https://github.com/openai/codex/pull/27071): expose the flow
through `/import`

**This PR is stack item 1.**
2026-06-10 14:25:04 -04:00
David de RegtandGitHub 3691fe5b76 fix: Auto-recover from corrupted sqlite databases (#26859)
Further investigation of the sqlite incidents showed that the problems
are due to corruption from the older version of SQLite that we recently
upgraded, and that the data is truly corrupted in the root database --
recovery of all data is not possible. Given that the data is
reconstructable from the rollouts on disk, we should just auto-backup
the database and let codex rebuild the rollout info from the disk
rollouts.

The new behavior is that appserver auto-backs-up and rebuilds (with logs
reflecting that behavior). The CLI now pops a message letting you know
this happened and the paths of the backed-up corrupt db and the new
database. There is also context added so that the desktop app can read
the rebuild info from it and inform the user with it.
2026-06-10 11:24:29 -07:00