From 7157bfb8d59468a7f8207eb9a32c0ed5510eca60 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sun, 12 Jul 2026 21:49:47 +0000 Subject: [PATCH] fix(tui): restore clicked reverted prompt --- .../tui/src/routes/session/dialog-message.tsx | 18 +++++++-- packages/tui/src/routes/session/index.tsx | 16 +------- packages/tui/src/util/revert-prompt.ts | 19 +++++++++ packages/tui/test/util/revert-prompt.test.ts | 39 +++++++++++++++++++ 4 files changed, 75 insertions(+), 17 deletions(-) create mode 100644 packages/tui/src/util/revert-prompt.ts create mode 100644 packages/tui/test/util/revert-prompt.test.ts diff --git a/packages/tui/src/routes/session/dialog-message.tsx b/packages/tui/src/routes/session/dialog-message.tsx index db64c7b5da..9cb689c0b3 100644 --- a/packages/tui/src/routes/session/dialog-message.tsx +++ b/packages/tui/src/routes/session/dialog-message.tsx @@ -6,12 +6,15 @@ import { useToast } from "../../ui/toast" import { useSDK } from "../../context/sdk" import { errorMessage } from "../../util/error" import { DialogFork } from "./dialog-fork" +import { usePromptRef } from "../../context/prompt" +import { revertedPrompt } from "../../util/revert-prompt" export function DialogMessage(props: { messageID: string; sessionID: string }) { const data = useData() const clipboard = useClipboard() const toast = useToast() const sdk = useSDK() + const promptRef = usePromptRef() const message = createMemo(() => data.session.message.get(props.sessionID, props.messageID)) return ( @@ -23,9 +26,18 @@ export function DialogMessage(props: { messageID: string; sessionID: string }) { value: "session.revert", description: "undo messages and file changes", onSelect: async (dialog) => { - await sdk.api.session - .revert.stage({ sessionID: props.sessionID, messageID: props.messageID }) - .catch((error) => toast.show({ message: errorMessage(error), variant: "error", duration: 5000 })) + const error = await sdk.api.session.revert + .stage({ sessionID: props.sessionID, messageID: props.messageID }) + .then( + () => undefined, + (error) => error, + ) + if (error) { + toast.show({ message: errorMessage(error), variant: "error", duration: 5000 }) + return + } + const value = message() + if (value?.type === "user") promptRef.current?.set(revertedPrompt(value)) dialog.clear() }, }, diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index bf36219421..940f72ce3c 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -75,6 +75,7 @@ import { usePathFormatter } from "../../context/path-format" import { LocationProvider } from "../../context/location" import { createSessionRows, resolvePart, type PartRef, type SessionRow } from "./rows" import { switchLabel } from "../../util/model" +import { revertedPrompt } from "../../util/revert-prompt" addDefaultParsers(parsers.parsers) @@ -424,20 +425,7 @@ export function Session() { void sdk.api.session.revert .stage({ sessionID: route.sessionID, messageID: message.id }) .catch((error) => toast.show({ message: errorMessage(error), variant: "error", duration: 5000 })) - prompt?.set({ - text: message.text, - files: message.files?.map((file) => ({ - uri: file.source.type === "uri" ? file.source.uri : `data:${file.mime};base64,${file.data}`, - name: file.name, - description: file.description, - mention: file.mention ? { ...file.mention } : undefined, - })), - agents: message.agents?.map((agent) => ({ - name: agent.name, - mention: agent.mention ? { ...agent.mention } : undefined, - })), - pasted: [], - }) + prompt?.set(revertedPrompt(message)) dialog.clear() }, }, diff --git a/packages/tui/src/util/revert-prompt.ts b/packages/tui/src/util/revert-prompt.ts new file mode 100644 index 0000000000..b2932d1f87 --- /dev/null +++ b/packages/tui/src/util/revert-prompt.ts @@ -0,0 +1,19 @@ +import type { SessionMessageUser } from "@opencode-ai/client" +import type { PromptInfo } from "../prompt/history" + +export function revertedPrompt(message: SessionMessageUser): PromptInfo { + return { + text: message.text, + files: message.files?.map((file) => ({ + uri: file.source.type === "uri" ? file.source.uri : `data:${file.mime};base64,${file.data}`, + name: file.name, + description: file.description, + mention: file.mention ? { ...file.mention } : undefined, + })), + agents: message.agents?.map((agent) => ({ + name: agent.name, + mention: agent.mention ? { ...agent.mention } : undefined, + })), + pasted: [], + } +} diff --git a/packages/tui/test/util/revert-prompt.test.ts b/packages/tui/test/util/revert-prompt.test.ts new file mode 100644 index 0000000000..49a0a44630 --- /dev/null +++ b/packages/tui/test/util/revert-prompt.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, test } from "bun:test" +import type { SessionMessageUser } from "@opencode-ai/client" +import { revertedPrompt } from "../../src/util/revert-prompt" + +describe("reverted prompt", () => { + test("restores message text and references", () => { + const message = { + id: "message-1", + type: "user", + text: "Fix @test.ts with @review", + time: { created: 1 }, + files: [ + { + mime: "text/typescript", + name: "test.ts", + description: "test file", + data: "", + source: { type: "uri", uri: "file:///repo/test.ts" }, + mention: { start: 4, end: 12, text: "@test.ts" }, + }, + ], + agents: [{ name: "review", mention: { start: 18, end: 25, text: "@review" } }], + } satisfies SessionMessageUser + + expect(revertedPrompt(message)).toEqual({ + text: "Fix @test.ts with @review", + files: [ + { + uri: "file:///repo/test.ts", + name: "test.ts", + description: "test file", + mention: { start: 4, end: 12, text: "@test.ts" }, + }, + ], + agents: [{ name: "review", mention: { start: 18, end: 25, text: "@review" } }], + pasted: [], + }) + }) +})