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,131 @@
1
+ """Simple API key management service."""
2
+
3
+ import hashlib
4
+ import base64
5
+ from datetime import datetime, timedelta, timezone
6
+ from typing import Dict, Any, Optional, List
7
+
8
+ from core.config import Settings
9
+ from core.database import Database
10
+ from core.cache import CacheService
11
+ from core.logging import get_logger
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ class AuthService:
17
+ """Simple API key management service."""
18
+
19
+ def __init__(self, database: Database, cache: CacheService, settings: Settings):
20
+ self.database = database
21
+ self.cache = cache
22
+ self.settings = settings
23
+
24
+ def encrypt_api_key(self, api_key: str) -> str:
25
+ """Simple base64 encoding (compatible with frontend)."""
26
+ return base64.b64encode(api_key.encode()).decode()
27
+
28
+ def decrypt_api_key(self, encrypted_key: str) -> str:
29
+ """Simple base64 decoding."""
30
+ try:
31
+ return base64.b64decode(encrypted_key.encode()).decode()
32
+ except Exception:
33
+ return ""
34
+
35
+ def hash_api_key(self, api_key: str) -> str:
36
+ """Create hash for API key identification."""
37
+ return hashlib.sha256(api_key.encode()).hexdigest()[:16]
38
+
39
+ async def store_api_key(self, provider: str, api_key: str, models: List[str],
40
+ session_id: str = "default") -> bool:
41
+ """Store API key with models."""
42
+ try:
43
+ key_id = f"{session_id}_{provider}"
44
+ encrypted_key = self.encrypt_api_key(api_key)
45
+ key_hash = self.hash_api_key(api_key)
46
+
47
+ logger.info(f"Storing API key for provider: {provider}, session: {session_id}, key_id: {key_id}")
48
+
49
+ # Store in database
50
+ success = await self.database.save_api_key(
51
+ key_id=key_id,
52
+ provider=provider,
53
+ session_id=session_id,
54
+ key_encrypted=encrypted_key,
55
+ key_hash=key_hash,
56
+ models=models
57
+ )
58
+
59
+ logger.info(f"Database save result: {success}")
60
+
61
+ # Cache for quick access
62
+ if success:
63
+ cache_data = {
64
+ "encrypted_key": encrypted_key,
65
+ "models": models,
66
+ "last_validated": datetime.utcnow().isoformat()
67
+ }
68
+ await self.cache.cache_api_key(provider, session_id, cache_data)
69
+ logger.info(f"Cached API key for {provider}")
70
+
71
+ return success
72
+
73
+ except Exception as e:
74
+ logger.error("Failed to store API key", provider=provider, error=str(e))
75
+ return False
76
+
77
+ async def get_api_key(self, provider: str, session_id: str = "default") -> Optional[str]:
78
+ """Get decrypted API key."""
79
+ try:
80
+ # Try cache first
81
+ cached_data = await self.cache.get_cached_api_key(provider, session_id)
82
+ if cached_data:
83
+ return self.decrypt_api_key(cached_data["encrypted_key"])
84
+
85
+ # Fallback to database
86
+ api_key_record = await self.database.get_api_key_by_provider(provider, session_id)
87
+ if api_key_record and api_key_record.is_valid:
88
+ # Check if not expired (30 days)
89
+ if datetime.now(timezone.utc) - api_key_record.last_validated < timedelta(days=30):
90
+ return self.decrypt_api_key(api_key_record.key_encrypted)
91
+
92
+ return None
93
+
94
+ except Exception as e:
95
+ logger.error("Failed to get API key", provider=provider, error=str(e))
96
+ return None
97
+
98
+ async def get_stored_models(self, provider: str, session_id: str = "default") -> List[str]:
99
+ """Get stored models for provider."""
100
+ try:
101
+ # Try cache first
102
+ cached_data = await self.cache.get_cached_api_key(provider, session_id)
103
+ if cached_data and cached_data.get("models"):
104
+ return cached_data["models"]
105
+
106
+ # Fallback to database
107
+ api_key_record = await self.database.get_api_key_by_provider(provider, session_id)
108
+ if api_key_record and api_key_record.models:
109
+ return api_key_record.models.get("models", [])
110
+
111
+ return []
112
+
113
+ except Exception as e:
114
+ logger.error("Failed to get stored models", provider=provider, error=str(e))
115
+ return []
116
+
117
+ async def remove_api_key(self, provider: str, session_id: str = "default") -> bool:
118
+ """Remove API key."""
119
+ try:
120
+ # Remove from cache and database
121
+ await self.cache.remove_cached_api_key(provider, session_id)
122
+ return await self.database.delete_api_key(provider, session_id)
123
+
124
+ except Exception as e:
125
+ logger.error("Failed to remove API key", provider=provider, error=str(e))
126
+ return False
127
+
128
+ async def has_valid_key(self, provider: str, session_id: str = "default") -> bool:
129
+ """Check if valid API key exists."""
130
+ api_key = await self.get_api_key(provider, session_id)
131
+ return api_key is not None
@@ -0,0 +1,160 @@
1
+ """
2
+ Chat WebSocket Client - JSON-RPC 2.0 Protocol
3
+
4
+ Simple client for chat backend. Uses aiohttp (already in project).
5
+ Connection URL: ws://{host}:{port}/ws/{sessionId}?api_key={apiKey}&client_type=web
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import uuid
11
+ import aiohttp
12
+ from typing import Optional, Dict, Any
13
+ import structlog
14
+
15
+ logger = structlog.get_logger()
16
+
17
+
18
+ async def send_chat_message(
19
+ host: str,
20
+ port: int,
21
+ session_id: str,
22
+ api_key: str,
23
+ content: str,
24
+ metadata: Optional[Dict[str, Any]] = None,
25
+ timeout: float = 10.0
26
+ ) -> Dict[str, Any]:
27
+ """Send a chat message via JSON-RPC 2.0 WebSocket.
28
+
29
+ Args:
30
+ host: Chat server host
31
+ port: Chat server port
32
+ session_id: Session identifier
33
+ api_key: API key for authentication
34
+ content: Message content
35
+ metadata: Optional message metadata
36
+ timeout: Request timeout in seconds
37
+
38
+ Returns:
39
+ JSON-RPC result or error dict
40
+ """
41
+ url = f"ws://{host}:{port}/ws/{session_id}?api_key={api_key}&client_type=web"
42
+ request_id = str(uuid.uuid4())
43
+
44
+ request = {
45
+ "jsonrpc": "2.0",
46
+ "method": "chat.sendMessage",
47
+ "params": {"content": content, **(metadata or {})},
48
+ "id": request_id
49
+ }
50
+
51
+ try:
52
+ async with aiohttp.ClientSession() as session:
53
+ async with session.ws_connect(url, timeout=timeout) as ws:
54
+ await ws.send_json(request)
55
+
56
+ # Wait for response with matching id
57
+ async with asyncio.timeout(timeout):
58
+ async for msg in ws:
59
+ if msg.type == aiohttp.WSMsgType.TEXT:
60
+ data = json.loads(msg.data)
61
+ if data.get("id") == request_id:
62
+ if "error" in data:
63
+ return {"success": False, "error": data["error"].get("message", "Unknown error")}
64
+ return {"success": True, "result": data.get("result", {})}
65
+ elif msg.type in (aiohttp.WSMsgType.CLOSED, aiohttp.WSMsgType.ERROR):
66
+ break
67
+
68
+ return {"success": False, "error": "No response received"}
69
+
70
+ except asyncio.TimeoutError:
71
+ return {"success": False, "error": "Connection timeout"}
72
+ except Exception as e:
73
+ logger.error("[Chat] Send error", error=str(e))
74
+ return {"success": False, "error": str(e)}
75
+
76
+
77
+ async def get_chat_history(
78
+ host: str,
79
+ port: int,
80
+ session_id: str,
81
+ api_key: str,
82
+ limit: int = 50,
83
+ timeout: float = 10.0
84
+ ) -> Dict[str, Any]:
85
+ """Get chat history via JSON-RPC 2.0 WebSocket.
86
+
87
+ Args:
88
+ host: Chat server host
89
+ port: Chat server port
90
+ session_id: Session identifier
91
+ api_key: API key for authentication
92
+ limit: Max messages to return
93
+ timeout: Request timeout in seconds
94
+
95
+ Returns:
96
+ JSON-RPC result with messages or error dict
97
+ """
98
+ url = f"ws://{host}:{port}/ws/{session_id}?api_key={api_key}&client_type=web"
99
+ request_id = str(uuid.uuid4())
100
+
101
+ request = {
102
+ "jsonrpc": "2.0",
103
+ "method": "chat.getHistory",
104
+ "params": {"limit": limit},
105
+ "id": request_id
106
+ }
107
+
108
+ try:
109
+ async with aiohttp.ClientSession() as session:
110
+ async with session.ws_connect(url, timeout=timeout) as ws:
111
+ await ws.send_json(request)
112
+
113
+ async with asyncio.timeout(timeout):
114
+ async for msg in ws:
115
+ if msg.type == aiohttp.WSMsgType.TEXT:
116
+ data = json.loads(msg.data)
117
+ if data.get("id") == request_id:
118
+ if "error" in data:
119
+ return {"success": False, "error": data["error"].get("message", "Unknown error")}
120
+ return {"success": True, "messages": data.get("result", {}).get("messages", [])}
121
+ elif msg.type in (aiohttp.WSMsgType.CLOSED, aiohttp.WSMsgType.ERROR):
122
+ break
123
+
124
+ return {"success": False, "error": "No response received"}
125
+
126
+ except asyncio.TimeoutError:
127
+ return {"success": False, "error": "Connection timeout"}
128
+ except Exception as e:
129
+ logger.error("[Chat] History error", error=str(e))
130
+ return {"success": False, "error": str(e)}
131
+
132
+
133
+ async def ping_chat_server(
134
+ host: str,
135
+ port: int,
136
+ session_id: str,
137
+ api_key: str,
138
+ timeout: float = 5.0
139
+ ) -> bool:
140
+ """Ping chat server to check connectivity."""
141
+ url = f"ws://{host}:{port}/ws/{session_id}?api_key={api_key}&client_type=web"
142
+ request_id = str(uuid.uuid4())
143
+
144
+ try:
145
+ async with aiohttp.ClientSession() as session:
146
+ async with session.ws_connect(url, timeout=timeout) as ws:
147
+ await ws.send_json({"jsonrpc": "2.0", "method": "ping", "params": {}, "id": request_id})
148
+
149
+ async with asyncio.timeout(timeout):
150
+ async for msg in ws:
151
+ if msg.type == aiohttp.WSMsgType.TEXT:
152
+ data = json.loads(msg.data)
153
+ if data.get("id") == request_id:
154
+ return "error" not in data
155
+ elif msg.type in (aiohttp.WSMsgType.CLOSED, aiohttp.WSMsgType.ERROR):
156
+ break
157
+ return False
158
+
159
+ except Exception:
160
+ return False
@@ -0,0 +1,12 @@
1
+ """Deployment module - Event-driven workflow deployment."""
2
+
3
+ from .state import DeploymentState, TriggerInfo
4
+ from .triggers import TriggerManager
5
+ from .manager import DeploymentManager
6
+
7
+ __all__ = [
8
+ "DeploymentState",
9
+ "TriggerInfo",
10
+ "TriggerManager",
11
+ "DeploymentManager",
12
+ ]