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
@@ -1,14 +1,15 @@
1
1
  """Telegram Send — Wave 11.C migration.
2
2
 
3
3
  Workflow-only ActionNode (no AI-tool exposure). The Telegram bot
4
- token lives in ``auth_service`` under ``telegram_bot_token``. Plugin
5
- delegates to the legacy ``handle_telegram_send`` handler during
6
- thin-migration; 11.E converts to a declarative ``TelegramCredential``.
4
+ token lives in ``auth_service`` under the ``telegram`` credential id
5
+ (was ``telegram_bot_token`` pre-rename). Plugin delegates to the
6
+ legacy ``handle_telegram_send`` handler during thin-migration; 11.E
7
+ converts to a declarative ``TelegramCredential``.
7
8
  """
8
9
 
9
10
  from __future__ import annotations
10
11
 
11
- from typing import Any, Dict, Literal, Optional
12
+ from typing import Any, Literal, Optional
12
13
 
13
14
  from pydantic import BaseModel, ConfigDict, Field
14
15
 
@@ -116,10 +117,7 @@ class TelegramSendParams(BaseModel):
116
117
  # ===== OPTIONS =====
117
118
  parse_mode: Literal["Auto", "", "HTML", "Markdown", "MarkdownV2"] = Field(
118
119
  default="Auto",
119
- description=(
120
- "Auto converts LLM markdown to Telegram HTML. "
121
- "Empty string = no parse mode (raw text)."
122
- ),
120
+ description=("Auto converts LLM markdown to Telegram HTML. " "Empty string = no parse mode (raw text)."),
123
121
  json_schema_extra={
124
122
  "displayOptions": {"show": {"message_type": ["text", "photo", "document"]}},
125
123
  },
@@ -152,10 +150,8 @@ class TelegramSendNode(ActionNode):
152
150
  description = "Send text, photo, document, location, or contact via Telegram bot"
153
151
  component_kind = "square"
154
152
  handles = (
155
- {"name": "input-main", "kind": "input", "position": "left",
156
- "label": "Input", "role": "main"},
157
- {"name": "output-main", "kind": "output", "position": "right",
158
- "label": "Output", "role": "main"},
153
+ {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
154
+ {"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
159
155
  )
160
156
  annotations = {"destructive": False, "readonly": False, "open_world": True}
161
157
  credentials = (TelegramCredential,)
@@ -183,6 +179,7 @@ class TelegramSendNode(ActionNode):
183
179
  if not chat_id:
184
180
  try:
185
181
  from services.plugin.deps import get_auth_service
182
+
186
183
  saved = await get_auth_service().get_api_key("telegram_owner_chat_id")
187
184
  if saved:
188
185
  owner_id = int(saved)
@@ -216,21 +213,27 @@ class TelegramSendNode(ActionNode):
216
213
  if not params.text:
217
214
  raise RuntimeError("text is required for text message")
218
215
  result = await service.send_message(
219
- text=params.text, parse_mode=parse_mode, **common,
216
+ text=params.text,
217
+ parse_mode=parse_mode,
218
+ **common,
220
219
  )
221
220
  elif mt == "photo":
222
221
  if not params.media_url:
223
222
  raise RuntimeError("media_url is required for photo message")
224
223
  result = await service.send_photo(
225
- photo=params.media_url, caption=params.caption or None,
226
- parse_mode=parse_mode, **common,
224
+ photo=params.media_url,
225
+ caption=params.caption or None,
226
+ parse_mode=parse_mode,
227
+ **common,
227
228
  )
228
229
  elif mt == "document":
229
230
  if not params.media_url:
230
231
  raise RuntimeError("media_url is required for document message")
231
232
  result = await service.send_document(
232
- document=params.media_url, caption=params.caption or None,
233
- parse_mode=parse_mode, **common,
233
+ document=params.media_url,
234
+ caption=params.caption or None,
235
+ parse_mode=parse_mode,
236
+ **common,
234
237
  )
235
238
  elif mt == "location":
236
239
  if params.latitude is None or params.longitude is None:
@@ -257,8 +260,7 @@ class TelegramSendNode(ActionNode):
257
260
  raise RuntimeError(f"Unsupported message type: {mt}")
258
261
 
259
262
  log.info(
260
- f"[Telegram] Message sent: type={mt}, chat={chat_id}, "
261
- f"msg_id={result.get('message_id')}",
263
+ f"[Telegram] Message sent: type={mt}, chat={chat_id}, " f"msg_id={result.get('message_id')}",
262
264
  )
263
265
  return {
264
266
  "message_id": result.get("message_id"),
@@ -17,7 +17,13 @@ from services.plugin import ActionNode, NodeContext, Operation, TaskQueue
17
17
 
18
18
  class FileHandlerParams(BaseModel):
19
19
  file_type: Literal[
20
- "generic", "markdown", "text", "json", "csv", "html", "xml",
20
+ "generic",
21
+ "markdown",
22
+ "text",
23
+ "json",
24
+ "csv",
25
+ "html",
26
+ "xml",
21
27
  ] = Field(
22
28
  default="generic",
23
29
  description="Content type tag used for downstream processing hints.",
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#bd93f9"
3
+ }
@@ -48,7 +48,8 @@ class TextGeneratorNode(ActionNode):
48
48
 
49
49
  text_service = get_text_service()
50
50
  response = await text_service.execute_text_generator(
51
- ctx.node_id, params.model_dump(),
51
+ ctx.node_id,
52
+ params.model_dump(),
52
53
  )
53
54
  if response.get("success"):
54
55
  return response.get("result") or response
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#bd93f9"
3
+ }
@@ -19,10 +19,10 @@ The five operations are pure canvas mutations:
19
19
  * ``create_workflow`` -- persist a fresh empty workflow + return its
20
20
  workflow_id.
21
21
 
22
- Each mutation pushes a ``workflow_ops_apply`` event via
23
- ``status_broadcaster.send_custom_event`` so the live canvas updates.
24
- LangGraph binds tools at graph compile time, so a mutation made
25
- mid-run does NOT add a callable tool to the current run; the
22
+ Each mutation pushes a ``workflow_ops_apply`` event via the plugin's
23
+ ``_events.broadcast_workflow_ops`` wrapper so the live canvas updates.
24
+ The agent loop binds tools at the start of each turn, so a mutation
25
+ made mid-run does NOT add a callable tool to the current turn; the
26
26
  agent's NEXT invocation rediscovers it. Each summary string ends
27
27
  with "Available on your next turn" so the LLM doesn't loop trying
28
28
  to call something that isn't there yet.
@@ -58,7 +58,7 @@ _TOOL_OUTPUT_HANDLE = "output-main"
58
58
  _MASTER_SKILL_TYPE = "masterSkill"
59
59
  _MASTER_SKILL_LABEL = "Master Skill"
60
60
  _AGENT_BUILDER_TYPE = "agentBuilder"
61
- _TEAM_LEAD_TYPES = frozenset({"orchestrator_agent", "ai_employee", "deep_agent"})
61
+ _TEAM_LEAD_TYPES = frozenset({"orchestrator_agent", "ai_employee"})
62
62
  _DENIED_TOOL_TYPES = frozenset({_AGENT_BUILDER_TYPE, _MASTER_SKILL_TYPE})
63
63
  _KEY_PARAM_FIELDS = ("provider", "model", "operation", "url", "query")
64
64
  _SKILLS_DIR = Path(__file__).resolve().parents[2] / "skills"
@@ -70,20 +70,25 @@ _SKILLS_DIR = Path(__file__).resolve().parents[2] / "skills"
70
70
 
71
71
 
72
72
  async def _broadcast(workflow_id: Optional[str], caller_id: str, ops: List[Dict[str, Any]]) -> None:
73
- """Push a workflow_ops_apply event so the live canvas updates."""
73
+ """Push a workflow_ops_apply event so the live canvas updates.
74
+
75
+ Wave 12 B10: routes through plugin _events.py wrapper.
76
+ """
74
77
  if not ops:
75
78
  return
76
79
  try:
77
- from services.status_broadcaster import get_status_broadcaster
78
- broadcaster = get_status_broadcaster()
79
- await broadcaster.send_custom_event(
80
- "workflow_ops_apply",
81
- {"workflow_id": workflow_id, "caller_node_id": caller_id, "operations": ops},
80
+ from ._events import broadcast_workflow_ops
81
+
82
+ await broadcast_workflow_ops(
83
+ workflow_id=workflow_id,
84
+ caller_node_id=caller_id,
85
+ operations=ops,
82
86
  )
83
87
  logger.info(
84
- "[agentBuilder] broadcast workflow_ops_apply: workflow_id=%s "
85
- "caller=%s ops=%s",
86
- workflow_id, caller_id, [op.get("type") for op in ops],
88
+ "[agentBuilder] broadcast workflow_ops_apply: workflow_id=%s " "caller=%s ops=%s",
89
+ workflow_id,
90
+ caller_id,
91
+ [op.get("type") for op in ops],
87
92
  )
88
93
  except Exception as exc:
89
94
  logger.warning(f"[agentBuilder] broadcast failed: {exc}", exc_info=True)
@@ -92,17 +97,14 @@ async def _broadcast(workflow_id: Optional[str], caller_id: str, ops: List[Dict[
92
97
  def _allowed_tool_types() -> set[str]:
93
98
  """Tool nodes the LLM may spawn -- excludes the builder + masterSkill."""
94
99
  return {
95
- ntype for ntype, cls in registered_node_classes().items()
96
- if getattr(cls, "component_kind", "") == "tool"
97
- and ntype not in _DENIED_TOOL_TYPES
100
+ ntype
101
+ for ntype, cls in registered_node_classes().items()
102
+ if getattr(cls, "component_kind", "") == "tool" and ntype not in _DENIED_TOOL_TYPES
98
103
  }
99
104
 
100
105
 
101
106
  def _allowed_subagent_types() -> set[str]:
102
- return {
103
- ntype for ntype, cls in registered_node_classes().items()
104
- if getattr(cls, "component_kind", "") == "agent"
105
- }
107
+ return {ntype for ntype, cls in registered_node_classes().items() if getattr(cls, "component_kind", "") == "agent"}
106
108
 
107
109
 
108
110
  def _is_team_lead(node_type: str) -> bool:
@@ -150,21 +152,20 @@ def _resolve_caller(ctx: NodeContext) -> str:
150
152
  """
151
153
  self_id = ctx.node_id
152
154
  for edge in ctx.edges or []:
153
- if (
154
- edge.get("source") == self_id
155
- and edge.get("targetHandle") == _TOOL_HANDLE
156
- ):
155
+ if edge.get("source") == self_id and edge.get("targetHandle") == _TOOL_HANDLE:
157
156
  target = edge.get("target")
158
157
  if target:
159
158
  logger.info(
160
- "[agentBuilder] caller resolved via input-tools edge: "
161
- "self=%s -> agent=%s", self_id, target,
159
+ "[agentBuilder] caller resolved via input-tools edge: " "self=%s -> agent=%s",
160
+ self_id,
161
+ target,
162
162
  )
163
163
  return target
164
164
  logger.info(
165
- "[agentBuilder] no input-tools edge found from %s; "
166
- "falling back to self as caller (canvas: %d nodes, %d edges)",
167
- self_id, len(ctx.nodes or []), len(ctx.edges or []),
165
+ "[agentBuilder] no input-tools edge found from %s; " "falling back to self as caller (canvas: %d nodes, %d edges)",
166
+ self_id,
167
+ len(ctx.nodes or []),
168
+ len(ctx.edges or []),
168
169
  )
169
170
  return self_id
170
171
 
@@ -179,10 +180,12 @@ def _log_op_entry(op: str, ctx: NodeContext, **fields: Any) -> None:
179
180
  edges = ctx.edges or []
180
181
  extra = " ".join(f"{k}={v!r}" for k, v in fields.items() if v not in (None, ""))
181
182
  logger.info(
182
- "[agentBuilder.%s] workflow_id=%s self=%s nodes=%d edges=%d "
183
- "raw_keys=%s%s",
184
- op, ctx.workflow_id, ctx.node_id,
185
- len(nodes), len(edges),
183
+ "[agentBuilder.%s] workflow_id=%s self=%s nodes=%d edges=%d " "raw_keys=%s%s",
184
+ op,
185
+ ctx.workflow_id,
186
+ ctx.node_id,
187
+ len(nodes),
188
+ len(edges),
186
189
  sorted((ctx.raw or {}).keys()),
187
190
  f" {extra}" if extra else "",
188
191
  )
@@ -227,10 +230,7 @@ class AgentBuilderParams(BaseModel):
227
230
  # add_skill
228
231
  skill_folder: str = Field(
229
232
  default="",
230
- description=(
231
- "For add_skill: skill folder name under server/skills/** "
232
- "(e.g. 'http-request-skill', 'memory-skill')."
233
- ),
233
+ description=("For add_skill: skill folder name under server/skills/** " "(e.g. 'http-request-skill', 'memory-skill')."),
234
234
  json_schema_extra={"displayOptions": {"show": {"operation": ["add_skill"]}}},
235
235
  )
236
236
 
@@ -241,7 +241,7 @@ class AgentBuilderParams(BaseModel):
241
241
  "For add_subagent: agent node type to spawn (e.g. "
242
242
  "'coding_agent', 'web_agent'). Must be component_kind='agent' "
243
243
  "and not a team-lead. Caller must itself be a team-lead "
244
- "(orchestrator_agent / ai_employee / deep_agent)."
244
+ "(orchestrator_agent / ai_employee)."
245
245
  ),
246
246
  json_schema_extra={"displayOptions": {"show": {"operation": ["add_subagent"]}}},
247
247
  )
@@ -296,11 +296,11 @@ class AgentBuilderNode(ToolNode):
296
296
  "agent calls operations through the standard tool path."
297
297
  )
298
298
  component_kind = "tool"
299
+ tool_name = "agent_builder"
300
+ tool_description = "Inspect and modify the workflow canvas at runtime. Operations: inspect_canvas (read current nodes/edges), spawn_tool (add a tool node + wire it), enable_skill (add a skill folder to a connected masterSkill), add_delegate_agent (add a specialized agent), create_workflow (spawn a brand-new workflow)."
299
301
  handles = (
300
- {"name": "input-main", "kind": "input", "position": "left",
301
- "label": "Input", "role": "main"},
302
- {"name": "output-tool", "kind": "output", "position": "top",
303
- "label": "Tool", "role": "tools"},
302
+ {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
303
+ {"name": "output-tool", "kind": "output", "position": "top", "label": "Tool", "role": "tools"},
304
304
  )
305
305
  ui_hints = {"isToolPanel": True, "hideRunButton": True}
306
306
  annotations = {"destructive": False, "readonly": False, "open_world": True}
@@ -313,7 +313,9 @@ class AgentBuilderNode(ToolNode):
313
313
 
314
314
  @Operation("inspect_canvas")
315
315
  async def inspect_canvas(
316
- self, ctx: NodeContext, params: AgentBuilderParams,
316
+ self,
317
+ ctx: NodeContext,
318
+ params: AgentBuilderParams,
317
319
  ) -> AgentBuilderOutput:
318
320
  _log_op_entry("inspect_canvas", ctx)
319
321
  nodes = list(ctx.nodes or [])
@@ -345,7 +347,8 @@ class AgentBuilderNode(ToolNode):
345
347
  "source_type": type_by_id.get(e.get("source")),
346
348
  "target_handle": e.get("targetHandle"),
347
349
  }
348
- for e in edges if e.get("target") == caller_id
350
+ for e in edges
351
+ if e.get("target") == caller_id
349
352
  ]
350
353
  outgoing = [
351
354
  {
@@ -353,7 +356,8 @@ class AgentBuilderNode(ToolNode):
353
356
  "target_type": type_by_id.get(e.get("target")),
354
357
  "source_handle": e.get("sourceHandle"),
355
358
  }
356
- for e in edges if e.get("source") == caller_id
359
+ for e in edges
360
+ if e.get("source") == caller_id
357
361
  ]
358
362
 
359
363
  tools = [c for c in incoming if c["target_handle"] == _TOOL_HANDLE]
@@ -380,7 +384,9 @@ class AgentBuilderNode(ToolNode):
380
384
 
381
385
  @Operation("add_tool")
382
386
  async def add_tool(
383
- self, ctx: NodeContext, params: AgentBuilderParams,
387
+ self,
388
+ ctx: NodeContext,
389
+ params: AgentBuilderParams,
384
390
  ) -> AgentBuilderOutput:
385
391
  _log_op_entry("add_tool", ctx, node_type=params.node_type)
386
392
  node_type = (params.node_type or "").strip()
@@ -395,10 +401,7 @@ class AgentBuilderNode(ToolNode):
395
401
  sample = ", ".join(sorted(allowed)[:10])
396
402
  return AgentBuilderOutput(
397
403
  operation="add_tool",
398
- summary=(
399
- f"add_tool: '{node_type}' is not an allowed tool type. "
400
- f"Examples of allowed types: {sample}..."
401
- ),
404
+ summary=(f"add_tool: '{node_type}' is not an allowed tool type. " f"Examples of allowed types: {sample}..."),
402
405
  operations=[],
403
406
  )
404
407
 
@@ -406,13 +409,17 @@ class AgentBuilderNode(ToolNode):
406
409
  client_ref = f"new_{node_type}"
407
410
  ops = [
408
411
  workflow_ops.add_node(
409
- client_ref, node_type, {},
412
+ client_ref,
413
+ node_type,
414
+ {},
410
415
  label=node_type,
411
416
  position=workflow_ops.anchored(caller_id, offset_x=200, offset_y=80),
412
417
  ),
413
418
  workflow_ops.add_edge(
414
- {"client_ref": client_ref}, caller_id,
415
- source_handle=_TOOL_OUTPUT_HANDLE, target_handle=_TOOL_HANDLE,
419
+ {"client_ref": client_ref},
420
+ caller_id,
421
+ source_handle=_TOOL_OUTPUT_HANDLE,
422
+ target_handle=_TOOL_HANDLE,
416
423
  ),
417
424
  ]
418
425
  await _broadcast(ctx.workflow_id, caller_id, ops)
@@ -426,7 +433,9 @@ class AgentBuilderNode(ToolNode):
426
433
 
427
434
  @Operation("add_skill")
428
435
  async def add_skill(
429
- self, ctx: NodeContext, params: AgentBuilderParams,
436
+ self,
437
+ ctx: NodeContext,
438
+ params: AgentBuilderParams,
430
439
  ) -> AgentBuilderOutput:
431
440
  _log_op_entry("add_skill", ctx, skill_folder=params.skill_folder)
432
441
  skill = (params.skill_folder or "").strip()
@@ -448,27 +457,25 @@ class AgentBuilderNode(ToolNode):
448
457
  caller_id = _resolve_caller(ctx)
449
458
 
450
459
  skill_edge = next(
451
- (e for e in edges if e.get("target") == caller_id
452
- and e.get("targetHandle") == _SKILL_HANDLE),
460
+ (e for e in edges if e.get("target") == caller_id and e.get("targetHandle") == _SKILL_HANDLE),
453
461
  None,
454
462
  )
455
463
  master_skill = None
456
464
  if skill_edge:
457
465
  master_skill = next(
458
- (n for n in nodes if n.get("id") == skill_edge.get("source")
459
- and n.get("type") == _MASTER_SKILL_TYPE),
466
+ (n for n in nodes if n.get("id") == skill_edge.get("source") and n.get("type") == _MASTER_SKILL_TYPE),
460
467
  None,
461
468
  )
462
469
 
463
470
  if master_skill:
464
- existing = (
465
- ((master_skill.get("data") or {}).get("parameters") or {})
466
- .get("skills_config") or {}
467
- )
471
+ existing = ((master_skill.get("data") or {}).get("parameters") or {}).get("skills_config") or {}
468
472
  new_config = _toggle_skill(existing, skill, True)
469
- ops = [workflow_ops.set_node_parameters(
470
- master_skill["id"], {"skills_config": new_config},
471
- )]
473
+ ops = [
474
+ workflow_ops.set_node_parameters(
475
+ master_skill["id"],
476
+ {"skills_config": new_config},
477
+ )
478
+ ]
472
479
  await _broadcast(ctx.workflow_id, caller_id, ops)
473
480
  return AgentBuilderOutput(
474
481
  operation="add_skill",
@@ -480,23 +487,23 @@ class AgentBuilderNode(ToolNode):
480
487
  client_ref = "new_master_skill"
481
488
  ops = [
482
489
  workflow_ops.add_node(
483
- client_ref, _MASTER_SKILL_TYPE,
490
+ client_ref,
491
+ _MASTER_SKILL_TYPE,
484
492
  {"skills_config": new_config},
485
493
  label=_MASTER_SKILL_LABEL,
486
494
  position=workflow_ops.anchored(caller_id, offset_x=-60, offset_y=220),
487
495
  ),
488
496
  workflow_ops.add_edge(
489
- {"client_ref": client_ref}, caller_id,
490
- source_handle=_SKILL_OUTPUT_HANDLE, target_handle=_SKILL_HANDLE,
497
+ {"client_ref": client_ref},
498
+ caller_id,
499
+ source_handle=_SKILL_OUTPUT_HANDLE,
500
+ target_handle=_SKILL_HANDLE,
491
501
  ),
492
502
  ]
493
503
  await _broadcast(ctx.workflow_id, caller_id, ops)
494
504
  return AgentBuilderOutput(
495
505
  operation="add_skill",
496
- summary=(
497
- f"Created Master Skill node and enabled '{skill}'. "
498
- "Available on your next turn."
499
- ),
506
+ summary=(f"Created Master Skill node and enabled '{skill}'. " "Available on your next turn."),
500
507
  operations=ops,
501
508
  )
502
509
 
@@ -504,7 +511,9 @@ class AgentBuilderNode(ToolNode):
504
511
 
505
512
  @Operation("add_subagent")
506
513
  async def add_subagent(
507
- self, ctx: NodeContext, params: AgentBuilderParams,
514
+ self,
515
+ ctx: NodeContext,
516
+ params: AgentBuilderParams,
508
517
  ) -> AgentBuilderOutput:
509
518
  _log_op_entry("add_subagent", ctx, agent_type=params.agent_type)
510
519
  agent_type = (params.agent_type or "").strip()
@@ -524,10 +533,7 @@ class AgentBuilderNode(ToolNode):
524
533
  leads = ", ".join(sorted(_TEAM_LEAD_TYPES))
525
534
  return AgentBuilderOutput(
526
535
  operation="add_subagent",
527
- summary=(
528
- f"add_subagent: only team-lead agents ({leads}) can spawn "
529
- f"delegates. This agent is '{caller_type}'."
530
- ),
536
+ summary=(f"add_subagent: only team-lead agents ({leads}) can spawn " f"delegates. This agent is '{caller_type}'."),
531
537
  operations=[],
532
538
  )
533
539
  allowed = _allowed_subagent_types()
@@ -535,41 +541,36 @@ class AgentBuilderNode(ToolNode):
535
541
  sample = ", ".join(sorted(allowed)[:10])
536
542
  return AgentBuilderOutput(
537
543
  operation="add_subagent",
538
- summary=(
539
- f"add_subagent: '{agent_type}' is not an allowed agent "
540
- f"type. Examples: {sample}..."
541
- ),
544
+ summary=(f"add_subagent: '{agent_type}' is not an allowed agent " f"type. Examples: {sample}..."),
542
545
  operations=[],
543
546
  )
544
547
  if _is_team_lead(agent_type):
545
548
  return AgentBuilderOutput(
546
549
  operation="add_subagent",
547
- summary=(
548
- f"add_subagent: cannot spawn another team-lead "
549
- f"('{agent_type}'); pick a specialized agent instead."
550
- ),
550
+ summary=(f"add_subagent: cannot spawn another team-lead " f"('{agent_type}'); pick a specialized agent instead."),
551
551
  operations=[],
552
552
  )
553
553
 
554
554
  client_ref = f"new_{agent_type}"
555
555
  ops = [
556
556
  workflow_ops.add_node(
557
- client_ref, agent_type, {},
557
+ client_ref,
558
+ agent_type,
559
+ {},
558
560
  label=agent_type,
559
561
  position=workflow_ops.anchored(caller_id, offset_x=300, offset_y=200),
560
562
  ),
561
563
  workflow_ops.add_edge(
562
- {"client_ref": client_ref}, caller_id,
563
- source_handle=_TEAMMATES_OUTPUT_HANDLE, target_handle=_TEAMMATES_HANDLE,
564
+ {"client_ref": client_ref},
565
+ caller_id,
566
+ source_handle=_TEAMMATES_OUTPUT_HANDLE,
567
+ target_handle=_TEAMMATES_HANDLE,
564
568
  ),
565
569
  ]
566
570
  await _broadcast(ctx.workflow_id, caller_id, ops)
567
571
  return AgentBuilderOutput(
568
572
  operation="add_subagent",
569
- summary=(
570
- f"Added '{agent_type}' as a teammate. Available on your "
571
- "next turn (configure provider/model first)."
572
- ),
573
+ summary=(f"Added '{agent_type}' as a teammate. Available on your " "next turn (configure provider/model first)."),
573
574
  operations=ops,
574
575
  )
575
576
 
@@ -577,10 +578,13 @@ class AgentBuilderNode(ToolNode):
577
578
 
578
579
  @Operation("create_workflow")
579
580
  async def create_workflow(
580
- self, ctx: NodeContext, params: AgentBuilderParams,
581
+ self,
582
+ ctx: NodeContext,
583
+ params: AgentBuilderParams,
581
584
  ) -> AgentBuilderOutput:
582
585
  _log_op_entry(
583
- "create_workflow", ctx,
586
+ "create_workflow",
587
+ ctx,
584
588
  workflow_name=params.workflow_name,
585
589
  workflow_description=params.workflow_description,
586
590
  )
@@ -611,9 +615,13 @@ class AgentBuilderNode(ToolNode):
611
615
  }
612
616
 
613
617
  from services.plugin.deps import get_database
618
+
614
619
  database = get_database()
615
620
  ok = await database.save_workflow(
616
- workflow_id, name, workflow_data, description=description or None,
621
+ workflow_id,
622
+ name,
623
+ workflow_data,
624
+ description=description or None,
617
625
  )
618
626
  if not ok:
619
627
  return AgentBuilderOutput(
@@ -622,9 +630,6 @@ class AgentBuilderNode(ToolNode):
622
630
  )
623
631
  return AgentBuilderOutput(
624
632
  operation="create_workflow",
625
- summary=(
626
- f"Created workflow '{name}' (id: {workflow_id}). "
627
- "User can switch to it from the toast notification."
628
- ),
633
+ summary=(f"Created workflow '{name}' (id: {workflow_id}). " "User can switch to it from the toast notification."),
629
634
  workflow_id=workflow_id,
630
635
  )
@@ -0,0 +1,91 @@
1
+ """CloudEvents factory + broadcaster wrapper for agent_builder.
2
+
3
+ Per RFC plugin_authoring_rfc.md §6.4: plugin-specific factories live in
4
+ the plugin folder.
5
+
6
+ This is NOT a trigger event — it's a canvas-mutation broadcast consumed
7
+ by the frontend's ``useWorkflowOpsListener`` hook. The wire format is
8
+ flat (``{workflow_id, caller_node_id, operations}``) for FE back-compat;
9
+ the typed envelope is constructed for parity with the other plugin
10
+ ``_events.py`` modules but not consumed today.
11
+
12
+ Delivery: direct WS broadcast (no ``dispatch.emit`` — no
13
+ :class:`TriggerListenerWorkflow` consumer exists for canvas mutations,
14
+ and no legacy ``event_waiter`` waiter listens on ``workflow_ops_apply``
15
+ either). Pre-Wave-13 this routed through ``send_custom_event`` which
16
+ also called ``event_waiter.dispatch_async`` — that dispatch was dead.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from typing import Any, Dict, List, Optional
22
+
23
+ from services.events.envelope import WorkflowEvent
24
+
25
+
26
+ # Flat wire-routing key consumed by ``client/src/hooks/useWorkflowOpsListener``.
27
+ _WIRE_ROUTING_KEY = "workflow_ops_apply"
28
+
29
+
30
+ def workflow_ops_applied(
31
+ *,
32
+ workflow_id: Optional[str],
33
+ caller_node_id: str,
34
+ operations: List[Dict[str, Any]],
35
+ ) -> WorkflowEvent:
36
+ """Canvas-mutation envelope. ``subject`` is the caller node id so
37
+ consumers can route per-builder."""
38
+ return WorkflowEvent(
39
+ source="machinaos://nodes/agent_builder",
40
+ type="com.machinaos.workflow.ops.applied",
41
+ subject=caller_node_id,
42
+ workflow_id=workflow_id,
43
+ data={
44
+ "workflow_id": workflow_id,
45
+ "caller_node_id": caller_node_id,
46
+ "operations": list(operations),
47
+ },
48
+ )
49
+
50
+
51
+ async def broadcast_workflow_ops(
52
+ *,
53
+ workflow_id: Optional[str],
54
+ caller_node_id: str,
55
+ operations: List[Dict[str, Any]],
56
+ ) -> None:
57
+ """Broadcast a canvas-mutation event for the FE to apply.
58
+
59
+ Flat payload (FE back-compat with ``useWorkflowOpsListener``); the
60
+ typed envelope is constructed for audit/future migration but not
61
+ on the wire today.
62
+ """
63
+ if not operations:
64
+ return
65
+ from services.status_broadcaster import get_status_broadcaster
66
+
67
+ broadcaster = get_status_broadcaster()
68
+ payload = {
69
+ "workflow_id": workflow_id,
70
+ "caller_node_id": caller_node_id,
71
+ "operations": list(operations),
72
+ }
73
+ # Envelope constructed for parity / future migration; not on the
74
+ # wire today because FE listener reads the flat shape.
75
+ _ = workflow_ops_applied(
76
+ workflow_id=workflow_id,
77
+ caller_node_id=caller_node_id,
78
+ operations=operations,
79
+ )
80
+ await broadcaster.broadcast(
81
+ {
82
+ "type": _WIRE_ROUTING_KEY,
83
+ "data": payload,
84
+ }
85
+ )
86
+
87
+
88
+ __all__ = [
89
+ "broadcast_workflow_ops",
90
+ "workflow_ops_applied",
91
+ ]
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#ffb86c"
3
+ }