"use client" import { useCallback, useEffect, useMemo, useState } from "react" import { useRouter } from "next/navigation" import { ArrowLeftIcon, CheckCircle2Icon, GitBranchIcon, SaveIcon, SendIcon } from "lucide-react" import { toast } from "sonner" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { fetchAIAgent, fetchAIAgentWorkflow, fetchAIWorkflowNodeSpecs, publishAIAgentWorkflow, saveAIAgentWorkflow, validateAIWorkflow, type AIAgent, type AIWorkflow, type AIWorkflowDefinition, type AIWorkflowNodeSpec, type AIWorkflowValidationResult, } from "@/lib/api/admin" import { WorkflowEditor } from "../../ai-workflows/_components/workflow-editor" const emptyDefinition: AIWorkflowDefinition = { schemaVersion: 1, entryNodeId: "start_1", nodes: [ { id: "start_1", type: "start", name: "Start", position: { x: 0, y: 80 }, config: {}, }, { id: "end_1", type: "end", name: "End", position: { x: 360, y: 80 }, config: {}, }, ], edges: [{ id: "edge_start_end", source: "start_1", target: "end_1" }], } function readAgentIdFromLocation() { if (typeof window === "undefined") { return 0 } return Number(new URLSearchParams(window.location.search).get("agentId")) } export default function DashboardAIAgentWorkflowPage() { const router = useRouter() const [agentId] = useState(() => readAgentIdFromLocation()) const [agent, setAgent] = useState(null) const [workflow, setWorkflow] = useState(null) const [nodeSpecs, setNodeSpecs] = useState([]) const [name, setName] = useState("") const [description, setDescription] = useState("") const [definition, setDefinition] = useState(emptyDefinition) const [validation, setValidation] = useState(null) const [loading, setLoading] = useState(false) const editorKey = useMemo( () => `${workflow?.id ?? "new"}-${workflow?.updatedAt ?? ""}`, [workflow?.id, workflow?.updatedAt] ) const loadData = useCallback(async () => { if (!Number.isFinite(agentId) || agentId <= 0) { return } const [agentDetail, workflowDetail, specs] = await Promise.all([ fetchAIAgent(agentId), fetchAIAgentWorkflow(agentId), fetchAIWorkflowNodeSpecs(), ]) setAgent(agentDetail) setWorkflow(workflowDetail) setNodeSpecs(specs ?? []) setName(workflowDetail.name || `${agentDetail.name} 会话流程`) setDescription(workflowDetail.description || "") setDefinition(workflowDetail.draftDefinition ?? emptyDefinition) setValidation(null) }, [agentId]) useEffect(() => { void loadData().catch((error) => { toast.error(error instanceof Error ? error.message : "Failed to load workflow") }) }, [loadData]) const saveDraft = async () => { if (!Number.isFinite(agentId) || agentId <= 0) { toast.error("Invalid AI Agent.") return } setLoading(true) try { const saved = await saveAIAgentWorkflow({ agentId, name, description, definition, }) setWorkflow(saved) toast.success("Draft saved") } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to save workflow") } finally { setLoading(false) } } const runValidation = async () => { setLoading(true) try { const result = await validateAIWorkflow(definition) setValidation(result) toast[result.valid ? "success" : "error"]( result.valid ? "Workflow is valid" : "Workflow has validation errors" ) } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to validate workflow") } finally { setLoading(false) } } const publish = async () => { if (!Number.isFinite(agentId) || agentId <= 0) { toast.error("Invalid AI Agent.") return } setLoading(true) try { const saved = await saveAIAgentWorkflow({ agentId, name, description, definition, }) setWorkflow(saved) const version = await publishAIAgentWorkflow(agentId, definition) toast.success(`Published version ${version.version}`) await loadData() } catch (error) { toast.error(error instanceof Error ? error.message : "Failed to publish workflow") } finally { setLoading(false) } } return (

{agent ? `${agent.name} · 会话流程` : "AI Agent Workflow"}

Edit and publish this Agent's customer-service conversation flow.