diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index 2528a4998965..a247b3d6baf5 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -331,6 +331,14 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ if (match.found) return store.session[match.index] return undefined }, + siblings(sessionID: string) { + const session = result.session.get(sessionID) + if (!session) return [] + const parentID = session.parentID ?? session.id + return store.session + .filter((x) => x.parentID === parentID || x.id === parentID) + .toSorted((b, a) => a.id.localeCompare(b.id)) + }, status(sessionID: string) { const session = result.session.get(sessionID) if (!session) return "idle" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx index cf6abef47553..99f53397a169 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx @@ -7,10 +7,19 @@ import type { Session } from "@opencode-ai/sdk/v2" import { useKeybind } from "../../context/keybind" import { useTerminalDimensions } from "@opentui/solid" -const Title = (props: { session: Accessor; truncate?: boolean }) => { +const Title = (props: { + session: Accessor + truncate?: boolean + position: Accessor<{ current: number; total: number } | null> +}) => { const { theme } = useTheme() return ( + + + [{props.position()!.current}/{props.position()!.total}]{" "} + + # {props.session().title} ) @@ -28,6 +37,25 @@ export function Header() { const dimensions = useTerminalDimensions() const tall = createMemo(() => dimensions().height > 40) + // Calculate session position among siblings (parent + children) + const sessionPosition = createMemo(() => { + const current = session() + if (!current) return null + + const siblings = sync.session.siblings(current.id) + + // Only show counter if there are multiple sessions (parent has children) + if (siblings.length <= 1) return null + + const currentIndex = siblings.findIndex((x) => x.id === current.id) + if (currentIndex === -1) return null + + return { + current: currentIndex + 1, // 1-indexed for users + total: siblings.length, + } + }) + return ( + + + [{sessionPosition()!.current}/{sessionPosition()!.total}]{" "} + + Subagent session @@ -99,7 +132,7 @@ export function Header() { - + <Title session={session} truncate={!tall()} position={sessionPosition} /> <Show when={showShare()}> <text fg={theme.textMuted} wrapMode="none" flexShrink={0}> /share{" "} diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 826fa2acf8e0..29427c3ae0ea 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -282,12 +282,11 @@ export function Session() { const local = useLocal() function moveChild(direction: number) { - const parentID = session()?.parentID ?? session()?.id - let children = sync.data.session - .filter((x) => x.parentID === parentID || x.id === parentID) - .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)) + const currentSession = session() + if (!currentSession) return + const children = sync.session.siblings(currentSession.id) if (children.length === 1) return - let next = children.findIndex((x) => x.id === session()?.id) + direction + let next = children.findIndex((x) => x.id === currentSession.id) + direction if (next >= children.length) next = 0 if (next < 0) next = children.length - 1 if (children[next]) {