skill.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. from datetime import datetime
  2. from typing import TYPE_CHECKING, Generic, TypeVar
  3. from core_domain import (
  4. SkillDefinitionContract,
  5. SkillInstallationContract,
  6. SkillInstallStatus,
  7. SkillRunContract,
  8. SkillStatus,
  9. )
  10. from core_shared import JSONValue
  11. from pydantic import BaseModel, Field
  12. if TYPE_CHECKING:
  13. from app.db.models import SkillDefinition, SkillInstallation, SkillRun
  14. T = TypeVar("T")
  15. class ApiErrorResponse(BaseModel):
  16. errorType: str
  17. message: str
  18. details: dict[str, JSONValue] = Field(default_factory=dict)
  19. class ApiResponse(BaseModel, Generic[T]):
  20. success: bool = True
  21. data: T | None = None
  22. error: ApiErrorResponse | None = None
  23. requestId: str
  24. serverTime: datetime
  25. class PageRequest(BaseModel):
  26. page: int = Field(default=1, ge=1)
  27. pageSize: int = Field(default=20, ge=1, le=200)
  28. keyword: str | None = None
  29. @property
  30. def offset(self) -> int:
  31. return (self.page - 1) * self.pageSize
  32. class PageResult(BaseModel, Generic[T]):
  33. items: list[T]
  34. total: int
  35. page: int
  36. pageSize: int
  37. hasMore: bool
  38. @classmethod
  39. def from_items(
  40. cls,
  41. *,
  42. items: list[T],
  43. total: int,
  44. page: int,
  45. page_size: int) -> "PageResult[T]":
  46. return cls(
  47. items=items,
  48. total=total,
  49. page=page,
  50. pageSize=page_size,
  51. hasMore=page * page_size < total)
  52. class SkillCreateRequest(BaseModel):
  53. code: str
  54. name: str
  55. skill_type: str = "template"
  56. description: str | None = None
  57. runtime_type: str = "template"
  58. entrypoint: str | None = None
  59. parameter_schema_json: dict[str, JSONValue] = Field(default_factory=dict)
  60. output_schema_json: dict[str, JSONValue] = Field(default_factory=dict)
  61. implementation_json: dict[str, JSONValue] = Field(default_factory=dict)
  62. owner_user_id: str | None = None
  63. metadata_json: dict[str, JSONValue] = Field(default_factory=dict)
  64. class SkillStatusUpdateRequest(BaseModel):
  65. status: SkillStatus
  66. class SkillResponse(SkillDefinitionContract):
  67. @classmethod
  68. def from_entity(cls, entity: "SkillDefinition") -> "SkillResponse":
  69. return cls.model_validate(entity, from_attributes=True)
  70. class SkillInstallRequest(BaseModel):
  71. skill_id: str
  72. install_scope: str = "global"
  73. scope_id: str
  74. config_json: dict[str, JSONValue] = Field(default_factory=dict)
  75. installed_by: str | None = None
  76. class SkillInstallationStatusUpdateRequest(BaseModel):
  77. status: SkillInstallStatus
  78. class SkillInstallationResponse(SkillInstallationContract):
  79. @classmethod
  80. def from_entity(cls, entity: "SkillInstallation") -> "SkillInstallationResponse":
  81. return cls.model_validate(entity, from_attributes=True)
  82. class SkillRunCreateRequest(BaseModel):
  83. skill_id: str
  84. installation_id: str | None = None
  85. input_json: dict[str, JSONValue] = Field(default_factory=dict)
  86. class SkillRunExecuteRequest(BaseModel):
  87. skillRunId: str | None = None
  88. worker_key: str | None = None
  89. class SkillRunResponse(SkillRunContract):
  90. @classmethod
  91. def from_entity(cls, entity: "SkillRun") -> "SkillRunResponse":
  92. return cls.model_validate(entity, from_attributes=True)
  93. class SkillRunDto(BaseModel):
  94. id: str
  95. skillId: str
  96. installationId: str | None = None
  97. status: str
  98. input: dict[str, JSONValue] = Field(default_factory=dict)
  99. output: dict[str, JSONValue] | None = None
  100. outputText: str | None = None
  101. workerKey: str | None = None
  102. startedTime: datetime | None = None
  103. finishedTime: datetime | None = None
  104. errorCode: str | None = None
  105. errorMessage: str | None = None
  106. createdTime: datetime
  107. @classmethod
  108. def from_entity(cls, entity: "SkillRun") -> "SkillRunDto":
  109. return cls(
  110. id=entity.id,
  111. skillId=entity.skill_id,
  112. installationId=entity.installation_id,
  113. status=entity.status,
  114. input=entity.input_json or {},
  115. output=entity.output_json,
  116. outputText=entity.output_text,
  117. workerKey=entity.worker_key,
  118. startedTime=entity.started_time,
  119. finishedTime=entity.finished_time,
  120. errorCode=entity.error_code,
  121. errorMessage=entity.error_message,
  122. createdTime=entity.created_time)
  123. class SkillRunCreateRequestDto(BaseModel):
  124. skillId: str
  125. installationId: str | None = None
  126. input: dict[str, JSONValue] = Field(default_factory=dict)
  127. class SkillRunExecuteRequestDto(BaseModel):
  128. skillRunId: str
  129. workerKey: str | None = None
  130. class SkillDefinitionDto(BaseModel):
  131. id: str
  132. name: str
  133. skillType: str
  134. description: str | None = None
  135. status: SkillStatus
  136. ownerUserId: str | None = None
  137. metadata: dict[str, JSONValue] = Field(default_factory=dict)
  138. category: str = "service"
  139. instruction: str = ""
  140. toolIds: list[str] = Field(default_factory=list)
  141. runtimeType: str = "template"
  142. entrypoint: str | None = None
  143. parameterSchema: dict[str, JSONValue] = Field(default_factory=dict)
  144. outputSchema: dict[str, JSONValue] = Field(default_factory=dict)
  145. implementation: dict[str, JSONValue] = Field(default_factory=dict)
  146. createdTime: datetime
  147. @classmethod
  148. def from_entity(cls, entity: "SkillDefinition") -> "SkillDefinitionDto":
  149. metadata = dict(entity.metadata_json or {})
  150. tool_ids = metadata.get("toolIds")
  151. return cls(
  152. id=entity.id,
  153. name=entity.name,
  154. skillType=entity.skill_type,
  155. description=entity.description,
  156. status=entity.status,
  157. ownerUserId=entity.owner_user_id,
  158. metadata=metadata,
  159. category=str(metadata.get("category") or "service"),
  160. instruction=str(metadata.get("instruction") or ""),
  161. toolIds=[str(item) for item in tool_ids] if isinstance(tool_ids, list) else [],
  162. runtimeType=entity.runtime_type,
  163. entrypoint=entity.entrypoint,
  164. parameterSchema=entity.parameter_schema_json,
  165. outputSchema=entity.output_schema_json,
  166. implementation=entity.implementation_json,
  167. createdTime=entity.created_time)
  168. class SkillListRequestDto(PageRequest):
  169. status: SkillStatus | None = None
  170. skillType: str | None = None
  171. category: str | None = None
  172. class SkillCreateRequestDto(BaseModel):
  173. name: str
  174. skillType: str = "template"
  175. description: str | None = None
  176. category: str = "service"
  177. instruction: str = ""
  178. toolIds: list[str] = Field(default_factory=list)
  179. runtimeType: str = "template"
  180. entrypoint: str | None = None
  181. parameterSchema: dict[str, JSONValue] = Field(default_factory=dict)
  182. outputSchema: dict[str, JSONValue] = Field(default_factory=dict)
  183. implementation: dict[str, JSONValue] = Field(default_factory=dict)
  184. ownerUserId: str | None = None
  185. metadata: dict[str, JSONValue] = Field(default_factory=dict)
  186. class SkillDetailRequestDto(BaseModel):
  187. skillId: str
  188. class SkillUpdateRequestDto(BaseModel):
  189. skillId: str
  190. name: str | None = None
  191. skillType: str | None = None
  192. description: str | None = None
  193. category: str | None = None
  194. instruction: str | None = None
  195. toolIds: list[str] | None = None
  196. runtimeType: str | None = None
  197. entrypoint: str | None = None
  198. parameterSchema: dict[str, JSONValue] | None = None
  199. outputSchema: dict[str, JSONValue] | None = None
  200. implementation: dict[str, JSONValue] | None = None
  201. ownerUserId: str | None = None
  202. metadata: dict[str, JSONValue] | None = None
  203. class SkillStatusRequestDto(BaseModel):
  204. skillId: str
  205. status: SkillStatus
  206. class SkillDeleteRequestDto(BaseModel):
  207. skillId: str
  208. class SkillInstallationDto(BaseModel):
  209. id: str
  210. skillId: str
  211. installScope: str
  212. scopeId: str | None = None
  213. status: SkillInstallStatus
  214. config: dict[str, JSONValue] = Field(default_factory=dict)
  215. installedBy: str | None = None
  216. installedTime: datetime | None = None
  217. createdTime: datetime
  218. @classmethod
  219. def from_entity(cls, entity: "SkillInstallation") -> "SkillInstallationDto":
  220. return cls(
  221. id=entity.id,
  222. skillId=entity.skill_id,
  223. installScope=entity.install_scope,
  224. scopeId=entity.scope_id,
  225. status=entity.status,
  226. config=entity.config_json or {},
  227. installedBy=entity.installed_by,
  228. installedTime=entity.installed_time,
  229. createdTime=entity.created_time)
  230. class SkillInstallationListRequestDto(PageRequest):
  231. installScope: str | None = None
  232. scopeId: str | None = None
  233. status: SkillInstallStatus | None = None
  234. class SkillInstallRequestDto(BaseModel):
  235. skillId: str
  236. installScope: str = "global"
  237. scopeId: str = "global"
  238. config: dict[str, JSONValue] = Field(default_factory=dict)
  239. installedBy: str | None = None
  240. class SkillInstallationStatusRequestDto(BaseModel):
  241. installationId: str
  242. status: SkillInstallStatus
  243. class DeleteData(BaseModel):
  244. deleted: bool
  245. skillId: str | None = None
  246. installationId: str | None = None