machinaos 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/.env.template +71 -0
  2. package/LICENSE +21 -0
  3. package/README.md +87 -0
  4. package/bin/cli.js +159 -0
  5. package/client/.dockerignore +45 -0
  6. package/client/Dockerfile +68 -0
  7. package/client/eslint.config.js +29 -0
  8. package/client/index.html +13 -0
  9. package/client/nginx.conf +66 -0
  10. package/client/package.json +48 -0
  11. package/client/src/App.tsx +27 -0
  12. package/client/src/Dashboard.tsx +1173 -0
  13. package/client/src/ParameterPanel.tsx +301 -0
  14. package/client/src/components/AIAgentNode.tsx +321 -0
  15. package/client/src/components/APIKeyValidator.tsx +118 -0
  16. package/client/src/components/ClaudeChatModelNode.tsx +18 -0
  17. package/client/src/components/ConditionalEdge.tsx +189 -0
  18. package/client/src/components/CredentialsModal.tsx +306 -0
  19. package/client/src/components/EdgeConditionEditor.tsx +443 -0
  20. package/client/src/components/GeminiChatModelNode.tsx +18 -0
  21. package/client/src/components/GenericNode.tsx +357 -0
  22. package/client/src/components/LocationParameterPanel.tsx +154 -0
  23. package/client/src/components/ModelNode.tsx +286 -0
  24. package/client/src/components/OpenAIChatModelNode.tsx +18 -0
  25. package/client/src/components/OutputPanel.tsx +471 -0
  26. package/client/src/components/ParameterRenderer.tsx +1874 -0
  27. package/client/src/components/SkillEditorModal.tsx +417 -0
  28. package/client/src/components/SquareNode.tsx +797 -0
  29. package/client/src/components/StartNode.tsx +250 -0
  30. package/client/src/components/ToolkitNode.tsx +365 -0
  31. package/client/src/components/TriggerNode.tsx +463 -0
  32. package/client/src/components/auth/LoginPage.tsx +247 -0
  33. package/client/src/components/auth/ProtectedRoute.tsx +59 -0
  34. package/client/src/components/base/BaseChatModelNode.tsx +271 -0
  35. package/client/src/components/icons/AIProviderIcons.tsx +50 -0
  36. package/client/src/components/maps/GoogleMapsPicker.tsx +137 -0
  37. package/client/src/components/maps/MapsPreviewPanel.tsx +110 -0
  38. package/client/src/components/maps/index.ts +26 -0
  39. package/client/src/components/parameterPanel/InputSection.tsx +1094 -0
  40. package/client/src/components/parameterPanel/LocationPanelLayout.tsx +65 -0
  41. package/client/src/components/parameterPanel/MapsSection.tsx +92 -0
  42. package/client/src/components/parameterPanel/MiddleSection.tsx +571 -0
  43. package/client/src/components/parameterPanel/OutputSection.tsx +81 -0
  44. package/client/src/components/parameterPanel/ParameterPanelLayout.tsx +82 -0
  45. package/client/src/components/parameterPanel/ToolSchemaEditor.tsx +436 -0
  46. package/client/src/components/parameterPanel/index.ts +42 -0
  47. package/client/src/components/shared/DataPanel.tsx +142 -0
  48. package/client/src/components/shared/JSONTreeRenderer.tsx +106 -0
  49. package/client/src/components/ui/AIResultModal.tsx +204 -0
  50. package/client/src/components/ui/AndroidSettingsPanel.tsx +401 -0
  51. package/client/src/components/ui/CodeEditor.tsx +81 -0
  52. package/client/src/components/ui/CollapsibleSection.tsx +88 -0
  53. package/client/src/components/ui/ComponentItem.tsx +154 -0
  54. package/client/src/components/ui/ComponentPalette.tsx +321 -0
  55. package/client/src/components/ui/ConsolePanel.tsx +1074 -0
  56. package/client/src/components/ui/ErrorBoundary.tsx +196 -0
  57. package/client/src/components/ui/InputNodesPanel.tsx +204 -0
  58. package/client/src/components/ui/MapSelector.tsx +314 -0
  59. package/client/src/components/ui/Modal.tsx +149 -0
  60. package/client/src/components/ui/NodeContextMenu.tsx +192 -0
  61. package/client/src/components/ui/NodeOutputPanel.tsx +1150 -0
  62. package/client/src/components/ui/OutputDisplayPanel.tsx +381 -0
  63. package/client/src/components/ui/SettingsPanel.tsx +243 -0
  64. package/client/src/components/ui/TopToolbar.tsx +736 -0
  65. package/client/src/components/ui/WhatsAppSettingsPanel.tsx +345 -0
  66. package/client/src/components/ui/WorkflowSidebar.tsx +294 -0
  67. package/client/src/config/antdTheme.ts +186 -0
  68. package/client/src/config/api.ts +54 -0
  69. package/client/src/contexts/AuthContext.tsx +221 -0
  70. package/client/src/contexts/ThemeContext.tsx +42 -0
  71. package/client/src/contexts/WebSocketContext.tsx +1971 -0
  72. package/client/src/factories/baseChatModelFactory.ts +256 -0
  73. package/client/src/hooks/useAndroidOperations.ts +164 -0
  74. package/client/src/hooks/useApiKeyValidation.ts +107 -0
  75. package/client/src/hooks/useApiKeys.ts +238 -0
  76. package/client/src/hooks/useAppTheme.ts +17 -0
  77. package/client/src/hooks/useComponentPalette.ts +51 -0
  78. package/client/src/hooks/useCopyPaste.ts +155 -0
  79. package/client/src/hooks/useDragAndDrop.ts +124 -0
  80. package/client/src/hooks/useDragVariable.ts +88 -0
  81. package/client/src/hooks/useExecution.ts +313 -0
  82. package/client/src/hooks/useParameterPanel.ts +176 -0
  83. package/client/src/hooks/useReactFlowNodes.ts +189 -0
  84. package/client/src/hooks/useToolSchema.ts +209 -0
  85. package/client/src/hooks/useWhatsApp.ts +196 -0
  86. package/client/src/hooks/useWorkflowManagement.ts +46 -0
  87. package/client/src/index.css +315 -0
  88. package/client/src/main.tsx +19 -0
  89. package/client/src/nodeDefinitions/aiAgentNodes.ts +336 -0
  90. package/client/src/nodeDefinitions/aiModelNodes.ts +340 -0
  91. package/client/src/nodeDefinitions/androidDeviceNodes.ts +140 -0
  92. package/client/src/nodeDefinitions/androidServiceNodes.ts +383 -0
  93. package/client/src/nodeDefinitions/chatNodes.ts +135 -0
  94. package/client/src/nodeDefinitions/codeNodes.ts +54 -0
  95. package/client/src/nodeDefinitions/documentNodes.ts +379 -0
  96. package/client/src/nodeDefinitions/index.ts +15 -0
  97. package/client/src/nodeDefinitions/locationNodes.ts +463 -0
  98. package/client/src/nodeDefinitions/schedulerNodes.ts +220 -0
  99. package/client/src/nodeDefinitions/skillNodes.ts +211 -0
  100. package/client/src/nodeDefinitions/toolNodes.ts +198 -0
  101. package/client/src/nodeDefinitions/utilityNodes.ts +284 -0
  102. package/client/src/nodeDefinitions/whatsappNodes.ts +865 -0
  103. package/client/src/nodeDefinitions/workflowNodes.ts +41 -0
  104. package/client/src/nodeDefinitions.ts +104 -0
  105. package/client/src/schemas/workflowSchema.ts +264 -0
  106. package/client/src/services/dynamicParameterService.ts +96 -0
  107. package/client/src/services/execution/aiAgentExecutionService.ts +35 -0
  108. package/client/src/services/executionService.ts +232 -0
  109. package/client/src/services/workflowApi.ts +91 -0
  110. package/client/src/store/useAppStore.ts +582 -0
  111. package/client/src/styles/theme.ts +508 -0
  112. package/client/src/styles/zIndex.ts +17 -0
  113. package/client/src/types/ComponentTypes.ts +39 -0
  114. package/client/src/types/EdgeCondition.ts +231 -0
  115. package/client/src/types/INodeProperties.ts +288 -0
  116. package/client/src/types/NodeTypes.ts +28 -0
  117. package/client/src/utils/formatters.ts +33 -0
  118. package/client/src/utils/googleMapsLoader.ts +140 -0
  119. package/client/src/utils/locationUtils.ts +85 -0
  120. package/client/src/utils/nodeUtils.ts +31 -0
  121. package/client/src/utils/workflow.ts +30 -0
  122. package/client/src/utils/workflowExport.ts +120 -0
  123. package/client/src/vite-env.d.ts +12 -0
  124. package/client/tailwind.config.js +60 -0
  125. package/client/tsconfig.json +25 -0
  126. package/client/tsconfig.node.json +11 -0
  127. package/client/vite.config.js +35 -0
  128. package/docker-compose.prod.yml +107 -0
  129. package/docker-compose.yml +104 -0
  130. package/docs-MachinaOs/README.md +85 -0
  131. package/docs-MachinaOs/deployment/docker.mdx +228 -0
  132. package/docs-MachinaOs/deployment/production.mdx +345 -0
  133. package/docs-MachinaOs/docs.json +75 -0
  134. package/docs-MachinaOs/faq.mdx +309 -0
  135. package/docs-MachinaOs/favicon.svg +5 -0
  136. package/docs-MachinaOs/installation.mdx +160 -0
  137. package/docs-MachinaOs/introduction.mdx +114 -0
  138. package/docs-MachinaOs/logo/dark.svg +6 -0
  139. package/docs-MachinaOs/logo/light.svg +6 -0
  140. package/docs-MachinaOs/nodes/ai-agent.mdx +216 -0
  141. package/docs-MachinaOs/nodes/ai-models.mdx +240 -0
  142. package/docs-MachinaOs/nodes/android.mdx +411 -0
  143. package/docs-MachinaOs/nodes/overview.mdx +181 -0
  144. package/docs-MachinaOs/nodes/schedulers.mdx +316 -0
  145. package/docs-MachinaOs/nodes/webhooks.mdx +330 -0
  146. package/docs-MachinaOs/nodes/whatsapp.mdx +305 -0
  147. package/docs-MachinaOs/quickstart.mdx +119 -0
  148. package/docs-MachinaOs/tutorials/ai-agent-workflow.mdx +177 -0
  149. package/docs-MachinaOs/tutorials/android-automation.mdx +242 -0
  150. package/docs-MachinaOs/tutorials/first-workflow.mdx +134 -0
  151. package/docs-MachinaOs/tutorials/whatsapp-automation.mdx +185 -0
  152. package/nul +0 -0
  153. package/package.json +70 -0
  154. package/scripts/build.js +158 -0
  155. package/scripts/check-ports.ps1 +33 -0
  156. package/scripts/clean.js +40 -0
  157. package/scripts/docker.js +93 -0
  158. package/scripts/kill-port.ps1 +154 -0
  159. package/scripts/start.js +210 -0
  160. package/scripts/stop.js +325 -0
  161. package/server/.dockerignore +44 -0
  162. package/server/Dockerfile +45 -0
  163. package/server/constants.py +249 -0
  164. package/server/core/__init__.py +1 -0
  165. package/server/core/cache.py +461 -0
  166. package/server/core/config.py +128 -0
  167. package/server/core/container.py +99 -0
  168. package/server/core/database.py +1211 -0
  169. package/server/core/logging.py +314 -0
  170. package/server/main.py +289 -0
  171. package/server/middleware/__init__.py +5 -0
  172. package/server/middleware/auth.py +89 -0
  173. package/server/models/__init__.py +1 -0
  174. package/server/models/auth.py +52 -0
  175. package/server/models/cache.py +24 -0
  176. package/server/models/database.py +211 -0
  177. package/server/models/nodes.py +455 -0
  178. package/server/package.json +9 -0
  179. package/server/pyproject.toml +72 -0
  180. package/server/requirements.txt +83 -0
  181. package/server/routers/__init__.py +1 -0
  182. package/server/routers/android.py +294 -0
  183. package/server/routers/auth.py +203 -0
  184. package/server/routers/database.py +151 -0
  185. package/server/routers/maps.py +142 -0
  186. package/server/routers/nodejs_compat.py +289 -0
  187. package/server/routers/webhook.py +90 -0
  188. package/server/routers/websocket.py +2127 -0
  189. package/server/routers/whatsapp.py +761 -0
  190. package/server/routers/workflow.py +200 -0
  191. package/server/services/__init__.py +1 -0
  192. package/server/services/ai.py +2415 -0
  193. package/server/services/android/__init__.py +27 -0
  194. package/server/services/android/broadcaster.py +114 -0
  195. package/server/services/android/client.py +608 -0
  196. package/server/services/android/manager.py +78 -0
  197. package/server/services/android/protocol.py +165 -0
  198. package/server/services/android_service.py +588 -0
  199. package/server/services/auth.py +131 -0
  200. package/server/services/chat_client.py +160 -0
  201. package/server/services/deployment/__init__.py +12 -0
  202. package/server/services/deployment/manager.py +706 -0
  203. package/server/services/deployment/state.py +47 -0
  204. package/server/services/deployment/triggers.py +275 -0
  205. package/server/services/event_waiter.py +785 -0
  206. package/server/services/execution/__init__.py +77 -0
  207. package/server/services/execution/cache.py +769 -0
  208. package/server/services/execution/conditions.py +373 -0
  209. package/server/services/execution/dlq.py +132 -0
  210. package/server/services/execution/executor.py +1351 -0
  211. package/server/services/execution/models.py +531 -0
  212. package/server/services/execution/recovery.py +235 -0
  213. package/server/services/handlers/__init__.py +126 -0
  214. package/server/services/handlers/ai.py +355 -0
  215. package/server/services/handlers/android.py +260 -0
  216. package/server/services/handlers/code.py +278 -0
  217. package/server/services/handlers/document.py +598 -0
  218. package/server/services/handlers/http.py +193 -0
  219. package/server/services/handlers/polyglot.py +105 -0
  220. package/server/services/handlers/tools.py +845 -0
  221. package/server/services/handlers/triggers.py +107 -0
  222. package/server/services/handlers/utility.py +822 -0
  223. package/server/services/handlers/whatsapp.py +476 -0
  224. package/server/services/maps.py +289 -0
  225. package/server/services/memory_store.py +103 -0
  226. package/server/services/node_executor.py +375 -0
  227. package/server/services/parameter_resolver.py +218 -0
  228. package/server/services/polyglot_client.py +169 -0
  229. package/server/services/scheduler.py +155 -0
  230. package/server/services/skill_loader.py +417 -0
  231. package/server/services/status_broadcaster.py +826 -0
  232. package/server/services/temporal/__init__.py +23 -0
  233. package/server/services/temporal/activities.py +344 -0
  234. package/server/services/temporal/client.py +76 -0
  235. package/server/services/temporal/executor.py +147 -0
  236. package/server/services/temporal/worker.py +251 -0
  237. package/server/services/temporal/workflow.py +355 -0
  238. package/server/services/temporal/ws_client.py +236 -0
  239. package/server/services/text.py +111 -0
  240. package/server/services/user_auth.py +172 -0
  241. package/server/services/websocket_client.py +29 -0
  242. package/server/services/workflow.py +597 -0
  243. package/server/skills/android-skill/SKILL.md +82 -0
  244. package/server/skills/assistant-personality/SKILL.md +45 -0
  245. package/server/skills/code-skill/SKILL.md +140 -0
  246. package/server/skills/http-skill/SKILL.md +161 -0
  247. package/server/skills/maps-skill/SKILL.md +170 -0
  248. package/server/skills/memory-skill/SKILL.md +154 -0
  249. package/server/skills/scheduler-skill/SKILL.md +84 -0
  250. package/server/skills/whatsapp-skill/SKILL.md +283 -0
  251. package/server/uv.lock +2916 -0
  252. package/server/whatsapp-rpc/.dockerignore +30 -0
  253. package/server/whatsapp-rpc/Dockerfile +44 -0
  254. package/server/whatsapp-rpc/Dockerfile.web +17 -0
  255. package/server/whatsapp-rpc/README.md +139 -0
  256. package/server/whatsapp-rpc/cli.js +95 -0
  257. package/server/whatsapp-rpc/configs/config.yaml +7 -0
  258. package/server/whatsapp-rpc/docker-compose.yml +35 -0
  259. package/server/whatsapp-rpc/docs/API.md +410 -0
  260. package/server/whatsapp-rpc/go.mod +67 -0
  261. package/server/whatsapp-rpc/go.sum +203 -0
  262. package/server/whatsapp-rpc/package.json +30 -0
  263. package/server/whatsapp-rpc/schema.json +1294 -0
  264. package/server/whatsapp-rpc/scripts/clean.cjs +66 -0
  265. package/server/whatsapp-rpc/scripts/cli.js +162 -0
  266. package/server/whatsapp-rpc/src/go/cmd/server/main.go +91 -0
  267. package/server/whatsapp-rpc/src/go/config/config.go +49 -0
  268. package/server/whatsapp-rpc/src/go/rpc/rpc.go +446 -0
  269. package/server/whatsapp-rpc/src/go/rpc/server.go +112 -0
  270. package/server/whatsapp-rpc/src/go/whatsapp/history.go +166 -0
  271. package/server/whatsapp-rpc/src/go/whatsapp/messages.go +390 -0
  272. package/server/whatsapp-rpc/src/go/whatsapp/service.go +2130 -0
  273. package/server/whatsapp-rpc/src/go/whatsapp/types.go +261 -0
  274. package/server/whatsapp-rpc/src/python/pyproject.toml +15 -0
  275. package/server/whatsapp-rpc/src/python/whatsapp_rpc/__init__.py +4 -0
  276. package/server/whatsapp-rpc/src/python/whatsapp_rpc/client.py +427 -0
  277. package/server/whatsapp-rpc/web/app.py +609 -0
  278. package/server/whatsapp-rpc/web/requirements.txt +6 -0
  279. package/server/whatsapp-rpc/web/rpc_client.py +427 -0
  280. package/server/whatsapp-rpc/web/static/openapi.yaml +59 -0
  281. package/server/whatsapp-rpc/web/templates/base.html +150 -0
  282. package/server/whatsapp-rpc/web/templates/contacts.html +240 -0
  283. package/server/whatsapp-rpc/web/templates/dashboard.html +320 -0
  284. package/server/whatsapp-rpc/web/templates/groups.html +328 -0
  285. package/server/whatsapp-rpc/web/templates/messages.html +465 -0
  286. package/server/whatsapp-rpc/web/templates/messaging.html +681 -0
  287. package/server/whatsapp-rpc/web/templates/send.html +259 -0
  288. package/server/whatsapp-rpc/web/templates/settings.html +459 -0
@@ -0,0 +1,52 @@
1
+ """User authentication models."""
2
+
3
+ from datetime import datetime, timezone
4
+ from typing import Optional
5
+ from sqlmodel import SQLModel, Field, Column, DateTime
6
+ from sqlalchemy import func
7
+ import bcrypt
8
+
9
+
10
+ class User(SQLModel, table=True):
11
+ """User account for authentication."""
12
+
13
+ __tablename__ = "users"
14
+
15
+ id: Optional[int] = Field(default=None, primary_key=True)
16
+ email: str = Field(unique=True, index=True, max_length=255)
17
+ password_hash: str = Field(max_length=255)
18
+ display_name: str = Field(max_length=100)
19
+ is_owner: bool = Field(default=False) # First user in single-owner mode
20
+ is_active: bool = Field(default=True)
21
+ created_at: datetime = Field(
22
+ default_factory=lambda: datetime.now(timezone.utc),
23
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
24
+ )
25
+ last_login: Optional[datetime] = Field(
26
+ default=None,
27
+ sa_column=Column(DateTime(timezone=True), nullable=True)
28
+ )
29
+
30
+ def set_password(self, password: str) -> None:
31
+ """Hash and set password using bcrypt."""
32
+ salt = bcrypt.gensalt()
33
+ self.password_hash = bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')
34
+
35
+ def verify_password(self, password: str) -> bool:
36
+ """Verify password against stored hash."""
37
+ return bcrypt.checkpw(
38
+ password.encode('utf-8'),
39
+ self.password_hash.encode('utf-8')
40
+ )
41
+
42
+ @classmethod
43
+ def create(cls, email: str, password: str, display_name: str, is_owner: bool = False) -> "User":
44
+ """Factory method to create a user with hashed password."""
45
+ user = cls(
46
+ email=email.lower().strip(),
47
+ password_hash="", # Will be set below
48
+ display_name=display_name.strip(),
49
+ is_owner=is_owner
50
+ )
51
+ user.set_password(password)
52
+ return user
@@ -0,0 +1,24 @@
1
+ """SQLite-backed cache model for key-value storage with TTL.
2
+
3
+ Follows n8n pattern where SQLite is sufficient for single-process deployments,
4
+ with Redis used only for distributed queue mode.
5
+ """
6
+
7
+ import time
8
+ from typing import Optional
9
+ from sqlmodel import SQLModel, Field
10
+
11
+
12
+ class CacheEntry(SQLModel, table=True):
13
+ """Generic key-value cache with optional expiration.
14
+
15
+ Used as Redis alternative for local development (no Docker required).
16
+ Production can use Redis for better performance at scale.
17
+ """
18
+
19
+ __tablename__ = "cache_entries"
20
+
21
+ key: str = Field(primary_key=True, max_length=512)
22
+ value: str = Field(max_length=1000000) # JSON serialized, up to 1MB
23
+ expires_at: Optional[float] = Field(default=None, index=True) # Unix timestamp
24
+ created_at: float = Field(default_factory=time.time)
@@ -0,0 +1,211 @@
1
+ """SQLModel database models and tables."""
2
+
3
+ from datetime import datetime, timezone
4
+ from typing import Optional, Dict, Any
5
+ from sqlmodel import SQLModel, Field, Column, DateTime, JSON
6
+ from sqlalchemy import func
7
+
8
+
9
+ class NodeParameter(SQLModel, table=True):
10
+ """Node parameters storage."""
11
+
12
+ __tablename__ = "node_parameters"
13
+
14
+ id: Optional[int] = Field(default=None, primary_key=True)
15
+ node_id: str = Field(index=True, unique=True, max_length=255)
16
+ parameters: Dict[str, Any] = Field(sa_column=Column(JSON))
17
+ created_at: datetime = Field(
18
+ default_factory=lambda: datetime.now(timezone.utc),
19
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
20
+ )
21
+ updated_at: datetime = Field(
22
+ default_factory=lambda: datetime.now(timezone.utc),
23
+ sa_column=Column(DateTime(timezone=True), onupdate=func.now())
24
+ )
25
+
26
+
27
+ class Workflow(SQLModel, table=True):
28
+ """Workflow definitions."""
29
+
30
+ __tablename__ = "workflows"
31
+
32
+ id: str = Field(primary_key=True, max_length=255)
33
+ name: str = Field(max_length=255)
34
+ description: Optional[str] = Field(default=None, max_length=1000)
35
+ data: Dict[str, Any] = Field(sa_column=Column(JSON))
36
+ created_at: datetime = Field(
37
+ default_factory=lambda: datetime.now(timezone.utc),
38
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
39
+ )
40
+ updated_at: datetime = Field(
41
+ default_factory=lambda: datetime.now(timezone.utc),
42
+ sa_column=Column(DateTime(timezone=True), onupdate=func.now())
43
+ )
44
+
45
+
46
+ class Execution(SQLModel, table=True):
47
+ """Workflow execution history."""
48
+
49
+ __tablename__ = "executions"
50
+
51
+ id: str = Field(primary_key=True, max_length=255)
52
+ workflow_id: str = Field(foreign_key="workflows.id", max_length=255)
53
+ node_id: str = Field(max_length=255)
54
+ status: str = Field(default="pending", max_length=50)
55
+ result: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
56
+ error: Optional[str] = Field(default=None, max_length=2000)
57
+ execution_time: Optional[float] = Field(default=None)
58
+ created_at: datetime = Field(
59
+ default_factory=lambda: datetime.now(timezone.utc),
60
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
61
+ )
62
+
63
+
64
+ class APIKey(SQLModel, table=True):
65
+ """Encrypted API key storage."""
66
+
67
+ __tablename__ = "api_keys"
68
+
69
+ id: str = Field(primary_key=True, max_length=255)
70
+ provider: str = Field(max_length=50)
71
+ session_id: str = Field(default="default", max_length=255)
72
+ key_encrypted: str = Field(max_length=1000)
73
+ key_hash: str = Field(max_length=64, index=True)
74
+ models: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
75
+ is_valid: bool = Field(default=True)
76
+ last_validated: datetime = Field(
77
+ default_factory=lambda: datetime.now(timezone.utc),
78
+ sa_column=Column(DateTime(timezone=True))
79
+ )
80
+ created_at: datetime = Field(
81
+ default_factory=lambda: datetime.now(timezone.utc),
82
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
83
+ )
84
+ updated_at: datetime = Field(
85
+ default_factory=lambda: datetime.now(timezone.utc),
86
+ sa_column=Column(DateTime(timezone=True), onupdate=func.now())
87
+ )
88
+
89
+
90
+ class APIKeyValidation(SQLModel, table=True):
91
+ """API key validation cache."""
92
+
93
+ __tablename__ = "api_key_validations"
94
+
95
+ id: Optional[int] = Field(default=None, primary_key=True)
96
+ key_hash: str = Field(unique=True, max_length=64, index=True)
97
+ validated: bool = Field(default=True)
98
+ timestamp: datetime = Field(
99
+ default_factory=lambda: datetime.now(timezone.utc),
100
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
101
+ )
102
+
103
+
104
+ class NodeOutput(SQLModel, table=True):
105
+ """Node execution output storage - persisted across server restarts."""
106
+
107
+ __tablename__ = "node_outputs"
108
+
109
+ id: Optional[int] = Field(default=None, primary_key=True)
110
+ node_id: str = Field(index=True, max_length=255)
111
+ session_id: str = Field(default="default", max_length=255)
112
+ output_name: str = Field(default="output_0", max_length=100)
113
+ data: Dict[str, Any] = Field(sa_column=Column(JSON))
114
+ created_at: datetime = Field(
115
+ default_factory=lambda: datetime.now(timezone.utc),
116
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
117
+ )
118
+ updated_at: datetime = Field(
119
+ default_factory=lambda: datetime.now(timezone.utc),
120
+ sa_column=Column(DateTime(timezone=True), onupdate=func.now())
121
+ )
122
+
123
+
124
+ class ConversationMessage(SQLModel, table=True):
125
+ """AI conversation message storage - persisted across server restarts."""
126
+
127
+ __tablename__ = "conversation_messages"
128
+
129
+ id: Optional[int] = Field(default=None, primary_key=True)
130
+ session_id: str = Field(index=True, max_length=255)
131
+ role: str = Field(max_length=20) # 'human' or 'ai'
132
+ content: str = Field(max_length=50000) # Large content support
133
+ created_at: datetime = Field(
134
+ default_factory=lambda: datetime.now(timezone.utc),
135
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
136
+ )
137
+
138
+
139
+ class ToolSchema(SQLModel, table=True):
140
+ """Tool node schema configuration - stores LLM-visible schema for tool nodes.
141
+
142
+ This allows Android Toolkit and other aggregator nodes to update the schema
143
+ of connected tool nodes, providing the LLM with accurate capability information.
144
+ """
145
+
146
+ __tablename__ = "tool_schemas"
147
+
148
+ id: Optional[int] = Field(default=None, primary_key=True)
149
+ node_id: str = Field(index=True, unique=True, max_length=255)
150
+ tool_name: str = Field(max_length=255) # e.g., 'android_device', 'calculator'
151
+ tool_description: str = Field(max_length=2000) # Description shown to LLM
152
+ schema_config: Dict[str, Any] = Field(sa_column=Column(JSON)) # Schema fields and types
153
+ connected_services: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON)) # For toolkit nodes
154
+ created_at: datetime = Field(
155
+ default_factory=lambda: datetime.now(timezone.utc),
156
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
157
+ )
158
+ updated_at: datetime = Field(
159
+ default_factory=lambda: datetime.now(timezone.utc),
160
+ sa_column=Column(DateTime(timezone=True), onupdate=func.now())
161
+ )
162
+
163
+
164
+ class ChatMessage(SQLModel, table=True):
165
+ """Chat panel messages - persisted across server restarts.
166
+
167
+ Stores user and assistant messages from the chat panel (Console Panel chat section).
168
+ These are separate from ConversationMessage which stores AI agent memory.
169
+ """
170
+
171
+ __tablename__ = "chat_messages"
172
+
173
+ id: Optional[int] = Field(default=None, primary_key=True)
174
+ session_id: str = Field(default="default", index=True, max_length=255)
175
+ role: str = Field(max_length=20) # 'user' or 'assistant'
176
+ message: str = Field(max_length=50000) # Large content support
177
+ created_at: datetime = Field(
178
+ default_factory=lambda: datetime.now(timezone.utc),
179
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
180
+ )
181
+
182
+
183
+ class UserSkill(SQLModel, table=True):
184
+ """User-created custom skills for Chat Agent.
185
+
186
+ Skills are defined using the Agent Skills specification format with YAML frontmatter.
187
+ This allows non-technical users to create and manage skills via the UI editor.
188
+ """
189
+
190
+ __tablename__ = "user_skills"
191
+
192
+ id: Optional[int] = Field(default=None, primary_key=True)
193
+ name: str = Field(unique=True, index=True, max_length=100) # Unique skill identifier
194
+ display_name: str = Field(max_length=200) # Human-readable name
195
+ description: str = Field(max_length=1000) # Short description for skill registry
196
+ instructions: str = Field(max_length=50000) # Full markdown instructions
197
+ allowed_tools: Optional[str] = Field(default=None, max_length=1000) # Comma-separated tool names
198
+ category: str = Field(default="custom", max_length=50) # Skill category
199
+ icon: str = Field(default="star", max_length=50) # Icon identifier
200
+ color: str = Field(default="#6366F1", max_length=20) # Color hex code
201
+ metadata_json: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON)) # Additional metadata
202
+ is_active: bool = Field(default=True) # Whether skill is available
203
+ created_by: Optional[int] = Field(default=None) # User ID who created it
204
+ created_at: datetime = Field(
205
+ default_factory=lambda: datetime.now(timezone.utc),
206
+ sa_column=Column(DateTime(timezone=True), server_default=func.now())
207
+ )
208
+ updated_at: datetime = Field(
209
+ default_factory=lambda: datetime.now(timezone.utc),
210
+ sa_column=Column(DateTime(timezone=True), onupdate=func.now())
211
+ )