2026-01-15 21:58:30 +08:00
|
|
|
from fastapi import APIRouter, HTTPException
|
|
|
|
|
from pytrace.core.registry import NodeRegistry
|
|
|
|
|
from pytrace.core.executor import WorkflowExecutor
|
|
|
|
|
from pytrace.model.graph import WorkflowGraph, Node, Edge
|
|
|
|
|
from ..models.graph import GraphExecuteRequest
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
|
|
|
|
@router.get("/plugins")
|
|
|
|
|
async def get_plugins():
|
|
|
|
|
"""
|
|
|
|
|
Gets the list of all available (registered) nodes and their specifications.
|
|
|
|
|
This is used by the frontend to populate the node palette.
|
|
|
|
|
"""
|
|
|
|
|
specs = NodeRegistry.get_all_specs()
|
|
|
|
|
|
|
|
|
|
# The old protocol expects a dictionary keyed by node type string.
|
|
|
|
|
plugins = {
|
|
|
|
|
spec.type: {
|
|
|
|
|
"display_name": spec.name,
|
|
|
|
|
"category": spec.category,
|
|
|
|
|
"description": spec.description,
|
|
|
|
|
"node_type": spec.node_type.value,
|
|
|
|
|
"class_name": spec.type, # Using the unique type string as class_name
|
|
|
|
|
"inputs": [p.dict() for p in spec.inputs],
|
|
|
|
|
"outputs": [p.dict() for p in spec.outputs],
|
|
|
|
|
"param_schema": [p.dict() for p in spec.params],
|
|
|
|
|
}
|
|
|
|
|
for spec in specs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"plugins": plugins,
|
|
|
|
|
"total": len(plugins),
|
|
|
|
|
"categories": NodeRegistry.get_categories()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@router.post("/execute")
|
|
|
|
|
async def execute_graph(request: GraphExecuteRequest):
|
|
|
|
|
"""
|
|
|
|
|
Executes a workflow graph.
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# 1. Build the WorkflowGraph from the request
|
|
|
|
|
graph = WorkflowGraph(name="Execution Graph")
|
|
|
|
|
for node_data in request.nodes:
|
|
|
|
|
graph.add_node(Node(
|
|
|
|
|
id=node_data.id,
|
|
|
|
|
type=node_data.type,
|
|
|
|
|
name=node_data.name,
|
|
|
|
|
params=node_data.params
|
|
|
|
|
))
|
|
|
|
|
for edge_data in request.edges:
|
|
|
|
|
graph.add_edge(Edge(
|
2026-01-19 00:49:55 +08:00
|
|
|
source_id=edge_data.source_node,
|
2026-01-15 21:58:30 +08:00
|
|
|
source_port=edge_data.source_port,
|
2026-01-19 00:49:55 +08:00
|
|
|
target_id=edge_data.target_node,
|
2026-01-15 21:58:30 +08:00
|
|
|
target_port=edge_data.target_port
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
# 2. Instantiate the executor and run the graph
|
|
|
|
|
executor = WorkflowExecutor()
|
|
|
|
|
results = executor.execute(graph, initial_inputs=request.initial_inputs)
|
|
|
|
|
|
|
|
|
|
# 3. Return the results
|
|
|
|
|
return {
|
|
|
|
|
"success": True,
|
|
|
|
|
"results": results
|
|
|
|
|
}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
import traceback
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=500,
|
|
|
|
|
detail={
|
|
|
|
|
"error": str(e),
|
|
|
|
|
"type": type(e).__name__,
|
|
|
|
|
"traceback": traceback.format_exc()
|
|
|
|
|
}
|
|
|
|
|
)
|