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
@@ -20,35 +20,32 @@ logger = get_logger(__name__)
20
20
 
21
21
  # Platform-specific field mappings to unified format
22
22
  PLATFORM_FIELD_MAPPINGS = {
23
- 'whatsapp': {
24
- 'sender': 'sender',
25
- 'sender_phone': 'sender_phone',
26
- 'sender_name': 'push_name',
27
- 'chat_id': 'chat_id',
28
- 'text': 'text',
29
- 'message_type': 'message_type',
30
- 'is_group': 'is_group',
31
- 'is_from_me': 'is_from_me',
32
- 'timestamp': 'timestamp',
33
- 'message_id': 'message_id',
23
+ "whatsapp": {
24
+ "sender": "sender",
25
+ "sender_phone": "sender_phone",
26
+ "sender_name": "push_name",
27
+ "chat_id": "chat_id",
28
+ "text": "text",
29
+ "message_type": "message_type",
30
+ "is_group": "is_group",
31
+ "is_from_me": "is_from_me",
32
+ "timestamp": "timestamp",
33
+ "message_id": "message_id",
34
34
  },
35
35
  # Add more platform mappings as they are integrated
36
- 'telegram': {},
37
- 'discord': {},
38
- 'slack': {},
39
- 'signal': {},
40
- 'sms': {},
41
- 'webchat': {},
42
- 'email': {},
43
- 'matrix': {},
44
- 'teams': {},
36
+ "telegram": {},
37
+ "discord": {},
38
+ "slack": {},
39
+ "signal": {},
40
+ "sms": {},
41
+ "webchat": {},
42
+ "email": {},
43
+ "matrix": {},
44
+ "teams": {},
45
45
  }
46
46
 
47
47
 
48
- def _normalize_to_unified_format(
49
- input_data: Dict[str, Any],
50
- source_channel: str
51
- ) -> Dict[str, Any]:
48
+ def _normalize_to_unified_format(input_data: Dict[str, Any], source_channel: str) -> Dict[str, Any]:
52
49
  """Normalize platform-specific message data to unified social format.
53
50
 
54
51
  Args:
@@ -61,88 +58,85 @@ def _normalize_to_unified_format(
61
58
  import uuid
62
59
 
63
60
  # Generate message_id if not present (e.g., chatTrigger doesn't have one)
64
- message_id = input_data.get('message_id') or str(uuid.uuid4())[:8]
61
+ message_id = input_data.get("message_id") or str(uuid.uuid4())[:8]
65
62
 
66
63
  # For webchat, use session_id as sender/chat_id if not provided
67
- session_id = input_data.get('session_id', 'default')
68
- default_sender = f"webchat_{session_id}" if source_channel == 'webchat' else ''
69
- default_chat_id = session_id if source_channel == 'webchat' else ''
64
+ session_id = input_data.get("session_id", "default")
65
+ default_sender = f"webchat_{session_id}" if source_channel == "webchat" else ""
66
+ default_chat_id = session_id if source_channel == "webchat" else ""
70
67
 
71
68
  # Start with unified structure
72
69
  unified = {
73
- 'message_id': message_id,
74
- 'channel': source_channel,
75
- 'sender': input_data.get('sender') or default_sender,
76
- 'sender_phone': input_data.get('sender_phone', ''),
77
- 'sender_name': input_data.get('sender_name') or input_data.get('push_name') or ('User' if source_channel == 'webchat' else ''),
78
- 'sender_username': input_data.get('sender_username', ''),
79
- 'chat_id': input_data.get('chat_id') or default_chat_id,
80
- 'chat_title': input_data.get('chat_title', ''),
81
- 'chat_type': _determine_chat_type(input_data),
82
- 'message_type': input_data.get('message_type', 'text'),
83
- 'text': input_data.get('text') or input_data.get('message', ''),
84
- 'timestamp': input_data.get('timestamp', datetime.now().isoformat()),
85
- 'is_group': input_data.get('is_group', False),
86
- 'is_from_me': input_data.get('is_from_me', False),
87
- 'is_forwarded': input_data.get('is_forwarded', False),
88
- 'is_bot': input_data.get('is_bot', False),
89
- 'is_admin': input_data.get('is_admin', False),
90
- 'thread_id': input_data.get('thread_id'),
91
- 'account_id': input_data.get('account_id'),
92
- 'session_id': input_data.get('session_id'),
70
+ "message_id": message_id,
71
+ "channel": source_channel,
72
+ "sender": input_data.get("sender") or default_sender,
73
+ "sender_phone": input_data.get("sender_phone", ""),
74
+ "sender_name": input_data.get("sender_name") or input_data.get("push_name") or ("User" if source_channel == "webchat" else ""),
75
+ "sender_username": input_data.get("sender_username", ""),
76
+ "chat_id": input_data.get("chat_id") or default_chat_id,
77
+ "chat_title": input_data.get("chat_title", ""),
78
+ "chat_type": _determine_chat_type(input_data),
79
+ "message_type": input_data.get("message_type", "text"),
80
+ "text": input_data.get("text") or input_data.get("message", ""),
81
+ "timestamp": input_data.get("timestamp", datetime.now().isoformat()),
82
+ "is_group": input_data.get("is_group", False),
83
+ "is_from_me": input_data.get("is_from_me", False),
84
+ "is_forwarded": input_data.get("is_forwarded", False),
85
+ "is_bot": input_data.get("is_bot", False),
86
+ "is_admin": input_data.get("is_admin", False),
87
+ "thread_id": input_data.get("thread_id"),
88
+ "account_id": input_data.get("account_id"),
89
+ "session_id": input_data.get("session_id"),
93
90
  }
94
91
 
95
92
  # Copy group_info if present
96
- if input_data.get('group_info'):
97
- unified['group_info'] = input_data['group_info']
93
+ if input_data.get("group_info"):
94
+ unified["group_info"] = input_data["group_info"]
98
95
 
99
96
  # Copy media if present
100
- if input_data.get('media'):
101
- unified['media'] = input_data['media']
97
+ if input_data.get("media"):
98
+ unified["media"] = input_data["media"]
102
99
 
103
100
  # Copy location if present
104
- if input_data.get('location'):
105
- unified['location'] = input_data['location']
101
+ if input_data.get("location"):
102
+ unified["location"] = input_data["location"]
106
103
 
107
104
  # Copy contact if present
108
- if input_data.get('contact'):
109
- unified['contact'] = input_data['contact']
105
+ if input_data.get("contact"):
106
+ unified["contact"] = input_data["contact"]
110
107
 
111
108
  # Copy poll if present
112
- if input_data.get('poll'):
113
- unified['poll'] = input_data['poll']
109
+ if input_data.get("poll"):
110
+ unified["poll"] = input_data["poll"]
114
111
 
115
112
  # Copy reaction if present
116
- if input_data.get('reaction'):
117
- unified['reaction'] = input_data['reaction']
113
+ if input_data.get("reaction"):
114
+ unified["reaction"] = input_data["reaction"]
118
115
 
119
116
  # Copy reply_to if present
120
- if input_data.get('reply_to'):
121
- unified['reply_to'] = input_data['reply_to']
117
+ if input_data.get("reply_to"):
118
+ unified["reply_to"] = input_data["reply_to"]
122
119
 
123
120
  # Copy mentions if present
124
- if input_data.get('mentions'):
125
- unified['mentions'] = input_data['mentions']
121
+ if input_data.get("mentions"):
122
+ unified["mentions"] = input_data["mentions"]
126
123
 
127
124
  # Keep raw data for platform-specific access
128
- unified['raw'] = input_data.get('raw', input_data)
125
+ unified["raw"] = input_data.get("raw", input_data)
129
126
 
130
127
  return unified
131
128
 
132
129
 
133
130
  def _determine_chat_type(data: Dict[str, Any]) -> str:
134
131
  """Determine chat type from message data."""
135
- if data.get('chat_type'):
136
- return data['chat_type']
137
- if data.get('is_group'):
138
- return 'group'
139
- return 'dm'
132
+ if data.get("chat_type"):
133
+ return data["chat_type"]
134
+ if data.get("is_group"):
135
+ return "group"
136
+ return "dm"
140
137
 
141
138
 
142
- def _apply_filters(
143
- message: Dict[str, Any],
144
- parameters: Dict[str, Any]
145
- ) -> bool:
139
+ def _apply_filters(message: Dict[str, Any], parameters: Dict[str, Any]) -> bool:
146
140
  """Check if message passes configured filters.
147
141
 
148
142
  Args:
@@ -153,50 +147,50 @@ def _apply_filters(
153
147
  True if message passes all filters
154
148
  """
155
149
  # Channel filter
156
- channel_filter = parameters.get('channel_filter', 'all')
157
- if channel_filter != 'all' and message.get('channel') != channel_filter:
150
+ channel_filter = parameters.get("channel_filter", "all")
151
+ if channel_filter != "all" and message.get("channel") != channel_filter:
158
152
  return False
159
153
 
160
154
  # Message type filter
161
- type_filter = parameters.get('message_type_filter', 'all')
162
- if type_filter != 'all' and message.get('message_type') != type_filter:
155
+ type_filter = parameters.get("message_type_filter", "all")
156
+ if type_filter != "all" and message.get("message_type") != type_filter:
163
157
  return False
164
158
 
165
159
  # Sender filter
166
- sender_filter = parameters.get('sender_filter', 'all')
160
+ sender_filter = parameters.get("sender_filter", "all")
167
161
 
168
- if sender_filter == 'any_contact':
162
+ if sender_filter == "any_contact":
169
163
  # Non-group messages only
170
- if message.get('is_group'):
164
+ if message.get("is_group"):
171
165
  return False
172
166
 
173
- elif sender_filter == 'contact':
167
+ elif sender_filter == "contact":
174
168
  # Specific contact
175
- contact_phone = parameters.get('contact_phone', '')
176
- if contact_phone and message.get('sender_phone') != contact_phone:
169
+ contact_phone = parameters.get("contact_phone", "")
170
+ if contact_phone and message.get("sender_phone") != contact_phone:
177
171
  return False
178
172
 
179
- elif sender_filter == 'group':
173
+ elif sender_filter == "group":
180
174
  # Specific group
181
- group_id = parameters.get('group_id', '')
182
- if group_id and message.get('chat_id') != group_id:
175
+ group_id = parameters.get("group_id", "")
176
+ if group_id and message.get("chat_id") != group_id:
183
177
  return False
184
178
 
185
- elif sender_filter == 'keywords':
179
+ elif sender_filter == "keywords":
186
180
  # Keyword matching
187
- keywords_str = parameters.get('keywords', '')
181
+ keywords_str = parameters.get("keywords", "")
188
182
  if keywords_str:
189
- keywords = [k.strip().lower() for k in keywords_str.split(',')]
190
- text = (message.get('text') or '').lower()
183
+ keywords = [k.strip().lower() for k in keywords_str.split(",")]
184
+ text = (message.get("text") or "").lower()
191
185
  if not any(kw in text for kw in keywords):
192
186
  return False
193
187
 
194
188
  # Ignore own messages
195
- if parameters.get('ignore_own_messages', True) and message.get('is_from_me'):
189
+ if parameters.get("ignore_own_messages", True) and message.get("is_from_me"):
196
190
  return False
197
191
 
198
192
  # Ignore bots
199
- if parameters.get('ignore_bots', False) and message.get('is_bot'):
193
+ if parameters.get("ignore_bots", False) and message.get("is_bot"):
200
194
  return False
201
195
 
202
196
  return True
@@ -208,7 +202,7 @@ async def handle_social_receive(
208
202
  parameters: Dict[str, Any],
209
203
  context: Dict[str, Any],
210
204
  outputs: Dict[str, Any] = None,
211
- source_nodes: list = None
205
+ source_nodes: list = None,
212
206
  ) -> Dict[str, Any]:
213
207
  """Handle Social Receive node - normalizes and filters incoming messages.
214
208
 
@@ -230,7 +224,7 @@ async def handle_social_receive(
230
224
 
231
225
  # Use outputs passed from node_executor, fall back to context for backwards compatibility
232
226
  if outputs is None:
233
- outputs = context.get('outputs', {})
227
+ outputs = context.get("outputs", {})
234
228
  if source_nodes is None:
235
229
  source_nodes = []
236
230
 
@@ -238,31 +232,31 @@ async def handle_social_receive(
238
232
 
239
233
  try:
240
234
  input_data = None
241
- source_channel = 'unknown'
235
+ source_channel = "unknown"
242
236
 
243
237
  # Find message data from connected outputs
244
238
  # Outputs are keyed by node type (e.g., 'whatsappReceive') and contain raw data directly
245
239
  for source_node in source_nodes:
246
- source_type = source_node.get('type', '')
240
+ source_type = source_node.get("type", "")
247
241
  source_output = outputs.get(source_type)
248
242
 
249
243
  if source_output and isinstance(source_output, dict):
250
244
  # Check if this output has message data (message_id, text, or message field)
251
- if source_output.get('message_id') or source_output.get('text') or source_output.get('message'):
245
+ if source_output.get("message_id") or source_output.get("text") or source_output.get("message"):
252
246
  input_data = source_output
253
247
  # Detect source channel from node type
254
- if 'whatsapp' in source_type.lower():
255
- source_channel = 'whatsapp'
256
- elif 'telegram' in source_type.lower():
257
- source_channel = 'telegram'
258
- elif 'discord' in source_type.lower():
259
- source_channel = 'discord'
260
- elif 'slack' in source_type.lower():
261
- source_channel = 'slack'
262
- elif 'chat' in source_type.lower():
263
- source_channel = 'webchat'
264
- elif source_output.get('channel'):
265
- source_channel = source_output['channel']
248
+ if "whatsapp" in source_type.lower():
249
+ source_channel = "whatsapp"
250
+ elif "telegram" in source_type.lower():
251
+ source_channel = "telegram"
252
+ elif "discord" in source_type.lower():
253
+ source_channel = "discord"
254
+ elif "slack" in source_type.lower():
255
+ source_channel = "slack"
256
+ elif "chat" in source_type.lower():
257
+ source_channel = "webchat"
258
+ elif source_output.get("channel"):
259
+ source_channel = source_output["channel"]
266
260
  logger.debug(f"[handle_social_receive] Found message from {source_type}, channel={source_channel}")
267
261
  break
268
262
 
@@ -270,27 +264,29 @@ async def handle_social_receive(
270
264
  if not input_data:
271
265
  for upstream_key, upstream_output in outputs.items():
272
266
  if isinstance(upstream_output, dict):
273
- if upstream_output.get('message_id') or upstream_output.get('text') or upstream_output.get('message'):
267
+ if upstream_output.get("message_id") or upstream_output.get("text") or upstream_output.get("message"):
274
268
  input_data = upstream_output
275
269
  # Detect source channel from key or data
276
- if 'whatsapp' in upstream_key.lower() or upstream_output.get('sender', '').endswith('@s.whatsapp.net'):
277
- source_channel = 'whatsapp'
278
- elif 'chat' in upstream_key.lower():
279
- source_channel = 'webchat'
280
- elif upstream_output.get('channel'):
281
- source_channel = upstream_output['channel']
270
+ if "whatsapp" in upstream_key.lower() or upstream_output.get("sender", "").endswith("@s.whatsapp.net"):
271
+ source_channel = "whatsapp"
272
+ elif "chat" in upstream_key.lower():
273
+ source_channel = "webchat"
274
+ elif upstream_output.get("channel"):
275
+ source_channel = upstream_output["channel"]
282
276
  logger.debug(f"[handle_social_receive] Found message via fallback from key={upstream_key}")
283
277
  break
284
278
 
285
279
  if not input_data:
286
- logger.warning(f"[handle_social_receive] No message data found. outputs keys={list(outputs.keys())}, source_nodes={source_nodes}")
280
+ logger.warning(
281
+ f"[handle_social_receive] No message data found. outputs keys={list(outputs.keys())}, source_nodes={source_nodes}"
282
+ )
287
283
  return {
288
284
  "success": False,
289
285
  "node_id": node_id,
290
286
  "node_type": "socialReceive",
291
287
  "error": f"No message data received from upstream trigger. Available sources: {list(outputs.keys())}",
292
288
  "execution_time": time.time() - start_time,
293
- "timestamp": datetime.now().isoformat()
289
+ "timestamp": datetime.now().isoformat(),
294
290
  }
295
291
 
296
292
  # Normalize to unified format
@@ -306,7 +302,7 @@ async def handle_social_receive(
306
302
  "filtered": True,
307
303
  "reason": "Message did not pass filters",
308
304
  "execution_time": time.time() - start_time,
309
- "timestamp": datetime.now().isoformat()
305
+ "timestamp": datetime.now().isoformat(),
310
306
  }
311
307
 
312
308
  # Build result with four outputs:
@@ -314,48 +310,46 @@ async def handle_social_receive(
314
310
  # - media: Media data and metadata
315
311
  # - contact: Sender/contact info
316
312
  # - metadata: Message-related metadata
317
- media_data = unified_message.get('media', {})
313
+ media_data = unified_message.get("media", {})
318
314
  result = {
319
315
  # Output 1: Just the text message
320
- "message": unified_message.get('text', ''),
321
-
316
+ "message": unified_message.get("text", ""),
322
317
  # Output 2: Media data and related metadata
323
318
  "media": {
324
- "url": media_data.get('url', '') if media_data else '',
325
- "type": media_data.get('type', '') if media_data else '',
326
- "mimetype": media_data.get('mimetype', '') if media_data else '',
327
- "caption": media_data.get('caption', '') if media_data else '',
328
- "size": media_data.get('size', 0) if media_data else 0,
329
- "thumbnail": media_data.get('thumbnail', '') if media_data else '',
330
- "filename": media_data.get('filename', '') if media_data else '',
331
- } if media_data else {},
332
-
319
+ "url": media_data.get("url", "") if media_data else "",
320
+ "type": media_data.get("type", "") if media_data else "",
321
+ "mimetype": media_data.get("mimetype", "") if media_data else "",
322
+ "caption": media_data.get("caption", "") if media_data else "",
323
+ "size": media_data.get("size", 0) if media_data else 0,
324
+ "thumbnail": media_data.get("thumbnail", "") if media_data else "",
325
+ "filename": media_data.get("filename", "") if media_data else "",
326
+ }
327
+ if media_data
328
+ else {},
333
329
  # Output 3: Contact/sender info
334
330
  "contact": {
335
- "sender": unified_message.get('sender'),
336
- "sender_phone": unified_message.get('sender_phone'),
337
- "sender_name": unified_message.get('sender_name'),
338
- "sender_username": unified_message.get('sender_username'),
339
- "channel": unified_message.get('channel'),
340
- "is_group": unified_message.get('is_group'),
341
- "group_info": unified_message.get('group_info'),
342
- "chat_title": unified_message.get('chat_title'),
331
+ "sender": unified_message.get("sender"),
332
+ "sender_phone": unified_message.get("sender_phone"),
333
+ "sender_name": unified_message.get("sender_name"),
334
+ "sender_username": unified_message.get("sender_username"),
335
+ "channel": unified_message.get("channel"),
336
+ "is_group": unified_message.get("is_group"),
337
+ "group_info": unified_message.get("group_info"),
338
+ "chat_title": unified_message.get("chat_title"),
343
339
  },
344
-
345
340
  # Output 4: Message-related metadata
346
341
  "metadata": {
347
- "message_id": unified_message.get('message_id'),
348
- "chat_id": unified_message.get('chat_id'),
349
- "timestamp": unified_message.get('timestamp'),
350
- "message_type": unified_message.get('message_type'),
351
- "is_from_me": unified_message.get('is_from_me'),
352
- "is_forwarded": unified_message.get('is_forwarded'),
353
- "reply_to": unified_message.get('reply_to'),
354
- "thread_id": unified_message.get('thread_id'),
342
+ "message_id": unified_message.get("message_id"),
343
+ "chat_id": unified_message.get("chat_id"),
344
+ "timestamp": unified_message.get("timestamp"),
345
+ "message_type": unified_message.get("message_type"),
346
+ "is_from_me": unified_message.get("is_from_me"),
347
+ "is_forwarded": unified_message.get("is_forwarded"),
348
+ "reply_to": unified_message.get("reply_to"),
349
+ "thread_id": unified_message.get("thread_id"),
355
350
  },
356
-
357
351
  # Backwards compatibility: include full data at top level
358
- **unified_message
352
+ **unified_message,
359
353
  }
360
354
 
361
355
  return {
@@ -364,7 +358,7 @@ async def handle_social_receive(
364
358
  "node_type": "socialReceive",
365
359
  "result": result,
366
360
  "execution_time": time.time() - start_time,
367
- "timestamp": datetime.now().isoformat()
361
+ "timestamp": datetime.now().isoformat(),
368
362
  }
369
363
 
370
364
  except Exception as e:
@@ -375,16 +369,11 @@ async def handle_social_receive(
375
369
  "node_type": "socialReceive",
376
370
  "error": str(e),
377
371
  "execution_time": time.time() - start_time,
378
- "timestamp": datetime.now().isoformat()
372
+ "timestamp": datetime.now().isoformat(),
379
373
  }
380
374
 
381
375
 
382
- async def handle_social_send(
383
- node_id: str,
384
- node_type: str,
385
- parameters: Dict[str, Any],
386
- context: Dict[str, Any]
387
- ) -> Dict[str, Any]:
376
+ async def handle_social_send(node_id: str, node_type: str, parameters: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
388
377
  """Handle Social Send node - routes outbound messages to platform.
389
378
 
390
379
  This node sends messages to the configured platform (WhatsApp, Telegram, etc.)
@@ -402,39 +391,35 @@ async def handle_social_send(
402
391
  start_time = time.time()
403
392
 
404
393
  try:
405
- channel = parameters.get('channel', 'whatsapp')
406
- recipient_type = parameters.get('recipient_type', 'phone')
407
- message_type = parameters.get('message_type', 'text')
394
+ channel = parameters.get("channel", "whatsapp")
395
+ recipient_type = parameters.get("recipient_type", "phone")
396
+ message_type = parameters.get("message_type", "text")
408
397
 
409
398
  # Get recipient based on type
410
399
  recipient = None
411
- if recipient_type == 'phone':
412
- recipient = parameters.get('phone')
413
- elif recipient_type == 'group':
414
- recipient = parameters.get('group_id')
415
- elif recipient_type == 'channel':
416
- recipient = parameters.get('channel_id')
417
- elif recipient_type == 'user':
418
- recipient = parameters.get('user_id')
419
- elif recipient_type == 'chat':
420
- recipient = parameters.get('chat_id')
400
+ if recipient_type == "phone":
401
+ recipient = parameters.get("phone")
402
+ elif recipient_type == "group":
403
+ recipient = parameters.get("group_id")
404
+ elif recipient_type == "channel":
405
+ recipient = parameters.get("channel_id")
406
+ elif recipient_type == "user":
407
+ recipient = parameters.get("user_id")
408
+ elif recipient_type == "chat":
409
+ recipient = parameters.get("chat_id")
421
410
 
422
411
  if not recipient:
423
412
  raise ValueError(f"Recipient ({recipient_type}) is required")
424
413
 
425
414
  # Route to platform-specific handler
426
- if channel == 'whatsapp':
415
+ if channel == "whatsapp":
427
416
  result = await _send_via_whatsapp(parameters, recipient, recipient_type, message_type)
428
417
  else:
429
418
  # Stub for other platforms - will be implemented as they are integrated
430
- result = {
431
- "success": False,
432
- "error": f"Platform '{channel}' is not yet implemented",
433
- "message_id": None
434
- }
419
+ result = {"success": False, "error": f"Platform '{channel}' is not yet implemented", "message_id": None}
435
420
 
436
- if not result.get('success'):
437
- raise Exception(result.get('error', 'Send failed'))
421
+ if not result.get("success"):
422
+ raise Exception(result.get("error", "Send failed"))
438
423
 
439
424
  return {
440
425
  "success": True,
@@ -442,15 +427,15 @@ async def handle_social_send(
442
427
  "node_type": "socialSend",
443
428
  "result": {
444
429
  "success": True,
445
- "message_id": result.get('message_id'),
430
+ "message_id": result.get("message_id"),
446
431
  "channel": channel,
447
432
  "recipient": recipient,
448
433
  "recipient_type": recipient_type,
449
434
  "message_type": message_type,
450
- "timestamp": datetime.now().isoformat()
435
+ "timestamp": datetime.now().isoformat(),
451
436
  },
452
437
  "execution_time": time.time() - start_time,
453
- "timestamp": datetime.now().isoformat()
438
+ "timestamp": datetime.now().isoformat(),
454
439
  }
455
440
 
456
441
  except Exception as e:
@@ -461,70 +446,77 @@ async def handle_social_send(
461
446
  "node_type": "socialSend",
462
447
  "error": str(e),
463
448
  "execution_time": time.time() - start_time,
464
- "timestamp": datetime.now().isoformat()
449
+ "timestamp": datetime.now().isoformat(),
465
450
  }
466
451
 
467
452
 
468
- async def _send_via_whatsapp(
469
- parameters: Dict[str, Any],
470
- recipient: str,
471
- recipient_type: str,
472
- message_type: str
473
- ) -> Dict[str, Any]:
474
- """Route message to WhatsApp via existing handler.
453
+ async def _send_via_whatsapp(parameters: Dict[str, Any], recipient: str, recipient_type: str, message_type: str) -> Dict[str, Any]:
454
+ """Route message to WhatsApp via the social-provider registry.
475
455
 
476
- Maps socialSend parameters to whatsappSend parameters.
456
+ Maps socialSend parameters to whatsappSend parameters, then
457
+ dispatches through :func:`services.plugin.social_provider_registry.
458
+ get_social_send_handler`. The whatsapp plugin self-registers as the
459
+ ``"whatsapp"`` platform from its own ``__init__.py`` — no
460
+ cross-plugin import from this module.
477
461
  """
478
- from nodes.whatsapp._service import handle_whatsapp_send as whatsapp_send_handler
462
+ from services.plugin.social_provider_registry import get_social_send_handler
463
+
464
+ whatsapp_send_handler = get_social_send_handler("whatsapp")
465
+ if whatsapp_send_handler is None:
466
+ raise RuntimeError(
467
+ "social: 'whatsapp' platform not registered. "
468
+ "Check that nodes/whatsapp/__init__.py is imported at startup "
469
+ "and calls register_social_send_handler('whatsapp', ...). "
470
+ )
479
471
 
480
472
  # Map socialSend params to whatsappSend format
481
473
  whatsapp_params = {
482
- 'recipient_type': recipient_type,
483
- 'message_type': message_type,
474
+ "recipient_type": recipient_type,
475
+ "message_type": message_type,
484
476
  }
485
477
 
486
478
  # Set recipient
487
- if recipient_type == 'phone':
488
- whatsapp_params['phone'] = recipient
479
+ if recipient_type == "phone":
480
+ whatsapp_params["phone"] = recipient
489
481
  else:
490
- whatsapp_params['group_id'] = recipient
482
+ whatsapp_params["group_id"] = recipient
491
483
 
492
484
  # Map message content based on type
493
- if message_type == 'text':
494
- whatsapp_params['message'] = parameters.get('message', '')
495
-
496
- elif message_type in ('image', 'video', 'audio', 'document', 'sticker'):
497
- media_source = parameters.get('media_source', 'url')
498
- whatsapp_params['media_source'] = media_source
499
-
500
- if media_source == 'url':
501
- whatsapp_params['media_url'] = parameters.get('media_url', '')
502
- elif media_source == 'base64':
503
- whatsapp_params['media_data'] = parameters.get('media_data', '')
504
- elif media_source == 'file':
505
- whatsapp_params['file_path'] = parameters.get('file_path', '')
506
-
507
- if parameters.get('mime_type'):
508
- whatsapp_params['mime_type'] = parameters['mime_type']
509
- if parameters.get('caption'):
510
- whatsapp_params['caption'] = parameters['caption']
511
- if parameters.get('filename'):
512
- whatsapp_params['filename'] = parameters['filename']
513
-
514
- elif message_type == 'location':
515
- whatsapp_params['latitude'] = parameters.get('latitude', 0)
516
- whatsapp_params['longitude'] = parameters.get('longitude', 0)
517
- whatsapp_params['location_name'] = parameters.get('location_name', '')
518
- whatsapp_params['address'] = parameters.get('address', '')
519
-
520
- elif message_type == 'contact':
521
- whatsapp_params['contact_name'] = parameters.get('contact_name', '')
522
- whatsapp_params['vcard'] = parameters.get('vcard', '')
485
+ if message_type == "text":
486
+ whatsapp_params["message"] = parameters.get("message", "")
487
+
488
+ elif message_type in ("image", "video", "audio", "document", "sticker"):
489
+ media_source = parameters.get("media_source", "url")
490
+ whatsapp_params["media_source"] = media_source
491
+
492
+ if media_source == "url":
493
+ whatsapp_params["media_url"] = parameters.get("media_url", "")
494
+ elif media_source == "base64":
495
+ whatsapp_params["media_data"] = parameters.get("media_data", "")
496
+ elif media_source == "file":
497
+ whatsapp_params["file_path"] = parameters.get("file_path", "")
498
+
499
+ if parameters.get("mime_type"):
500
+ whatsapp_params["mime_type"] = parameters["mime_type"]
501
+ if parameters.get("caption"):
502
+ whatsapp_params["caption"] = parameters["caption"]
503
+ if parameters.get("filename"):
504
+ whatsapp_params["filename"] = parameters["filename"]
505
+
506
+ elif message_type == "location":
507
+ whatsapp_params["latitude"] = parameters.get("latitude", 0)
508
+ whatsapp_params["longitude"] = parameters.get("longitude", 0)
509
+ whatsapp_params["location_name"] = parameters.get("location_name", "")
510
+ whatsapp_params["address"] = parameters.get("address", "")
511
+
512
+ elif message_type == "contact":
513
+ whatsapp_params["contact_name"] = parameters.get("contact_name", "")
514
+ whatsapp_params["vcard"] = parameters.get("vcard", "")
523
515
 
524
516
  # Reply options
525
- if parameters.get('reply_to_message'):
526
- whatsapp_params['is_reply'] = True
527
- whatsapp_params['reply_message_id'] = parameters.get('reply_message_id', '')
517
+ if parameters.get("reply_to_message"):
518
+ whatsapp_params["is_reply"] = True
519
+ whatsapp_params["reply_message_id"] = parameters.get("reply_message_id", "")
528
520
 
529
521
  # Call WhatsApp handler
530
522
  return await whatsapp_send_handler(whatsapp_params)