from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import text from sqlalchemy.orm import Session from core_dsl import EdgeDefinition, NodeDefinition, WorkflowDefinition from core_domain import ServiceHealth from app.application.services import WorkflowApplicationService from app.domain.repositories import ( AppDefinitionRepository, AppVersionRepository, WorkflowDefinitionRepository, WorkflowVersionRepository, ) from app.db.session import get_db from app.schemas.app import AppCreateRequest, AppResponse, AppVersionCreateRequest, AppVersionResponse from app.schemas.workflow import ( WorkflowCreateRequest, WorkflowDefinitionResponse, 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("/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( tenant_id: str = Query(...), service: WorkflowApplicationService = Depends(get_workflow_application_service), ) -> list[AppResponse]: return [AppResponse.from_entity(item) for item in service.list_apps(tenant_id)] @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( tenant_id: str = Query(...), 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(tenant_id, 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( tenant_id: str = Query(...), app_id: str | None = Query(default=None), service: WorkflowApplicationService = Depends(get_workflow_application_service), ) -> list[WorkflowDefinitionResponse]: items = service.list_workflows(tenant_id=tenant_id, 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( tenant_id: str = Query(...), workflow_id: str = Query(...), service: WorkflowApplicationService = Depends(get_workflow_application_service), ) -> list[WorkflowVersionResponse]: items = service.list_workflow_versions(tenant_id=tenant_id, 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, tenant_id: str = Query(...), service: WorkflowApplicationService = Depends(get_workflow_application_service), ) -> WorkflowVersionResponse: entity = service.get_workflow_version(tenant_id=tenant_id, 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)