routes.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. from fastapi import APIRouter, Depends, HTTPException, Query
  2. from sqlalchemy import text
  3. from sqlalchemy.orm import Session
  4. from core_dsl import EdgeDefinition, NodeDefinition, WorkflowDefinition
  5. from core_domain import ServiceHealth
  6. from app.application.services import WorkflowApplicationService
  7. from app.domain.repositories import (
  8. AppDefinitionRepository,
  9. AppVersionRepository,
  10. WorkflowDefinitionRepository,
  11. WorkflowVersionRepository,
  12. )
  13. from app.db.session import get_db
  14. from app.schemas.app import AppCreateRequest, AppResponse, AppVersionCreateRequest, AppVersionResponse
  15. from app.schemas.workflow import (
  16. WorkflowCreateRequest,
  17. WorkflowDefinitionResponse,
  18. WorkflowDebuggerPlanRequest,
  19. WorkflowDebuggerPlanResponse,
  20. WorkflowDesignerValidateRequest,
  21. WorkflowDesignerValidateResponse,
  22. WorkflowVersionCreateRequest,
  23. WorkflowVersionResponse,
  24. )
  25. router = APIRouter()
  26. def get_workflow_application_service(db: Session = Depends(get_db)) -> WorkflowApplicationService:
  27. return WorkflowApplicationService(
  28. app_repository=AppDefinitionRepository(db),
  29. workflow_repository=WorkflowDefinitionRepository(db),
  30. app_version_repository=AppVersionRepository(db),
  31. workflow_version_repository=WorkflowVersionRepository(db),
  32. )
  33. @router.get("/health", response_model=ServiceHealth)
  34. def health_check(db: Session = Depends(get_db)) -> ServiceHealth:
  35. db.execute(text("SELECT 1"))
  36. return ServiceHealth(service="workflow-service", status="ok", database="ok")
  37. @router.get("/sample", response_model=WorkflowDefinition)
  38. def get_sample_workflow() -> WorkflowDefinition:
  39. return WorkflowDefinition(
  40. code="sample_workflow",
  41. name="Sample Workflow",
  42. nodes=[
  43. NodeDefinition(id="start", type="llm"),
  44. NodeDefinition(id="end", type="answer"),
  45. ],
  46. edges=[EdgeDefinition(source="start", target="end")],
  47. )
  48. @router.post("/designer/validate", response_model=WorkflowDesignerValidateResponse)
  49. def validate_workflow_designer_dsl(
  50. payload: WorkflowDesignerValidateRequest,
  51. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  52. ) -> WorkflowDesignerValidateResponse:
  53. inspection = service.validate_designer_workflow(payload)
  54. return WorkflowDesignerValidateResponse.from_inspection(inspection)
  55. @router.post("/designer/debug", response_model=WorkflowDebuggerPlanResponse)
  56. def debug_workflow_designer_dsl(
  57. payload: WorkflowDebuggerPlanRequest,
  58. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  59. ) -> WorkflowDebuggerPlanResponse:
  60. plan = service.build_designer_debug_plan(payload)
  61. return WorkflowDebuggerPlanResponse.from_plan(plan)
  62. @router.post("/apps", response_model=AppResponse)
  63. def create_app(
  64. payload: AppCreateRequest,
  65. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  66. ) -> AppResponse:
  67. entity = service.create_app(payload)
  68. return AppResponse.from_entity(entity)
  69. @router.get("/apps", response_model=list[AppResponse])
  70. def list_apps(
  71. tenant_id: str = Query(...),
  72. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  73. ) -> list[AppResponse]:
  74. return [AppResponse.from_entity(item) for item in service.list_apps(tenant_id)]
  75. @router.post("/apps/versions", response_model=AppVersionResponse)
  76. def create_app_version(
  77. payload: AppVersionCreateRequest,
  78. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  79. ) -> AppVersionResponse:
  80. entity = service.create_app_version(payload)
  81. return AppVersionResponse.from_entity(entity)
  82. @router.get("/apps/versions", response_model=list[AppVersionResponse])
  83. def list_app_versions(
  84. tenant_id: str = Query(...),
  85. app_id: str = Query(...),
  86. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  87. ) -> list[AppVersionResponse]:
  88. return [AppVersionResponse.from_entity(item) for item in service.list_app_versions(tenant_id, app_id)]
  89. @router.post("", response_model=WorkflowDefinitionResponse)
  90. def create_workflow(
  91. payload: WorkflowCreateRequest,
  92. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  93. ) -> WorkflowDefinitionResponse:
  94. entity = service.create_workflow(payload)
  95. return WorkflowDefinitionResponse.from_entity(entity)
  96. @router.get("", response_model=list[WorkflowDefinitionResponse])
  97. def list_workflows(
  98. tenant_id: str = Query(...),
  99. app_id: str | None = Query(default=None),
  100. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  101. ) -> list[WorkflowDefinitionResponse]:
  102. items = service.list_workflows(tenant_id=tenant_id, app_id=app_id)
  103. return [WorkflowDefinitionResponse.from_entity(item) for item in items]
  104. @router.post("/versions", response_model=WorkflowVersionResponse)
  105. def create_workflow_version(
  106. payload: WorkflowVersionCreateRequest,
  107. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  108. ) -> WorkflowVersionResponse:
  109. try:
  110. entity = service.create_workflow_version(payload)
  111. except ValueError as exc:
  112. raise HTTPException(status_code=422, detail=str(exc)) from exc
  113. return WorkflowVersionResponse.from_entity(entity)
  114. @router.get("/versions", response_model=list[WorkflowVersionResponse])
  115. def list_workflow_versions(
  116. tenant_id: str = Query(...),
  117. workflow_id: str = Query(...),
  118. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  119. ) -> list[WorkflowVersionResponse]:
  120. items = service.list_workflow_versions(tenant_id=tenant_id, workflow_id=workflow_id)
  121. return [WorkflowVersionResponse.from_entity(item) for item in items]
  122. @router.get("/versions/{workflow_version_id}", response_model=WorkflowVersionResponse)
  123. def get_workflow_version(
  124. workflow_version_id: str,
  125. tenant_id: str = Query(...),
  126. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  127. ) -> WorkflowVersionResponse:
  128. entity = service.get_workflow_version(tenant_id=tenant_id, workflow_version_id=workflow_version_id)
  129. if entity is None:
  130. raise HTTPException(status_code=404, detail=f"workflow_version not found: {workflow_version_id}")
  131. return WorkflowVersionResponse.from_entity(entity)
  132. @router.get("/versions/{workflow_version_id}/debug", response_model=WorkflowDebuggerPlanResponse)
  133. def debug_workflow_version(
  134. workflow_version_id: str,
  135. tenant_id: str = Query(...),
  136. max_preview_steps: int = Query(default=50, ge=1, le=500),
  137. service: WorkflowApplicationService = Depends(get_workflow_application_service),
  138. ) -> WorkflowDebuggerPlanResponse:
  139. plan = service.build_version_debug_plan(
  140. tenant_id=tenant_id,
  141. workflow_version_id=workflow_version_id,
  142. max_preview_steps=max_preview_steps,
  143. )
  144. if plan is None:
  145. raise HTTPException(status_code=404, detail=f"workflow_version not found: {workflow_version_id}")
  146. return WorkflowDebuggerPlanResponse.from_plan(plan)