import { Component, createMemo } from "solid-js" import { useNavigate, useParams } from "@solidjs/router" import { useSync } from "@/context/sync" import { useSDK } from "@/context/sdk" import { usePrompt } from "@/context/prompt" import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" import { extractPromptFromParts } from "@/utils/prompt" import type { TextPart as SDKTextPart } from "@opencode-ai/sdk/v2/client" import { base64Encode } from "@opencode-ai/util/encode" import { useLanguage } from "@/context/language" interface ForkableMessage { id: string text: string time: string } function formatTime(date: Date): string { return date.toLocaleTimeString(undefined, { timeStyle: "short" }) } export const DialogFork: Component = () => { const params = useParams() const navigate = useNavigate() const sync = useSync() const sdk = useSDK() const prompt = usePrompt() const dialog = useDialog() const language = useLanguage() const messages = createMemo((): ForkableMessage[] => { const sessionID = params.id if (!sessionID) return [] const msgs = sync.data.message[sessionID] ?? [] const result: ForkableMessage[] = [] for (const message of msgs) { if (message.role !== "user") continue const parts = sync.data.part[message.id] ?? [] const textPart = parts.find((x): x is SDKTextPart => x.type === "text" && !x.synthetic && !x.ignored) if (!textPart) continue result.push({ id: message.id, text: textPart.text.replace(/\n/g, " ").slice(0, 200), time: formatTime(new Date(message.time.created)), }) } return result.reverse() }) const handleSelect = (item: ForkableMessage | undefined) => { if (!item) return const sessionID = params.id if (!sessionID) return const parts = sync.data.part[item.id] ?? [] const restored = extractPromptFromParts(parts, { directory: sdk.directory, attachmentName: language.t("common.attachment"), }) dialog.close() sdk.client.session.fork({ sessionID, messageID: item.id }).then((forked) => { if (!forked.data) return navigate(`/${base64Encode(sdk.directory)}/session/${forked.data.id}`) requestAnimationFrame(() => { prompt.set(restored) }) }) } return ( x.id} items={messages} filterKeys={["text"]} onSelect={handleSelect} > {(item) => (
{item.text} {item.time}
)}
) }