- Increased codex websocket first event timeout default to 300 seconds.
- Increased default stream idle and first event timeout thresholds to 300 seconds.
- Updated stream timeout test expectations to match new 300s global default.
- Kept zero timeout resolutions distinct from missing first-event policy so the iterator does not fall back to the idle watchdog.
- Added deterministic coverage for an SSE response that opens before local prompt prefill emits its first event.
- Added a per-model first-event watchdog policy and disabled it for local OpenAI-compatible backends while retaining inter-event stall detection.
- Applied the policy to Responses and chat-completions transports with regression coverage for resolver and runtime precedence.
Fixes#6524
Gave each Codex SSE transport attempt an independent pre-response watchdog while reserving the retry-loop signal for caller cancellation.
Added provider-level coverage for retry recovery and explicit abort behavior.
Fixes#5329
The lazy stream wrapper registered streamCursor without provider-handled
timeouts, so iterateWithIdleTimeout treated every gap between
AssistantMessageEvents as potential provider death. During a Cursor
exec-channel round-trip the server is waiting on OUR local tool result
(shell/read/grep/write/MCP/...) and legitimately sends nothing, so any
local tool outliving the idle budget (120s default) tripped onIdle ->
abortLocally(StreamTimeoutError) and killed a healthy stream mid-task.
Fix at the watchdog seam instead of faking progress events:
- EventStream tracks consumer-side local work in flight
(trackLocalWork / hasPendingLocalWork).
- iterateWithIdleTimeout accepts a hasPendingLocalWork probe; an expired
idle or first-event deadline slides forward while it reports true and
the pending iterator.next() is persisted across the extension so no
item is dropped. Once local work finishes the watchdog re-arms with a
full budget, so genuinely silent streams still abort.
- forwardStream wires the probe for any provider stream instance.
- cursor.ts marks the exec-server dispatch as local work, covering every
exec case including shellStream and MCP.
Unlike synthesizing empty toolcall_delta keepalives (PR #4594), no
synthetic events reach consumers: post-toolcall_end deltas would clobber
reconstructed tool arguments in proxy adapters and re-trigger TTSR
argument checks.
Adopted from PR #4594: the setCursorProviderModule test seam.
Fixes#4593
- Migrated 288 lines of scattered error classification logic from `utils/error-id.ts` into a cohesive `packages/ai/src/error/` module with 13 specialized submodules covering flags, classes, OAuth, providers, rate-limiting, and finalization.
- Replaced 100+ generic `Error` throws across 60+ provider and registry files with semantic `AIError.*` classes (e.g., `AIError.MissingApiKeyError`, `AIError.OAuthError`, `AIError.ProviderResponseError`), improving error diagnostics and retry logic.
- Consolidated error utility imports from `pi-utils` and scattered classification functions into a single `AIError` namespace, reducing coupling and simplifying error handling across all packages.
- Prevents absolute `AbortSignal.timeout` from cutting off active stream bodies by introducing a clearable pre-response timer.
- Clears the watchdog timer for Bedrock, Gemini, Ollama, and Codex providers once headers are received.
- Restores regular caller abort signaling capability on the combined fetch stream.
- Adds comprehensive fake-timer tests to cover the timeout arming and clearing lifecycle.
- Added a terminal-aware async iterator that enforces a post-completion grace window, then ends iteration and optionally aborts the request.
- Wrapped OpenAI completions streaming with terminal detection of finish-reason and usage payloads so iteration stops once a response is logically complete.
- Stopped OpenAI Responses stream consumption at terminal response events instead of waiting for connection close timeouts.
- Scoped Anthropic provider session state by base URL and model so strict-tools/fast-mode fallback state no longer leaks across unrelated endpoints or models, and fast-mode re-arming clears all matching scoped entries.
- Dropped stale strict fallback error messages after successful retries and only enabled adaptive thinking display for models that advertise support, avoiding unsupported-model 400 errors.
- Updated idle stream iteration to close the upstream iterator on non-continuing exits (including consumer early break) and added coverage for upstream closure behavior.
Always route OpenAI-family providers through getOpenAIStreamFirstEventTimeoutMs so PI_OPENAI_STREAM_FIRST_EVENT_TIMEOUT_MS wins even when callers pass per-call streamIdleTimeoutMs. The OpenAI helper now floors the first-event budget at the caller-resolved idle (which already encompasses per-call streamIdleTimeoutMs or PI_OPENAI_STREAM_IDLE_TIMEOUT_MS upstream), and explicit env disables ("0") on either knob continue to drop the watchdog.
Fixes#1603
OpenAI-compatible local servers can spend longer than the generic first-event budget processing large prompts before they emit response headers or SSE frames. The OpenAI-specific idle timeout now also acts as the OpenAI-family first-event floor unless an explicit OpenAI first-event timeout is configured.
Added regression coverage for OpenAI Responses request setup so a lower generic first-event watchdog no longer undercuts PI_OPENAI_STREAM_IDLE_TIMEOUT_MS.
Fixes#1603
- Replaced external watchdog timers with per-request SDK timeouts for first-event budget across OpenAI, Anthropic, and Azure providers.
- Keyed Python shared kernels by (sessionId, cwd) to prevent cross-directory state bleed.
- Deduplicated concurrent cold-start session acquisition for JS and Python executors.
- Moved `isOpenAIResponsesProgressEvent` to shared module and scoped display output routing per run for interleaved async cells.
- Refactored stream timeout handling to allow providers to manage first-event and idle timeouts directly.
- Extracted firstEventTimeoutMs calculations into reusable variables across OpenAI, Azure OpenAI, and Codex providers.
- Consolidated timeout enforcement logic in idle-iterator to use absolute deadline checking and early callback invocation.
- Added providerHandlesStreamTimeouts flag to LazyStreamLimits interface to skip framework-level timeouts when providers handle them.
- Exported isOpenAIResponsesProgressEvent function and removed deprecated MockModelHandle type alias.
- Restored per-provider stream watchdog with idle and first-event timeout support, progress-event filtering, and per-provider timeout overrides via `getStreamIdleTimeoutMs()` and `getStreamFirstEventTimeoutMs()`.
- Fixed silent multi-hour hangs on Codex WebSocket and z.ai/GLM-via-OpenRouter subagent runs by filtering keepalive frames from idle watchdog resets.
- Added `isOpenAICompletionsProgressChunk` export and progress-event filtering to multiple providers (Anthropic, OpenAI Responses/Completions, Azure OpenAI, Codex) to prevent keepalive frames from resetting idle timeouts.
- Un-deprecated `StreamOptions.streamIdleTimeoutMs` and wired it into all built-in providers and lazy stream forwarder with environment variable fallback support.
Removed OMP-owned first-event and idle watchdogs from provider stream consumption while preserving caller abort handling. Updated provider stream tests to assert slow/silent streams wait for provider output or caller abort instead of surfacing watchdog errors.
Fixes#1392
- Added optional per-provider fallback parameters to stream timeout helper functions so callers can widen default watchdog values safely.
- Threaded provider-specific lazy stream limits into stream creation and set Google Gemini CLI to a 300000ms first-event fallback by default.
- Added tests covering fallback defaults, env precedence, and global-default behavior for both idle and first-event timeouts.
- Restored default stream idle timeout from 30s back to 120s (regression from 15.0.0).
- Fixed `iterateWithIdleTimeout` to only flip `awaitingFirstItem` on real progress items, not synthetic `start` events.
- Marked provider `start` events as non-progress keepalives in the lazy-stream wrapper.
Adds an opt-in onSseEvent callback across HTTP-streaming providers (Anthropic, OpenAI Responses/Completions, Azure OpenAI Responses, OpenAI Codex SSE, Google Gemini CLI, GitLab Duo, Kimi, Synthetic) so callers can inspect raw SSE frames without altering parsed output. Provider fetch wrapping only tees response bodies when an observer is wired; standalone packages/ai consumers without onSseEvent are not penalized.
Adds streamIdleTimeoutMs (env: PI_STREAM_IDLE_TIMEOUT_MS, with PI_OPENAI_STREAM_IDLE_TIMEOUT_MS as a backward-compatible alias). Anthropic now enforces a steady-state idle watchdog (default 120s) in addition to the first-event watchdog. OpenAI Responses, Azure Responses, and Codex (SSE + WebSocket) gain a semantic-progress predicate so response.in_progress-style keepalives no longer keep stalled tool calls alive forever.
Adds a coding-agent debug-panel raw SSE viewer backed by a per-session bounded buffer (1000 records / 512KB) that AgentSession populates unconditionally so users can post-hoc inspect a stuck stream from the TUI.
The OpenAI completions/responses providers fed the SDK stream into
iterateWithIdleTimeout, which only raced iterator.next() against the
idle/first-event watchdog (default 100s) and relied on the underlying
fetch body reader to surface caller aborts. When the transport does not
propagate AbortSignal to body reads — the path triggered by
github-copilot's gpt-5* responses on macOS — ESC was observed only after
the watchdog elapsed, so the spinner appeared to hang forever.
Race iterator.next() against the caller signal as well, threading
options.signal into iterateWithIdleTimeout. On signal abort the
iterator is closed via iterator.return() and the abort reason is thrown,
letting the provider catch surface a clean stopReason: "aborted"
within tens of milliseconds.
Fixes#912
- Reworked `idle-iterator` to replace the first-event watchdog wrapper with a shared timeout handle passed through stream iteration.
- Updated Anthropic and OpenAI/Azure response-completion streams to pass the watchdog into `iterateWithIdleTimeout` and rely on unified first-event timeout logic.
- Raised the default first-stream-event timeout from 60 seconds to 100 seconds.
- Added asynchronous LSP server discovery and warmup at startup via `discoverStartupLspServers()` function.
- Added LSP startup event channel (`lsp:startup`) for real-time server status notifications during warmup.
- Added `LspStartupServerInfo` type to track LSP server status (connecting, ready, error) throughout lifecycle.
- Changed LSP server warmup from blocking synchronous operation to non-blocking background task.
- Refactored interactive mode to subscribe to LSP startup events and display real-time server status updates.
- Deferred first-event watchdog initialization until after stream request creation in OpenAI-family providers to exclude slow request setup from timeout.
- Increased default first-event timeout from 15s to 45s to accommodate longer request setup times.
- Modified first-event watchdog to inherit idle timeout when it exceeds the default threshold.
- Refactored timeout calculation logic to use Math.max for proper threshold enforcement.
- Added comprehensive test coverage for first-event timeout behavior across default, inherited, and override scenarios.
- Added first-event timeout detection for streaming responses to prevent stuck requests and enable faster recovery from stream stalls.
- Added PI_STREAM_FIRST_EVENT_TIMEOUT_MS environment variable to configure first-event timeout behavior independently from idle timeouts.
- Fixed Anthropic stream timeout errors to be properly retried with first-event recognition, distinguishing first-event from idle timeouts.
- Enhanced idle-iterator utility with FirstEventWatchdog mechanism and markFirstStreamEvent wrapper for unified timeout handling across OpenAI, Azure OpenAI, and Anthropic providers.
- Added idle-iterator utility to enforce maximum gaps between stream events, preventing indefinite hangs when providers stop sending mid-response. Applied watchdog to OpenAI completions, responses, Azure OpenAI responses, and Codex SSE streams with configurable timeout via PI_OPENAI_STREAM_IDLE_TIMEOUT_MS.
- Added separate first-event timeout for Codex websocket connections to quickly fall back to SSE when a prewarmed socket connects but never starts the response stream. Codex websocket now validates auth headers match before reusing connections.
- Fixed OAuth token refresh and usage lookups to respect request timeouts instead of waiting indefinitely during credential selection or rotation.