diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 605eb2bf..33a5d816 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -7,6 +7,7 @@ import { Locale } from "@/util/locale" import { Keybind } from "@/util/keybind" import { useTheme } from "../context/theme" import { useSDK } from "../context/sdk" +import { DialogSessionRename } from "./dialog-session-rename" export function DialogSessionList() { const dialog = useDialog() @@ -74,6 +75,13 @@ export function DialogSessionList() { setToDelete(option.value) }, }, + { + keybind: Keybind.parse("r")[0], + title: "rename", + onTrigger: async (option) => { + dialog.replace(() => ) + }, + }, ]} /> ) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx new file mode 100644 index 00000000..aaf03320 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx @@ -0,0 +1,35 @@ +import { DialogPrompt } from "@tui/ui/dialog-prompt" +import { useDialog } from "@tui/ui/dialog" +import { useSync } from "@tui/context/sync" +import { createMemo } from "solid-js" +import { useSDK } from "../context/sdk" + +interface DialogSessionRenameProps { + session: string +} + +export function DialogSessionRename(props: DialogSessionRenameProps) { + const dialog = useDialog() + const sync = useSync() + const sdk = useSDK() + const session = createMemo(() => sync.session.get(props.session)) + + return ( + { + sdk.client.session.update({ + path: { + id: props.session, + }, + body: { + title: value, + }, + }) + dialog.clear() + }} + onCancel={() => dialog.clear()} + /> + ) +} diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index da9caa5a..92798b94 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -222,6 +222,11 @@ export function Autocomplete(props: { description: "unshare a session", onSelect: () => command.trigger("session.unshare"), }, + { + display: "/rename", + description: "rename session", + onSelect: () => command.trigger("session.rename"), + }, ) } results.push( 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 baa63d37..78b1ed4a 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -63,6 +63,7 @@ import { Sidebar } from "./sidebar" import { LANGUAGE_EXTENSIONS } from "@/lsp/language" import parsers from "../../../../../../parsers-config.ts" import { Toast } from "../../ui/toast" +import { DialogSessionRename } from "../../component/dialog-session-rename" addDefaultParsers(parsers.parsers) @@ -370,6 +371,15 @@ export function Session() { dialog.clear() }, }, + { + title: "Rename session", + value: "session.rename", + keybind: "session_rename", + category: "Session", + onSelect: (dialog) => { + dialog.replace(() => ) + }, + }, ]) const revert = createMemo(() => { diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx new file mode 100644 index 00000000..a77727aa --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx @@ -0,0 +1,65 @@ +import { TextareaRenderable, TextAttributes } from "@opentui/core" +import { useTheme } from "../context/theme" +import { useDialog, type DialogContext } from "./dialog" +import { onMount } from "solid-js" + +export type DialogPromptProps = { + title: string + value?: string + onConfirm?: (value: string) => void + onCancel?: () => void +} + +export function DialogPrompt(props: DialogPromptProps) { + const dialog = useDialog() + const { theme } = useTheme() + let textarea: TextareaRenderable + + onMount(() => { + dialog.setSize("large") + setTimeout(() => { + textarea.focus() + }, 1) + textarea.gotoLineEnd() + }) + + return ( + + + {props.title} + esc + + +