diff --git a/packages/ui/src/stores/session-events.ts b/packages/ui/src/stores/session-events.ts index 58d2a64a..0d6ed470 100644 --- a/packages/ui/src/stores/session-events.ts +++ b/packages/ui/src/stores/session-events.ts @@ -40,7 +40,7 @@ import { } from "./instances" import { showAlertDialog } from "./alerts" import { createClientSession, mapSdkSessionStatus, type Session, type SessionStatus } from "../types/session" -import { sessions, setSessions, syncInstanceSessionIndicator, withSession } from "./session-state" +import { ensureSessionParentExpanded, sessions, setSessions, syncInstanceSessionIndicator, withSession } from "./session-state" import { normalizeMessagePart } from "./message-v2/normalizers" import { updateSessionInfo } from "./message-v2/session-info" import { tGlobal } from "../lib/i18n" @@ -108,6 +108,8 @@ interface TuiToastEvent { const ALLOWED_TOAST_VARIANTS = new Set(["info", "success", "warning", "error"]) function applySessionStatus(instanceId: string, sessionId: string, status: SessionStatus) { + let parentToExpand: string | null = null + withSession(instanceId, sessionId, (session) => { const current = session.status ?? "idle" if (current === status) return false @@ -117,7 +119,17 @@ function applySessionStatus(instanceId: string, sessionId: string, status: Sessi } session.status = status + + // Auto-expand the parent thread when a child session starts working. + // Users can still collapse it; we only expand on the transition. + if (session.parentId && status === "working" && current !== "working") { + parentToExpand = session.parentId + } }) + + if (parentToExpand) { + ensureSessionParentExpanded(instanceId, parentToExpand) + } } async function fetchSessionInfo(instanceId: string, sessionId: string, directory?: string): Promise { @@ -158,6 +170,7 @@ async function fetchSessionInfo(instanceId: string, sessionId: string, directory const fetched = createClientSession(info, instanceId, "", { providerId: "", modelId: "" }, fetchedStatus) let updatedInstanceSessions: Map | undefined + let shouldExpandParent: string | null = null setSessions((prev) => { const next = new Map(prev) @@ -174,11 +187,19 @@ async function fetchSessionInfo(instanceId: string, sessionId: string, directory instanceSessions.set(sessionId, merged) next.set(instanceId, instanceSessions) updatedInstanceSessions = instanceSessions + + if (merged.parentId && merged.status === "working" && (existing?.status ?? "idle") !== "working") { + shouldExpandParent = merged.parentId + } return next }) syncInstanceSessionIndicator(instanceId, updatedInstanceSessions) + if (shouldExpandParent) { + ensureSessionParentExpanded(instanceId, shouldExpandParent) + } + return fetched } catch (error) { log.error("Failed to fetch session info", error) diff --git a/packages/ui/src/stores/session-state.ts b/packages/ui/src/stores/session-state.ts index 89019ce5..d0e57c37 100644 --- a/packages/ui/src/stores/session-state.ts +++ b/packages/ui/src/stores/session-state.ts @@ -347,10 +347,23 @@ function clearActiveParentSession(instanceId: string): void { } function setSessionStatus(instanceId: string, sessionId: string, status: SessionStatus): void { + let parentToExpand: string | null = null + withSession(instanceId, sessionId, (session) => { if (session.status === status) return false + const previous = session.status session.status = status + + // If a child session starts working, auto-expand its parent thread once. + // Users can still collapse it afterwards; we only expand on the transition. + if (session.parentId && status === "working" && previous !== "working") { + parentToExpand = session.parentId + } }) + + if (parentToExpand) { + ensureSessionParentExpanded(instanceId, parentToExpand) + } } function getActiveParentSession(instanceId: string): Session | null {