From 10922dd71a2f317820ea48328392449ffcf573ba Mon Sep 17 00:00:00 2001 From: xintaofei Date: Wed, 22 Apr 2026 12:38:31 +0800 Subject: [PATCH] fix(acp): reconnect agent when folder selector switches working directory --- src/contexts/acp-connections-context.tsx | 6 ++++ src/hooks/use-connection-lifecycle.ts | 46 ++++++++++++------------ 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/contexts/acp-connections-context.tsx b/src/contexts/acp-connections-context.tsx index 2678539..6719728 100644 --- a/src/contexts/acp-connections-context.tsx +++ b/src/contexts/acp-connections-context.tsx @@ -110,6 +110,7 @@ export interface ConnectionState { connectionId: string contextKey: string agentType: AgentType + workingDir: string | null status: ConnectionStatus promptCapabilities: PromptCapabilitiesInfo supportsFork: boolean @@ -134,6 +135,7 @@ type Action = contextKey: string connectionId: string agentType: AgentType + workingDir: string | null } | { type: "CONNECTION_REMOVED"; contextKey: string } | { type: "REMOVE_ALL" } @@ -601,6 +603,7 @@ function connectionsReducer( connectionId: action.connectionId, contextKey: action.contextKey, agentType: action.agentType, + workingDir: action.workingDir, status: "connecting", promptCapabilities: { image: false, @@ -2167,10 +2170,12 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) { throw createAlertedError(blocked.reason) } + const nextWorkingDir = workingDir ?? null const existing = storeRef.current.connections.get(contextKey) if (existing) { if ( existing.agentType === agentType && + existing.workingDir === nextWorkingDir && existing.status !== "disconnected" && existing.status !== "error" ) { @@ -2204,6 +2209,7 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) { contextKey, connectionId, agentType, + workingDir: nextWorkingDir, }) const buffered = consumeBufferedEvents(connectionId) diff --git a/src/hooks/use-connection-lifecycle.ts b/src/hooks/use-connection-lifecycle.ts index 7f7d4ad..e2aa1db 100644 --- a/src/hooks/use-connection-lifecycle.ts +++ b/src/hooks/use-connection-lifecycle.ts @@ -129,35 +129,35 @@ export function useConnectionLifecycle({ // Auto-connect when tab becomes active and workingDir is available. // Depends on isActive + workingDir so that connections wait for folder - // info to load (workingDir transitions from undefined → folder.path). + // info to load (workingDir transitions from undefined → folder.path), + // and so that changing folders on an already-connected tab triggers a + // reconnect with the new cwd. The context's connect() dedups same-param + // calls and disconnects+reconnects when workingDir differs. // Status changes must NOT re-trigger this to avoid infinite reconnect // loops on transient errors. useEffect(() => { if (!isActive) return if (!workingDir) return let cancelled = false - const s = statusRef.current - if (!s || s === "disconnected" || s === "error") { - connConnectRef - .current(agentTypeRef.current, workingDir, sessionIdRef.current) - .then(() => { - if (!cancelled) { - setLastAutoConnectError(null) - } - }) - .catch((e: unknown) => { - if (!cancelled) { - setLastAutoConnectError({ - contextKey: contextKeyRef.current, - agentType: agentTypeRef.current, - message: normalizeErrorMessage(e), - }) - } - if (!isExpectedConnectError(e)) { - console.error("[ConnLifecycle] auto-connect:", e) - } - }) - } + connConnectRef + .current(agentTypeRef.current, workingDir, sessionIdRef.current) + .then(() => { + if (!cancelled) { + setLastAutoConnectError(null) + } + }) + .catch((e: unknown) => { + if (!cancelled) { + setLastAutoConnectError({ + contextKey: contextKeyRef.current, + agentType: agentTypeRef.current, + message: normalizeErrorMessage(e), + }) + } + if (!isExpectedConnectError(e)) { + console.error("[ConnLifecycle] auto-connect:", e) + } + }) return () => { cancelled = true }