Skip to content

Latest commit

 

History

History
77 lines (52 loc) · 3.96 KB

File metadata and controls

77 lines (52 loc) · 3.96 KB

Streaming timeouts and keep-alives

This document describes the timeout layers used by the adapter after the streaming reliability fix in PR #11.

Timeout layers

Layer Default Behavior
Codex provider stream_idle_timeout_ms 360000 ms Maximum time Codex waits without receiving activity from the adapter's Responses SSE stream. init writes this value into ~/.codex/config.toml.
Adapter downstream SSE keep-alive 15 seconds Sends an SSE comment frame (: keep-alive) while no Responses event is available, so the Codex-facing connection does not remain silent.
Non-stream upstream request timeout 300 seconds CODEX_OPENCODE_TIMEOUT_SECONDS is a total deadline for a normal non-stream OpenCode Go request.
Stream upstream connect timeout 300 seconds CODEX_OPENCODE_TIMEOUT_SECONDS limits establishment of the upstream streaming connection.
Stream upstream read timeout 300 seconds The same variable limits the gap between successful upstream body reads. It is not a total stream-duration limit.

Effective behavior

A healthy streaming response may run longer than CODEX_OPENCODE_TIMEOUT_SECONDS as long as the upstream continues to deliver body data before each read timeout expires.

The downstream 15-second keep-alive protects only the adapter-to-Codex connection. It does not create upstream model output and does not prevent the upstream read timeout from firing when OpenCode Go sends no bytes for the configured read-timeout period.

The default relationship is intentional:

adapter SSE keep-alive:       15 seconds
upstream per-read timeout:   300 seconds
Codex stream idle timeout:   360 seconds

This allows the adapter to detect a truly stalled upstream before Codex treats the downstream stream as lost, while keep-alive comments prevent ordinary model thinking gaps from looking like downstream inactivity.

Generated Codex provider configuration

codex-opencode-adapter init writes:

[model_providers.opencode_go_adapter]
request_max_retries = 0
stream_max_retries = 0
stream_idle_timeout_ms = 360000

Existing installations are not changed merely by updating the binary. If ~/.codex/config.toml still contains stream_idle_timeout_ms = 120000, rerun init for the project or update that provider value manually.

CODEX_OPENCODE_TIMEOUT_SECONDS semantics

The variable has different semantics by request type:

  • non-stream: total upstream request deadline;
  • stream: upstream connection timeout plus per-read idle timeout;
  • stream: no total response-duration deadline.

Increasing it allows a longer gap between upstream stream reads, but also makes a genuinely stalled upstream take longer to fail. It does not control the 15-second downstream SSE keep-alive or Codex's stream_idle_timeout_ms.

Troubleshooting

When a long stream disconnects, record:

  1. The current stream_idle_timeout_ms in ~/.codex/config.toml.
  2. The current CODEX_OPENCODE_TIMEOUT_SECONDS value.
  3. Whether : keep-alive comment frames continued to arrive downstream.
  4. The time since the last upstream body chunk.
  5. The last Responses event emitted before termination.

Interpretation:

  • no downstream keep-alive within roughly 15 seconds: inspect the adapter process or downstream response path;
  • downstream keep-alives continue, but no upstream body bytes arrive for the read-timeout period: upstream stream stall or network issue;
  • stream ends at a fixed total duration despite regular upstream chunks: regression in the dedicated streaming client behavior;
  • Codex disconnects while keep-alives are arriving: inspect the effective Codex provider configuration and client behavior.

Regression coverage

The repository includes tests that verify:

  • downstream SSE emits keep-alive comments while the Responses stream is idle;
  • generated provider configuration uses the 360-second Codex idle timeout;
  • a streaming upstream request can outlive the normal non-stream total timeout when chunks continue arriving.