Commit Graph
34 Commits
Author SHA1 Message Date
joeflorencio-openai 9695e71519 Add turn-scoped settings updates to the app server (#40656)
## What changed

- Add the experimental `turn/settings/update` method for changing `model`,
  `effort`, `summary`, and `serviceTier` on a specific live turn without
  changing future turns.
- Report whether the update was applied or the target turn was unavailable,
  and reject unsupported fields, disabled feature use, unsafe model changes,
  and direct updates to parent-owned subagents.
- Document the method's feature requirements, null handling, and limits.

## Testing

- Cover current-turn and future-turn isolation, rejected and unavailable
  targets, feature and capability gates, saved threads, and subagent ownership.

GitOrigin-RevId: 18440f6d7ee5fcd06ae23bd41b22c492b62bb2b5
2026-08-25 17:55:50 +00:00
Martin Au-Yeung ee46c5ba0e Negotiate MCP extensions per app-server session (#36910)
## Why

App-server clients need to advertise structured MCP extension settings, including supported MCP App UI MIME types, rather than only opting into OpenAI form elicitation with a boolean.

## What changed

- Add an `extensions` map to initialize capabilities and preserve `mcpServerOpenaiFormElicitation` as a legacy alias for `openai/form`.
- Capture the declared extension profile when a thread is started, resumed, or forked, propagate it to subagents, and advertise it to downstream MCP servers during initialization.
- Keep the profile stable for the lifetime of the loaded session instead of changing it on later turns or direct tool calls.

## Testing

- Cover extension conversion, downstream MCP initialization, session isolation, legacy form support, and subagent inheritance.

GitOrigin-RevId: fbcedbb74ce788e574b0f884a4c45c4cedb9de54
2026-08-04 15:23:43 +00:00
jiayuhuang-openai 6751b54cae Add a realtime delegation acknowledgement control (#36413)
## What changed

- Add the optional `delegationAckFiller` field to `thread/realtime/start`.
- Forward explicit `true` or `false` values to V3 Frameless Bidi session payloads as `delegation.ack_filler`; leave the field absent when unspecified so the Realtime API default is preserved.
- Document that V1 and V2 ignore this setting.

## Testing

- Cover both boolean values in Frameless Bidi serialization and verify the WebRTC V3 session creation payload.

GitOrigin-RevId: 9fe8efd14e42738c3e86e3e9a8af81d0f4521244
2026-08-01 01:17:26 +00:00
guinness-oai 670f69416b Allow custom Codex instructions for realtime transitions (#36408)
## What changed

- Add optional `realtimeStartInstructions` and `realtimeEndInstructions` fields to `thread/realtime/start`.
- Apply the instructions when Codex enters and leaves realtime mode, while preserving the existing defaults when either field is omitted.
- Limit each field to 8,192 estimated tokens.

## Testing

- Cover custom entry and exit instructions across realtime state transitions.
- Cover token-limit validation for both fields.

GitOrigin-RevId: b9cfa1ff22e084d8a6b2ed56bd27d95ffdd6b6bd
2026-07-31 23:51:33 +00:00
jiayuhuang-openai 4ebd976312 Support configurable realtime BEM channel prefixes (#34816)
## What changed

- Route realtime V3 `bemTags` handoffs using `[ANALYSIS]`, `[COMMENTARY]`, and `[FINAL]` prefixes by default.
- Add `codexResponseHandoffChannelPrefixes` to realtime start requests so clients can replace the accepted prefixes for individual channels. Each channel may accept multiple prefixes, and omitted channels retain their defaults.
- Apply the configured prefixes to both complete and streamed handoff messages, without treating empty prefixes as matches.

## Testing

- Cover request deserialization, default and custom routing, partial streamed prefixes, empty-prefix handling, and end-to-end V3 handoffs.

GitOrigin-RevId: d0aef50aa71362a5beef2c6f6d28b8633da4e529
2026-07-22 19:43:35 +00:00
pakrym-oai 10cc57c95c Simplify app-server integration test setup (#34786)
## What changed

- Add typed helpers for initialized app-server instances, JSON-RPC requests,
  responses, notifications, and thread startup.
- Add a composable `MockResponsesConfig` builder while preserving the existing
  mock config writers.
- Migrate the app-server integration suite to the shared helpers, removing
  repeated request ID management, deserialization, initialization, and config
  assembly.

## Testing

- Add unit coverage for composing mock provider, feature, and extra config, and
  for compatibility of the existing mock config writer.

GitOrigin-RevId: 62da177c1d6e8299400de64bd6766567bf1ba3d8
2026-07-22 16:30:12 +00:00
jiayuhuang-openai 312caf176a Seed realtime V3 sessions with initial text items (#34067)
## What changed

- Add an optional `initialItems` field to `thread/realtime/start` for seeding
  realtime V3 session history with `user`, `developer`, and `assistant` text.
- Encode the items in Frameless Bidi session bootstrap payloads for websocket
  and WebRTC transports while preserving existing payloads when the list is
  omitted or empty.
- Reject non-empty initial items for V1 and V2, more than 128 items, any item
  over 8,192 estimated tokens, or a combined total over 8,192 estimated tokens.

## Testing

- Cover protocol serialization, app-server forwarding, websocket and WebRTC
  payloads, empty-list compatibility, version checks, and size limits.

GitOrigin-RevId: 09af367f9a07543e3f8d59b7fa5387f932dc5a6a
2026-07-18 20:59:57 +00:00
jiayuhuang-openai 025db22058 Route realtime V3 handoffs by response channel (#33903)
## What changed

- Add `codexResponseHandoffMode` to `thread/realtime/start` for V3 sessions, with `thinking` as the default and `commentary` and `bemTags` routing modes.
- Map BEM `analysis` and `commentary` output to the commentary channel and `final` output to the speakable channel, while preserving the original BEM envelope. Unrecognized output falls back to speakable.
- Mark explicit speech appends as speakable and stop adding the legacy `"Agent Final Message"` prefix to V3 handoffs. V1 and V2 continue to ignore the new setting.

## Testing

- Cover channel selection for every routing mode, streamed BEM header parsing, fallback behavior, explicit speech, and V1 compatibility.

GitOrigin-RevId: 1974578257488f2914b252c9c1990ba38831c96b
2026-07-17 21:12:40 +00:00
jiayuhuang-openai b03545b5b8 Stream realtime V3 Codex handoff output (#33856)
## What changed

- Stream V3 agent message deltas to `delegation.context.append` at 200 ms intervals instead of waiting for each completed message.
- Send commentary without a prefix and label final or phase-less V1/V3 output with `"Agent Final Message":`.
- Bound streamed output while preserving both its beginning and final tail when truncation is required.
- Remove `codexResponseHandoffPrefix` from `thread/realtime/start`; unknown fields from older clients remain ignored.

## Testing

- Cover incremental V3 commentary and final output, Unicode-safe truncation, V1/V3 phase labeling, and legacy request compatibility.

GitOrigin-RevId: 633c18b5eb9a4f5756a264b63b7bfc185b073951
2026-07-17 15:54:33 +00:00
Adam Perry @ OpenAI 5c7624a69e test: migrate app-server v2 starts to auto env (#31614)
## Why

We should be running as many integrations tests as possible against the
split cross-OS configuration.

## What

- migrate eligible thread starts and builders to auto env
- keep explicit custom/local-executor cases local with rationale
comments
- keep auto-env coverage where possible and add narrow `TODO(anp)` skips
for fixtures that are not target-native yet
2026-07-08 14:13:59 -07:00
Adam Perry @ OpenAI dbd2df27d1 test: migrate TestAppServer callers to builder (#31451)
## Why

Keep the TestAppServer builder API change reviewable by moving the
repository-wide caller migration into a mechanical follow-up.

## What

- replace TestAppServer constructor callsites with equivalent builder
chains
- preserve each caller's automatic-environment, args, program, env,
managed-config, plugin-startup, and JSON-logging behavior
- make no TestAppServer implementation changes

## Validation

- cargo check -p codex-app-server --tests

## Cleanup stack

1. [#31425 test: add TestAppServer
builder](https://github.com/openai/codex/pull/31425)
2. [#31451 test: migrate TestAppServer callers to
builder](https://github.com/openai/codex/pull/31451)
3. [#31452 test: remove TestAppServer
constructors](https://github.com/openai/codex/pull/31452)
2026-07-08 00:15:49 +00:00
guinness-oai c976741124 [codex] Flush trailing realtime transcript tail (#29918)
## Why

A realtime session can end after more transcript has accumulated than
was included in its last handoff. That tail already lives in core's
active transcript state, but the stop path aborted the realtime
input/fanout tasks before routing it, so the final bit of the
conversation could disappear before `thread/realtime/closed`.

This behavior is still being evaluated, so clients must opt in per
realtime session. Omitted or false leaves shutdown behavior unchanged.

## What changed

- Add optional `flushTranscriptTailOnSessionEnd` to
`thread/realtime/start`, defaulting to false in app-server.
- Expose an idempotent `take_transcript_tail()` from the existing active
transcript state using `last_handoff_entry_count`.
- When enabled, let shutdown cancel the input owner cleanly and publish
at most one final existing `<realtime_delegation>` with the remaining
text in `<transcript_delta>`.
- Have the existing fanout drain already-parsed events before routing
that final delegation, so a queued handoff wins first and is not
duplicated in the tail.
- Flush realtime shutdown before ordinary session task abort during core
cleanup.

## Validation

- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
realtime_conversation_stop_emits_closed_notification`
- `just test -p codex-core conversation_transport_close_`
- `just test -p codex-core
conversation_close_routes_only_remaining_transcript_tail_once`
- scoped `just fix` for `codex-app-server-protocol`, `codex-app-server`,
`codex-protocol`, and `codex-core`
- `just fmt`
2026-07-06 14:12:54 -07:00
Peter Bakkum 8e7c213f8f Always use AVAS for realtime WebRTC calls (#28856)
## Summary

- Remove the realtime `architecture` selector from core protocol,
app-server protocol, config parsing, generated schemas, and callers.
- Always create WebRTC realtime calls with the AVAS query params:
`intent=quicksilver&architecture=avas`.
- Keep direct websocket realtime behavior on the existing config/default
path, while WebRTC starts without an explicit version now default to
realtime v1 because AVAS requires v1.

## Notes

- WebRTC realtime now means AVAS. If a caller explicitly asks to start
WebRTC with realtime v2, Codex rejects that request because the AVAS
WebRTC path only supports realtime v1. Websocket realtime is separate
and can still use realtime v2.
- The old `[realtime] architecture = "realtimeapi" | "avas"` config knob
is removed. Local configs that still set it will need to delete that
line.
- Some app-server tests that were only trying to exercise realtime v2
protocol behavior now use websocket transport, because WebRTC is
intentionally locked to AVAS/v1. Separate WebRTC tests cover the AVAS
query params, v1 startup, SDP flow, and sideband join.

## Validation

- Merged fresh `origin/main` at `83e6a786a2`.
- `just fmt`
- `just write-config-schema`
- `just write-app-server-schema`
- `git diff --check`
- `just test -p codex-api -p codex-core -p codex-app-server-protocol -p
codex-app-server realtime` (176 passed)
- `just test -p codex-protocol -p codex-config` (413 passed)
2026-06-18 19:11:21 -05:00
Gabriel Peal 21a599fa56 Support openai/form extended form elicitations (#27500)
# Summary
Allow App Server clients to opt into `openai/form` MCP elicitations.
2026-06-18 11:54:49 -07:00
jiayuhuang-openai 683bd170dc [codex] control automatic realtime handoff delivery (#27986)
## What

Built on the realtime speech-control plumbing merged in #27917.

- Add optional `codexResponseHandoffPrefix` to `thread/realtime/start`.
- Apply that prefix only to automatic V1 commentary sent through
`conversation.handoff.append`; final answers remain unprefixed.
- Add opt-in `clientManagedHandoffs`. When true, core suppresses
automatic response handoffs and completion output so delivery is
controlled by explicit client append APIs.
- Preserve existing automatic behavior by default.
`codexResponsesAsItems: true` continues to select item routing when
client-managed mode is disabled.

## Why

Voice clients need two delivery policies: automatic background context
with silent commentary instructions and fully client-owned handoffs.
Phase-aware prefixing keeps routine commentary silent without
suppressing the final answer, while client-managed mode lets an app
decide exactly which updates to append.

## Validation

- `just fmt`
- `cargo test -p codex-app-server-protocol
serialize_thread_realtime_start`
- `RUST_MIN_STACK=16777216 cargo test -p codex-core --test all
conversation_handoff_persists_across_item_done_until_turn_complete`
- `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all
webrtc_v1_client_managed_handoffs_disable_automatic_output`
- `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all
webrtc_v1_final_automatic_handoff_omits_silent_prefix`
- `cargo build -p codex-cli --bin codex`
- Local Codex Apps compatibility check: 43 focused webview tests passed,
and a live voice session routed through the source-built app-server.

The explicit `RUST_MIN_STACK` avoids a macOS Tokio test-worker stack
overflow seen with the default test environment.
2026-06-18 02:22:29 +00:00
guinness-oai d5b4b98370 Add a toggle for realtime startup context (#28405)
## Summary
- Add `includeStartupContext` to realtime start requests so callers can
explicitly skip Codex startup context while keeping the backend prompt
- Thread the new flag through protocol types, request processing, and
realtime session config
- Update app-server docs and coverage for the new default and opt-out
behavior

## Testing
- Added protocol serialization coverage for `includeStartupContext`
- Added realtime integration coverage for starting a session with
startup context disabled
2026-06-15 17:14:22 -07:00
guinness-oai 1d8ff89aa3 Add realtime speech append control (#27917)
## Why

Realtime voice harness tuning needs app-side control over what backend
Codex text is spoken. Backend orchestrator text is written for a reading
UI, so automatically speaking every preamble, progress update, or final
assistant message can make the realtime voice model too chatty.

For experimentation, clients need two simple controls: keep app/client
text-item injection on the existing item-create path, and add an
explicit speakable path that app code can call only when it wants
realtime to speak. Automatic Codex output also needs an opt-in way to
switch from the protocol's default speakable path to regular realtime
items, with a caller-provided prefix so prompt wording can be tuned
outside core.

The default remains unchanged: if a client omits the new start fields
and never calls `appendSpeech`, automatic backend output continues down
the existing speakable path for the selected realtime protocol.

## What Changed

- Adds experimental `thread/realtime/appendSpeech` for app-provided
speakable text.
- Keeps existing `thread/realtime/appendText` as the item-create API for
app-provided realtime text items.
- Adds `codexResponsesAsItems` / `codex_responses_as_items` on
`thread/realtime/start` to send automatic Codex responses with
`conversation.item.create` instead of the protocol's default speakable
output path.
- Adds `codexResponseItemPrefix` / `codex_response_item_prefix` so
clients can prepend experiment instructions to those automatic Codex
response items.
- Keeps literal `conversation.handoff.append` routing scoped to the v1
speakable path; v2 default speech uses its item/function-output plus
`response.create` behavior.
- Removes the earlier public silent-context API and hardcoded
silent-context prefix.
- Updates realtime tests to cover default automatic speakable behavior,
opt-in automatic item-create behavior, and explicit `appendSpeech`
behavior.

## Validation

- `cargo check -p codex-core -p codex-app-server -p codex-api`
- `just test -p codex-app-server realtime_conversation`
- `just test -p codex-core realtime_conversation` (50/51 passed in the
filtered parallel run; the lone failure passed when rerun in isolation)
- `just test -p codex-core
conversation_mirrors_assistant_message_text_to_realtime_handoff`
- `just test -p codex-api
e2e_connect_and_exchange_events_against_mock_ws_server`
- `just fix -p codex-core`
- `just fix -p codex-app-server`
- `cargo build -p codex-cli`
2026-06-15 16:15:58 -07:00
Peter Bakkum 6652e82dd0 realtime: add AVAS architecture override (#27720)
## Summary

Adds a `RealtimeConversationArchitecture` option for realtime
conversation startup, with `realtimeapi` as the default and `avas` as an
opt-in architecture.

The AVAS path is limited to realtime v1 conversational WebRTC starts,
and WebRTC call creation appends `intent=quicksilver&architecture=avas`
to `/v1/realtime/calls`. The existing sideband websocket still joins by
`call_id`.

This also exposes the per-session architecture override through
app-server v2 `thread/realtime/start` params and updates the config
schema for `[realtime].architecture`.

## Validation

- `just fmt`
- `just write-config-schema`
- `just test -p codex-api sends_avas_session_call_query_params`
- `just test -p codex-core -E
'test(~conversation_webrtc_start_uses_avas_architecture_query)'`
- `just test -p codex-core -E 'test(realtime_loads_from_config_toml)'`
- `just test -p codex-app-server-protocol -E
'test(~serialize_thread_realtime_start) |
test(generated_ts_optional_nullable_fields_only_in_params)'`
- `just test -p codex-app-server -E
'test(realtime_webrtc_start_emits_sdp_notification)'`
2026-06-12 18:11:13 +00:00
guinness-oai 4a3eac2144 Add per-session realtime model and version overrides (#24999)
## Why

Clients need to select a realtime session configuration for an
individual start without rewriting persisted configuration or restarting
the app-server process.

## What Changed

- Add optional `model` and `version` fields to `thread/realtime/start`
- Forward those optional values through the realtime start operation and
apply them only for that session
- Preserve existing configured/default behavior when the new fields are
omitted
- Update generated protocol schema and app-server documentation

## Validation

- Added/updated protocol serialization coverage for the new optional
request fields
- Added focused core coverage for a session override taking precedence
over configured realtime selection
- Added focused app-server coverage that a request override reaches the
realtime WebSocket handshake
2026-06-09 17:54:32 -07:00
Michael Bolin 6536841d89 fix: rename McpServer to TestAppServer (#25701)
This PR brought to you via VS Code rather than Codex...

- opened `codex-rs/app-server/tests/common/mcp_process.rs`
- put the cursor on `McpServer`
- hit `F2` and renamed the symbol to `TestAppServer`
- went to the file tree
- hit enter and renamed `mcp_process.rs` to `test_app_server.rs`
- ran **Save All Files** from the Command Palette
- ran `just fmt`

The End

(Admittedly, most of the local variables for `TestAppServer` are still
named `mcp`, though.)
2026-06-01 21:49:38 +00:00
Eric Traut 771a4e74ac Add thread/settings/update app-server API (#23502)
## Why

App-server clients need a way to update a thread's next-turn settings
without starting a turn, adding transcript content, or waiting for turn
lifecycle events. This gives settings UI a direct path for durable
thread settings while clients observe the eventual effective state
through a notification.

This is a simplified rework of PR
https://github.com/openai/codex/pull/22509. In particular, it changes
the `thread/settings/update` api to return immediately rather than
waiting and returning the effective (updated) thread settings. This
makes the new api consistent with `turn/start` and greatly reduces the
complexity of the implementation relative to the earlier attempt.

## What Changed

- Adds experimental `thread/settings/update` with partial-update request
fields and an empty acknowledgment response.
- Adds experimental `thread/settings/updated`, carrying full effective
`ThreadSettings` and scoped by `threadId` to subscribed clients for the
affected thread.
- Shares durable settings validation with `turn/start`, including
`sandboxPolicy` plus `permissions` rejection and `serviceTier: null`
clearing.
- Emits the same settings notification when `turn/start` overrides
change the stored effective thread settings.
- Regenerates app-server protocol schema fixtures and updates
`app-server/README.md`.
2026-05-20 11:03:20 -07:00
Jiaming ZhangandCodex 5f4d0ec343 [codex] request desktop attestation from app (#20619)
## Summary

TL;DR: teaches `codex-rs` / app-server to request a desktop-provided
attestation token and attach it as `x-oai-attestation` on the scoped
ChatGPT Codex request paths.

![DeviceCheck attestation
interface](https://raw.githubusercontent.com/openai/codex/dev/jm/devicecheck-diagram-assets/pr-assets/devicecheck-attestation-interface.png)

## Details

This PR teaches the Codex app-server runtime how to request and attach
an attestation token. It does not generate DeviceCheck tokens directly;
instead, it relies on the connected desktop app to advertise that it can
generate attestation and then asks that app for a fresh header value
when needed.

The flow is:

1. The Codex desktop app connects to app-server.
2. During `initialize`, the app can advertise that it supports
`requestAttestation`.
3. Before app-server calls selected ChatGPT Codex endpoints, it sends
the internal server request `attestation/generate` to the app.
4. app-server receives a pre-encoded header value back.
5. app-server forwards that value as `x-oai-attestation` on the scoped
outbound requests.

The code in this repo is mostly protocol and runtime plumbing: it adds
the app-server request/response shape, introduces an attestation
provider in core, wires that provider into Responses / compaction /
realtime setup paths, and covers the intended scoping with tests. The
signed macOS DeviceCheck generation remains owned by the desktop app PR.

## Related PR

- Codex desktop app implementation:
https://github.com/openai/openai/pull/878649

## Validation

<details>
<summary>Tests run</summary>

```sh
cargo test -p codex-app-server-protocol
cargo test -p codex-core attestation --lib
cargo test -p codex-app-server --lib attestation
```

Also ran:

```sh
just fix -p codex-core
just fix -p codex-app-server
just fix -p codex-app-server-protocol
just fmt
just write-app-server-schema
```

</details>

<details>
<summary>E2E DeviceCheck validation</summary>

First validated the signed desktop app boundary directly: launched a
packaged signed `Codex.app`, sent `attestation/generate`, decoded the
returned `v1.` attestation header, and validated the extracted
DeviceCheck token with `personal/jm/verify_devicecheck_token.py` using
bundle ID `com.openai.codex`. Apple returned `status_code: 200` and
`is_ok: true`.

Then ran the fuller app + app-server flow. The packaged `Codex.app`
launched a current-branch app-server via `CODEX_CLI_PATH`, and a local
MITM proxy intercepted outbound `chatgpt.com` traffic. The app-server
requested `attestation/generate` from the real Electron app process, and
the intercepted `/backend-api/codex/responses` traffic included
`x-oai-attestation` on both routes:

```text
GET  /backend-api/codex/responses  Upgrade: websocket  x-oai-attestation: present
POST /backend-api/codex/responses  Upgrade: none       x-oai-attestation: present
```

The captured header decoded to a DeviceCheck token that also validated
with Apple for `com.openai.codex` (`status_code: 200`, `is_ok: true`,
team `2DC432GLL2`).

</details>

---------

Co-authored-by: Codex <noreply@openai.com>
2026-05-08 12:36:02 -07:00
Ahmed IbrahimandCodex 8a97f3cf03 realtime: rename provider session ids (#20361)
## Summary

Codex is repurposing `session` to mean a thread group, so the realtime
provider session id should no longer use `session_id` / `sessionId` in
Codex-facing protocol payloads. This PR renames that provider-specific
field to `realtime_session_id` / `realtimeSessionId` and intentionally
breaks clients that still send the old field names.

## What Changed

- Renamed realtime provider session fields in `ConversationStartParams`,
`RealtimeConversationStartedEvent`, and `RealtimeEvent::SessionUpdated`.
- Renamed app-server v2 realtime request and notification fields to
`realtimeSessionId`.
- Removed legacy serde aliases for `session_id` / `sessionId`; clients
must send the new names.
- Propagated the rename through core realtime startup, app-server
adapters, codex-api websocket handling, and TUI realtime state.
- Regenerated app-server protocol schema/TypeScript outputs and updated
app-server README examples.
- Kept upstream Realtime API concepts unchanged: provider `session.id`
parsing and `x-session-id` headers still use the upstream wire names.

## Testing

- CI is running on the latest pushed commit.
- Earlier local verification on this PR:
  - `cargo test -p codex-protocol`
- `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-core
realtime_conversation`
  - `cargo test -p codex-app-server-protocol`
- `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-app-server
realtime_conversation`
- attempted `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-tui` (local
linker bus error while linking the test binary)

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-30 13:39:48 +03:00
Ahmed Ibrahim 2f6fc7c137 Add realtime output modality and transcript events (#17701)
- Add outputModality to thread/realtime/start and wire text/audio output
selection through app-server, core, API, and TUI.\n- Rename the realtime
transcript delta notification and add a separate transcript done
notification that forwards final text from item done without correlating
it with deltas.
2026-04-14 00:13:13 -07:00
jif-oai 46a266cd6a feat: disable memory endpoint (#17626) 2026-04-13 18:29:49 +01:00
Ahmed Ibrahim 2f9090be62 Add realtime voice selection (#17176)
- Add realtime voice selection for realtime/start.
- Expose the supported v1/v2 voice lists and cover explicit, configured,
default, and invalid voice paths.
2026-04-08 20:19:15 -07:00
Ahmed IbrahimandCodex 4c2a1ae31b Move default realtime prompt into core (#17165)
- Adds a core-owned realtime backend prompt template and preparation
path.
- Makes omitted realtime start prompts use the core default, while null
or empty prompts intentionally send empty instructions.
- Covers the core realtime path and app-server v2 path with integration
coverage.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-08 19:34:40 -07:00
Ahmed IbrahimandCodex fb3dcfde1d Add WebRTC transport to realtime start (#16960)
Adds WebRTC startup to the experimental app-server
`thread/realtime/start` method with an optional transport enum. The
websocket path remains the default; WebRTC offers create the realtime
session through the shared start flow and emit the answer SDP via
`thread/realtime/sdp`.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-07 15:43:38 -07:00
Jack Mousseau b7dba72dbd Rename reject approval policy to granular (#14516) 2026-03-12 16:38:04 -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
Dylan Hurdandcelia-oai 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
Ahmed IbrahimandCodex 947092283a Add app-server v2 thread realtime API (#12715)
Add experimental `thread/realtime/*` v2 requests and notifications, then
route app-server realtime events through that thread-scoped surface with
integration coverage.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-02-25 09:59:10 -08:00
jif-oai a364dd8b56 feat: opt-out of events in the app-server (#11319)
Add `optOutNotificationMethods` in the app-server to opt-out events
based on exact method matching
2026-02-10 18:04:52 +00:00
jif-oai 3cc9122ee2 feat: experimental flags (#10231)
## Problem being solved
- We need a single, reliable way to mark app-server API surface as
experimental so that:
  1. the runtime can reject experimental usage unless the client opts in
2. generated TS/JSON schemas can exclude experimental methods/fields for
stable clients.

Right now that’s easy to drift or miss when done ad-hoc.

## How to declare experimental methods and fields
- **Experimental method**: add `#[experimental("method/name")]` to the
`ClientRequest` variant in `client_request_definitions!`.
- **Experimental field**: on the params struct, derive `ExperimentalApi`
and annotate the field with `#[experimental("method/name.field")]` + set
`inspect_params: true` for the method variant so
`ClientRequest::experimental_reason()` inspects params for experimental
fields.

## How the macro solves it
- The new derive macro lives in
`codex-rs/codex-experimental-api-macros/src/lib.rs` and is used via
`#[derive(ExperimentalApi)]` plus `#[experimental("reason")]`
attributes.
- **Structs**:
- Generates `ExperimentalApi::experimental_reason(&self)` that checks
only annotated fields.
  - The “presence” check is type-aware:
    - `Option<T>`: `is_some_and(...)` recursively checks inner.
    - `Vec`/`HashMap`/`BTreeMap`: must be non-empty.
    - `bool`: must be `true`.
    - Other types: considered present (returns `true`).
- Registers each experimental field in an `inventory` with `(type_name,
serialized field name, reason)` and exposes `EXPERIMENTAL_FIELDS` for
that type. Field names are converted from `snake_case` to `camelCase`
for schema/TS filtering.
- **Enums**:
- Generates an exhaustive `match` returning `Some(reason)` for annotated
variants and `None` otherwise (no wildcard arm).
- **Wiring**:
- Runtime gating uses `ExperimentalApi::experimental_reason()` in
`codex-rs/app-server/src/message_processor.rs` to reject requests unless
`InitializeParams.capabilities.experimental_api == true`.
- Schema/TS export filters use the inventory list and
`EXPERIMENTAL_CLIENT_METHODS` from `client_request_definitions!` to
strip experimental methods/fields when `experimental_api` is false.
2026-02-02 11:06:50 +00:00