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
@@ -37,14 +37,10 @@ PollCoroutine = Callable[[asyncio.Queue, Callable[[], bool]], Awaitable[None]]
37
37
  PollCoroutineFactory = Callable[[str, Dict[str, Any]], PollCoroutine]
38
38
 
39
39
 
40
- _REGISTRY: IdempotentRegistry[str, PollCoroutineFactory] = IdempotentRegistry(
41
- "poll_coroutine_factory"
42
- )
40
+ _REGISTRY: IdempotentRegistry[str, PollCoroutineFactory] = IdempotentRegistry("poll_coroutine_factory")
43
41
 
44
42
 
45
- def register_poll_coroutine_factory(
46
- node_type: str, factory: PollCoroutineFactory
47
- ) -> None:
43
+ def register_poll_coroutine_factory(node_type: str, factory: PollCoroutineFactory) -> None:
48
44
  """Publish a polling-coroutine factory for a trigger node type.
49
45
 
50
46
  Idempotent on re-import (same callable for the same key is a
@@ -8,6 +8,7 @@ from typing import Dict, Any, List, Optional
8
8
  @dataclass
9
9
  class DeploymentState:
10
10
  """Immutable deployment state."""
11
+
11
12
  deployment_id: str
12
13
  workflow_id: str
13
14
  is_running: bool
@@ -33,6 +34,7 @@ class DeploymentState:
33
34
  @dataclass
34
35
  class TriggerInfo:
35
36
  """Info about a registered trigger."""
37
+
36
38
  node_id: str
37
39
  node_type: str
38
40
  job_id: Optional[str] = None # For cron triggers
@@ -33,8 +33,7 @@ class TriggerManager:
33
33
  # CRON TRIGGERS
34
34
  # =========================================================================
35
35
 
36
- def setup_cron(self, node_id: str, cron_expr: str, timezone: str,
37
- on_tick: Callable[[], None]) -> str:
36
+ def setup_cron(self, node_id: str, cron_expr: str, timezone: str, on_tick: Callable[[], None]) -> str:
38
37
  """Setup a cron trigger that calls on_tick on schedule."""
39
38
  job_id = f"cron_{node_id}"
40
39
 
@@ -43,12 +42,7 @@ class TriggerManager:
43
42
  return
44
43
  on_tick()
45
44
 
46
- cron_scheduler.register_cron_job(
47
- job_id=job_id,
48
- cron_expression=cron_expr,
49
- callback=tick_callback,
50
- timezone=timezone
51
- )
45
+ cron_scheduler.register_cron_job(job_id=job_id, cron_expression=cron_expr, callback=tick_callback, timezone=timezone)
52
46
 
53
47
  self._active_cron_jobs[node_id] = job_id
54
48
  logger.info("Cron trigger setup", job_id=job_id, expr=cron_expr)
@@ -81,11 +75,15 @@ class TriggerManager:
81
75
  # EVENT TRIGGERS (Webhook, WhatsApp, etc.)
82
76
  # =========================================================================
83
77
 
84
- async def setup_event_trigger(self, node_id: str, node_type: str,
85
- parameters: Dict[str, Any],
86
- on_event: Callable[[Dict], Any],
87
- broadcaster: Any,
88
- workflow_id: Optional[str] = None) -> None:
78
+ async def setup_event_trigger(
79
+ self,
80
+ node_id: str,
81
+ node_type: str,
82
+ parameters: Dict[str, Any],
83
+ on_event: Callable[[Dict], Any],
84
+ broadcaster: Any,
85
+ workflow_id: Optional[str] = None,
86
+ ) -> None:
89
87
  """Setup an event-based trigger with queue-based sequential processing.
90
88
 
91
89
  Args:
@@ -111,12 +109,12 @@ class TriggerManager:
111
109
  msg = f"Waiting for {config.display_name}..."
112
110
  if queue_size > 0:
113
111
  msg = f"Waiting... ({queue_size} queued)"
114
- await broadcaster.update_node_status(node_id, "waiting", {
115
- "message": msg,
116
- "event_type": config.event_type,
117
- "waiter_id": waiter.id,
118
- "queue_size": queue_size
119
- }, workflow_id=workflow_id)
112
+ await broadcaster.update_node_status(
113
+ node_id,
114
+ "waiting",
115
+ {"message": msg, "event_type": config.event_type, "waiter_id": waiter.id, "queue_size": queue_size},
116
+ workflow_id=workflow_id,
117
+ )
120
118
 
121
119
  event_data = await event_waiter.wait_for_event(waiter)
122
120
  if self._is_running:
@@ -143,10 +141,9 @@ class TriggerManager:
143
141
  config = event_waiter.get_trigger_config(node_type)
144
142
 
145
143
  # Clear waiting indicator during execution
146
- await broadcaster.update_node_status(node_id, "idle", {
147
- "message": "Graph executing...",
148
- "is_processing": True
149
- }, workflow_id=workflow_id)
144
+ await broadcaster.update_node_status(
145
+ node_id, "idle", {"message": "Graph executing...", "is_processing": True}, workflow_id=workflow_id
146
+ )
150
147
 
151
148
  try:
152
149
  await on_event(event_data)
@@ -159,11 +156,9 @@ class TriggerManager:
159
156
  queue_size = event_queue.qsize()
160
157
  name = config.display_name if config else node_type
161
158
  msg = f"Waiting for {name}..." if queue_size == 0 else f"Processing next... ({queue_size} queued)"
162
- await broadcaster.update_node_status(node_id, "waiting", {
163
- "message": msg,
164
- "queue_size": queue_size,
165
- "is_processing": False
166
- }, workflow_id=workflow_id)
159
+ await broadcaster.update_node_status(
160
+ node_id, "waiting", {"message": msg, "queue_size": queue_size, "is_processing": False}, workflow_id=workflow_id
161
+ )
167
162
 
168
163
  except asyncio.CancelledError:
169
164
  break
@@ -184,12 +179,16 @@ class TriggerManager:
184
179
  task = asyncio.create_task(combined())
185
180
  self._active_listeners[node_id] = task
186
181
 
187
- async def setup_polling_trigger(self, node_id: str, node_type: str,
188
- parameters: Dict[str, Any],
189
- poll_coroutine: Callable,
190
- on_event: Callable[[Dict], Any],
191
- broadcaster: Any,
192
- workflow_id: Optional[str] = None) -> None:
182
+ async def setup_polling_trigger(
183
+ self,
184
+ node_id: str,
185
+ node_type: str,
186
+ parameters: Dict[str, Any],
187
+ poll_coroutine: Callable,
188
+ on_event: Callable[[Dict], Any],
189
+ broadcaster: Any,
190
+ workflow_id: Optional[str] = None,
191
+ ) -> None:
193
192
  """Setup a polling-based trigger with queue-based sequential processing.
194
193
 
195
194
  Unlike event triggers that wait for externally dispatched events via
@@ -211,10 +210,9 @@ class TriggerManager:
211
210
  # Broadcast initial "waiting" status immediately
212
211
  config = event_waiter.get_trigger_config(node_type)
213
212
  display_name = config.display_name if config else node_type
214
- await broadcaster.update_node_status(node_id, "waiting", {
215
- "message": f"Waiting for {display_name} (polling)...",
216
- "is_processing": False
217
- }, workflow_id=workflow_id)
213
+ await broadcaster.update_node_status(
214
+ node_id, "waiting", {"message": f"Waiting for {display_name} (polling)...", "is_processing": False}, workflow_id=workflow_id
215
+ )
218
216
 
219
217
  async def poller():
220
218
  """Run the polling coroutine to collect events."""
@@ -238,10 +236,9 @@ class TriggerManager:
238
236
  is_executing = True
239
237
  config = event_waiter.get_trigger_config(node_type)
240
238
 
241
- await broadcaster.update_node_status(node_id, "idle", {
242
- "message": "Graph executing...",
243
- "is_processing": True
244
- }, workflow_id=workflow_id)
239
+ await broadcaster.update_node_status(
240
+ node_id, "idle", {"message": "Graph executing...", "is_processing": True}, workflow_id=workflow_id
241
+ )
245
242
 
246
243
  try:
247
244
  await on_event(event_data)
@@ -253,11 +250,9 @@ class TriggerManager:
253
250
  queue_size = event_queue.qsize()
254
251
  name = config.display_name if config else node_type
255
252
  msg = f"Waiting for {name} (polling)..." if queue_size == 0 else f"Processing next... ({queue_size} queued)"
256
- await broadcaster.update_node_status(node_id, "waiting", {
257
- "message": msg,
258
- "queue_size": queue_size,
259
- "is_processing": False
260
- }, workflow_id=workflow_id)
253
+ await broadcaster.update_node_status(
254
+ node_id, "waiting", {"message": msg, "queue_size": queue_size, "is_processing": False}, workflow_id=workflow_id
255
+ )
261
256
 
262
257
  except asyncio.CancelledError:
263
258
  break
@@ -303,48 +298,48 @@ class TriggerManager:
303
298
  @staticmethod
304
299
  def build_cron_expression(parameters: Dict[str, Any]) -> Optional[str]:
305
300
  """Build cron expression from user-friendly parameters."""
306
- frequency = parameters.get('frequency', 'minutes')
307
-
308
- second, minute, hour = '0', '*/5', '*'
309
- day, month, weekday = '*', '*', '*'
310
-
311
- if frequency == 'seconds':
312
- interval = str(parameters.get('interval', 30))
313
- second, minute = f'*/{interval}', '*'
314
-
315
- elif frequency == 'minutes':
316
- interval = str(parameters.get('interval_minutes', 5))
317
- minute = f'*/{interval}' if interval != '1' else '*'
318
-
319
- elif frequency == 'hours':
320
- interval = str(parameters.get('interval_hours', 1))
321
- minute = '0'
322
- hour = f'*/{interval}' if interval != '1' else '*'
323
-
324
- elif frequency == 'days':
325
- time_str = parameters.get('daily_time', '09:00')
326
- parts = time_str.split(':')
327
- hour = parts[0] if parts else '9'
328
- minute = parts[1] if len(parts) > 1 else '0'
329
-
330
- elif frequency == 'weeks':
331
- time_str = parameters.get('weekly_time', '09:00')
332
- parts = time_str.split(':')
333
- hour = parts[0] if parts else '9'
334
- minute = parts[1] if len(parts) > 1 else '0'
335
- weekday = parameters.get('weekday', '1')
336
-
337
- elif frequency == 'months':
338
- time_str = parameters.get('monthly_time', '09:00')
339
- parts = time_str.split(':')
340
- hour = parts[0] if parts else '9'
341
- minute = parts[1] if len(parts) > 1 else '0'
342
- day = parameters.get('month_day', '1')
343
-
344
- elif frequency == 'once':
301
+ frequency = parameters.get("frequency", "minutes")
302
+
303
+ second, minute, hour = "0", "*/5", "*"
304
+ day, month, weekday = "*", "*", "*"
305
+
306
+ if frequency == "seconds":
307
+ interval = str(parameters.get("interval", 30))
308
+ second, minute = f"*/{interval}", "*"
309
+
310
+ elif frequency == "minutes":
311
+ interval = str(parameters.get("interval_minutes", 5))
312
+ minute = f"*/{interval}" if interval != "1" else "*"
313
+
314
+ elif frequency == "hours":
315
+ interval = str(parameters.get("interval_hours", 1))
316
+ minute = "0"
317
+ hour = f"*/{interval}" if interval != "1" else "*"
318
+
319
+ elif frequency == "days":
320
+ time_str = parameters.get("daily_time", "09:00")
321
+ parts = time_str.split(":")
322
+ hour = parts[0] if parts else "9"
323
+ minute = parts[1] if len(parts) > 1 else "0"
324
+
325
+ elif frequency == "weeks":
326
+ time_str = parameters.get("weekly_time", "09:00")
327
+ parts = time_str.split(":")
328
+ hour = parts[0] if parts else "9"
329
+ minute = parts[1] if len(parts) > 1 else "0"
330
+ weekday = parameters.get("weekday", "1")
331
+
332
+ elif frequency == "months":
333
+ time_str = parameters.get("monthly_time", "09:00")
334
+ parts = time_str.split(":")
335
+ hour = parts[0] if parts else "9"
336
+ minute = parts[1] if len(parts) > 1 else "0"
337
+ day = parameters.get("month_day", "1")
338
+
339
+ elif frequency == "once":
345
340
  return None
346
341
 
347
- return f'{second} {minute} {hour} {day} {month} {weekday}'
342
+ return f"{second} {minute} {hour} {day} {month} {weekday}"
348
343
 
349
344
  @staticmethod
350
345
  def find_trigger_nodes(nodes: list, edges: list) -> tuple:
@@ -355,16 +350,15 @@ class TriggerManager:
355
350
  after an AI agent). Each trigger listens for its event type and, when fired,
356
351
  executes its downstream subgraph independently.
357
352
  """
358
- trigger_types_no_cron = WORKFLOW_TRIGGER_TYPES - {'cronScheduler'}
359
- triggers = [n for n in nodes
360
- if n.get('type') in trigger_types_no_cron]
353
+ trigger_types_no_cron = WORKFLOW_TRIGGER_TYPES - {"cronScheduler"}
354
+ triggers = [n for n in nodes if n.get("type") in trigger_types_no_cron]
361
355
 
362
- start_nodes = [n for n in triggers if n.get('type') == 'start']
363
- event_triggers = [n for n in triggers if n.get('type') != 'start']
356
+ start_nodes = [n for n in triggers if n.get("type") == "start"]
357
+ event_triggers = [n for n in triggers if n.get("type") != "start"]
364
358
 
365
359
  return start_nodes, event_triggers
366
360
 
367
361
  @staticmethod
368
362
  def find_cron_nodes(nodes: list) -> list:
369
363
  """Find all cron scheduler nodes."""
370
- return [n for n in nodes if n.get('type') == 'cronScheduler']
364
+ return [n for n in nodes if n.get("type") == "cronScheduler"]
@@ -7,6 +7,7 @@ Architecture:
7
7
  - Redis mode: Events stored in Redis Streams, waiters poll streams with blocking XREAD
8
8
  - Memory mode: Events dispatched to in-memory asyncio.Future waiters
9
9
  """
10
+
10
11
  import asyncio
11
12
  import json
12
13
  import uuid
@@ -74,9 +75,11 @@ def is_redis_mode() -> bool:
74
75
  # TRIGGER CONFIGURATION REGISTRY
75
76
  # =============================================================================
76
77
 
78
+
77
79
  @dataclass
78
80
  class TriggerConfig:
79
81
  """Configuration for a trigger node type."""
82
+
80
83
  node_type: str
81
84
  event_type: str # Event to wait for (e.g., 'whatsapp_message_received')
82
85
  display_name: str
@@ -86,26 +89,10 @@ class TriggerConfig:
86
89
  # Note: cronScheduler is NOT an event-based trigger - it uses APScheduler directly
87
90
  TRIGGER_REGISTRY: Dict[str, TriggerConfig] = {
88
91
  # Framework-level triggers — not owned by any plugin domain.
89
- 'start': TriggerConfig(
90
- node_type='start',
91
- event_type='deploy_triggered',
92
- display_name='Deploy Start'
93
- ),
94
- 'webhookTrigger': TriggerConfig(
95
- node_type='webhookTrigger',
96
- event_type='webhook_received',
97
- display_name='Webhook Request'
98
- ),
99
- 'chatTrigger': TriggerConfig(
100
- node_type='chatTrigger',
101
- event_type='chat_message_received',
102
- display_name='Chat Message'
103
- ),
104
- 'taskTrigger': TriggerConfig(
105
- node_type='taskTrigger',
106
- event_type='task_completed',
107
- display_name='Task Completed'
108
- ),
92
+ "start": TriggerConfig(node_type="start", event_type="deploy_triggered", display_name="Deploy Start"),
93
+ "webhookTrigger": TriggerConfig(node_type="webhookTrigger", event_type="webhook_received", display_name="Webhook Request"),
94
+ "chatTrigger": TriggerConfig(node_type="chatTrigger", event_type="chat_message_received", display_name="Chat Message"),
95
+ "taskTrigger": TriggerConfig(node_type="taskTrigger", event_type="task_completed", display_name="Task Completed"),
109
96
  # Plugin-owned trigger entries (whatsappReceive, twitterReceive,
110
97
  # telegramReceive, emailReceive, googleGmailReceive) live in their
111
98
  # plugin folders' ``_filters.py`` and are backfilled here from each
@@ -175,6 +162,7 @@ def is_trigger_node(node_type: str) -> bool:
175
162
  This includes all trigger types: start, cronScheduler, and event-based triggers.
176
163
  """
177
164
  from constants import WORKFLOW_TRIGGER_TYPES
165
+
178
166
  return node_type in WORKFLOW_TRIGGER_TYPES
179
167
 
180
168
 
@@ -199,6 +187,7 @@ def get_trigger_config(node_type: str) -> Optional[TriggerConfig]:
199
187
  # FILTER BUILDERS - One per trigger type
200
188
  # =============================================================================
201
189
 
190
+
202
191
  def build_webhook_filter(params: Dict) -> Callable[[Dict], bool]:
203
192
  """Build filter function for webhook requests.
204
193
 
@@ -210,10 +199,10 @@ def build_webhook_filter(params: Dict) -> Callable[[Dict], bool]:
210
199
  Returns:
211
200
  Filter function that checks if event path matches
212
201
  """
213
- webhook_path = params.get('path', '')
202
+ webhook_path = params.get("path", "")
214
203
 
215
204
  def matches(data: Dict) -> bool:
216
- event_path = data.get('path', '')
205
+ event_path = data.get("path", "")
217
206
  if webhook_path and event_path != webhook_path:
218
207
  return False
219
208
  return True
@@ -231,11 +220,11 @@ def build_chat_filter(params: Dict) -> Callable[[Dict], bool]:
231
220
  Returns:
232
221
  Filter function that checks if event session_id matches
233
222
  """
234
- session_id = params.get('session_id', 'default')
223
+ session_id = params.get("session_id", "default")
235
224
 
236
225
  def matches(data: Dict) -> bool:
237
- event_session = data.get('session_id', 'default')
238
- if session_id != 'default' and event_session != session_id:
226
+ event_session = data.get("session_id", "default")
227
+ if session_id != "default" and event_session != session_id:
239
228
  return False
240
229
  return True
241
230
 
@@ -257,33 +246,33 @@ def build_task_completed_filter(params: Dict) -> Callable[[Dict], bool]:
257
246
  Returns:
258
247
  Filter function that checks if event matches criteria
259
248
  """
260
- task_id_filter = params.get('task_id', '')
261
- agent_name_filter = params.get('agent_name', '')
262
- status_filter = params.get('status_filter', 'all') # all, completed, error
263
- parent_node_id = params.get('parent_node_id', '')
249
+ task_id_filter = params.get("task_id", "")
250
+ agent_name_filter = params.get("agent_name", "")
251
+ status_filter = params.get("status_filter", "all") # all, completed, error
252
+ parent_node_id = params.get("parent_node_id", "")
264
253
 
265
254
  def matches(data: Dict) -> bool:
266
255
  # Task ID filter (exact match if specified)
267
256
  if task_id_filter:
268
- if data.get('task_id') != task_id_filter:
257
+ if data.get("task_id") != task_id_filter:
269
258
  return False
270
259
 
271
260
  # Agent name filter (contains match)
272
261
  if agent_name_filter:
273
- event_agent = data.get('agent_name', '')
262
+ event_agent = data.get("agent_name", "")
274
263
  if agent_name_filter.lower() not in event_agent.lower():
275
264
  return False
276
265
 
277
266
  # Status filter
278
- event_status = data.get('status', '')
279
- if status_filter == 'completed' and event_status != 'completed':
267
+ event_status = data.get("status", "")
268
+ if status_filter == "completed" and event_status != "completed":
280
269
  return False
281
- if status_filter == 'error' and event_status != 'error':
270
+ if status_filter == "error" and event_status != "error":
282
271
  return False
283
272
 
284
273
  # Parent node filter (for scoping to specific parent agent)
285
274
  if parent_node_id:
286
- if data.get('parent_node_id') != parent_node_id:
275
+ if data.get("parent_node_id") != parent_node_id:
287
276
  return False
288
277
 
289
278
  return True
@@ -301,17 +290,17 @@ def build_task_completed_filter(params: Dict) -> Callable[[Dict], bool]:
301
290
  # googleGmailReceive, emailReceive) live in their plugin folders'
302
291
  # ``_filters.py`` and self-register at import time.
303
292
  FILTER_BUILDERS: Dict[str, Callable[[Dict], Callable[[Dict], bool]]] = {
304
- 'webhookTrigger': build_webhook_filter,
305
- 'chatTrigger': build_chat_filter,
306
- 'taskTrigger': build_task_completed_filter,
293
+ "webhookTrigger": build_webhook_filter,
294
+ "chatTrigger": build_chat_filter,
295
+ "taskTrigger": build_task_completed_filter,
307
296
  }
308
297
 
309
298
  from services.plugin.registry import IdempotentRegistry as _IdempotentRegistry # noqa: E402
310
299
 
311
300
  # Backed by the module-level FILTER_BUILDERS dict so existing readers
312
301
  # (e.g. build_filter, _ensure_populated, tests) keep working.
313
- _FILTER_REGISTRY: _IdempotentRegistry[str, Callable[[Dict], Callable[[Dict], bool]]] = (
314
- _IdempotentRegistry("filter_builder", items=FILTER_BUILDERS)
302
+ _FILTER_REGISTRY: _IdempotentRegistry[str, Callable[[Dict], Callable[[Dict], bool]]] = _IdempotentRegistry(
303
+ "filter_builder", items=FILTER_BUILDERS
315
304
  )
316
305
 
317
306
 
@@ -361,9 +350,7 @@ import inspect as _inspect
361
350
 
362
351
  _TriggerPrecheck = Callable[[Dict[str, Any]], Any]
363
352
  _TRIGGER_PRECHECKS: Dict[str, _TriggerPrecheck] = {}
364
- _TRIGGER_PRECHECK_REGISTRY: _IdempotentRegistry[str, _TriggerPrecheck] = (
365
- _IdempotentRegistry("trigger_precheck", items=_TRIGGER_PRECHECKS)
366
- )
353
+ _TRIGGER_PRECHECK_REGISTRY: _IdempotentRegistry[str, _TriggerPrecheck] = _IdempotentRegistry("trigger_precheck", items=_TRIGGER_PRECHECKS)
367
354
 
368
355
 
369
356
  def register_trigger_precheck(node_type: str, fn: _TriggerPrecheck) -> None:
@@ -394,6 +381,7 @@ async def run_trigger_precheck(node_type: str, parameters: Dict) -> Any:
394
381
  # WAITER DATA STRUCTURES
395
382
  # =============================================================================
396
383
 
384
+
397
385
  @dataclass
398
386
  class Waiter:
399
387
  """Single event waiter.
@@ -401,6 +389,7 @@ class Waiter:
401
389
  In memory mode: uses asyncio.Future
402
390
  In Redis mode: uses stream polling with stored metadata
403
391
  """
392
+
404
393
  id: str = field(default_factory=lambda: str(uuid.uuid4()))
405
394
  node_id: str = ""
406
395
  node_type: str = ""
@@ -433,6 +422,7 @@ def _get_stream_name(event_type: str) -> str:
433
422
  # WAITER REGISTRATION
434
423
  # =============================================================================
435
424
 
425
+
436
426
  async def register(node_type: str, node_id: str, params: Dict) -> Waiter:
437
427
  """Register a waiter for a trigger node.
438
428
 
@@ -480,7 +470,7 @@ async def register(node_type: str, node_id: str, params: Dict) -> Waiter:
480
470
  # Create unique consumer group for this waiter
481
471
  # start_id='$' means only new messages from this point forward
482
472
  stream_name = _get_stream_name(config.event_type)
483
- await cache.stream_create_group(stream_name, consumer_group, start_id='$')
473
+ await cache.stream_create_group(stream_name, consumer_group, start_id="$")
484
474
 
485
475
  logger.debug(f"[EventWaiter] Registered {node_type} waiter {waiter.id} (Redis)")
486
476
  else:
@@ -560,9 +550,9 @@ async def _wait_redis(waiter: Waiter, timeout: Optional[float]) -> Dict:
560
550
  result = await cache.stream_read_group(
561
551
  consumer_group, # Each waiter has its own group
562
552
  consumer_name,
563
- {stream_name: '>'}, # '>' = new messages for this consumer
553
+ {stream_name: ">"}, # '>' = new messages for this consumer
564
554
  count=10,
565
- block=block_ms
555
+ block=block_ms,
566
556
  )
567
557
 
568
558
  if not result:
@@ -616,6 +606,7 @@ def _cleanup_waiter(waiter_id: str) -> None:
616
606
  # EVENT DISPATCH
617
607
  # =============================================================================
618
608
 
609
+
619
610
  def _unpack_event(
620
611
  event: "Any",
621
612
  data: Optional[Dict] = None,
@@ -638,10 +629,7 @@ def _unpack_event(
638
629
  return event.type, event.data if isinstance(event.data, dict) else {"data": event.data}
639
630
  if isinstance(event, str):
640
631
  return event, data or {}
641
- raise TypeError(
642
- f"dispatch expects a WorkflowEvent or (event_type: str, data: Dict); "
643
- f"got {type(event).__name__}"
644
- )
632
+ raise TypeError(f"dispatch expects a WorkflowEvent or (event_type: str, data: Dict); " f"got {type(event).__name__}")
645
633
 
646
634
 
647
635
  async def dispatch_async(
@@ -713,14 +701,17 @@ def dispatch(
713
701
  resolved = 0
714
702
  to_remove = []
715
703
 
716
- matching_waiters = [(wid, w) for wid, w in _waiters.items()
717
- if w.event_type == event_type and w.future and not w.future.done()]
704
+ matching_waiters = [(wid, w) for wid, w in _waiters.items() if w.event_type == event_type and w.future and not w.future.done()]
718
705
 
719
706
  if not matching_waiters:
720
707
  logger.debug(f"[EventWaiter] No active waiters for {event_type} (total waiters: {len(_waiters)})")
721
708
  else:
722
- logger.info(f"[EventWaiter] Dispatching {event_type} to {len(matching_waiters)} waiter(s)",
723
- event_type=event_type, from_id=data.get('from_id'), text=str(data.get('text', ''))[:50])
709
+ logger.info(
710
+ f"[EventWaiter] Dispatching {event_type} to {len(matching_waiters)} waiter(s)",
711
+ event_type=event_type,
712
+ from_id=data.get("from_id"),
713
+ text=str(data.get("text", ""))[:50],
714
+ )
724
715
 
725
716
  for wid, w in matching_waiters:
726
717
  try:
@@ -744,6 +735,7 @@ def dispatch(
744
735
  # WAITER CANCELLATION
745
736
  # =============================================================================
746
737
 
738
+
747
739
  def cancel(waiter_id: str) -> bool:
748
740
  """Cancel a waiter by ID."""
749
741
  if w := _waiters.pop(waiter_id, None):
@@ -776,6 +768,7 @@ def cancel_for_node(node_id: str) -> int:
776
768
  # UTILITY FUNCTIONS
777
769
  # =============================================================================
778
770
 
771
+
779
772
  def get_active_waiters() -> List[Dict[str, Any]]:
780
773
  """Get info about active waiters (for debugging/UI)."""
781
774
  return [
@@ -32,6 +32,17 @@ from .verifiers import (
32
32
  GitHubVerifier,
33
33
  )
34
34
 
35
+ # Wave 12 D3: publish the Visibility admin WS handlers into the central
36
+ # WS dispatcher on package import. Even though ``admin_handlers.py`` is
37
+ # framework code (not plugin code), routing it through the same
38
+ # ws_handler_registry keeps the router's dispatch surface uniform —
39
+ # the registry queries don't care whether the caller is plugin or
40
+ # framework.
41
+ from .admin_handlers import WS_HANDLERS as _ADMIN_WS_HANDLERS # noqa: E402
42
+ from services.ws_handler_registry import register_ws_handlers as _register_ws_handlers # noqa: E402
43
+
44
+ _register_ws_handlers(_ADMIN_WS_HANDLERS)
45
+
35
46
  __all__ = [
36
47
  "BaseTriggerParams",
37
48
  "DaemonEventSource",