diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index c66a71d..69538f2 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,13 +1,40 @@ import { google } from "@ai-sdk/google"; +import { Message } from "ai/react"; import { streamText } from "ai"; - +import { z } from "zod"; export const maxDuration = 30; +// Define tool interfaces +interface DisplayFlowChartArgs { + xml: string; +} + +interface ToolContext { + getCurrentXML: () => string; + displayChart: (xml: string) => void; +} + export async function POST(req: Request) { const { messages } = await req.json(); - const result = streamText({ + const response = streamText({ model: google("gemini-2.0-flash"), messages, + tools: { + display_flow_chart: { + description: "Display a flowchart on draw.io", + parameters: z.object( + { + xml: z.string().describe("XML string to be displayed on draw.io"), + }, + ) + }, + fetch_flow_chart: { + description: "Get the current flowchart XML from draw.io", + parameters: z.object({}), + } + }, + temperature: 0, }); - return result.toDataStreamResponse(); -} \ No newline at end of file + + return response.toDataStreamResponse(); +} diff --git a/app/page.tsx b/app/page.tsx index 65cb4dc..b2fbb09 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -9,24 +9,23 @@ import ChatPanel from "@/components/chatPanel"; export default function Home() { const drawioRef = useRef(null); const [chartXML, setChartXML] = useState(""); - const [diagram, setDiagram] = useState(""); - // const handleExport = () => {}; + const handleExport = () => { - // use this function to export the diagramxml from the drawio editor if (drawioRef.current) { drawioRef.current.exportDiagram({ format: "xmlsvg", }); } }; + const loadDiagram = (chart: string) => { - // use this function to display the diagramxml in the drawio editor if (drawioRef.current) { drawioRef.current.load({ xml: chart, }); } }; + return (
@@ -34,7 +33,6 @@ export default function Home() { ref={drawioRef} onExport={(data) => setChartXML(extractDiagramXML(data.data))} urlParameters={{ - // ui: "kennedy", spin: true, libraries: false, saveAndExit: false, @@ -42,8 +40,14 @@ export default function Home() { }} />
-
- +
+ loadDiagram(xml)} + onFetchChart={() => { + handleExport(); + return chartXML; + }} + />
); diff --git a/components/chatPanel.tsx b/components/chatPanel.tsx index 2b29abf..d49faa7 100644 --- a/components/chatPanel.tsx +++ b/components/chatPanel.tsx @@ -1,20 +1,41 @@ "use client" import type React from "react" - import { useRef, useEffect } from "react" -import { useChat } from "@ai-sdk/react" + import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" import { ScrollArea } from "@/components/ui/scroll-area" import { Loader2, Send } from "lucide-react" +import { useChat } from '@ai-sdk/react'; +import { ToolInvocation } from 'ai'; -export default function ChatPanel() { - const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({ - api: "/api/chat", - maxSteps: 5, // Allow multiple steps for complex diagram generation +interface ChatPanelProps { + onDisplayChart: (xml: string) => void; + onFetchChart: () => string; +} + +export default function ChatPanel({ onDisplayChart, onFetchChart }: ChatPanelProps) { + const { messages, input, handleInputChange, handleSubmit, isLoading, error, addToolResult } = useChat({ + async onToolCall({ toolCall }) { + console.log("Tool call:", toolCall); + if (toolCall.toolName === "display_flow_chart") { + const { xml } = toolCall.args as { xml: string }; + onDisplayChart(xml); + } else if (toolCall.toolName === "fetch_flow_chart") { + const currentXML = onFetchChart(); + console.log("Current XML:", currentXML); + addToolResult({ + toolCallId: toolCall.toolCallId, + result: currentXML + }); + } + }, + onError: (error) => { + console.error("Chat error:", error); + } }) const messagesEndRef = useRef(null) @@ -25,10 +46,9 @@ export default function ChatPanel() { } }, [messages]) - const onFormSubmit = (e: React.FormEvent) => { e.preventDefault() - if (input.trim()) { + if (input.trim() && !isLoading) { handleSubmit(e) } } @@ -42,7 +62,7 @@ export default function ChatPanel() { {messages.length === 0 ? (
-

Start a conversation to generate a diagram.

+

Start a conversation to generate or modify diagrams.

Try: "Create a flowchart for user authentication"

) : ( @@ -54,16 +74,21 @@ export default function ChatPanel() { > {message.content}
- {message.toolInvocations?.map((tool, index) => ( -
+ {(message as any).function_call && ( +
- {tool.state === "call" ? "Generating diagram..." : "Diagram generated"} + Using tool: {(message as any).function_call.name}...
- ))} + )}
)) )} + {error && ( +
+ Error: {error.message} +
+ )}
@@ -72,7 +97,7 @@ export default function ChatPanel() { @@ -84,4 +109,3 @@ export default function ChatPanel() { ) } -