from core_domain import ServiceHealth from core_dsl import EdgeDefinition, NodeDefinition, WorkflowDefinition from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import text from sqlalchemy.orm import Session from app.application.services import WorkflowApplicationService from app.db.session import get_db from app.domain.repositories import ( AppDefinitionRepository, AppVersionRepository, WorkflowDefinitionRepository, WorkflowVersionRepository, ) from app.schemas.app import ( AppCreateRequest, AppResponse, AppVersionCreateRequest, AppVersionResponse, ) from app.schemas.workflow import ( WorkflowCreateRequest, WorkflowDebuggerPlanRequest, WorkflowDebuggerPlanResponse, WorkflowDefinitionResponse, WorkflowDesignerValidateRequest, WorkflowDesignerValidateResponse, WorkflowVersionCreateRequest, WorkflowVersionResponse, ) router = APIRouter() def get_workflow_application_service(db: Session = Depends(get_db)) -> WorkflowApplicationService: return WorkflowApplicationService( app_repository=AppDefinitionRepository(db), workflow_repository=WorkflowDefinitionRepository(db), app_version_repository=AppVersionRepository(db), workflow_version_repository=WorkflowVersionRepository(db)) @router.get("/health", response_model=ServiceHealth) def health_check(db: Session = Depends(get_db)) -> ServiceHealth: db.execute(text("SELECT 1")) return ServiceHealth(service="workflow-service", status="ok", database="ok") @router.get("/sample", response_model=WorkflowDefinition) def get_sample_workflow() -> WorkflowDefinition: return WorkflowDefinition( code="sample_workflow", name="Sample Workflow", nodes=[ NodeDefinition(id="start", type="llm"), NodeDefinition(id="end", type="answer"), ], edges=[EdgeDefinition(source="start", target="end")]) @router.post("/designer/validate", response_model=WorkflowDesignerValidateResponse) def validate_workflow_designer_dsl( payload: WorkflowDesignerValidateRequest, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> WorkflowDesignerValidateResponse: inspection = service.validate_designer_workflow(payload) return WorkflowDesignerValidateResponse.from_inspection(inspection) @router.post("/designer/debug", response_model=WorkflowDebuggerPlanResponse) def debug_workflow_designer_dsl( payload: WorkflowDebuggerPlanRequest, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> WorkflowDebuggerPlanResponse: plan = service.build_designer_debug_plan(payload) return WorkflowDebuggerPlanResponse.from_plan(plan) @router.post("/apps", response_model=AppResponse) def create_app( payload: AppCreateRequest, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> AppResponse: entity = service.create_app(payload) return AppResponse.from_entity(entity) @router.get("/apps", response_model=list[AppResponse]) def list_apps( service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> list[AppResponse]: return [AppResponse.from_entity(item) for item in service.list_apps()] @router.post("/apps/versions", response_model=AppVersionResponse) def create_app_version( payload: AppVersionCreateRequest, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> AppVersionResponse: entity = service.create_app_version(payload) return AppVersionResponse.from_entity(entity) @router.get("/apps/versions", response_model=list[AppVersionResponse]) def list_app_versions( app_id: str = Query(...), service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> list[AppVersionResponse]: return [AppVersionResponse.from_entity(item) for item in service.list_app_versions(app_id)] @router.post("", response_model=WorkflowDefinitionResponse) def create_workflow( payload: WorkflowCreateRequest, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> WorkflowDefinitionResponse: entity = service.create_workflow(payload) return WorkflowDefinitionResponse.from_entity(entity) @router.get("", response_model=list[WorkflowDefinitionResponse]) def list_workflows( app_id: str | None = Query(default=None), service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> list[WorkflowDefinitionResponse]: items = service.list_workflows(app_id=app_id) return [WorkflowDefinitionResponse.from_entity(item) for item in items] @router.post("/versions", response_model=WorkflowVersionResponse) def create_workflow_version( payload: WorkflowVersionCreateRequest, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> WorkflowVersionResponse: try: entity = service.create_workflow_version(payload) except ValueError as exc: raise HTTPException(status_code=422, detail=str(exc)) from exc return WorkflowVersionResponse.from_entity(entity) @router.get("/versions", response_model=list[WorkflowVersionResponse]) def list_workflow_versions( workflow_id: str = Query(...), service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> list[WorkflowVersionResponse]: items = service.list_workflow_versions(workflow_id=workflow_id) return [WorkflowVersionResponse.from_entity(item) for item in items] @router.get("/versions/{workflow_version_id}", response_model=WorkflowVersionResponse) def get_workflow_version( workflow_version_id: str, service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> WorkflowVersionResponse: entity = service.get_workflow_version(workflow_version_id=workflow_version_id) if entity is None: raise HTTPException(status_code=404, detail=f"workflow_version not found: {workflow_version_id}") return WorkflowVersionResponse.from_entity(entity) @router.get("/versions/{workflow_version_id}/debug", response_model=WorkflowDebuggerPlanResponse) def debug_workflow_version( workflow_version_id: str, max_preview_steps: int = Query(default=50, ge=1, le=500), service: WorkflowApplicationService = Depends(get_workflow_application_service)) -> WorkflowDebuggerPlanResponse: plan = service.build_version_debug_plan( workflow_version_id=workflow_version_id, max_preview_steps=max_preview_steps) if plan is None: raise HTTPException(status_code=404, detail=f"workflow_version not found: {workflow_version_id}") return WorkflowDebuggerPlanResponse.from_plan(plan)