Repository navigation
Conversation
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
There was a problem hiding this comment.
Looks good. I reproduced the problem on Node 24: against a server that waits 310s before sending headers, the built-in fetch fails at 300s with UND_ERR_HEADERS_TIMEOUT, and the new withoutRuntimeTimeouts fetch returns 200 at 310s. The --bundle-only Node CLI build bundles undici and opencode2-node starts. The core tests closest to the change (aisdk, aisdk-native, request hooks, app-node-platform) and typecheck for core and cli all pass.
Public API: no SDK, HTTP, plugin, config or CLI changes. One behaviour change on Node: provider requests now honour HTTP_PROXY, HTTPS_PROXY and NO_PROXY through EnvHttpProxyAgent. The built-in fetch only did that with NODE_USE_ENV_PROXY, so Node users who have those variables set will now send provider traffic through the proxy, as Bun already does.
I have no blocking concerns.
Fixes #26602
On Node, a provider that sends nothing for 5 minutes is disconnected with
UND_ERR_HEADERS_TIMEOUT, even withheaderTimeout: false. Node's built-in fetch applies undici's default 300sheadersTimeoutandbodyTimeout. Bun has the same deadline, and Core already turns it off withtimeout: false. This PR turns off the Node deadline in the same way.opencode2-node) and Core embedded in a Node process. Desktop 2.0.x starts the bundled Bun CLI (opencode-cli serve --service), the same service the TUI uses, so it already behaves correctly.headerTimeout(default 300s),chunkTimeout(default 900s), andtimeout(no default), on every runtime.Change
Both provider request paths (native routes through
RequestExecutor, AI SDK routes throughaisdk.ts) now get their fetch from a runtime-conditioned import, like#sqliteand#pty:flowchart LR N[Native routes<br/>RequestExecutor] --> R{"#runtime-fetch"} A[AI SDK routes<br/>aisdk.ts] --> R R -->|bun| B["ambient fetch + timeout: false<br/>(unchanged behavior)"] R -->|node| U["undici fetch + EnvHttpProxyAgent<br/>headersTimeout: 0, bodyTimeout: 0"] R -->|workerd| W[platform fetch]UND_ERR_INVALID_ARG), so the agent is paired with undici's own fetch.FormDataandRequestkeep the built-in fetch: undici's fetch does not recognize the built-in classes. For example, it sends a built-inFormDataas the text[object FormData], which would break image and transcription uploads.EnvHttpProxyAgenthonorsHTTP_PROXY,HTTPS_PROXY, andNO_PROXY, like Bun's fetch and Core's WebSocket transport on Node.timeout: false.undiciis a builtin) leaves it external and the executable fails at startup withCannot find package 'undici'.Before and after
A real V2 server and an OpenAI-compatible provider that waits 330s before it sends response headers, with
headerTimeout: false:opencode2-node)UND_ERR_HEADERS_TIMEOUT: Headers Timeout Error, then retriedWith
headerTimeout: 20000and a 60s provider delay, patched Node still ends the request after 20s withTimed out waiting for response headers.Relation to #54793
#54793 by @Yedigaryan found the same cause. This PR differs in three places:
nodecondition, so it stays out of the Bun and workerd graphs (the review note on fix(core): lift undici's 300s timeouts on Node #54793).FormDataandRequestinputs keep the built-in fetch.Added by the opencode bot (AI-generated).
Public API: On Node, provider requests now honour HTTP_PROXY/HTTPS_PROXY/NO_PROXY, matching Bun (behaviour change, no API surface change)