Commit Graph

8638 Commits

Author SHA1 Message Date
Michael Bolin
29163eb4d0 Merge bb776026d7 into sapling-pr-archive-bolinfest 2026-02-27 12:51:01 -08:00
Michael Bolin
bb776026d7 fix: use https://git.savannah.gnu.org/git/bash instead of https://github.com/bolinfest/bash 2026-02-27 12:50:49 -08:00
Michael Bolin
6e0f1e9469 fix: disable Bazel builds in CI on ubuntu-24.04-arm until we can stabilize them (#13055)
The other three Bazel builds have experienced low flakiness in my
experience whereas I find myself re-running the `ubuntu-24.04-arm` jobs
often to shake out the flakes. Disabling for now.
2026-02-27 12:49:13 -08:00
Ruslan Nigmatullin
69d7a456bb app-server: Replay pending item requests on thread/resume (#12560)
Replay pending client requests after `thread/resume` and emit resolved
notifications when those requests clear so approval/input UI state stays
in sync after reconnects and across subscribed clients.

Affected RPCs:
- `item/commandExecution/requestApproval`
- `item/fileChange/requestApproval`
- `item/tool/requestUserInput`

Motivation:
- Resumed clients need to see pending approval/input requests that were
already outstanding before the reconnect.
- Clients also need an explicit signal when a pending request resolves
or is cleared so stale UI can be removed on turn start, completion, or
interruption.

Implementation notes:
- Use pending client requests from `OutgoingMessageSender` in order to
replay them after `thread/resume` attaches the connection, using
original request ids.
- Emit `serverRequest/resolved` when pending requests are answered
or cleared by lifecycle cleanup.
- Update the app-server protocol schema, generated TypeScript bindings,
and README docs for the replay/resolution flow.

High-level test plan:
- Added automated coverage for replaying pending command execution and
file change approval requests on `thread/resume`.
- Added automated coverage for resolved notifications in command
approval, file change approval, request_user_input, turn start, and turn
interrupt flows.
- Verified schema/docs updates in the relevant protocol and app-server
tests.

Manual testing:
- Tested reconnect/resume with multiple connections.
- Confirmed state stayed in sync between connections.
2026-02-27 12:45:59 -08:00
Michael Bolin
121318dc80 Merge 012d5b251a into sapling-pr-archive-bolinfest 2026-02-27 12:32:03 -08:00
Michael Bolin
012d5b251a fix: disable Bazel builds in CI on ubuntu-24.04-arm until we can stabilize them 2026-02-27 12:31:46 -08:00
Michael Bolin
5e9c954a6e merge commit for archive created by Sapling 2026-02-27 12:03:57 -08:00
Michael Bolin
a1884681b5 execpolicy: add host_executable() support 2026-02-27 12:03:45 -08:00
Michael Bolin
93bcae4b9a Merge 4318bd0082 into sapling-pr-archive-bolinfest 2026-02-27 11:52:58 -08:00
Michael Bolin
4318bd0082 fix: merge skill permissions into escalated sandbox by default 2026-02-27 11:52:43 -08:00
Michael Bolin
66b0adb34c app-server: deflake running thread resume tests (#13047)
## Why

CI has been intermittently failing in
`suite::v2::thread_resume::thread_resume_rejoins_running_thread_even_with_override_mismatch`
because these running-thread resume tests treated `turn/started` as
proof that the thread was already active.

That signal is too early for this path. `turn/started` is emitted
optimistically from
[`turn_start`](1103d0037e/codex-rs/app-server/src/codex_message_processor.rs (L5757-L5767)).
In `single_client_mode`, the listener skips `current_turn_history`
tracking in
[`codex_message_processor.rs`](1103d0037e/codex-rs/app-server/src/codex_message_processor.rs (L6461-L6465)),
so running-thread resume still depends on `ThreadWatchManager` observing
the core `TurnStarted` event in
[`bespoke_event_handling.rs`](1103d0037e/codex-rs/app-server/src/bespoke_event_handling.rs (L152-L156)).
If `thread/resume` lands in that window, the thread can still look
`Idle` and the assertion flakes.

## What

- Add a helper in `codex-rs/app-server/tests/suite/v2/thread_resume.rs`
that waits for `thread/status/changed` to report `Active` for the target
thread.
- Use that public v2 notification as the synchronization barrier in the
four running-thread resume tests instead of relying on `turn/started`.

## Follow-up

This PR keeps the fix at the test layer so we can remove the flake
without changing server behavior. A broader runtime fix should still be
considered separately, for example:

- make `turn/start` eagerly transition the thread to `Active` so
`turn/started` and `thread/status/changed` are coherent
- or revisit the `single_client_mode` guard that skips current-turn
tracking for running-thread resume

## Testing

- `cargo test -p codex-app-server thread_resume -- --nocapture`
- `for i in $(seq 1 10); do cargo test -p codex-app-server
'suite::v2::thread_resume::thread_resume_rejoins_running_thread_even_with_override_mismatch'
-- --exact --nocapture; done`
2026-02-27 19:47:30 +00:00
Michael Bolin
a68b9cb1f2 merge commit for archive created by Sapling 2026-02-27 11:39:15 -08:00
Michael Bolin
f613814abc core: adopt host_executable() rules in zsh-fork 2026-02-27 11:25:04 -08:00
Michael Bolin
e7cf04363a execpolicy: add host_executable() support 2026-02-27 11:25:04 -08:00
Michael Bolin
d833b4004c Merge 291ea30be1 into sapling-pr-archive-bolinfest 2026-02-27 11:09:49 -08:00
Michael Bolin
291ea30be1 app-server: stabilize running thread resume tests 2026-02-27 11:09:36 -08:00
Michael Bolin
edaa6a8dd3 Merge 58b805a96c into sapling-pr-archive-bolinfest 2026-02-27 11:07:17 -08:00
Michael Bolin
58b805a96c core: adopt host_executable() rules in zsh-fork 2026-02-27 11:06:01 -08:00
Michael Bolin
a9933c78d1 execpolicy: add host_executable() support 2026-02-27 11:05:47 -08:00
Michael Bolin
31a6ef17ff Merge eedb6e3f28 into sapling-pr-archive-bolinfest 2026-02-27 10:38:03 -08:00
Michael Bolin
eedb6e3f28 execpolicy: add host_executable() support 2026-02-27 10:37:56 -08:00
Jeremy Rose
bc0a5843df Align TUI voice transcription audio with 4o ASR (#13030)
## Summary
- switch TUI push-to-talk transcription requests to
`gpt-4o-mini-transcribe`
- prefer 24 kHz mono `i16` microphone configs and normalize voice input
to 24 kHz mono before upload/send
- add unit coverage for the new downmix/resample path

## Testing
- `just fmt`
- `cargo test -p codex-tui`
2026-02-27 18:22:48 +00:00
Felipe Coury
3b5996f988 fix(tui): promote windows terminal diff ansi16 to truecolor (#13016)
## Summary

- Promote ANSI-16 to truecolor for diff rendering when running inside
Windows Terminal
- Respect explicit `FORCE_COLOR` override, skipping promotion when set
- Extract a pure `diff_color_level_for_terminal` function for
testability
- Strip background tints from ANSI-16 diff output, rendering add/delete
lines with foreground color only
- Introduce `RichDiffColorLevel` to type-safely restrict background
fills to truecolor and ansi256

## Problem

Windows Terminal fully supports 24-bit (truecolor) rendering but often
does not provide the usual TERM metadata (`TERM`, `TERM_PROGRAM`,
`COLORTERM`) in `cmd.exe`/PowerShell sessions. In those environments,
`supports-color` can report only ANSI-16 support. The diff renderer
therefore falls back to a 16-color palette, producing washed-out,
hard-to-read diffs.

The screenshots below demonstrate that both PowerShell and cmd.exe don't
set any `*TERM*` environment variables.

| PowerShell | cmd.exe |
|---|---|
| <img width="2032" height="1162" alt="SCR-20260226-nfvy"
src="https://github.com/user-attachments/assets/59e968cc-4add-4c7b-a415-07163297e86a"
/> | <img width="2032" height="1162" alt="SCR-20260226-nfyc"
src="https://github.com/user-attachments/assets/d06b3e39-bf91-4ce3-9705-82bf9563a01b"
/> |


## Mental model

`StdoutColorLevel` (from `supports-color`) is the _detected_ capability.
`DiffColorLevel` is the _intended_ capability for diff rendering. A new
intermediary — `diff_color_level_for_terminal` — maps one to the other
and is the single place where terminal-specific overrides live.

Windows Terminal is detected two independent ways: the `TerminalName`
parsed by `terminal_info()` and the raw presence of `WT_SESSION`. When
`WT_SESSION` is present and `FORCE_COLOR` is not set, we promote
unconditionally to truecolor. When `WT_SESSION` is absent but
`TerminalName::WindowsTerminal` is detected, we promote only the ANSI-16
level (not `Unknown`).

A single override helper — `has_force_color_override()` — checks whether
`FORCE_COLOR` is set. When it is, both the `WT_SESSION` fast-path and
the `TerminalName`-based promotion are suppressed, preserving explicit
user intent.

| PowerShell | cmd.exe | WSL | Bash for Windows |
|---|---|---|---|
|
![SCR-20260226-msrh](https://github.com/user-attachments/assets/0f6297a6-4241-4dbf-b7ff-cf02da8941b0)
|
![SCR-20260226-nbao](https://github.com/user-attachments/assets/bb5ff8a9-903c-4677-a2de-1f6e1f34b18e)
|
![SCR-20260226-nbej](https://github.com/user-attachments/assets/26ecec2c-a7e9-410a-8702-f73995b490a6)
|
![SCR-20260226-nbkz](https://github.com/user-attachments/assets/80c4bf9a-3b41-40e1-bc87-f5c565f96075)
|

## Non-goals

- This does not change color detection for anything outside the diff
renderer (e.g. the chat widget, markdown rendering).
- This does not add a user-facing config knob; `FORCE_COLOR` already
serves that role.

## Tradeoffs

- The `has_wt_session` signal is intentionally kept separate from
`TerminalName::WindowsTerminal`. `terminal_info()` is derived with
`TERM_PROGRAM` precedence, so it can differ from raw `WT_SESSION`.
- Real-world validation in this issue: in both `cmd.exe` and PowerShell,
`TERM`/`TERM_PROGRAM`/`COLORTERM` were absent, so TERM-based capability
hints were unavailable in those sessions.
- Checking `FORCE_COLOR` for presence rather than parsing its value is a
simplification. In practice `supports-color` has already parsed it, so
our check is a coarse "did the user set _anything_?" gate. The effective
color level still comes from `supports-color`.
- When `WT_SESSION` is present without `FORCE_COLOR`, we promote to
truecolor regardless of `stdout_level` (including `Unknown`). This is
aggressive but correct: `WT_SESSION` is a strong signal that we're in
Windows Terminal.
- ANSI-16 add/delete backgrounds (bright green/red) overpower
syntax-highlighted token colors, making diffs harder to read.
Foreground-only cues (colored text, gutter signs) preserve readability
on low-color terminals.

## Architecture

```
stdout_color_level()  ──┐
terminal_info().name  ──┤
WT_SESSION presence   ──┼──▶ diff_color_level_for_terminal() ──▶ DiffColorLevel
FORCE_COLOR presence  ──┘                                            │
                                                                     ▼
                                                          RichDiffColorLevel::from_diff_color_level()
                                                                     │
                                                          ┌──────────┴──────────┐
                                                          │ Some(TrueColor|256) │ → bg tints
                                                          │ None (Ansi16)       │ → fg only
                                                          └─────────────────────┘
```

`diff_color_level()` is the environment-reading entry point; it gathers
the four runtime signals and delegates to the pure, testable
`diff_color_level_for_terminal()`.

## Observability

No new logs or metrics. Incorrect color selection is immediately visible
as broken diff rendering; the test suite covers the decision matrix
exhaustively.

## Tests

Six new unit tests exercise every branch of
`diff_color_level_for_terminal`:

| Test | Inputs | Expected |
|------|--------|----------|
| `windows_terminal_promotes_ansi16_to_truecolor_for_diffs` | Ansi16 +
WindowsTerminal name | TrueColor |
| `wt_session_promotes_ansi16_to_truecolor_for_diffs` | Ansi16 +
WT_SESSION only | TrueColor |
| `non_windows_terminal_keeps_ansi16_diff_palette` | Ansi16 + WezTerm |
Ansi16 |
| `wt_session_promotes_unknown_color_level_to_truecolor` | Unknown +
WT_SESSION | TrueColor |
| `explicit_force_override_keeps_ansi16_on_windows_terminal` | Ansi16 +
WindowsTerminal + FORCE_COLOR | Ansi16 |
| `explicit_force_override_keeps_ansi256_on_windows_terminal` | Ansi256
+ WT_SESSION + FORCE_COLOR | Ansi256 |
| `ansi16_add_style_uses_foreground_only` | Dark + Ansi16 | fg=Green,
bg=None |
| (and any other new snapshot/assertion tests from commits d757fee and
d7c78b3) | | |

## Test plan

- [x] Verify all new unit tests pass (`cargo test -p codex-tui --lib`)
- [x] On Windows Terminal: confirm diffs render with truecolor
backgrounds
- [x] On Windows Terminal with `FORCE_COLOR` set: confirm promotion is
disabled and output follows the forced `supports-color` level
- [x] On macOS/Linux terminals: confirm no behavior change

Fixes https://github.com/openai/codex/issues/12904 
Fixes https://github.com/openai/codex/issues/12890
Fixes https://github.com/openai/codex/issues/12912
Fixes https://github.com/openai/codex/issues/12840
2026-02-27 10:45:59 -07:00
Michael Bolin
d09a7535ed fix: use AbsolutePathBuf for permission profile file roots (#12970)
## Why
`PermissionProfile` should describe filesystem roots as absolute paths
at the type level. Using `PathBuf` in `FileSystemPermissions` made the
shared type too permissive and blurred together three different
deserialization cases:

- skill metadata in `agents/openai.yaml`, where relative paths should
resolve against the skill directory
- app-server API payloads, where callers should have to send absolute
paths
- local tool-call payloads for commands like `shell_command` and
`exec_command`, where `additional_permissions.file_system` may
legitimately be relative to the command `workdir`

This change tightens the shared model without regressing the existing
local command flow.

## What Changed
- changed `protocol::models::FileSystemPermissions` and the app-server
`AdditionalFileSystemPermissions` mirror to use `AbsolutePathBuf`
- wrapped skill metadata deserialization in `AbsolutePathBufGuard`, so
relative permission roots in `agents/openai.yaml` resolve against the
containing skill directory
- kept app-server/API deserialization strict, so relative
`additionalPermissions.fileSystem.*` paths are rejected at the boundary
- restored cwd/workdir-relative deserialization for local tool-call
payloads by parsing `shell`, `shell_command`, and `exec_command`
arguments under an `AbsolutePathBufGuard` rooted at the resolved command
working directory
- simplified runtime additional-permission normalization so it only
canonicalizes and deduplicates absolute roots instead of trying to
recover relative ones later
- updated the app-server schema fixtures, `app-server/README.md`, and
the affected transport/TUI tests to match the final behavior
2026-02-27 17:42:52 +00:00
Michael Bolin
bb3483edaa merge commit for archive created by Sapling 2026-02-27 09:23:35 -08:00
Michael Bolin
717a248adc fix: use AbsolutePathBuf for permission profile file roots 2026-02-27 09:23:29 -08:00
Michael Bolin
ff2fa91c94 merge commit for archive created by Sapling 2026-02-27 09:11:09 -08:00
Michael Bolin
7c5be39b5f fix: use AbsolutePathBuf for permission profile file roots 2026-02-27 09:10:47 -08:00
Michael Bolin
448defb5f6 merge commit for archive created by Sapling 2026-02-27 08:41:51 -08:00
Michael Bolin
93194bcdf4 execpolicy: add host_executable() support 2026-02-27 08:41:40 -08:00
jif-oai
8cf5b00aef fix: more stable notify script (#13011) 2026-02-27 16:05:44 +01:00
jif-oai
fe439afb81 chore: tmp remove awaiter (#13001) 2026-02-27 13:22:17 +01:00
jif-oai
c76bc8d1ce feat: use the memory mode for phase 1 extraction (#13002) 2026-02-27 12:49:03 +01:00
jif-oai
bbd237348d feat: gen memories config (#12999) 2026-02-27 12:38:47 +01:00
jif-oai
a63d8bd569 feat: add use memories config (#12997) 2026-02-27 11:40:54 +01:00
Michael Bolin
e6cd75a684 notify: include client in legacy hook payload (#12968)
## Why

The `notify` hook payload did not identify which Codex client started
the turn. That meant downstream notification hooks could not distinguish
between completions coming from the TUI and completions coming from
app-server clients such as VS Code or Xcode. Now that the Codex App
provides its own desktop notifications, it would be nice to be able to
filter those out.

This change adds that context without changing the existing payload
shape for callers that do not know the client name, and keeps the new
end-to-end test cross-platform.

## What changed

- added an optional top-level `client` field to the legacy `notify` JSON
payload
- threaded that value through `core` and `hooks`; the internal session
and turn state now carries it as `app_server_client_name`
- set the field to `codex-tui` for TUI turns
- captured `initialize.clientInfo.name` in the app server and applied it
to subsequent turns before dispatching hooks
- replaced the notify integration test hook with a `python3` script so
the test does not rely on Unix shell permissions or `bash`
- documented the new field in `docs/config.md`

## Testing

- `cargo test -p codex-hooks`
- `cargo test -p codex-tui`
- `cargo test -p codex-app-server
suite::v2::initialize::turn_start_notify_payload_includes_initialize_client_name
-- --exact --nocapture`
- `cargo test -p codex-core` (`src/lib.rs` passed; `core/tests/all.rs`
still has unrelated existing failures in this environment)

## Docs

The public config reference on `developers.openai.com/codex` should
mention that the legacy `notify` payload may include a top-level
`client` field. The TUI reports `codex-tui`, and the app server reports
`initialize.clientInfo.name` when it is available.
2026-02-26 22:27:34 -08:00
Ahmed Ibrahim
53e28f18cf Add realtime websocket tracing (#12981)
- add transport and conversation logs around connect, close, and parse
flow
- log realtime transport failures as errors for easier debugging
2026-02-26 22:15:18 -08:00
Ahmed Ibrahim
4d180ae428 Add model availability NUX metadata (#12972)
- replace show_nux with structured availability_nux model metadata
- expose availability NUX data through the app-server model API
- update shared fixtures and tests for the new field
2026-02-26 22:02:57 -08:00
alexsong-oai
f53612d3b2 Add a background job to refresh the requirements local cache (#12936)
- Update the cloud requirements cache TTL to 30 minutes.
- Add a background job to refresh the cache every 5 minutes.
- Ensure there is only one refresh job per process.
2026-02-27 04:16:19 +00:00
Eric Traut
cee009d117 Add oauth_resource handling for MCP login flows (#12866)
Addresses bug https://github.com/openai/codex/issues/12589

Builds on community PR #12763.

This adds `oauth_resource` support for MCP `streamable_http` servers and
wires it through the relevant config and login paths. It fixes the bug
where the configured OAuth resource was not reliably included in the
authorization request, causing MCP login to omit the expected
`resource` parameter.
2026-02-26 20:10:12 -08:00
Matthew Zeng
6fe3dc2e22 [apps] Improve app/list with force_fetch=true (#12745)
- [x] Improve app/list with force_fetch=true, we now keep cached
snapshot until both install apps and directory apps load.
2026-02-27 03:54:03 +00:00
Curtis 'Fjord' Hawthorne
7e980d7db6 Support multimodal custom tool outputs (#12948)
## Summary

This changes `custom_tool_call_output` to use the same output payload
shape as `function_call_output`, so freeform tools can return either
plain text or structured content items.

The main goal is to let `js_repl` return image content from nested
`view_image` calls in its own `custom_tool_call_output`, instead of
relying on a separate injected message.

## What changed

- Changed `custom_tool_call_output.output` from `string` to
`FunctionCallOutputPayload`
- Updated freeform tool plumbing to preserve structured output bodies
- Updated `js_repl` to aggregate nested tool content items and attach
them to the outer `js_repl` result
- Removed the old `js_repl` special case that injected `view_image`
results as a separate pending user image message
- Updated normalization/history/truncation paths to handle multimodal
`custom_tool_call_output`
- Regenerated app-server protocol schema artifacts

## Behavior

Direct `view_image` calls still return a `function_call_output` with
image content.

When `view_image` is called inside `js_repl`, the outer `js_repl`
`custom_tool_call_output` now carries:
- an `input_text` item if the JS produced text output
- one or more `input_image` items from nested tool results

So the nested image result now stays inside the `js_repl` tool output
instead of being injected as a separate message.

## Compatibility

This is intended to be backward-compatible for resumed conversations.

Older histories that stored `custom_tool_call_output.output` as a plain
string still deserialize correctly, and older histories that used the
previous injected-image-message flow also continue to resume.

Added regression coverage for resuming a pre-change rollout containing:
- string-valued `custom_tool_call_output`
- legacy injected image message history


#### [git stack](https://github.com/magus/git-stack-cli)
- 👉 `1` https://github.com/openai/codex/pull/12948
2026-02-26 18:17:46 -08:00
Michael Bolin
ed59c49e40 Merge 6bbf5b2c9f into sapling-pr-archive-bolinfest 2026-02-26 17:55:39 -08:00
Michael Bolin
6bbf5b2c9f fix: use AbsolutePathBuf for permission profile file roots 2026-02-26 17:55:31 -08:00
Michael Bolin
ff6efd3ca4 merge commit for archive created by Sapling 2026-02-26 17:47:07 -08:00
Michael Bolin
f0249dc085 notify: include client in legacy hook payload 2026-02-26 17:46:45 -08:00
Ahmed Ibrahim
f90e97e414 Add realtime audio device picker (#12850)
## Summary
- add a dedicated /audio picker for realtime microphone and speaker
selection
- persist realtime audio choices and prompt to restart only local audio
when voice is live
- add snapshot coverage for the new picker surfaces

## Validation
- cargo test -p codex-tui
- cargo insta accept
- just fix -p codex-tui
- just fmt
2026-02-26 17:27:44 -08:00
Michael Bolin
d5f6ed39c9 Merge 554fd38785 into sapling-pr-archive-bolinfest 2026-02-26 17:27:20 -08:00
Michael Bolin
554fd38785 fix: use AbsolutePathBuf for permission profile file roots 2026-02-26 17:27:01 -08:00
Michael Bolin
4a55700f8b merge commit for archive created by Sapling 2026-02-26 17:21:52 -08:00