fix: increase proxy stream timeout from 30s to 10min

The 30-second AbortSignal.timeout on streaming fetch requests was
causing long-running tool calls (file editing, code search) to be
silently killed. The UI would show the task as still running but
no data was flowing, making it appear stuck indefinitely.

- Increase fetch timeout to 600s (10 min) for both stream and
  non-stream requests
- Add 5-minute per-chunk timeout in both stream parsers so a
  truly dead upstream is detected and surfaced as an error
  instead of hanging forever

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 18:33:47 +08:00
co-authored by Claude Opus 4.6
parent 9a3597c923
commit bbe5c8866b
3 changed files with 16 additions and 4 deletions
+2 -2
View File
@@ -119,7 +119,7 @@ async function handleOpenaiChat(
Authorization: `Bearer ${apiKey}`, Authorization: `Bearer ${apiKey}`,
}, },
body: JSON.stringify(transformed), body: JSON.stringify(transformed),
signal: isStream ? AbortSignal.timeout(30_000) : AbortSignal.timeout(300_000), signal: AbortSignal.timeout(600_000),
}) })
if (!upstream.ok) { if (!upstream.ok) {
@@ -176,7 +176,7 @@ async function handleOpenaiResponses(
Authorization: `Bearer ${apiKey}`, Authorization: `Bearer ${apiKey}`,
}, },
body: JSON.stringify(transformed), body: JSON.stringify(transformed),
signal: isStream ? AbortSignal.timeout(30_000) : AbortSignal.timeout(300_000), signal: AbortSignal.timeout(600_000),
}) })
if (!upstream.ok) { if (!upstream.ok) {
@@ -105,7 +105,13 @@ export function openaiChatStreamToAnthropic(
try { try {
while (true) { while (true) {
const { done, value } = await reader.read() const readResult = await Promise.race([
reader.read(),
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Stream chunk timeout: no data for 5 minutes')), 300_000)
),
])
const { done, value } = readResult
if (done) break if (done) break
buffer += decoder.decode(value, { stream: true }) buffer += decoder.decode(value, { stream: true })
@@ -44,7 +44,13 @@ export function openaiResponsesStreamToAnthropic(
try { try {
while (true) { while (true) {
const { done, value } = await reader.read() const readResult = await Promise.race([
reader.read(),
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Stream chunk timeout: no data for 5 minutes')), 300_000)
),
])
const { done, value } = readResult
if (done) break if (done) break
buffer += decoder.decode(value, { stream: true }) buffer += decoder.decode(value, { stream: true })