Change keybindings to navigate between child sessions (#14814)

This commit is contained in:
James Long
2026-02-27 09:41:23 -05:00
committed by GitHub
parent 157920b2fb
commit 3dc10a1c16
2 changed files with 63 additions and 30 deletions

View File

@@ -48,6 +48,7 @@ import type { SkillTool } from "@/tool/skill"
import { useKeyboard, useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
import { useSDK } from "@tui/context/sdk"
import { useCommandDialog } from "@tui/component/dialog-command"
import type { DialogContext } from "@tui/ui/dialog"
import { useKeybind } from "@tui/context/keybind"
import { Header } from "./header"
import { parsePatch } from "diff"
@@ -226,6 +227,8 @@ export function Session() {
let scroll: ScrollBoxRenderable
let prompt: PromptRef
const keybind = useKeybind()
const dialog = useDialog()
const renderer = useRenderer()
// Allow exit when in child session (prompt is hidden)
const exit = useExit()
@@ -312,19 +315,40 @@ export function Session() {
const local = useLocal()
function moveChild(direction: number) {
function moveFirstChild() {
if (children().length === 1) return
let next = children().findIndex((x) => x.id === session()?.id) + direction
if (next >= children().length) next = 0
if (next < 0) next = children().length - 1
if (children()[next]) {
const next = children().find((x) => !!x.parentID)
if (next) {
navigate({
type: "session",
sessionID: children()[next].id,
sessionID: next.id,
})
}
}
function moveChild(direction: number) {
if (children().length === 1) return
const sessions = children().filter((x) => !!x.parentID)
let next = sessions.findIndex((x) => x.id === session()?.id) + direction
if (next >= sessions.length) next = 0
if (next < 0) next = sessions.length - 1
if (sessions[next]) {
navigate({
type: "session",
sessionID: sessions[next].id,
})
}
}
function childSessionHandler(func: (dialog: DialogContext) => void) {
return (dialog: DialogContext) => {
if (!session()?.parentID || dialog.stack.length > 0) return
func(dialog)
}
}
const command = useCommandDialog()
command.register(() => [
{
@@ -884,24 +908,13 @@ export function Session() {
},
},
{
title: "Next child session",
value: "session.child.next",
keybind: "session_child_cycle",
title: "Go to child session",
value: "session.child.first",
keybind: "session_child_first",
category: "Session",
hidden: true,
onSelect: (dialog) => {
moveChild(1)
dialog.clear()
},
},
{
title: "Previous child session",
value: "session.child.previous",
keybind: "session_child_cycle_reverse",
category: "Session",
hidden: true,
onSelect: (dialog) => {
moveChild(-1)
moveFirstChild()
dialog.clear()
},
},
@@ -911,7 +924,7 @@ export function Session() {
keybind: "session_parent",
category: "Session",
hidden: true,
onSelect: (dialog) => {
onSelect: childSessionHandler((dialog) => {
const parentID = session()?.parentID
if (parentID) {
navigate({
@@ -920,7 +933,29 @@ export function Session() {
})
}
dialog.clear()
},
}),
},
{
title: "Next child session",
value: "session.child.next",
keybind: "session_child_cycle",
category: "Session",
hidden: true,
onSelect: childSessionHandler((dialog) => {
moveChild(1)
dialog.clear()
}),
},
{
title: "Previous child session",
value: "session.child.previous",
keybind: "session_child_cycle_reverse",
category: "Session",
hidden: true,
onSelect: childSessionHandler((dialog) => {
moveChild(-1)
dialog.clear()
}),
},
])
@@ -971,9 +1006,6 @@ export function Session() {
}
})
const dialog = useDialog()
const renderer = useRenderer()
// snap to bottom when session changes
createEffect(on(() => route.sessionID, toBottom))
@@ -1933,7 +1965,7 @@ function Task(props: ToolProps<typeof TaskTool>) {
</box>
<Show when={props.metadata.sessionId}>
<text fg={theme.text}>
{keybind.print("session_child_cycle")}
{keybind.print("session_child_first")}
<span style={{ fg: theme.textMuted }}> view subagents</span>
</text>
</Show>

View File

@@ -896,9 +896,10 @@ export namespace Config {
.describe("Delete word backward in input"),
history_previous: z.string().optional().default("up").describe("Previous history item"),
history_next: z.string().optional().default("down").describe("Next history item"),
session_child_cycle: z.string().optional().default("<leader>right").describe("Next child session"),
session_child_cycle_reverse: z.string().optional().default("<leader>left").describe("Previous child session"),
session_parent: z.string().optional().default("<leader>up").describe("Go to parent session"),
session_child_first: z.string().optional().default("<leader>down").describe("Go to first child session"),
session_child_cycle: z.string().optional().default("right").describe("Go to next child session"),
session_child_cycle_reverse: z.string().optional().default("left").describe("Go to previous child session"),
session_parent: z.string().optional().default("up").describe("Go to parent session"),
terminal_suspend: z.string().optional().default("ctrl+z").describe("Suspend terminal"),
terminal_title_toggle: z.string().optional().default("none").describe("Toggle terminal title"),
tips_toggle: z.string().optional().default("<leader>h").describe("Toggle tips on home screen"),