tool.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. from datetime import datetime
  2. from typing import TYPE_CHECKING, Generic, TypeVar
  3. from core_domain import (
  4. ToolBindingContract,
  5. ToolBindingDetailContract,
  6. ToolCredentialContract,
  7. ToolCredentialRevealContract,
  8. ToolDefinitionContract,
  9. ToolConnectionContract,
  10. )
  11. from core_shared import JSONValue
  12. from pydantic import BaseModel, Field
  13. if TYPE_CHECKING:
  14. from app.db.models import ToolBinding, ToolCredential, ToolDefinition, ToolConnection
  15. T = TypeVar("T")
  16. class ApiErrorResponse(BaseModel):
  17. errorType: str
  18. message: str
  19. details: dict[str, JSONValue] = Field(default_factory=dict)
  20. class ApiResponse(BaseModel, Generic[T]):
  21. success: bool = True
  22. data: T | None = None
  23. error: ApiErrorResponse | None = None
  24. requestId: str
  25. serverTime: datetime
  26. class PageRequest(BaseModel):
  27. page: int = Field(default=1, ge=1)
  28. pageSize: int = Field(default=20, ge=1, le=200)
  29. keyword: str | None = None
  30. @property
  31. def offset(self) -> int:
  32. return (self.page - 1) * self.pageSize
  33. class PageResult(BaseModel, Generic[T]):
  34. items: list[T]
  35. total: int
  36. page: int
  37. pageSize: int
  38. hasMore: bool
  39. @classmethod
  40. def from_items(
  41. cls,
  42. *,
  43. items: list[T],
  44. total: int,
  45. page: int,
  46. page_size: int) -> "PageResult[T]":
  47. return cls(
  48. items=items,
  49. total=total,
  50. page=page,
  51. pageSize=page_size,
  52. hasMore=page * page_size < total)
  53. class ToolCreateRequest(BaseModel):
  54. plugin_id: str | None = None
  55. code: str | None = None
  56. name: str
  57. tool_type: str
  58. description: str | None = None
  59. class ToolResponse(ToolDefinitionContract):
  60. @classmethod
  61. def from_entity(cls, entity: "ToolDefinition") -> "ToolResponse":
  62. return cls.model_validate(entity, from_attributes=True)
  63. class ToolConnectionCreateRequest(BaseModel):
  64. tool_id: str
  65. input_schema_json: dict[str, JSONValue] = Field(default_factory=dict)
  66. output_schema_json: dict[str, JSONValue] = Field(default_factory=dict)
  67. invoke_config_json: dict[str, JSONValue] = Field(default_factory=dict)
  68. timeout_ms: int | None = None
  69. retry_policy_json: dict[str, JSONValue] = Field(default_factory=dict)
  70. class ToolConnectionResponse(ToolConnectionContract):
  71. @classmethod
  72. def from_entity(cls, entity: "ToolConnection") -> "ToolConnectionResponse":
  73. return cls.model_validate(entity, from_attributes=True)
  74. class ToolBindingCreateRequest(BaseModel):
  75. app_id: str
  76. tool_connection_id: str
  77. credential_id: str | None = None
  78. binding_scope: str = "app"
  79. enabled: bool = True
  80. config_json: dict[str, JSONValue] = Field(default_factory=dict)
  81. class ToolBindingResponse(ToolBindingContract):
  82. @classmethod
  83. def from_entity(cls, entity: "ToolBinding") -> "ToolBindingResponse":
  84. return cls.model_validate(entity, from_attributes=True)
  85. class ToolBindingDetailResponse(ToolBindingDetailContract):
  86. binding: ToolBindingResponse
  87. connection: ToolConnectionResponse
  88. tool_definition: ToolResponse
  89. class ToolCredentialCreateRequest(BaseModel):
  90. name: str
  91. credential_type: str = "generic"
  92. secret_json: dict[str, JSONValue] = Field(default_factory=dict)
  93. metadata_json: dict[str, JSONValue] = Field(default_factory=dict)
  94. class ToolCredentialResponse(ToolCredentialContract):
  95. @classmethod
  96. def from_entity(cls, entity: "ToolCredential") -> "ToolCredentialResponse":
  97. return cls.model_validate(entity, from_attributes=True)
  98. class ToolCredentialRevealResponse(ToolCredentialRevealContract):
  99. credential: ToolCredentialResponse
  100. class ToolDto(BaseModel):
  101. id: str
  102. pluginId: str | None = None
  103. name: str
  104. toolType: str
  105. description: str | None = None
  106. createdTime: datetime
  107. @classmethod
  108. def from_entity(cls, entity: "ToolDefinition") -> "ToolDto":
  109. return cls(
  110. id=entity.id,
  111. pluginId=entity.plugin_id,
  112. name=entity.name,
  113. toolType=entity.tool_type,
  114. description=entity.description,
  115. createdTime=entity.created_time)
  116. class ToolCreateRequestDto(BaseModel):
  117. pluginId: str | None = None
  118. name: str
  119. toolType: str = "mcp"
  120. description: str | None = None
  121. class ToolDeleteRequestDto(BaseModel):
  122. toolId: str
  123. class ToolDetailRequestDto(BaseModel):
  124. toolId: str
  125. class ToolUpdateRequestDto(BaseModel):
  126. toolId: str
  127. name: str | None = None
  128. toolType: str | None = None
  129. description: str | None = None
  130. pluginId: str | None = None
  131. class ToolConnectionDto(BaseModel):
  132. id: str
  133. toolId: str
  134. inputSchema: dict[str, JSONValue] | None = None
  135. outputSchema: dict[str, JSONValue] | None = None
  136. invokeConfig: dict[str, JSONValue] | None = None
  137. timeoutMs: int | None = None
  138. retryPolicy: dict[str, JSONValue] | None = None
  139. createdTime: datetime
  140. @classmethod
  141. def from_entity(cls, entity: "ToolConnection") -> "ToolConnectionDto":
  142. return cls(
  143. id=entity.id,
  144. toolId=entity.tool_id,
  145. inputSchema=entity.input_schema_json,
  146. outputSchema=entity.output_schema_json,
  147. invokeConfig=entity.invoke_config_json,
  148. timeoutMs=entity.timeout_ms,
  149. retryPolicy=entity.retry_policy_json,
  150. createdTime=entity.created_time)
  151. class ToolConnectionListRequestDto(PageRequest):
  152. toolId: str | None = None
  153. class ToolConnectionCreateRequestDto(BaseModel):
  154. toolId: str
  155. inputSchema: dict[str, JSONValue] = Field(default_factory=dict)
  156. outputSchema: dict[str, JSONValue] = Field(default_factory=dict)
  157. invokeConfig: dict[str, JSONValue] = Field(default_factory=dict)
  158. timeoutMs: int | None = None
  159. retryPolicy: dict[str, JSONValue] = Field(default_factory=dict)
  160. class ToolConnectionDeleteRequestDto(BaseModel):
  161. connectionId: str
  162. class ToolConnectionDetailRequestDto(BaseModel):
  163. connectionId: str
  164. class ToolConnectionUpdateRequestDto(BaseModel):
  165. connectionId: str
  166. inputSchema: dict[str, JSONValue] | None = None
  167. outputSchema: dict[str, JSONValue] | None = None
  168. invokeConfig: dict[str, JSONValue] | None = None
  169. timeoutMs: int | None = None
  170. retryPolicy: dict[str, JSONValue] | None = None
  171. class ToolBindingDto(BaseModel):
  172. id: str
  173. appId: str
  174. connectionId: str
  175. credentialId: str | None = None
  176. bindingScope: str
  177. configJson: dict[str, JSONValue] | None = None
  178. createdTime: datetime
  179. @classmethod
  180. def from_entity(cls, entity: "ToolBinding") -> "ToolBindingDto":
  181. return cls(
  182. id=entity.id,
  183. appId=entity.app_id,
  184. connectionId=entity.tool_connection_id,
  185. credentialId=entity.credential_id,
  186. bindingScope=entity.binding_scope,
  187. configJson=entity.config_json,
  188. createdTime=entity.created_time)
  189. class ToolBindingListRequestDto(PageRequest):
  190. appId: str | None = None
  191. class ToolBindingCreateRequestDto(BaseModel):
  192. appId: str
  193. connectionId: str
  194. credentialId: str | None = None
  195. bindingScope: str = "app"
  196. configJson: dict[str, JSONValue] = Field(default_factory=dict)
  197. class ToolBindingDeleteRequestDto(BaseModel):
  198. bindingId: str
  199. class ToolBindingDetailRequestDto(BaseModel):
  200. bindingId: str
  201. class ToolBindingUpdateRequestDto(BaseModel):
  202. bindingId: str
  203. credentialId: str | None = None
  204. bindingScope: str | None = None
  205. configJson: dict[str, JSONValue] | None = None
  206. class ToolCredentialDto(BaseModel):
  207. id: str
  208. name: str
  209. credentialType: str
  210. secretFingerprint: str
  211. encryptionAlgorithm: str
  212. metadataJson: dict[str, JSONValue] = Field(default_factory=dict)
  213. createdTime: datetime
  214. @classmethod
  215. def from_entity(cls, entity: "ToolCredential") -> "ToolCredentialDto":
  216. return cls(
  217. id=entity.id,
  218. name=entity.name,
  219. credentialType=entity.credential_type,
  220. secretFingerprint=entity.secret_fingerprint,
  221. encryptionAlgorithm=entity.encryption_algorithm,
  222. metadataJson=entity.metadata_json,
  223. createdTime=entity.created_time)
  224. class ToolCredentialCreateRequestDto(BaseModel):
  225. name: str
  226. credentialType: str = "generic"
  227. secretJson: dict[str, JSONValue] = Field(default_factory=dict)
  228. metadataJson: dict[str, JSONValue] = Field(default_factory=dict)
  229. class ToolCredentialDeleteRequestDto(BaseModel):
  230. credentialId: str
  231. class ToolCredentialDetailRequestDto(BaseModel):
  232. credentialId: str
  233. class ToolCredentialUpdateRequestDto(BaseModel):
  234. credentialId: str
  235. name: str | None = None
  236. metadataJson: dict[str, JSONValue] | None = None
  237. class ToolCredentialRevealRequestDto(BaseModel):
  238. credentialId: str
  239. class ToolCredentialRevealDto(BaseModel):
  240. credential: ToolCredentialDto
  241. secretJson: dict[str, JSONValue] = Field(default_factory=dict)
  242. class McpToolDto(BaseModel):
  243. name: str
  244. description: str | None = None
  245. inputSchema: dict[str, JSONValue] | None = None
  246. class McpConnectRequestDto(BaseModel):
  247. name: str | None = None
  248. config: dict[str, JSONValue]
  249. class McpDiscoverRequestDto(BaseModel):
  250. connectionId: str
  251. class McpConnectData(BaseModel):
  252. tool: ToolDto
  253. connection: ToolConnectionDto
  254. discoveredTools: list[McpToolDto] = Field(default_factory=list)
  255. class DeleteData(BaseModel):
  256. deleted: bool
  257. toolId: str | None = None
  258. connectionId: str | None = None
  259. bindingId: str | None = None
  260. credentialId: str | None = None