From aa2d753e7edbf323baf635aec7972b673d2b64a3 Mon Sep 17 00:00:00 2001 From: Dax Date: Sat, 28 Mar 2026 12:16:00 -0400 Subject: [PATCH] feat: dialog variant menu and subagent improvements (#19537) --- .../src/cli/cmd/tui/routes/session/index.tsx | 19 ++------------ .../tui/routes/session/subagent-footer.tsx | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 19 deletions(-) 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 50199b010e..fb62de9acf 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -334,7 +334,7 @@ export function Session() { if (children().length === 1) return const sessions = children().filter((x) => !!x.parentID) - let next = sessions.findIndex((x) => x.id === session()?.id) + direction + let next = sessions.findIndex((x) => x.id === session()?.id) - direction if (next >= sessions.length) next = 0 if (next < 0) next = sessions.length - 1 @@ -1228,7 +1228,6 @@ function UserMessage(props: { const local = useLocal() const text = createMemo(() => props.parts.flatMap((x) => (x.type === "text" && !x.synthetic ? [x] : []))[0]) const files = createMemo(() => props.parts.flatMap((x) => (x.type === "file" ? [x] : []))) - const sync = useSync() const { theme } = useTheme() const [hover, setHover] = createSignal(false) const queued = createMemo(() => props.pending && props.message.id > props.pending) @@ -1614,17 +1613,6 @@ function GenericTool(props: ToolProps) { ) } -function ToolTitle(props: { fallback: string; when: any; icon: string; children: JSX.Element }) { - const { theme } = useTheme() - return ( - - ~ {props.fallback}} when={props.when}> - {props.icon} {props.children} - - - ) -} - function InlineTool(props: { icon: string iconColor?: RGBA @@ -1962,10 +1950,7 @@ function WebSearch(props: ToolProps) { } function Task(props: ToolProps) { - const { theme } = useTheme() - const keybind = useKeybind() const { navigate } = useRoute() - const local = useLocal() const sync = useSync() onMount(() => { @@ -1996,7 +1981,7 @@ function Task(props: ToolProps) { const content = createMemo(() => { if (!props.input.description) return "" - let content = [`Task ${props.input.description}`] + let content = [`${Locale.titlecase(props.input.subagent_type ?? "General")} Task — ${props.input.description}`] if (isRunning() && tools().length > 0) { // content[0] += ` · ${tools().length} toolcalls` diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx index 315cd1e88c..70c6f6ea99 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx @@ -13,6 +13,23 @@ export function SubagentFooter() { const route = useRouteData("session") const sync = useSync() const messages = createMemo(() => sync.data.message[route.sessionID] ?? []) + const session = createMemo(() => sync.session.get(route.sessionID)) + + const subagentInfo = createMemo(() => { + const s = session() + if (!s) return { label: "Subagent", index: 0, total: 0 } + const agentMatch = s.title.match(/@(\w+) subagent/) + const label = agentMatch ? Locale.titlecase(agentMatch[1]) : "Subagent" + + if (!s.parentID) return { label, index: 0, total: 0 } + + const siblings = sync.data.session + .filter((x) => x.parentID === s.parentID) + .toSorted((a, b) => a.time.created - b.time.created) + const index = siblings.findIndex((x) => x.id === s.id) + + return { label, index: index + 1, total: siblings.length } + }) const usage = createMemo(() => { const msg = messages() @@ -58,10 +75,15 @@ export function SubagentFooter() { backgroundColor={theme.backgroundPanel} > - + - Subagent session + {subagentInfo().label} + 0}> + + ({subagentInfo().index} of {subagentInfo().total}) + + {(item) => (