fix: stop stuck desktop provider streams (#634)

Desktop sessions already had CLI stream-idle recovery code available, but
child CLI processes did not enable it by default. A provider stream that
stopped producing chunks without closing could therefore leave the desktop UI
showing a running turn indefinitely.

Enable the existing watchdog for desktop-launched CLI sessions and lock the
launch environment with a focused regression test.

Constraint: Desktop provider streams must surface a terminal state when upstream TCP stalls silently.
Rejected: Add a frontend-only running-state timeout | it would mask the hung CLI stream without recovering the turn.
Confidence: high
Scope-risk: narrow
Directive: Keep desktop stream-stall handling at the CLI stream boundary unless the transport contract changes.
Tested: bun test src/server/__tests__/conversation-service.test.ts
Tested: bun run check:server
This commit is contained in:
程序员阿江(Relakkes) 2026-05-27 21:57:29 +08:00
parent bee3d3286b
commit aa749c5b37
2 changed files with 12 additions and 0 deletions

View File

@ -549,6 +549,16 @@ describe('ConversationService', () => {
expect(env.CC_HAHA_DESKTOP_AWAIT_MCP_TIMEOUT_MS).toBe('5000')
})
test('buildChildEnv enables stream idle watchdog for desktop CLI sessions', async () => {
const service = new ConversationService() as any
const env = (await service.buildChildEnv(
'/tmp',
'ws://127.0.0.1:3456/sdk/test-session?token=test-token',
)) as Record<string, string>
expect(env.CLAUDE_ENABLE_STREAM_WATCHDOG).toBe('1')
})
test('buildSessionCliArgs forwards the selected runtime model and effort to the CLI process', () => {
const service = new ConversationService() as any
const args = service.buildSessionCliArgs(

View File

@ -983,6 +983,8 @@ export class ConversationService {
...cleanEnv,
CLAUDE_CODE_ENABLE_TASKS: '1',
CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING: '1',
// Desktop must fail stuck provider streams instead of leaving the UI running forever.
CLAUDE_ENABLE_STREAM_WATCHDOG: cleanEnv.CLAUDE_ENABLE_STREAM_WATCHDOG || '1',
CLAUDE_CODE_DIAGNOSTICS_FILE: cliDiagnosticsPath,
CLAUDE_COWORK_MEMORY_PATH_OVERRIDE: this.resolveDesktopAutoMemoryPath(workDir),
CALLER_DIR: workDir,