""" Workflow CRUD endpoints """ from fastapi import APIRouter, HTTPException from models.workflow import Workflow, Node, Edge from typing import Optional router = APIRouter() # In-memory storage for MVP (frontend uses localStorage, this is for API testing) workflows_db: dict[str, Workflow] = {} @router.get("/") async def list_workflows(): """List all workflows""" return {"workflows": list(workflows_db.values())} @router.get("/{workflow_id}") async def get_workflow(workflow_id: str): """Get a specific workflow by ID""" if workflow_id not in workflows_db: raise HTTPException(status_code=404, detail="Workflow not found") return workflows_db[workflow_id] @router.post("/") async def create_workflow(workflow: Workflow): """Create a new workflow""" workflows_db[workflow.id] = workflow return {"message": "Workflow created", "workflow": workflow} @router.put("/{workflow_id}") async def update_workflow(workflow_id: str, workflow: Workflow): """Update an existing workflow""" if workflow_id not in workflows_db: raise HTTPException(status_code=404, detail="Workflow not found") workflow.id = workflow_id # Ensure ID matches workflows_db[workflow_id] = workflow return {"message": "Workflow updated", "workflow": workflow} @router.delete("/{workflow_id}") async def delete_workflow(workflow_id: str): """Delete a workflow""" if workflow_id not in workflows_db: raise HTTPException(status_code=404, detail="Workflow not found") del workflows_db[workflow_id] return {"message": "Workflow deleted"} @router.post("/validate") async def validate_workflow(workflow: Workflow): """Validate a workflow structure (Guardian pre-check)""" errors = [] warnings = [] # Check for trigger node trigger_nodes = [n for n in workflow.nodes if n.type == "trigger"] if len(trigger_nodes) == 0: errors.append("Workflow must have at least one trigger node") elif len(trigger_nodes) > 1: warnings.append("Multiple trigger nodes found - only first will be used") # Check for orphan nodes (no connections) connected_nodes = set() for edge in workflow.edges: connected_nodes.add(edge.source) connected_nodes.add(edge.target) for node in workflow.nodes: if node.id not in connected_nodes and node.type != "trigger": warnings.append(f"Node '{node.data.label}' is not connected to any other node") # Check LLM nodes have required fields for node in workflow.nodes: if node.type == "llm": if not node.data.provider: errors.append(f"LLM node '{node.data.label}' must have a provider") if not node.data.model: errors.append(f"LLM node '{node.data.label}' must have a model") return { "valid": len(errors) == 0, "errors": errors, "warnings": warnings }