From fbd9b7cf4fb27433a066a10a197c7edb420336d1 Mon Sep 17 00:00:00 2001
From: Adam <2363879+adamdotdevin@users.noreply.github.com>
Date: Wed, 11 Mar 2026 16:34:48 -0500
Subject: feat(app): restore to message and fork session (#17092)
---
packages/ui/src/components/icon.tsx | 2 +
packages/ui/src/components/message-part.tsx | 59 +++++++++++++++++++++++++++++
packages/ui/src/components/session-turn.tsx | 11 +++++-
3 files changed, 70 insertions(+), 2 deletions(-)
(limited to 'packages/ui/src/components')
diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx
index 6486da851..7f4598f29 100644
--- a/packages/ui/src/components/icon.tsx
+++ b/packages/ui/src/components/icon.tsx
@@ -9,6 +9,7 @@ const icons = {
"bubble-5": ``,
prompt: ``,
brain: ``,
+ fork: ``,
"bullet-list": ``,
"check-small": ``,
"chevron-down": ``,
@@ -80,6 +81,7 @@ const icons = {
selector: ``,
"arrow-down-to-line": ``,
warning: ``,
+ reset: ``,
link: ``,
providers: ``,
models: ``,
diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx
index 65b6229d6..1a50ed48c 100644
--- a/packages/ui/src/components/message-part.tsx
+++ b/packages/ui/src/components/message-part.tsx
@@ -129,12 +129,20 @@ function DiagnosticsDisplay(props: { diagnostics: Diagnostic[] }): JSX.Element {
export interface MessageProps {
message: MessageType
parts: PartType[]
+ actions?: UserActions
showAssistantCopyPartID?: string | null
interrupted?: boolean
queued?: boolean
showReasoningSummaries?: boolean
}
+export type SessionAction = (input: { sessionID: string; messageID: string }) => Promise | void
+
+export type UserActions = {
+ fork?: SessionAction
+ revert?: SessionAction
+}
+
export interface MessagePartProps {
part: PartType
message: MessageType
@@ -676,6 +684,7 @@ export function Message(props: MessageProps) {
@@ -872,6 +881,7 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean }) {
export function UserMessageDisplay(props: {
message: UserMessage
parts: PartType[]
+ actions?: UserActions
interrupted?: boolean
queued?: boolean
}) {
@@ -879,6 +889,7 @@ export function UserMessageDisplay(props: {
const dialog = useDialog()
const i18n = useI18n()
const [copied, setCopied] = createSignal(false)
+ const [busy, setBusy] = createSignal<"fork" | "revert" | undefined>()
const textPart = createMemo(
() => props.parts?.find((p) => p.type === "text" && !(p as TextPart).synthetic) as TextPart | undefined,
@@ -945,6 +956,22 @@ export function UserMessageDisplay(props: {
setTimeout(() => setCopied(false), 2000)
}
+ const run = (kind: "fork" | "revert") => {
+ const act = kind === "fork" ? props.actions?.fork : props.actions?.revert
+ if (!act || busy()) return
+ setBusy(kind)
+ void Promise.resolve()
+ .then(() =>
+ act({
+ sessionID: props.message.sessionID,
+ messageID: props.message.id,
+ }),
+ )
+ .finally(() => {
+ if (busy() === kind) setBusy(undefined)
+ })
+ }
+
return (
0}>
@@ -1012,6 +1039,38 @@ export function UserMessageDisplay(props: {
+
+
+ e.preventDefault()}
+ onClick={(event) => {
+ event.stopPropagation()
+ run("fork")
+ }}
+ aria-label={i18n.t("ui.message.forkMessage")}
+ />
+
+
+
+
+ e.preventDefault()}
+ onClick={(event) => {
+ event.stopPropagation()
+ run("revert")
+ }}
+ aria-label={i18n.t("ui.message.revertMessage")}
+ />
+
+
-
+
--
cgit v1.2.3