Spaces:
Sleeping
Sleeping
File size: 3,043 Bytes
d6815ad |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
"""
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
}
|