refactor(tui): unify command registry and derive slash commands (#9115)

This commit is contained in:
Kit Langton
2026-01-17 21:39:19 -05:00
committed by GitHub
parent 93e43d8e5e
commit 759e68616e
6 changed files with 194 additions and 222 deletions

View File

@@ -295,37 +295,39 @@ export function Session() {
const command = useCommandDialog()
command.register(() => [
...(sync.data.config.share !== "disabled"
? [
{
title: "Share session",
value: "session.share",
suggested: route.type === "session",
keybind: "session_share" as const,
disabled: !!session()?.share?.url,
category: "Session",
onSelect: async (dialog: any) => {
await sdk.client.session
.share({
sessionID: route.sessionID,
})
.then((res) =>
Clipboard.copy(res.data!.share!.url).catch(() =>
toast.show({ message: "Failed to copy URL to clipboard", variant: "error" }),
),
)
.then(() => toast.show({ message: "Share URL copied to clipboard!", variant: "success" }))
.catch(() => toast.show({ message: "Failed to share session", variant: "error" }))
dialog.clear()
},
},
]
: []),
{
title: "Share session",
value: "session.share",
suggested: route.type === "session",
keybind: "session_share",
category: "Session",
enabled: sync.data.config.share !== "disabled" && !session()?.share?.url,
slash: {
name: "share",
},
onSelect: async (dialog) => {
await sdk.client.session
.share({
sessionID: route.sessionID,
})
.then((res) =>
Clipboard.copy(res.data!.share!.url).catch(() =>
toast.show({ message: "Failed to copy URL to clipboard", variant: "error" }),
),
)
.then(() => toast.show({ message: "Share URL copied to clipboard!", variant: "success" }))
.catch(() => toast.show({ message: "Failed to share session", variant: "error" }))
dialog.clear()
},
},
{
title: "Rename session",
value: "session.rename",
keybind: "session_rename",
category: "Session",
slash: {
name: "rename",
},
onSelect: (dialog) => {
dialog.replace(() => <DialogSessionRename session={route.sessionID} />)
},
@@ -335,6 +337,9 @@ export function Session() {
value: "session.timeline",
keybind: "session_timeline",
category: "Session",
slash: {
name: "timeline",
},
onSelect: (dialog) => {
dialog.replace(() => (
<DialogTimeline
@@ -355,6 +360,9 @@ export function Session() {
value: "session.fork",
keybind: "session_fork",
category: "Session",
slash: {
name: "fork",
},
onSelect: (dialog) => {
dialog.replace(() => (
<DialogForkFromTimeline
@@ -374,6 +382,10 @@ export function Session() {
value: "session.compact",
keybind: "session_compact",
category: "Session",
slash: {
name: "compact",
aliases: ["summarize"],
},
onSelect: (dialog) => {
const selectedModel = local.model.current()
if (!selectedModel) {
@@ -396,8 +408,11 @@ export function Session() {
title: "Unshare session",
value: "session.unshare",
keybind: "session_unshare",
disabled: !session()?.share?.url,
category: "Session",
enabled: !!session()?.share?.url,
slash: {
name: "unshare",
},
onSelect: async (dialog) => {
await sdk.client.session
.unshare({
@@ -413,6 +428,9 @@ export function Session() {
value: "session.undo",
keybind: "messages_undo",
category: "Session",
slash: {
name: "undo",
},
onSelect: async (dialog) => {
const status = sync.data.session_status?.[route.sessionID]
if (status?.type !== "idle") await sdk.client.session.abort({ sessionID: route.sessionID }).catch(() => {})
@@ -447,8 +465,11 @@ export function Session() {
title: "Redo",
value: "session.redo",
keybind: "messages_redo",
disabled: !session()?.revert?.messageID,
category: "Session",
enabled: !!session()?.revert?.messageID,
slash: {
name: "redo",
},
onSelect: (dialog) => {
dialog.clear()
const messageID = session()?.revert?.messageID
@@ -495,6 +516,10 @@ export function Session() {
title: showTimestamps() ? "Hide timestamps" : "Show timestamps",
value: "session.toggle.timestamps",
category: "Session",
slash: {
name: "timestamps",
aliases: ["toggle-timestamps"],
},
onSelect: (dialog) => {
setTimestamps((prev) => (prev === "show" ? "hide" : "show"))
dialog.clear()
@@ -504,6 +529,10 @@ export function Session() {
title: showThinking() ? "Hide thinking" : "Show thinking",
value: "session.toggle.thinking",
category: "Session",
slash: {
name: "thinking",
aliases: ["toggle-thinking"],
},
onSelect: (dialog) => {
setShowThinking((prev) => !prev)
dialog.clear()
@@ -513,6 +542,9 @@ export function Session() {
title: "Toggle diff wrapping",
value: "session.toggle.diffwrap",
category: "Session",
slash: {
name: "diffwrap",
},
onSelect: (dialog) => {
setDiffWrapMode((prev) => (prev === "word" ? "none" : "word"))
dialog.clear()
@@ -552,7 +584,7 @@ export function Session() {
value: "session.page.up",
keybind: "messages_page_up",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
scroll.scrollBy(-scroll.height / 2)
dialog.clear()
@@ -563,7 +595,7 @@ export function Session() {
value: "session.page.down",
keybind: "messages_page_down",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
scroll.scrollBy(scroll.height / 2)
dialog.clear()
@@ -574,7 +606,7 @@ export function Session() {
value: "session.half.page.up",
keybind: "messages_half_page_up",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
scroll.scrollBy(-scroll.height / 4)
dialog.clear()
@@ -585,7 +617,7 @@ export function Session() {
value: "session.half.page.down",
keybind: "messages_half_page_down",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
scroll.scrollBy(scroll.height / 4)
dialog.clear()
@@ -596,7 +628,7 @@ export function Session() {
value: "session.first",
keybind: "messages_first",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
scroll.scrollTo(0)
dialog.clear()
@@ -607,7 +639,7 @@ export function Session() {
value: "session.last",
keybind: "messages_last",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
scroll.scrollTo(scroll.scrollHeight)
dialog.clear()
@@ -618,6 +650,7 @@ export function Session() {
value: "session.messages_last_user",
keybind: "messages_last_user",
category: "Session",
hidden: true,
onSelect: () => {
const messages = sync.data.message[route.sessionID]
if (!messages || !messages.length) return
@@ -649,7 +682,7 @@ export function Session() {
value: "session.message.next",
keybind: "messages_next",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => scrollToMessage("next", dialog),
},
{
@@ -657,7 +690,7 @@ export function Session() {
value: "session.message.previous",
keybind: "messages_previous",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => scrollToMessage("prev", dialog),
},
{
@@ -706,8 +739,10 @@ export function Session() {
{
title: "Copy session transcript",
value: "session.copy",
keybind: "session_copy",
category: "Session",
slash: {
name: "copy",
},
onSelect: async (dialog) => {
try {
const sessionData = session()
@@ -735,6 +770,9 @@ export function Session() {
value: "session.export",
keybind: "session_export",
category: "Session",
slash: {
name: "export",
},
onSelect: async (dialog) => {
try {
const sessionData = session()
@@ -793,7 +831,7 @@ export function Session() {
value: "session.child.next",
keybind: "session_child_cycle",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
moveChild(1)
dialog.clear()
@@ -804,7 +842,7 @@ export function Session() {
value: "session.child.previous",
keybind: "session_child_cycle_reverse",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
moveChild(-1)
dialog.clear()
@@ -815,7 +853,7 @@ export function Session() {
value: "session.parent",
keybind: "session_parent",
category: "Session",
disabled: true,
hidden: true,
onSelect: (dialog) => {
const parentID = session()?.parentID
if (parentID) {