Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ Providers can expose a built-in shorthand, such as `agy` for `google-antigravity
| `unsafeAllowNativeLocalExec?` | `boolean` | Cursor legacy boolean, equivalent to `nativeLocalExec: "on"` only when the newer field is unset. |
| `nativeLocalExec?` | `"off" \| "codex-sandbox" \| "on"` | Cursor local-exec policy. `off` is default; `codex-sandbox` currently fails closed like `off`. |

With `webSearchBridge` enabled, a search continuation stays bound to the API-key selection that
served the first request. Changing the selected key, its reference or resolved value, authentication
mode, or base URL during search or provider pacing ends the turn with a bridge error before another
provider request is sent. Changing away and back also ends that continuation. Start a new turn to
use the new selection. Selection changes before the first provider send retain normal reselection.

Custom-model `reasoningEfforts` normally override discovered provider metadata. The bounded
exception is an explicit Astra or Daybreak custom row on the canonical `openai` Codex-forward
destination: its advertised list is intersected with that model's pinned native capabilities.
Expand Down
11 changes: 10 additions & 1 deletion src/server/responses/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6149,6 +6149,8 @@ async function handleResponsesInner(
isPassthrough: true,
stream: parsed.stream === true,
});
// Capture the binding that actually served the first leg, after its permitted reselection.
const webSearchBridgeBinding = requestBindings.get(request);
// The bridge wraps the RAW upstream body, so terminal repair below still owns the single
// client-facing terminal — the bridge drops the terminal of every intercepted leg.
const upstreamSseBody = webSearchBridgePlan
Expand All @@ -6166,7 +6168,14 @@ async function handleResponsesInner(
connectMs,
true,
providerFetch(route.provider, options.codexWsRuntimeIdentity, {
dispatchOverride: oauthDispatch(request),
// Pacing can outlive a manual selection change. A continuation must retain the
// first leg's key and appended search result, never rebuild from the original turn.
beforeDispatch: () => {
if (webSearchBridgeBinding?.kind !== "api-key"
|| !providerApiKeySelectionIsCurrent(config, route.providerName, webSearchBridgeBinding.provider)) {
throw new Error("API key selection changed during a web-search continuation");
}
},
providerName: route.providerName,
modelId: route.modelId,
}),
Expand Down
3 changes: 3 additions & 0 deletions structure/adapters/registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
The configuration-only [plaintext V2 contract](../subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.

The server-owned key-auth Responses hosted-search bridge retains the serving adapter's account
binding as specified in [continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Decision

Runtime adapter construction has one authority: `src/adapters/registry.ts`.
Expand Down
3 changes: 3 additions & 0 deletions structure/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ real turn depends on it (`src/codex/warmup.ts`).

## Routed tool discovery and hosted search

For opted-in key-auth Responses providers, the declared hosted-search tool follows the
[continuation binding contract](runtime.md#hosted-search-continuation-binding).

All routed catalog rows advertise `supports_search_tool: true` together with
`tool_mode: "code_mode_only"` — the pair is load-bearing. The field selects Codex's deferred
tool-discovery surface; it does not describe the hosted web-search sidecar. Under code mode,
Expand Down
3 changes: 3 additions & 0 deletions structure/clients/claude-desktop.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
The configuration-only [plaintext V2 contract](../subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.

The shared server's key-auth Responses hosted-search continuation policy is documented in
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Connected Claude Desktop profiles

Connected `ocx claude desktop apply` reads the hub's Desktop snapshot and writes the hub origin
Expand Down
3 changes: 3 additions & 0 deletions structure/data-planes/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
The configuration-only [plaintext V2 contract](../subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.

For the shared Responses server's hosted-search continuation binding, see
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Standalone Images

Codex's local `image_gen.imagegen` tool makes a second Images request after the model calls it:
Expand Down
3 changes: 3 additions & 0 deletions structure/data-planes/inbound-compat.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ to gpt-live-1-codex; gpt-live-1 is an explicit alias. Dictation and Frameless ev
separate. Coverage lives in `tests/server/audio-client.test.ts`,
`tests/server/audio-dictation.test.ts` and `tests/server/live-call-bindings.test.ts`.

Requests entering the key-auth Responses hosted-search bridge follow its
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Chat Completions inbound native path

`POST /v1/chat/completions` sends eligible `openai-chat` routes directly to the provider's Chat
Expand Down
3 changes: 3 additions & 0 deletions structure/data-planes/search.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Search Data Plane

The opt-in key-auth Responses hosted-search bridge follows the
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Standalone Search and exact account selectors

`POST /v1/alpha/search` retains the selected model in its request body. When that value is an
Expand Down
2 changes: 1 addition & 1 deletion structure/gui-and-management-api.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# GUI And Management API

The configuration-only [plaintext V2 contract](subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged. Changing the selected API key during an opted-in Responses hosted-search turn follows the [continuation binding contract](runtime.md#hosted-search-continuation-binding).

## Dashboard serving

Expand Down
3 changes: 3 additions & 0 deletions structure/ops/docs-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ is scoped to canonical ChatGPT Responses forwarding; other source-area behavior

## Public docs

The provider configuration reference documents the user-visible
[hosted-search continuation binding](../runtime.md#hosted-search-continuation-binding).

The public documentation site lives in `docs-site/` and is built with Astro + Starlight. English is
served at the site root, with Korean under `/ko`, Simplified Chinese under `/zh-cn`, Traditional Chinese under `/zh-tw`, Russian under `/ru`, and Japanese under `/ja`. `docs-site/astro.config.mjs` is the locale source of truth.

Expand Down
3 changes: 3 additions & 0 deletions structure/ops/service-and-sidecars.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ PATH, so a launcher-backed job is never misreported as an older plist (#3464).

## Sidecars

The opt-in key-auth Responses hosted-search bridge follows the
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

Web search and vision sidecars run only when the main request needs that capability and a usable
sidecar authority exists. Vision has two possible backends; web search's config union additionally
admits `xai`, `gemini`, and `exa`. xAI is a live explicit-only backend through stored Grok OAuth;
Expand Down
3 changes: 3 additions & 0 deletions structure/providers/xai-grok.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
The configuration-only [plaintext V2 contract](../subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.

The opt-in key-auth Responses hosted-search bridge uses the shared
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## xAI Grok hardening (official Grok Build contract parity)

Grounded in the open-sourced official client (xai-org/grok-build); unit + evidence:
Expand Down
13 changes: 13 additions & 0 deletions structure/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,19 @@ Routed Responses continuations whose local replay state is missing resolve their

The shared Responses path follows the [bounded multipart recovery contract](subagents.md#multipart-encrypted-task-recovery); credential admission and retry policy remain unchanged.

### Hosted-search continuation binding

The opt-in key-auth Responses hosted-search bridge in `src/server/responses/core.ts` captures the
request binding that served the first leg, after any permitted initial reselection. Before every
continuation dispatch, after provider pacing, that binding must remain an API-key selection matching
the configured entry, reference, revision, resolved key, authentication mode, and base URL; a
disabled or removed provider fails the same check. Drift produces the bridge's failed terminal
without another provider request, and an unchanged binding resends the built request with its
executed search result appended, never re-entering the initial reselection/rebuild path. Initial
dispatch keeps its normal reselection policy. `tests/web-search/web-search-passthrough-bridge.test.ts`
covers drift during search, while pacing, and before first-leg headers return, plus successful
first-dispatch reselection and result preservation.

## Remote Hub hardening ownership

`src/remote/protocol.ts` owns pure interval/feature negotiation. `src/remote/hub-state.ts` owns the `GET|HEAD /v1/hub-state` contract, its caps, and the parser both sides share. `src/client/hub-client.ts` owns bounded, schema-validated remote catalog consumption, hub-state reads, and key-id probes; `src/client/hub-state.ts` owns the resolution and the owner-stamped 0600 cache, and a failed read reports "unavailable" rather than degrading to the client's own local provider and login state. `src/client/hub-relay.ts` is a fixed-authority management relay with URL, header, body, redirect, and stream bounds. The public data listener remains the direct client→hub path; the loopback management ingress never serves data-plane routes.
Expand Down
3 changes: 3 additions & 0 deletions structure/subagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ other fragment layouts and mixed readable content retain their documented residu

## Subagents

Parent and subagent requests using the key-auth Responses hosted-search bridge share the
[continuation binding contract](runtime.md#hosted-search-continuation-binding).

New non-OAuth provider registrations carry `initialModelSelection` with a unique
registration identity. Until reliable live/static discovery completes, public
catalogs and model candidates withhold those providers' models; the provider itself
Expand Down
3 changes: 3 additions & 0 deletions structure/transports/inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
The configuration-only [plaintext V2 contract](../subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.

The opt-in key-auth Responses hosted-search bridge has a separate
[continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Transport inventory

The sections above cover the transports with load-bearing invariants. The rest of the transport
Expand Down
2 changes: 1 addition & 1 deletion structure/transports/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Plaintext collaboration restoration treats a null namespace as absent, rejects n

`/v1/responses` is the main Codex-facing endpoint. The server parses Responses input, routes to a
provider, lets the selected adapter speak the upstream protocol, then bridges adapter events back to
Responses-compatible streaming output.
Responses-compatible streaming output. For an opted-in key-auth provider, a hosted-search continuation stays bound to the API-key selection that served the first leg; the contract is the [hosted-search continuation binding](../runtime.md#hosted-search-continuation-binding).

### Credential-bearing HTTP redirects

Expand Down
3 changes: 3 additions & 0 deletions structure/transports/streaming-health.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
The configuration-only [plaintext V2 contract](../subagents.md#plaintext-v2-agent-messages)
is scoped to canonical ChatGPT Responses forwarding; other source-area behavior described here is unchanged.

Key-auth hosted-search continuations validate account selection after pacing and report a failed
terminal on drift; see [continuation binding contract](../runtime.md#hosted-search-continuation-binding).

## Heartbeat and stall deadline

The HTTP/SSE bridge emits an SSE comment-line keep-alive (`: opencodex heartbeat`) during upstream
Expand Down
Loading
Loading