routes.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from fastapi import APIRouter, Depends, HTTPException, Query
  2. from sqlalchemy import text
  3. from sqlalchemy.orm import Session
  4. from core_domain import ServiceHealth
  5. from app.application.services import SkillApplicationService
  6. from app.db.session import get_db
  7. from app.domain.repositories import (
  8. SkillDefinitionRepository,
  9. SkillInstallationRepository,
  10. SkillRunRepository,
  11. SkillVersionRepository,
  12. )
  13. from app.schemas.skill import (
  14. SkillCreateRequest,
  15. SkillInstallRequest,
  16. SkillInstallationResponse,
  17. SkillInstallationStatusUpdateRequest,
  18. SkillResponse,
  19. SkillRunCreateRequest,
  20. SkillRunExecuteRequest,
  21. SkillRunResponse,
  22. SkillStatusUpdateRequest,
  23. SkillVersionCreateRequest,
  24. SkillVersionResponse,
  25. )
  26. router = APIRouter()
  27. def get_skill_application_service(db: Session = Depends(get_db)) -> SkillApplicationService:
  28. return SkillApplicationService(
  29. skill_repository=SkillDefinitionRepository(db),
  30. skill_version_repository=SkillVersionRepository(db),
  31. installation_repository=SkillInstallationRepository(db),
  32. skill_run_repository=SkillRunRepository(db),
  33. )
  34. @router.get("/health", response_model=ServiceHealth)
  35. def health_check(db: Session = Depends(get_db)) -> ServiceHealth:
  36. db.execute(text("SELECT 1"))
  37. return ServiceHealth(service="skill-service", status="ok", database="ok")
  38. @router.post("", response_model=SkillResponse)
  39. def create_skill(
  40. payload: SkillCreateRequest,
  41. service: SkillApplicationService = Depends(get_skill_application_service),
  42. ) -> SkillResponse:
  43. return SkillResponse.from_entity(service.create_skill(payload))
  44. @router.get("", response_model=list[SkillResponse])
  45. def list_skills(
  46. tenant_id: str = Query(...),
  47. service: SkillApplicationService = Depends(get_skill_application_service),
  48. ) -> list[SkillResponse]:
  49. return [SkillResponse.from_entity(item) for item in service.list_skills(tenant_id=tenant_id)]
  50. @router.patch("/{skill_id}/status", response_model=SkillResponse)
  51. def update_skill_status(
  52. skill_id: str,
  53. payload: SkillStatusUpdateRequest,
  54. service: SkillApplicationService = Depends(get_skill_application_service),
  55. ) -> SkillResponse:
  56. entity = service.update_skill_status(skill_id=skill_id, payload=payload)
  57. if entity is None:
  58. raise HTTPException(status_code=404, detail=f"skill not found: {skill_id}")
  59. return SkillResponse.from_entity(entity)
  60. @router.post("/versions", response_model=SkillVersionResponse)
  61. def create_skill_version(
  62. payload: SkillVersionCreateRequest,
  63. service: SkillApplicationService = Depends(get_skill_application_service),
  64. ) -> SkillVersionResponse:
  65. try:
  66. return SkillVersionResponse.from_entity(service.create_skill_version(payload))
  67. except ValueError as exc:
  68. raise HTTPException(status_code=422, detail=str(exc)) from exc
  69. @router.get("/versions", response_model=list[SkillVersionResponse])
  70. def list_skill_versions(
  71. tenant_id: str = Query(...),
  72. skill_id: str = Query(...),
  73. service: SkillApplicationService = Depends(get_skill_application_service),
  74. ) -> list[SkillVersionResponse]:
  75. return [
  76. SkillVersionResponse.from_entity(item)
  77. for item in service.list_skill_versions(tenant_id=tenant_id, skill_id=skill_id)
  78. ]
  79. @router.post("/installations", response_model=SkillInstallationResponse)
  80. def install_skill(
  81. payload: SkillInstallRequest,
  82. service: SkillApplicationService = Depends(get_skill_application_service),
  83. ) -> SkillInstallationResponse:
  84. try:
  85. return SkillInstallationResponse.from_entity(service.install_skill(payload))
  86. except ValueError as exc:
  87. raise HTTPException(status_code=422, detail=str(exc)) from exc
  88. @router.get("/installations", response_model=list[SkillInstallationResponse])
  89. def list_installations(
  90. tenant_id: str = Query(...),
  91. install_scope: str | None = Query(default=None),
  92. scope_id: str | None = Query(default=None),
  93. service: SkillApplicationService = Depends(get_skill_application_service),
  94. ) -> list[SkillInstallationResponse]:
  95. return [
  96. SkillInstallationResponse.from_entity(item)
  97. for item in service.list_installations(
  98. tenant_id=tenant_id,
  99. install_scope=install_scope,
  100. scope_id=scope_id,
  101. )
  102. ]
  103. @router.patch("/installations/{installation_id}/status", response_model=SkillInstallationResponse)
  104. def update_installation_status(
  105. installation_id: str,
  106. payload: SkillInstallationStatusUpdateRequest,
  107. service: SkillApplicationService = Depends(get_skill_application_service),
  108. ) -> SkillInstallationResponse:
  109. entity = service.update_installation_status(installation_id=installation_id, payload=payload)
  110. if entity is None:
  111. raise HTTPException(status_code=404, detail=f"skill installation not found: {installation_id}")
  112. return SkillInstallationResponse.from_entity(entity)
  113. @router.post("/runs", response_model=SkillRunResponse)
  114. def create_skill_run(
  115. payload: SkillRunCreateRequest,
  116. service: SkillApplicationService = Depends(get_skill_application_service),
  117. ) -> SkillRunResponse:
  118. try:
  119. return SkillRunResponse.from_entity(service.create_skill_run(payload))
  120. except ValueError as exc:
  121. raise HTTPException(status_code=422, detail=str(exc)) from exc
  122. @router.post("/runs/{skill_run_id}/execute", response_model=SkillRunResponse)
  123. def execute_skill_run(
  124. skill_run_id: str,
  125. payload: SkillRunExecuteRequest,
  126. service: SkillApplicationService = Depends(get_skill_application_service),
  127. ) -> SkillRunResponse:
  128. entity = service.execute_skill_run(skill_run_id=skill_run_id, payload=payload)
  129. if entity is None:
  130. raise HTTPException(status_code=404, detail=f"skill_run not found: {skill_run_id}")
  131. return SkillRunResponse.from_entity(entity)