Compare commits

...

204 Commits

Author SHA1 Message Date
Keyan Zhang
920b6928d8 fix types 2026-03-13 03:13:42 -07:00
Keyan Zhang
71c7299d0b up 1039 - Fri Mar 13 2026 00:05:59 2026-03-13 03:13:42 -07:00
Keyan Zhang
48f2d0d992 up 1038 - Fri Mar 13 2026 00:04:58 2026-03-13 03:13:42 -07:00
Keyan Zhang
b7f0cf5743 up 1037 - Thu Mar 12 2026 23:59:50 2026-03-13 03:13:41 -07:00
Keyan Zhang
658798fc63 no js 2026-03-13 03:13:41 -07:00
Keyan Zhang
9156ac04bd up 1019 - Wed Mar 11 2026 22:39:06 2026-03-13 03:13:41 -07:00
Keyan Zhang
77733ef248 up 1018 - Wed Mar 11 2026 22:32:50 2026-03-13 03:13:41 -07:00
Keyan Zhang
6323052ab3 up 1017 - Wed Mar 11 2026 22:28:26 2026-03-13 03:13:41 -07:00
Keyan Zhang
938085eff9 simplify 2026-03-13 03:13:41 -07:00
Keyan Zhang
c51f563151 . 2026-03-13 03:13:41 -07:00
Keyan Zhang
da65178bb3 simplify 2026-03-13 03:13:41 -07:00
Keyan Zhang
82a6c11a5f update 2026-03-13 03:13:41 -07:00
Keyan Zhang
401df3306e schema 2026-03-13 03:13:41 -07:00
Keyan Zhang
5b2ec83373 script 2026-03-13 03:13:41 -07:00
Keyan Zhang
aab7d8d3a4 add TS codegen 2026-03-13 03:13:41 -07:00
Ahmed Ibrahim
c7e847aaeb Add diagnostics for read_only_unless_trusted timeout flake (#14518)
## Summary
- add targeted diagnostic logging for the
read_only_unless_trusted_requires_approval scenarios in
approval_matrix_covers_all_modes
- add a scoped timeout buffer only for ro_unless_trusted write-file
scenarios: 1000ms -> 2000ms
- keep all other write-file scenarios at 1000ms

## Why
The last two main failures were both in codex-core::all
suite::approvals::approval_matrix_covers_all_modes with exit_code=124 in
the same scenario. This points to execution-time jitter in CI rather
than a semantic approval-policy mismatch.

## Notes
- This does not introduce any >5s timeout and does not
disable/quarantine tests.
- The timeout increase is tightly scoped to the single flaky path and
keeps the matrix deterministic under CI scheduling variance.
2026-03-12 23:51:03 -07:00
Ahmed Ibrahim
2253a9d1d7 Add realtime transcription mode for websocket sessions (#14556)
- add experimental_realtime_ws_mode (conversational/transcription) and
plumb it into realtime conversation session config
- switch realtime websocket intent and session.update payload shape
based on mode
- update config schema and realtime/config tests

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 23:50:30 -07:00
Ahmed Ibrahim
eaf81d3f6f Add codex tool support for realtime v2 handoff (#14554)
- Advertise a `codex` function tool in realtime v2 session updates.
- Emit handoff replies as `function_call_output` items while keeping v1
behavior unchanged.
- Split realtime event parsing into explicit v1/v2 modules with shared
common helpers.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 23:30:02 -07:00
Celia Chen
0c60eea4a5 feat: support skill-scoped managed network domain overrides in skill config (#14522)
## Summary

This lets skill loading split `permissions.network` into two distinct
pieces:

- `permissions.network.enabled` still feeds the skill
`PermissionProfile` and remains the coarse gate for whether the skill
can use network access at all.
- `permissions.network.allowed_domains` and
`permissions.network.denied_domains` are lifted into a new
`SkillManagedNetworkOverride` so managed-network sessions can start
per-skill scoped proxies with the right domain overrides.

The change also updates `SkillMetadata` construction sites and adds
loader tests covering YAML parsing plus normalization of the network
gate vs. domain override fields.

## Follow-up
A PR that uses the network_override to spin up a skill-specific proxy if
network_override is not none.
2026-03-13 04:45:14 +00:00
Jack Mousseau
7c7e267501 Simplify permissions available in request permissions tool (#14529) 2026-03-12 21:13:17 -07:00
Ahmed Ibrahim
3e8f47169e Add realtime v2 event parser behind feature flag (#14537)
- Add a feature-flagged realtime v2 parser on the existing
websocket/session pipeline.
- Wire parser selection from core feature flags and map the codex
handoff tool-call path into existing handoff events.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 21:12:40 -07:00
alexsong-oai
650beb177e Refactor cloud requirements error and surface in JSON-RPC error (#14504)
Refactors cloud requirements error handling to carry structured error
metadata and surfaces that metadata through JSON-RPC config-load
failures, including:
* adds typed CloudRequirementsLoadErrorCode values plus optional
statusCode
* marks thread/start, thread/resume, and thread/fork config failures
with structured cloud-requirements error data
2026-03-13 03:30:51 +00:00
Channing Conger
0daffe667a code_mode: Move exec params from runtime declarations to @pragma (#14511)
This change moves code_mode exec session settings out of the runtime API
and into an optional first-line pragma, so instead of calling runtime
helpers like set_yield_time() or set_max_output_tokens_per_exec_call(),
the model can write // @exec: {"yield_time_ms": ...,
"max_output_tokens": ...} at the top of the freeform exec source. Rust
now parses that pragma before building the source, validates it, and
passes the values directly in the exec start message to the code-mode
broker, which applies them at session start without any worker-runtime
mutation path. The @openai/code_mode module no longer exposes those
setter functions, the docs and grammar were updated to describe the
pragma form, and the existing code_mode tests were converted to use
pragma-based configuration instead.
2026-03-13 03:27:42 +00:00
alexsong-oai
1a363d5fcf Add plugin usage telemetry (#14531)
adding metrics including: 
* plugin used
* plugin installed/uninstalled
* plugin enabled/disabled
2026-03-12 19:22:30 -07:00
viyatb-oai
f194d4b115 fix: reopen writable linux carveouts under denied parents (#14514)
## Summary
- preserve Linux bubblewrap semantics for `write -> none -> write`
filesystem policies by recreating masked mount targets before rebinding
narrower writable descendants
- add a Linux runtime regression for `/repo = write`, `/repo/a = none`,
`/repo/a/b = write` so the nested writable child is exercised under
bubblewrap
- document the supported legacy Landlock fallback and the split-policy
bubblewrap behavior for overlapping carveouts

## Example
Given a split filesystem policy like:

```toml
"/repo" = "write"
"/repo/a" = "none"
"/repo/a/b" = "write"
```

this PR keeps `/repo` writable, masks `/repo/a`, and still reopens
`/repo/a/b` as writable again under bubblewrap.

## Testing
- `just fmt`
- `cargo test -p codex-linux-sandbox`
- `cargo clippy -p codex-linux-sandbox --tests -- -D warnings`
2026-03-13 01:36:06 +00:00
pakrym-oai
7626f61274 Add typed multi-agent tool outputs (#14536)
## Summary
- return typed `ToolOutput` values from the multi-agent handlers instead
of plain `FunctionToolOutput`
- keep the regular function-call response shape as JSON text while
exposing structured values to code mode
- add output schemas for `spawn_agent`, `send_input`, `resume_agent`,
`wait`, and `close_agent`

## Verification
- `just fmt`
- focused multi-agent and integration tests passed earlier in this
branch during iteration
- after the final edit, I only reran formatting before opening this PR
2026-03-13 01:10:10 +00:00
Josh McKinney
6912da84a8 client: extend custom CA handling across HTTPS and websocket clients (#14239)
## Stacked PRs

This work is now effectively split across two steps:

- #14178: add custom CA support for browser and device-code login flows,
docs, and hermetic subprocess tests
- #14239: extend that shared custom CA handling across Codex HTTPS
clients and secure websocket TLS

Note: #14240 was merged into this branch while it was stacked on top of
this PR. This PR now subsumes that websocket follow-up and should be
treated as the combined change.

Builds on top of #14178.

## Problem

Custom CA support landed first in the login path, but the real
requirement is broader. Codex constructs outbound TLS clients in
multiple places, and both HTTPS and secure websocket paths can fail
behind enterprise TLS interception if they do not honor
`CODEX_CA_CERTIFICATE` or `SSL_CERT_FILE` consistently.

This PR broadens the shared custom-CA logic beyond login and applies the
same policy to websocket TLS, so the enterprise-proxy story is no longer
split between “HTTPS works” and “websockets still fail”.

## What This Delivers

Custom CA support is no longer limited to login. Codex outbound HTTPS
clients and secure websocket connections can now honor the same
`CODEX_CA_CERTIFICATE` / `SSL_CERT_FILE` configuration, so enterprise
proxy/intercept setups work more consistently end-to-end.

For users and operators, nothing new needs to be configured beyond the
same CA env vars introduced in #14178. The change is that more of Codex
now respects them, including websocket-backed flows that were previously
still using default trust roots.

I also manually validated the proxy path locally with mitmproxy using:
`CODEX_CA_CERTIFICATE=~/.mitmproxy/mitmproxy-ca-cert.pem
HTTPS_PROXY=http://127.0.0.1:8080 just codex`
with mitmproxy installed via `brew install mitmproxy` and configured as
the macOS system proxy.

## Mental model

`codex-client` is now the owner of shared custom-CA policy for outbound
TLS client construction. Reqwest callers start from the builder
configuration they already need, then pass that builder through
`build_reqwest_client_with_custom_ca(...)`. Websocket callers ask the
same module for a rustls client config when a custom CA bundle is
configured.

The env precedence is the same everywhere:
- `CODEX_CA_CERTIFICATE` wins
- otherwise fall back to `SSL_CERT_FILE`
- otherwise use system roots

The helper is intentionally narrow. It loads every usable certificate
from the configured PEM bundle into the appropriate root store and
returns either a configured transport or a typed error that explains
what went wrong.

## Non-goals

This does not add handshake-level integration tests against a live TLS
endpoint. It does not validate that the configured bundle forms a
meaningful certificate chain. It also does not try to force every
transport in the repo through one abstraction; it extends the shared CA
policy across the reqwest and websocket paths that actually needed it.

## Tradeoffs

The main tradeoff is centralizing CA behavior in `codex-client` while
still leaving adoption up to call sites. That keeps the implementation
additive and reviewable, but it means the rule "outbound Codex TLS that
should honor enterprise roots must use the shared helper" is still
partly enforced socially rather than by types.

For websockets, the shared helper only builds an explicit rustls config
when a custom CA bundle is configured. When no override env var is set,
websocket callers still use their ordinary default connector path.

## Architecture

`codex-client::custom_ca` now owns CA bundle selection, PEM
normalization, mixed-section parsing, certificate extraction, typed
CA-loading errors, and optional rustls client-config construction for
websocket TLS.

The affected consumers now call into that shared helper directly rather
than carrying login-local CA behavior:
- backend-client
- cloud-tasks
- RMCP client paths that use `reqwest`
- TUI voice HTTP paths
- `codex-core` default reqwest client construction
- `codex-api` websocket clients for both responses and realtime
websocket connections

The subprocess CA probe, env-sensitive integration tests, and shared PEM
fixtures also live in `codex-client`, which is now the actual owner of
the behavior they exercise.

## Observability

The shared CA path logs:
- which environment variable selected the bundle
- which path was loaded
- how many certificates were accepted
- when `TRUSTED CERTIFICATE` labels were normalized
- when CRLs were ignored
- where client construction failed

Returned errors remain user-facing and include the relevant env var,
path, and remediation hint. That same error model now applies whether
the failure surfaced while building a reqwest client or websocket TLS
configuration.

## Tests

Pure unit tests in `codex-client` cover env precedence and PEM
normalization behavior. Real client construction remains in subprocess
tests so the suite can control process env and avoid the macOS seatbelt
panic path that motivated the hermetic test split.

The subprocess coverage verifies:
- `CODEX_CA_CERTIFICATE` precedence over `SSL_CERT_FILE`
- fallback to `SSL_CERT_FILE`
- single-cert and multi-cert bundles
- malformed and empty-file errors
- OpenSSL `TRUSTED CERTIFICATE` handling
- CRL tolerance for well-formed CRL sections

The websocket side is covered by the existing `codex-api` / `codex-core`
websocket test suites plus the manual mitmproxy validation above.

---------

Co-authored-by: Ivan Zakharchanka <3axap4eHko@gmail.com>
Co-authored-by: Codex <noreply@openai.com>
2026-03-13 00:59:26 +00:00
aaronl-openai
d9a403a8c0 [js_repl] Hard-stop active js_repl execs on explicit user interrupts (#13329)
## Summary
- hard-stop `js_repl` only for `TurnAbortReason::Interrupted`,
preserving the persistent REPL across replaced turns
- track the current top-level exec by turn and only reset when the
interrupted turn owns submitted work or a freshly started kernel for the
current exec attempt
- close both interrupt races: the write-window race by marking the exec
as submitted before async pipe writes begin, and the startup-window race
by tracking fresh-kernel ownership until submission
- add regression coverage for interrupted in-flight execs and the
pending-kernel-start window

## Why
Stopping a turn previously surfaced `aborted by user after Xs` even
though the underlying `js_repl` kernel could continue executing. Earlier
fixes also risked resetting the session-scoped REPL too broadly or
missing already-dispatched work. This change keeps cleanup scoped to
explicit stop semantics and makes the interrupt path line up with both
submitted execs and newly started kernels.

## Testing
- `just fmt`
- `cargo test -p codex-core`
- `just fix -p codex-core`

`cargo test -p codex-core` passes the updated `js_repl` coverage,
including the new startup-window regression test, but still has
unrelated integration failures in this environment outside `js_repl`.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 17:51:56 -07:00
pakrym-oai
793bf32585 Split multi-agent handlers per tool (#14535)
Summary
- move the existing multi-agent handler logic into each tool-specific
handler and inline helper implementations
- remove the old central dispatcher now that each handler encapsulates
its own behavior
- adjust handler specs and tests to match the new structure without
macros

Testing
- Not run (not requested)
2026-03-12 17:43:29 -07:00
Josh McKinney
76d8d174b1 login: add custom CA support for login flows (#14178)
## Stacked PRs

This work is split across three stacked PRs:

- #14178: add custom CA support for browser and device-code login flows,
docs, and hermetic subprocess tests
- #14239: broaden the shared custom CA path from login to other outbound
`reqwest` clients across Codex
- #14240: extend that shared custom CA handling to secure websocket TLS
so websocket connections honor the same CA env vars

Review order: #14178, then #14239, then #14240.

Supersedes #6864.

Thanks to @3axap4eHko for the original implementation and investigation
here. Although this version rearranges the code and history
significantly, the majority of the credit for this work belongs to them.

## Problem

Login flows need to work in enterprise environments where outbound TLS
is intercepted by an internal proxy or gateway. In those setups, system
root certificates alone are often insufficient to validate the OAuth and
device-code endpoints used during login. The change adds a
login-specific custom CA loading path, but the important contracts
around env precedence, PEM compatibility, test boundaries, and
probe-only workarounds need to be explicit so reviewers can understand
what behavior is intentional.

For users and operators, the behavior is simple: if login needs to trust
a custom root CA, set `CODEX_CA_CERTIFICATE` to a PEM file containing
one or more certificates. If that variable is unset, login falls back to
`SSL_CERT_FILE`. If neither is set, login uses system roots. Invalid or
empty PEM files now fail with an error that points back to those
environment variables and explains how to recover.

## What This Delivers

Users can now make Codex login work behind enterprise TLS interception
by pointing `CODEX_CA_CERTIFICATE` at a PEM bundle containing the
relevant root certificates. If that variable is unset, login falls back
to `SSL_CERT_FILE`, then to system roots.

This PR applies that behavior to both browser-based and device-code
login flows. It also makes login tolerant of the PEM shapes operators
actually have in hand: multi-certificate bundles, OpenSSL `TRUSTED
CERTIFICATE` labels, and bundles that include well-formed CRLs.

## Mental model

`codex-login` is the place where the login flows construct ad hoc
outbound HTTP clients. That makes it the right boundary for a narrow CA
policy: look for `CODEX_CA_CERTIFICATE`, fall back to `SSL_CERT_FILE`,
load every parseable certificate block in that bundle into a
`reqwest::Client`, and fail early with a clear user-facing error if the
bundle is unreadable or malformed.

The implementation is intentionally pragmatic about PEM input shape. It
accepts ordinary certificate bundles, multi-certificate bundles, OpenSSL
`TRUSTED CERTIFICATE` labels, and bundles that also contain CRLs. It
does not validate a certificate chain or prove a handshake; it only
constructs the root store used by login.

## Non-goals

This change does not introduce a general-purpose transport abstraction
for the rest of the product. It does not validate whether the provided
bundle forms a real chain, and it does not add handshake-level
integration tests against a live TLS server. It also does not change
login state management or OAuth semantics beyond ensuring the existing
flows share the same CA-loading rules.

## Tradeoffs

The main tradeoff is keeping this logic scoped to login-specific client
construction rather than lifting it into a broader shared HTTP layer.
That keeps the review surface smaller, but it also means future
login-adjacent code must continue to use `build_login_http_client()` or
it can silently bypass enterprise CA overrides.

The `TRUSTED CERTIFICATE` handling is also intentionally a local
compatibility shim. The rustls ecosystem does not currently accept that
PEM label upstream, so the code normalizes it locally and trims the
OpenSSL `X509_AUX` trailer bytes down to the certificate DER that
`reqwest` can consume.

## Architecture

`custom_ca.rs` is now the single place that owns login CA behavior. It
selects the CA file from the environment, reads it, normalizes PEM label
shape where needed, iterates mixed PEM sections with `rustls-pki-types`,
ignores CRLs, trims OpenSSL trust metadata when necessary, and returns
either a configured `reqwest::Client` or a typed error.

The browser login server and the device-code flow both call
`build_login_http_client()`, so they share the same trust-store policy.
Environment-sensitive tests run through the `login_ca_probe` helper
binary because those tests must control process-wide env vars and cannot
reliably build a real reqwest client in-process on macOS seatbelt runs.

## Observability

The custom CA path logs which environment variable selected the bundle,
which file path was loaded, how many certificates were accepted, when
`TRUSTED CERTIFICATE` labels were normalized, when CRLs were ignored,
and where client construction failed. Returned errors remain user-facing
and include the relevant path, env var, and remediation hint.

This gives enough signal for three audiences:
- users can see why login failed and which env/file caused it
- sysadmins can confirm which override actually won
- developers can tell whether the failure happened during file read, PEM
parsing, certificate registration, or final reqwest client construction

## Tests

Pure unit tests stay limited to env precedence and empty-value handling.
Real client construction lives in subprocess tests so the suite remains
hermetic with respect to process env and macOS sandbox behavior.

The subprocess tests verify:
- `CODEX_CA_CERTIFICATE` precedence over `SSL_CERT_FILE`
- fallback to `SSL_CERT_FILE`
- single-certificate and multi-certificate bundles
- malformed and empty-bundle errors
- OpenSSL `TRUSTED CERTIFICATE` handling
- CRL tolerance for well-formed CRL sections

The named PEM fixtures under `login/tests/fixtures/` are shared by the
tests so their purpose stays reviewable.

---------

Co-authored-by: Ivan Zakharchanka <3axap4eHko@gmail.com>
Co-authored-by: Codex <noreply@openai.com>
2026-03-13 00:14:54 +00:00
xl-openai
1ea69e8d50 feat: add plugin/read. (#14445)
return more information for a specific plugin.
2026-03-12 16:52:21 -07:00
Jack Mousseau
b7dba72dbd Rename reject approval policy to granular (#14516) 2026-03-12 16:38:04 -07:00
Eric Traut
d32820ab07 Fix codex exec --profile handling (#14524)
PR #14005 introduced a regression whereby `codex exec --profile`
overrides were dropped when starting or resuming a thread. That causes
the thread to miss profile-scoped settings like
`model_instructions_file`.

This PR preserve the active profile in the thread start/resume config
overrides so the
app-server rebuild sees the same profile that exec resolved. 

Fixes #14515
2026-03-12 17:34:25 -06:00
Rasmus Rygaard
53d5972226 Reapply "Pass more params to compaction" (#14298) (#14521)
This reverts commit 8af97ce4b0.

Confirmed that this runs locally without the previous issues with tool
use
2026-03-12 23:27:21 +00:00
Anton Panasenko
651717323c feat(search_tool): gate search_tool on model supports_search_tool field (#14502) 2026-03-12 16:03:50 -07:00
pakrym-oai
a2546d5dff Expose code-mode tools through globals (#14517)
Summary
- make all code-mode tools accessible as globals so callers only need
`tools.<name>`
- rename text/image helpers and key globals (store, load, ALL_TOOLS,
etc.) to reflect the new shared namespace
- update the JS bridge, runners, descriptions, router, and tests to
follow the new API

Testing
- Not run (not requested)
2026-03-12 15:43:59 -07:00
Curtis 'Fjord' Hawthorne
b560494c9f Persist js_repl codex helpers across cells (#14503)
## Summary

This changes `js_repl` so saved references to `codex.tool(...)` and
`codex.emitImage(...)` keep working across cells.

Previously, those helpers were recreated per exec and captured that
exec's `message.id`. If a persisted object or saved closure reused an
old helper in a later cell, the nested tool/image call could fail with
`js_repl exec context not found`.

This patch:
- keeps stable `codex.tool` and `codex.emitImage` helper identities in
the kernel
- resolves the current exec dynamically at call time using
`AsyncLocalStorage`
- adds regression coverage for persisted helper references across cells
- updates the js_repl docs and project-doc instructions to describe the
new behavior and its limits

## Why

We already support persistent top-level bindings across `js_repl` cells,
so persisted objects should be able to reuse `codex` helpers in later
active cells. The bug was that helper identity was exec-scoped, not
kernel-scoped.

Using `AsyncLocalStorage` fixes the cross-cell reuse case without
falling back to a single global active exec that could accidentally
attribute stale background callbacks to the wrong cell.
2026-03-12 15:41:54 -07:00
Jack Mousseau
a314c7d3ae Decouple request permissions feature and tool (#14426) 2026-03-12 14:47:08 -07:00
Matthew Zeng
bc48b9289a Update tool search prompts (#14500)
- [x] Add mentions of connectors because model always think in connector
terms in its CoT.
- [x] Suppress list_mcp_resources in favor of tool search for available
apps.
2026-03-12 14:28:51 -07:00
pakrym-oai
04e14bdf23 Rename exec session IDs to cell IDs (#14510)
- Update the code-mode executor, wait handler, and protocol plumbing to
use cell IDs instead of session IDs for node communication
- Switch tool metadata, wait description, and suite tests to refer to
cell IDs so user-visible messages match the new terminology

**Testing**
- Not run (not requested)
2026-03-12 14:05:30 -07:00
Andi Liu
11812383c5 memories: focus write prompts on user preferences (#14493)
## Summary
- update `codex-rs/core/templates/memories/stage_one_system.md` so phase
1 captures stronger user-preference signals, richer task summaries, and
cwd provenance without branch-specific fields
- update `codex-rs/core/templates/memories/consolidation.md` so phase 2
keeps separate sections for user preferences, reusable knowledge, and
failure shields while staying cwd-aware but branchless
- document the `codex` prompt-template maintenance rule in
`codex-rs/core/src/memories/README.md`: the undated templates are
canonical here and should be edited in place

## Testing
- cargo test -p codex-core memories --manifest-path codex-rs/Cargo.toml
2026-03-12 20:39:59 +00:00
pakrym-oai
dadffd27d4 Fix MCP tool calling (#14491)
Properly escape mcp tool names and make tools only available via
imports.
2026-03-12 13:38:52 -07:00
pakrym-oai
a5a4899d0c Skip nested tool call parallel test on Windows (#14505)
**Summary**
- disable the `code_mode_nested_tool_calls_can_run_in_parallel` test on
Windows where `exec_command` is unavailable

**Testing**
- Not run (not requested)
2026-03-12 13:32:11 -07:00
aaronl-openai
f35d46002a Fix js_repl hangs on U+2028/U+2029 dynamic tool responses (#14421)
## Summary
Dynamic tool responses containing literal U+2028 / U+2029 would cause
await codex.tool(...) to hang even though the response had already
arrived. This PR replaces the kernel’s readline-based stdin handling
with byte-oriented JSONL framing that handles these characters properly.

## Testing
- `cargo test -p codex-core`
- tested the binary on a repro case and confirmed it's fixed

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 13:01:02 -07:00
pakrym-oai
09ba6b47ae Reuse tool runtime for code mode worker (#14496)
## Summary
- create the turn-scoped `ToolCallRuntime` before starting the code mode
worker so the worker reuses the same runtime and router
- thread the shared runtime through the code mode service/worker path
and use it for nested tool calls
- model aborted tool calls as a concrete `ToolOutput` so aborted
responses still produce valid tool output shapes

## Testing
- `just fmt`
- `cargo test -p codex-core` (still running locally)
2026-03-12 12:48:32 -07:00
Owen Lin
d3e6680531 fix turn_start_jsonrpc_span_parents_core_turn_spans flakiness (#14490)
This makes the test less flaky by checking the core invariant instead of
the full span chain.

Before, the test waited for several specific internal spans
(`submission_dispatch`, `session_task.turn`, `run_turn`) and asserted
their exact relationships. That was brittle because those spans are
exported asynchronously and are more of an implementation detail than
the thing we actually care about.

Now, the test only checks that:
- `turn/start` is on the expected remote trace with the expected remote
parent
- at least one representative core turn span on that same trace descends
from it

That keeps the sanity-check we want while making the test less sensitive
to timing and internal refactors.
2026-03-12 12:16:56 -07:00
Owen Lin
4724a2e9e7 chore(app-server): stop exporting EventMsg schemas (#14478)
Follow up to https://github.com/openai/codex/pull/14392, stop exporting
EventMsg types to TypeScript and JSON schema since we no longer emit
them.
2026-03-12 12:16:05 -07:00
pakrym-oai
25e301ed98 Add parallel tool call test (#14494)
Summary
- pin tests to `test-gpt-5.1-codex` so code-mode suites exercise that
model explicitly
- add a regression test that ensures nested tool calls can execute in
parallel and assert on timing
- refresh `codex-rs/Cargo.lock` for the updated dependency tree (add
`codex-utils-pty`, drop `codex-otel`)

Testing
- Not run (not requested)
2026-03-12 12:10:14 -07:00
pakrym-oai
d1b03f0d7f Add default code-mode yield timeout (#14484)
Summary
- expose the default yield timeout through code mode runtime so the
handler, wait tool, and protocol share the same 10s value that matches
unified exec
- document the timeout change in the tool descriptions and propagate the
value all the way into the runner metadata
- adjust Cargo.lock to keep the dependency tree in sync with the added
code mode tool dependency

Testing
- Not run (not requested)
2026-03-12 12:06:23 -07:00
jgershen-oai
3e96c867fe use scopes_supported for OAuth when present on MCP servers (#14419)
Fixes [#8889](https://github.com/openai/codex/issues/8889).

## Summary
- Discover and use advertised MCP OAuth `scopes_supported` when no
explicit or configured scopes are present.
- Apply the same scope precedence across `mcp add`, `mcp login`, skill
dependency auto-login, and app-server MCP OAuth login.
- Keep discovered scopes ephemeral and non-persistent.
- Retry once without scopes for CLI and skill auto-login flows if the
OAuth provider rejects discovered scopes.

## Motivation
Some MCP servers advertise the scopes they expect clients to request
during OAuth, but Codex was ignoring that metadata and typically
starting OAuth with no scopes unless the user manually passed `--scopes`
or configured `server.scopes`.

That made compliant MCP servers harder to use out of the box and is the
behavior described in
[#8889](https://github.com/openai/codex/issues/8889).

This change also brings our behavior in line with the MCP authorization
spec's scope selection guidance:

https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#scope-selection-strategy

## Behavior
Scope selection now follows this order everywhere:
1. Explicit request scopes / CLI `--scopes`
2. Configured `server.scopes`
3. Discovered `scopes_supported`
4. Legacy empty-scope behavior

Compatibility notes:
- Existing working setups keep the same behavior because explicit and
configured scopes still win.
- Discovered scopes are never written back into config or token storage.
- If discovery is missing, malformed, or empty, behavior falls back to
the previous empty-scope path.
- App-server login gets the same precedence rules, but does not add a
transparent retry path in this change.

## Implementation
- Extend streamable HTTP OAuth discovery to parse and normalize
`scopes_supported`.
- Add a shared MCP scope resolver in `core` so all login entrypoints use
the same precedence rules.
- Preserve provider callback errors from the OAuth flow so CLI/skill
flows can safely distinguish provider rejections from other failures.
- Reuse discovered scopes from the existing OAuth support check where
possible instead of persisting new config.
2026-03-12 11:57:06 -07:00
iceweasel-oai
fa26597689 Do not allow unified_exec for sandboxed scenarios on Windows (#14398)
as reported in https://github.com/openai/codex/issues/14367 users can
explicitly enable unified_exec which will bypass the sandbox even when
it should be enabled.

Until we support unified_exec with the Windows Sandbox, we will disallow
it unless the sandbox is disabled
2026-03-12 11:21:30 -07:00
gabec-openai
4fa7d6f444 Handle malformed agent role definitions nonfatally (#14488)
## Summary
- make malformed agent role definitions nonfatal during config loading
- drop invalid agent roles and record warnings in `startup_warnings`
- forward startup warnings through app-server `configWarning`
notifications

## Testing
- `cargo test -p codex-core agent_role_ -- --nocapture`
- `just fix -p codex-core`
- `just fmt`
- `cargo test -p codex-app-server config_warning -- --nocapture`

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 11:20:31 -07:00
pakrym-oai
cfe3f6821a Cleanup code_mode tool descriptions (#14480)
Move to separate files and clarify a bit.
2026-03-12 11:13:35 -07:00
viyatb-oai
774965f1e8 fix: preserve split filesystem semantics in linux sandbox (#14173)
## Stack

   fix: fail closed for unsupported split windows sandboxing #14172
-> fix: preserve split filesystem semantics in linux sandbox #14173
   fix: align core approvals with split sandbox policies #14171
   refactor: centralize filesystem permissions precedence #14174

## Summary
## Summary
- Preserve Linux split filesystem carveouts in bubblewrap by applying
mount masks in the right order, so narrower rules still win under
broader writable roots.
- Preserve unreadable ancestors of writable roots by masking them first
and then rebinding the narrower writable descendants.
- Stop rejecting legacy-plus-split Linux configs that are
sandbox-equivalent after `cwd` resolution by comparing semantics instead
of raw legacy structs.
- Fail closed when callers provide partial split policies, mismatched
legacy-plus-split policies, or force `--use-legacy-landlock` for
split-only shapes that legacy Landlock cannot enforce.
- Add Linux regressions for overlapping writable, read-only, and denied
paths, and document the supported split-policy enforcement path.

## Example
Given a split filesystem policy like:

```toml
[permissions.dev.filesystem]
":root" = "read"
"/code" = "write"
"/code/.git" = "read"
"/code/secrets" = "none"
"/code/secrets/tmp" = "write"
```

this PR makes Linux enforce the intended result under bubblewrap:

- `/code` stays writable
- `/code/.git` stays read-only
- `/code/secrets` stays denied
- `/code/secrets/tmp` can still be reopened as writable if explicitly
allowed

Before this, Linux could lose one of those carveouts depending on mount
order or legacy-policy fallback. This PR keeps the split-policy
semantics intact and rejects configurations that legacy Landlock cannot
represent safely.
2026-03-12 10:56:32 -07:00
daveaitel-openai
4e99c0f179 rename spawn_csv feature flag to enable_fanout (#14475)
## Summary
- rename the public feature flag for `spawn_agents_on_csv()` from
`spawn_csv` to `enable_fanout`
- regenerate the config schema so only `enable_fanout` is advertised
- keep the behavior the same: enabling `enable_fanout` still pulls in
`multi_agent`

## Notes
- this is a hard rename with no `spawn_csv` compatibility alias
- the internal enum remains `Feature::SpawnCsv` to keep the patch small

## Testing
- `cd codex-rs && just fmt`
- `cd codex-rs && cargo test -p codex-core` (running locally;
`suite::agent_jobs::*` and rename-specific coverage passed so far)
2026-03-12 13:27:05 -04:00
pakrym-oai
c0528b9bd9 Move code mode tool files under tools/code_mode and split functionality (#14476)
- **Summary**
- migrate the code mode handler, service, worker, process, runner, and
bridge assets into the `tools/code_mode` module tree
- split Execution, protocol, and handler logic into dedicated files and
relocate the tool definition into `code_mode/spec.rs`
- update core references and tests to stitch the new organization
together
- **Testing**
  - Not run (not requested)
2026-03-12 09:54:11 -07:00
Ahmed Ibrahim
09aa71adb7 Fix stdio-to-uds peer-close flake (#13882)
## What changed
- `codex-stdio-to-uds` now tolerates `NotConnected` when
`shutdown(Write)` happens after the peer has already closed.
- The socket test was rewritten to send stdin from a fixture file and to
read an exact request payload length instead of waiting on EOF timing.

## Why this fixes the flake
- This one exposed a real cross-platform runtime edge case: on macOS,
the peer can close first after a successful exchange, and
`shutdown(Write)` can report `NotConnected` even though the interaction
already succeeded.
- Treating that specific ordering as a harmless shutdown condition
removes the production-level false failure.
- The old test compounded the problem by depending on EOF timing, which
varies by platform and scheduler. Exact-length IO makes the test
deterministic and focused on the actual data exchange.

## Scope
- Production logic change with matching test rewrite.
2026-03-12 09:52:50 -07:00
viyatb-oai
a30b807efe fix(cli): support legacy use_linux_sandbox_bwrap flag (#14473)
## Summary
- restore `use_linux_sandbox_bwrap` as a removed feature key so older
`--enable` callers parse again
- keep it as a no-op by leaving runtime behavior unchanged
- add regression coverage for the legacy `--enable` path

## Testing
- Not run (updated and pushed quickly)
2026-03-12 16:33:58 +00:00
Shaqayeq
ff6764e808 Add Python app-server SDK (#14435)
## TL;DR
Bring the Python app-server SDK from `main-with-prs-13953-and-14232`
onto current `main` as a standalone SDK-only PR.

- adds the new `sdk/python` and `sdk/python-runtime` package trees
- keeps the scope to the SDK payload only, without the unrelated
branch-history or workflow changes from the source branch
- regenerates `sdk/python/src/codex_app_server/generated/v2_all.py`
against current `main` schema so the extracted SDK matches today's
protocol definitions

## Validation
- `PYTHONPATH=sdk/python/src python3 -m pytest sdk/python/tests`

Co-authored-by: Codex <noreply@openai.com>
2026-03-12 09:22:01 -07:00
pakrym-oai
2f03b1a322 Dispatch tools when code mode is not awaited directly (#14437)
## Summary
- start a code mode worker once per turn and let it pump nested tool
calls through a dedicated queue
- simplify code mode request/response dispatch around request ids and
generic runner-unavailable errors
- clean up the code mode process API and runner protocol plumbing

## Testing
- not run yet
2026-03-12 09:00:20 -07:00
Michael Bolin
0c8a36676a fix: move inline codex-rs/core unit tests into sibling files (#14444)
## Why
PR #13783 moved the `codex.rs` unit tests into `codex_tests.rs`. This
applies the same extraction pattern across the rest of `codex-rs/core`
so the production modules stay focused on runtime code instead of large
inline test blocks.

Keeping the tests in sibling files also makes follow-up edits easier to
review because product changes no longer have to share a file with
hundreds or thousands of lines of test scaffolding.

## What changed
- replaced each inline `mod tests { ... }` in `codex-rs/core/src/**`
with a path-based module declaration
- moved each extracted unit test module into a sibling `*_tests.rs`
file, using `mod_tests.rs` for `mod.rs` modules
- preserved the existing `cfg(...)` guards and module-local structure so
the refactor remains structural rather than behavioral

## Testing
- `cargo test -p codex-core --lib` (`1653 passed; 0 failed; 5 ignored`)
- `just fix -p codex-core`
- `cargo fmt --check`
- `cargo shear`
2026-03-12 08:16:36 -07:00
Eric Traut
7f2ca502f5 Updated out-of-date tip about availability on free and go plans (#14471)
This addresses #14464
2026-03-12 09:12:38 -06:00
Jack Mousseau
745ed4e5e0 Use granted permissions when invoking apply_patch (#14429) 2026-03-12 01:30:13 -07:00
Matthew Zeng
23e55d7668 [elicitation] User-friendly tool call messages. (#14403)
- [x] Add a curated set of tool call messages and human-readable tool
param names.
2026-03-12 00:35:21 -07:00
Jack Mousseau
19d0949aab Handle pre-approved permissions in zsh fork (#14431) 2026-03-12 00:27:11 -07:00
viyatb-oai
e99e8e4a6b fix: follow up on linux sandbox review nits (#14440)
## Summary
- address the follow-up review nits from #13996 in a separate PR
- make the approvals test command a raw string and keep the
managed-network path using env proxy routing
- inline `--apply-seccomp-then-exec` in the Linux sandbox inner command
builder
- remove the bubblewrap-specific sandbox metric tag path and drop the
`use_legacy_landlock` shim from `sandbox_tag`/`TurnMetadataState::new`
- restore the `Feature` import that `origin/main` currently still needs
in `connectors.rs`

## Testing
- `cargo test -p codex-linux-sandbox`
- focused `codex-core` tests were rerun/started, but the final
verification pass was interrupted when I pushed at request
2026-03-11 23:59:50 -07:00
viyatb-oai
04892b4ceb refactor: make bubblewrap the default Linux sandbox (#13996)
## Summary
- make bubblewrap the default Linux sandbox and keep
`use_legacy_landlock` as the only override
- remove `use_linux_sandbox_bwrap` from feature, config, schema, and
docs surfaces
- update Linux sandbox selection, CLI/config plumbing, and related
tests/docs to match the new default
- fold in the follow-up CI fixes for request-permissions responses and
Linux read-only sandbox error text
2026-03-11 23:31:18 -07:00
xl-openai
b5f927b973 feat: refactor on openai-curated plugins. (#14427)
- Curated repo sync now uses GitHub HTTP, not local git.
- Curated plugin cache/versioning now uses commit SHA instead of local.
- Startup sync now always repairs or refreshes curated plugin cache from
tmp (auto update to the lastest)
2026-03-11 23:18:58 -07:00
pakrym-oai
f6c6128fc7 Support waiting for code_mode sessions (#14295)
## Summary
- persist the code mode runner process in the session-scoped code mode
store
- switch the runner protocol from `init` to `start` with explicit
session ids
- handle runner-side session processing without the init waiter queue

## Validation
- just fmt
- cargo check -p codex-core
- node --check codex-rs/core/src/tools/code_mode_runner.cjs
2026-03-11 23:13:54 -07:00
Ahmed Ibrahim
367a8a2210 Clarify spawn agent authorization (#14432)
- Clarify that spawn_agent requires explicit user permission for
delegation or parallel agent work.
- Add a regression test covering the new description text.
2026-03-11 23:03:07 -07:00
Matthew Zeng
ba5b94287e [apps] Add tool_suggest tool. (#14287)
- [x] Add tool_suggest tool.
- [x] Move chatgpt/src/connectors.rs and core/src/connectors.rs into a
dedicated mod so that we have all the logic and global cache in one
place.
- [x] Update TUI app link view to support rendering the installation
view for mcp elicitation.

---------

Co-authored-by: Shaqayeq <shaqayeq@openai.com>
Co-authored-by: Eric Traut <etraut@openai.com>
Co-authored-by: pakrym-oai <pakrym@openai.com>
Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
Co-authored-by: guinness-oai <guinness@openai.com>
Co-authored-by: Eugene Brevdo <ebrevdo@users.noreply.github.com>
Co-authored-by: Charlie Guo <cguo@openai.com>
Co-authored-by: Fouad Matin <fouad@openai.com>
Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
Co-authored-by: xl-openai <xl@openai.com>
Co-authored-by: alexsong-oai <alexsong@openai.com>
Co-authored-by: Owen Lin <owenlin0@gmail.com>
Co-authored-by: sdcoffey <stevendcoffey@gmail.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Won Park <won@openai.com>
Co-authored-by: Dylan Hurd <dylan.hurd@openai.com>
Co-authored-by: celia-oai <celia@openai.com>
Co-authored-by: gabec-openai <gabec@openai.com>
Co-authored-by: joeytrasatti-openai <joey.trasatti@openai.com>
Co-authored-by: Leo Shimonaka <leoshimo@openai.com>
Co-authored-by: Rasmus Rygaard <rasmus@openai.com>
Co-authored-by: maja-openai <163171781+maja-openai@users.noreply.github.com>
Co-authored-by: pash-openai <pash@openai.com>
Co-authored-by: Josh McKinney <joshka@openai.com>
2026-03-11 22:06:59 -07:00
sayan-oai
917c2df201 chore: use AVAILABLE and ON_INSTALL as default plugin install and auth policies (#14407)
make `AVAILABLE` the default plugin installPolicy when unset in
`marketplace.json`. similarly, make `ON_INSTALL` the default authPolicy.

this means, when unset, plugins are available to be installed (but not
auto-installed), and the contained connectors will be authed at
install-time.

updated tests.
2026-03-11 20:33:17 -07:00
Owen Lin
5bc82c5b93 feat(app-server): propagate traces across tasks and core ops (#14387)
## Summary

This PR keeps app-server RPC request trace context alive for the full
lifetime of the work that request kicks off (e.g. for `thread/start`,
this is `app-server rpc handler -> tokio background task -> core op
submissions`). Previously we lose trace lineage once the request handler
returns or hands work off to background tasks.

This approach is especially relevant for `thread/start` and other RPC
handlers that run in a non-blocking way. In the near future we'll most
likely want to make all app-server handlers run in a non-blocking way by
default, and only queue operations that must operate in order (e.g.
thread RPCs per thread?), so we want to make sure tracing in app-server
just generally works.

Depends on https://github.com/openai/codex/pull/14300

**Before**
<img width="155" height="207" alt="image"
src="https://github.com/user-attachments/assets/c9487459-36f1-436c-beb7-fafeb40737af"
/>


**After**
<img width="299" height="337" alt="image"
src="https://github.com/user-attachments/assets/727392b2-d072-4427-9dc4-0502d8652dea"
/>

## What changed

- Keep request-scoped trace context around until we send the final
response or error, or the connection closes.
- Thread that trace context through detached `thread/start` work so
background startup stays attached to the originating request.
- Pass request trace context through to downstream core operations,
including:
  - thread creation
  - resume/fork flows
  - turn submission
  - review
  - interrupt
  - realtime conversation operations
- Add tracing tests that verify:
  - remote W3C trace context is preserved for `thread/start`
  - remote W3C trace context is preserved for `turn/start`
  - downstream core spans stay under the originating request span
  - request-scoped tracing state is cleaned up correctly
- Clean up shutdown behavior so detached background tasks and spawned
threads are drained before process exit.
2026-03-11 20:18:31 -07:00
Ahmed Ibrahim
bf5e997b31 Include spawn agent model metadata in app-server items (#14410)
- add model and reasoning effort to app-server collab spawn items and
notifications
- regenerate app-server protocol schemas for the new fields

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-11 19:25:21 -07:00
viyatb-oai
c2d5458d67 fix: align core approvals with split sandbox policies (#14171)
## Stack

   fix: fail closed for unsupported split windows sandboxing #14172
   fix: preserve split filesystem semantics in linux sandbox #14173
-> fix: align core approvals with split sandbox policies #14171
   refactor: centralize filesystem permissions precedence #14174

## Why This PR Exists

This PR is intentionally narrower than the title may suggest.

Most of the original split-permissions migration already landed in the
earlier `#13434 -> #13453` stack. In particular:

- `#13439` already did the broad runtime plumbing for split filesystem
and network policies.
- `#13445` already moved `apply_patch` safety onto filesystem-policy
semantics.
- `#13448` already switched macOS Seatbelt generation to split policies.
- `#13449` and `#13453` already handled Linux helper and bubblewrap
enforcement.
- `#13440` already introduced the first protocol-side helpers for
deriving effective filesystem access.

The reason this PR still exists is that after the follow-on
`[permissions]` work and the new shared precedence helper in `#14174`, a
few core approval paths were still deciding behavior from the legacy
`SandboxPolicy` projection instead of the split filesystem policy that
actually carries the carveouts.

That means this PR is mostly a cleanup and alignment pass over the
remaining core consumers, not a fresh sandbox backend migration.

## What Is Actually New Here

- make unmatched-command fallback decisions consult
`FileSystemSandboxPolicy` instead of only legacy `DangerFullAccess` /
`ReadOnly` / `WorkspaceWrite` categories
- thread `file_system_sandbox_policy` into the shell, unified-exec, and
intercepted-exec approval paths so they all use the same split-policy
semantics
- keep `apply_patch` safety on the same effective-access rules as the
shared protocol helper, rather than letting it drift through
compatibility projections
- add loader-level regression coverage proving legacy `sandbox_mode`
config still builds split policies and round-trips back without semantic
drift

## What This PR Does Not Do

This PR does not introduce new platform backend enforcement on its own.

- Linux backend parity remains in `#14173`.
- Windows fail-closed handling remains in `#14172`.
- The shared precedence/model changes live in `#14174`.

## Files To Focus On

- `core/src/exec_policy.rs`: unmatched-command fallback and approval
rendering now read the split filesystem policy directly
- `core/src/tools/sandboxing.rs`: default exec-approval requirement keys
off `FileSystemSandboxPolicy.kind`
- `core/src/tools/handlers/shell.rs`: shell approval requests now carry
the split filesystem policy
- `core/src/unified_exec/process_manager.rs`: unified-exec approval
requests now carry the split filesystem policy
- `core/src/tools/runtimes/shell/unix_escalation.rs`: intercepted exec
fallback now uses the same split-policy approval semantics
- `core/src/safety.rs`: `apply_patch` safety keeps using effective
filesystem access rather than legacy sandbox categories
- `core/src/config/config_tests.rs`: new regression coverage for legacy
`sandbox_mode` no-drift behavior through the split-policy loader

## Notes

- `core/src/codex.rs` and `core/src/codex_tests.rs` are just small
fallout updates for `RequestPermissionsResponse.scope`; they are not the
point of the PR.
- If you reviewed the earlier `#13439` / `#13445` stack, the main review
question here is simply: “are there any remaining approval or
patch-safety paths that still reconstruct semantics from legacy
`SandboxPolicy` instead of consuming the split filesystem policy
directly?”

## Testing
- cargo test -p codex-core
legacy_sandbox_mode_config_builds_split_policies_without_drift
- cargo test -p codex-core request_permissions
- cargo test -p codex-core intercepted_exec_policy
- cargo test -p codex-core
restricted_sandbox_requires_exec_approval_on_request
- cargo test -p codex-core
unmatched_on_request_uses_split_filesystem_policy_for_escalation_prompts
- cargo test -p codex-core explicit_
- cargo clippy -p codex-core --tests -- -D warnings
2026-03-12 02:23:22 +00:00
Owen Lin
c1ea3f95d1 chore(app-server): delete unused rpc methods from v1.rs (#14394)
## Description

This PR trims `app-server-protocol`'s v1 surface down to the small set
of legacy types we still actually use.

Unfortunately, we can't delete all of them yet because:
- a few one-off v1 RPCs are still used by the Codex app
- a few of these app-server-protocol v1 types are actually imported by
core crates

This change deletes that unused RPC surface, keeps the remaining
compatibility types in place, and makes the crate root re-export only
the v1 structs that downstream crates still depend on.

## Why

The main goal here is to make the legacy protocol surface match reality.
Leaving a large pile of dead v1 structs in place makes it harder to tell
which compatibility paths are still intentional, and it keeps old
schema/types around even though nothing should be building against them
anymore.

This also gives us a cleaner boundary for future cleanup. Instead of
re-exporting all of `protocol::v1::*`, the crate now explicitly exposes
only the v1 types that are still live, which makes it much easier to see
what remains and delete more safely later.

## What changed

- Deleted the unused v1 RPC/request/response structs from
`app-server-protocol/src/protocol/v1.rs`.
- Kept the small set of v1 compatibility types that are still live,
including:
  - `initialize`
  - `getConversationSummary`
  - `getAuthStatus`
  - `gitDiffToRemote`
  - legacy approval payloads
  - config-related structs still used by downstream crates
- Replaced the blanket `pub use protocol::v1::*` export in
`app-server-protocol/src/lib.rs` with an explicit list of the remaining
supported v1 types.
- Regenerated the schema/type artifacts, which also updated the
`InitializeCapabilities` opt-out example to use `thread/started` instead
of the old `codex/event/session_configured` example.

## Validation

- `just write-app-server-schema`
- `cargo test -p codex-app-server-protocol`

## Follow-up

The next cleanup is to keep shrinking the remaining v1 compatibility
surface as callers migrate off it. Once the remaining consumers stop
importing these legacy types, we should be able to remove more of the v1
module and eventually stop exporting it from the crate root entirely.
2026-03-12 01:41:16 +00:00
viyatb-oai
f276325cdc refactor: centralize filesystem permissions precedence (#14174)
## Stack

   fix: fail closed for unsupported split windows sandboxing #14172
   fix: preserve split filesystem semantics in linux sandbox #14173
   fix: align core approvals with split sandbox policies #14171
-> refactor: centralize filesystem permissions precedence #14174

## Summary
- add a shared per-path split filesystem precedence helper in
`FileSystemSandboxPolicy`
- derive readable, writable, and unreadable roots from the same
most-specific resolution rules
- add regression coverage for nested `write` / `read` / `none` carveouts
and legacy bridge enforcement detection

## Testing
- cargo test -p codex-protocol
- cargo clippy -p codex-protocol --tests -- -D warnings
2026-03-12 01:35:44 +00:00
Anton Panasenko
77b0c75267 feat: search_tool migrate to bring you own tool of Responses API (#14274)
## Why

to support a new bring your own search tool in Responses
API(https://developers.openai.com/api/docs/guides/tools-tool-search#client-executed-tool-search)
we migrating our bm25 search tool to use official way to execute search
on client and communicate additional tools to the model.

## What
- replace the legacy `search_tool_bm25` flow with client-executed
`tool_search`
- add protocol, SSE, history, and normalization support for
`tool_search_call` and `tool_search_output`
- return namespaced Codex Apps search results and wire namespaced
follow-up tool calls back into MCP dispatch
2026-03-11 17:51:51 -07:00
Owen Lin
72631755e0 chore(app-server): stop emitting codex/event/ notifications (#14392)
## Description

This PR stops emitting legacy `codex/event/*` notifications from the
public app-server transports.

It's been a long time coming! app-server was still producing a raw
notification stream from core, alongside the typed app-server
notifications and server requests, for compatibility reasons. Now,
external clients should no longer be depending on those legacy
notifications, so this change removes them from the stdio and websocket
contract and updates the surrounding docs, examples, and tests to match.

### Caveat
I left the "in-process" version of app-server alone for now, since
`codex exec` was recently based on top of app-server via this in-process
form here: https://github.com/openai/codex/pull/14005

Seems like `codex exec` still consumes some legacy notifications
internally, so this branch only removes `codex/event/*` from app-server
over stdio and websockets.

## Follow-up

Once `codex exec` is fully migrated off `codex/event/*` notifications,
we'll be able to stop emitting them entirely entirely instead of just
filtering it at the external transport boundary.
2026-03-12 00:45:20 +00:00
Owen Lin
f50e88db82 check for large binaries in CI (#14382)
Prevent binaries >500KB from being committed. And maintain an allowlist
if we need to bypass on a case-by-case basis.

I checked the currently tracked binary-like assets in the repo. There
are only 5 obvious committed binaries by extension/MIME type:
- `.github/codex-cli-splash.png`: `838,131` bytes, about `818 KiB`
- `codex-rs/vendor/bubblewrap/bubblewrap.jpg`: `40,239` bytes, about `39
KiB`
-
`codex-rs/skills/src/assets/samples/skill-creator/assets/skill-creator.png`:
`1,563` bytes
- `codex-rs/skills/src/assets/samples/openai-docs/assets/openai.png`:
`1,429` bytes
-
`codex-rs/skills/src/assets/samples/skill-installer/assets/skill-installer.png`:
`1,086` bytes

So `500 KB` looks like a good default for this repo. It would only trip
on one existing intentional asset, which keeps the allowlist small and
the policy easy to understand.

Here's a smoke-test from a throwaway branch that tries to commit a large
binary:
https://github.com/openai/codex/actions/runs/22971558828/job/66689330435?pr=14383
2026-03-11 22:39:08 +00:00
Curtis 'Fjord' Hawthorne
8791f0ab9a Let models opt into original image detail (#14175)
## Summary

This PR narrows original image detail handling to a single opt-in
feature:

- `image_detail_original` lets the model request `detail: "original"` on
supported models
- Omitting `detail` preserves the default resized behavior

The model only sees `detail: "original"` guidance when the active model
supports it:

- JS REPL instructions include the guidance and examples only on
supported models
- `view_image` only exposes a `detail` parameter when the feature and
model can use it

The image detail API is intentionally narrow and consistent across both
paths:

- `view_image.detail` supports only `"original"`; otherwise omit the
field
- `codex.emitImage(..., detail)` supports only `"original"`; otherwise
omit the field
- Unsupported explicit values fail clearly at the API boundary instead
of being silently reinterpreted
- Unsupported explicit `detail: "original"` requests fall back to normal
behavior when the feature is disabled or the model does not support
original detail
2026-03-11 15:25:07 -07:00
Josh McKinney
f548309797 Keep agent-switch word-motion keys out of draft editing (#14376)
## Summary
- only trigger multi-agent fast-switch shortcuts when the composer is
empty
- keep the Option+b/f fallback for terminals that encode Option+arrow
that way
- document why the empty-composer gate preserves expected word-wise
editing behavior

## Testing
- just fmt
- cargo test -p codex-tui

Co-authored-by: Codex <noreply@openai.com>
2026-03-11 14:52:40 -07:00
Curtis 'Fjord' Hawthorne
5a89660ae4 Add js_repl cwd and homeDir helpers (#14385)
## Summary

This PR adds two read-only path helpers to `js_repl`:

- `codex.cwd`
- `codex.homeDir`

They are exposed alongside the existing `codex.tmpDir` helper so the
REPL can reference basic host path context without reopening direct
`process` access.

## Implementation

- expose `codex.cwd` and `codex.homeDir` from the js_repl kernel
- make `codex.homeDir` come from the kernel process environment
- pass session dependency env through js_repl kernel startup so
`codex.homeDir` matches the env a shell-launched process would see
- keep existing shell `HOME` population behavior unchanged
- update js_repl prompt/docs and add runtime/integration coverage for
the new helpers
2026-03-11 14:44:44 -07:00
viyatb-oai
5259e5e236 fix(network-proxy): serve HTTP proxy listener as HTTP/1 (#14395)
## Summary
- switch the local HTTP proxy listener from Rama's auto server to
explicit HTTP/1 so CONNECT clients skip the version-sniffing pre-read
path
- move rustls crypto-provider bootstrap into the HTTP proxy runner so
direct callers do not need hidden global init
- add a regression test that exercises a plain HTTP/1 CONNECT request
against a live loopback listener
2026-03-11 14:35:44 -07:00
Charley Cunningham
f5bb338fdb Defer initial context insertion until the first turn (#14313)
## Summary
- defer fresh-session `build_initial_context()` until the first real
turn instead of seeding model-visible context during startup
- rely on the existing `reference_context_item == None` turn-start path
to inject full initial context on that first real turn (and again after
baseline resets such as compaction)
- add a regression test for `InitialHistory::New` and update affected
deterministic tests / snapshots around developer-message layout,
collaboration instructions, personality updates, and compact request
shapes

## Notes
- this PR does not add any special empty-thread `/compact` behavior
- most of the snapshot churn is the direct result of moving the initial
model-visible context from startup to the first real turn, so first-turn
request layouts no longer contain a pre-user startup copy of permissions
/ environment / other developer-visible context
- remote manual `/compact` with no prior user still skips the remote
compact request; local first-turn `/compact` still issues a compact
request, but that request now reflects the lack of startup-seeded
context

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-11 12:33:10 -07:00
Ahmed Ibrahim
c32c445f1c Clarify locked role settings in spawn prompt (#14283)
- tell agents when a role pins model or reasoning effort so they know
those settings are not changeable
- add prompt-builder coverage for the locked-setting notes
2026-03-11 12:33:10 -07:00
viyatb-oai
52a3bde6cc feat(core): emit turn metric for network proxy state (#14250)
## Summary
- add a per-turn `codex.turn.network_proxy` metric constant
- emit the metric from turn completion using the live managed proxy
enabled state
- add focused tests for active and inactive tag emission
2026-03-11 12:33:10 -07:00
Ahmed Ibrahim
8f8a0f55ce spawn prompt (#14362)
# External (non-OpenAI) Pull Request Requirements

Before opening this Pull Request, please read the dedicated
"Contributing" markdown file or your PR may be closed:
https://github.com/openai/codex/blob/main/docs/contributing.md

If your PR conforms to our contribution guidelines, replace this text
with a detailed and high quality description of your changes.

Include a link to a bug report or enhancement request.
2026-03-11 12:33:10 -07:00
pakrym-oai
65b325159d Add ALL_TOOLS export to code mode (#14294)
So code mode can search for tools.
2026-03-11 12:33:10 -07:00
sayan-oai
7b2cee53db chore: wire through plugin policies + category from marketplace.json (#14305)
wire plugin marketplace metadata through app-server endpoints:
- `plugin/list` has `installPolicy` and `authPolicy`
- `plugin/install` has plugin-level `authPolicy`

`plugin/install` also now enforces `NOT_AVAILABLE` `installPolicy` when
installing.


added tests.
2026-03-11 12:33:10 -07:00
Owen Lin
fa1242c83b fix(otel): make HTTP trace export survive app-server runtimes (#14300)
## Summary

This PR fixes OTLP HTTP trace export in runtimes where the previous
exporter setup was unreliable, especially around app-server usage. It
also removes the old `codex_otel::otel_provider` compatibility shim and
switches remaining call sites over to the crate-root
`codex_otel::OtelProvider` export.

## What changed

- Use a runtime-safe OTLP HTTP trace exporter path for Tokio runtimes.
- Add an async HTTP client path for trace export when we are already
inside a multi-thread Tokio runtime.
- Make provider shutdown flush traces before tearing down the tracer
provider.
- Add loopback coverage that verifies traces are actually sent to
`/v1/traces`:
  - outside Tokio
  - inside a multi-thread Tokio runtime
  - inside a current-thread Tokio runtime
- Remove the `codex_otel::otel_provider` shim and update remaining
imports.

## Why

I hit cases where spans were being created correctly but never made it
to the collector. The issue turned out to be in exporter/runtime
behavior rather than the span plumbing itself. This PR narrows that gap
and gives us regression coverage for the actual export path.
2026-03-11 12:33:10 -07:00
pakrym-oai
548583198a Allow bool web_search in ToolsToml (#14352)
Summary
- add a custom deserializer so `[tools].web_search` can be a bool
(treated as disabled) or a config object
- extend core and app-server tests to cover bool handling in TOML config

Testing
- Not run (not requested)
2026-03-11 12:33:10 -07:00
Rasmus Rygaard
7f22329389 Revert "Pass more params to compaction" (#14298) 2026-03-11 12:33:10 -07:00
Channing Conger
fd4a673525 Responses: set x-client-request-id as convesration_id when talking to responses (#14312)
Right now we're sending the header session_id to responses which is
ignored/dropped. This sets a useful x-client-request-id to the
conversation_id.
2026-03-11 12:33:10 -07:00
Fouad Matin
f385199cc0 fix(arc_monitor): api path (#14290)
This PR just fixes the API path for ARC monitor.
2026-03-11 12:33:10 -07:00
gabec-openai
180a5820fc Add keyboard based fast switching between agents in TUI (#13923) 2026-03-11 12:33:10 -07:00
pakrym-oai
12ee9eb6e0 Add snippets annotated with types to tools when code mode enabled (#14284)
Main purpose is for code mode to understand the return type.
2026-03-11 12:33:09 -07:00
Ahmed Ibrahim
a4d884c767 Split spawn_csv from multi_agent (#14282)
- make `spawn_csv` a standalone feature for CSV agent jobs
- keep `spawn_csv -> multi_agent` one-way and preserve restricted
subagent disable paths
2026-03-11 12:33:09 -07:00
Ahmed Ibrahim
39c1bc1c68 Add realtime start instructions config override (#14270)
- add `realtime_start_instructions` config support
- thread it into realtime context updates, schema, docs, and tests
2026-03-11 12:33:09 -07:00
pakrym-oai
31bf1dbe63 Make unified exec session_id numeric (#14279)
It's a number on the write_stdin input, make it a number on the output
and also internally.
2026-03-11 12:33:09 -07:00
pakrym-oai
01792a4c61 Prefix code mode output with success or failure message and include error stack (#14272) 2026-03-11 12:33:09 -07:00
pash-openai
da74da6684 render local file links from target paths (#13857)
Co-authored-by: Josh McKinney <joshka@openai.com>
2026-03-11 12:33:09 -07:00
Ahmed Ibrahim
c8446d7cf3 Stabilize websocket response.failed error delivery (#14017)
## What changed
- Drop failed websocket connections immediately after a terminal stream
error instead of awaiting a graceful close handshake before forwarding
the error to the caller.
- Keep the success path and the closed-connection guard behavior
unchanged.

## Why this fixes the flake
- The failing integration test waits for the second websocket stream to
surface the model error before issuing a follow-up request.
- On slower runners, the old error path awaited
`ws_stream.close().await` before sending the error downstream. If that
close handshake stalled, the test kept waiting for an error that had
already happened server-side and nextest timed it out.
- Dropping the failed websocket immediately makes the terminal error
observable right away and marks the session closed so the next request
reconnects cleanly instead of depending on a best-effort close
handshake.

## Code or test?
- This is a production logic fix in `codex-api`. The existing websocket
integration test already exercises the regression path.
2026-03-11 12:33:09 -07:00
Ahmed Ibrahim
285b3a5143 Show spawned agent model and effort in TUI (#14273)
- include the requested sub-agent model and reasoning effort in the
spawn begin event\n- render that metadata next to the spawned agent name
and role in the TUI transcript

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-11 12:33:09 -07:00
pakrym-oai
8a099b3dfb Rename code mode tool to exec (#14254)
Summary
- update the code-mode handler, runner, instructions, and error text to
refer to the `exec` tool name everywhere that used to say `code_mode`
- ensure generated documentation strings and tool specs describe `exec`
and rely on the shared `PUBLIC_TOOL_NAME`
- refresh the suite tests so they invoke `exec` instead of the old name

Testing
- Not run (not requested)
2026-03-11 12:33:09 -07:00
maja-openai
e77b2fd925 prompt changes to guardian (#14263)
## Summary
  - update the guardian prompting
- clarify the guardian rejection message so an action may still proceed
if the user explicitly approves it after being informed of the risk

  ## Testing
  - cargo run on selected examples
2026-03-11 12:33:09 -07:00
Ahmed Ibrahim
9b5078d3e8 Stabilize pipe process stdin round-trip test (#14013)
## What changed
- keep the explicit stdin-close behavior after writing so the child
still receives EOF deterministically
- on Windows, stop using `python -c` for the round-trip assertion and
instead run a native `cmd.exe` pipeline that reads one line from stdin
with `set /p` and echoes it back
- send `
` on Windows so the stdin payload matches the platform-native line
ending the shell reader expects

## Why this fixes flakiness
The failing branch-local flake was not in `spawn_pipe_process` itself.
The child exited cleanly, but the Windows ARM runner sometimes produced
an empty stdout string when the test used Python as the stdin consumer.
That makes the test sensitive to Python startup and stdin-close timing
rather than the pipe primitive we actually want to validate. Switching
the Windows path to a native `cmd.exe` reader keeps the assertion
focused on our pipe behavior: bytes written to stdin should come back on
stdout before EOF closes the process. The explicit `
` write removes line-ending ambiguity on Windows.

## Scope
- test-only
- no production logic change
2026-03-11 12:33:09 -07:00
Celia Chen
c1a424691f chore: add a separate reject-policy flag for skill approvals (#14271)
## Summary
- add `skill_approval` to `RejectConfig` and the app-server v2
`AskForApproval::Reject` payload so skill-script prompts can be
configured independently from sandbox and rule-based prompts
- update Unix shell escalation to reject prompts based on the actual
decision source, keeping prefix rules tied to `rules`, unmatched command
fallbacks tied to `sandbox_approval`, and skill scripts tied to
`skill_approval`
- regenerate the affected protocol/config schemas and expand
unit/integration coverage for the new flag and skill approval behavior
2026-03-11 12:33:09 -07:00
pakrym-oai
83b22bb612 Add store/load support for code mode (#14259)
adds support for transferring state across code mode invocations.
2026-03-11 12:33:09 -07:00
Rasmus Rygaard
2621ba17e3 Pass more params to compaction (#14247)
Pass more params to /compact. This should give us parity with the
/responses endpoint to improve caching.

I'm torn about the MCP await. Blocking will give us parity but it seems
like we explicitly don't block on MCPs. Happy either way
2026-03-11 12:33:09 -07:00
Leo Shimonaka
889b4796fc feat: Add additional macOS Sandbox Permissions for Launch Services, Contacts, Reminders (#14155)
Add additional macOS Sandbox Permissions levers for the following:

- Launch Services
- Contacts
- Reminders
2026-03-11 12:33:09 -07:00
joeytrasatti-openai
8ac27b2a16 Add ephemeral flag support to thread fork (#14248)
### Summary
This PR adds first-class ephemeral support to thread/fork, bringing it
in line with thread/start. The goal is to support one-off completions on
full forked threads without persisting them as normal user-visible
threads.

### Testing
2026-03-11 12:33:08 -07:00
pakrym-oai
07c22d20f6 Add code_mode output helpers for text and images (#14244)
Summary
- document how code-mode can import `output_text`/`output_image` and
ensure `add_content` stays compatible
- add a synthetic `@openai/code_mode` module that appends content items
and validates inputs
- cover the new behavior with integration tests for structured text and
image outputs

Testing
- Not run (not requested)
2026-03-11 12:33:08 -07:00
Ahmed Ibrahim
ce1d9abf11 Clarify close_agent tool description (#14269)
- clarify the `close_agent` tool description so it nudges models to
close agents they no longer need
- keep the change scoped to the tool spec text only

Co-authored-by: Codex <noreply@openai.com>
2026-03-11 12:33:08 -07:00
Ahmed Ibrahim
b1dddcb76e Increase sdk workflow timeout to 15 minutes (#14252)
- raise the sdk workflow job timeout from 10 to 15 minutes to reduce
false cancellations near the current limit

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-11 12:33:08 -07:00
gabec-openai
a67660da2d Load agent metadata from role files (#14177) 2026-03-11 12:33:08 -07:00
pakrym-oai
3d41ff0b77 Add model-controlled truncation for code mode results (#14258)
Summary
- document that `@openai/code_mode` exposes
`set_max_output_tokens_per_exec_call` and that `code_mode` truncates the
final Rust-side output when the budget is exceeded
- enforce the configured budget in the Rust tool runner, reusing
truncation helpers so text-only outputs follow the unified-exec wrapper
and mixed outputs still fit within the limit
- ensure the new behavior is covered by a code-mode integration test and
string spec update

Testing
- Not run (not requested)
2026-03-11 12:33:08 -07:00
pakrym-oai
ee8f84153e 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-11 12:33:08 -07:00
Dylan Hurd
d5694529ca 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-11 12:33:08 -07:00
Won Park
722e8f08e1 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-11 12:33:08 -07:00
Ahmed Ibrahim
91ca20c7c3 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-11 12:33:08 -07:00
alexsong-oai
3d4628c9c4 Add granular metrics for cloud requirements load (#14108) 2026-03-11 12:33:08 -07:00
xl-openai
d751e68f44 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-11 12:33:08 -07:00
Matthew Zeng
f2d66fadd8 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-11 12:33:08 -07:00
Charlie Guo
b7f8e9195a 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-11 12:33:08 -07:00
Eugene Brevdo
3b1c78a5c5 [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-11 12:33:08 -07:00
guinness-oai
4ac6042850 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-11 12:33:07 -07:00
pakrym-oai
c4d35084f5 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-11 12:33:07 -07:00
Ahmed Ibrahim
52a7f4b68b 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-11 12:33:07 -07:00
pakrym-oai
00ea8aa7ee 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-11 12:33:07 -07:00
Eric Traut
f9cba5cb16 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-11 12:33:07 -07:00
Eric Traut
026cfde023 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-11 12:33:07 -07:00
Eric Traut
7144f84c69 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-11 12:33:07 -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
sayan-oai
a3cd9f16f5 sort plugins first in menu (#14163)
we want plugin mentions to show up before others, like apps and skills.

updated tests.
2026-03-10 03:51:16 +00:00
pakrym-oai
aa04ea6bd7 Refactor tool output into trait implementations (#14152)
First state to making tool outputs strongly typed (and `renderable`).
2026-03-09 19:38:32 -07:00
sayan-oai
a5af11211a make dollar-mention always clarify item category (skill, app, plugin) (#14147)
#### What

###### Context + Problem

With the introduction of plugins, we now have one more type of
`$`-mentionable item in the TUI's popup menu on `$`. Apps, skills, and
plugins can all have the same user-facing name, and we attempt to
distinguish with a category tag suffix, like `[App]`. This has a few
problems:

- We decide to show tags by the text that will be inserted into the
conversation, not the actual user-visible text, so two visibly-identical
entries can have no clarifying category tag suffix
- The category tag is a suffix and commonly gets cut off by long
descriptions
- The skill category tag is currently only displayed on repo skills as
`[Repo]`, which is confusing to most users
- The plugin category tag is currently `[<marketplace-name>]`, which is
also confusing to most users

###### Solution
- **Always** show a **prefix** category tag that is `[Skill]`, `[App]`,
or `[Plugin]`. No conditional rendering or copy.

Before:
<img width="801" height="153" alt="image"
src="https://github.com/user-attachments/assets/448e06e7-2af8-4c14-9804-ed1ca17cf514"
/>

After:
<img width="800" height="118" alt="image"
src="https://github.com/user-attachments/assets/57895b41-06fe-4d92-887b-68704c5a15fd"
/>

I also feel this clarifies the results at-a-glance while you scroll:


https://github.com/user-attachments/assets/cbdd5840-53d9-4656-812c-6e816755e1fd

### Tests
Added + updated tests (including snapshots), tested locally
2026-03-09 19:35:11 -07:00
viyatb-oai
1165a16e6f fix: keep permissions profiles forward compatible (#14107)
## Summary
- preserve unknown `:special_path` tokens, including nested entries, so
older Codex builds warn and ignore instead of failing config load
- fail closed with a startup warning when a permissions profile has
missing or empty filesystem entries instead of aborting profile
compilation
- normalize Windows verbatim paths like `\?\C:\...` before absolute-path
validation while keeping explicit errors for truly invalid paths

## Testing
- just fmt
- cargo test -p codex-core permissions_profiles_allow
- cargo test -p codex-core
normalize_absolute_path_for_platform_simplifies_windows_verbatim_paths
- cargo test -p codex-protocol
unknown_special_paths_are_ignored_by_legacy_bridge
- cargo clippy -p codex-core -p codex-protocol --all-targets -- -D
warnings
- cargo clean
2026-03-09 18:43:38 -07:00
viyatb-oai
b0cbc25a48 fix(protocol): preserve legacy workspace-write semantics (#13957)
## Summary
This is a fast follow to the initial `[permissions]` structure.

- keep the new split-policy carveout behavior for narrower non-write
entries under broader writable roots
- preserve legacy `WorkspaceWrite` semantics by using a cwd-aware bridge
that drops only redundant nested readable roots when projecting from
`SandboxPolicy`
- route the legacy macOS seatbelt adapter through that same legacy
bridge so redundant nested readable roots do not become read-only
carveouts on macOS
- derive the legacy bridge for `command_exec` using the sandbox root cwd
rather than the request cwd so policy derivation matches later sandbox
enforcement
- add regression coverage for the legacy macOS nested-readable-root case

## Examples
### Legacy `workspace-write` on macOS
A legacy `workspace-write` policy can redundantly list a nested readable
root under an already-writable workspace root.

For example, legacy config can effectively mean:
- workspace root (`.` / `cwd`) is writable
- `docs/` is also listed in `readable_roots`

The new shared split-policy helper intentionally treats a narrower
non-write entry under a broader writable root as a carveout for real
`[permissions]` configs. Without this fast follow, the unchanged macOS
seatbelt legacy adapter could project that legacy shape into a
`FileSystemSandboxPolicy` that treated `docs/` like a read-only carveout
under the writable workspace root. In practice, legacy callers on macOS
could unexpectedly lose write access inside `docs/`, even though that
path was writable before the `[permissions]` migration work.

This change fixes that by routing the legacy seatbelt path through the
cwd-aware legacy bridge, so:
- legacy `workspace-write` keeps `docs/` writable when `docs/` was only
a redundant readable root
- explicit `[permissions]` entries like `'.' = 'write'` and `'docs' =
'read'` still make `docs/` read-only, which is the new intended
split-policy behavior

### Legacy `command_exec` with a subdirectory cwd
`command_exec` can run a command from a request cwd that is narrower
than the sandbox root cwd.

For example:
- sandbox root cwd is `/repo`
- request cwd is `/repo/subdir`
- legacy policy is still `workspace-write` rooted at `/repo`

Before this fast follow, `command_exec` derived the legacy bridge using
the request cwd, but the sandbox was later built using the sandbox root
cwd. That mismatch could miss redundant legacy readable roots during
projection and accidentally reintroduce read-only carveouts for paths
that should still be writable under the legacy model.

This change fixes that by deriving the legacy bridge with the same
sandbox root cwd that sandbox enforcement later uses.

## Verification
- `just fmt`
- `cargo test -p codex-core
seatbelt_legacy_workspace_write_nested_readable_root_stays_writable`
- `cargo test -p codex-core test_sandbox_config_parsing`
- `cargo clippy -p codex-core -p codex-app-server --all-targets -- -D
warnings`
- `cargo clean`
2026-03-09 18:43:27 -07:00
Dylan Hurd
6da84efed8 feat(approvals) RejectConfig for request_permissions (#14118)
## Summary
We need to support allowing request_permissions calls when using
`Reject` policy

<img width="1133" height="588" alt="Screenshot 2026-03-09 at 12 06
40 PM"
src="https://github.com/user-attachments/assets/a8df987f-c225-4866-b8ab-5590960daec5"
/>

Note that this is a backwards-incompatible change for Reject policy. I'm
not sure if we need to add a default based on our current use/setup

## Testing
- [x] Added tests
- [x] Tested locally
2026-03-09 18:16:54 -07:00
Dylan Hurd
c1defcc98c fix(core) RequestPermissions + ApplyPatch (#14055)
## Summary
The apply_patch tool should also respect AdditionalPermissions

## Testing
- [x] Added unit tests

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-09 16:11:19 -07:00
Max Johnson
66e71cce11 codex-rs/app-server: add health endpoints for --listen websocket server (#13782)
Healthcheck endpoints for the websocket server

- serve `GET /readyz` and `GET /healthz` from the same listener used for
`--listen ws://...`
- switch the websocket listener over to `axum` upgrade handling instead
of manual socket parsing
- add websocket transport coverage for the health endpoints and document
the new behavior

Testing
- integration tests
- built and tested e2e

```
> curl -i http://127.0.0.1:9234/readyz
HTTP/1.1 200 OK
content-length: 0
date: Fri, 06 Mar 2026 19:20:23 GMT

>  curl -i http://127.0.0.1:9234/healthz
HTTP/1.1 200 OK
content-length: 0
date: Fri, 06 Mar 2026 19:20:24 GMT
```
2026-03-09 22:11:30 +00:00
Owen Lin
d309c102ef fix(core): use dedicated types for responsesapi web search tool config (#14136)
This changes the web_search tool spec in codex-core to use dedicated
Responses-API payload structs instead of shared config types and custom
serializers.

Previously, `ToolSpec::WebSearch` stored `WebSearchFilters` and
`WebSearchUserLocation` directly and relied on hand-written serializers
to shape the outgoing JSON. This worked, but it mixed config/schema
types with the OpenAI Responses payload contract and created an easy
place for drift if those shared types changed later.

### Why
This keeps the boundary clearer:
- app-server/config/schema types stay focused on config
- Responses tool payload types stay focused on the OpenAI wire format

It also makes the serialization behavior obvious from the structs
themselves, instead of hiding it in custom serializer functions.
2026-03-09 14:58:33 -07:00
Dylan Hurd
d241dc598c feat(core) Persist request_permission data across turns (#14009)
## Summary
request_permissions flows should support persisting results for the
session.

Open Question: Still deciding if we need within-turn approvals - this
adds complexity but I could see it being useful

## Testing
- [x] Updated unit tests

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-09 14:36:38 -07:00
Ahmed Ibrahim
831ee51c86 Stabilize protocol schema fixture generation (#13886)
## What changed
- TypeScript schema fixture generation now goes through in-memory tree
helpers rather than a heavier on-disk generation path.
- The comparison logic normalizes generated banner and path differences
that are not semantically relevant to the exported schema.
- TypeScript and JSON fixture coverage are split into separate tests,
and the expensive schema-export tests are serialized in `nextest`.

## Why this fixes the flake
- The original fixture coverage mixed several heavy codegen paths into
one monolithic test and then compared generated output that included
incidental banner/path differences.
- On Windows CI, that combination created both runtime pressure and
output variance unrelated to the schema shapes we actually care about.
- Splitting the coverage isolates failures by format, in-memory
generation reduces filesystem churn, normalization strips generator
noise, and serializing the heavy tests removes parallel resource
contention.

## Scope
- Production helper change plus test changes.
2026-03-09 13:51:50 -07:00
Won Park
42f20a6845 pass on save info to model + ui tweaks (#14123)
Passing on more information to the model for context purposes, to
streamline image-identification.
2026-03-09 20:10:15 +00:00
Ahmed Ibrahim
44ecc527cb Stabilize RMCP streamable HTTP readiness tests (#13880)
## What changed
- The RMCP streamable HTTP tests now wait for metadata and tool
readiness before issuing tool calls.
- OAuth state is isolated per test home.
- The helper server startup path now uses bounded bind retries so
transient `AddrInUse` collisions do not fail the test immediately.

## Why this fixes the flake
- The old tests could begin issuing tool requests before the helper
server had finished advertising its metadata and tools, so the first
request sometimes raced the server startup sequence.
- On top of that, shared OAuth state and occasional bind collisions on
CI runners introduced cross-test environmental noise unrelated to the
functionality under test.
- Readiness polling makes the client wait for an observable “server is
ready” signal, while isolated state and bounded bind retries remove
external contention that was causing intermittent failures.

## Scope
- Test-only change.
2026-03-09 19:52:55 +00:00
Owen Lin
da991bdf3a feat(otel): Centralize OTEL metric names and shared tag builders (#14117)
This cleans up a bunch of metric plumbing that had started to drift.

The main change is making `codex-otel` the canonical home for shared
metric definitions and metric tag helpers. I moved the `turn/thread`
metric names that were still duplicated into the OTEL metric registry,
added a shared `metrics::tags` module for common tag keys and session
tag construction, and updated `SessionTelemetry` to build its metadata
tags through that shared path.

On the codex-core side, TTFT/TTFM now use the shared metric-name
constants instead of local string definitions. I also switched the
obvious remaining turn/thread metric callsites over to the shared
constants, and added a small helper so TTFT/TTFM can attach an optional
sanitized client.name tag from TurnContext.

This should make follow-on telemetry work less ad hoc:
- one canonical place for metric names
- one canonical place for common metric tag keys/builders
- less duplication between `codex-core` and `codex-otel`
2026-03-09 12:46:42 -07:00
sayan-oai
6ad448b658 chore: plugin/uninstall endpoint (#14111)
add `plugin/uninstall` app-server endpoint to fully rm plugin from
plugins cache dir and rm entry from user config file.

plugin-enablement is session-scoped, so uninstalls are only picked up in
new sessions (like installs).

added tests.
2026-03-09 12:40:25 -07:00
Dylan Hurd
0334ddeccb fix(ci) Faster shell_command::unicode_output test (#14114)
## Summary
Alternative to #14061 - we need to use a child process on windows to
correctly validate Powershell behavior.

## Testing
- [x] These are tests
2026-03-09 19:09:56 +00:00
Ahmed Ibrahim
fefd01b9e0 Stabilize resumed rollout messages (#14060)
## What changed
- add a bounded `resume_until_initial_messages` helper in
`core/tests/suite/resume.rs`
- retry the resume call until `initial_messages` contains the fully
persisted final turn shape before asserting

## Why this fixes flakiness
The old test resumed once immediately after `TurnComplete` and sometimes
read rollout state before the final turn had been persisted. That made
the assertion race persistence timing instead of checking the resumed
message shape. The new helper polls for up to two seconds in 10ms steps
and only asserts once the expected message sequence is actually present,
so the test waits for the real readiness condition instead of depending
on a lucky timing window.

## Scope
- test-only
- no production logic change
2026-03-09 11:48:13 -07:00
Ahmed Ibrahim
e03e9b63ea Stabilize guardian approval coverage (#14103)
## Summary
- align the guardian permission test with the actual sandbox policy it
widens and use a slightly larger Windows-only timeout budget
- expose the additional-permissions normalization helper to the guardian
test module
- replace the guardian popup snapshot assertion with targeted string
assertions

## Why this fixes the flake
This group was carrying two separate sources of drift. The guardian core
test widened derived sandbox policies without updating the source
sandbox policy, and it used a Windows command/timeout combination that
was too tight on slower runners. Separately, the TUI test was
snapshotting the full popup even though unrelated feature text changes
were the only thing moving. The new assertions keep coverage on the
guardian entry itself while removing unrelated snapshot churn.
2026-03-09 11:23:20 -07:00
Ahmed Ibrahim
ad57505ef5 Stabilize interrupted task approval cleanup (#14102)
## Summary
- drain the active turn tasks before clearing pending approvals during
interruption
- keep the turn in hand long enough for interrupted tasks to observe
cancellation first

## Why this fixes the flake
Interrupted turns could clear pending approvals too early, which let an
in-flight approval wait surface as a model-visible rejection before the
turn emitted `TurnAborted`. Reordering the cleanup removes that race
without changing the steady-state task model.
2026-03-09 11:22:51 -07:00
Ahmed Ibrahim
203a70a191 Stabilize shell approval MCP test (#14101)
## Summary
- replace the Python-based file creation command in the MCP shell
approval test with native platform commands
- build the expected command string from the exact argv that the test
sends

## Why this fixes the flake
The old test depended on Python startup and shell quoting details that
varied across runners. The new version still verifies the same approval
flow, but it uses `touch` on Unix and `New-Item` on Windows so the
assertion only depends on the MCP shell command that Codex actually
forwards.
2026-03-09 11:18:26 -07:00
xl-openai
b15cfe9329 fix: properly handle 401 error in clound requirement fetch. (#14049)
Handle cloud requirements 401s with the same auth recovery flow as
normal requests, so permanent refresh failures surface the existing
user-facing auth message instead of a generic workspace-config load
error.
2026-03-09 11:14:23 -07:00
xl-openai
c1f3ef16ec fix(plugin): Also load curated plugins for TUI. (#14050)
Also run maybe_start_curated_repo_sync_for_config at TUI start time.
2026-03-09 11:05:02 -07:00
Ahmed Ibrahim
75e608343c Stabilize realtime startup context tests (#13876)
## What changed
- The realtime startup-context tests no longer assume the interesting
websocket payload is always `connection 1 / request 0`.
- Instead, they now wait for the first outbound websocket request that
actually carries `session.instructions`, regardless of which websocket
connection won the accept-order race on the runner.
- The env-key fallback test stays serialized because it mutates process
environment.

## Why this fixes the flake
- The old test synchronized on the mirrored `session.updated` client
event and then inspected a fixed websocket slot.
- On CI, the response websocket and the realtime websocket can race each
other during startup. When the response websocket wins that race, the
fixed slot can contain `response.create` instead of the
startup-context-bearing `session.update` request the test actually cares
about.
- That made the test fail nondeterministically by inspecting the wrong
request, or by timing out waiting on a secondary event even though the
real outbound request path was correct.
- Waiting directly on the first request whose payload includes
`session.instructions` removes both ordering assumptions and makes the
assertion line up with the actual contract under test.
- Separately, serializing the environment-mutating fallback case
prevents unrelated tests from seeing partially updated auth state.

## Scope
- Test-only change.
2026-03-09 10:57:43 -07:00
Ahmed Ibrahim
4a0e6dc916 Serialize shell snapshot stdin test (#13878)
## What changed
- `snapshot_shell_does_not_inherit_stdin` now runs under its own serial
key.
- The change isolates it from other Unix shell-snapshot tests that also
interact with stdin.

## Why this fixes the flake
- The failure was not a shell-snapshot logic bug. It was shared-stdin
interference between concurrently executing tests.
- When multiple tests compete for inherited stdin at the same time, one
test can observe EOF or consumed input that actually belongs to a
different test.
- Running this specific test in a dedicated serial bucket guarantees
exclusive ownership of stdin, which makes the assertion deterministic
without weakening coverage.

## Scope
- Test-only change.
2026-03-09 10:44:13 -07:00
Ahmed Ibrahim
10bf6008f4 Stabilize thread resume replay tests (#13885)
## What changed
- The thread-resume replay tests now use unchecked mock sequencing so
the replay flow can complete before the test asserts.
- They also poll outbound `/responses` request counts and fail
immediately if replay emits an unexpected extra request.

## Why this fixes the flake
- The previous version asserted while the replay machinery was still
mid-flight, so the test was sometimes checking an intermediate state
instead of the completed behavior.
- Strict mock sequencing made that problem worse by forcing the test to
care about exact sub-step timing rather than about the end result.
- Letting replay settle and then asserting on stabilized request counts
makes the test validate the real contract: the replay path finishes and
does not send extra model requests.

## Scope
- Test-only change.
2026-03-09 10:41:23 -07:00
Ahmed Ibrahim
0dc242a672 Order websocket initialize after handshake (#13943)
## What changed
- `app-server` now sends initialize notifications to the specific
websocket connection before that connection is marked outbound-ready.
- `message_processor` now exposes the forwarding hook needed to target
that initialize delivery path.

## Why this fixes the flake
- This was a real websocket ordering bug.
- The old code allowed “connection is ready for outbound broadcasts” to
become true before the initialize notification had been routed to the
intended client.
- On CI this showed up as a race where tests would occasionally miss or
misorder initialize delivery depending on scheduler timing.
- Sending initialize to the exact connection first, then exposing it to
the general outbound path, removes that race instead of hiding it with
timing slack.

## Scope
- Production logic change.
2026-03-09 10:27:19 -07:00
Ahmed Ibrahim
6b68d1ef66 Stabilize plan item app-server tests (#14058)
## What changed
- run the two plan-mode app-server tests on a multi-thread Tokio runtime
instead of the default single-thread test runtime
- stop relying on wiremock teardown expectations for `/responses` and
explicitly wait for the expected request count after the turn completes

## Why this fixes the flake
- this failure was showing up on Windows ARM as a late wiremock panic
saying the mock server saw zero `/responses` calls, but the real issue
was that the test could stall around app-server startup and only fail
during teardown
- moving these tests to the same multi-thread runtime used by the other
collaboration-mode app-server tests removes that startup scheduling race
- asserting the `/responses` count directly makes the test
deterministic: we now wait for the real POST instead of depending on a
drop-time verification that can hide the underlying timing issue

## Scope
- test-only change; no production logic changes
2026-03-09 10:24:18 -07:00
Ahmed Ibrahim
5d9db0f995 Stabilize PTY Python REPL test (#13883)
## What changed
- The PTY Python REPL test now starts Python with a startup marker
already embedded in argv.
- The test waits for that marker in PTY output before making assertions.

## Why this fixes the flake
- The old version tried to probe the live REPL almost immediately after
spawn.
- That races PTY initialization, Python startup, and prompt buffering,
all of which vary across platforms and CI load.
- By having the child process emit a known marker as part of its own
startup path, the test gets a deterministic synchronization point that
comes from the process under test rather than from guessed timing.

## Scope
- Test-only change.
2026-03-09 10:08:36 -07:00
Ahmed Ibrahim
6052558a01 Stabilize RMCP pid file cleanup test (#13881)
## What changed
- The pid-file cleanup test now keeps polling when the pid file exists
but is still empty.
- Assertions only proceed once the wrapper has actually written the
child pid.

## Why this fixes the flake
- File creation and pid writing are not atomic as one logical action
from the test’s point of view.
- The previous test sometimes won the race and read the file in the tiny
window after creation but before the pid bytes were flushed.
- Treating “empty file” as “not ready yet” synchronizes the test on the
real event we need: the wrapper has finished publishing the child pid.

## Scope
- Test-only change.
2026-03-09 10:01:34 -07:00
Ahmed Ibrahim
615ed0e437 Stabilize zsh fork app-server tests (#13872)
## What changed
- `turn_start_shell_zsh_fork_executes_command_v2` now keeps the shell
command alive with a file marker until the interrupt arrives instead of
using a command that can finish too quickly.
-
`turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2`
now waits for `turn/completed` before sending a fallback interrupt and
accepts the real terminal outcomes observed across platforms.

## Why this fixes the flake
- The original tests assumed a narrow ordering window: the child command
would still be running when the interrupt happened, and completion would
always arrive in one specific order.
- In CI, especially across different shells and runner speeds, those
assumptions break. Sometimes the child finishes before the interrupt;
sometimes the protocol completes while the fallback path is still arming
itself.
- Holding the command open until the interrupt and waiting for the
explicit protocol completion event makes the tests synchronize on the
behavior under test instead of on wall-clock timing.

## Scope
- Test-only change.
2026-03-09 09:38:16 -07:00
Ahmed Ibrahim
3f1280ce1c Reduce app-server test timeout pressure (#13884)
## What changed
- The auth/account/fuzzy-file-search test configs disable unrelated
`shell_snapshot` setup.
- The fuzzy-file-search fixture set was reduced so the stop-updates test
does less incidental work before reaching the assertion.

## Why this fixes the flake
- These failures were caused by cumulative timeout pressure, not by a
missing product-level delay.
- The old tests were paying for shell snapshot initialization and extra
fixture volume that were not part of the behavior being validated.
- Removing that incidental work keeps the same coverage but shortens the
critical path enough that the tests finish comfortably inside the
existing timeout budget, which is the right fix versus simply extending
the timeout.

## Scope
- Test-only change.
2026-03-09 09:37:41 -07:00
Charley Cunningham
f23fcd6ced guardian initial feedback / tweaks (#13897)
## Summary
- remove the remaining model-visible guardian-specific `on-request`
prompt additions so enabling the feature does not change the main
approval-policy instructions
- neutralize user-facing guardian wording to talk about automatic
approval review / approval requests rather than a second reviewer or
only sandbox escalations
- tighten guardian retry-context handling so agent-authored
`justification` stays in the structured action JSON and is not also
injected as raw retry context
- simplify guardian review plumbing in core by deleting dead
prompt-append paths and trimming some request/transcript setup code

## Notable Changes
- delete the dead `permissions/approval_policy/guardian.md` append path
and stop threading `guardian_approval_enabled` through model-facing
developer-instruction builders
- rename the experimental feature copy to `Automatic approval review`
and update the `/experimental` snapshot text accordingly
- make approval-review status strings generic across shell, patch,
network, and MCP review types
- forward real sandbox/network retry reasons for shell and unified-exec
guardian review, but do not pass agent-authored justification as raw
retry context
- simplify `guardian.rs` by removing the one-field request wrapper,
deduping reasoning-effort selection, and cleaning up transcript entry
collection

## Testing
- `just fmt`
- full validation left to CI

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-09 09:25:24 -07:00
Ahmed Ibrahim
2bc3e52a91 Stabilize app list update ordering test (#14052)
## Summary
- make
`list_apps_waits_for_accessible_data_before_emitting_directory_updates`
accept the two valid notification paths the server can emit
- keep rejecting the real bug this test is meant to catch: a
directory-only `app/list/updated` notification before accessible app
data is available

## Why this fixes the flake
The old test used a fixed `150ms` silence window and assumed the first
notification after that window had to be the fully merged final update.
In CI, scheduling occasionally lets accessible app data arrive before
directory data, so the first valid notification can be an
accessible-only interim update. That made the test fail even though the
server behavior was correct.

This change makes the test deterministic by reading notifications until
the final merged payload arrives. Any interim update is only accepted if
it contains accessible apps only; if the server ever emits inaccessible
directory data before accessible data is ready, the test still fails
immediately.

## Change type
- test-only; no production app-list logic changes
2026-03-09 00:16:13 -07:00
Dylan Hurd
06f82c123c feat(tui) render request_permissions calls (#14004)
## Summary
Adds support for tui rendering of request_permission calls

<img width="724" height="245" alt="Screenshot 2026-03-08 at 9 04 07 PM"
src="https://github.com/user-attachments/assets/e1997825-a496-4bfb-bbda-43d0006460a5"
/>


## Testing
- [x] Added snapshot test
2026-03-09 04:24:04 +00:00
Dylan Hurd
05332b0e96 fix(bazel) add missing app-server-client BUILD.bazel (#14027)
## Summary
Adds missing BUILD.bazel file for the new app-server-client crate

## Testing
- [x] 🤞 that this gets bazel ci to pass
2026-03-09 03:42:54 +00:00
Jack Mousseau
e6b93841c5 Add request permissions tool (#13092)
Adds a built-in `request_permissions` tool and wires it through the
Codex core, protocol, and app-server layers so a running turn can ask
the client for additional permissions instead of relying on a static
session policy.

The new flow emits a `RequestPermissions` event from core, tracks the
pending request by call ID, forwards it through app-server v2 as an
`item/permissions/requestApproval` request, and resumes the tool call
once the client returns an approved subset of the requested permission
profile.
2026-03-08 20:23:06 -07:00
Charley Cunningham
4ad3b59de3 tui: clarify pending steer follow-ups (#13841)
## Summary
- split the pending input preview into labeled pending-steer and queued
follow-up sections
- explain that pending steers submit after the next tool call and that
Esc can interrupt and send them immediately
- treat Esc as an interrupt-plus-resubmit path when pending steers
exist, with updated TUI snapshots and tests

Queues and steers:
<img width="1038" height="263" alt="Screenshot 2026-03-07 at 10 17
17 PM"
src="https://github.com/user-attachments/assets/4ef433ef-27a3-4b7c-ad69-2046f6eb89e6"
/>

After pressing Esc:
<img width="1046" height="320" alt="Screenshot 2026-03-07 at 10 17
21 PM"
src="https://github.com/user-attachments/assets/0f4d89e0-b6b9-486a-9f04-b6021f169ba7"
/>

## Codex author
`codex resume 019cc6f4-2cca-7803-b717-8264526dbd97`

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-08 20:13:21 -07:00
Dylan Hurd
f41b1638c9 fix(core) patch otel test (#14014)
## Summary
This test was missing the turn completion event in the responses stream,
so it was hanging. This PR fixes the issue

## Testing
- [x] This does update the test
2026-03-08 19:06:30 -07:00
Celia Chen
340f9c9ecb app-server: include experimental skill metadata in exec approval requests (#13929)
## Summary

This change surfaces skill metadata on command approval requests so
app-server clients can tell when an approval came from a skill script
and identify the originating `SKILL.md`.

- add `skill_metadata` to exec approval events in the shared protocol
- thread skill metadata through core shell escalation and delegated
approval handling for skill-triggered approvals
- expose the field in app-server v2 as experimental `skillMetadata`
- regenerate the JSON/TypeScript schemas and cover the new field in
protocol, transport, core, and TUI tests

## Why

Skill-triggered approvals already carry skill context inside core, but
app-server clients could not see which skill caused the prompt. Sending
the skill metadata with the approval request makes it possible for
clients to present better approval UX and connect the prompt back to the
relevant skill definition.


## example event in app-server-v2
verified that we see this event when experimental api is on:
```
< {
<   "id": 11,
<   "method": "item/commandExecution/requestApproval",
<   "params": {
<     "additionalPermissions": {
<       "fileSystem": null,
<       "macos": {
<         "accessibility": false,
<         "automations": {
<           "bundle_ids": [
<             "com.apple.Notes"
<           ]
<         },
<         "calendar": false,
<         "preferences": "read_only"
<       },
<       "network": null
<     },
<     "approvalId": "25d600ee-5a3c-4746-8d17-e2e61fb4c563",
<     "availableDecisions": [
<       "accept",
<       "acceptForSession",
<       "cancel"
<     ],
<     "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
<     "commandActions": [
<       {
<         "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
<         "type": "unknown"
<       }
<     ],
<     "cwd": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes",
<     "itemId": "call_jZp3xFpNg4D8iKAD49cvEvZy",
<     "skillMetadata": {
<       "pathToSkillsMd": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/SKILL.md"
<     },
<     "threadId": "019ccc10-b7d3-7ff2-84fe-3a75e7681e69",
<     "turnId": "019ccc10-b848-76f1-81b3-4a1fa225493f"
<   }
< }`
```

& verified that this is the event when experimental api is off:
```
< {
<   "id": 13,
<   "method": "item/commandExecution/requestApproval",
<   "params": {
<     "approvalId": "5fbbf776-261b-4cf8-899b-c125b547f2c0",
<     "availableDecisions": [
<       "accept",
<       "acceptForSession",
<       "cancel"
<     ],
<     "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
<     "commandActions": [
<       {
<         "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
<         "type": "unknown"
<       }
<     ],
<     "cwd": "/Users/celia/code/codex/codex-rs",
<     "itemId": "call_OV2DHzTgYcbYtWaTTBWlocOt",
<     "threadId": "019ccc16-2a2b-7be1-8500-e00d45b892d4",
<     "turnId": "019ccc16-2a8e-7961-98ec-649600e7d06a"
<   }
< }
```
2026-03-08 18:07:46 -07:00
Eric Traut
da3689f0ef Add in-process app server and wire up exec to use it (#14005)
This is a subset of PR #13636. See that PR for a full overview of the
architectural change.

This PR implements the in-process app server and modifies the
non-interactive "exec" entry point to use the app server.

---------

Co-authored-by: Felipe Coury <felipe.coury@gmail.com>
2026-03-08 18:43:55 -06:00
Matthew Zeng
a684a36091 [app-server] Support hot-reload user config when batch writing config. (#13839)
- [x] Support hot-reload user config when batch writing config.
2026-03-08 17:38:01 -07:00
Ahmed Ibrahim
1f150eda8b Stabilize shell serialization tests (#13877)
## What changed
- The duration-recording fixture sleep was reduced from a large
artificial delay to `0.2s`, and the assertion floor was lowered to
`0.1s`.
- The shell tool fixtures now force `login = false` so they do not
invoke login-shell startup paths.

## Why this fixes the flake
- The old tests were paying for two kinds of noise that had nothing to
do with the feature being validated: oversized sleep time and variable
shell initialization cost.
- Login shells can pick up runner-specific startup files and incur
inconsistent startup latency.
- The test only needs to prove that we record a nontrivial duration and
preserve shell output. A shorter fixture delay plus a non-login shell
keeps that coverage while removing runner-dependent wall-clock variance.

## Scope
- Test-only change.
2026-03-08 13:37:41 -07:00
Charley Cunningham
7ba1fccfc1 fix(ci): restore guardian coverage and bazel unit tests (#13912)
## Summary
- restore the guardian review request snapshot test and its tracked
snapshot after it was dropped from `main`
- make Bazel Rust unit-test wrappers resolve runfiles correctly on
manifest-only platforms like macOS and point Insta at the real workspace
root
- harden the shell-escalation socket-closure assertion so the musl Bazel
test no longer depends on fd reuse behavior

## Verification
- cargo test -p codex-core
guardian_review_request_layout_matches_model_visible_request_snapshot
- cargo test -p codex-shell-escalation
- bazel test //codex-rs/exec:exec-unit-tests
//codex-rs/shell-escalation:shell-escalation-unit-tests

Supersedes #13894.

---------

Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
Co-authored-by: viyatb-oai <viyatb@openai.com>
Co-authored-by: Codex <noreply@openai.com>
2026-03-08 12:05:19 -07:00
Eric Traut
a30edb6c17 Fix inverted Windows PTY TerminateProcess handling (#13989)
Addresses #13945

The vendored WezTerm ConPTY backend in
`codex-rs/utils/pty/src/win/mod.rs` treated `TerminateProcess` return
values backwards: nonzero success was handled as failure, and `0`
failure was handled as success.

This is likely causing a number of bugs reported against Codex running
on Windows native where processes are not cleaned up.
2026-03-08 11:52:16 -06:00
Michael Bolin
dcc4d7b634 linux-sandbox: honor split filesystem policies in bwrap (#13453)
## Why

After `#13449`, the Linux helper could receive split filesystem and
network policies, but the bubblewrap mount builder still reconstructed
filesystem access from the legacy `SandboxPolicy`.

That loses explicit unreadable carveouts under writable roots, and it
also mishandles `Root` read access paired with explicit deny carveouts.
In those cases bubblewrap could still expose paths that the split
filesystem policy intentionally blocked.

## What changed

- switched bubblewrap mount generation to consume
`FileSystemSandboxPolicy` directly at the implementation boundary;
legacy `SandboxPolicy` configs still flow through the existing
`FileSystemSandboxPolicy::from(&sandbox_policy)` bridge before reaching
bwrap
- kept the Linux helper and preflight path on the split filesystem
policy all the way into bwrap
- re-applied explicit unreadable carveouts after readable and writable
mounts so blocked subpaths still win under bubblewrap
- masked denied directories with `--tmpfs` plus `--remount-ro` and
denied files with `--ro-bind-data`, preserving the backing fd until exec
- added comments in the unreadable-root masking block to explain why the
mount order and directory/file split are intentional
- updated Linux helper call sites and tests for the split-policy bwrap
path

## Verification

- added protocol coverage for root carveouts staying scoped
- added core coverage that root-write plus deny carveouts still requires
a platform sandbox
- added bwrap unit coverage for reapplying blocked carveouts after
writable binds
- added Linux integration coverage for explicit split-policy carveouts
under bubblewrap
- validated the final branch state with `cargo test -p
codex-linux-sandbox`, `cargo clippy -p codex-linux-sandbox --all-targets
-- -D warnings`, and the PR CI reruns

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13453).
* __->__ #13453
* #13452
* #13451
* #13449
* #13448
* #13445
* #13440
* #13439

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-03-07 23:46:52 -08:00
Ahmed Ibrahim
dc19e78962 Stabilize abort task follow-up handling (#13874)
- production logic plus tests; cancel running tasks before clearing
pending turn state
- suppress follow-up model requests after cancellation and assert on
stabilized request counts instead of fixed sleeps
2026-03-07 22:56:00 -08:00
Michael Bolin
3b5fe5ca35 protocol: keep root carveouts sandboxed (#13452)
## Why

A restricted filesystem policy that grants `:root` read or write access
but also carries explicit deny entries should still behave like scoped
access with carveouts, not like unrestricted disk access.

Without that distinction, later platform backends cannot preserve
blocked subpaths under root-level permissions because the protocol layer
reports the policy as fully unrestricted.

## What changed

- taught `FileSystemSandboxPolicy` to treat root access plus explicit
deny entries as scoped access rather than full-disk access
- derived readable and writable roots from the filesystem root when root
access is combined with carveouts, while preserving the denied paths as
read-only subpaths
- added protocol coverage for root-write policies with carveouts and a
core sandboxing regression so those policies still require platform
sandboxing

## Verification

- added protocol coverage in `protocol/src/permissions.rs` and
`protocol/src/protocol.rs` for root access with explicit carveouts
- added platform-sandbox regression coverage in
`core/src/sandboxing/mod.rs`
- verified the current PR state with `just clippy`




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13452).
* #13453
* __->__ #13452
* #13451
* #13449
* #13448
* #13445
* #13440
* #13439

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-03-07 21:15:47 -08:00
Michael Bolin
46b8d127cf sandboxing: preserve denied paths when widening permissions (#13451)
## Why

After the split-policy plumbing landed, additional-permissions widening
still rebuilt filesystem access through the legacy projection in a few
places.

That can erase explicit deny entries and make the runtime treat a policy
as fully writable even when it still has blocked subpaths, which in turn
can skip the platform sandbox when it is still needed.

## What changed

- preserved explicit deny entries when merging additional read and write
permissions into `FileSystemSandboxPolicy`
- switched platform-sandbox selection to rely on
`FileSystemSandboxPolicy::has_full_disk_write_access()` instead of ad
hoc root-write checks
- kept the widened policy path in `core/src/exec.rs` and
`core/src/sandboxing/mod.rs` aligned so denied subpaths survive both
policy merging and sandbox selection
- added regression coverage for root-write policies that still carry
carveouts

## Verification

- added regression coverage in `core/src/sandboxing/mod.rs` showing that
root write plus carveouts still requires the platform sandbox
- verified the current PR state with `just clippy`




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13451).
* #13453
* #13452
* __->__ #13451
* #13449
* #13448
* #13445
* #13440
* #13439

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-03-08 04:29:35 +00:00
Michael Bolin
07a30da3fb linux-sandbox: plumb split sandbox policies through helper (#13449)
## Why

The Linux sandbox helper still only accepted the legacy `SandboxPolicy`
payload.

That meant the runtime could compute split filesystem and network
policies, but the helper would immediately collapse them back to the
compatibility projection before applying seccomp or staging the
bubblewrap inner command.

## What changed

- added hidden `--file-system-sandbox-policy` and
`--network-sandbox-policy` flags alongside the legacy `--sandbox-policy`
flag so the helper can migrate incrementally
- updated the core-side Landlock wrapper to pass the split policies
explicitly when launching `codex-linux-sandbox`
- added helper-side resolution logic that accepts either the legacy
policy alone or a complete split-policy pair and normalizes that into
one effective configuration
- switched Linux helper network decisions to use `NetworkSandboxPolicy`
directly
- added `FromStr` support for the split policy types so the helper can
parse them from CLI JSON

## Verification

- added helper coverage in `linux-sandbox/src/linux_run_main_tests.rs`
for split-policy flags and policy resolution
- added CLI argument coverage in `core/src/landlock.rs`
- verified the current PR state with `just clippy`




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13449).
* #13453
* #13452
* #13451
* __->__ #13449
* #13448
* #13445
* #13440
* #13439

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-03-07 19:40:10 -08:00
Matthew Zeng
a4a9536fd7 [elicitations] Support always allow option for mcp tool calls. (#13807)
- [x] Support always allow option for mcp tool calls, writes to
config.toml.
- [x] Fix config hot-reload after starting a new thread for TUI.
2026-03-08 01:46:40 +00:00
sayan-oai
590cfa6176 chore: use @plugin instead of $plugin for plaintext mentions (#13921)
change plaintext plugin-mentions from `$plugin` to `@plugin`, ensure TUI
can correctly decode these from history.

tested locally, added/updated tests.
2026-03-08 01:36:39 +00:00
Michael Bolin
bf5c2f48a5 seatbelt: honor split filesystem sandbox policies (#13448)
## Why

After `#13440` and `#13445`, macOS Seatbelt policy generation was still
deriving filesystem and network behavior from the legacy `SandboxPolicy`
projection.

That projection loses explicit unreadable carveouts and conflates split
network decisions, so the generated Seatbelt policy could still be wider
than the split policy that Codex had already computed.

## What changed

- added Seatbelt entrypoints that accept `FileSystemSandboxPolicy` and
`NetworkSandboxPolicy` directly
- built read and write policy stanzas from access roots plus excluded
subpaths so explicit unreadable carveouts survive into the generated
Seatbelt policy
- switched network policy generation to consult `NetworkSandboxPolicy`
directly
- failed closed when managed-network or proxy-constrained sessions do
not yield usable loopback proxy endpoints
- updated the macOS callers and test helpers that now need to carry the
split policies explicitly

## Verification

- added regression coverage in `core/src/seatbelt.rs` for unreadable
carveouts under both full-disk and scoped-readable policies
- verified the current PR state with `just clippy`




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13448).
* #13453
* #13452
* #13451
* #13449
* __->__ #13448
* #13445
* #13440
* #13439

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-03-08 00:35:19 +00:00
Eric Traut
e8d7ede83c Fix TUI context window display before first TokenCount (#13896)
The TUI was showing the raw configured `model_context_window` until the
first
`TokenCount` event arrived, even though core had already emitted the
effective
runtime window on `TurnStarted`. This made the footer, status-line
context
window, and `/status` output briefly inconsistent for models/configs
where the
effective window differs from the configured value, such as the
`gpt-5.4`
1,000,000-token override reported in #13623.

Update the TUI to cache `TurnStarted.model_context_window` immediately
so
pre-token-count displays use the runtime effective window, and add
regression
coverage for the startup path.

---------

Co-authored-by: Charles Cunningham <ccunningham@openai.com>
Co-authored-by: Codex <noreply@openai.com>
2026-03-07 17:01:47 -07:00
Dylan Hurd
92f7541624 fix(ci) fix guardian ci (#13911)
## Summary
#13910 was merged with some unused imports, let's fix this

## Testing
- [x] Let's make sure CI is green

---------

Co-authored-by: Charles Cunningham <ccunningham@openai.com>
Co-authored-by: Codex <noreply@openai.com>
2026-03-07 23:34:56 +00:00
Dylan Hurd
1c888709b5 fix(core) rm guardian snapshot test (#13910)
## Summary
This test is good, but flakey and we have to figure out some bazel build
issues. Let's get CI back go green and then land a stable version!

## Test Summary
- [x] CI Passes
2026-03-07 14:28:54 -08:00
897 changed files with 108857 additions and 58614 deletions

8
.github/blob-size-allowlist.txt vendored Normal file
View File

@@ -0,0 +1,8 @@
# Paths are matched exactly, relative to the repository root.
# Keep this list short and limited to intentional large checked-in assets.
.github/codex-cli-splash.png
MODULE.bazel.lock
codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
codex-rs/tui/tests/fixtures/oss-story.jsonl

29
.github/workflows/blob-size-policy.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: blob-size-policy
on:
pull_request: {}
jobs:
check:
name: Blob size policy
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Determine PR comparison range
id: range
shell: bash
run: |
set -euo pipefail
echo "base=$(git rev-parse HEAD^1)" >> "$GITHUB_OUTPUT"
echo "head=$(git rev-parse HEAD^2)" >> "$GITHUB_OUTPUT"
- name: Check changed blob sizes
run: |
python3 scripts/check_blob_size.py \
--base "${{ steps.range.outputs.base }}" \
--head "${{ steps.range.outputs.head }}" \
--max-bytes 512000 \
--allowlist .github/blob-size-allowlist.txt

View File

@@ -7,7 +7,9 @@ on:
jobs:
sdks:
runs-on: ubuntu-latest
runs-on:
group: codex-runners
labels: codex-linux-x64
timeout-minutes: 10
steps:
- name: Checkout repository

View File

@@ -19,7 +19,22 @@ In the codex-rs folder where the rust code lives:
repo root to refresh `MODULE.bazel.lock`, and include that lockfile update in the same change.
- After dependency changes, run `just bazel-lock-check` from the repo root so lockfile drift is caught
locally before CI.
- Bazel does not automatically make source-tree files available to compile-time Rust file access. If
you add `include_str!`, `include_bytes!`, `sqlx::migrate!`, or similar build-time file or
directory reads, update the crate's `BUILD.bazel` (`compile_data`, `build_script_data`, or test
data) or Bazel may fail even when Cargo passes.
- Do not create small helper methods that are referenced only once.
- Avoid large modules:
- Prefer adding new modules instead of growing existing ones.
- Target Rust modules under 500 LoC, excluding tests.
- If a file exceeds roughly 800 LoC, add new functionality in a new module instead of extending
the existing file unless there is a strong documented reason not to.
- This rule applies especially to high-touch files that already attract unrelated changes, such
as `codex-rs/tui/src/app.rs`, `codex-rs/tui/src/bottom_pane/chat_composer.rs`,
`codex-rs/tui/src/bottom_pane/footer.rs`, `codex-rs/tui/src/chatwidget.rs`,
`codex-rs/tui/src/bottom_pane/mod.rs`, and similarly central orchestration modules.
- When extracting code from a large module, move the related tests and module/type docs toward
the new implementation so the invariants stay close to the code that owns them.
Run `just fmt` (in `codex-rs` directory) automatically after you have finished making Rust code changes; do not ask for approval to run it. Additionally, run the tests:

View File

@@ -28,4 +28,8 @@ alias(
actual = "@rbe_platform",
)
exports_files(["AGENTS.md"])
exports_files([
"AGENTS.md",
"workspace_root_test_launcher.bat.tpl",
"workspace_root_test_launcher.sh.tpl",
])

View File

@@ -2,6 +2,12 @@
# Do not increase, fix your test instead
slow-timeout = { period = "15s", terminate-after = 2 }
[test-groups.app_server_protocol_codegen]
max-threads = 1
[test-groups.app_server_integration]
max-threads = 1
[[profile.default.overrides]]
# Do not add new tests here
@@ -11,3 +17,13 @@ slow-timeout = { period = "1m", terminate-after = 4 }
[[profile.default.overrides]]
filter = 'test(approval_matrix_covers_all_modes)'
slow-timeout = { period = "30s", terminate-after = 2 }
[[profile.default.overrides]]
filter = 'package(codex-app-server-protocol) & (test(typescript_schema_fixtures_match_generated) | test(json_schema_fixtures_match_generated) | test(generate_ts_with_experimental_api_retains_experimental_entries) | test(generated_ts_optional_nullable_fields_only_in_params) | test(generate_json_filters_experimental_fields_and_methods))'
test-group = 'app_server_protocol_codegen'
[[profile.default.overrides]]
# These integration tests spawn a fresh app-server subprocess per case.
# Keep the library unit tests parallel.
filter = 'package(codex-app-server) & kind(test)'
test-group = 'app_server_integration'

59
codex-rs/Cargo.lock generated
View File

@@ -827,6 +827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
dependencies = [
"axum-core",
"base64 0.22.1",
"bytes",
"form_urlencoded",
"futures-util",
@@ -845,8 +846,10 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sha1",
"sync_wrapper",
"tokio",
"tokio-tungstenite",
"tower",
"tower-layer",
"tower-service",
@@ -1439,8 +1442,11 @@ dependencies = [
"codex-utils-pty",
"core_test_support",
"futures",
"opentelemetry",
"opentelemetry_sdk",
"owo-colors",
"pretty_assertions",
"reqwest",
"rmcp",
"serde",
"serde_json",
@@ -1453,11 +1459,30 @@ dependencies = [
"tokio-util",
"toml 0.9.11+spec-1.1.0",
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
"uuid",
"wiremock",
]
[[package]]
name = "codex-app-server-client"
version = "0.0.0"
dependencies = [
"codex-app-server",
"codex-app-server-protocol",
"codex-arg0",
"codex-core",
"codex-feedback",
"codex-protocol",
"pretty_assertions",
"serde",
"serde_json",
"tokio",
"toml 0.9.11+spec-1.1.0",
"tracing",
]
[[package]]
name = "codex-app-server-protocol"
version = "0.0.0"
@@ -1571,6 +1596,7 @@ version = "0.0.0"
dependencies = [
"anyhow",
"codex-backend-openapi-models",
"codex-client",
"codex-core",
"codex-protocol",
"pretty_assertions",
@@ -1594,6 +1620,7 @@ version = "0.0.0"
dependencies = [
"anyhow",
"clap",
"codex-connectors",
"codex-core",
"codex-git",
"codex-utils-cargo-bin",
@@ -1603,7 +1630,6 @@ dependencies = [
"serde_json",
"tempfile",
"tokio",
"urlencoding",
]
[[package]]
@@ -1658,15 +1684,22 @@ version = "0.0.0"
dependencies = [
"async-trait",
"bytes",
"codex-utils-cargo-bin",
"codex-utils-rustls-provider",
"eventsource-stream",
"futures",
"http 1.4.0",
"opentelemetry",
"opentelemetry_sdk",
"pretty_assertions",
"rand 0.9.2",
"reqwest",
"rustls",
"rustls-native-certs",
"rustls-pki-types",
"serde",
"serde_json",
"tempfile",
"thiserror 2.0.18",
"tokio",
"tracing",
@@ -1707,6 +1740,7 @@ dependencies = [
"base64 0.22.1",
"chrono",
"clap",
"codex-client",
"codex-cloud-tasks-client",
"codex-core",
"codex-login",
@@ -1765,6 +1799,18 @@ dependencies = [
"tracing",
]
[[package]]
name = "codex-connectors"
version = "0.0.0"
dependencies = [
"anyhow",
"codex-app-server-protocol",
"pretty_assertions",
"serde",
"tokio",
"urlencoding",
]
[[package]]
name = "codex-core"
version = "0.0.0"
@@ -1789,6 +1835,7 @@ dependencies = [
"codex-async-utils",
"codex-client",
"codex-config",
"codex-connectors",
"codex-execpolicy",
"codex-file-search",
"codex-git",
@@ -1899,10 +1946,13 @@ dependencies = [
"anyhow",
"assert_cmd",
"clap",
"codex-app-server-client",
"codex-app-server-protocol",
"codex-apply-patch",
"codex-arg0",
"codex-cloud-requirements",
"codex-core",
"codex-feedback",
"codex-otel",
"codex-protocol",
"codex-utils-absolute-path",
@@ -2030,9 +2080,12 @@ version = "0.0.0"
dependencies = [
"anyhow",
"chrono",
"codex-config",
"codex-protocol",
"futures",
"pretty_assertions",
"regex",
"schemars 0.8.22",
"serde",
"serde_json",
"tempfile",
@@ -2089,6 +2142,7 @@ dependencies = [
"base64 0.22.1",
"chrono",
"codex-app-server-protocol",
"codex-client",
"codex-core",
"core_test_support",
"pretty_assertions",
@@ -2291,6 +2345,7 @@ version = "0.0.0"
dependencies = [
"anyhow",
"axum",
"codex-client",
"codex-keyring-store",
"codex-protocol",
"codex-utils-cargo-bin",
@@ -2414,7 +2469,6 @@ name = "codex-stdio-to-uds"
version = "0.0.0"
dependencies = [
"anyhow",
"assert_cmd",
"codex-utils-cargo-bin",
"pretty_assertions",
"tempfile",
@@ -2446,6 +2500,7 @@ dependencies = [
"codex-backend-client",
"codex-chatgpt",
"codex-cli",
"codex-client",
"codex-cloud-requirements",
"codex-core",
"codex-feedback",

View File

@@ -4,6 +4,7 @@ members = [
"ansi-escape",
"async-utils",
"app-server",
"app-server-client",
"app-server-protocol",
"app-server-test-client",
"debug-client",
@@ -15,6 +16,7 @@ members = [
"cloud-tasks",
"cloud-tasks-client",
"cli",
"connectors",
"config",
"shell-command",
"shell-escalation",
@@ -86,6 +88,7 @@ codex-api = { path = "codex-api" }
codex-artifacts = { path = "artifacts" }
codex-package-manager = { path = "package-manager" }
codex-app-server = { path = "app-server" }
codex-app-server-client = { path = "app-server-client" }
codex-app-server-protocol = { path = "app-server-protocol" }
codex-app-server-test-client = { path = "app-server-test-client" }
codex-apply-patch = { path = "apply-patch" }
@@ -96,6 +99,7 @@ codex-chatgpt = { path = "chatgpt" }
codex-cli = { path = "cli" }
codex-client = { path = "codex-client" }
codex-cloud-requirements = { path = "cloud-requirements" }
codex-connectors = { path = "connectors" }
codex-config = { path = "config" }
codex-core = { path = "core" }
codex-exec = { path = "exec" }
@@ -236,6 +240,8 @@ rustls = { version = "0.23", default-features = false, features = [
"ring",
"std",
] }
rustls-native-certs = "0.8.3"
rustls-pki-types = "1.14.0"
schemars = "0.8.22"
seccompiler = "0.5.0"
semver = "1.0"

View File

@@ -0,0 +1,6 @@
load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "app-server-client",
crate_name = "codex_app_server_client",
)

View File

@@ -0,0 +1,30 @@
[package]
name = "codex-app-server-client"
version.workspace = true
edition.workspace = true
license.workspace = true
[lib]
name = "codex_app_server_client"
path = "src/lib.rs"
[lints]
workspace = true
[dependencies]
codex-app-server = { workspace = true }
codex-app-server-protocol = { workspace = true }
codex-arg0 = { workspace = true }
codex-core = { workspace = true }
codex-feedback = { workspace = true }
codex-protocol = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["sync", "time", "rt"] }
toml = { workspace = true }
tracing = { workspace = true }
[dev-dependencies]
pretty_assertions = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }

View File

@@ -0,0 +1,67 @@
# codex-app-server-client
Shared in-process app-server client used by conversational CLI surfaces:
- `codex-exec`
- `codex-tui`
## Purpose
This crate centralizes startup and lifecycle management for an in-process
`codex-app-server` runtime, so CLI clients do not need to duplicate:
- app-server bootstrap and initialize handshake
- in-memory request/event transport wiring
- lifecycle orchestration around caller-provided startup identity
- graceful shutdown behavior
## Startup identity
Callers pass both the app-server `SessionSource` and the initialize
`client_info.name` explicitly when starting the facade.
That keeps thread metadata (for example in `thread/list` and `thread/read`)
aligned with the originating runtime without baking TUI/exec-specific policy
into the shared client layer.
## Transport model
The in-process path uses typed channels:
- client -> server: `ClientRequest` / `ClientNotification`
- server -> client: `InProcessServerEvent`
- `ServerRequest`
- `ServerNotification`
- `LegacyNotification`
JSON serialization is still used at external transport boundaries
(stdio/websocket), but the in-process hot path is typed.
Typed requests still receive app-server responses through the JSON-RPC
result envelope internally. That is intentional: the in-process path is
meant to preserve app-server semantics while removing the process
boundary, not to introduce a second response contract.
## Bootstrap behavior
The client facade starts an already-initialized in-process runtime, but
thread bootstrap still follows normal app-server flow:
- caller sends `thread/start` or `thread/resume`
- app-server returns the immediate typed response
- richer session metadata may arrive later as a `SessionConfigured`
legacy event
Surfaces such as TUI and exec may therefore need a short bootstrap
phase where they reconcile startup response data with later events.
## Backpressure and shutdown
- Queues are bounded and use `DEFAULT_IN_PROCESS_CHANNEL_CAPACITY` by default.
- Full queues return explicit overload behavior instead of unbounded growth.
- `shutdown()` performs a bounded graceful shutdown and then aborts if timeout
is exceeded.
If the client falls behind on event consumption, the worker emits
`InProcessServerEvent::Lagged` and may reject pending server requests so
approval flows do not hang indefinitely behind a saturated queue.

View File

@@ -0,0 +1,801 @@
//! Shared in-process app-server client facade for CLI surfaces.
//!
//! This crate wraps [`codex_app_server::in_process`] behind a single async API
//! used by surfaces like TUI and exec. It centralizes:
//!
//! - Runtime startup and initialize-capabilities handshake.
//! - Typed caller-provided startup identity (`SessionSource` + client name).
//! - Typed and raw request/notification dispatch.
//! - Server request resolution and rejection.
//! - Event consumption with backpressure signaling ([`InProcessServerEvent::Lagged`]).
//! - Bounded graceful shutdown with abort fallback.
//!
//! The facade interposes a worker task between the caller and the underlying
//! [`InProcessClientHandle`](codex_app_server::in_process::InProcessClientHandle),
//! bridging async `mpsc` channels on both sides. Queues are bounded so overload
//! surfaces as channel-full errors rather than unbounded memory growth.
use std::error::Error;
use std::fmt;
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::time::Duration;
pub use codex_app_server::in_process::DEFAULT_IN_PROCESS_CHANNEL_CAPACITY;
pub use codex_app_server::in_process::InProcessServerEvent;
use codex_app_server::in_process::InProcessStartArgs;
use codex_app_server_protocol::ClientInfo;
use codex_app_server_protocol::ClientNotification;
use codex_app_server_protocol::ClientRequest;
use codex_app_server_protocol::ConfigWarningNotification;
use codex_app_server_protocol::InitializeCapabilities;
use codex_app_server_protocol::InitializeParams;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::Result as JsonRpcResult;
use codex_arg0::Arg0DispatchPaths;
use codex_core::config::Config;
use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::config_loader::LoaderOverrides;
use codex_feedback::CodexFeedback;
use codex_protocol::protocol::SessionSource;
use serde::de::DeserializeOwned;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio::time::timeout;
use toml::Value as TomlValue;
use tracing::warn;
const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
/// Raw app-server request result for typed in-process requests.
///
/// Even on the in-process path, successful responses still travel back through
/// the same JSON-RPC result envelope used by socket/stdio transports because
/// `MessageProcessor` continues to produce that shape internally.
pub type RequestResult = std::result::Result<JsonRpcResult, JSONRPCErrorError>;
fn event_requires_delivery(event: &InProcessServerEvent) -> bool {
// These terminal events drive surface shutdown/completion state. Dropping
// them under backpressure can leave exec/TUI waiting forever even though
// the underlying turn has already ended.
match event {
InProcessServerEvent::ServerNotification(
codex_app_server_protocol::ServerNotification::TurnCompleted(_),
) => true,
InProcessServerEvent::LegacyNotification(notification) => matches!(
notification
.method
.strip_prefix("codex/event/")
.unwrap_or(&notification.method),
"task_complete" | "turn_aborted" | "shutdown_complete"
),
_ => false,
}
}
/// Layered error for [`InProcessAppServerClient::request_typed`].
///
/// This keeps transport failures, server-side JSON-RPC failures, and response
/// decode failures distinct so callers can decide whether to retry, surface a
/// server error, or treat the response as an internal request/response mismatch.
#[derive(Debug)]
pub enum TypedRequestError {
Transport {
method: String,
source: IoError,
},
Server {
method: String,
source: JSONRPCErrorError,
},
Deserialize {
method: String,
source: serde_json::Error,
},
}
impl fmt::Display for TypedRequestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Transport { method, source } => {
write!(f, "{method} transport error: {source}")
}
Self::Server { method, source } => {
write!(f, "{method} failed: {}", source.message)
}
Self::Deserialize { method, source } => {
write!(f, "{method} response decode error: {source}")
}
}
}
}
impl Error for TypedRequestError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Transport { source, .. } => Some(source),
Self::Server { .. } => None,
Self::Deserialize { source, .. } => Some(source),
}
}
}
#[derive(Clone)]
pub struct InProcessClientStartArgs {
/// Resolved argv0 dispatch paths used by command execution internals.
pub arg0_paths: Arg0DispatchPaths,
/// Shared config used to initialize app-server runtime.
pub config: Arc<Config>,
/// CLI config overrides that are already parsed into TOML values.
pub cli_overrides: Vec<(String, TomlValue)>,
/// Loader override knobs used by config API paths.
pub loader_overrides: LoaderOverrides,
/// Preloaded cloud requirements provider.
pub cloud_requirements: CloudRequirementsLoader,
/// Feedback sink used by app-server/core telemetry and logs.
pub feedback: CodexFeedback,
/// Startup warnings emitted after initialize succeeds.
pub config_warnings: Vec<ConfigWarningNotification>,
/// Session source recorded in app-server thread metadata.
pub session_source: SessionSource,
/// Whether auth loading should honor the `CODEX_API_KEY` environment variable.
pub enable_codex_api_key_env: bool,
/// Client name reported during initialize.
pub client_name: String,
/// Client version reported during initialize.
pub client_version: String,
/// Whether experimental APIs are requested at initialize time.
pub experimental_api: bool,
/// Notification methods this client opts out of receiving.
pub opt_out_notification_methods: Vec<String>,
/// Queue capacity for command/event channels (clamped to at least 1).
pub channel_capacity: usize,
}
impl InProcessClientStartArgs {
/// Builds initialize params from caller-provided metadata.
pub fn initialize_params(&self) -> InitializeParams {
let capabilities = InitializeCapabilities {
experimental_api: self.experimental_api,
opt_out_notification_methods: if self.opt_out_notification_methods.is_empty() {
None
} else {
Some(self.opt_out_notification_methods.clone())
},
};
InitializeParams {
client_info: ClientInfo {
name: self.client_name.clone(),
title: None,
version: self.client_version.clone(),
},
capabilities: Some(capabilities),
}
}
fn into_runtime_start_args(self) -> InProcessStartArgs {
let initialize = self.initialize_params();
InProcessStartArgs {
arg0_paths: self.arg0_paths,
config: self.config,
cli_overrides: self.cli_overrides,
loader_overrides: self.loader_overrides,
cloud_requirements: self.cloud_requirements,
feedback: self.feedback,
config_warnings: self.config_warnings,
session_source: self.session_source,
enable_codex_api_key_env: self.enable_codex_api_key_env,
initialize,
channel_capacity: self.channel_capacity,
}
}
}
/// Internal command sent from public facade methods to the worker task.
///
/// Each variant carries a oneshot sender so the caller can `await` the
/// result without holding a mutable reference to the client.
enum ClientCommand {
Request {
request: Box<ClientRequest>,
response_tx: oneshot::Sender<IoResult<RequestResult>>,
},
Notify {
notification: ClientNotification,
response_tx: oneshot::Sender<IoResult<()>>,
},
ResolveServerRequest {
request_id: RequestId,
result: JsonRpcResult,
response_tx: oneshot::Sender<IoResult<()>>,
},
RejectServerRequest {
request_id: RequestId,
error: JSONRPCErrorError,
response_tx: oneshot::Sender<IoResult<()>>,
},
Shutdown {
response_tx: oneshot::Sender<IoResult<()>>,
},
}
/// Async facade over the in-process app-server runtime.
///
/// This type owns a worker task that bridges between:
/// - caller-facing async `mpsc` channels used by TUI/exec
/// - [`codex_app_server::in_process::InProcessClientHandle`], which speaks to
/// the embedded `MessageProcessor`
///
/// The facade intentionally preserves the server's request/notification/event
/// model instead of exposing direct core runtime handles. That keeps in-process
/// callers aligned with app-server behavior while still avoiding a process
/// boundary.
pub struct InProcessAppServerClient {
command_tx: mpsc::Sender<ClientCommand>,
event_rx: mpsc::Receiver<InProcessServerEvent>,
worker_handle: tokio::task::JoinHandle<()>,
}
impl InProcessAppServerClient {
/// Starts the in-process runtime and facade worker task.
///
/// The returned client is ready for requests and event consumption. If the
/// internal event queue is saturated later, server requests are rejected
/// with overload error instead of being silently dropped.
pub async fn start(args: InProcessClientStartArgs) -> IoResult<Self> {
let channel_capacity = args.channel_capacity.max(1);
let mut handle =
codex_app_server::in_process::start(args.into_runtime_start_args()).await?;
let request_sender = handle.sender();
let (command_tx, mut command_rx) = mpsc::channel::<ClientCommand>(channel_capacity);
let (event_tx, event_rx) = mpsc::channel::<InProcessServerEvent>(channel_capacity);
let worker_handle = tokio::spawn(async move {
let mut event_stream_enabled = true;
let mut skipped_events = 0usize;
loop {
tokio::select! {
command = command_rx.recv() => {
match command {
Some(ClientCommand::Request { request, response_tx }) => {
let request_sender = request_sender.clone();
// Request waits happen on a detached task so
// this loop can keep draining runtime events
// while the request is blocked on client input.
tokio::spawn(async move {
let result = request_sender.request(*request).await;
let _ = response_tx.send(result);
});
}
Some(ClientCommand::Notify {
notification,
response_tx,
}) => {
let result = request_sender.notify(notification);
let _ = response_tx.send(result);
}
Some(ClientCommand::ResolveServerRequest {
request_id,
result,
response_tx,
}) => {
let send_result =
request_sender.respond_to_server_request(request_id, result);
let _ = response_tx.send(send_result);
}
Some(ClientCommand::RejectServerRequest {
request_id,
error,
response_tx,
}) => {
let send_result = request_sender.fail_server_request(request_id, error);
let _ = response_tx.send(send_result);
}
Some(ClientCommand::Shutdown { response_tx }) => {
let shutdown_result = handle.shutdown().await;
let _ = response_tx.send(shutdown_result);
break;
}
None => {
let _ = handle.shutdown().await;
break;
}
}
}
event = handle.next_event(), if event_stream_enabled => {
let Some(event) = event else {
break;
};
if skipped_events > 0 {
if event_requires_delivery(&event) {
// Surface lag before the terminal event, but
// do not let the lag marker itself cause us to
// drop the completion/abort notification that
// the caller is blocked on.
if event_tx
.send(InProcessServerEvent::Lagged {
skipped: skipped_events,
})
.await
.is_err()
{
event_stream_enabled = false;
continue;
}
skipped_events = 0;
} else {
match event_tx.try_send(InProcessServerEvent::Lagged {
skipped: skipped_events,
}) {
Ok(()) => {
skipped_events = 0;
}
Err(mpsc::error::TrySendError::Full(_)) => {
skipped_events = skipped_events.saturating_add(1);
warn!(
"dropping in-process app-server event because consumer queue is full"
);
if let InProcessServerEvent::ServerRequest(request) = event {
let _ = request_sender.fail_server_request(
request.id().clone(),
JSONRPCErrorError {
code: -32001,
message: "in-process app-server event queue is full".to_string(),
data: None,
},
);
}
continue;
}
Err(mpsc::error::TrySendError::Closed(_)) => {
event_stream_enabled = false;
continue;
}
}
}
}
if event_requires_delivery(&event) {
// Block until the consumer catches up for
// terminal notifications; this preserves the
// completion signal even when the queue is
// otherwise saturated.
if event_tx.send(event).await.is_err() {
event_stream_enabled = false;
}
continue;
}
match event_tx.try_send(event) {
Ok(()) => {}
Err(mpsc::error::TrySendError::Full(event)) => {
skipped_events = skipped_events.saturating_add(1);
warn!("dropping in-process app-server event because consumer queue is full");
if let InProcessServerEvent::ServerRequest(request) = event {
let _ = request_sender.fail_server_request(
request.id().clone(),
JSONRPCErrorError {
code: -32001,
message: "in-process app-server event queue is full".to_string(),
data: None,
},
);
}
}
Err(mpsc::error::TrySendError::Closed(_)) => {
event_stream_enabled = false;
}
}
}
}
}
});
Ok(Self {
command_tx,
event_rx,
worker_handle,
})
}
/// Sends a typed client request and returns raw JSON-RPC result.
///
/// Callers that expect a concrete response type should usually prefer
/// [`request_typed`](Self::request_typed).
pub async fn request(&self, request: ClientRequest) -> IoResult<RequestResult> {
let (response_tx, response_rx) = oneshot::channel();
self.command_tx
.send(ClientCommand::Request {
request: Box::new(request),
response_tx,
})
.await
.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server worker channel is closed",
)
})?;
response_rx.await.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server request channel is closed",
)
})?
}
/// Sends a typed client request and decodes the successful response body.
///
/// This still deserializes from a JSON value produced by app-server's
/// JSON-RPC result envelope. Because the caller chooses `T`, `Deserialize`
/// failures indicate an internal request/response mismatch at the call site
/// (or an in-process bug), not transport skew from an external client.
pub async fn request_typed<T>(&self, request: ClientRequest) -> Result<T, TypedRequestError>
where
T: DeserializeOwned,
{
let method = request_method_name(&request);
let response =
self.request(request)
.await
.map_err(|source| TypedRequestError::Transport {
method: method.clone(),
source,
})?;
let result = response.map_err(|source| TypedRequestError::Server {
method: method.clone(),
source,
})?;
serde_json::from_value(result)
.map_err(|source| TypedRequestError::Deserialize { method, source })
}
/// Sends a typed client notification.
pub async fn notify(&self, notification: ClientNotification) -> IoResult<()> {
let (response_tx, response_rx) = oneshot::channel();
self.command_tx
.send(ClientCommand::Notify {
notification,
response_tx,
})
.await
.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server worker channel is closed",
)
})?;
response_rx.await.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server notify channel is closed",
)
})?
}
/// Resolves a pending server request.
///
/// This should only be called with request IDs obtained from the current
/// client's event stream.
pub async fn resolve_server_request(
&self,
request_id: RequestId,
result: JsonRpcResult,
) -> IoResult<()> {
let (response_tx, response_rx) = oneshot::channel();
self.command_tx
.send(ClientCommand::ResolveServerRequest {
request_id,
result,
response_tx,
})
.await
.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server worker channel is closed",
)
})?;
response_rx.await.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server resolve channel is closed",
)
})?
}
/// Rejects a pending server request with JSON-RPC error payload.
pub async fn reject_server_request(
&self,
request_id: RequestId,
error: JSONRPCErrorError,
) -> IoResult<()> {
let (response_tx, response_rx) = oneshot::channel();
self.command_tx
.send(ClientCommand::RejectServerRequest {
request_id,
error,
response_tx,
})
.await
.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server worker channel is closed",
)
})?;
response_rx.await.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server reject channel is closed",
)
})?
}
/// Returns the next in-process event, or `None` when worker exits.
///
/// Callers are expected to drain this stream promptly. If they fall behind,
/// the worker emits [`InProcessServerEvent::Lagged`] markers and may reject
/// pending server requests rather than letting approval flows hang.
pub async fn next_event(&mut self) -> Option<InProcessServerEvent> {
self.event_rx.recv().await
}
/// Shuts down worker and in-process runtime with bounded wait.
///
/// If graceful shutdown exceeds timeout, the worker task is aborted to
/// avoid leaking background tasks in embedding callers.
pub async fn shutdown(self) -> IoResult<()> {
let Self {
command_tx,
event_rx,
worker_handle,
} = self;
let mut worker_handle = worker_handle;
// Drop the caller-facing receiver before asking the worker to shut
// down. That unblocks any pending must-deliver `event_tx.send(..)`
// so the worker can reach `handle.shutdown()` instead of timing out
// and getting aborted with the runtime still attached.
drop(event_rx);
let (response_tx, response_rx) = oneshot::channel();
if command_tx
.send(ClientCommand::Shutdown { response_tx })
.await
.is_ok()
&& let Ok(command_result) = timeout(SHUTDOWN_TIMEOUT, response_rx).await
{
command_result.map_err(|_| {
IoError::new(
ErrorKind::BrokenPipe,
"in-process app-server shutdown channel is closed",
)
})??;
}
if let Err(_elapsed) = timeout(SHUTDOWN_TIMEOUT, &mut worker_handle).await {
worker_handle.abort();
let _ = worker_handle.await;
}
Ok(())
}
}
/// Extracts the JSON-RPC method name for diagnostics without extending the
/// protocol crate with in-process-only helpers.
fn request_method_name(request: &ClientRequest) -> String {
serde_json::to_value(request)
.ok()
.and_then(|value| {
value
.get("method")
.and_then(serde_json::Value::as_str)
.map(ToOwned::to_owned)
})
.unwrap_or_else(|| "<unknown>".to_string())
}
#[cfg(test)]
mod tests {
use super::*;
use codex_app_server_protocol::ConfigRequirementsReadResponse;
use codex_app_server_protocol::SessionSource as ApiSessionSource;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_core::config::ConfigBuilder;
use pretty_assertions::assert_eq;
use tokio::time::Duration;
use tokio::time::timeout;
async fn build_test_config() -> Config {
match ConfigBuilder::default().build().await {
Ok(config) => config,
Err(_) => Config::load_default_with_cli_overrides(Vec::new())
.expect("default config should load"),
}
}
async fn start_test_client_with_capacity(
session_source: SessionSource,
channel_capacity: usize,
) -> InProcessAppServerClient {
InProcessAppServerClient::start(InProcessClientStartArgs {
arg0_paths: Arg0DispatchPaths::default(),
config: Arc::new(build_test_config().await),
cli_overrides: Vec::new(),
loader_overrides: LoaderOverrides::default(),
cloud_requirements: CloudRequirementsLoader::default(),
feedback: CodexFeedback::new(),
config_warnings: Vec::new(),
session_source,
enable_codex_api_key_env: false,
client_name: "codex-app-server-client-test".to_string(),
client_version: "0.0.0-test".to_string(),
experimental_api: true,
opt_out_notification_methods: Vec::new(),
channel_capacity,
})
.await
.expect("in-process app-server client should start")
}
async fn start_test_client(session_source: SessionSource) -> InProcessAppServerClient {
start_test_client_with_capacity(session_source, DEFAULT_IN_PROCESS_CHANNEL_CAPACITY).await
}
#[tokio::test]
async fn typed_request_roundtrip_works() {
let client = start_test_client(SessionSource::Exec).await;
let _response: ConfigRequirementsReadResponse = client
.request_typed(ClientRequest::ConfigRequirementsRead {
request_id: RequestId::Integer(1),
params: None,
})
.await
.expect("typed request should succeed");
client.shutdown().await.expect("shutdown should complete");
}
#[tokio::test]
async fn typed_request_reports_json_rpc_errors() {
let client = start_test_client(SessionSource::Exec).await;
let err = client
.request_typed::<ConfigRequirementsReadResponse>(ClientRequest::ThreadRead {
request_id: RequestId::Integer(99),
params: codex_app_server_protocol::ThreadReadParams {
thread_id: "missing-thread".to_string(),
include_turns: false,
},
})
.await
.expect_err("missing thread should return a JSON-RPC error");
assert!(
err.to_string().starts_with("thread/read failed:"),
"expected method-qualified JSON-RPC failure message"
);
client.shutdown().await.expect("shutdown should complete");
}
#[tokio::test]
async fn caller_provided_session_source_is_applied() {
for (session_source, expected_source) in [
(SessionSource::Exec, ApiSessionSource::Exec),
(SessionSource::Cli, ApiSessionSource::Cli),
] {
let client = start_test_client(session_source).await;
let parsed: ThreadStartResponse = client
.request_typed(ClientRequest::ThreadStart {
request_id: RequestId::Integer(2),
params: ThreadStartParams {
ephemeral: Some(true),
..ThreadStartParams::default()
},
})
.await
.expect("thread/start should succeed");
assert_eq!(parsed.thread.source, expected_source);
client.shutdown().await.expect("shutdown should complete");
}
}
#[tokio::test]
async fn tiny_channel_capacity_still_supports_request_roundtrip() {
let client = start_test_client_with_capacity(SessionSource::Exec, 1).await;
let _response: ConfigRequirementsReadResponse = client
.request_typed(ClientRequest::ConfigRequirementsRead {
request_id: RequestId::Integer(1),
params: None,
})
.await
.expect("typed request should succeed");
client.shutdown().await.expect("shutdown should complete");
}
#[test]
fn typed_request_error_exposes_sources() {
let transport = TypedRequestError::Transport {
method: "config/read".to_string(),
source: IoError::new(ErrorKind::BrokenPipe, "closed"),
};
assert_eq!(std::error::Error::source(&transport).is_some(), true);
let server = TypedRequestError::Server {
method: "thread/read".to_string(),
source: JSONRPCErrorError {
code: -32603,
data: None,
message: "internal".to_string(),
},
};
assert_eq!(std::error::Error::source(&server).is_some(), false);
let deserialize = TypedRequestError::Deserialize {
method: "thread/start".to_string(),
source: serde_json::from_str::<u32>("\"nope\"")
.expect_err("invalid integer should return deserialize error"),
};
assert_eq!(std::error::Error::source(&deserialize).is_some(), true);
}
#[tokio::test]
async fn next_event_surfaces_lagged_markers() {
let (command_tx, _command_rx) = mpsc::channel(1);
let (event_tx, event_rx) = mpsc::channel(1);
let worker_handle = tokio::spawn(async {});
event_tx
.send(InProcessServerEvent::Lagged { skipped: 3 })
.await
.expect("lagged marker should enqueue");
drop(event_tx);
let mut client = InProcessAppServerClient {
command_tx,
event_rx,
worker_handle,
};
let event = timeout(Duration::from_secs(2), client.next_event())
.await
.expect("lagged marker should arrive before timeout");
assert!(matches!(
event,
Some(InProcessServerEvent::Lagged { skipped: 3 })
));
client.shutdown().await.expect("shutdown should complete");
}
#[test]
fn event_requires_delivery_marks_terminal_events() {
assert!(event_requires_delivery(
&InProcessServerEvent::ServerNotification(
codex_app_server_protocol::ServerNotification::TurnCompleted(
codex_app_server_protocol::TurnCompletedNotification {
thread_id: "thread".to_string(),
turn: codex_app_server_protocol::Turn {
id: "turn".to_string(),
items: Vec::new(),
status: codex_app_server_protocol::TurnStatus::Completed,
error: None,
},
}
)
)
));
assert!(event_requires_delivery(
&InProcessServerEvent::LegacyNotification(
codex_app_server_protocol::JSONRPCNotification {
method: "codex/event/turn_aborted".to_string(),
params: None,
}
)
));
assert!(!event_requires_delivery(&InProcessServerEvent::Lagged {
skipped: 1
}));
}
}

View File

@@ -52,16 +52,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -73,9 +81,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]
@@ -350,6 +358,10 @@
"string",
"null"
]
},
"reloadUserConfig": {
"description": "When true, hot-reload the updated user config into all loaded threads after writing.",
"type": "boolean"
}
},
"required": [
@@ -690,24 +702,6 @@
}
]
},
"FunctionCallOutputPayload": {
"description": "The payload we send back to OpenAI when reporting a tool call result.\n\n`body` serializes directly as the wire value for `function_call_output.output`. `success` remains internal metadata for downstream handling.",
"properties": {
"body": {
"$ref": "#/definitions/FunctionCallOutputBody"
},
"success": {
"type": [
"boolean",
"null"
]
}
},
"required": [
"body"
],
"type": "object"
},
"FuzzyFileSearchParams": {
"properties": {
"cancellationToken": {
@@ -801,7 +795,7 @@
"type": "boolean"
},
"optOutNotificationMethods": {
"description": "Exact notification method names that should be suppressed for this connection (for example `codex/event/session_configured`).",
"description": "Exact notification method names that should be suppressed for this connection (for example `thread/started`).",
"items": {
"type": "string"
},
@@ -1123,10 +1117,40 @@
"array",
"null"
]
},
"forceRemoteSync": {
"description": "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.",
"type": "boolean"
}
},
"type": "object"
},
"PluginReadParams": {
"properties": {
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"pluginName": {
"type": "string"
}
},
"required": [
"marketplacePath",
"pluginName"
],
"type": "object"
},
"PluginUninstallParams": {
"properties": {
"pluginId": {
"type": "string"
}
},
"required": [
"pluginId"
],
"type": "object"
},
"ProductSurface": {
"enum": [
"chatgpt",
@@ -1364,10 +1388,6 @@
"null"
]
},
"id": {
"type": "string",
"writeOnly": true
},
"summary": {
"items": {
"$ref": "#/definitions/ReasoningItemReasoningSummary"
@@ -1383,7 +1403,6 @@
}
},
"required": [
"id",
"summary",
"type"
],
@@ -1447,6 +1466,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"function_call"
@@ -1464,13 +1489,54 @@
"title": "FunctionCallResponseItem",
"type": "object"
},
{
"properties": {
"arguments": true,
"call_id": {
"type": [
"string",
"null"
]
},
"execution": {
"type": "string"
},
"id": {
"type": [
"string",
"null"
],
"writeOnly": true
},
"status": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"tool_search_call"
],
"title": "ToolSearchCallResponseItemType",
"type": "string"
}
},
"required": [
"arguments",
"execution",
"type"
],
"title": "ToolSearchCallResponseItem",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"output": {
"$ref": "#/definitions/FunctionCallOutputPayload"
"$ref": "#/definitions/FunctionCallOutputBody"
},
"type": {
"enum": [
@@ -1535,7 +1601,7 @@
"type": "string"
},
"output": {
"$ref": "#/definitions/FunctionCallOutputPayload"
"$ref": "#/definitions/FunctionCallOutputBody"
},
"type": {
"enum": [
@@ -1553,6 +1619,41 @@
"title": "CustomToolCallOutputResponseItem",
"type": "object"
},
{
"properties": {
"call_id": {
"type": [
"string",
"null"
]
},
"execution": {
"type": "string"
},
"status": {
"type": "string"
},
"tools": {
"items": true,
"type": "array"
},
"type": {
"enum": [
"tool_search_output"
],
"title": "ToolSearchOutputResponseItemType",
"type": "string"
}
},
"required": [
"execution",
"status",
"tools",
"type"
],
"title": "ToolSearchOutputResponseItem",
"type": "object"
},
{
"properties": {
"action": {
@@ -2251,6 +2352,9 @@
"null"
]
},
"ephemeral": {
"type": "boolean"
},
"model": {
"description": "Configuration overrides for the forked thread, if any.",
"type": [
@@ -3447,6 +3551,30 @@
"title": "Plugin/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/read"
],
"title": "Plugin/readRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginReadParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/readRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -3567,6 +3695,30 @@
"title": "Plugin/installRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/uninstall"
],
"title": "Plugin/uninstallRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginUninstallParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/uninstallRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4217,4 +4369,4 @@
}
],
"title": "ClientRequest"
}
}

View File

@@ -39,15 +39,27 @@
"calendar": {
"type": "boolean"
},
"contacts": {
"$ref": "#/definitions/MacOsContactsPermission"
},
"launchServices": {
"type": "boolean"
},
"preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
},
"reminders": {
"type": "boolean"
}
},
"required": [
"accessibility",
"automations",
"calendar",
"preferences"
"contacts",
"launchServices",
"preferences",
"reminders"
],
"type": "object"
},
@@ -286,6 +298,17 @@
}
]
},
"CommandExecutionRequestApprovalSkillMetadata": {
"properties": {
"pathToSkillsMd": {
"type": "string"
}
},
"required": [
"pathToSkillsMd"
],
"type": "object"
},
"MacOsAutomationPermission": {
"oneOf": [
{
@@ -313,6 +336,14 @@
}
]
},
"MacOsContactsPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"MacOsPreferencesPermission": {
"enum": [
"none",

View File

@@ -0,0 +1,184 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"AdditionalFileSystemPermissions": {
"properties": {
"read": {
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
},
"write": {
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
}
},
"type": "object"
},
"AdditionalMacOsPermissions": {
"properties": {
"accessibility": {
"type": "boolean"
},
"automations": {
"$ref": "#/definitions/MacOsAutomationPermission"
},
"calendar": {
"type": "boolean"
},
"contacts": {
"$ref": "#/definitions/MacOsContactsPermission"
},
"launchServices": {
"type": "boolean"
},
"preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
},
"reminders": {
"type": "boolean"
}
},
"required": [
"accessibility",
"automations",
"calendar",
"contacts",
"launchServices",
"preferences",
"reminders"
],
"type": "object"
},
"AdditionalNetworkPermissions": {
"properties": {
"enabled": {
"type": [
"boolean",
"null"
]
}
},
"type": "object"
},
"AdditionalPermissionProfile": {
"properties": {
"fileSystem": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalFileSystemPermissions"
},
{
"type": "null"
}
]
},
"macos": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalMacOsPermissions"
},
{
"type": "null"
}
]
},
"network": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalNetworkPermissions"
},
{
"type": "null"
}
]
}
},
"type": "object"
},
"MacOsAutomationPermission": {
"oneOf": [
{
"enum": [
"none",
"all"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"bundle_ids": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"bundle_ids"
],
"title": "BundleIdsMacOsAutomationPermission",
"type": "object"
}
]
},
"MacOsContactsPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"MacOsPreferencesPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
}
},
"properties": {
"itemId": {
"type": "string"
},
"permissions": {
"$ref": "#/definitions/AdditionalPermissionProfile"
},
"reason": {
"type": [
"string",
"null"
]
},
"threadId": {
"type": "string"
},
"turnId": {
"type": "string"
}
},
"required": [
"itemId",
"permissions",
"threadId",
"turnId"
],
"title": "PermissionsRequestApprovalParams",
"type": "object"
}

View File

@@ -0,0 +1,205 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"AdditionalFileSystemPermissions": {
"properties": {
"read": {
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
},
"write": {
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
}
},
"type": "object"
},
"AdditionalNetworkPermissions": {
"properties": {
"enabled": {
"type": [
"boolean",
"null"
]
}
},
"type": "object"
},
"GrantedMacOsPermissions": {
"properties": {
"accessibility": {
"type": [
"boolean",
"null"
]
},
"automations": {
"anyOf": [
{
"$ref": "#/definitions/MacOsAutomationPermission"
},
{
"type": "null"
}
]
},
"calendar": {
"type": [
"boolean",
"null"
]
},
"contacts": {
"anyOf": [
{
"$ref": "#/definitions/MacOsContactsPermission"
},
{
"type": "null"
}
]
},
"launchServices": {
"type": [
"boolean",
"null"
]
},
"preferences": {
"anyOf": [
{
"$ref": "#/definitions/MacOsPreferencesPermission"
},
{
"type": "null"
}
]
},
"reminders": {
"type": [
"boolean",
"null"
]
}
},
"type": "object"
},
"GrantedPermissionProfile": {
"properties": {
"fileSystem": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalFileSystemPermissions"
},
{
"type": "null"
}
]
},
"macos": {
"anyOf": [
{
"$ref": "#/definitions/GrantedMacOsPermissions"
},
{
"type": "null"
}
]
},
"network": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalNetworkPermissions"
},
{
"type": "null"
}
]
}
},
"type": "object"
},
"MacOsAutomationPermission": {
"oneOf": [
{
"enum": [
"none",
"all"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"bundle_ids": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"bundle_ids"
],
"title": "BundleIdsMacOsAutomationPermission",
"type": "object"
}
]
},
"MacOsContactsPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"MacOsPreferencesPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"PermissionGrantScope": {
"enum": [
"turn",
"session"
],
"type": "string"
}
},
"properties": {
"permissions": {
"$ref": "#/definitions/GrantedPermissionProfile"
},
"scope": {
"allOf": [
{
"$ref": "#/definitions/PermissionGrantScope"
}
],
"default": "turn"
}
},
"required": [
"permissions"
],
"title": "PermissionsRequestApprovalResponse",
"type": "object"
}

View File

@@ -1056,6 +1056,184 @@
},
"type": "object"
},
"HookCompletedNotification": {
"properties": {
"run": {
"$ref": "#/definitions/HookRunSummary"
},
"threadId": {
"type": "string"
},
"turnId": {
"type": [
"string",
"null"
]
}
},
"required": [
"run",
"threadId"
],
"type": "object"
},
"HookEventName": {
"enum": [
"sessionStart",
"stop"
],
"type": "string"
},
"HookExecutionMode": {
"enum": [
"sync",
"async"
],
"type": "string"
},
"HookHandlerType": {
"enum": [
"command",
"prompt",
"agent"
],
"type": "string"
},
"HookOutputEntry": {
"properties": {
"kind": {
"$ref": "#/definitions/HookOutputEntryKind"
},
"text": {
"type": "string"
}
},
"required": [
"kind",
"text"
],
"type": "object"
},
"HookOutputEntryKind": {
"enum": [
"warning",
"stop",
"feedback",
"context",
"error"
],
"type": "string"
},
"HookRunStatus": {
"enum": [
"running",
"completed",
"failed",
"blocked",
"stopped"
],
"type": "string"
},
"HookRunSummary": {
"properties": {
"completedAt": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"displayOrder": {
"format": "int64",
"type": "integer"
},
"durationMs": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"entries": {
"items": {
"$ref": "#/definitions/HookOutputEntry"
},
"type": "array"
},
"eventName": {
"$ref": "#/definitions/HookEventName"
},
"executionMode": {
"$ref": "#/definitions/HookExecutionMode"
},
"handlerType": {
"$ref": "#/definitions/HookHandlerType"
},
"id": {
"type": "string"
},
"scope": {
"$ref": "#/definitions/HookScope"
},
"sourcePath": {
"type": "string"
},
"startedAt": {
"format": "int64",
"type": "integer"
},
"status": {
"$ref": "#/definitions/HookRunStatus"
},
"statusMessage": {
"type": [
"string",
"null"
]
}
},
"required": [
"displayOrder",
"entries",
"eventName",
"executionMode",
"handlerType",
"id",
"scope",
"sourcePath",
"startedAt",
"status"
],
"type": "object"
},
"HookScope": {
"enum": [
"thread",
"turn"
],
"type": "string"
},
"HookStartedNotification": {
"properties": {
"run": {
"$ref": "#/definitions/HookRunSummary"
},
"threadId": {
"type": "string"
},
"turnId": {
"type": [
"string",
"null"
]
}
},
"required": [
"run",
"threadId"
],
"type": "object"
},
"ItemCompletedNotification": {
"properties": {
"item": {
@@ -1410,6 +1588,18 @@
],
"type": "object"
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"ReasoningSummaryPartAddedNotification": {
"properties": {
"itemId": {
@@ -2197,6 +2387,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -2204,6 +2401,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {
@@ -3378,6 +3586,26 @@
"title": "Turn/startedNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"hook/started"
],
"title": "Hook/startedNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/HookStartedNotification"
}
},
"required": [
"method",
"params"
],
"title": "Hook/startedNotification",
"type": "object"
},
{
"properties": {
"method": {
@@ -3398,6 +3626,26 @@
"title": "Turn/completedNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"hook/completed"
],
"title": "Hook/completedNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/HookCompletedNotification"
}
},
"required": [
"method",
"params"
],
"title": "Hook/completedNotification",
"type": "object"
},
{
"properties": {
"method": {

View File

@@ -39,15 +39,27 @@
"calendar": {
"type": "boolean"
},
"contacts": {
"$ref": "#/definitions/MacOsContactsPermission"
},
"launchServices": {
"type": "boolean"
},
"preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
},
"reminders": {
"type": "boolean"
}
},
"required": [
"accessibility",
"automations",
"calendar",
"preferences"
"contacts",
"launchServices",
"preferences",
"reminders"
],
"type": "object"
},
@@ -440,6 +452,17 @@
],
"type": "object"
},
"CommandExecutionRequestApprovalSkillMetadata": {
"properties": {
"pathToSkillsMd": {
"type": "string"
}
},
"required": [
"pathToSkillsMd"
],
"type": "object"
},
"DynamicToolCallParams": {
"properties": {
"arguments": true,
@@ -642,6 +665,14 @@
}
]
},
"MacOsContactsPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"MacOsPreferencesPermission": {
"enum": [
"none",
@@ -1412,6 +1443,35 @@
}
]
},
"PermissionsRequestApprovalParams": {
"properties": {
"itemId": {
"type": "string"
},
"permissions": {
"$ref": "#/definitions/AdditionalPermissionProfile"
},
"reason": {
"type": [
"string",
"null"
]
},
"threadId": {
"type": "string"
},
"turnId": {
"type": "string"
}
},
"required": [
"itemId",
"permissions",
"threadId",
"turnId"
],
"type": "object"
},
"RequestId": {
"anyOf": [
{
@@ -1609,6 +1669,31 @@
"title": "McpServer/elicitation/requestRequest",
"type": "object"
},
{
"description": "Request approval for additional permissions from the user.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"item/permissions/requestApproval"
],
"title": "Item/permissions/requestApprovalRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PermissionsRequestApprovalParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Item/permissions/requestApprovalRequest",
"type": "object"
},
{
"description": "Execute a dynamic tool call on the client.",
"properties": {

View File

@@ -31,7 +31,7 @@
"type": "boolean"
},
"optOutNotificationMethods": {
"description": "Exact notification method names that should be suppressed for this connection (for example `codex/event/session_configured`).",
"description": "Exact notification method names that should be suppressed for this connection (for example `thread/started`).",
"items": {
"type": "string"
},

View File

@@ -45,6 +45,10 @@
"string",
"null"
]
},
"reloadUserConfig": {
"description": "When true, hot-reload the updated user config into all loaded threads after writing.",
"type": "boolean"
}
},
"required": [

View File

@@ -143,16 +143,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -164,9 +172,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]

View File

@@ -15,16 +15,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -36,9 +44,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]

View File

@@ -0,0 +1,161 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"HookEventName": {
"enum": [
"sessionStart",
"stop"
],
"type": "string"
},
"HookExecutionMode": {
"enum": [
"sync",
"async"
],
"type": "string"
},
"HookHandlerType": {
"enum": [
"command",
"prompt",
"agent"
],
"type": "string"
},
"HookOutputEntry": {
"properties": {
"kind": {
"$ref": "#/definitions/HookOutputEntryKind"
},
"text": {
"type": "string"
}
},
"required": [
"kind",
"text"
],
"type": "object"
},
"HookOutputEntryKind": {
"enum": [
"warning",
"stop",
"feedback",
"context",
"error"
],
"type": "string"
},
"HookRunStatus": {
"enum": [
"running",
"completed",
"failed",
"blocked",
"stopped"
],
"type": "string"
},
"HookRunSummary": {
"properties": {
"completedAt": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"displayOrder": {
"format": "int64",
"type": "integer"
},
"durationMs": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"entries": {
"items": {
"$ref": "#/definitions/HookOutputEntry"
},
"type": "array"
},
"eventName": {
"$ref": "#/definitions/HookEventName"
},
"executionMode": {
"$ref": "#/definitions/HookExecutionMode"
},
"handlerType": {
"$ref": "#/definitions/HookHandlerType"
},
"id": {
"type": "string"
},
"scope": {
"$ref": "#/definitions/HookScope"
},
"sourcePath": {
"type": "string"
},
"startedAt": {
"format": "int64",
"type": "integer"
},
"status": {
"$ref": "#/definitions/HookRunStatus"
},
"statusMessage": {
"type": [
"string",
"null"
]
}
},
"required": [
"displayOrder",
"entries",
"eventName",
"executionMode",
"handlerType",
"id",
"scope",
"sourcePath",
"startedAt",
"status"
],
"type": "object"
},
"HookScope": {
"enum": [
"thread",
"turn"
],
"type": "string"
}
},
"properties": {
"run": {
"$ref": "#/definitions/HookRunSummary"
},
"threadId": {
"type": "string"
},
"turnId": {
"type": [
"string",
"null"
]
}
},
"required": [
"run",
"threadId"
],
"title": "HookCompletedNotification",
"type": "object"
}

View File

@@ -0,0 +1,161 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"HookEventName": {
"enum": [
"sessionStart",
"stop"
],
"type": "string"
},
"HookExecutionMode": {
"enum": [
"sync",
"async"
],
"type": "string"
},
"HookHandlerType": {
"enum": [
"command",
"prompt",
"agent"
],
"type": "string"
},
"HookOutputEntry": {
"properties": {
"kind": {
"$ref": "#/definitions/HookOutputEntryKind"
},
"text": {
"type": "string"
}
},
"required": [
"kind",
"text"
],
"type": "object"
},
"HookOutputEntryKind": {
"enum": [
"warning",
"stop",
"feedback",
"context",
"error"
],
"type": "string"
},
"HookRunStatus": {
"enum": [
"running",
"completed",
"failed",
"blocked",
"stopped"
],
"type": "string"
},
"HookRunSummary": {
"properties": {
"completedAt": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"displayOrder": {
"format": "int64",
"type": "integer"
},
"durationMs": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"entries": {
"items": {
"$ref": "#/definitions/HookOutputEntry"
},
"type": "array"
},
"eventName": {
"$ref": "#/definitions/HookEventName"
},
"executionMode": {
"$ref": "#/definitions/HookExecutionMode"
},
"handlerType": {
"$ref": "#/definitions/HookHandlerType"
},
"id": {
"type": "string"
},
"scope": {
"$ref": "#/definitions/HookScope"
},
"sourcePath": {
"type": "string"
},
"startedAt": {
"format": "int64",
"type": "integer"
},
"status": {
"$ref": "#/definitions/HookRunStatus"
},
"statusMessage": {
"type": [
"string",
"null"
]
}
},
"required": [
"displayOrder",
"entries",
"eventName",
"executionMode",
"handlerType",
"id",
"scope",
"sourcePath",
"startedAt",
"status"
],
"type": "object"
},
"HookScope": {
"enum": [
"thread",
"turn"
],
"type": "string"
}
},
"properties": {
"run": {
"$ref": "#/definitions/HookRunSummary"
},
"threadId": {
"type": "string"
},
"turnId": {
"type": [
"string",
"null"
]
}
},
"required": [
"run",
"threadId"
],
"title": "HookStartedNotification",
"type": "object"
}

View File

@@ -374,6 +374,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"TextElement": {
"properties": {
"byteRange": {
@@ -751,6 +763,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -758,6 +777,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -374,6 +374,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"TextElement": {
"properties": {
"byteRange": {
@@ -751,6 +763,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -758,6 +777,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AppSummary": {
"description": "EXPERIMENTAL - app metadata summary for plugin-install responses.",
"description": "EXPERIMENTAL - app metadata summary for plugin responses.",
"properties": {
"description": {
"type": [
@@ -28,6 +28,13 @@
"name"
],
"type": "object"
},
"PluginAuthPolicy": {
"enum": [
"ON_INSTALL",
"ON_USE"
],
"type": "string"
}
},
"properties": {
@@ -36,10 +43,14 @@
"$ref": "#/definitions/AppSummary"
},
"type": "array"
},
"authPolicy": {
"$ref": "#/definitions/PluginAuthPolicy"
}
},
"required": [
"appsNeedingAuth"
"appsNeedingAuth",
"authPolicy"
],
"title": "PluginInstallResponse",
"type": "object"

View File

@@ -16,6 +16,10 @@
"array",
"null"
]
},
"forceRemoteSync": {
"description": "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.",
"type": "boolean"
}
},
"title": "PluginListParams",

View File

@@ -5,6 +5,21 @@
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"PluginAuthPolicy": {
"enum": [
"ON_INSTALL",
"ON_USE"
],
"type": "string"
},
"PluginInstallPolicy": {
"enum": [
"NOT_AVAILABLE",
"AVAILABLE",
"INSTALLED_BY_DEFAULT"
],
"type": "string"
},
"PluginInterface": {
"properties": {
"brandColor": {
@@ -154,12 +169,18 @@
},
"PluginSummary": {
"properties": {
"authPolicy": {
"$ref": "#/definitions/PluginAuthPolicy"
},
"enabled": {
"type": "boolean"
},
"id": {
"type": "string"
},
"installPolicy": {
"$ref": "#/definitions/PluginInstallPolicy"
},
"installed": {
"type": "boolean"
},
@@ -181,8 +202,10 @@
}
},
"required": [
"authPolicy",
"enabled",
"id",
"installPolicy",
"installed",
"name",
"source"
@@ -196,6 +219,12 @@
"$ref": "#/definitions/PluginMarketplaceEntry"
},
"type": "array"
},
"remoteSyncError": {
"type": [
"string",
"null"
]
}
},
"required": [

View File

@@ -0,0 +1,23 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
}
},
"properties": {
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"pluginName": {
"type": "string"
}
},
"required": [
"marketplacePath",
"pluginName"
],
"title": "PluginReadParams",
"type": "object"
}

View File

@@ -0,0 +1,354 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"AppSummary": {
"description": "EXPERIMENTAL - app metadata summary for plugin responses.",
"properties": {
"description": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string"
},
"installUrl": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
},
"PluginAuthPolicy": {
"enum": [
"ON_INSTALL",
"ON_USE"
],
"type": "string"
},
"PluginDetail": {
"properties": {
"apps": {
"items": {
"$ref": "#/definitions/AppSummary"
},
"type": "array"
},
"description": {
"type": [
"string",
"null"
]
},
"marketplaceName": {
"type": "string"
},
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"mcpServers": {
"items": {
"type": "string"
},
"type": "array"
},
"skills": {
"items": {
"$ref": "#/definitions/SkillSummary"
},
"type": "array"
},
"summary": {
"$ref": "#/definitions/PluginSummary"
}
},
"required": [
"apps",
"marketplaceName",
"marketplacePath",
"mcpServers",
"skills",
"summary"
],
"type": "object"
},
"PluginInstallPolicy": {
"enum": [
"NOT_AVAILABLE",
"AVAILABLE",
"INSTALLED_BY_DEFAULT"
],
"type": "string"
},
"PluginInterface": {
"properties": {
"brandColor": {
"type": [
"string",
"null"
]
},
"capabilities": {
"items": {
"type": "string"
},
"type": "array"
},
"category": {
"type": [
"string",
"null"
]
},
"composerIcon": {
"anyOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
},
{
"type": "null"
}
]
},
"defaultPrompt": {
"type": [
"string",
"null"
]
},
"developerName": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"logo": {
"anyOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
},
{
"type": "null"
}
]
},
"longDescription": {
"type": [
"string",
"null"
]
},
"privacyPolicyUrl": {
"type": [
"string",
"null"
]
},
"screenshots": {
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": "array"
},
"shortDescription": {
"type": [
"string",
"null"
]
},
"termsOfServiceUrl": {
"type": [
"string",
"null"
]
},
"websiteUrl": {
"type": [
"string",
"null"
]
}
},
"required": [
"capabilities",
"screenshots"
],
"type": "object"
},
"PluginSource": {
"oneOf": [
{
"properties": {
"path": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": {
"enum": [
"local"
],
"title": "LocalPluginSourceType",
"type": "string"
}
},
"required": [
"path",
"type"
],
"title": "LocalPluginSource",
"type": "object"
}
]
},
"PluginSummary": {
"properties": {
"authPolicy": {
"$ref": "#/definitions/PluginAuthPolicy"
},
"enabled": {
"type": "boolean"
},
"id": {
"type": "string"
},
"installPolicy": {
"$ref": "#/definitions/PluginInstallPolicy"
},
"installed": {
"type": "boolean"
},
"interface": {
"anyOf": [
{
"$ref": "#/definitions/PluginInterface"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"source": {
"$ref": "#/definitions/PluginSource"
}
},
"required": [
"authPolicy",
"enabled",
"id",
"installPolicy",
"installed",
"name",
"source"
],
"type": "object"
},
"SkillInterface": {
"properties": {
"brandColor": {
"type": [
"string",
"null"
]
},
"defaultPrompt": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"iconLarge": {
"type": [
"string",
"null"
]
},
"iconSmall": {
"type": [
"string",
"null"
]
},
"shortDescription": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"SkillSummary": {
"properties": {
"description": {
"type": "string"
},
"interface": {
"anyOf": [
{
"$ref": "#/definitions/SkillInterface"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"path": {
"type": "string"
},
"shortDescription": {
"type": [
"string",
"null"
]
}
},
"required": [
"description",
"name",
"path"
],
"type": "object"
}
},
"properties": {
"plugin": {
"$ref": "#/definitions/PluginDetail"
}
},
"required": [
"plugin"
],
"title": "PluginReadResponse",
"type": "object"
}

View File

@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"pluginId": {
"type": "string"
}
},
"required": [
"pluginId"
],
"title": "PluginUninstallParams",
"type": "object"
}

View File

@@ -0,0 +1,5 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PluginUninstallResponse",
"type": "object"
}

View File

@@ -133,24 +133,6 @@
}
]
},
"FunctionCallOutputPayload": {
"description": "The payload we send back to OpenAI when reporting a tool call result.\n\n`body` serializes directly as the wire value for `function_call_output.output`. `success` remains internal metadata for downstream handling.",
"properties": {
"body": {
"$ref": "#/definitions/FunctionCallOutputBody"
},
"success": {
"type": [
"boolean",
"null"
]
}
},
"required": [
"body"
],
"type": "object"
},
"GhostCommit": {
"description": "Details of a ghost commit created from a repository state.",
"properties": {
@@ -413,10 +395,6 @@
"null"
]
},
"id": {
"type": "string",
"writeOnly": true
},
"summary": {
"items": {
"$ref": "#/definitions/ReasoningItemReasoningSummary"
@@ -432,7 +410,6 @@
}
},
"required": [
"id",
"summary",
"type"
],
@@ -496,6 +473,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"function_call"
@@ -513,13 +496,54 @@
"title": "FunctionCallResponseItem",
"type": "object"
},
{
"properties": {
"arguments": true,
"call_id": {
"type": [
"string",
"null"
]
},
"execution": {
"type": "string"
},
"id": {
"type": [
"string",
"null"
],
"writeOnly": true
},
"status": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"tool_search_call"
],
"title": "ToolSearchCallResponseItemType",
"type": "string"
}
},
"required": [
"arguments",
"execution",
"type"
],
"title": "ToolSearchCallResponseItem",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"output": {
"$ref": "#/definitions/FunctionCallOutputPayload"
"$ref": "#/definitions/FunctionCallOutputBody"
},
"type": {
"enum": [
@@ -584,7 +608,7 @@
"type": "string"
},
"output": {
"$ref": "#/definitions/FunctionCallOutputPayload"
"$ref": "#/definitions/FunctionCallOutputBody"
},
"type": {
"enum": [
@@ -602,6 +626,41 @@
"title": "CustomToolCallOutputResponseItem",
"type": "object"
},
{
"properties": {
"call_id": {
"type": [
"string",
"null"
]
},
"execution": {
"type": "string"
},
"status": {
"type": "string"
},
"tools": {
"items": true,
"type": "array"
},
"type": {
"enum": [
"tool_search_output"
],
"title": "ToolSearchOutputResponseItemType",
"type": "string"
}
},
"required": [
"execution",
"status",
"tools",
"type"
],
"title": "ToolSearchOutputResponseItem",
"type": "object"
},
{
"properties": {
"action": {

View File

@@ -488,6 +488,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"TextElement": {
"properties": {
"byteRange": {
@@ -865,6 +877,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -872,6 +891,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -15,16 +15,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -36,9 +44,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]
@@ -96,6 +104,9 @@
"null"
]
},
"ephemeral": {
"type": "boolean"
},
"model": {
"description": "Configuration overrides for the forked thread, if any.",
"type": [

View File

@@ -19,16 +19,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -40,9 +48,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]
@@ -1341,6 +1349,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1348,6 +1363,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -511,6 +511,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"SessionSource": {
"oneOf": [
{
@@ -1103,6 +1115,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1110,6 +1129,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -511,6 +511,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"SessionSource": {
"oneOf": [
{
@@ -1103,6 +1115,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1110,6 +1129,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -511,6 +511,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"SessionSource": {
"oneOf": [
{
@@ -1103,6 +1115,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1110,6 +1129,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -15,16 +15,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -36,9 +44,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]
@@ -175,24 +183,6 @@
}
]
},
"FunctionCallOutputPayload": {
"description": "The payload we send back to OpenAI when reporting a tool call result.\n\n`body` serializes directly as the wire value for `function_call_output.output`. `success` remains internal metadata for downstream handling.",
"properties": {
"body": {
"$ref": "#/definitions/FunctionCallOutputBody"
},
"success": {
"type": [
"boolean",
"null"
]
}
},
"required": [
"body"
],
"type": "object"
},
"GhostCommit": {
"description": "Details of a ghost commit created from a repository state.",
"properties": {
@@ -463,10 +453,6 @@
"null"
]
},
"id": {
"type": "string",
"writeOnly": true
},
"summary": {
"items": {
"$ref": "#/definitions/ReasoningItemReasoningSummary"
@@ -482,7 +468,6 @@
}
},
"required": [
"id",
"summary",
"type"
],
@@ -546,6 +531,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"function_call"
@@ -563,13 +554,54 @@
"title": "FunctionCallResponseItem",
"type": "object"
},
{
"properties": {
"arguments": true,
"call_id": {
"type": [
"string",
"null"
]
},
"execution": {
"type": "string"
},
"id": {
"type": [
"string",
"null"
],
"writeOnly": true
},
"status": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"tool_search_call"
],
"title": "ToolSearchCallResponseItemType",
"type": "string"
}
},
"required": [
"arguments",
"execution",
"type"
],
"title": "ToolSearchCallResponseItem",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"output": {
"$ref": "#/definitions/FunctionCallOutputPayload"
"$ref": "#/definitions/FunctionCallOutputBody"
},
"type": {
"enum": [
@@ -634,7 +666,7 @@
"type": "string"
},
"output": {
"$ref": "#/definitions/FunctionCallOutputPayload"
"$ref": "#/definitions/FunctionCallOutputBody"
},
"type": {
"enum": [
@@ -652,6 +684,41 @@
"title": "CustomToolCallOutputResponseItem",
"type": "object"
},
{
"properties": {
"call_id": {
"type": [
"string",
"null"
]
},
"execution": {
"type": "string"
},
"status": {
"type": "string"
},
"tools": {
"items": true,
"type": "array"
},
"type": {
"enum": [
"tool_search_output"
],
"title": "ToolSearchOutputResponseItemType",
"type": "string"
}
},
"required": [
"execution",
"status",
"tools",
"type"
],
"title": "ToolSearchOutputResponseItem",
"type": "object"
},
{
"properties": {
"action": {

View File

@@ -19,16 +19,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -40,9 +48,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]
@@ -1341,6 +1349,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1348,6 +1363,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -511,6 +511,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"SessionSource": {
"oneOf": [
{
@@ -1103,6 +1115,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1110,6 +1129,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -15,16 +15,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -36,9 +44,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]

View File

@@ -19,16 +19,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -40,9 +48,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]
@@ -1341,6 +1349,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1348,6 +1363,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -511,6 +511,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"SessionSource": {
"oneOf": [
{
@@ -1103,6 +1115,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1110,6 +1129,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -511,6 +511,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"SessionSource": {
"oneOf": [
{
@@ -1103,6 +1115,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -1110,6 +1129,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -488,6 +488,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"TextElement": {
"properties": {
"byteRange": {
@@ -865,6 +877,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -872,6 +891,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -19,16 +19,24 @@
{
"additionalProperties": false,
"properties": {
"reject": {
"granular": {
"properties": {
"mcp_elicitations": {
"type": "boolean"
},
"request_permissions": {
"default": false,
"type": "boolean"
},
"rules": {
"type": "boolean"
},
"sandbox_approval": {
"type": "boolean"
},
"skill_approval": {
"default": false,
"type": "boolean"
}
},
"required": [
@@ -40,9 +48,9 @@
}
},
"required": [
"reject"
"granular"
],
"title": "RejectAskForApproval",
"title": "GranularAskForApproval",
"type": "object"
}
]

View File

@@ -488,6 +488,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"TextElement": {
"properties": {
"byteRange": {
@@ -865,6 +877,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -872,6 +891,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -488,6 +488,18 @@
}
]
},
"ReasoningEffort": {
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
"enum": [
"none",
"minimal",
"low",
"medium",
"high",
"xhigh"
],
"type": "string"
},
"TextElement": {
"properties": {
"byteRange": {
@@ -865,6 +877,13 @@
"description": "Unique identifier for this collab tool call.",
"type": "string"
},
"model": {
"description": "Model requested for the spawned agent, when applicable.",
"type": [
"string",
"null"
]
},
"prompt": {
"description": "Prompt text sent as part of the collab tool call, when available.",
"type": [
@@ -872,6 +891,17 @@
"null"
]
},
"reasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
],
"description": "Reasoning effort requested for the spawned agent, when applicable."
},
"receiverThreadIds": {
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
"items": {

View File

@@ -33,4 +33,4 @@
],
"title": "WindowsSandboxSetupStartParams",
"type": "object"
}
}

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type AgentMessageContentDeltaEvent = { thread_id: string, turn_id: string, item_id: string, delta: string, };

View File

@@ -1,21 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentMessageContent } from "./AgentMessageContent";
import type { MessagePhase } from "./MessagePhase";
/**
* Assistant-authored message payload used in turn-item streams.
*
* `phase` is optional because not all providers/models emit it. Consumers
* should use it when present, but retain legacy completion semantics when it
* is `None`.
*/
export type AgentMessageItem = { id: string, content: Array<AgentMessageContent>,
/**
* Optional phase metadata carried through from `ResponseItem::Message`.
*
* This is currently used by TUI rendering to distinguish mid-turn
* commentary from a final answer and avoid status-indicator jitter.
*/
phase?: MessagePhase, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type AgentReasoningRawContentDeltaEvent = { delta: string, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type AgentReasoningRawContentEvent = { text: string, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type AgentReasoningSectionBreakEvent = { item_id: string, summary_index: bigint, };

View File

@@ -1,8 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Agent lifecycle status, derived from emitted events.
*/
export type AgentStatus = "pending_init" | "running" | { "completed": string | null } | { "errored": string } | "shutdown" | "not_found";

View File

@@ -1,23 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { FileChange } from "./FileChange";
export type ApplyPatchApprovalRequestEvent = {
/**
* Responses API call id for the associated patch apply call, if available.
*/
call_id: string,
/**
* Turn ID that this patch belongs to.
* Uses `#[serde(default)]` for backwards compatibility with older senders.
*/
turn_id: string, changes: { [key in string]?: FileChange },
/**
* Optional explanatory reason (e.g. request for extra write access).
*/
reason: string | null,
/**
* When set, the agent is asking the user to allow writes under this root for the remainder of the session.
*/
grant_root: string | null, };

View File

@@ -1,10 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { RejectConfig } from "./RejectConfig";
/**
* Determines the conditions under which the user is consulted to approve
* running the command proposed by Codex.
*/
export type AskForApproval = "untrusted" | "on-failure" | "on-request" | { "reject": RejectConfig } | "never";

View File

@@ -1,13 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ByteRange = {
/**
* Start byte offset (inclusive) within the UTF-8 text buffer.
*/
start: number,
/**
* End byte offset (exclusive) within the UTF-8 text buffer.
*/
end: number, };

View File

@@ -1,9 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "./serde_json/JsonValue";
/**
* The server's response to a tool call.
*/
export type CallToolResult = { content: Array<JsonValue>, structuredContent?: JsonValue, isError?: boolean, _meta?: JsonValue, };

View File

@@ -27,6 +27,8 @@ import type { McpServerOauthLoginParams } from "./v2/McpServerOauthLoginParams";
import type { ModelListParams } from "./v2/ModelListParams";
import type { PluginInstallParams } from "./v2/PluginInstallParams";
import type { PluginListParams } from "./v2/PluginListParams";
import type { PluginReadParams } from "./v2/PluginReadParams";
import type { PluginUninstallParams } from "./v2/PluginUninstallParams";
import type { ReviewStartParams } from "./v2/ReviewStartParams";
import type { SkillsConfigWriteParams } from "./v2/SkillsConfigWriteParams";
import type { SkillsListParams } from "./v2/SkillsListParams";
@@ -53,4 +55,4 @@ import type { WindowsSandboxSetupStartParams } from "./v2/WindowsSandboxSetupSta
/**
* Request from the client to the server.
*/
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, };
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "plugin/read", id: RequestId, params: PluginReadParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "plugin/uninstall", id: RequestId, params: PluginUninstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, };

View File

@@ -1,8 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Codex errors that we expose to clients.
*/
export type CodexErrorInfo = "context_window_exceeded" | "usage_limit_exceeded" | "server_overloaded" | { "http_connection_failed": { http_status_code: number | null, } } | { "response_stream_connection_failed": { http_status_code: number | null, } } | "internal_server_error" | "unauthorized" | "bad_request" | "sandbox_error" | { "response_stream_disconnected": { http_status_code: number | null, } } | { "response_too_many_failed_attempts": { http_status_code: number | null, } } | "thread_rollback_failed" | "other";

View File

@@ -1,23 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";
export type CollabAgentInteractionBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Prompt sent from the sender to the receiver. Can be empty to prevent CoT
* leaking at the beginning.
*/
prompt: string, };

View File

@@ -1,36 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";
export type CollabAgentInteractionEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Optional nickname assigned to the receiver agent.
*/
receiver_agent_nickname?: string | null,
/**
* Optional role assigned to the receiver agent.
*/
receiver_agent_role?: string | null,
/**
* Prompt sent from the sender to the receiver. Can be empty to prevent CoT
* leaking at the beginning.
*/
prompt: string,
/**
* Last known status of the receiver agent reported to the sender agent.
*/
status: AgentStatus, };

View File

@@ -1,18 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";
export type CollabAgentRef = {
/**
* Thread ID of the receiver/new agent.
*/
thread_id: ThreadId,
/**
* Optional nickname assigned to an AgentControl-spawned sub-agent.
*/
agent_nickname?: string | null,
/**
* Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.
*/
agent_role?: string | null, };

View File

@@ -1,19 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";
export type CollabAgentSpawnBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
* beginning.
*/
prompt: string, };

View File

@@ -1,36 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";
export type CollabAgentSpawnEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the newly spawned agent, if it was created.
*/
new_thread_id: ThreadId | null,
/**
* Optional nickname assigned to the new agent.
*/
new_agent_nickname?: string | null,
/**
* Optional role assigned to the new agent.
*/
new_agent_role?: string | null,
/**
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
* beginning.
*/
prompt: string,
/**
* Last known status of the new agent reported to the sender agent.
*/
status: AgentStatus, };

View File

@@ -1,23 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";
export type CollabAgentStatusEntry = {
/**
* Thread ID of the receiver/new agent.
*/
thread_id: ThreadId,
/**
* Optional nickname assigned to an AgentControl-spawned sub-agent.
*/
agent_nickname?: string | null,
/**
* Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.
*/
agent_role?: string | null,
/**
* Last known status of the agent.
*/
status: AgentStatus, };

View File

@@ -1,18 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";
export type CollabCloseBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId, };

View File

@@ -1,32 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";
export type CollabCloseEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Optional nickname assigned to the receiver agent.
*/
receiver_agent_nickname?: string | null,
/**
* Optional role assigned to the receiver agent.
*/
receiver_agent_role?: string | null,
/**
* Last known status of the receiver agent reported to the sender agent before
* the close.
*/
status: AgentStatus, };

View File

@@ -1,26 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";
export type CollabResumeBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Optional nickname assigned to the receiver agent.
*/
receiver_agent_nickname?: string | null,
/**
* Optional role assigned to the receiver agent.
*/
receiver_agent_role?: string | null, };

View File

@@ -1,32 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";
export type CollabResumeEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Optional nickname assigned to the receiver agent.
*/
receiver_agent_nickname?: string | null,
/**
* Optional role assigned to the receiver agent.
*/
receiver_agent_role?: string | null,
/**
* Last known status of the receiver agent reported to the sender agent after
* resume.
*/
status: AgentStatus, };

View File

@@ -1,23 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { CollabAgentRef } from "./CollabAgentRef";
import type { ThreadId } from "./ThreadId";
export type CollabWaitingBeginEvent = {
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receivers.
*/
receiver_thread_ids: Array<ThreadId>,
/**
* Optional nicknames/roles for receivers.
*/
receiver_agents?: Array<CollabAgentRef>,
/**
* ID of the waiting call.
*/
call_id: string, };

View File

@@ -1,24 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { CollabAgentStatusEntry } from "./CollabAgentStatusEntry";
import type { ThreadId } from "./ThreadId";
export type CollabWaitingEndEvent = {
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* ID of the waiting call.
*/
call_id: string,
/**
* Optional receiver metadata paired with final statuses.
*/
agent_statuses?: Array<CollabAgentStatusEntry>,
/**
* Last known status of the receiver agents reported to the sender agent.
*/
statuses: { [key in ThreadId]?: AgentStatus }, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type CreditsSnapshot = { has_credits: boolean, unlimited: boolean, balance: string | null, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type CustomPrompt = { name: string, path: string, content: string, description: string | null, argument_hint: string | null, };

View File

@@ -1,13 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DeprecationNoticeEvent = {
/**
* Concise summary of what is deprecated.
*/
summary: string,
/**
* Optional extra guidance, such as migration steps or rationale.
*/
details: string | null, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DynamicToolCallOutputContentItem = { "type": "inputText", text: string, } | { "type": "inputImage", imageUrl: string, };

View File

@@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "./serde_json/JsonValue";
export type DynamicToolCallRequest = { callId: string, turnId: string, tool: string, arguments: JsonValue, };

View File

@@ -1,39 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DynamicToolCallOutputContentItem } from "./DynamicToolCallOutputContentItem";
import type { JsonValue } from "./serde_json/JsonValue";
export type DynamicToolCallResponseEvent = {
/**
* Identifier for the corresponding DynamicToolCallRequest.
*/
call_id: string,
/**
* Turn ID that this dynamic tool call belongs to.
*/
turn_id: string,
/**
* Dynamic tool name.
*/
tool: string,
/**
* Dynamic tool call arguments.
*/
arguments: JsonValue,
/**
* Dynamic tool response content items.
*/
content_items: Array<DynamicToolCallOutputContentItem>,
/**
* Whether the tool call succeeded.
*/
success: boolean,
/**
* Optional error text when the tool call failed before producing a response.
*/
error: string | null,
/**
* The duration of the dynamic tool call.
*/
duration: string, };

View File

@@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { JsonValue } from "./serde_json/JsonValue";
export type ElicitationRequest = { "mode": "form", _meta?: JsonValue, message: string, requested_schema: JsonValue, } | { "mode": "url", _meta?: JsonValue, message: string, url: string, elicitation_id: string, };

View File

@@ -1,10 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ElicitationRequest } from "./ElicitationRequest";
export type ElicitationRequestEvent = {
/**
* Turn ID that this elicitation belongs to, when known.
*/
turn_id?: string, server_name: string, id: string | number, request: ElicitationRequest, };

View File

@@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { CodexErrorInfo } from "./CodexErrorInfo";
export type ErrorEvent = { message: string, codex_error_info: CodexErrorInfo | null, };

View File

@@ -1,84 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentMessageContentDeltaEvent } from "./AgentMessageContentDeltaEvent";
import type { AgentMessageDeltaEvent } from "./AgentMessageDeltaEvent";
import type { AgentMessageEvent } from "./AgentMessageEvent";
import type { AgentReasoningDeltaEvent } from "./AgentReasoningDeltaEvent";
import type { AgentReasoningEvent } from "./AgentReasoningEvent";
import type { AgentReasoningRawContentDeltaEvent } from "./AgentReasoningRawContentDeltaEvent";
import type { AgentReasoningRawContentEvent } from "./AgentReasoningRawContentEvent";
import type { AgentReasoningSectionBreakEvent } from "./AgentReasoningSectionBreakEvent";
import type { ApplyPatchApprovalRequestEvent } from "./ApplyPatchApprovalRequestEvent";
import type { BackgroundEventEvent } from "./BackgroundEventEvent";
import type { CollabAgentInteractionBeginEvent } from "./CollabAgentInteractionBeginEvent";
import type { CollabAgentInteractionEndEvent } from "./CollabAgentInteractionEndEvent";
import type { CollabAgentSpawnBeginEvent } from "./CollabAgentSpawnBeginEvent";
import type { CollabAgentSpawnEndEvent } from "./CollabAgentSpawnEndEvent";
import type { CollabCloseBeginEvent } from "./CollabCloseBeginEvent";
import type { CollabCloseEndEvent } from "./CollabCloseEndEvent";
import type { CollabResumeBeginEvent } from "./CollabResumeBeginEvent";
import type { CollabResumeEndEvent } from "./CollabResumeEndEvent";
import type { CollabWaitingBeginEvent } from "./CollabWaitingBeginEvent";
import type { CollabWaitingEndEvent } from "./CollabWaitingEndEvent";
import type { ContextCompactedEvent } from "./ContextCompactedEvent";
import type { DeprecationNoticeEvent } from "./DeprecationNoticeEvent";
import type { DynamicToolCallRequest } from "./DynamicToolCallRequest";
import type { DynamicToolCallResponseEvent } from "./DynamicToolCallResponseEvent";
import type { ElicitationRequestEvent } from "./ElicitationRequestEvent";
import type { ErrorEvent } from "./ErrorEvent";
import type { ExecApprovalRequestEvent } from "./ExecApprovalRequestEvent";
import type { ExecCommandBeginEvent } from "./ExecCommandBeginEvent";
import type { ExecCommandEndEvent } from "./ExecCommandEndEvent";
import type { ExecCommandOutputDeltaEvent } from "./ExecCommandOutputDeltaEvent";
import type { ExitedReviewModeEvent } from "./ExitedReviewModeEvent";
import type { GetHistoryEntryResponseEvent } from "./GetHistoryEntryResponseEvent";
import type { ImageGenerationBeginEvent } from "./ImageGenerationBeginEvent";
import type { ImageGenerationEndEvent } from "./ImageGenerationEndEvent";
import type { ItemCompletedEvent } from "./ItemCompletedEvent";
import type { ItemStartedEvent } from "./ItemStartedEvent";
import type { ListCustomPromptsResponseEvent } from "./ListCustomPromptsResponseEvent";
import type { ListRemoteSkillsResponseEvent } from "./ListRemoteSkillsResponseEvent";
import type { ListSkillsResponseEvent } from "./ListSkillsResponseEvent";
import type { McpListToolsResponseEvent } from "./McpListToolsResponseEvent";
import type { McpStartupCompleteEvent } from "./McpStartupCompleteEvent";
import type { McpStartupUpdateEvent } from "./McpStartupUpdateEvent";
import type { McpToolCallBeginEvent } from "./McpToolCallBeginEvent";
import type { McpToolCallEndEvent } from "./McpToolCallEndEvent";
import type { ModelRerouteEvent } from "./ModelRerouteEvent";
import type { PatchApplyBeginEvent } from "./PatchApplyBeginEvent";
import type { PatchApplyEndEvent } from "./PatchApplyEndEvent";
import type { PlanDeltaEvent } from "./PlanDeltaEvent";
import type { RawResponseItemEvent } from "./RawResponseItemEvent";
import type { RealtimeConversationClosedEvent } from "./RealtimeConversationClosedEvent";
import type { RealtimeConversationRealtimeEvent } from "./RealtimeConversationRealtimeEvent";
import type { RealtimeConversationStartedEvent } from "./RealtimeConversationStartedEvent";
import type { ReasoningContentDeltaEvent } from "./ReasoningContentDeltaEvent";
import type { ReasoningRawContentDeltaEvent } from "./ReasoningRawContentDeltaEvent";
import type { RemoteSkillDownloadedEvent } from "./RemoteSkillDownloadedEvent";
import type { RequestUserInputEvent } from "./RequestUserInputEvent";
import type { ReviewRequest } from "./ReviewRequest";
import type { SessionConfiguredEvent } from "./SessionConfiguredEvent";
import type { StreamErrorEvent } from "./StreamErrorEvent";
import type { TerminalInteractionEvent } from "./TerminalInteractionEvent";
import type { ThreadNameUpdatedEvent } from "./ThreadNameUpdatedEvent";
import type { ThreadRolledBackEvent } from "./ThreadRolledBackEvent";
import type { TokenCountEvent } from "./TokenCountEvent";
import type { TurnAbortedEvent } from "./TurnAbortedEvent";
import type { TurnCompleteEvent } from "./TurnCompleteEvent";
import type { TurnDiffEvent } from "./TurnDiffEvent";
import type { TurnStartedEvent } from "./TurnStartedEvent";
import type { UndoCompletedEvent } from "./UndoCompletedEvent";
import type { UndoStartedEvent } from "./UndoStartedEvent";
import type { UpdatePlanArgs } from "./UpdatePlanArgs";
import type { UserMessageEvent } from "./UserMessageEvent";
import type { ViewImageToolCallEvent } from "./ViewImageToolCallEvent";
import type { WarningEvent } from "./WarningEvent";
import type { WebSearchBeginEvent } from "./WebSearchBeginEvent";
import type { WebSearchEndEvent } from "./WebSearchEndEvent";
/**
* Response event from the agent
* NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.
*/
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "image_generation_begin" } & ImageGenerationBeginEvent | { "type": "image_generation_end" } & ImageGenerationEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;

View File

@@ -1,62 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ExecPolicyAmendment } from "./ExecPolicyAmendment";
import type { NetworkApprovalContext } from "./NetworkApprovalContext";
import type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment";
import type { ParsedCommand } from "./ParsedCommand";
import type { PermissionProfile } from "./PermissionProfile";
import type { ReviewDecision } from "./ReviewDecision";
export type ExecApprovalRequestEvent = {
/**
* Identifier for the associated command execution item.
*/
call_id: string,
/**
* Identifier for this specific approval callback.
*
* When absent, the approval is for the command item itself (`call_id`).
* This is present for subcommand approvals (via execve intercept).
*/
approval_id?: string,
/**
* Turn ID that this command belongs to.
* Uses `#[serde(default)]` for backwards compatibility.
*/
turn_id: string,
/**
* The command to be executed.
*/
command: Array<string>,
/**
* The command's working directory.
*/
cwd: string,
/**
* Optional human-readable reason for the approval (e.g. retry without sandbox).
*/
reason: string | null,
/**
* Optional network context for a blocked request that can be approved.
*/
network_approval_context?: NetworkApprovalContext,
/**
* Proposed execpolicy amendment that can be applied to allow future runs.
*/
proposed_execpolicy_amendment?: ExecPolicyAmendment,
/**
* Proposed network policy amendments (for example allow/deny this host in future).
*/
proposed_network_policy_amendments?: Array<NetworkPolicyAmendment>,
/**
* Optional additional filesystem permissions requested for this command.
*/
additional_permissions?: PermissionProfile,
/**
* Ordered list of decisions the client may present for this prompt.
*
* When absent, clients should derive the legacy default set from the
* other fields on this request.
*/
available_decisions?: Array<ReviewDecision>, parsed_cmd: Array<ParsedCommand>, };

View File

@@ -1,35 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ExecCommandSource } from "./ExecCommandSource";
import type { ParsedCommand } from "./ParsedCommand";
export type ExecCommandBeginEvent = {
/**
* Identifier so this can be paired with the ExecCommandEnd event.
*/
call_id: string,
/**
* Identifier for the underlying PTY process (when available).
*/
process_id?: string,
/**
* Turn ID that this command belongs to.
*/
turn_id: string,
/**
* The command to be executed.
*/
command: Array<string>,
/**
* The command's working directory if not the default cwd for the agent.
*/
cwd: string, parsed_cmd: Array<ParsedCommand>,
/**
* Where the command originated. Defaults to Agent for backward compatibility.
*/
source: ExecCommandSource,
/**
* Raw input sent to a unified exec session (if this is an interaction event).
*/
interaction_input?: string, };

View File

@@ -1,64 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ExecCommandSource } from "./ExecCommandSource";
import type { ExecCommandStatus } from "./ExecCommandStatus";
import type { ParsedCommand } from "./ParsedCommand";
export type ExecCommandEndEvent = {
/**
* Identifier for the ExecCommandBegin that finished.
*/
call_id: string,
/**
* Identifier for the underlying PTY process (when available).
*/
process_id?: string,
/**
* Turn ID that this command belongs to.
*/
turn_id: string,
/**
* The command that was executed.
*/
command: Array<string>,
/**
* The command's working directory if not the default cwd for the agent.
*/
cwd: string, parsed_cmd: Array<ParsedCommand>,
/**
* Where the command originated. Defaults to Agent for backward compatibility.
*/
source: ExecCommandSource,
/**
* Raw input sent to a unified exec session (if this is an interaction event).
*/
interaction_input?: string,
/**
* Captured stdout
*/
stdout: string,
/**
* Captured stderr
*/
stderr: string,
/**
* Captured aggregated output
*/
aggregated_output: string,
/**
* The command's exit code.
*/
exit_code: number,
/**
* The duration of the command execution.
*/
duration: string,
/**
* Formatted output from the command, as seen by the model.
*/
formatted_output: string,
/**
* Completion status for this command execution.
*/
status: ExecCommandStatus, };

View File

@@ -1,18 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ExecOutputStream } from "./ExecOutputStream";
export type ExecCommandOutputDeltaEvent = {
/**
* Identifier for the ExecCommandBegin that produced this chunk.
*/
call_id: string,
/**
* Which stream produced this chunk.
*/
stream: ExecOutputStream,
/**
* Raw bytes from the stream (may not be valid UTF-8).
*/
chunk: string, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ExecCommandSource = "agent" | "user_shell" | "unified_exec_startup" | "unified_exec_interaction";

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ExecCommandStatus = "completed" | "failed" | "declined";

View File

@@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ReviewOutputEvent } from "./ReviewOutputEvent";
export type ExitedReviewModeEvent = { review_output: ReviewOutputEvent | null, };

View File

@@ -1,6 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AbsolutePathBuf } from "./AbsolutePathBuf";
export type FileSystemPermissions = { read: Array<AbsolutePathBuf> | null, write: Array<AbsolutePathBuf> | null, };

View File

@@ -1,10 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { HistoryEntry } from "./HistoryEntry";
export type GetHistoryEntryResponseEvent = { offset: number, log_id: bigint,
/**
* The entry at the requested offset, if available and parseable.
*/
entry: HistoryEntry | null, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type HistoryEntry = { conversation_id: string, ts: bigint, text: string, };

View File

@@ -1,5 +0,0 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ImageGenerationBeginEvent = { call_id: string, };

Some files were not shown because too many files have changed in this diff Show More