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,25 +1,36 @@
1
1
  """Central handler for node visuals (icon + color).
2
2
 
3
- Every node plugin's icon and color live in ``visuals.json`` next to
4
- this module. The base ``BaseNode`` class consults
5
- :func:`get_icon` / :func:`get_color` at registration time when a
6
- subclass doesn't set the class attribute itself.
7
-
8
- Single source of truth — change the icon for ``aiAgent`` here once
9
- and every consumer (palette, parameter panel, canvas) picks it up
10
- the next time the backend NodeSpec cache rehydrates.
11
-
12
- Adding a new node: add an entry to ``visuals.json`` (or rely on the
13
- empty default — the icon resolver falls back to the empty string,
14
- which the frontend renders as a placeholder). Node files do NOT
15
- declare ``icon`` or ``color`` themselves.
3
+ Two icon sources co-exist by design (per RFC §6.5):
4
+
5
+ 1. **Per-plugin ``icon.svg``** co-located with the plugin folder
6
+ (e.g. ``server/nodes/telegram/icon.svg``). Resolved at runtime via
7
+ :func:`get_plugin_icon_path`. Preferred for new plugins; served
8
+ by ``GET /api/schemas/nodes/{type}/icon`` (see ``routers/schemas.py``).
9
+
10
+ 2. **``visuals.json``** for emoji entries and library-icon
11
+ (``lobehub:<brand>``) entries that don't map to a file. Resolved
12
+ via :func:`get_icon` / :func:`get_color`.
13
+
14
+ ``BaseNode._metadata_dict`` checks the per-folder path first and
15
+ falls back to ``visuals.json``. The frontend resolver dispatches by
16
+ the wire-format prefix (URL paths route to ``<img>``; ``asset:``,
17
+ ``lobehub:``, emoji each have their own branch).
18
+
19
+ Adding a new node:
20
+ - Drop ``icon.svg`` into the plugin folder, OR
21
+ - Add an entry to ``visuals.json`` (emoji or ``lobehub:<brand>``).
22
+
23
+ Node files do NOT declare ``icon`` or ``color`` themselves.
16
24
  """
17
25
 
18
26
  from __future__ import annotations
19
27
 
28
+ import inspect
20
29
  import json
21
30
  from pathlib import Path
22
- from typing import Dict
31
+ from typing import Dict, Optional
32
+
33
+ from services.plugin.identifiers import is_valid_node_type
23
34
 
24
35
 
25
36
  _VISUALS_PATH = Path(__file__).resolve().parent / "visuals.json"
@@ -59,6 +70,10 @@ def get_color(node_type: str) -> str:
59
70
 
60
71
  Color strings are arbitrary CSS color literals — the canvas node
61
72
  components apply them as-is to gradients, borders, and badges.
73
+
74
+ Falls back to ``visuals.json`` for legacy entries that haven't been
75
+ migrated to per-plugin ``meta.json`` yet (F2 cleanup of the plugin
76
+ authoring RFC).
62
77
  """
63
78
  entry = _VISUALS.get(node_type)
64
79
  if not entry:
@@ -66,6 +81,123 @@ def get_color(node_type: str) -> str:
66
81
  return str(entry.get("color", ""))
67
82
 
68
83
 
84
+ def get_plugin_meta(node_type: str, key: Optional[str] = None) -> Optional[dict | str]:
85
+ """Read the plugin's co-located ``meta.json`` file.
86
+
87
+ Same folder-resolution path as :func:`get_plugin_icon_path` — uses
88
+ :func:`inspect.getfile` on the plugin class to locate the folder,
89
+ then loads ``meta.json`` if present.
90
+
91
+ Returns the value at ``key`` (str) when given, the whole dict when
92
+ ``key`` is ``None``, or ``None`` when the file or key is absent.
93
+ Callers fall back to :func:`get_color` / other ``visuals.json`` keys
94
+ for legacy entries.
95
+
96
+ Per RFC §6.2 / F2 of the deferred follow-ups: ``meta.json`` mirrors
97
+ ``icon.svg`` co-location so a plugin's entire visual surface area
98
+ lives in one folder. The previous central ``visuals.json`` color
99
+ map remains as a transitional fallback for entries without a
100
+ per-plugin ``meta.json``.
101
+ """
102
+ from services.node_registry import get_node_class
103
+
104
+ if not is_valid_node_type(node_type):
105
+ return None
106
+ cls = get_node_class(node_type)
107
+ if cls is None:
108
+ return None
109
+ try:
110
+ plugin_dir = Path(inspect.getfile(cls)).resolve().parent
111
+ except (TypeError, OSError):
112
+ return None
113
+ meta_path = plugin_dir / "meta.json"
114
+ if not meta_path.exists():
115
+ return None
116
+ try:
117
+ with meta_path.open("r", encoding="utf-8") as fh:
118
+ data = json.load(fh)
119
+ except (OSError, json.JSONDecodeError):
120
+ return None
121
+ if not isinstance(data, dict):
122
+ return None
123
+ if key is None:
124
+ return data
125
+ value = data.get(key)
126
+ return None if value is None else str(value)
127
+
128
+
129
+ def get_plugin_icon_path(node_type: str, variant: str = "light") -> Optional[Path]:
130
+ """Return the on-disk path to a plugin's co-located icon SVG.
131
+
132
+ ``variant="dark"`` looks for the dark-mode SVG first and falls back
133
+ to the light variant when no dark file exists.
134
+
135
+ Resolution chain (first hit wins):
136
+ 1. **Per-node-type icon** — ``<plugin_dir>/icon_<node_type>.svg``
137
+ (or ``icon_<node_type>.dark.svg`` for ``variant="dark"``).
138
+ Lets multi-node-per-plugin folders (whatsapp / telegram / stripe)
139
+ serve distinct icons per node type WITHOUT splitting the folder.
140
+ e.g. ``server/nodes/whatsapp/icon_whatsappSend.svg`` serves the
141
+ ``whatsappSend`` node while sharing the folder with
142
+ ``whatsappReceive`` and ``whatsappDb``.
143
+ 2. **Shared plugin icon** — ``<plugin_dir>/icon.svg`` (or
144
+ ``icon.dark.svg``). The original Phase 9 contract; one icon for
145
+ the whole folder.
146
+
147
+ Folder resolution itself:
148
+ 1. Look up the plugin class via :func:`services.node_registry.get_node_class`.
149
+ 2. Resolve the class's source file via ``inspect.getfile``.
150
+ 3. The plugin folder is the file's parent directory — equally
151
+ correct for single-file plugins (``server/nodes/tool/calc.py``
152
+ → parent ``server/nodes/tool/``) and self-contained-folder
153
+ plugins (``server/nodes/telegram/telegram_send.py`` → parent
154
+ ``server/nodes/telegram/``).
155
+
156
+ Returns ``None`` when the type is unknown or no icon SVG is
157
+ present — caller falls back to :func:`get_icon` (visuals.json).
158
+ """
159
+ # Local import to avoid a top-level circular dep (node_registry
160
+ # itself doesn't import _visuals, but plugin modules import both).
161
+ from services.node_registry import get_node_class
162
+
163
+ if not is_valid_node_type(node_type):
164
+ return None
165
+ cls = get_node_class(node_type)
166
+ if cls is None:
167
+ return None
168
+ try:
169
+ plugin_dir = Path(inspect.getfile(cls)).resolve().parent
170
+ except (TypeError, OSError):
171
+ return None
172
+
173
+ # Candidate filenames in resolution order. Per-node-type first so
174
+ # multi-node folders can override the shared icon for specific node
175
+ # types. ``node_type`` is already constrained to ``NODE_TYPE_PATTERN``
176
+ # (``^[A-Za-z_][A-Za-z0-9_]*$``) by ``is_valid_node_type`` above --
177
+ # no path separators possible -- but we resolve the candidate and
178
+ # call ``Path.relative_to(plugin_dir)`` (which raises ``ValueError``
179
+ # on traversal). CodeQL's taint tracker recognises
180
+ # ``Path.relative_to`` as a ``py/path-injection`` sanitizer; the
181
+ # ``is_relative_to`` predicate it does not.
182
+ candidates: list[str] = []
183
+ if variant == "dark":
184
+ candidates.append(f"icon_{node_type}.dark.svg")
185
+ candidates.append(f"icon_{node_type}.svg")
186
+ if variant == "dark":
187
+ candidates.append("icon.dark.svg")
188
+ candidates.append("icon.svg")
189
+
190
+ for name in candidates:
191
+ candidate = (plugin_dir / name).resolve()
192
+ try:
193
+ candidate.relative_to(plugin_dir)
194
+ except ValueError:
195
+ continue
196
+ if candidate.exists():
197
+ return candidate
198
+ return None
199
+
200
+
69
201
  def get_skill(node_type: str) -> str:
70
202
  """Return the teaching skill folder name registered for ``node_type``.
71
203
 
@@ -0,0 +1,124 @@
1
+ """CloudEvents broadcaster wrappers for agent task delegation.
2
+
3
+ Plugin-folder-owned wrappers around the cross-cutting
4
+ ``WorkflowEvent.task_completed`` factory. The factory itself stays in
5
+ ``services/events/envelope.py`` per RFC §6.4 — it's parametrised by
6
+ ``task_id`` + ``agent`` + ``status`` and uniformly applies to every
7
+ delegated agent task, not a single-plugin shape. The broadcaster
8
+ wrappers below live with the agent plugin folder so the 3 callsites in
9
+ ``services/handlers/tools.py`` (the fire-and-forget delegation
10
+ dispatcher) import from ``nodes.agent._events`` rather than building
11
+ the wire frame inline.
12
+
13
+ Delivery: a single ``dispatch.emit`` call. ``dispatch.emit`` Signals
14
+ running :class:`TriggerListenerWorkflow` consumers via Temporal
15
+ Visibility AND broadcasts the same envelope to in-process WS clients on
16
+ the ``task_completed`` wire-routing key — one canonical path. Pre-Wave-13
17
+ this also called ``broadcaster.send_custom_event`` for the legacy
18
+ collector path; that's dead since taskTrigger is canary-registered and
19
+ the deployment manager skips ``setup_event_trigger`` for canary types.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from typing import Any, Optional
25
+
26
+
27
+ # Outer wire-routing key. FE consumers (if any) and the legacy
28
+ # back-compat receipt path still switch on this string; the inner
29
+ # envelope carries ``com.machinaos.agent.task.completed``.
30
+ _WIRE_ROUTING_KEY = "task_completed"
31
+
32
+
33
+ async def broadcast_agent_task_completed(
34
+ *,
35
+ task_id: str,
36
+ agent_name: str,
37
+ agent_node_id: str,
38
+ parent_node_id: str,
39
+ workflow_id: Optional[str] = None,
40
+ result: Optional[str] = None,
41
+ ) -> None:
42
+ """Broadcast a delegated agent task completing successfully."""
43
+ await _broadcast_task_event(
44
+ task_id=task_id,
45
+ status="completed",
46
+ agent_name=agent_name,
47
+ agent_node_id=agent_node_id,
48
+ parent_node_id=parent_node_id,
49
+ workflow_id=workflow_id,
50
+ result=result,
51
+ )
52
+
53
+
54
+ async def broadcast_agent_task_failed(
55
+ *,
56
+ task_id: str,
57
+ agent_name: str,
58
+ agent_node_id: str,
59
+ parent_node_id: str,
60
+ workflow_id: Optional[str] = None,
61
+ error: str,
62
+ ) -> None:
63
+ """Broadcast a delegated agent task failing."""
64
+ await _broadcast_task_event(
65
+ task_id=task_id,
66
+ status="error",
67
+ agent_name=agent_name,
68
+ agent_node_id=agent_node_id,
69
+ parent_node_id=parent_node_id,
70
+ workflow_id=workflow_id,
71
+ error=error,
72
+ )
73
+
74
+
75
+ async def _broadcast_task_event(
76
+ *,
77
+ task_id: str,
78
+ status: str, # "completed" | "error"
79
+ agent_name: str,
80
+ agent_node_id: str,
81
+ parent_node_id: str,
82
+ workflow_id: Optional[str] = None,
83
+ result: Optional[str] = None,
84
+ error: Optional[str] = None,
85
+ ) -> None:
86
+ """Single delivery path: build the envelope, route through
87
+ :func:`services.events.dispatch.emit`.
88
+
89
+ ``emit`` does two things in one call: (a) Visibility query for
90
+ running :class:`TriggerListenerWorkflow` consumers tagged with
91
+ ``EventType='com.machinaos.agent.task.completed'`` and signals each;
92
+ (b) direct in-process WS broadcast on the ``task_completed`` wire
93
+ key so any FE consumers receive the envelope. Payload shape in
94
+ ``data`` is exactly what the taskTrigger filter reads.
95
+ """
96
+ from services.events.dispatch import emit
97
+ from services.events.envelope import WorkflowEvent
98
+
99
+ payload: dict[str, Any] = {
100
+ "task_id": task_id,
101
+ "status": status,
102
+ "agent_name": agent_name,
103
+ "agent_node_id": agent_node_id,
104
+ "parent_node_id": parent_node_id,
105
+ "workflow_id": workflow_id,
106
+ }
107
+ if status == "completed" and result is not None:
108
+ payload["result"] = result
109
+ elif status == "error" and error is not None:
110
+ payload["error"] = error
111
+
112
+ envelope = WorkflowEvent.task_completed(
113
+ task_id=task_id,
114
+ status="completed" if status == "completed" else "error",
115
+ agent=agent_name,
116
+ data=payload,
117
+ )
118
+ await emit(envelope, wire_routing_key=_WIRE_ROUTING_KEY)
119
+
120
+
121
+ __all__ = [
122
+ "broadcast_agent_task_completed",
123
+ "broadcast_agent_task_failed",
124
+ ]
@@ -16,13 +16,13 @@ def std_agent_handles() -> tuple:
16
16
  of the 20 agent variants. Returned as a tuple so the BaseNode
17
17
  `handles` class attribute is immutable."""
18
18
  return (
19
- {"name": "input-skill", "kind": "input", "position": "bottom", "offset": "25%", "label": "Skill", "role": "skill"},
20
- {"name": "input-tools", "kind": "input", "position": "bottom", "offset": "75%", "label": "Tool", "role": "tools"},
21
- {"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
22
- {"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory", "role": "memory"},
23
- {"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
24
- {"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output", "role": "main"},
25
- {"name": "output-top", "kind": "output", "position": "top", "label": "Output", "role": "main"},
19
+ {"name": "input-skill", "kind": "input", "position": "bottom", "offset": "25%", "label": "Skill", "role": "skill"},
20
+ {"name": "input-tools", "kind": "input", "position": "bottom", "offset": "75%", "label": "Tool", "role": "tools"},
21
+ {"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
22
+ {"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory", "role": "memory"},
23
+ {"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
24
+ {"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output", "role": "main"},
25
+ {"name": "output-top", "kind": "output", "position": "top", "label": "Output", "role": "main"},
26
26
  )
27
27
 
28
28
 
@@ -30,26 +30,12 @@ def team_lead_agent_handles() -> tuple:
30
30
  """Skill / Tool / Teammates bottom + Memory/Task/Input left + Outputs.
31
31
  Used by orchestrator_agent and ai_employee."""
32
32
  return (
33
- {"name": "input-skill", "kind": "input", "position": "bottom", "offset": "20%", "label": "Skill", "role": "skill"},
34
- {"name": "input-tools", "kind": "input", "position": "bottom", "offset": "50%", "label": "Tool", "role": "tools"},
35
- {"name": "input-teammates", "kind": "input", "position": "bottom", "offset": "80%", "label": "Team", "role": "teammates"},
36
- {"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
37
- {"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory","role": "memory"},
38
- {"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
39
- {"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output","role": "main"},
40
- {"name": "output-top", "kind": "output", "position": "top", "label": "Output","role": "main"},
41
- )
42
-
43
-
44
- def deep_agent_handles() -> tuple:
45
- """Skill / Teammates / Tool bottom — used by deep_agent only."""
46
- return (
47
- {"name": "input-skill", "kind": "input", "position": "bottom", "offset": "30%", "label": "Skill", "role": "skill"},
48
- {"name": "input-teammates", "kind": "input", "position": "bottom", "offset": "55%", "label": "Team", "role": "teammates"},
49
- {"name": "input-tools", "kind": "input", "position": "bottom", "offset": "80%", "label": "Tool", "role": "tools"},
50
- {"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
51
- {"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory","role": "memory"},
52
- {"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
53
- {"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output","role": "main"},
54
- {"name": "output-top", "kind": "output", "position": "top", "label": "Output","role": "main"},
33
+ {"name": "input-skill", "kind": "input", "position": "bottom", "offset": "20%", "label": "Skill", "role": "skill"},
34
+ {"name": "input-tools", "kind": "input", "position": "bottom", "offset": "50%", "label": "Tool", "role": "tools"},
35
+ {"name": "input-teammates", "kind": "input", "position": "bottom", "offset": "80%", "label": "Team", "role": "teammates"},
36
+ {"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
37
+ {"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory", "role": "memory"},
38
+ {"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
39
+ {"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output", "role": "main"},
40
+ {"name": "output-top", "kind": "output", "position": "top", "label": "Output", "role": "main"},
55
41
  )
@@ -22,7 +22,7 @@ to ``ai_service.execute_agent(...)`` or ``ai_service.execute_chat_agent(...)``.
22
22
 
23
23
  from __future__ import annotations
24
24
 
25
- from typing import Any, Dict, Optional
25
+ from typing import Any, Dict
26
26
 
27
27
  from core.logging import get_logger
28
28
  from services.plugin.edge_walker import (
@@ -60,7 +60,10 @@ async def prepare_agent_call(
60
60
  parameters = {**parameters, "api_key": raw_params["api_key"]}
61
61
 
62
62
  memory_data, skill_data, tool_data, input_data, task_data = await collect_agent_connections(
63
- node_id, context, database, log_prefix=log_prefix,
63
+ node_id,
64
+ context,
65
+ database,
66
+ log_prefix=log_prefix,
64
67
  )
65
68
 
66
69
  # Step 1: task-context injection + tool-strip.
@@ -76,8 +79,7 @@ async def prepare_agent_call(
76
79
  original_tool_count = len(tool_data)
77
80
  tool_data = []
78
81
  logger.info(
79
- f"{log_prefix} Stripped ALL {original_tool_count} tools for "
80
- "task completion handling",
82
+ f"{log_prefix} Stripped ALL {original_tool_count} tools for " "task completion handling",
81
83
  )
82
84
 
83
85
  # Step 2: auto-prompt fallback.
@@ -113,31 +115,34 @@ async def prepare_agent_call(
113
115
  tm_id = tm["node_id"]
114
116
  child_tools = []
115
117
  for child_edge in all_edges:
116
- if (
117
- child_edge.get("target") != tm_id
118
- or child_edge.get("targetHandle") != "input-tools"
119
- ):
118
+ if child_edge.get("target") != tm_id or child_edge.get("targetHandle") != "input-tools":
120
119
  continue
121
120
  child_id = child_edge.get("source")
122
121
  child_node = next(
123
- (n for n in all_nodes if n.get("id") == child_id), None,
122
+ (n for n in all_nodes if n.get("id") == child_id),
123
+ None,
124
124
  )
125
125
  if not child_node:
126
126
  continue
127
- child_tools.append({
128
- "node_id": child_id,
129
- "node_type": child_node.get("type"),
130
- "label": child_node.get("data", {}).get(
131
- "label", child_node.get("type"),
132
- ),
133
- })
134
- tool_data.append({
135
- "node_id": tm_id,
136
- "node_type": tm["node_type"],
137
- "label": tm["label"],
138
- "parameters": tm.get("parameters", {}),
139
- "child_tools": child_tools,
140
- })
127
+ child_tools.append(
128
+ {
129
+ "node_id": child_id,
130
+ "node_type": child_node.get("type"),
131
+ "label": child_node.get("data", {}).get(
132
+ "label",
133
+ child_node.get("type"),
134
+ ),
135
+ }
136
+ )
137
+ tool_data.append(
138
+ {
139
+ "node_id": tm_id,
140
+ "node_type": tm["node_type"],
141
+ "label": tm["label"],
142
+ "parameters": tm.get("parameters", {}),
143
+ "child_tools": child_tools,
144
+ }
145
+ )
141
146
  logger.info(f"[Teams] Added {len(teammates)} teammates as delegation tools")
142
147
 
143
148
  from services.status_broadcaster import get_status_broadcaster
@@ -152,5 +157,3 @@ async def prepare_agent_call(
152
157
  "context": context,
153
158
  "database": database,
154
159
  }
155
-
156
-
@@ -1,12 +1,12 @@
1
1
  """Specialized agent base — subclass + set 5 attrs to mint a new agent.
2
2
 
3
- 13 specialized agents (android / coding / web / task / social / travel
4
- / tool / productivity / payments / consumer / autonomous / rlm /
5
- claude_code) all share the LangGraph-via-handle_chat_agent execution
6
- path. The only differences are display name, icon, colour, subtitle,
7
- description. Each agent gets its own file under ``nodes/agent/`` so
8
- the user can find ``android_agent.py`` directly but the body lives
9
- here so changing the dispatch path is a one-file edit.
3
+ All specialized agents (android / coding / web / task / social / travel
4
+ / tool / productivity / payments / consumer / autonomous) share the
5
+ ``handle_chat_agent`` execution path. The only differences are display
6
+ name, icon, colour, subtitle, description. Each agent gets its own file
7
+ under ``nodes/agent/`` so the user can find ``android_agent.py``
8
+ directly but the body lives here so changing the dispatch path is a
9
+ one-file edit.
10
10
  """
11
11
 
12
12
  from __future__ import annotations
@@ -36,14 +36,23 @@ class SpecializedAgentParams(BaseModel):
36
36
  },
37
37
  )
38
38
  provider: Literal[
39
- "openai", "anthropic", "gemini", "openrouter",
40
- "groq", "cerebras", "deepseek", "kimi", "mistral",
39
+ "openai",
40
+ "anthropic",
41
+ "gemini",
42
+ "openrouter",
43
+ "groq",
44
+ "cerebras",
45
+ "deepseek",
46
+ "kimi",
47
+ "mistral",
41
48
  # Local-server providers — see ai_agent.Params for the proxy_url
42
49
  # rationale. Same fix; same reason.
43
- "ollama", "lmstudio",
50
+ "ollama",
51
+ "lmstudio",
44
52
  ] = "openai"
45
53
  model: str = Field(
46
- default="", json_schema_extra={"placeholder": "Select a model..."},
54
+ default="",
55
+ json_schema_extra={"placeholder": "Select a model..."},
47
56
  )
48
57
  system_message: Optional[str] = Field(
49
58
  default="You are a helpful assistant",
@@ -54,14 +63,18 @@ class SpecializedAgentParams(BaseModel):
54
63
  # default=None so an unset value falls through to ``agent.default_temperature``
55
64
  # in server/config/llm_defaults.json (resolved by _resolve_temperature).
56
65
  temperature: Optional[float] = Field(
57
- default=None, ge=0.0, le=2.0,
66
+ default=None,
67
+ ge=0.0,
68
+ le=2.0,
58
69
  json_schema_extra={"group": "options"},
59
70
  )
60
71
  # default=None so an unset value is absent from the dumped dict and the
61
72
  # backend (_resolve_max_tokens) falls through to the per-model default
62
73
  # in server/config/llm_defaults.json instead of being silently capped.
63
74
  max_tokens: Optional[int] = Field(
64
- default=None, ge=1, le=200000,
75
+ default=None,
76
+ ge=1,
77
+ le=200000,
65
78
  json_schema_extra={"group": "options"},
66
79
  )
67
80
 
@@ -117,9 +130,11 @@ class SpecializedAgentBase(ActionNode, abstract=True):
117
130
  ai_service = get_ai_service()
118
131
  database = get_database()
119
132
  kwargs = await prepare_agent_call(
120
- node_id=ctx.node_id, node_type=self.type,
133
+ node_id=ctx.node_id,
134
+ node_type=self.type,
121
135
  parameters=params.model_dump(),
122
- context=ctx.raw, database=database,
136
+ context=ctx.raw,
137
+ database=database,
123
138
  log_prefix=f"[{self.type}]",
124
139
  )
125
140
  response = await ai_service.execute_chat_agent(ctx.node_id, **kwargs)
@@ -1,8 +1,8 @@
1
- """AI Agent — Wave 11.C migration (LangGraph agent).
1
+ """AI Agent — Wave 11.C migration (tool-calling agent).
2
2
 
3
- Tool-calling LangGraph agent with memory, skills, and iterative
3
+ Tool-calling agent with memory, skills, and iterative
4
4
  reasoning. Delegates execution to ``handlers/ai.handle_ai_agent`` —
5
- that body owns the LangGraph graph construction + tool binding +
5
+ that body owns the agent-loop construction + tool binding +
6
6
  streaming + memory persistence + delegation.
7
7
  """
8
8
 
@@ -14,7 +14,7 @@ from pydantic import BaseModel, ConfigDict, Field
14
14
 
15
15
  from services.plugin import ActionNode, NodeContext, Operation, TaskQueue
16
16
 
17
- from ._handles import STD_AGENT_HINTS, std_agent_handles
17
+ from .._handles import STD_AGENT_HINTS, std_agent_handles
18
18
 
19
19
 
20
20
  class AIAgentParams(BaseModel):
@@ -39,17 +39,26 @@ class AIAgentParams(BaseModel):
39
39
  },
40
40
  )
41
41
  provider: Literal[
42
- "openai", "anthropic", "gemini", "openrouter",
43
- "groq", "cerebras", "deepseek", "kimi", "mistral",
42
+ "openai",
43
+ "anthropic",
44
+ "gemini",
45
+ "openrouter",
46
+ "groq",
47
+ "cerebras",
48
+ "deepseek",
49
+ "kimi",
50
+ "mistral",
44
51
  # Local-server providers — agent execution reads
45
52
  # ``{provider}_proxy`` to point the LangChain client at the
46
53
  # user's localhost server. Without these entries the dropdown
47
54
  # silently falls back to ``"openai"`` and execute_agent ends
48
55
  # up calling api.openai.com instead.
49
- "ollama", "lmstudio",
56
+ "ollama",
57
+ "lmstudio",
50
58
  ] = "openai"
51
59
  model: str = Field(
52
- default="", json_schema_extra={"placeholder": "Select a model..."},
60
+ default="",
61
+ json_schema_extra={"placeholder": "Select a model..."},
53
62
  )
54
63
  system_message: Optional[str] = Field(
55
64
  default="You are a helpful assistant",
@@ -60,14 +69,18 @@ class AIAgentParams(BaseModel):
60
69
  # default=None so an unset value falls through to ``agent.default_temperature``
61
70
  # in server/config/llm_defaults.json (resolved by _resolve_temperature).
62
71
  temperature: Optional[float] = Field(
63
- default=None, ge=0.0, le=2.0,
72
+ default=None,
73
+ ge=0.0,
74
+ le=2.0,
64
75
  json_schema_extra={"numberStepSize": 0.1, "group": "options"},
65
76
  )
66
77
  # default=None so an unset value is absent from the dumped dict and the
67
78
  # backend (_resolve_max_tokens) falls through to the per-model default
68
79
  # in server/config/llm_defaults.json instead of being silently capped.
69
80
  max_tokens: Optional[int] = Field(
70
- default=None, ge=1, le=200000,
81
+ default=None,
82
+ ge=1,
83
+ le=200000,
71
84
  json_schema_extra={"group": "options"},
72
85
  )
73
86
 
@@ -98,10 +111,11 @@ class AIAgentOutput(BaseModel):
98
111
  class AIAgentNode(ActionNode):
99
112
  type = "aiAgent"
100
113
  display_name = "AI Agent"
101
- subtitle = "LangGraph Agent"
114
+ subtitle = "AI Agent"
102
115
  group = ("agent",)
103
- description = "LangGraph agent with tool calling, memory, and iterative reasoning"
116
+ description = "AI agent with tool calling, memory, and iterative reasoning"
104
117
  component_kind = "agent"
118
+ tool_name = "delegate_to_ai_agent"
105
119
  handles = std_agent_handles()
106
120
  ui_hints = STD_AGENT_HINTS
107
121
  annotations = {"destructive": False, "readonly": False, "open_world": True}
@@ -117,19 +131,21 @@ class AIAgentNode(ActionNode):
117
131
  Pre-dispatch flow (edge walk + task inject + prompt fallback)
118
132
  lives in :mod:`nodes.agent._inline`. This method just calls
119
133
  ``AIService.execute_agent`` with the prepared kwargs. The
120
- underlying LangGraph orchestration + tool binding + memory
121
- I/O + streaming hooks stay in AIService.
134
+ underlying agent loop + tool binding + memory I/O + streaming
135
+ hooks stay in AIService.
122
136
  """
123
137
  from services.plugin.deps import get_ai_service, get_database
124
138
 
125
- from ._inline import prepare_agent_call
139
+ from .._inline import prepare_agent_call
126
140
 
127
141
  ai_service = get_ai_service()
128
142
  database = get_database()
129
143
  kwargs = await prepare_agent_call(
130
- node_id=ctx.node_id, node_type=self.type,
144
+ node_id=ctx.node_id,
145
+ node_type=self.type,
131
146
  parameters=params.model_dump(),
132
- context=ctx.raw, database=database,
147
+ context=ctx.raw,
148
+ database=database,
133
149
  log_prefix="[AI Agent]",
134
150
  )
135
151
  # ``execute_agent`` raises ``NodeUserError`` directly for typed