Commit Graph

4434 Commits

Author SHA1 Message Date
Charles Cunningham
5543aceaaa Document rollout metadata builder scan
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 18:48:17 -07:00
Charles Cunningham
39e057131a Fix rollout store rename after rebase
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 17:06:49 -07:00
Charles Cunningham
6e2682fb9d Collect rollout git metadata at write time
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:55 -07:00
Charles Cunningham
4c27c32f19 Simplify rollout metadata builder scan
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:55 -07:00
Charles Cunningham
00d58bff2f Clarify rollout path materialization docs
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:55 -07:00
Charles Cunningham
50fe1fa89b Simplify resumed rollout startup paths
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:55 -07:00
Charles Cunningham
34eb24848a Avoid awaiting rollout sends under source lock
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:55 -07:00
Charles Cunningham
37f1f32899 codex: fix remaining CI regressions
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
d326eab70c codex: fix core CI fallout after rebase
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
59f4327e0c Avoid cloning rollout source during resume reconstruction
Borrow the in-memory rollout source when reconstructing resumed history, tool selection, and token usage instead of cloning the full rollout into a second buffer during startup.

Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
7363f87ac8 Restore deferred rollout materialization semantics
Reinstate main's deferred rollout persistence behavior while keeping the shared rollout source groundwork. Materialize the rollout on first persisted user-visible activity, restore app-server's unmaterialized-thread handling, and keep in-memory rollout state aligned with persisted session metadata.

Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
50c70d2af7 codex: simplify rollout metadata update path
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
0e1309282f codex: address PR review feedback (#13096)
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
b668dae035 codex: fix CI failure on PR #13096
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
3c072cf30e codex: fix CI failures on PR #13096
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
Charles Cunningham
61a0323a32 Introduce rollout source groundwork
Co-authored-by: Codex <noreply@openai.com>
2026-03-10 15:37:54 -07:00
pakrym-oai
c7e28cffab Add output schema to MCP tools and expose MCP tool results in code mode (#14236)
Summary
- drop `McpToolOutput` in favor of `CallToolResult`, moving its helpers
to keep MCP tooling focused on the final result shape
- wire the new schema definitions through code mode, context, handlers,
and spec modules so MCP tools serialize the exact output shape expected
by the model
- extend code mode tests to cover multiple MCP call scenarios and ensure
the serialized data matches the new schema
- refresh JS runner helpers and protocol models alongside the schema
changes

Testing
- Not run (not requested)
2026-03-10 15:25:19 -07:00
Dylan Hurd
15163050dc app-server: propagate nested experimental gating for AskForApproval::Reject (#14191)
## Summary
This change makes `AskForApproval::Reject` gate correctly anywhere it
appears inside otherwise-stable app-server protocol types.

Previously, experimental gating for `approval_policy: Reject` was
handled with request-specific logic in `ClientRequest` detection. That
covered a few request params types, but it did not generalize to other
nested uses such as `ProfileV2`, `Config`, `ConfigReadResponse`, or
`ConfigRequirements`.

This PR replaces that ad hoc handling with a generic nested experimental
propagation mechanism.

## Testing

seeing this when run app-server-test-client without experimental api
enabled:
```
 initialize response: InitializeResponse { user_agent: "codex-toy-app-server/0.0.0 (Mac OS 26.3.1; arm64) vscode/2.4.36 (codex-toy-app-server; 0.0.0)" }
> {
>   "id": "50244f6a-270a-425d-ace0-e9e98205bde7",
>   "method": "thread/start",
>   "params": {
>     "approvalPolicy": {
>       "reject": {
>         "mcp_elicitations": false,
>         "request_permissions": true,
>         "rules": false,
>         "sandbox_approval": true
>       }
>     },
>     "baseInstructions": null,
>     "config": null,
>     "cwd": null,
>     "developerInstructions": null,
>     "dynamicTools": null,
>     "ephemeral": null,
>     "experimentalRawEvents": false,
>     "mockExperimentalField": null,
>     "model": null,
>     "modelProvider": null,
>     "persistExtendedHistory": false,
>     "personality": null,
>     "sandbox": null,
>     "serviceName": null
>   }
> }
< {
<   "error": {
<     "code": -32600,
<     "message": "askForApproval.reject requires experimentalApi capability"
<   },
<   "id": "50244f6a-270a-425d-ace0-e9e98205bde7"
< }
[verified] thread/start rejected approvalPolicy=Reject without experimentalApi
```

---------

Co-authored-by: celia-oai <celia@openai.com>
2026-03-10 22:21:52 +00:00
Won Park
28934762d0 unifying all image saves to /tmp to bug-proof (#14149)
image-gen feature will have the model saving to /tmp by default + at all
times
2026-03-10 15:13:12 -07:00
Ahmed Ibrahim
2895d3571b Add spawn_agent model overrides (#14160)
- add `model` and `reasoning_effort` to the `spawn_agent` schema so the
values pass through
- validate requested models against `model.model` and only check that
the selected model supports the requested reasoning effort

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-10 14:04:04 -07:00
Owen Lin
9b3332e62f fix(python-sdk): stop checking in codex binaries; stage pinned runtim… (#14232)
…e package

## Summary

This changes the Python SDK packaging model so we no longer commit
`codex`
binaries into `sdk/python`.

Instead, published SDK builds now depend on a separate `codex-cli-bin`
runtime
package that carries the platform-specific `codex` binary. The SDK and
runtime
can be staged together with an exact version pin, so the published
Python SDK
still resolves to a Codex version we know is compatible.

The SDK now resolves `codex` in this order:

- `AppServerConfig.codex_bin` if explicitly set
- installed `codex-cli-bin` runtime package

There is no `PATH` fallback anymore. Published installs either use the
pinned
runtime or fail loudly, and local development uses an explicit
`codex_bin`
override when working from the repo.

## What changed

- removed checked-in binaries from `sdk/python/src/codex_app_server/bin`
- changed `AppServerClient` to resolve `codex` from:
  - explicit `AppServerConfig.codex_bin`
  - installed `codex-cli-bin`
- kept `AppServerConfig.codex_bin` override support for local/dev use
- added a new `sdk/python-runtime` package template for the pinned
runtime
- updated `scripts/update_sdk_artifacts.py` to stage releasable
SDK/runtime
  packages instead of downloading binaries into the repo
- made `codex-cli-bin` build as a platform-specific wheel
- made `codex-cli-bin` wheel-only by rejecting `sdist` builds
- updated docs/tests to match the new packaging flow and explicit
local-dev
  contract

## Why

Checking in six platform binaries made the repo much heavier and tied
normal
source changes to release artifacts.

This keeps the compatibility guarantees we want, but moves them into
packaging:

- the published SDK can depend on an exact `codex-cli-bin==...`
- the runtime package carries the platform-specific binary
- users still get a pinned runtime
- the repo no longer needs to store those binaries

It also makes the runtime contract stricter and more predictable:

- published installs never silently fall back to an arbitrary `codex` on
`PATH`
- local development remains supported through explicit `codex_bin`
- `codex-cli-bin` is distributed as platform wheels only, which avoids
unsafe
source-distribution installs for a package that embeds a prebuilt binary

## Validation

- ran targeted Python SDK tests:
- `python3 -m pytest
sdk/python/tests/test_artifact_workflow_and_binaries.py
sdk/python/tests/test_client_rpc_methods.py
sdk/python/tests/test_contract_generation.py`
- exercised the staging flow with a local dummy binary to verify
SDK/runtime
  staging end to end
- verified the staged runtime package builds a platform-specific wheel
(`Root-Is-Purelib: false`) rather than a universal `py3-none-any` wheel
- added test coverage for the explicit-only runtime resolution model
- added test coverage that `codex-cli-bin` rejects `sdist` builds

---------

Co-authored-by: sdcoffey <stevendcoffey@gmail.com>
2026-03-10 13:53:08 -07:00
alexsong-oai
22d0aea5ba Add granular metrics for cloud requirements load (#14108) 2026-03-10 13:44:26 -07:00
xl-openai
2544bd02a2 feat: Allow sync with remote plugin status. (#14176)
Add forceRemoteSync to plugin/list.
When it is set to True, we will sync the local plugin status with the
remote one (backend-api/plugins/list).
2026-03-10 13:32:59 -07:00
Matthew Zeng
bda9e55c7e add(core): arc_monitor (#13936)
## Summary
- add ARC monitor support for MCP tool calls by serializing MCP approval
requests into the ARC action shape and sending the relevant
conversation/policy context to the `/api/codex/safety/arc` endpoint
- route ARC outcomes back into MCP approval flow so `ask-user` falls
back to a user prompt and `steer-model` blocks the tool call, with
guardian/ARC tests covering the new request shape
- update the TUI approval copy from “Approve Once” to “Allow” / “Allow
for this session” and refresh the related
  snapshots

---------

Co-authored-by: Fouad Matin <fouad@openai.com>
Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
2026-03-10 13:16:47 -07:00
Charlie Guo
01e2c3b8d9 Add OpenAI Docs skill (#13596)
## Summary
- add the OpenAI Docs skill under
codex-rs/skills/src/assets/samples/openai-docs
- include the skill metadata, assets, and GPT-5.4 upgrade reference
files
- exclude the test harness and test fixtures

## Testing
- not run (skill-only asset copy)
2026-03-10 12:37:23 -07:00
Eugene Brevdo
027afb8858 [skill-creator] Add forward-testing instructions (#13600)
This updates the `skill-creator` sample skill to explicitly cover
forward-testing as part of the skill authoring workflow. The guidance
now treats subagent-based validation as a first-class step for complex
or fragile skills, with an emphasis on preserving evaluation integrity
and avoiding leaked context.

The sample initialization script is also updated so newly created skills
point authors toward forward-testing after validation. Together, these
changes make the sample more opinionated about how skills should be
iterated on once the initial implementation is complete.

- Add new guidance to `SKILL.md` on protecting validation integrity,
when to use subagents for forward-testing, and how to structure
realistic test prompts without leaking expected answers.
- Expand the skill creation workflow so iteration explicitly includes
forward-testing for complex skills, including approval guidance for
expensive or risky validation runs.
2026-03-10 12:08:48 -07:00
guinness-oai
b33edebd6a Mark incomplete resumed turns interrupted when idle (#14125)
Fixes a Codex app bug where quitting the app mid-run could leave the
reopened thread stuck in progress and non-interactable. On cold thread
resume, app-server could return an idle thread with a replayed turn
still marked in progress. This marks incomplete replayed turns as
interrupted unless the thread is actually active.
2026-03-10 10:57:03 -07:00
pakrym-oai
46e6661d4e Reuse McpToolOutput in McpHandler (#14229)
We already have a type to represent the MCP tool output, reuse it
instead of the custom McpHandlerOutput
2026-03-10 10:41:41 -07:00
Ahmed Ibrahim
77a02909a8 Stabilize split PTY output on Windows (#14003)
## Summary
- run the split stdout/stderr PTY test through the normal shell helper
on every platform
- use a Windows-native command string instead of depending on Python to
emit split streams
- assert CRLF line endings on Windows explicitly

## Why this fixes the flake
The earlier PTY split-output test used a Python one-liner on Windows
while the rest of the file exercised shell-command behavior. That made
the test depend on runner-local Python availability and masked the real
Windows shell output shape. Using a native cmd-compatible command and
asserting the actual CRLF output makes the split stdout/stderr coverage
deterministic on Windows runners.
2026-03-10 10:25:29 -07:00
pakrym-oai
e52afd28b0 Expose strongly-typed result for exec_command (#14183)
Summary
- document output types for the various tool handlers and registry so
the API exposes richer descriptions
- update unified execution helpers and client tests to align with the
new output metadata
- clean up unused helpers across tool dispatch paths

Testing
- Not run (not requested)
2026-03-10 09:54:34 -07:00
Eric Traut
e4edafe1a8 Log ChatGPT user ID for feedback tags (#13901)
There are some bug investigations that currently require us to ask users
for their user ID even though they've already uploaded logs and session
details via `/feedback`. This frustrates users and increases the time
for diagnosis.

This PR includes the ChatGPT user ID in the metadata uploaded for
`/feedback` (both the TUI and app-server).
2026-03-10 09:57:41 -06:00
Eric Traut
9a501ddb08 Fix Linux tmux segfault in user shell lookup (#13900)
Replace the Unix shell lookup path in `codex-rs/core/src/shell.rs` to
use
`libc::getpwuid_r()` instead of `libc::getpwuid()` when resolving the
current
user's shell.

Why:
- `getpwuid()` can return pointers into libc-managed shared storage
- on the musl static Linux build, concurrent callers can race on that
storage
- this matches the crash pattern reported in tmux/Linux sessions with
parallel
  shell activity

Refs:
- Fixes #13842
2026-03-10 09:57:18 -06:00
Eric Traut
b90921eba8 Fix release-mode integration test compiler failure (#13603)
Addresses #13586

This doesn't affect our CI scripts. It was user-reported.

Summary
- add `wiremock::ResponseTemplate` and `body_string_contains` imports
behind `#[cfg(not(debug_assertions))]` in
`codex-rs/core/tests/suite/view_image.rs` so release builds only pull
the helpers they actually use
2026-03-10 08:30:56 -06:00
Shaqayeq
6baeec68bd python-sdk: generated type foundation (all v2 schemas) (#13953)
## Summary
Foundation PR only (base for PR #3).

This PR contains the SDK runtime foundation and generated artifacts:

- pinned runtime binary in `sdk/python/bin/` (`codex` or `codex.exe` by
platform)
- single maintenance script:
`sdk/python/scripts/update_sdk_artifacts.py`
- generated protocol/types artifacts under:
  - `sdk/python/src/codex_app_server/generated/protocol_types.py`
  - `sdk/python/src/codex_app_server/generated/schema_types.py`
  - `sdk/python/src/codex_app_server/generated/v2_all/*`
- generation-contract test wiring (`tests/test_contract_generation.py`)

## Release asset behavior
`update_sdk_artifacts.py` now:
- selects latest release by channel (`--channel stable|alpha`)
- resolves the correct asset for current OS/arch
- extracts platform binary (`codex` on macOS/Linux, `codex.exe` on
Windows)
- keeps runtime on single pinned binary source in `sdk/python/bin/`

## Scope boundary
-  PR #2 = binary + generation pipeline + generated types foundation
-  PR #2 does **not** include examples/integration logic polish (that
is PR #3)

## Validation
- Ran: `python scripts/update_sdk_artifacts.py --channel stable`
- Regenerated and committed resulting generated artifacts
- Local tests pass on branch
2026-03-10 01:00:46 -07:00
Ahmed Ibrahim
f3f47cf455 Stabilize app-server notify initialize test (#13939)
## What changed
- This PR changes only the flaky test setup for
`turn_start_notify_payload_includes_initialize_client_name`.
- Instead of shelling out to `python3` to write the notify payload, the
test uses the first-party `codex-app-server-test-notify-capture` helper.
- The helper writes `notify.json` atomically and the test waits for the
file to exist before reading it.

## Why this fixes the flake
- The old test depended on an external Python interpreter being present
and behaving consistently on every CI runner.
- It also raced the file write: the test could observe the path before
the payload had been fully written, which produced partial reads and
intermittent assertion failures.
- Moving the write into a repo-owned helper removes the external
dependency, and atomic write-plus-wait makes the handoff deterministic.

## Scope
- Test-only change.
2026-03-09 23:41:58 -07:00
Ahmed Ibrahim
b39ae9501f Stabilize websocket test server binding (#14002)
## Summary
- stop reserving a localhost port in the websocket tests before spawning
the server
- let the app-server bind `127.0.0.1:0` itself and read back the actual
bound websocket address from stderr
- update the websocket test helpers and callers to use the discovered
address

## Why this fixes the flake
The previous harness reserved a port in the test process, dropped it,
and then asked the server process to bind that same address. On busy
runners there is a race between releasing the reservation and the child
process rebinding it, which can produce sporadic startup failures.
Binding to port `0` inside the server removes that race entirely, and
waiting for the server to report the real bound address makes the tests
connect only after the listener is actually ready.
2026-03-09 23:39:56 -07:00
Ahmed Ibrahim
6b7253b123 Fix unified exec test output assertion (#14184)
## Summary
- update the unified exec test to use truncated_output() instead of the
removed output field
- fix the compile failure on latest main after ExecCommandToolOutput
changed shape
2026-03-09 23:12:36 -07:00
Ahmed Ibrahim
aa6a57dfa2 Stabilize incomplete SSE retry test (#13879)
## What changed
- The retry test now uses the same streaming SSE test server used by
production-style tests instead of a wiremock sequence.
- The fixture is resolved via `find_resource!`, and the test asserts
that exactly two outbound requests were sent.

## Why this fixes the flake
- The old wiremock sequence approximated early-close behavior, but it
did not reproduce the same streaming semantics the real client sees.
- That meant the retry path depended on mock implementation details
instead of on the actual transport behavior we care about.
- Switching to the streaming SSE helper makes the test exercise the real
early-close/retry contract, and counting requests directly verifies that
we retried exactly once rather than merely hoping the sequence aligned.

## Scope
- Test-only change.
2026-03-09 22:34:44 -07:00
Ahmed Ibrahim
2e24be2134 Use realtime transcript for handoff context (#14132)
- collect input/output transcript deltas into active handoff transcript
state
- attach and clear that transcript on each handoff, and regenerate
schema/tests
2026-03-09 22:30:03 -07:00
Channing Conger
c6343e0649 Implemented thread-level atomic elicitation counter for stopwatch pausing (#12296)
### Purpose
While trying to build out CLI-Tools for the agent to use under skills we
have found that those tools sometimes need to invoke a user elicitation.
These elicitations are handled out of band of the codex app-server but
need to indicate to the exec manager that the command running is not
going to progress on the usual timeout horizon.

### Example
Model calls universal exec:
`$ download-credit-card-history --start-date 2026-01-19 --end-date
2026-02-19 > credit_history.jsonl`

download-cred-card-history might hit a hosted/preauthenticated service
to fetch data. That service might decide that the request requires an
end user approval the access to the personal data. It should be able to
signal to the running thread that the command in question is blocked on
user elicitation. In that case we want the exec to continue, but the
timeout to not expire on the tool call, essentially freezing time until
the user approves or rejects the command at which point the tool would
signal the app-server to decrement the outstanding elicitation count.
Now timeouts would proceed as normal.

### What's Added

- New v2 RPC methods:
    - thread/increment_elicitation
    - thread/decrement_elicitation
- Protocol updates in:
    - codex-rs/app-server-protocol/src/protocol/common.rs
    - codex-rs/app-server-protocol/src/protocol/v2.rs
- App-server handlers wired in:
    - codex-rs/app-server/src/codex_message_processor.rs

### Behavior

- Counter starts at 0 per thread.
- increment atomically increases the counter.
- decrement atomically decreases the counter; decrement at 0 returns
invalid request.
- Transition rules:
- 0 -> 1: broadcast pause state, pausing all active stopwatches
immediately.
    - \>0 -> >0: remain paused.
    - 1 -> 0: broadcast unpause state, resuming stopwatches.
- Core thread/session logic:
    - codex-rs/core/src/codex_thread.rs
    - codex-rs/core/src/codex.rs
    - codex-rs/core/src/mcp_connection_manager.rs

### Exec-server stopwatch integration

- Added centralized stopwatch tracking/controller:
    - codex-rs/exec-server/src/posix/stopwatch_controller.rs
- Hooked pause/unpause broadcast handling + stopwatch registration:
    - codex-rs/exec-server/src/posix/mcp.rs
    - codex-rs/exec-server/src/posix/stopwatch.rs
    - codex-rs/exec-server/src/posix.rs
2026-03-09 22:29:26 -07:00
Ahmed Ibrahim
79307b7933 Delay pending cleanup until task aborts (#14000)
## Summary
- move interrupted-turn cleanup so running tasks are aborted before
pending approvals are cleared
- keep unified exec shutdown behavior unchanged

## Why this fixes the flake
The interrupted-turn path could clear pending approvals before the
in-flight task had observed cancellation. On slower runners that let an
approval wait resolve in between those steps, tests would sometimes
surface a model-visible rejection instead of the expected TurnAborted
flow. Draining the active turn first and only then clearing pending
approval state makes the abort ordering deterministic.
2026-03-09 22:28:43 -07:00
Matthew Zeng
566e4cee4b [apps] Fix apps enablement condition. (#14011)
- [x] Fix apps enablement condition to check both the feature flag and
that the user is not an API key user.
2026-03-09 22:25:43 -07:00
pakrym-oai
a9ae43621b Move exec command truncation into ExecCommandToolOutput (#14169)
Summary
- relocate truncation logic for exec command output into the new
`ExecCommandToolOutput` response helper instead of centralized handler
code
- update all affected tools and unified exec handling to use the new
response item structure and eliminate `Function(FunctionToolOutput)`
responses
- adjust context, registry, and handler interfaces to align with the new
response semantics and error fields

Testing
- Not run (not requested)
2026-03-09 22:13:48 -07:00
xl-openai
0c33af7746 feat: support disabling bundled system skills (#13792)
Support disable bundled system skills with a config:

[skills.bundled]
enabled = false
2026-03-09 22:02:53 -07:00
pakrym-oai
710682598d Export tools module into code mode runner (#14167)
**Summary**
- allow `code_mode` to pass enabled tools metadata to the runner and
expose them via `tools.js`
- import tools inside JavaScript rather than relying only on globals or
proxies for nested tool calls
- update specs, docs, and tests to exercise the new bridge and explain
the tooling changes

**Testing**
- Not run (not requested)
2026-03-09 21:59:09 -07:00
Dylan Hurd
772259b01f fix(core) default RejectConfig.request_permissions (#14165)
## Summary
Adds a default here so existing config deserializes

## Testing
- [x] Added a unit test
2026-03-10 04:56:23 +00:00
pakrym-oai
d71e042694 Enforce single tool output type in codex handlers (#14157)
We'll need to associate output schema with each tool. Each tool can only
have on output type.
2026-03-09 21:49:44 -07:00
pash-openai
63597d1b2d tui: only show fast status for gpt-5.4 (#14135) 2026-03-09 21:12:05 -07:00
Andrei Eternal
244b2d53f4 start of hooks engine (#13276)
(Experimental)

This PR adds a first MVP for hooks, with SessionStart and Stop

The core design is:

- hooks live in a dedicated engine under codex-rs/hooks
- each hook type has its own event-specific file
- hook execution is synchronous and blocks normal turn progression while
running
- matching hooks run in parallel, then their results are aggregated into
a normalized HookRunSummary

On the AppServer side, hooks are exposed as operational metadata rather
than transcript-native items:

- new live notifications: hook/started, hook/completed
- persisted/replayed hook results live on Turn.hookRuns
- we intentionally did not add hook-specific ThreadItem variants

Hooks messages are not persisted, they remain ephemeral. The context
changes they add are (they get appended to the user's prompt)
2026-03-10 04:11:31 +00:00
pakrym-oai
da616136cc Add code_mode experimental feature (#13418)
A much narrower and more isolated (no node features) version of js_repl
2026-03-09 20:56:27 -07:00