"use client"; import { useEffect, useRef } from "react"; import { AssistantRuntimeProvider, useLocalRuntime, type ChatModelAdapter, } from "@assistant-ui/react"; import { Thread } from "@/components/assistant-ui/thread"; import { Button } from "@/components/ui/button"; import { RotateCcw } from "lucide-react"; // --------------------------------------------------------------------------- // Props // --------------------------------------------------------------------------- interface AtlasChatProps { projectId: string; projectName?: string; } // --------------------------------------------------------------------------- // Runtime adapter — calls our existing /api/projects/[id]/atlas-chat endpoint // --------------------------------------------------------------------------- function makeAtlasAdapter(projectId: string): ChatModelAdapter { return { async run({ messages, abortSignal }) { const lastUser = [...messages].reverse().find((m) => m.role === "user"); const text = lastUser?.content .filter((p) => p.type === "text") .map((p) => (p as { type: "text"; text: string }).text) .join("") ?? ""; const res = await fetch(`/api/projects/${projectId}/atlas-chat`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: text }), signal: abortSignal, }); if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err.error || "Atlas is unavailable. Please try again."); } const data = await res.json(); return { content: [{ type: "text", text: data.reply || "…" }], }; }, }; } // --------------------------------------------------------------------------- // Inner component — has access to runtime context // --------------------------------------------------------------------------- function AtlasChatInner({ projectId, projectName, runtime, }: AtlasChatProps & { runtime: ReturnType }) { const greeted = useRef(false); // Send Atlas's opening message automatically on first load useEffect(() => { if (greeted.current) return; greeted.current = true; const opener = `Hey — I'm starting a new project called "${projectName || "my project"}". I'd love your help defining what we're building.`; // Small delay so the thread is mounted before we submit const t = setTimeout(() => { runtime.thread.composer.setText(opener); runtime.thread.composer.send(); }, 300); return () => clearTimeout(t); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleReset = async () => { if (!confirm("Start the discovery conversation over from scratch?")) return; await fetch(`/api/projects/${projectId}/atlas-chat`, { method: "DELETE" }); // Reload to get a fresh runtime state window.location.reload(); }; return (
{/* Minimal header bar */}
{/* Thread */}
); } // --------------------------------------------------------------------------- // Main export — wraps with runtime provider // --------------------------------------------------------------------------- export function AtlasChat({ projectId, projectName }: AtlasChatProps) { const adapter = makeAtlasAdapter(projectId); const runtime = useLocalRuntime(adapter); return ( ); }