schemas.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. from __future__ import annotations
  2. from typing import Any, Literal
  3. from pydantic import BaseModel, Field, field_validator
  4. ConfirmStatus = Literal["PENDING", "TRUSTED", "SUSPICIOUS", "IGNORED", "NEED_MORE_INFO"]
  5. ItemType = Literal["service", "process"]
  6. AiProviderType = Literal["OPENAI", "OPENAI_COMPATIBLE", "GOOGLE_GEMINI"]
  7. MouseAutomationAction = Literal["move_to", "move_rel", "click", "double_click", "right_click", "drag_to", "scroll"]
  8. KeyboardAutomationAction = Literal["press", "hotkey", "write", "key_down", "key_up"]
  9. AutomationNodeType = str
  10. class StatusUpdate(BaseModel):
  11. confirm_status: ConfirmStatus
  12. user_note: str | None = None
  13. class BatchStatusUpdate(BaseModel):
  14. ids: list[int] = Field(default_factory=list)
  15. confirm_status: ConfirmStatus
  16. user_note: str | None = None
  17. class AiImportItem(BaseModel):
  18. type: ItemType
  19. name: str
  20. description: str | None = None
  21. judgement: Literal["TRUSTED", "SUSPICIOUS", "NEED_MORE_INFO"]
  22. risk_level: Literal["LOW", "MEDIUM", "HIGH"]
  23. reason: str | None = None
  24. suggestion: str | None = None
  25. tags: list[str] | None = None
  26. @field_validator("tags", mode="before")
  27. @classmethod
  28. def normalize_tags(cls, value: Any) -> list[str] | None:
  29. if value is None:
  30. return None
  31. if isinstance(value, str):
  32. return [value]
  33. if isinstance(value, list):
  34. names: list[str] = []
  35. for item in value:
  36. if isinstance(item, str):
  37. names.append(item)
  38. elif isinstance(item, dict) and item.get("name"):
  39. names.append(str(item["name"]))
  40. return names
  41. raise ValueError("tags must be a string, list of strings, or list of objects with name")
  42. class AiImportRequest(BaseModel):
  43. items: list[AiImportItem]
  44. class PromptRequest(BaseModel):
  45. ids: list[int] | None = None
  46. scope: Literal["selected", "pending"] = "pending"
  47. class TagCreate(BaseModel):
  48. name: str = Field(min_length=1, max_length=80)
  49. description: str | None = None
  50. is_controllable: bool = True
  51. class TagUpdate(BaseModel):
  52. name: str = Field(min_length=1, max_length=80)
  53. description: str | None = None
  54. is_controllable: bool = True
  55. class TagAssignRequest(BaseModel):
  56. tag_ids: list[int] = Field(default_factory=list)
  57. class ProcessStartRequest(BaseModel):
  58. command: str = Field(min_length=1)
  59. cwd: str | None = None
  60. class AutomationPowerRequest(BaseModel):
  61. delay_seconds: int = Field(default=0, ge=0, le=86400)
  62. force: bool = False
  63. reason: str | None = Field(default=None, max_length=512)
  64. class AutomationProgramStartRequest(BaseModel):
  65. command: str = Field(min_length=1)
  66. cwd: str | None = None
  67. shell: bool = True
  68. class AutomationProgramStopRequest(BaseModel):
  69. pid: int | None = Field(default=None, ge=0)
  70. name: str | None = Field(default=None, min_length=1)
  71. timeout_seconds: float = Field(default=8, ge=0, le=60)
  72. kill_after_timeout: bool = True
  73. class AutomationScreenshotRequest(BaseModel):
  74. save_path: str | None = None
  75. include_base64: bool = True
  76. class AutomationMouseRequest(BaseModel):
  77. action: MouseAutomationAction
  78. x: int | None = None
  79. y: int | None = None
  80. duration: float = Field(default=0, ge=0, le=60)
  81. button: Literal["left", "middle", "right"] = "left"
  82. clicks: int = Field(default=1, ge=1, le=20)
  83. amount: int = 0
  84. class AutomationKeyboardRequest(BaseModel):
  85. action: KeyboardAutomationAction
  86. key: str | None = None
  87. keys: list[str] | None = None
  88. text: str | None = None
  89. interval: float = Field(default=0, ge=0, le=10)
  90. class AutomationVisionAnalyzeRequest(BaseModel):
  91. provider_id: int | None = None
  92. model_id: int | None = None
  93. temperature: float = Field(default=0.1, ge=0, le=2)
  94. class AutomationScreenshotCaptureRequest(BaseModel):
  95. save: bool = True
  96. class AutomationElementLocateRequest(BaseModel):
  97. provider_id: int | None = None
  98. model_id: int | None = None
  99. temperature: float = Field(default=0.1, ge=0, le=2)
  100. class AutomationActionBase(BaseModel):
  101. screen_id: int | None = None
  102. provider_id: int | None = None
  103. model_id: int | None = None
  104. temperature: float = Field(default=0.1, ge=0, le=2)
  105. workflow_id: int | None = None
  106. node_id: int | None = None
  107. class AutomationMouseActionRequest(AutomationActionBase):
  108. x: int
  109. y: int
  110. mouse_action: Literal["click", "double_click", "right_click"]
  111. class AutomationKeyboardActionRequest(AutomationActionBase):
  112. keys: list[str] = Field(min_length=1)
  113. class AutomationTextInputRequest(AutomationActionBase):
  114. text: str
  115. class AutomationStartProgramRequest(AutomationActionBase):
  116. command: str = Field(min_length=1)
  117. cwd: str | None = None
  118. shell: bool = True
  119. class AutomationCloseProgramsRequest(BaseModel):
  120. pids: list[int] | None = None
  121. class AutomationWorkflowPosition(BaseModel):
  122. x: float = 80
  123. y: float = 80
  124. class AutomationWorkflowValueRef(BaseModel):
  125. source: Literal["literal", "variable", "node_output", "runtime"]
  126. value: Any = None
  127. name: str | None = None
  128. node_id: str | None = None
  129. output: str | None = None
  130. class AutomationWorkflowNode(BaseModel):
  131. id: str = Field(min_length=1, max_length=120)
  132. type: AutomationNodeType = Field(min_length=1, max_length=120)
  133. title: str | None = Field(default=None, max_length=160)
  134. position: AutomationWorkflowPosition = Field(default_factory=AutomationWorkflowPosition)
  135. params: dict[str, Any] = Field(default_factory=dict)
  136. inputs: dict[str, AutomationWorkflowValueRef | Any] = Field(default_factory=dict)
  137. class AutomationWorkflowSaveRequest(BaseModel):
  138. schema_version: Literal["workflow/v1"] = "workflow/v1"
  139. workflow_key: str | None = Field(default=None, min_length=1, max_length=80, pattern=r"^[a-zA-Z0-9][a-zA-Z0-9_-]*$")
  140. name: str = Field(min_length=1, max_length=160)
  141. description: str | None = None
  142. variables: dict[str, Any] = Field(default_factory=dict)
  143. settings: dict[str, Any] = Field(default_factory=dict)
  144. nodes: list[AutomationWorkflowNode] = Field(default_factory=list)
  145. edges: list[dict[str, Any]] = Field(default_factory=list)
  146. class AutomationWorkflowRunRequest(BaseModel):
  147. provider_id: int | None = None
  148. model_id: int | None = None
  149. temperature: float | None = Field(default=None, ge=0, le=2)
  150. variables: dict[str, Any] = Field(default_factory=dict)
  151. class AutomationWorkflowPlanRequest(BaseModel):
  152. requirement: str = Field(min_length=1, max_length=4000)
  153. provider_id: int | None = None
  154. model_id: int | None = None
  155. temperature: float | None = Field(default=None, ge=0, le=2)
  156. class AutomationWorkflowPlanContinueRequest(BaseModel):
  157. session_id: str = Field(min_length=1)
  158. user_message: str = Field(min_length=1, max_length=4000)
  159. provider_id: int | None = None
  160. model_id: int | None = None
  161. temperature: float | None = Field(default=None, ge=0, le=2)
  162. class SystemSettingsUpdate(BaseModel):
  163. default_ai_provider_id: int | None = None
  164. default_ai_model_id: int | None = None
  165. default_ai_temperature: float | None = Field(default=None, ge=0, le=2)
  166. automation_file_root: str | None = None
  167. automation_screen_path: str | None = None
  168. automation_error_path: str | None = None
  169. automation_runtime_path: str | None = None
  170. automation_auto_screenshot_enabled: bool | None = None
  171. automation_auto_screenshot_interval: int | None = Field(default=None, ge=1, le=3600)
  172. automation_remote_token: str | None = Field(default=None, max_length=256)
  173. class AiProviderCreate(BaseModel):
  174. name: str = Field(min_length=1, max_length=120)
  175. provider_type: AiProviderType
  176. base_url: str | None = None
  177. api_key: str | None = None
  178. enabled: bool = True
  179. class AiProviderUpdate(BaseModel):
  180. name: str = Field(min_length=1, max_length=120)
  181. provider_type: AiProviderType
  182. base_url: str | None = None
  183. api_key: str | None = None
  184. clear_api_key: bool = False
  185. enabled: bool = True
  186. class AiModelCreate(BaseModel):
  187. provider_id: int
  188. name: str = Field(min_length=1, max_length=160)
  189. display_name: str | None = None
  190. is_default: bool = False
  191. class AiModelUpdate(BaseModel):
  192. provider_id: int
  193. name: str = Field(min_length=1, max_length=160)
  194. display_name: str | None = None
  195. is_default: bool = False
  196. class AiChatRequest(BaseModel):
  197. provider_id: int
  198. model_id: int
  199. prompt: str = Field(min_length=1)
  200. temperature: float = Field(default=0.2, ge=0, le=2)
  201. class AiAnalyzeRequest(BaseModel):
  202. provider_id: int
  203. model_id: int
  204. temperature: float = Field(default=0.2, ge=0, le=2)
  205. ids: list[int] | None = None
  206. scope: Literal["selected", "pending"] = "pending"