diff --git a/app/[workspace]/project/[projectId]/build/page.tsx b/app/[workspace]/project/[projectId]/build/page.tsx index 9c5a456..3185bf4 100644 --- a/app/[workspace]/project/[projectId]/build/page.tsx +++ b/app/[workspace]/project/[projectId]/build/page.tsx @@ -812,181 +812,6 @@ function TerminalPanel({ appName }: { appName: string }) { ); } -// ── COO / Assist chat — persistent left-side advisor ───────────────────────── - -interface CooMessage { - id: string; - role: "user" | "assistant"; - content: string; - streaming?: boolean; -} - -const WELCOME: CooMessage = { - id: "welcome", - role: "assistant", - content: "Hi. I'm your product COO — I know your codebase, your goals, and what's been built. What do you need?", -}; - -function CooChat({ projectId, projectName }: { projectId: string; projectName: string }) { - const [messages, setMessages] = useState([WELCOME]); - const [input, setInput] = useState(""); - const [loading, setLoading] = useState(false); - const bottomRef = useRef(null); - const textareaRef = useRef(null); - - useEffect(() => { - bottomRef.current?.scrollIntoView({ behavior: "smooth" }); - }, [messages]); - - const send = async () => { - const text = input.trim(); - if (!text || loading) return; - setInput(""); - - const userMsg: CooMessage = { id: Date.now().toString(), role: "user", content: text }; - const assistantId = (Date.now() + 1).toString(); - const assistantMsg: CooMessage = { id: assistantId, role: "assistant", content: "", streaming: true }; - - setMessages(prev => [...prev, userMsg, assistantMsg]); - setLoading(true); - - // Build history for the API (exclude welcome message, exclude the new blank assistant placeholder) - const history = messages - .filter(m => m.id !== "welcome" && m.content) - .map(m => ({ role: m.role === "assistant" ? "model" as const : "user" as const, content: m.content })); - - try { - const res = await fetch(`/api/projects/${projectId}/advisor`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ message: text, history }), - }); - - if (!res.ok || !res.body) { - setMessages(prev => prev.map(m => m.id === assistantId - ? { ...m, content: "Something went wrong. Please try again.", streaming: false } - : m)); - return; - } - - const reader = res.body.getReader(); - const decoder = new TextDecoder(); - - while (true) { - const { done, value } = await reader.read(); - if (done) break; - const chunk = decoder.decode(value, { stream: true }); - setMessages(prev => prev.map(m => m.id === assistantId - ? { ...m, content: m.content + chunk } - : m)); - } - - setMessages(prev => prev.map(m => m.id === assistantId ? { ...m, streaming: false } : m)); - } catch { - setMessages(prev => prev.map(m => m.id === assistantId - ? { ...m, content: "Connection error. Please try again.", streaming: false } - : m)); - } finally { - setLoading(false); - textareaRef.current?.focus(); - } - }; - - return ( -
- {/* Messages */} -
- {messages.map(msg => ( -
- {msg.role === "assistant" && ( - - )} -
- {msg.content || (msg.streaming ? "" : "")} - {msg.streaming && msg.content === "" && ( - - {[0, 1, 2].map(i => ( - - ))} - - )} - {msg.streaming && msg.content !== "" && ( - - )} -
-
- ))} -
-
- - {/* Input */} -
-
-