fix(acp): reconnect agent when folder selector switches working directory
This commit is contained in:
@@ -110,6 +110,7 @@ export interface ConnectionState {
|
|||||||
connectionId: string
|
connectionId: string
|
||||||
contextKey: string
|
contextKey: string
|
||||||
agentType: AgentType
|
agentType: AgentType
|
||||||
|
workingDir: string | null
|
||||||
status: ConnectionStatus
|
status: ConnectionStatus
|
||||||
promptCapabilities: PromptCapabilitiesInfo
|
promptCapabilities: PromptCapabilitiesInfo
|
||||||
supportsFork: boolean
|
supportsFork: boolean
|
||||||
@@ -134,6 +135,7 @@ type Action =
|
|||||||
contextKey: string
|
contextKey: string
|
||||||
connectionId: string
|
connectionId: string
|
||||||
agentType: AgentType
|
agentType: AgentType
|
||||||
|
workingDir: string | null
|
||||||
}
|
}
|
||||||
| { type: "CONNECTION_REMOVED"; contextKey: string }
|
| { type: "CONNECTION_REMOVED"; contextKey: string }
|
||||||
| { type: "REMOVE_ALL" }
|
| { type: "REMOVE_ALL" }
|
||||||
@@ -601,6 +603,7 @@ function connectionsReducer(
|
|||||||
connectionId: action.connectionId,
|
connectionId: action.connectionId,
|
||||||
contextKey: action.contextKey,
|
contextKey: action.contextKey,
|
||||||
agentType: action.agentType,
|
agentType: action.agentType,
|
||||||
|
workingDir: action.workingDir,
|
||||||
status: "connecting",
|
status: "connecting",
|
||||||
promptCapabilities: {
|
promptCapabilities: {
|
||||||
image: false,
|
image: false,
|
||||||
@@ -2167,10 +2170,12 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
|||||||
throw createAlertedError(blocked.reason)
|
throw createAlertedError(blocked.reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nextWorkingDir = workingDir ?? null
|
||||||
const existing = storeRef.current.connections.get(contextKey)
|
const existing = storeRef.current.connections.get(contextKey)
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (
|
if (
|
||||||
existing.agentType === agentType &&
|
existing.agentType === agentType &&
|
||||||
|
existing.workingDir === nextWorkingDir &&
|
||||||
existing.status !== "disconnected" &&
|
existing.status !== "disconnected" &&
|
||||||
existing.status !== "error"
|
existing.status !== "error"
|
||||||
) {
|
) {
|
||||||
@@ -2204,6 +2209,7 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
|||||||
contextKey,
|
contextKey,
|
||||||
connectionId,
|
connectionId,
|
||||||
agentType,
|
agentType,
|
||||||
|
workingDir: nextWorkingDir,
|
||||||
})
|
})
|
||||||
|
|
||||||
const buffered = consumeBufferedEvents(connectionId)
|
const buffered = consumeBufferedEvents(connectionId)
|
||||||
|
|||||||
@@ -129,35 +129,35 @@ export function useConnectionLifecycle({
|
|||||||
|
|
||||||
// Auto-connect when tab becomes active and workingDir is available.
|
// Auto-connect when tab becomes active and workingDir is available.
|
||||||
// Depends on isActive + workingDir so that connections wait for folder
|
// 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
|
// Status changes must NOT re-trigger this to avoid infinite reconnect
|
||||||
// loops on transient errors.
|
// loops on transient errors.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isActive) return
|
if (!isActive) return
|
||||||
if (!workingDir) return
|
if (!workingDir) return
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
const s = statusRef.current
|
connConnectRef
|
||||||
if (!s || s === "disconnected" || s === "error") {
|
.current(agentTypeRef.current, workingDir, sessionIdRef.current)
|
||||||
connConnectRef
|
.then(() => {
|
||||||
.current(agentTypeRef.current, workingDir, sessionIdRef.current)
|
if (!cancelled) {
|
||||||
.then(() => {
|
setLastAutoConnectError(null)
|
||||||
if (!cancelled) {
|
}
|
||||||
setLastAutoConnectError(null)
|
})
|
||||||
}
|
.catch((e: unknown) => {
|
||||||
})
|
if (!cancelled) {
|
||||||
.catch((e: unknown) => {
|
setLastAutoConnectError({
|
||||||
if (!cancelled) {
|
contextKey: contextKeyRef.current,
|
||||||
setLastAutoConnectError({
|
agentType: agentTypeRef.current,
|
||||||
contextKey: contextKeyRef.current,
|
message: normalizeErrorMessage(e),
|
||||||
agentType: agentTypeRef.current,
|
})
|
||||||
message: normalizeErrorMessage(e),
|
}
|
||||||
})
|
if (!isExpectedConnectError(e)) {
|
||||||
}
|
console.error("[ConnLifecycle] auto-connect:", e)
|
||||||
if (!isExpectedConnectError(e)) {
|
}
|
||||||
console.error("[ConnLifecycle] auto-connect:", e)
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return () => {
|
return () => {
|
||||||
cancelled = true
|
cancelled = true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user