From 214a1cffd117cd7d9185c45682ed827aafa42eae Mon Sep 17 00:00:00 2001 From: qwen-code-ci-bot Date: Tue, 28 Jul 2026 17:10:33 +0000 Subject: [PATCH] fix(cli): address review feedback on agent-view supervisor (#7799) --- .../cli/src/agent-view/supervisor-client.ts | 11 ++++- .../cli/src/agent-view/supervisor-process.ts | 8 ++-- .../src/agent-view/supervisor-runner.test.ts | 14 ++++++- .../cli/src/agent-view/supervisor-store.ts | 40 +++++++++---------- .../cli/src/agent-view/terminal-bridge.ts | 1 + 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/packages/cli/src/agent-view/supervisor-client.ts b/packages/cli/src/agent-view/supervisor-client.ts index 0b6e79ef41..d071b06e81 100644 --- a/packages/cli/src/agent-view/supervisor-client.ts +++ b/packages/cli/src/agent-view/supervisor-client.ts @@ -378,8 +378,15 @@ export function subscribeAgentViewSupervisor( let response: AgentViewSupervisorResponse; try { response = parseSupervisorResponse(line); - } catch { - continue; + } catch (parseError) { + notifySubscriptionError( + new AgentViewSupervisorClientError( + `Invalid subscription response: ${parseError instanceof Error ? parseError.message : String(parseError)}`, + 'invalid_response', + ), + ); + socket.destroy(); + return; } if (!response.ok) { notifySubscriptionError( diff --git a/packages/cli/src/agent-view/supervisor-process.ts b/packages/cli/src/agent-view/supervisor-process.ts index da118cd03a..06fceedf15 100644 --- a/packages/cli/src/agent-view/supervisor-process.ts +++ b/packages/cli/src/agent-view/supervisor-process.ts @@ -144,16 +144,16 @@ class AgentViewSupervisorProcessHandler } async tickIdleHibernation(): Promise { - if (this.options.hibernationPolicy?.enabled === false) { - return { hibernated: [], shutdownRequested: false }; - } - const states = await listAgentViewSessionStates(this.store); if (this.shouldAutoExit(states)) { void this.options.onShutdown?.(); return { hibernated: [], shutdownRequested: true }; } + if (this.options.hibernationPolicy?.enabled === false) { + return { hibernated: [], shutdownRequested: false }; + } + return { hibernated: [], shutdownRequested: false }; } diff --git a/packages/cli/src/agent-view/supervisor-runner.test.ts b/packages/cli/src/agent-view/supervisor-runner.test.ts index cc959ab9dd..2a73949755 100644 --- a/packages/cli/src/agent-view/supervisor-runner.test.ts +++ b/packages/cli/src/agent-view/supervisor-runner.test.ts @@ -167,6 +167,12 @@ describe('Agent View supervisor runner', () => { result: { subscribed: true }, })}\n`, ); + socket.write( + `${JSON.stringify({ + type: 'changed', + at: '2026-07-17T00:00:00.000Z', + })}\n`, + ); }), dispatch: vi.fn(() => ({ sessionId: 'session-2' })), adopt: vi.fn(() => ({ sessionId: 'session-2', adopted: true })), @@ -199,8 +205,14 @@ describe('Agent View supervisor runner', () => { ]); expect(handler.list).toHaveBeenCalledWith({ cwd: '/workspace/project' }); - const subscription = handle.subscribe(() => {}); + const eventCallback = vi.fn(); + const subscription = handle.subscribe(eventCallback); await waitFor(() => handler.subscribe.mock.calls.length === 1); + await waitFor(() => eventCallback.mock.calls.length === 1); + expect(eventCallback).toHaveBeenCalledWith({ + type: 'changed', + at: '2026-07-17T00:00:00.000Z', + }); subscription.dispose(); await expect( diff --git a/packages/cli/src/agent-view/supervisor-store.ts b/packages/cli/src/agent-view/supervisor-store.ts index 84865c7c2b..89edfebfba 100644 --- a/packages/cli/src/agent-view/supervisor-store.ts +++ b/packages/cli/src/agent-view/supervisor-store.ts @@ -502,27 +502,13 @@ function normalizeWorker( return { ...raw, schemaVersion: 1, - ...(numberValue(raw['hostPid']) - ? { hostPid: numberValue(raw['hostPid']) } - : {}), - ...(numberValue(raw['workerPid']) - ? { workerPid: numberValue(raw['workerPid']) } - : {}), - ...(stringValue(raw['endpoint']) - ? { endpoint: stringValue(raw['endpoint']) } - : {}), - ...(stringValue(raw['hostEndpoint']) - ? { hostEndpoint: stringValue(raw['hostEndpoint']) } - : {}), - ...(stringValue(raw['hostAuthToken']) - ? { hostAuthToken: stringValue(raw['hostAuthToken']) } - : {}), - ...(stringValue(raw['tokenDigest']) - ? { tokenDigest: stringValue(raw['tokenDigest']) } - : {}), - ...(stringValue(raw['lastHeartbeatAt']) - ? { lastHeartbeatAt: stringValue(raw['lastHeartbeatAt']) } - : {}), + hostPid: numberValue(raw['hostPid']), + workerPid: numberValue(raw['workerPid']), + endpoint: stringValue(raw['endpoint']), + hostEndpoint: stringValue(raw['hostEndpoint']), + hostAuthToken: stringValue(raw['hostAuthToken']), + tokenDigest: stringValue(raw['tokenDigest']), + lastHeartbeatAt: stringValue(raw['lastHeartbeatAt']), protocolVersion: numberValue(raw['protocolVersion']) ?? 1, platform: platformValue(raw['platform']), recentOutputBytes: numberValue(raw['recentOutputBytes']) ?? 0, @@ -609,8 +595,18 @@ function terminalValue(value: unknown): AgentViewLaunchFile['terminal'] { }; } +const KNOWN_PLATFORMS: ReadonlySet = new Set([ + 'aix', + 'darwin', + 'freebsd', + 'linux', + 'openbsd', + 'sunos', + 'win32', +]); + function platformValue(value: unknown): NodeJS.Platform { - return typeof value === 'string' + return typeof value === 'string' && KNOWN_PLATFORMS.has(value) ? (value as NodeJS.Platform) : process.platform; } diff --git a/packages/cli/src/agent-view/terminal-bridge.ts b/packages/cli/src/agent-view/terminal-bridge.ts index 187e96b00f..d5ed791467 100644 --- a/packages/cli/src/agent-view/terminal-bridge.ts +++ b/packages/cli/src/agent-view/terminal-bridge.ts @@ -121,6 +121,7 @@ async function pumpInputToPty( } await pty.write(toBuffer(next.value)); } + detached = true; return 'detached'; } finally { const returned = iterator.return?.();