From 1fbef481fdeb97abe5eadbc698fd09b1fc5d8213 Mon Sep 17 00:00:00 2001 From: starmorph Date: Mon, 19 May 2025 16:58:31 -0700 Subject: [PATCH] fix artifact code --- src/components/thread/index.tsx | 76 ++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/components/thread/index.tsx b/src/components/thread/index.tsx index ba69f01..28c270f 100644 --- a/src/components/thread/index.tsx +++ b/src/components/thread/index.tsx @@ -22,6 +22,7 @@ import { SquarePen, Plus, CircleX, + XIcon, } from "lucide-react"; import { useQueryState, parseAsBoolean } from "nuqs"; import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom"; @@ -39,6 +40,12 @@ import { } from "../ui/tooltip"; import { useFileUpload } from "@/hooks/use-file-upload"; import { ContentBlocksPreview } from "./ContentBlocksPreview"; +import { + useArtifactOpen, + ArtifactContent, + ArtifactTitle, + useArtifactContext, +} from "./artifact"; function StickyToBottomContent(props: { content: ReactNode; @@ -106,7 +113,10 @@ function OpenGitHubRepo() { } export function Thread() { - const [threadId, setThreadId] = useQueryState("threadId"); + const [_threadId, _setThreadId] = useQueryState("threadId"); + + const [artifactContext, setArtifactContext] = useArtifactContext(); + const [artifactOpen, closeArtifact] = useArtifactOpen(); const [chatHistoryOpen, setChatHistoryOpen] = useQueryState( "chatHistoryOpen", parseAsBoolean.withDefault(false), @@ -133,6 +143,33 @@ export function Thread() { const lastError = useRef(undefined); + useEffect(() => { + if (!stream.error) { + lastError.current = undefined; + return; + } + try { + const message = (stream.error as any).message; + if (!message || lastError.current === message) { + // Message has already been logged. do not modify ref, return early. + return; + } + // Message is defined, and it has not been logged yet. Save it, and send the error + lastError.current = message; + toast.error("An error occurred. Please try again.", { + description: ( +

+ Error: {message} +

+ ), + richColors: true, + closeButton: true, + }); + } catch { + // no-op + } + }, [stream.error]); + // TODO: this should be part of the useStream hook const prevMessageLength = useRef(0); useEffect(() => { @@ -164,11 +201,15 @@ export function Thread() { const toolMessages = ensureToolCallsHaveResponses(stream.messages); stream.submit( - { messages: [...toolMessages, newHumanMessage] }, + { + messages: [...toolMessages, newHumanMessage], + context: artifactContext, + }, { streamMode: ["values"], optimisticValues: (prev) => ({ ...prev, + context: artifactContext, messages: [ ...(prev.messages ?? []), ...toolMessages, @@ -182,11 +223,6 @@ export function Thread() { setContentBlocks([]); }; - const chatStarted = !!threadId || !!messages.length; - const hasNoAIOrToolMessages = !messages.find( - (m) => m.type === "ai" || m.type === "tool", - ); - // Restore handleRegenerate const handleRegenerate = ( parentCheckpoint: Checkpoint | null | undefined, @@ -200,6 +236,18 @@ export function Thread() { }); }; + const setThreadId = (id: string | null) => { + _setThreadId(id); + // close artifact and reset artifact context + closeArtifact(); + setArtifactContext({}); + }; + const threadId = _threadId; + const chatStarted = !!threadId || !!messages.length; + const hasNoAIOrToolMessages = !messages.find( + (m) => m.type === "ai" || m.type === "tool", + ); + return (
@@ -476,6 +524,20 @@ export function Thread() { /> +
+
+
+ + +
+ +
+
); }