machinaos 0.0.78 → 0.0.80

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 (743) hide show
  1. package/.env.template +74 -5
  2. package/{workflows/AI Assistant_workflow-1778504793388-ou1m1tz2x.json → .machina/workflows/AI Assistant_example_workflow-1779017037684-e2e5da7a.json } +164 -105
  3. package/{workflows/AI Employee_example_workflow-1777720598005-u4cm858dv.json → .machina/workflows/AI Employee_example_workflow-1779102911870-cbc76c82.json } +582 -328
  4. package/{workflows/Claude Assistant_workflow-1778380124051-mdibn807c.json → .machina/workflows/Claude Assistant_example_workflow-1779095939967-2369cff4.json } +152 -83
  5. package/README.md +5 -2
  6. package/bin/cli.js +2 -2
  7. package/{machina → cli}/__main__.py +11 -7
  8. package/cli/_common.py +122 -0
  9. package/cli/buildenv.py +40 -0
  10. package/cli/cli.py +204 -0
  11. package/{machina → cli}/colors.py +10 -2
  12. package/cli/commands/__init__.py +1 -0
  13. package/cli/commands/_temporal_specs.py +59 -0
  14. package/{machina → cli}/commands/build.py +35 -45
  15. package/cli/commands/clean.py +141 -0
  16. package/cli/commands/daemon/__init__.py +47 -0
  17. package/cli/commands/daemon/_state.py +97 -0
  18. package/cli/commands/daemon/restart.py +14 -0
  19. package/cli/commands/daemon/start.py +49 -0
  20. package/cli/commands/daemon/status.py +20 -0
  21. package/cli/commands/daemon/stop.py +22 -0
  22. package/{machina → cli}/commands/dev.py +32 -42
  23. package/{machina → cli}/commands/docs.py +13 -11
  24. package/{machina → cli}/commands/start.py +69 -62
  25. package/{machina → cli}/commands/stop.py +7 -10
  26. package/{machina → cli}/commands/version.py +12 -6
  27. package/cli/config.py +170 -0
  28. package/cli/platform_.py +169 -0
  29. package/{machina → cli}/ports.py +42 -3
  30. package/{machina → cli}/run.py +29 -2
  31. package/{machina → cli}/supervisor.py +29 -12
  32. package/{machina → cli}/tcp.py +6 -2
  33. package/{machina → cli}/tree.py +38 -11
  34. package/client/dist/assets/{ActionBar-Du2MSFSz.js → ActionBar-Cjr3TF7g.js} +1 -1
  35. package/client/dist/assets/{ApiKeyInput-k2LBmBjb.js → ApiKeyInput-DIJE2PVA.js} +1 -1
  36. package/client/dist/assets/{ApiKeyPanel-C_bV9U0X.js → ApiKeyPanel-CPmye7uh.js} +1 -1
  37. package/client/dist/assets/{ApiUsageSection-CmVfwZzL.js → ApiUsageSection-TF_7gH2D.js} +1 -1
  38. package/client/dist/assets/{EmailPanel-CeKIMGu-.js → EmailPanel-Bs-xvbKR.js} +1 -1
  39. package/client/dist/assets/{OAuthPanel-KA3t3Q2K.js → OAuthPanel-BDtVJhAV.js} +1 -1
  40. package/client/dist/assets/{QrPairingPanel-NgNpJNuk.js → QrPairingPanel-BwJehTuZ.js} +1 -1
  41. package/client/dist/assets/{RateLimitSection-Du5YNVIA.js → RateLimitSection-CfNOoPIS.js} +1 -1
  42. package/client/dist/assets/{StatusCard-DNLyayXc.js → StatusCard-DkwIrgdP.js} +1 -1
  43. package/client/dist/assets/index-P2FzntoL.js +165 -0
  44. package/client/dist/index.html +1 -1
  45. package/client/package.json +1 -1
  46. package/client/src/Dashboard.tsx +128 -76
  47. package/client/src/adapters/nodeSpecToDescription.ts +7 -0
  48. package/client/src/assets/icons/index.test.ts +10 -0
  49. package/client/src/assets/icons/index.ts +16 -3
  50. package/client/src/components/AIAgentNode.tsx +8 -8
  51. package/client/src/components/ParameterRenderer.tsx +6 -3
  52. package/client/src/components/SkillEditorModal.tsx +1 -0
  53. package/client/src/components/credentials/panels/EmailPanel.tsx +2 -0
  54. package/client/src/components/credentials/sections/ProviderDefaultsSection.tsx +2 -0
  55. package/client/src/components/credentials/sections/RateLimitSection.tsx +1 -0
  56. package/client/src/components/icons/AIProviderIcons.tsx +1 -0
  57. package/client/src/components/maps/GoogleMapsPicker.tsx +1 -0
  58. package/client/src/components/parameterPanel/InputSection.tsx +1 -0
  59. package/client/src/components/parameterPanel/MasterSkillEditor.tsx +1 -0
  60. package/client/src/components/parameterPanel/OutputSection.tsx +1 -0
  61. package/client/src/components/ui/ComponentPalette.tsx +1 -0
  62. package/client/src/components/ui/MapSelector.tsx +1 -0
  63. package/client/src/components/ui/NodeContextMenu.tsx +3 -3
  64. package/client/src/components/ui/SettingsPanel.tsx +1 -0
  65. package/client/src/components/ui/action-button.tsx +1 -0
  66. package/client/src/components/ui/badge.tsx +1 -0
  67. package/client/src/components/ui/button.tsx +1 -0
  68. package/client/src/components/ui/form.tsx +1 -0
  69. package/client/src/components/ui/tabs.tsx +1 -0
  70. package/client/src/contexts/AuthContext.tsx +1 -0
  71. package/client/src/contexts/ThemeContext.tsx +1 -0
  72. package/client/src/contexts/WebSocketContext.tsx +104 -34
  73. package/client/src/hooks/__tests__/useApiKeys.test.ts +2 -2
  74. package/client/src/hooks/useReactFlowNodes.ts +1 -0
  75. package/client/src/hooks/useWorkflowValidation.ts +142 -0
  76. package/client/src/lib/nodeSpec.ts +1 -0
  77. package/client/src/test/providers.tsx +1 -0
  78. package/client/src/types/__tests__/cloudEvents.test.ts +5 -2
  79. package/client/src/types/cloudEvents.ts +19 -7
  80. package/client/src/utils/nodeUtils.ts +1 -1
  81. package/client/src/utils/workflow.ts +8 -2
  82. package/client/src/utils/workflowExport.ts +60 -3
  83. package/package.json +24 -23
  84. package/scripts/install.js +16 -27
  85. package/scripts/migrate_icons.py +3 -1
  86. package/scripts/migrate_skill_icons.py +6 -7
  87. package/scripts/postinstall.js +11 -9
  88. package/server/config/ai_cli_providers.json +2 -3
  89. package/server/config/credential_providers.json +15 -15
  90. package/server/config/llm_defaults.json +1 -1
  91. package/server/config/model_registry.json +416 -611
  92. package/server/constants.py +285 -223
  93. package/server/core/__init__.py +1 -1
  94. package/server/core/cache.py +9 -29
  95. package/server/core/cleanup.py +12 -24
  96. package/server/core/config.py +148 -24
  97. package/server/core/container.py +68 -59
  98. package/server/core/credential_backends.py +5 -13
  99. package/server/core/credentials_database.py +13 -43
  100. package/server/core/database.py +292 -353
  101. package/server/core/health.py +4 -5
  102. package/server/core/logging.py +241 -87
  103. package/server/core/paths.py +285 -0
  104. package/server/core/tracing.py +2 -8
  105. package/server/gunicorn.conf.py +1 -0
  106. package/server/main.py +150 -74
  107. package/server/middleware/auth.py +18 -24
  108. package/server/models/__init__.py +1 -1
  109. package/server/models/auth.py +5 -12
  110. package/server/models/database.py +36 -68
  111. package/server/models/node_metadata.py +25 -18
  112. package/server/nodejs/dist/index.js +107 -0
  113. package/server/nodes/README.md +11 -5
  114. package/server/nodes/__init__.py +1 -1
  115. package/server/nodes/_visuals.py +146 -14
  116. package/server/nodes/agent/_events.py +124 -0
  117. package/server/nodes/agent/_handles.py +15 -29
  118. package/server/nodes/agent/_inline.py +28 -25
  119. package/server/nodes/agent/_specialized.py +30 -15
  120. package/server/nodes/agent/{ai_agent.py → ai_agent/__init__.py} +33 -17
  121. package/server/nodes/agent/ai_agent/meta.json +3 -0
  122. package/server/nodes/agent/{ai_employee.py → ai_employee/__init__.py} +5 -2
  123. package/server/nodes/agent/ai_employee/meta.json +3 -0
  124. package/server/nodes/agent/{android_agent.py → android_agent/__init__.py} +1 -1
  125. package/server/nodes/agent/android_agent/meta.json +3 -0
  126. package/server/nodes/agent/{autonomous_agent.py → autonomous_agent/__init__.py} +2 -1
  127. package/server/nodes/agent/autonomous_agent/meta.json +3 -0
  128. package/server/nodes/agent/{chat_agent.py → chat_agent/__init__.py} +29 -12
  129. package/server/nodes/agent/chat_agent/meta.json +3 -0
  130. package/server/nodes/agent/{claude_code_agent.py → claude_code_agent/__init__.py} +192 -95
  131. package/server/nodes/agent/claude_code_agent/_handlers.py +169 -0
  132. package/server/{services/claude_oauth.py → nodes/agent/claude_code_agent/_oauth.py} +26 -13
  133. package/server/nodes/agent/claude_code_agent/_pool.py +1020 -0
  134. package/server/nodes/agent/claude_code_agent/_provider.py +513 -0
  135. package/server/nodes/agent/claude_code_agent/_skills.py +245 -0
  136. package/server/nodes/agent/claude_code_agent/meta.json +3 -0
  137. package/server/nodes/agent/{codex_agent.py → codex_agent/__init__.py} +26 -35
  138. package/server/nodes/agent/codex_agent/meta.json +3 -0
  139. package/server/nodes/agent/{coding_agent.py → coding_agent/__init__.py} +1 -1
  140. package/server/nodes/agent/coding_agent/meta.json +3 -0
  141. package/server/nodes/agent/{consumer_agent.py → consumer_agent/__init__.py} +1 -1
  142. package/server/nodes/agent/consumer_agent/meta.json +3 -0
  143. package/server/nodes/agent/{orchestrator_agent.py → orchestrator_agent/__init__.py} +5 -2
  144. package/server/nodes/agent/orchestrator_agent/meta.json +3 -0
  145. package/server/nodes/agent/{payments_agent.py → payments_agent/__init__.py} +1 -1
  146. package/server/nodes/agent/payments_agent/meta.json +3 -0
  147. package/server/nodes/agent/{productivity_agent.py → productivity_agent/__init__.py} +1 -1
  148. package/server/nodes/agent/productivity_agent/meta.json +3 -0
  149. package/server/nodes/agent/{rlm_agent.py → rlm_agent/__init__.py} +18 -17
  150. package/server/nodes/agent/rlm_agent/meta.json +3 -0
  151. package/server/nodes/agent/{social_agent.py → social_agent/__init__.py} +1 -1
  152. package/server/nodes/agent/social_agent/meta.json +3 -0
  153. package/server/nodes/agent/{task_agent.py → task_agent/__init__.py} +1 -1
  154. package/server/nodes/agent/task_agent/meta.json +3 -0
  155. package/server/nodes/agent/{tool_agent.py → tool_agent/__init__.py} +1 -1
  156. package/server/nodes/agent/tool_agent/meta.json +3 -0
  157. package/server/nodes/agent/{travel_agent.py → travel_agent/__init__.py} +1 -1
  158. package/server/nodes/agent/travel_agent/meta.json +3 -0
  159. package/server/nodes/agent/{web_agent.py → web_agent/__init__.py} +1 -1
  160. package/server/nodes/agent/web_agent/meta.json +3 -0
  161. package/server/nodes/android/__init__.py +24 -0
  162. package/server/nodes/android/_base.py +93 -76
  163. package/server/nodes/android/_dispatcher.py +140 -223
  164. package/server/nodes/android/_events.py +154 -0
  165. package/server/nodes/android/_handlers.py +13 -7
  166. package/server/nodes/android/_option_loaders.py +1 -4
  167. package/server/nodes/android/_refresh.py +27 -37
  168. package/server/nodes/android/_relay/broadcaster.py +25 -41
  169. package/server/nodes/android/_relay/client.py +23 -42
  170. package/server/nodes/android/_relay/manager.py +1 -0
  171. package/server/nodes/android/_relay/protocol.py +6 -0
  172. package/server/nodes/android/_router.py +48 -133
  173. package/server/nodes/android/{airplane_mode_control.py → airplane_mode_control/__init__.py} +2 -1
  174. package/server/nodes/android/airplane_mode_control/meta.json +3 -0
  175. package/server/nodes/android/{app_launcher.py → app_launcher/__init__.py} +2 -1
  176. package/server/nodes/android/app_launcher/meta.json +3 -0
  177. package/server/nodes/android/{app_list.py → app_list/__init__.py} +2 -1
  178. package/server/nodes/android/app_list/meta.json +3 -0
  179. package/server/nodes/android/{audio_automation.py → audio_automation/__init__.py} +2 -1
  180. package/server/nodes/android/audio_automation/meta.json +3 -0
  181. package/server/nodes/android/{battery_monitor.py → battery_monitor/__init__.py} +2 -1
  182. package/server/nodes/android/battery_monitor/meta.json +3 -0
  183. package/server/nodes/android/{bluetooth_automation.py → bluetooth_automation/__init__.py} +2 -1
  184. package/server/nodes/android/bluetooth_automation/meta.json +3 -0
  185. package/server/nodes/android/{camera_control.py → camera_control/__init__.py} +2 -1
  186. package/server/nodes/android/camera_control/meta.json +3 -0
  187. package/server/nodes/android/{device_state_automation.py → device_state_automation/__init__.py} +2 -1
  188. package/server/nodes/android/device_state_automation/meta.json +3 -0
  189. package/server/nodes/android/{environmental_sensors.py → environmental_sensors/__init__.py} +2 -1
  190. package/server/nodes/android/environmental_sensors/meta.json +3 -0
  191. package/server/nodes/android/{location.py → location/__init__.py} +2 -1
  192. package/server/nodes/android/location/meta.json +3 -0
  193. package/server/nodes/android/{media_control.py → media_control/__init__.py} +2 -1
  194. package/server/nodes/android/media_control/meta.json +3 -0
  195. package/server/nodes/android/{motion_detection.py → motion_detection/__init__.py} +2 -1
  196. package/server/nodes/android/motion_detection/meta.json +3 -0
  197. package/server/nodes/android/{network_monitor.py → network_monitor/__init__.py} +2 -1
  198. package/server/nodes/android/network_monitor/meta.json +3 -0
  199. package/server/nodes/android/{screen_control_automation.py → screen_control_automation/__init__.py} +2 -1
  200. package/server/nodes/android/screen_control_automation/meta.json +3 -0
  201. package/server/nodes/android/{system_info.py → system_info/__init__.py} +2 -1
  202. package/server/nodes/android/system_info/meta.json +3 -0
  203. package/server/nodes/android/{wifi_automation.py → wifi_automation/__init__.py} +2 -1
  204. package/server/nodes/android/wifi_automation/meta.json +3 -0
  205. package/server/nodes/browser/__init__.py +22 -1
  206. package/server/nodes/browser/_install.py +63 -0
  207. package/server/nodes/browser/_service.py +21 -25
  208. package/server/nodes/browser/{browser.py → browser/__init__.py} +58 -25
  209. package/server/nodes/browser/browser/meta.json +3 -0
  210. package/server/nodes/chat/{chat_history.py → chat_history/__init__.py} +2 -4
  211. package/server/nodes/chat/chat_history/meta.json +3 -0
  212. package/server/nodes/chat/{chat_send.py → chat_send/__init__.py} +2 -4
  213. package/server/nodes/chat/chat_send/icon.svg +1 -0
  214. package/server/nodes/chat/chat_send/meta.json +3 -0
  215. package/server/nodes/code/_base.py +1 -1
  216. package/server/nodes/code/{javascript_executor.py → javascript_executor/__init__.py} +5 -5
  217. package/server/nodes/code/javascript_executor/meta.json +3 -0
  218. package/server/nodes/code/{python_executor.py → python_executor/__init__.py} +32 -14
  219. package/server/nodes/code/python_executor/meta.json +3 -0
  220. package/server/nodes/code/{typescript_executor.py → typescript_executor/__init__.py} +5 -5
  221. package/server/nodes/code/typescript_executor/meta.json +3 -0
  222. package/server/nodes/document/{document_parser.py → document_parser/__init__.py} +26 -15
  223. package/server/nodes/document/document_parser/meta.json +3 -0
  224. package/server/nodes/document/{embedding_generator.py → embedding_generator/__init__.py} +16 -9
  225. package/server/nodes/document/embedding_generator/meta.json +3 -0
  226. package/server/nodes/document/{file_downloader.py → file_downloader/__init__.py} +30 -20
  227. package/server/nodes/document/file_downloader/meta.json +3 -0
  228. package/server/nodes/document/{http_scraper.py → http_scraper/__init__.py} +31 -21
  229. package/server/nodes/document/http_scraper/meta.json +3 -0
  230. package/server/nodes/document/{text_chunker.py → text_chunker/__init__.py} +17 -12
  231. package/server/nodes/document/text_chunker/meta.json +3 -0
  232. package/server/nodes/document/{vector_store.py → vector_store/__init__.py} +88 -72
  233. package/server/nodes/document/vector_store/meta.json +3 -0
  234. package/server/nodes/email/__init__.py +9 -2
  235. package/server/nodes/email/_events.py +54 -0
  236. package/server/nodes/email/_filters.py +3 -3
  237. package/server/nodes/email/_himalaya.py +95 -50
  238. package/server/nodes/email/_service.py +23 -13
  239. package/server/nodes/email/{email_read.py → email_read/__init__.py} +23 -11
  240. package/server/nodes/email/email_read/icon.svg +6 -0
  241. package/server/nodes/email/email_read/meta.json +3 -0
  242. package/server/nodes/email/{email_receive.py → email_receive/__init__.py} +45 -23
  243. package/server/nodes/email/email_receive/meta.json +3 -0
  244. package/server/nodes/email/{email_send.py → email_send/__init__.py} +13 -7
  245. package/server/nodes/email/email_send/meta.json +3 -0
  246. package/server/nodes/filesystem/_backend.py +1 -5
  247. package/server/nodes/filesystem/{file_modify.py → file_modify/__init__.py} +10 -5
  248. package/server/nodes/filesystem/file_modify/meta.json +3 -0
  249. package/server/nodes/filesystem/{file_read.py → file_read/__init__.py} +7 -3
  250. package/server/nodes/filesystem/file_read/meta.json +3 -0
  251. package/server/nodes/filesystem/{fs_search.py → fs_search/__init__.py} +11 -3
  252. package/server/nodes/filesystem/fs_search/meta.json +3 -0
  253. package/server/nodes/filesystem/{shell.py → shell/__init__.py} +12 -5
  254. package/server/nodes/filesystem/shell/meta.json +3 -0
  255. package/server/nodes/google/__init__.py +12 -0
  256. package/server/nodes/google/_auth_helper.py +7 -13
  257. package/server/nodes/google/_base.py +14 -11
  258. package/server/nodes/google/_credentials.py +2 -1
  259. package/server/nodes/google/_events.py +47 -0
  260. package/server/nodes/google/_filters.py +3 -3
  261. package/server/nodes/google/_gmail.py +70 -47
  262. package/server/nodes/google/_handlers.py +3 -1
  263. package/server/nodes/google/_oauth.py +25 -11
  264. package/server/nodes/google/_option_loaders.py +9 -30
  265. package/server/nodes/google/_refresh.py +8 -12
  266. package/server/nodes/google/_router.py +4 -5
  267. package/server/nodes/google/{calendar.py → calendar/__init__.py} +87 -64
  268. package/server/nodes/google/calendar/meta.json +3 -0
  269. package/server/nodes/google/{contacts.py → contacts/__init__.py} +84 -72
  270. package/server/nodes/google/contacts/meta.json +3 -0
  271. package/server/nodes/google/{drive.py → drive/__init__.py} +87 -72
  272. package/server/nodes/google/drive/meta.json +3 -0
  273. package/server/nodes/google/{gmail.py → gmail/__init__.py} +73 -39
  274. package/server/nodes/google/gmail/meta.json +3 -0
  275. package/server/nodes/google/{gmail_receive.py → gmail_receive/__init__.py} +31 -24
  276. package/server/nodes/google/gmail_receive/icon.svg +7 -0
  277. package/server/nodes/google/gmail_receive/meta.json +3 -0
  278. package/server/nodes/google/google.svg +7 -0
  279. package/server/nodes/google/{sheets.py → sheets/__init__.py} +54 -42
  280. package/server/nodes/google/sheets/meta.json +3 -0
  281. package/server/nodes/google/{tasks.py → tasks/__init__.py} +56 -43
  282. package/server/nodes/google/tasks/meta.json +3 -0
  283. package/server/nodes/groups.py +28 -28
  284. package/server/nodes/location/__init__.py +31 -1
  285. package/server/nodes/location/_credentials.py +1 -6
  286. package/server/nodes/location/_service.py +88 -107
  287. package/server/nodes/location/{gmaps_create.py → gmaps_create/__init__.py} +6 -6
  288. package/server/nodes/location/gmaps_create/meta.json +3 -0
  289. package/server/nodes/location/{gmaps_locations.py → gmaps_locations/__init__.py} +8 -6
  290. package/server/nodes/location/gmaps_locations/meta.json +3 -0
  291. package/server/nodes/location/{gmaps_nearby_places.py → gmaps_nearby_places/__init__.py} +8 -6
  292. package/server/nodes/location/gmaps_nearby_places/meta.json +3 -0
  293. package/server/nodes/model/_base.py +10 -7
  294. package/server/nodes/model/_credentials.py +10 -10
  295. package/server/nodes/model/_local_validator.py +28 -24
  296. package/server/nodes/model/{anthropic_chat_model.py → anthropic_chat_model/__init__.py} +5 -3
  297. package/server/nodes/model/anthropic_chat_model/meta.json +3 -0
  298. package/server/nodes/model/{cerebras_chat_model.py → cerebras_chat_model/__init__.py} +5 -3
  299. package/server/nodes/model/cerebras_chat_model/meta.json +3 -0
  300. package/server/nodes/model/{deepseek_chat_model.py → deepseek_chat_model/__init__.py} +8 -4
  301. package/server/nodes/model/deepseek_chat_model/meta.json +3 -0
  302. package/server/nodes/model/{gemini_chat_model.py → gemini_chat_model/__init__.py} +5 -3
  303. package/server/nodes/model/gemini_chat_model/meta.json +3 -0
  304. package/server/nodes/model/{groq_chat_model.py → groq_chat_model/__init__.py} +2 -2
  305. package/server/nodes/model/groq_chat_model/meta.json +3 -0
  306. package/server/nodes/model/{kimi_chat_model.py → kimi_chat_model/__init__.py} +2 -2
  307. package/server/nodes/model/kimi_chat_model/meta.json +3 -0
  308. package/server/nodes/model/{lmstudio_chat_model.py → lmstudio_chat_model/__init__.py} +2 -2
  309. package/server/nodes/model/lmstudio_chat_model/meta.json +3 -0
  310. package/server/nodes/model/{mistral_chat_model.py → mistral_chat_model/__init__.py} +2 -2
  311. package/server/nodes/model/mistral_chat_model/meta.json +3 -0
  312. package/server/nodes/model/{ollama_chat_model.py → ollama_chat_model/__init__.py} +2 -2
  313. package/server/nodes/model/ollama_chat_model/meta.json +3 -0
  314. package/server/nodes/model/{openai_chat_model.py → openai_chat_model/__init__.py} +8 -4
  315. package/server/nodes/model/openai_chat_model/meta.json +3 -0
  316. package/server/nodes/model/{openrouter_chat_model.py → openrouter_chat_model/__init__.py} +8 -4
  317. package/server/nodes/model/openrouter_chat_model/meta.json +3 -0
  318. package/server/nodes/proxy/_usage.py +14 -15
  319. package/server/nodes/proxy/{proxy_config.py → proxy_config/__init__.py} +39 -30
  320. package/server/nodes/proxy/proxy_config/meta.json +3 -0
  321. package/server/nodes/proxy/{proxy_request.py → proxy_request/__init__.py} +30 -16
  322. package/server/nodes/proxy/proxy_request/meta.json +3 -0
  323. package/server/nodes/proxy/{proxy_status.py → proxy_status/__init__.py} +2 -0
  324. package/server/nodes/proxy/proxy_status/meta.json +3 -0
  325. package/server/nodes/scheduler/{cron_scheduler.py → cron_scheduler/__init__.py} +96 -23
  326. package/server/nodes/scheduler/cron_scheduler/_workflow.py +155 -0
  327. package/server/nodes/scheduler/cron_scheduler/meta.json +3 -0
  328. package/server/nodes/scheduler/{timer.py → timer/__init__.py} +6 -5
  329. package/server/nodes/scheduler/timer/meta.json +3 -0
  330. package/server/nodes/scraper/_credentials.py +0 -1
  331. package/server/nodes/scraper/{apify_actor.py → apify_actor/__init__.py} +44 -35
  332. package/server/nodes/scraper/apify_actor/icon.svg +5 -0
  333. package/server/nodes/scraper/apify_actor/meta.json +3 -0
  334. package/server/nodes/scraper/{crawlee_scraper.py → crawlee_scraper/__init__.py} +96 -57
  335. package/server/nodes/scraper/crawlee_scraper/meta.json +3 -0
  336. package/server/nodes/search/{brave_search.py → brave_search/__init__.py} +6 -5
  337. package/server/nodes/search/brave_search/icon.svg +3 -0
  338. package/server/nodes/search/brave_search/meta.json +3 -0
  339. package/server/nodes/search/{duckduckgo_search.py → duckduckgo_search/__init__.py} +17 -6
  340. package/server/nodes/search/duckduckgo_search/meta.json +3 -0
  341. package/server/nodes/search/{perplexity_search.py → perplexity_search/__init__.py} +4 -5
  342. package/server/nodes/search/perplexity_search/icon.svg +3 -0
  343. package/server/nodes/search/perplexity_search/meta.json +3 -0
  344. package/server/nodes/search/{serper_search.py → serper_search/__init__.py} +32 -25
  345. package/server/nodes/search/serper_search/icon.svg +3 -0
  346. package/server/nodes/search/serper_search/meta.json +3 -0
  347. package/server/nodes/skill/__init__.py +21 -1
  348. package/server/nodes/skill/_expander.py +75 -0
  349. package/server/nodes/skill/{master_skill.py → master_skill/__init__.py} +2 -8
  350. package/server/nodes/skill/master_skill/_events.py +84 -0
  351. package/server/nodes/skill/master_skill/meta.json +3 -0
  352. package/server/nodes/skill/{simple_memory.py → simple_memory/__init__.py} +8 -16
  353. package/server/nodes/skill/simple_memory/meta.json +3 -0
  354. package/server/nodes/social/_base.py +223 -231
  355. package/server/nodes/social/{social_receive.py → social_receive/__init__.py} +38 -13
  356. package/server/nodes/social/social_receive/meta.json +3 -0
  357. package/server/nodes/social/{social_send.py → social_send/__init__.py} +71 -29
  358. package/server/nodes/social/social_send/icon.svg +1 -0
  359. package/server/nodes/social/social_send/meta.json +3 -0
  360. package/server/nodes/stripe/__init__.py +7 -3
  361. package/server/nodes/stripe/_credentials.py +0 -1
  362. package/server/nodes/stripe/_handlers.py +18 -7
  363. package/server/nodes/stripe/_install.py +14 -15
  364. package/server/nodes/stripe/_source.py +5 -5
  365. package/server/nodes/stripe/icon.svg +1 -0
  366. package/server/nodes/stripe/meta.json +3 -0
  367. package/server/nodes/stripe/stripe_action.py +4 -4
  368. package/server/nodes/stripe/stripe_receive.py +6 -9
  369. package/server/nodes/telegram/__init__.py +13 -0
  370. package/server/nodes/telegram/_credentials.py +2 -7
  371. package/server/nodes/telegram/_events.py +167 -0
  372. package/server/nodes/telegram/_filters.py +3 -11
  373. package/server/nodes/telegram/_handlers.py +17 -7
  374. package/server/nodes/telegram/_refresh.py +24 -34
  375. package/server/nodes/telegram/_service.py +29 -45
  376. package/server/nodes/telegram/meta.json +3 -0
  377. package/server/nodes/telegram/telegram.svg +3 -0
  378. package/server/nodes/telegram/telegram_receive.py +38 -18
  379. package/server/nodes/telegram/telegram_send.py +21 -19
  380. package/server/nodes/text/{file_handler.py → file_handler/__init__.py} +7 -1
  381. package/server/nodes/text/file_handler/meta.json +3 -0
  382. package/server/nodes/text/{text_generator.py → text_generator/__init__.py} +2 -1
  383. package/server/nodes/text/text_generator/meta.json +3 -0
  384. package/server/nodes/tool/{agent_builder.py → agent_builder/__init__.py} +105 -100
  385. package/server/nodes/tool/agent_builder/_events.py +91 -0
  386. package/server/nodes/tool/agent_builder/meta.json +3 -0
  387. package/server/nodes/tool/{calculator_tool.py → calculator_tool/__init__.py} +19 -7
  388. package/server/nodes/tool/calculator_tool/meta.json +3 -0
  389. package/server/nodes/tool/{current_time_tool.py → current_time_tool/__init__.py} +6 -4
  390. package/server/nodes/tool/current_time_tool/meta.json +3 -0
  391. package/server/nodes/tool/{task_manager.py → task_manager/__init__.py} +17 -18
  392. package/server/nodes/tool/task_manager/meta.json +3 -0
  393. package/server/nodes/tool/{write_todos.py → write_todos/__init__.py} +20 -6
  394. package/server/nodes/tool/write_todos/meta.json +3 -0
  395. package/server/nodes/trigger/{chat_trigger.py → chat_trigger/__init__.py} +11 -7
  396. package/server/nodes/trigger/chat_trigger/_events.py +53 -0
  397. package/server/nodes/trigger/chat_trigger/meta.json +3 -0
  398. package/server/nodes/trigger/{task_trigger.py → task_trigger/__init__.py} +10 -7
  399. package/server/nodes/trigger/task_trigger/meta.json +3 -0
  400. package/server/nodes/trigger/{webhook_trigger.py → webhook_trigger/__init__.py} +10 -7
  401. package/server/nodes/trigger/webhook_trigger/_events.py +54 -0
  402. package/server/nodes/trigger/webhook_trigger/meta.json +3 -0
  403. package/server/nodes/twitter/__init__.py +7 -1
  404. package/server/nodes/twitter/_base.py +86 -61
  405. package/server/nodes/twitter/_credentials.py +7 -5
  406. package/server/nodes/twitter/_events.py +101 -0
  407. package/server/nodes/twitter/_filters.py +9 -9
  408. package/server/nodes/twitter/_handlers.py +3 -1
  409. package/server/nodes/twitter/_oauth.py +1 -2
  410. package/server/nodes/twitter/_refresh.py +8 -12
  411. package/server/nodes/twitter/{twitter_receive.py → twitter_receive/__init__.py} +7 -7
  412. package/server/nodes/twitter/twitter_receive/icon.svg +1 -0
  413. package/server/nodes/twitter/twitter_receive/meta.json +3 -0
  414. package/server/nodes/twitter/{twitter_search.py → twitter_search/__init__.py} +16 -11
  415. package/server/nodes/twitter/twitter_search/icon.svg +1 -0
  416. package/server/nodes/twitter/twitter_search/meta.json +3 -0
  417. package/server/nodes/twitter/{twitter_send.py → twitter_send/__init__.py} +60 -27
  418. package/server/nodes/twitter/twitter_send/icon.svg +1 -0
  419. package/server/nodes/twitter/twitter_send/meta.json +3 -0
  420. package/server/nodes/twitter/{twitter_user.py → twitter_user/__init__.py} +34 -19
  421. package/server/nodes/twitter/twitter_user/icon.svg +1 -0
  422. package/server/nodes/twitter/twitter_user/meta.json +3 -0
  423. package/server/nodes/utility/{console.py → console/__init__.py} +17 -22
  424. package/server/nodes/utility/console/meta.json +3 -0
  425. package/server/nodes/utility/{http_request.py → http_request/__init__.py} +9 -6
  426. package/server/nodes/utility/http_request/meta.json +3 -0
  427. package/server/nodes/utility/{process_manager.py → process_manager/__init__.py} +10 -6
  428. package/server/nodes/utility/process_manager/meta.json +3 -0
  429. package/server/nodes/utility/team_monitor/meta.json +3 -0
  430. package/server/nodes/utility/{webhook_response.py → webhook_response/__init__.py} +12 -7
  431. package/server/nodes/utility/webhook_response/meta.json +3 -0
  432. package/server/nodes/visuals.json +69 -251
  433. package/server/nodes/whatsapp/__init__.py +24 -0
  434. package/server/nodes/whatsapp/_base.py +283 -338
  435. package/server/nodes/whatsapp/_credentials.py +44 -0
  436. package/server/nodes/whatsapp/_events.py +277 -0
  437. package/server/nodes/whatsapp/_filters.py +36 -37
  438. package/server/nodes/whatsapp/_handlers.py +2 -0
  439. package/server/nodes/whatsapp/_option_loaders.py +1 -3
  440. package/server/nodes/whatsapp/_refresh.py +13 -18
  441. package/server/nodes/whatsapp/_runtime.py +9 -6
  442. package/server/nodes/whatsapp/_service.py +89 -152
  443. package/server/nodes/whatsapp/meta.json +3 -0
  444. package/server/nodes/whatsapp/whatsapp_db.py +116 -54
  445. package/server/nodes/whatsapp/whatsapp_receive.py +30 -13
  446. package/server/nodes/whatsapp/whatsapp_send.py +60 -37
  447. package/server/nodes/workflow/{start.py → start/__init__.py} +1 -4
  448. package/server/nodes/workflow/start/meta.json +3 -0
  449. package/server/package-lock.json +3 -3
  450. package/server/package.json +3 -0
  451. package/server/pyproject.toml +39 -10
  452. package/server/requirements.txt +3 -5
  453. package/server/routers/__init__.py +1 -1
  454. package/server/routers/auth.py +16 -56
  455. package/server/routers/database.py +27 -50
  456. package/server/routers/nodejs_compat.py +25 -87
  457. package/server/routers/schemas.py +66 -2
  458. package/server/routers/webhook.py +12 -12
  459. package/server/routers/websocket.py +312 -1716
  460. package/server/routers/workflow.py +28 -53
  461. package/server/scripts/smoke_test_skills.py +178 -0
  462. package/server/services/__init__.py +1 -1
  463. package/server/services/_supervisor/process.py +9 -3
  464. package/server/services/_supervisor/registry.py +3 -3
  465. package/server/services/_supervisor/util.py +1 -1
  466. package/server/services/agent_team.py +15 -43
  467. package/server/services/agent_teams/__init__.py +17 -0
  468. package/server/services/agent_teams/handlers.py +195 -0
  469. package/server/services/ai.py +853 -1108
  470. package/server/services/auth.py +10 -34
  471. package/server/services/chat_client.py +5 -34
  472. package/server/services/circuit_breaker.py +2 -6
  473. package/server/services/cli_agent/__init__.py +28 -4
  474. package/server/services/cli_agent/_cli_auth.py +61 -0
  475. package/server/services/cli_agent/_handlers.py +24 -183
  476. package/server/services/cli_agent/config.py +5 -8
  477. package/server/services/cli_agent/factory.py +168 -22
  478. package/server/services/cli_agent/jsonl_watcher.py +380 -0
  479. package/server/services/cli_agent/lockfile.py +9 -2
  480. package/server/services/cli_agent/mcp_server.py +110 -34
  481. package/server/services/cli_agent/protocol.py +37 -19
  482. package/server/services/cli_agent/providers/__init__.py +8 -4
  483. package/server/services/cli_agent/providers/google_gemini.py +11 -5
  484. package/server/services/cli_agent/providers/openai_codex.py +34 -34
  485. package/server/services/cli_agent/service.py +245 -83
  486. package/server/services/cli_agent/session.py +409 -229
  487. package/server/services/cli_agent/transports/__init__.py +47 -0
  488. package/server/services/cli_agent/transports/base.py +111 -0
  489. package/server/services/cli_agent/transports/posix.py +196 -0
  490. package/server/services/cli_agent/transports/windows.py +189 -0
  491. package/server/services/cli_agent/types.py +45 -18
  492. package/server/services/cli_agent/workflow_tools.py +28 -15
  493. package/server/services/compaction.py +68 -52
  494. package/server/services/credential_registry.py +6 -20
  495. package/server/services/credentials/__init__.py +18 -0
  496. package/server/services/credentials/handlers.py +196 -0
  497. package/server/services/deployment/__init__.py +12 -1
  498. package/server/services/deployment/canary_registry.py +137 -0
  499. package/server/services/deployment/handlers.py +382 -0
  500. package/server/services/deployment/manager.py +653 -163
  501. package/server/services/deployment/poll_registry.py +2 -6
  502. package/server/services/deployment/state.py +2 -0
  503. package/server/services/deployment/triggers.py +87 -93
  504. package/server/services/event_waiter.py +47 -54
  505. package/server/services/events/__init__.py +11 -0
  506. package/server/services/events/admin_handlers.py +368 -0
  507. package/server/services/events/daemon.py +3 -1
  508. package/server/services/events/dispatch.py +188 -0
  509. package/server/services/events/envelope.py +264 -45
  510. package/server/services/events/oauth_lifecycle.py +98 -42
  511. package/server/services/events/triggers.py +3 -13
  512. package/server/services/events/verifiers/hmac_basic.py +1 -1
  513. package/server/services/events/verifiers/standard_webhooks.py +2 -4
  514. package/server/services/events/webhook.py +2 -3
  515. package/server/services/example_loader.py +73 -15
  516. package/server/services/execution/cache.py +36 -76
  517. package/server/services/execution/conditions.py +7 -20
  518. package/server/services/execution/dlq.py +20 -24
  519. package/server/services/execution/executor.py +234 -265
  520. package/server/services/execution/models.py +40 -46
  521. package/server/services/execution/recovery.py +23 -46
  522. package/server/services/handlers/__init__.py +12 -16
  523. package/server/services/handlers/todo.py +3 -6
  524. package/server/services/handlers/tools.py +143 -194
  525. package/server/services/handlers/triggers.py +24 -23
  526. package/server/services/llm/config.py +10 -1
  527. package/server/services/llm/factory.py +16 -4
  528. package/server/services/llm/messages.py +1 -5
  529. package/server/services/llm/protocol.py +9 -1
  530. package/server/services/llm/providers/anthropic.py +23 -12
  531. package/server/services/llm/providers/gemini.py +43 -22
  532. package/server/services/llm/providers/openai.py +14 -6
  533. package/server/services/llm/providers/openrouter.py +6 -1
  534. package/server/services/markdown_formatter.py +1 -2
  535. package/server/services/memory/__init__.py +2 -2
  536. package/server/services/memory/jsonl.py +6 -2
  537. package/server/services/memory/markdown.py +6 -6
  538. package/server/services/memory/state.py +6 -5
  539. package/server/services/memory_store.py +8 -12
  540. package/server/services/model_registry.py +22 -20
  541. package/server/services/node_executor.py +85 -80
  542. package/server/services/node_output_schemas.py +4 -7
  543. package/server/services/node_registry.py +40 -4
  544. package/server/services/node_spec.py +3 -7
  545. package/server/services/nodejs_client.py +4 -14
  546. package/server/services/oauth_utils.py +11 -7
  547. package/server/services/parameter_resolver.py +30 -36
  548. package/server/services/plugin/base.py +321 -38
  549. package/server/services/plugin/connection.py +12 -7
  550. package/server/services/plugin/credential.py +80 -22
  551. package/server/services/plugin/edge_walker.py +128 -105
  552. package/server/services/plugin/identifiers.py +48 -0
  553. package/server/services/plugin/interceptor.py +1 -1
  554. package/server/services/plugin/oauth.py +25 -21
  555. package/server/services/plugin/operation.py +1 -1
  556. package/server/services/plugin/polling.py +151 -26
  557. package/server/services/plugin/registry.py +52 -4
  558. package/server/services/plugin/routing.py +6 -9
  559. package/server/services/plugin/scaling.py +36 -18
  560. package/server/services/plugin/service_factories.py +95 -0
  561. package/server/services/plugin/shutdown_hooks.py +103 -0
  562. package/server/services/plugin/social_provider_registry.py +80 -0
  563. package/server/services/plugin/ws.py +2 -1
  564. package/server/services/pricing.py +26 -40
  565. package/server/services/pricing_handlers.py +90 -0
  566. package/server/services/process_service.py +33 -32
  567. package/server/services/proxy/models.py +15 -9
  568. package/server/services/proxy/service.py +26 -40
  569. package/server/services/rlm/adapters.py +43 -40
  570. package/server/services/rlm/constants.py +9 -9
  571. package/server/services/rlm/service.py +57 -45
  572. package/server/services/scheduler.py +8 -39
  573. package/server/services/settings/__init__.py +16 -0
  574. package/server/services/settings/handlers.py +275 -0
  575. package/server/services/skill_loader.py +53 -45
  576. package/server/services/skill_prompt.py +8 -6
  577. package/server/services/skills/__init__.py +23 -0
  578. package/server/services/skills/handlers.py +479 -0
  579. package/server/services/status_broadcaster.py +314 -291
  580. package/server/services/temporal/__init__.py +22 -1
  581. package/server/services/temporal/_handlers.py +65 -0
  582. package/server/services/temporal/_install.py +158 -0
  583. package/server/services/temporal/_refresh.py +57 -0
  584. package/server/services/temporal/_retry_policies.py +85 -0
  585. package/server/services/temporal/_runtime.py +181 -0
  586. package/server/services/temporal/_supervised_runtime.py +102 -0
  587. package/server/services/temporal/activities.py +168 -11
  588. package/server/services/temporal/agent_activities.py +683 -0
  589. package/server/services/temporal/agent_workflow.py +601 -0
  590. package/server/services/temporal/client.py +58 -13
  591. package/server/services/temporal/executor.py +2 -3
  592. package/server/services/temporal/plugin_activities.py +37 -2
  593. package/server/services/temporal/plugin_registry.py +82 -0
  594. package/server/services/temporal/polling_trigger_workflow.py +267 -0
  595. package/server/services/temporal/schedules.py +220 -0
  596. package/server/services/temporal/search_attributes.py +177 -0
  597. package/server/services/temporal/trigger_listener_workflow.py +378 -0
  598. package/server/services/temporal/worker.py +111 -18
  599. package/server/services/temporal/workflow.py +259 -40
  600. package/server/services/temporal/ws_client.py +22 -11
  601. package/server/services/text.py +14 -28
  602. package/server/services/tracked_http.py +29 -49
  603. package/server/services/user_auth.py +7 -21
  604. package/server/services/workflow.py +28 -20
  605. package/server/services/workflow_import.py +351 -0
  606. package/server/services/workflow_ops.py +4 -0
  607. package/server/services/workflow_storage/__init__.py +18 -0
  608. package/server/services/workflow_storage/handlers.py +132 -0
  609. package/server/services/workflow_validator.py +209 -0
  610. package/server/services/ws_handler_registry.py +80 -9
  611. package/server/skills/assistant/agent-builder-skill/SKILL.md +6 -6
  612. package/server/tests/conftest.py +54 -3
  613. package/server/tests/credentials/test_auth_service.py +9 -21
  614. package/server/tests/credentials/test_credential_broadcasts.py +116 -22
  615. package/server/tests/credentials/test_credentials_database.py +12 -38
  616. package/server/tests/credentials/test_encryption.py +3 -9
  617. package/server/tests/credentials/test_google_oauth.py +1 -3
  618. package/server/tests/credentials/test_oauth_utils.py +31 -38
  619. package/server/tests/credentials/test_twitter_oauth.py +1 -3
  620. package/server/tests/credentials/test_websocket_handlers.py +37 -72
  621. package/server/tests/fixtures/tool_names_snapshot.json +78 -0
  622. package/server/tests/llm/test_factory.py +12 -4
  623. package/server/tests/llm/test_providers.py +25 -32
  624. package/server/tests/llm/test_wiring.py +27 -22
  625. package/server/tests/nodes/_compat.py +4 -5
  626. package/server/tests/nodes/_harness.py +31 -24
  627. package/server/tests/nodes/_mocks.py +2 -6
  628. package/server/tests/nodes/test_agent_builder.py +43 -35
  629. package/server/tests/nodes/test_ai_agents.py +29 -24
  630. package/server/tests/nodes/test_ai_chat_models.py +3 -9
  631. package/server/tests/nodes/test_ai_tools.py +29 -24
  632. package/server/tests/nodes/test_android.py +34 -64
  633. package/server/tests/nodes/test_chat_utility.py +2 -2
  634. package/server/tests/nodes/test_code_fs_process.py +26 -84
  635. package/server/tests/nodes/test_document.py +23 -47
  636. package/server/tests/nodes/test_email.py +88 -51
  637. package/server/tests/nodes/test_google_workspace.py +26 -20
  638. package/server/tests/nodes/test_http_proxy.py +43 -89
  639. package/server/tests/nodes/test_search.py +3 -9
  640. package/server/tests/nodes/test_specialized_agents.py +58 -162
  641. package/server/tests/nodes/test_stripe_plugin.py +25 -5
  642. package/server/tests/nodes/test_telegram_social.py +33 -37
  643. package/server/tests/nodes/test_twitter.py +59 -150
  644. package/server/tests/nodes/test_web_automation.py +21 -51
  645. package/server/tests/nodes/test_whatsapp.py +13 -19
  646. package/server/tests/nodes/test_workflow_triggers.py +16 -45
  647. package/server/tests/services/cli_agent/test_claude_session_events.py +201 -0
  648. package/server/tests/services/cli_agent/test_jsonl_watcher.py +190 -0
  649. package/server/tests/services/cli_agent/test_mcp_server.py +67 -29
  650. package/server/tests/services/cli_agent/test_providers.py +236 -47
  651. package/server/tests/services/cli_agent/test_service.py +9 -7
  652. package/server/tests/services/memory/test_jsonl.py +30 -25
  653. package/server/tests/services/test_events.py +26 -7
  654. package/server/tests/services/test_identifiers.py +122 -0
  655. package/server/tests/services/test_process_lifecycle.py +129 -0
  656. package/server/tests/services/test_supervisor.py +0 -1
  657. package/server/tests/temporal/__init__.py +0 -0
  658. package/server/tests/temporal/test_agent_workflow.py +215 -0
  659. package/server/tests/temporal/test_dispatch.py +231 -0
  660. package/server/tests/test_admin_handlers.py +394 -0
  661. package/server/tests/test_auto_skill.py +4 -2
  662. package/server/tests/test_canary_registry.py +310 -0
  663. package/server/tests/test_chat_trigger_canary_producer.py +101 -0
  664. package/server/tests/test_cloudevents_node_parameters.py +129 -0
  665. package/server/tests/test_credential_icon.py +115 -0
  666. package/server/tests/test_cron_canary.py +511 -0
  667. package/server/tests/test_deployment_canary_listener.py +692 -0
  668. package/server/tests/test_event_framework_phase_a.py +537 -0
  669. package/server/tests/test_no_raw_prints.py +131 -0
  670. package/server/tests/test_node_spec.py +196 -103
  671. package/server/tests/test_parameter_resolver.py +20 -20
  672. package/server/tests/test_plugin_contract.py +76 -49
  673. package/server/tests/test_plugin_helpers.py +0 -1
  674. package/server/tests/test_plugin_self_containment.py +40 -47
  675. package/server/tests/test_polling_trigger_workflow.py +572 -0
  676. package/server/tests/test_retry_policies.py +146 -0
  677. package/server/tests/test_service_factories.py +168 -0
  678. package/server/tests/test_shutdown_hooks.py +199 -0
  679. package/server/tests/test_social_provider_registry.py +177 -0
  680. package/server/tests/test_status_broadcasts.py +214 -63
  681. package/server/tests/test_task_trigger_canary_producer.py +131 -0
  682. package/server/tests/test_telegram_trigger_canary_producer.py +113 -0
  683. package/server/tests/test_tool_registry.py +110 -0
  684. package/server/tests/test_trigger_listener_workflow.py +365 -0
  685. package/server/tests/test_whatsapp_trigger_canary_producer.py +164 -0
  686. package/server/tests/test_workflow_ops.py +1 -3
  687. package/server/tests/test_workflow_validator.py +791 -0
  688. package/server/uv.lock +3539 -0
  689. package/client/dist/assets/index-DQ0nwhec.js +0 -257
  690. package/client/src/assets/icons/apify/index.ts +0 -19
  691. package/client/src/assets/icons/browser/index.ts +0 -17
  692. package/client/src/assets/icons/email/index.ts +0 -22
  693. package/client/src/assets/icons/google/index.ts +0 -34
  694. package/client/src/assets/icons/llm/deepseek.svg +0 -1
  695. package/client/src/assets/icons/llm/index.ts +0 -18
  696. package/client/src/assets/icons/llm/kimi.svg +0 -1
  697. package/client/src/assets/icons/llm/mistral.svg +0 -1
  698. package/client/src/assets/icons/search/index.ts +0 -28
  699. package/client/src/assets/icons/telegram/index.ts +0 -19
  700. package/machina/buildenv.py +0 -44
  701. package/machina/cli.py +0 -55
  702. package/machina/commands/__init__.py +0 -1
  703. package/machina/commands/clean.py +0 -80
  704. package/machina/commands/daemon.py +0 -150
  705. package/machina/config.py +0 -93
  706. package/machina/platform_.py +0 -37
  707. package/machina/pyproject.toml +0 -33
  708. package/server/nodes/agent/deep_agent.py +0 -103
  709. package/server/services/agents/__init__.py +0 -9
  710. package/server/services/agents/adapters.py +0 -199
  711. package/server/services/agents/constants.py +0 -10
  712. package/server/services/agents/service.py +0 -297
  713. package/server/services/cli_agent/providers/anthropic_claude.py +0 -419
  714. /package/{machina → cli}/README.md +0 -0
  715. /package/{machina → cli}/__init__.py +0 -0
  716. /package/{client/src/assets/icons/apify → server/credentials/icons}/apify.svg +0 -0
  717. /package/{client/src/assets/icons/search/brave.svg → server/credentials/icons/brave_search.svg} +0 -0
  718. /package/{client/src/assets/icons/email/read.svg → server/credentials/icons/email_himalaya.svg} +0 -0
  719. /package/{client/src/assets/icons/search → server/credentials/icons}/perplexity.svg +0 -0
  720. /package/{client/src/assets/icons/search/google.svg → server/credentials/icons/serper.svg} +0 -0
  721. /package/{client/src/assets → server/credentials}/icons/stripe.svg +0 -0
  722. /package/{client/src/assets/icons/twitter/x.svg → server/credentials/icons/twitter.svg} +0 -0
  723. /package/{client/src/assets/icons/browser/chrome.svg → server/nodes/browser/browser/icon.svg} +0 -0
  724. /package/{client/src/assets/icons/chat/chat.svg → server/nodes/chat/chat_history/icon.svg} +0 -0
  725. /package/{client/src/assets/icons/code/javascript.svg → server/nodes/code/javascript_executor/icon.svg} +0 -0
  726. /package/{client/src/assets/icons/code/python.svg → server/nodes/code/python_executor/icon.svg} +0 -0
  727. /package/{client/src/assets/icons/code/typescript.svg → server/nodes/code/typescript_executor/icon.svg} +0 -0
  728. /package/{client/src/assets/icons/email/receive.svg → server/nodes/email/email_receive/icon.svg} +0 -0
  729. /package/{client/src/assets/icons/email/send.svg → server/nodes/email/email_send/icon.svg} +0 -0
  730. /package/{client/src/assets/icons/google/calendar.svg → server/nodes/google/calendar/icon.svg} +0 -0
  731. /package/{client/src/assets/icons/google/contacts.svg → server/nodes/google/contacts/icon.svg} +0 -0
  732. /package/{client/src/assets/icons/google/drive.svg → server/nodes/google/drive/icon.svg} +0 -0
  733. /package/{client/src/assets/icons/google/gmail.svg → server/nodes/google/gmail/icon.svg} +0 -0
  734. /package/{client/src/assets/icons/google/sheets.svg → server/nodes/google/sheets/icon.svg} +0 -0
  735. /package/{client/src/assets/icons/google/tasks.svg → server/nodes/google/tasks/icon.svg} +0 -0
  736. /package/{client/src/assets/icons/search/duckduckgo.svg → server/nodes/search/duckduckgo_search/icon.svg} +0 -0
  737. /package/{client/src/assets/icons/social/social.svg → server/nodes/social/social_receive/icon.svg} +0 -0
  738. /package/{client/src/assets/icons/telegram/telegram.svg → server/nodes/telegram/icon.svg} +0 -0
  739. /package/server/nodes/utility/{team_monitor.py → team_monitor/__init__.py} +0 -0
  740. /package/{client/src/assets/icons/whatsapp/whatsapp-db.svg → server/nodes/whatsapp/icon_whatsappDb.svg} +0 -0
  741. /package/{client/src/assets/icons/whatsapp/whatsapp-receive.svg → server/nodes/whatsapp/icon_whatsappReceive.svg} +0 -0
  742. /package/{client/src/assets/icons/whatsapp/whatsapp-send.svg → server/nodes/whatsapp/icon_whatsappSend.svg} +0 -0
  743. /package/{client/src/assets/icons → server/nodes}/whatsapp/whatsapp.svg +0 -0
@@ -0,0 +1,154 @@
1
+ """Wave 12 B1: CloudEvents factories + broadcaster wrappers for android.
2
+
3
+ Plugin-specific event emission — replaces the
4
+ ``StatusBroadcaster.update_android_status`` method (deleted in this
5
+ commit) and the direct ``broadcaster._status["android"]`` mutations
6
+ inside ``_refresh.py`` / ``_relay/broadcaster.py``.
7
+
8
+ Per RFC plugin_authoring_rfc.md §6.4: plugin-specific factories live in
9
+ the plugin folder. The cross-cutting ``WorkflowEvent.connection_status``
10
+ factory in ``services/events/envelope.py`` is borderline (parametrized
11
+ by plugin but each plugin's payload differs) — Phase B moves the
12
+ plugin-specific shape into per-plugin factories.
13
+
14
+ Wire format (Wave 12 D4 — legacy ``android_status`` raw frame retired):
15
+ - Typed CloudEvents sibling: ``{type: "plugin_connection_status",
16
+ data: <WorkflowEvent envelope>}``
17
+
18
+ The FE handler at ``client/src/contexts/WebSocketContext.tsx::case
19
+ 'plugin_connection_status'`` routes by ``envelope.source`` substring to
20
+ the matching Zustand setter.
21
+
22
+ Caller pattern (from ``_refresh.py`` / ``_relay/broadcaster.py``):
23
+ from nodes.android import broadcast_android_status
24
+ await broadcast_android_status(connected=True, device_id="...", ...)
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import Any, Dict, List, Optional
30
+
31
+ from services.events.envelope import WorkflowEvent
32
+
33
+
34
+ # Wire-routing key — outer ``type`` field on the WS frame.
35
+ _TYPED_WIRE_KEY = "plugin_connection_status"
36
+
37
+ # Module-level cache mirror — kept in sync with
38
+ # ``StatusBroadcaster._status["android"]`` until the framework's
39
+ # ``get_status()`` snapshot path migrates to a per-plugin getter
40
+ # registry. The plugin owns the SHAPE of this dict; the broadcaster
41
+ # stores it.
42
+ _DEFAULT_STATUS: Dict[str, Any] = {
43
+ "connected": False,
44
+ "paired": False,
45
+ "device_id": None,
46
+ "device_name": None,
47
+ "connected_devices": [],
48
+ "connection_type": None,
49
+ "qr_data": None,
50
+ "session_token": None,
51
+ }
52
+
53
+
54
+ # ---- Typed factory ---------------------------------------------------------
55
+
56
+
57
+ def android_connection_status(
58
+ *,
59
+ connected: bool,
60
+ paired: bool = False,
61
+ device_id: Optional[str] = None,
62
+ device_name: Optional[str] = None,
63
+ connected_devices: Optional[List[str]] = None,
64
+ connection_type: Optional[str] = None,
65
+ qr_data: Optional[str] = None,
66
+ session_token: Optional[str] = None,
67
+ ) -> WorkflowEvent:
68
+ """Build a typed CloudEvents envelope describing the android relay
69
+ connection state.
70
+
71
+ ``subject`` is the device id so the FE can route per-device updates.
72
+ ``data`` carries the full android status payload (mirrors
73
+ ``_DEFAULT_STATUS`` shape).
74
+ """
75
+ return WorkflowEvent(
76
+ source="machinaos://nodes/android",
77
+ type=("com.machinaos.android.connection.opened" if connected else "com.machinaos.android.connection.closed"),
78
+ subject=device_id,
79
+ data={
80
+ "connected": connected,
81
+ "paired": paired,
82
+ "device_id": device_id,
83
+ "device_name": device_name,
84
+ "connected_devices": list(connected_devices or []),
85
+ "connection_type": connection_type,
86
+ "qr_data": qr_data,
87
+ "session_token": session_token,
88
+ },
89
+ )
90
+
91
+
92
+ # ---- Broadcaster wrapper ---------------------------------------------------
93
+
94
+
95
+ async def broadcast_android_status(
96
+ *,
97
+ connected: bool,
98
+ paired: bool = False,
99
+ device_id: Optional[str] = None,
100
+ device_name: Optional[str] = None,
101
+ connected_devices: Optional[List[str]] = None,
102
+ connection_type: Optional[str] = None,
103
+ qr_data: Optional[str] = None,
104
+ session_token: Optional[str] = None,
105
+ ) -> None:
106
+ """Update the android status cache + emit the typed
107
+ ``plugin_connection_status`` CloudEvents envelope.
108
+
109
+ Replaces ``StatusBroadcaster.update_android_status``. The legacy
110
+ raw ``android_status`` frame retired in Wave 12 D4 — FE consumes
111
+ via the envelope-aware ``plugin_connection_status`` case in
112
+ ``WebSocketContext.tsx`` (routes by ``envelope.source``).
113
+ """
114
+ from services.status_broadcaster import get_status_broadcaster
115
+
116
+ broadcaster = get_status_broadcaster()
117
+
118
+ # Status cache lives on the broadcaster (still consumed by
119
+ # ``StatusBroadcaster.get_android_status()`` + the WS-connect
120
+ # initial-status snapshot). Plugin owns the SHAPE of the cache.
121
+ payload: Dict[str, Any] = {
122
+ "connected": connected,
123
+ "paired": paired,
124
+ "device_id": device_id,
125
+ "device_name": device_name,
126
+ "connected_devices": list(connected_devices or []),
127
+ "connection_type": connection_type,
128
+ "qr_data": qr_data,
129
+ "session_token": session_token,
130
+ }
131
+ broadcaster._status["android"] = payload
132
+
133
+ event = android_connection_status(
134
+ connected=connected,
135
+ paired=paired,
136
+ device_id=device_id,
137
+ device_name=device_name,
138
+ connected_devices=connected_devices,
139
+ connection_type=connection_type,
140
+ qr_data=qr_data,
141
+ session_token=session_token,
142
+ )
143
+ await broadcaster.broadcast(
144
+ {
145
+ "type": _TYPED_WIRE_KEY,
146
+ "data": event.model_dump(mode="json"),
147
+ }
148
+ )
149
+
150
+
151
+ __all__ = [
152
+ "android_connection_status",
153
+ "broadcast_android_status",
154
+ ]
@@ -29,6 +29,12 @@ from services.status_broadcaster import get_status_broadcaster
29
29
  logger = get_logger(__name__)
30
30
 
31
31
 
32
+ async def handle_get_android_status(data: Dict[str, Any], websocket: WebSocket) -> Dict[str, Any]:
33
+ """Get Android connection status (Wave 13.9 — moved from routers/websocket.py)."""
34
+ broadcaster = get_status_broadcaster()
35
+ return {"type": "android_status", "data": broadcaster.get_android_status()}
36
+
37
+
32
38
  async def handle_get_android_devices(data: Dict[str, Any], websocket: WebSocket) -> Dict[str, Any]:
33
39
  """Get list of connected Android devices."""
34
40
  from services.plugin.deps import get_android_service
@@ -49,16 +55,16 @@ async def handle_execute_android_action(data: Dict[str, Any], websocket: WebSock
49
55
 
50
56
  await broadcaster.update_node_status(node_id, "executing")
51
57
  result = await android_service.execute_service(
52
- node_id=node_id, service_id=service_id, action=action,
58
+ node_id=node_id,
59
+ service_id=service_id,
60
+ action=action,
53
61
  parameters=data.get("parameters", {}),
54
62
  android_host=data.get("android_host", "localhost"),
55
- android_port=data.get("android_port", 8888)
63
+ android_port=data.get("android_port", 8888),
56
64
  )
57
65
 
58
66
  status = "success" if result.get("success") else "error"
59
- await broadcaster.update_node_status(
60
- node_id, status, result.get("result") or {"error": result.get("error")}
61
- )
67
+ await broadcaster.update_node_status(node_id, status, result.get("result") or {"error": result.get("error")})
62
68
  return result
63
69
 
64
70
 
@@ -84,8 +90,7 @@ async def handle_android_relay_connect(data: Dict[str, Any], websocket: WebSocke
84
90
  client, error = await get_relay_client(url, api_key)
85
91
  if client:
86
92
  logger.info(
87
- f"[WebSocket] Android relay connect success, qr_data present: "
88
- f"{bool(client.qr_data)}, session_token: {client.session_token}"
93
+ f"[WebSocket] Android relay connect success, qr_data present: " f"{bool(client.qr_data)}, session_token: {client.session_token}"
89
94
  )
90
95
  return {
91
96
  "success": True,
@@ -146,6 +151,7 @@ async def handle_android_relay_reconnect(data: Dict[str, Any], websocket: WebSoc
146
151
 
147
152
 
148
153
  WS_HANDLERS = {
154
+ "get_android_status": handle_get_android_status,
149
155
  "get_android_devices": handle_get_android_devices,
150
156
  "execute_android_action": handle_execute_android_action,
151
157
  "android_relay_connect": handle_android_relay_connect,
@@ -36,9 +36,6 @@ async def load_service_actions(params: Dict[str, Any]) -> List[Dict[str, Any]]:
36
36
 
37
37
  android_svc = get_android_service()
38
38
  actions = await android_svc.list_actions(service_id) # type: ignore[attr-defined]
39
- return [
40
- {"value": a, "label": a.replace("_", " ").title()}
41
- for a in actions or []
42
- ]
39
+ return [{"value": a, "label": a.replace("_", " ").title()} for a in actions or []]
43
40
  except Exception:
44
41
  return []
@@ -37,27 +37,27 @@ async def refresh_android_status(broadcaster: "StatusBroadcaster") -> None:
37
37
 
38
38
 
39
39
  async def _auto_reconnect_body(broadcaster: "StatusBroadcaster", span) -> None:
40
+ # Single source of truth for android status emission — owns both
41
+ # the cache update + the dual-emit (legacy raw + typed sibling).
42
+ from ._events import broadcast_android_status
43
+
40
44
  try:
41
45
  # Already connected? Refresh the cached snapshot and stop.
42
46
  from ._relay.manager import get_current_relay_client
43
47
 
44
48
  existing = get_current_relay_client()
45
49
  if existing and existing.is_connected():
46
- broadcaster._status["android"] = {
47
- "connected": True,
48
- "paired": existing.is_paired(),
49
- "device_id": existing.paired_device_id,
50
- "device_name": existing.paired_device_name,
51
- "connected_devices": list(existing.get_connected_devices()),
52
- "connection_type": "relay",
53
- "qr_data": existing.qr_data,
54
- "session_token": existing.session_token,
55
- }
50
+ await broadcast_android_status(
51
+ connected=True,
52
+ paired=existing.is_paired(),
53
+ device_id=existing.paired_device_id,
54
+ device_name=existing.paired_device_name,
55
+ connected_devices=list(existing.get_connected_devices()),
56
+ connection_type="relay",
57
+ qr_data=existing.qr_data,
58
+ session_token=existing.session_token,
59
+ )
56
60
  logger.debug("[StatusBroadcaster] Android relay already connected")
57
- await broadcaster.broadcast({
58
- "type": "android_status",
59
- "data": broadcaster._status["android"],
60
- })
61
61
  span.set_attribute("path", "already_connected")
62
62
  return
63
63
 
@@ -77,9 +77,7 @@ async def _auto_reconnect_body(broadcaster: "StatusBroadcaster", span) -> None:
77
77
 
78
78
  if not relay_url or not api_key:
79
79
  span.set_attribute("path", "session_missing_creds")
80
- logger.debug(
81
- "[StatusBroadcaster] Stored session missing relay URL or API key"
82
- )
80
+ logger.debug("[StatusBroadcaster] Stored session missing relay URL or API key")
83
81
  return
84
82
 
85
83
  span.set_attribute("path", "auto_reconnect")
@@ -98,30 +96,22 @@ async def _auto_reconnect_body(broadcaster: "StatusBroadcaster", span) -> None:
98
96
  # The relay server creates a new session on each connect, so
99
97
  # pairing may be lost -- mirror whatever the new client
100
98
  # reports.
101
- broadcaster._status["android"] = {
102
- "connected": True,
103
- "paired": client.is_paired(),
104
- "device_id": client.paired_device_id,
105
- "device_name": client.paired_device_name,
106
- "connected_devices": list(client.get_connected_devices()),
107
- "connection_type": "relay",
108
- "qr_data": client.qr_data,
109
- "session_token": client.session_token,
110
- }
111
- await broadcaster.broadcast({
112
- "type": "android_status",
113
- "data": broadcaster._status["android"],
114
- })
99
+ await broadcast_android_status(
100
+ connected=True,
101
+ paired=client.is_paired(),
102
+ device_id=client.paired_device_id,
103
+ device_name=client.paired_device_name,
104
+ connected_devices=list(client.get_connected_devices()),
105
+ connection_type="relay",
106
+ qr_data=client.qr_data,
107
+ session_token=client.session_token,
108
+ )
115
109
  span.set_attribute("reconnect_ok", True)
116
110
  else:
117
111
  span.set_attribute("reconnect_ok", False)
118
- logger.warning(
119
- "[StatusBroadcaster] Failed to reconnect Android relay: %s", error
120
- )
112
+ logger.warning("[StatusBroadcaster] Failed to reconnect Android relay: %s", error)
121
113
  # Stored session is stale; drop it.
122
114
  await database.clear_android_relay_session()
123
115
  except Exception as exc: # noqa: BLE001 -- mirror pre-migration behaviour
124
116
  span.record_exception(exc)
125
- logger.debug(
126
- "[StatusBroadcaster] Could not auto-reconnect Android relay: %s", exc
127
- )
117
+ logger.debug("[StatusBroadcaster] Could not auto-reconnect Android relay: %s", exc)
@@ -1,39 +1,37 @@
1
1
  """
2
2
  Android Status Broadcaster
3
3
 
4
- Broadcasts Android relay connection status changes to frontend WebSocket clients.
4
+ Relay-specific helpers that translate relay-shaped arguments
5
+ (``devices: Set[str]``, derived ``connection_type="relay"``) into the
6
+ canonical :func:`nodes.android.broadcast_android_status` shape. Wave 12
7
+ B1 — the actual broadcast emission moved into
8
+ :mod:`nodes.android._events` (plugin-owned). This file just adapts
9
+ relay-state to that shape.
5
10
  """
11
+
6
12
  from typing import Optional, Set
7
13
  import structlog
8
14
 
9
15
  logger = structlog.get_logger()
10
16
 
11
17
 
12
- async def broadcast_android_status(
18
+ async def _emit_relay_status(
13
19
  connected: bool,
14
20
  paired: bool = False,
15
21
  device_id: Optional[str] = None,
16
22
  device_name: Optional[str] = None,
17
23
  devices: Optional[Set[str]] = None,
18
24
  qr_data: Optional[str] = None,
19
- session_token: Optional[str] = None
25
+ session_token: Optional[str] = None,
20
26
  ):
21
- """
22
- Broadcast Android relay status changes to frontend WebSocket clients.
23
-
24
- Args:
25
- connected: Whether connected to relay server
26
- paired: Whether paired with Android device
27
- device_id: Paired device ID (if any)
28
- device_name: Paired device name (if any)
29
- devices: Set of all connected device IDs
30
- qr_data: QR code data for pairing (app://pair?token=...)
31
- session_token: Relay session token
32
- """
27
+ """Translate relay-shaped args and route to the canonical
28
+ plugin-owned broadcaster (``nodes.android._events``)."""
33
29
  try:
34
- from services.status_broadcaster import get_status_broadcaster
35
- broadcaster = get_status_broadcaster()
36
- await broadcaster.update_android_status(
30
+ # Import from the plugin package — single source of truth
31
+ # for the android status wire format (Wave 12 B1).
32
+ from nodes.android import broadcast_android_status
33
+
34
+ await broadcast_android_status(
37
35
  connected=connected,
38
36
  paired=paired,
39
37
  device_id=device_id,
@@ -41,7 +39,7 @@ async def broadcast_android_status(
41
39
  connected_devices=list(devices) if devices else [],
42
40
  connection_type="relay" if connected else None,
43
41
  qr_data=qr_data,
44
- session_token=session_token
42
+ session_token=session_token,
45
43
  )
46
44
  except Exception as e:
47
45
  logger.warning("[Android] Failed to broadcast status", error=str(e))
@@ -49,20 +47,12 @@ async def broadcast_android_status(
49
47
 
50
48
  async def broadcast_connected(device_id: str, device_name: Optional[str] = None):
51
49
  """Broadcast that Android device is paired"""
52
- await broadcast_android_status(
53
- connected=True,
54
- paired=True,
55
- device_id=device_id,
56
- device_name=device_name,
57
- devices={device_id} if device_id else set()
50
+ await _emit_relay_status(
51
+ connected=True, paired=True, device_id=device_id, device_name=device_name, devices={device_id} if device_id else set()
58
52
  )
59
53
 
60
54
 
61
- async def broadcast_device_disconnected(
62
- relay_connected: bool = True,
63
- qr_data: Optional[str] = None,
64
- session_token: Optional[str] = None
65
- ):
55
+ async def broadcast_device_disconnected(relay_connected: bool = True, qr_data: Optional[str] = None, session_token: Optional[str] = None):
66
56
  """Broadcast that Android device is disconnected (but relay may still be connected).
67
57
 
68
58
  This is called when the Android device unpairs. The relay connection may still be active.
@@ -73,26 +63,20 @@ async def broadcast_device_disconnected(
73
63
  qr_data: QR code data for re-pairing
74
64
  session_token: Current session token
75
65
  """
76
- await broadcast_android_status(
66
+ await _emit_relay_status(
77
67
  connected=relay_connected, # Relay may still be connected
78
68
  paired=False, # Device is disconnected
79
69
  device_id=None,
80
70
  device_name=None,
81
71
  devices=set(),
82
72
  qr_data=qr_data, # Keep QR data for re-pairing
83
- session_token=session_token
73
+ session_token=session_token,
84
74
  )
85
75
 
86
76
 
87
77
  async def broadcast_relay_disconnected():
88
78
  """Broadcast that relay connection is closed (fully disconnected)"""
89
- await broadcast_android_status(
90
- connected=False,
91
- paired=False,
92
- device_id=None,
93
- device_name=None,
94
- devices=set()
95
- )
79
+ await _emit_relay_status(connected=False, paired=False, device_id=None, device_name=None, devices=set())
96
80
 
97
81
 
98
82
  # Legacy alias for backwards compatibility
@@ -103,12 +87,12 @@ async def broadcast_disconnected():
103
87
 
104
88
  async def broadcast_qr_code(qr_data: str, session_token: Optional[str] = None):
105
89
  """Broadcast QR code for pairing"""
106
- await broadcast_android_status(
90
+ await _emit_relay_status(
107
91
  connected=True, # Connected to relay but not paired
108
92
  paired=False,
109
93
  device_id=None,
110
94
  device_name=None,
111
95
  devices=set(),
112
96
  qr_data=qr_data,
113
- session_token=session_token
97
+ session_token=session_token,
114
98
  )
@@ -10,6 +10,7 @@ Connection flow:
10
10
  4. Receive pairing.connected when Android pairs
11
11
  5. Exchange messages via relay.send / relay.message
12
12
  """
13
+
13
14
  import asyncio
14
15
  import json
15
16
  import uuid
@@ -18,12 +19,7 @@ from typing import Optional, Dict, Any, Set, Callable
18
19
  import structlog
19
20
 
20
21
  from .protocol import RPCResponse, RPCRequestTracker, is_response
21
- from .broadcaster import (
22
- broadcast_connected,
23
- broadcast_device_disconnected,
24
- broadcast_relay_disconnected,
25
- broadcast_qr_code
26
- )
22
+ from .broadcaster import broadcast_connected, broadcast_device_disconnected, broadcast_relay_disconnected, broadcast_qr_code
27
23
 
28
24
  logger = structlog.get_logger()
29
25
 
@@ -90,7 +86,7 @@ class RelayWebSocketClient:
90
86
  self.url,
91
87
  heartbeat=30,
92
88
  autoping=True,
93
- ssl=True # Explicit SSL for wss://
89
+ ssl=True, # Explicit SSL for wss://
94
90
  )
95
91
  self.connected = True
96
92
  self._running = True
@@ -111,9 +107,7 @@ class RelayWebSocketClient:
111
107
  self.session_token = params.get("session_token")
112
108
  self.qr_data = params.get("qr_data")
113
109
 
114
- logger.info("[Relay] Connection established",
115
- session_token=self.session_token,
116
- has_qr=bool(self.qr_data))
110
+ logger.info("[Relay] Connection established", session_token=self.session_token, has_qr=bool(self.qr_data))
117
111
 
118
112
  # Broadcast QR data to frontend
119
113
  if self.qr_data:
@@ -208,6 +202,7 @@ class RelayWebSocketClient:
208
202
  """Clear stored pairing session from database."""
209
203
  try:
210
204
  from services.plugin.deps import get_database
205
+
211
206
  database = get_database()
212
207
 
213
208
  await database.clear_android_relay_session()
@@ -277,11 +272,7 @@ class RelayWebSocketClient:
277
272
  await asyncio.sleep(25)
278
273
  if self._running and self.ws and not self.ws.closed:
279
274
  try:
280
- await self.ws.send_json({
281
- "jsonrpc": "2.0",
282
- "method": "ping",
283
- "params": {}
284
- })
275
+ await self.ws.send_json({"jsonrpc": "2.0", "method": "ping", "params": {}})
285
276
  except Exception as e:
286
277
  logger.error("[Relay] Keepalive error", error=str(e))
287
278
  self._running = False
@@ -335,9 +326,7 @@ class RelayWebSocketClient:
335
326
  self.paired_device_id = params.get("device_id")
336
327
  self.paired_device_name = params.get("device_name")
337
328
 
338
- logger.info("[Relay] Android paired",
339
- device_id=self.paired_device_id,
340
- device_name=self.paired_device_name)
329
+ logger.info("[Relay] Android paired", device_id=self.paired_device_id, device_name=self.paired_device_name)
341
330
 
342
331
  await broadcast_connected(self.paired_device_id, self.paired_device_name)
343
332
 
@@ -353,9 +342,9 @@ class RelayWebSocketClient:
353
342
  self.paired_device_id = params.get("device_id")
354
343
  self.paired_device_name = params.get("device_name")
355
344
 
356
- logger.info("[Relay] Android pairing restored (auto-reconnect)",
357
- device_id=self.paired_device_id,
358
- device_name=self.paired_device_name)
345
+ logger.info(
346
+ "[Relay] Android pairing restored (auto-reconnect)", device_id=self.paired_device_id, device_name=self.paired_device_name
347
+ )
359
348
 
360
349
  await broadcast_connected(self.paired_device_id, self.paired_device_name)
361
350
 
@@ -369,6 +358,7 @@ class RelayWebSocketClient:
369
358
  """Save pairing session to database for auto-reconnect."""
370
359
  try:
371
360
  from services.plugin.deps import get_database
361
+
372
362
  database = get_database()
373
363
 
374
364
  await database.save_android_relay_session(
@@ -376,7 +366,7 @@ class RelayWebSocketClient:
376
366
  api_key=self.api_key,
377
367
  device_id=self.paired_device_id,
378
368
  device_name=self.paired_device_name,
379
- session_token=self.session_token
369
+ session_token=self.session_token,
380
370
  )
381
371
  logger.debug("[Relay] Pairing session saved for auto-reconnect")
382
372
  except Exception as e:
@@ -396,11 +386,7 @@ class RelayWebSocketClient:
396
386
  self.paired_device_name = None
397
387
 
398
388
  # Broadcast device disconnection - relay is still connected, pass QR data for re-pairing
399
- await broadcast_device_disconnected(
400
- relay_connected=self.is_connected(),
401
- qr_data=self.qr_data,
402
- session_token=self.session_token
403
- )
389
+ await broadcast_device_disconnected(relay_connected=self.is_connected(), qr_data=self.qr_data, session_token=self.session_token)
404
390
 
405
391
  if self.on_pairing_disconnected:
406
392
  await self.on_pairing_disconnected(params)
@@ -414,8 +400,7 @@ class RelayWebSocketClient:
414
400
  # Schema: params = {"data": {...}}
415
401
  data = params.get("data", {})
416
402
 
417
- logger.debug("[Relay] relay.message received",
418
- data_keys=list(data.keys()) if isinstance(data, dict) else "not_dict")
403
+ logger.debug("[Relay] relay.message received", data_keys=list(data.keys()) if isinstance(data, dict) else "not_dict")
419
404
 
420
405
  # Route to service response queue if matching request_id
421
406
  # Android app uses "request_id" (underscore), not "requestId" (camelCase)
@@ -505,7 +490,7 @@ class RelayWebSocketClient:
505
490
  action: str,
506
491
  parameters: Dict[str, Any] = None,
507
492
  target_id: Optional[str] = None, # Ignored, kept for compatibility
508
- timeout: float = 30.0
493
+ timeout: float = 30.0,
509
494
  ) -> Optional[Dict[str, Any]]:
510
495
  """
511
496
  Send service request to paired Android device.
@@ -535,17 +520,11 @@ class RelayWebSocketClient:
535
520
  # - action
536
521
  # - request_id (not requestId)
537
522
  # - params (not parameters)
538
- await self.relay_send({
539
- "service": service_id,
540
- "action": action,
541
- "request_id": request_id,
542
- "params": parameters or {}
543
- }, timeout=5.0)
544
-
545
- logger.debug("[Relay] Sent service request",
546
- request_id=request_id,
547
- service_id=service_id,
548
- action=action)
523
+ await self.relay_send(
524
+ {"service": service_id, "action": action, "request_id": request_id, "params": parameters or {}}, timeout=5.0
525
+ )
526
+
527
+ logger.debug("[Relay] Sent service request", request_id=request_id, service_id=service_id, action=action)
549
528
 
550
529
  # Wait for response
551
530
  logger.debug("[Relay] Waiting for response", request_id=request_id, timeout=timeout)
@@ -554,7 +533,9 @@ class RelayWebSocketClient:
554
533
  return response
555
534
 
556
535
  except asyncio.TimeoutError:
557
- logger.warning("[Relay] Service response timeout", request_id=request_id, timeout=timeout, pending_queues=list(self._service_queues.keys()))
536
+ logger.warning(
537
+ "[Relay] Service response timeout", request_id=request_id, timeout=timeout, pending_queues=list(self._service_queues.keys())
538
+ )
558
539
  return None
559
540
  except Exception as e:
560
541
  logger.error("[Relay] Service request error", error=str(e))
@@ -4,6 +4,7 @@ Android Relay Client Manager
4
4
  Global instance management for persistent WebSocket connection.
5
5
  Provides singleton pattern for reusing connection across API requests.
6
6
  """
7
+
7
8
  from typing import Optional
8
9
  import structlog
9
10
 
@@ -15,6 +15,7 @@ Error codes:
15
15
  - -32002: Pairing failed
16
16
  - -32003: Relay error
17
17
  """
18
+
18
19
  import asyncio
19
20
  from dataclasses import dataclass, field
20
21
  from typing import Dict, Any, Optional
@@ -23,6 +24,7 @@ from enum import Enum
23
24
 
24
25
  class RPCErrorCode(Enum):
25
26
  """JSON-RPC 2.0 error codes"""
27
+
26
28
  INVALID_REQUEST = -32600
27
29
  METHOD_NOT_FOUND = -32601
28
30
  INVALID_PARAMS = -32602
@@ -34,6 +36,7 @@ class RPCErrorCode(Enum):
34
36
  @dataclass
35
37
  class RPCRequest:
36
38
  """JSON-RPC 2.0 request"""
39
+
37
40
  method: str
38
41
  params: Dict[str, Any] = field(default_factory=dict)
39
42
  id: Optional[int] = None
@@ -52,6 +55,7 @@ class RPCRequest:
52
55
  @dataclass
53
56
  class RPCResponse:
54
57
  """JSON-RPC 2.0 response"""
58
+
55
59
  id: int
56
60
  result: Optional[Any] = None
57
61
  error: Optional[Dict[str, Any]] = None
@@ -72,6 +76,7 @@ class RPCResponse:
72
76
  @dataclass
73
77
  class RPCEvent:
74
78
  """JSON-RPC 2.0 server event (notification without id)"""
79
+
75
80
  method: str
76
81
  params: Dict[str, Any] = field(default_factory=dict)
77
82
 
@@ -142,6 +147,7 @@ class RPCRequestTracker:
142
147
 
143
148
  class RPCError(Exception):
144
149
  """JSON-RPC error"""
150
+
145
151
  def __init__(self, message: str, code: int = None):
146
152
  super().__init__(message)
147
153
  self.code = code