Skip to content
Merged
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
2 changes: 2 additions & 0 deletions src/server/relay-eager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ export function relaySseEagerBounded(
else hooks.onSynthetic(syntheticKind, syntheticReason);
}
if (cancelled && !hooks.sawTerminal()) {
// Finalize transport telemetry before the cancellation hook persists its usage row.
upstream.abort();
hooks.onClientCancel();
}
if (cancelled || upstream.signal.aborted || syntheticKind === "failed" || deliveryFallbackSent) {
Expand Down
5 changes: 5 additions & 0 deletions src/server/responses/codex-ws-wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ export type CodexWsStageRecord = Omit<CodexWsFailureStage, "requestBytes"> & {
const codexWsStageByResponse = new WeakMap<Response, CodexWsStageRecord>();

export function markCodexWsStage(response: Response, record: CodexWsStageRecord): void {
const current = codexWsStageByResponse.get(response);
if (current) {
Object.assign(current, record);
Comment thread
luvs01 marked this conversation as resolved.
return;
}
codexWsStageByResponse.set(response, record);
}

Expand Down
2 changes: 1 addition & 1 deletion structure/adapters/registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
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.

Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](../transports/responses.md#passthrough-sse-stream-shapes-314).

## Decision

Expand Down
2 changes: 1 addition & 1 deletion structure/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
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.

Shared parsing and streaming follow the [request-copy](transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](transports/responses.md#passthrough-sse-stream-shapes-314).

## Shared catalog

Expand Down
2 changes: 1 addition & 1 deletion structure/clients/claude-desktop.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ is scoped to canonical ChatGPT Responses forwarding; other source-area behavior
Codex-native model discovery follows the [shared retirement policy](../catalog.md#shared-catalog).
That projection does not migrate existing user-selected Desktop configuration or usage history.

Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](../transports/responses.md#passthrough-sse-stream-shapes-314).

Claude-only connections keep their existing non-failing readiness policy; displayed catalog reasons follow the [terminal rendering contract](../runtime.md#cli-readiness-diagnostics) whether they surface at connect time or on a later refresh.

Expand Down
2 changes: 1 addition & 1 deletion structure/data-planes/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Hosted Responses image-tool eligibility uses the shared compatibility policy wit
Codex Spark exception; standalone Images retain the separate relay contract below. See
[Responses transport](../transports/responses.md#responses-httpsse).

Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](../transports/responses.md#passthrough-sse-stream-shapes-314).

## Standalone Images

Expand Down
2 changes: 1 addition & 1 deletion structure/data-planes/inbound-compat.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Translated Claude timeline reminders use the Chat adapter's
on its exact supported route. This is separate from trailing-notice stabilization
and from native Chat message passthrough.

Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](../transports/responses.md#passthrough-sse-stream-shapes-314).

## Chat Completions inbound native path

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. Response-attached WebSocket telemetry follows the [stage record identity contract](transports/responses.md#passthrough-sse-stream-shapes-314).

## Dashboard serving

Expand Down
2 changes: 1 addition & 1 deletion structure/ops/service-and-sidecars.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ is scoped to canonical ChatGPT Responses forwarding; other source-area behavior
Service startup and restore use the [catalog retirement policy](../catalog.md#shared-catalog);
retirement does not itself change service registration or user-selected model configuration.

Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](../transports/responses.md#passthrough-sse-stream-shapes-314).

## Background service command selection

Expand Down
2 changes: 1 addition & 1 deletion structure/providers/xai-grok.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Codex-native retirement is scoped to OpenAI catalog/quota evidence. Shared Respo
retains xAI provider behavior; see
[the catalog boundary](../catalog.md#shared-catalog).

Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](../transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](../transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](../transports/responses.md#passthrough-sse-stream-shapes-314).

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

Expand Down
2 changes: 1 addition & 1 deletion structure/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Chat request serialization owns the destination-scoped
[OpenCode Go instruction ordering](providers/chat-compat.md#opencode-go-chronological-instructions);
it requires no runtime lifecycle change or new configuration option.

Shared parsing and streaming follow the [request-copy](transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](transports/responses.md#passthrough-sse-stream-shapes-314).

## CLI readiness diagnostics

Expand Down
2 changes: 1 addition & 1 deletion structure/subagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Codex treats qualified names literally and defaults absent namespaces to functio
declarations inherit their restored namespace container; the compiler never invents an empty
encryption marker when the upstream omitted it or returned a nonempty marker.

Shared parsing and streaming follow the [request-copy](transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](transports/byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](transports/byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](transports/byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](transports/responses.md#passthrough-sse-stream-shapes-314).

## Multi-agent surface mode (3-state)

Expand Down
2 changes: 1 addition & 1 deletion structure/transports/byte-accounting.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

How opencodex measures request and stream bytes without allocating copies solely to count
them. These contracts are shared by request parsing, SSE rewriting, the provider adapters and
the translator budget, which is why so many documents link here rather than restating them.
the translator budget, which is why so many documents link here rather than restating them. Response-attached WebSocket telemetry follows the [stage record identity contract](responses.md#passthrough-sse-stream-shapes-314).

## Request-copy accounting

Expand Down
2 changes: 1 addition & 1 deletion structure/transports/inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ is scoped to canonical ChatGPT Responses forwarding; other source-area behavior
The Chat adapter's [OpenCode Go instruction ordering](../providers/chat-compat.md#opencode-go-chronological-instructions)
changes translated message placement only; endpoint selection and transport stay with their existing owners.

Shared parsing and streaming follow the [request-copy](byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](responses.md#passthrough-sse-stream-shapes-314).

## Transport inventory

Expand Down
2 changes: 1 addition & 1 deletion structure/transports/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ caller's abort signal, so a `connectTimeoutMs` shorter than 90 seconds cancels
an already-sent create before the prelude timer fires.
These are transport-fidelity guarantees, not a provider-billing guarantee.

Every exchange also leaves a content-free stage record (`CodexWsStageRecord`, #4191): create-frame bytes (measured on failure only — the committed-success record keeps it null so the happy path never byte-counts a megabyte replay frame), send completion, numeric close code, elapsed and first-frame durations, frame counters, liveness ping/pong counts, pool reuse, and the OCX/Bun versions. The exchange pins the record on the resolved Response (`markCodexWsStage`, the same marker seam as `markCodexWsResponse`); `handleResponses` adopts it onto the serving attempt, and usage.jsonl persists it per attempt behind a drop-guard normalizer, so hand-edited rows cannot inject strings into the DTO. The record never carries conversation text, headers, close-reason text, or account identifiers, and it is not a fallback-eligibility signal: the no-replay-after-send contract stands regardless of what it says.
Every exchange also leaves a content-free stage record (`CodexWsStageRecord`, #4191): create-frame bytes (measured on failure only — the committed-success record keeps it null so the happy path never byte-counts a megabyte replay frame), send completion, numeric close code, elapsed and first-frame durations, frame counters, liveness ping/pong counts, pool reuse, and the OCX/Bun versions. The exchange pins the record on the resolved Response (`markCodexWsStage`, the same marker seam as `markCodexWsResponse`); `handleResponses` adopts it onto the serving attempt, and usage.jsonl persists it per attempt behind a drop-guard normalizer, so hand-edited rows cannot inject strings into the DTO. Later snapshots update the same response-local record in place, so an attempt holding the committed reference observes final success or failure counters. Each exchange supplies a complete fresh snapshot; separate responses keep distinct records. On eager-relay cancel-drain expiry, upstream cancellation finalizes the transport snapshot before the cancellation hook writes the usage row; an actual terminal observed within the drain still wins over cancellation. The record never carries conversation text, headers, close-reason text, or account identifiers, and it is not a fallback-eligibility signal: the no-replay-after-send contract stands regardless of what it says.

Eligible complete-input creates can retain a canonical upstream socket within
one selected account, credential, thread and turn. Model/tier and immutable
Expand Down
2 changes: 1 addition & 1 deletion structure/transports/streaming-health.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ removing support for non-default WebSocket quota families.
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).

Shared parsing and streaming follow the [request-copy](byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](byte-accounting.md#stream-buffer-accounting) contracts.
Shared parsing and streaming follow the [request-copy](byte-accounting.md#request-copy-accounting) and [stream-buffer accounting](byte-accounting.md#stream-buffer-accounting) contracts. Response-attached WebSocket telemetry follows the [stage record identity contract](responses.md#passthrough-sse-stream-shapes-314).

## Heartbeat and stall deadline

Expand Down
Loading
Loading