Skip to content

fix(cli): auto-resume network reconnects#10358

Open
catrielmuller wants to merge 4 commits into
mainfrom
typical-duckling
Open

fix(cli): auto-resume network reconnects#10358
catrielmuller wants to merge 4 commits into
mainfrom
typical-duckling

Conversation

@catrielmuller
Copy link
Copy Markdown
Contributor

@catrielmuller catrielmuller commented May 18, 2026

Context

CLI network reconnects currently require users to manually press Enter after connectivity returns, which blocks unattended workflows. This changes the reconnect flow so users still have a short cancellation window, but interrupted turns resume automatically once the network is back.

Implementation

Network waits now record an authoritative restore timestamp and auto-reply after 10 seconds unless the user cancels. The TUI shows the countdown from that server timestamp, Enter still resumes immediately, and Esc still stops the turn.

Network detection was broadened to cover additional transient socket/browser-style errors and aggregate causes, and recovery probing now uses short HTTPS checks instead of a single DNS lookup. The provider connection timeout is also increased to 3 minutes.

Screenshots

Pasted image Pasted image (2) Pasted image (3)

How to Test

  • Start a CLI turn and trigger a transient network failure during the provider request.
  • Restore connectivity and verify the prompt shows Network reconnected with a 10 second retry countdown.
  • Press Esc during the countdown and verify the turn stops.
  • Repeat and let the countdown finish; verify the turn retries automatically.
  • Run bun test ./test/session/network.test.ts ./test/kilocode/run-network.test.ts from packages/opencode/.
  • Run bun run typecheck from packages/opencode/.

Get in Touch

Comment thread packages/opencode/src/session/network.ts Outdated
).catch(() => false)
}

async function resume(input: { requestID: QuestionID }) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: resume() does not propagate or respect the abort signal from the original ask() call. While the current implicit guard (if (!req || !req.info.restored) return after looking up the pending map) correctly prevents double-reply when the request has already been rejected/aborted, the 10-second setTimeout keeps a live promise in flight even after the user has already cancelled (Esc). This is not a crash, but it means a dangling async task exists for 10 seconds after every abort.

Consider passing the abort signal through to resume() and using it to short-circuit the wait:

async function resume(input: { requestID: QuestionID; abort: AbortSignal }) {
  await new Promise<void>((resolve) => {
    const id = setTimeout(resolve, RESUME_MS)
    input.abort.addEventListener("abort", () => { clearTimeout(id); resolve() }, { once: true })
  })
  if (input.abort.aborted) return
  // ... rest
}

setCountdown(10)
return
}
const restored = props.request.time.restored ?? Date.now()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: The restored timestamp fallback ?? Date.now() creates a subtle discrepancy: if props.request.time.restored is undefined (e.g. the TUI received the restored=true event before the time.restored field was applied), the countdown is calculated from the client's current time rather than the server's authoritative restore timestamp. This could show a full 10-second countdown even when the server's auto-resume will fire in less than 10 seconds.

Since time.restored is set atomically alongside restored = true in restore() on the server side, and the TUI sync now sets both fields in the same event handler, this fallback should rarely trigger — but when it does it will desync the displayed countdown from the actual auto-resume. Consider logging a warning or asserting the value is present rather than silently falling back.

globalThis.setTimeout = timer
})

function manual() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: The manual() helper only intercepts setTimeout (used by resume()), but does not intercept setInterval or clearTimeout. If resume() ever changes to use setInterval internally, the mock won't capture it. The approach works for the current implementation, but it's worth noting this is testing an implementation detail of resume() (its use of setTimeout) rather than observable behavior.

Also, globalThis.setTimeout is patched at the module level, so if tests run concurrently (Bun runs test files in parallel workers), the global mutation could leak between test files. The afterEach restore mitigates leaks within this file, but concurrent tests in the same worker could still interfere. This is acceptable for the current test setup, just worth being aware of.

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented May 18, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

All 4 issues from the previous review have been resolved. The latest commit (621af97) replaces https://www.gstatic.com/generate_204 with https://example.com in the network probe URL list — a safe substitution since example.com is IANA-reserved, always resolves, and returns HTTP 200 (satisfying the res.status < 500 check). The change avoids link-checker false positives from the Google-owned URL.

Files Reviewed (5 core files + formatting)
  • packages/opencode/src/session/network.ts — all previous issues resolved; probe URL swap is correct
  • packages/opencode/src/cli/cmd/tui/routes/session/network.tsx — previous issue resolved
  • packages/opencode/test/session/network.test.ts — all 4 issues addressed, new tests added
  • packages/kilo-docs/source-links.md — source link count updated (88 → 87), gstatic URL removed
  • packages/core/src/kilocode/global.ts — clean new utility

Reviewed by claude-sonnet-4.6 · 165,883 tokens

Review guidance: REVIEW.md from base branch main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant