fix(acp): defer auto-connect until historical session id resolves
When reopening a historical conversation, the ACP auto-connect fired before the detail fetch resolved external_id, so the backend fell back to session/new and the agent lost prior context. Gate both the auto-connect effect and the focus-triggered reconnect on the session id being ready.
This commit is contained in:
@@ -202,8 +202,6 @@ const ConversationTabView = memo(function ConversationTabView({
|
|||||||
const [hasSentMessage, setHasSentMessage] = useState(false)
|
const [hasSentMessage, setHasSentMessage] = useState(false)
|
||||||
|
|
||||||
const hasPersistedConversation = dbConversationId != null
|
const hasPersistedConversation = dbConversationId != null
|
||||||
const canAutoConnect =
|
|
||||||
hasPersistedConversation || (agentsLoaded && usableAgentCount > 0)
|
|
||||||
|
|
||||||
// Expose the runtime session key to the tab so the aux panel (Diff sidebar)
|
// Expose the runtime session key to the tab so the aux panel (Diff sidebar)
|
||||||
// can look up live turns even before the DB conversation is created.
|
// can look up live turns even before the DB conversation is created.
|
||||||
@@ -266,6 +264,17 @@ const ConversationTabView = memo(function ConversationTabView({
|
|||||||
}, [effectiveSessionStats, isActive, setSessionStats])
|
}, [effectiveSessionStats, isActive, setSessionStats])
|
||||||
|
|
||||||
const externalId = detail?.summary.external_id ?? undefined
|
const externalId = detail?.summary.external_id ?? undefined
|
||||||
|
// For persisted conversations opened from the sidebar, wait until the
|
||||||
|
// session's external_id has been resolved before auto-connecting.
|
||||||
|
// Otherwise the auto-connect effect fires with sessionId=undefined and
|
||||||
|
// the backend falls back to session/new, orphaning the historical
|
||||||
|
// context. cline doesn't support session resume, so it connects
|
||||||
|
// immediately regardless.
|
||||||
|
const awaitingHistoricalSessionId =
|
||||||
|
hasPersistedConversation && selectedAgent !== "cline" && detailLoading
|
||||||
|
const canAutoConnect =
|
||||||
|
(hasPersistedConversation || (agentsLoaded && usableAgentCount > 0)) &&
|
||||||
|
!awaitingHistoricalSessionId
|
||||||
const draftStorageKey = useMemo(() => {
|
const draftStorageKey = useMemo(() => {
|
||||||
if (dbConversationId != null) {
|
if (dbConversationId != null) {
|
||||||
return buildConversationDraftStorageKey(dbConversationId)
|
return buildConversationDraftStorageKey(dbConversationId)
|
||||||
|
|||||||
@@ -264,6 +264,10 @@ export function useConnectionLifecycle({
|
|||||||
}, [removeTask, clearSelectorTask])
|
}, [removeTask, clearSelectorTask])
|
||||||
|
|
||||||
const handleFocus = useCallback(() => {
|
const handleFocus = useCallback(() => {
|
||||||
|
// Respect the caller's readiness gate — e.g. historical conversations
|
||||||
|
// set isActive=false until the session's external_id resolves, to
|
||||||
|
// avoid connecting with sessionId=undefined and orphaning context.
|
||||||
|
if (!isActive) return
|
||||||
touchActivity(contextKey)
|
touchActivity(contextKey)
|
||||||
if (!status || status === "disconnected" || status === "error") {
|
if (!status || status === "disconnected" || status === "error") {
|
||||||
setLastAutoConnectError(null)
|
setLastAutoConnectError(null)
|
||||||
@@ -274,6 +278,7 @@ export function useConnectionLifecycle({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
|
isActive,
|
||||||
agentType,
|
agentType,
|
||||||
workingDir,
|
workingDir,
|
||||||
sessionId,
|
sessionId,
|
||||||
|
|||||||
Reference in New Issue
Block a user