diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 989defd9..03aa5df6 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -177,17 +177,14 @@ function App() { const exit = useExit() useKeyboard(async (evt) => { + if (!Installation.isLocal()) return if (evt.meta && evt.name === "t") { - if (process.env.DEBUG) { - renderer.toggleDebugOverlay() - } + renderer.toggleDebugOverlay() return } if (evt.meta && evt.name === "d") { - if (process.env.DEBUG) { - renderer.console.toggle() - } + renderer.console.toggle() return } }) 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 c3846b55..5cd2e671 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -64,7 +64,6 @@ import { LANGUAGE_EXTENSIONS } from "@/lsp/language" import parsers from "../../../../../../parsers-config.ts" import { Clipboard } from "../../util/clipboard" import { Toast, useToast } from "../../ui/toast" -import { DialogSessionRename } from "../../component/dialog-session-rename" import { useKV } from "../../context/kv.tsx" addDefaultParsers(parsers.parsers) @@ -401,12 +400,49 @@ export function Session() { }, }, { - title: "Rename session", - value: "session.rename", - keybind: "session_rename", + title: "Copy last assistant message", + value: "messages.copy", + keybind: "messages_copy", category: "Session", onSelect: (dialog) => { - dialog.replace(() => ) + const lastAssistantMessage = messages().findLast((msg) => msg.role === "assistant") + if (!lastAssistantMessage) { + toast.show({ message: "No assistant messages found", variant: "error" }) + dialog.clear() + return + } + + const parts = sync.data.part[lastAssistantMessage.id] ?? [] + const textParts = parts.filter((part) => part.type === "text") + if (textParts.length === 0) { + toast.show({ message: "No text parts found in last assistant message", variant: "error" }) + dialog.clear() + return + } + + const text = textParts + .map((part) => part.text) + .join("\n") + .trim() + if (!text) { + toast.show({ + message: "No text content found in last assistant message", + variant: "error", + }) + dialog.clear() + return + } + + console.log(text) + const base64 = Buffer.from(text).toString("base64") + const osc52 = `\x1b]52;c;${base64}\x07` + const finalOsc52 = process.env["TMUX"] ? `\x1bPtmux;\x1b${osc52}\x1b\\` : osc52 + /* @ts-expect-error */ + renderer.writeOut(finalOsc52) + Clipboard.copy(text) + .then(() => toast.show({ message: "Message copied to clipboard!", variant: "success" })) + .catch(() => toast.show({ message: "Failed to copy to clipboard", variant: "error" })) + dialog.clear() }, }, { @@ -431,6 +467,47 @@ export function Session() { dialog.clear() }, }, + { + title: "Copy last assistant message", + value: "messages.copy", + keybind: "messages_copy", + category: "Session", + onSelect: (dialog) => { + const lastAssistantMessage = messages().findLast((msg) => msg.role === "assistant") + if (lastAssistantMessage) { + const parts = sync.data.part[lastAssistantMessage.id] ?? [] + const textParts = parts.filter((part) => part.type === "text") + if (textParts.length > 0) { + const text = textParts + .map((part) => part.text) + .join("\n") + .trim() + if (text) { + Clipboard.copy(text) + .then(() => + toast.show({ message: "Message copied to clipboard!", variant: "success" }), + ) + .catch(() => + toast.show({ message: "Failed to copy to clipboard", variant: "error" }), + ) + } else { + toast.show({ + message: "No text content found in last assistant message", + variant: "error", + }) + } + } else { + toast.show({ + message: "No text parts found in last assistant message", + variant: "error", + }) + } + } else { + toast.show({ message: "No assistant messages found", variant: "error" }) + } + dialog.clear() + }, + }, ]) const revert = createMemo(() => { diff --git a/packages/opencode/src/file/index.ts b/packages/opencode/src/file/index.ts index 020b3568..3a143d07 100644 --- a/packages/opencode/src/file/index.ts +++ b/packages/opencode/src/file/index.ts @@ -320,7 +320,10 @@ export namespace File { log.info("search", { query: input.query }) const limit = input.limit ?? 100 const result = await state().then((x) => x.files()) - if (!input.query) return input.dirs !== false ? result.dirs.toSorted().slice(0, limit) : [] + if (!input.query) + return input.dirs !== false + ? result.dirs.toSorted().slice(0, limit) + : result.files.slice(0, limit) const items = input.dirs !== false ? [...result.files, ...result.dirs] : result.files const sorted = fuzzysort.go(input.query, items, { limit: limit }).map((r) => r.target) log.info("search", { query: input.query, results: sorted.length })