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
@@ -29,9 +29,16 @@ _ROUTING_REMOVE_OPS = ["remove_routing_rule"]
29
29
 
30
30
  class ProxyConfigParams(BaseModel):
31
31
  operation: Literal[
32
- "list_providers", "add_provider", "update_provider", "remove_provider",
33
- "set_credentials", "test_provider", "get_stats",
34
- "add_routing_rule", "list_routing_rules", "remove_routing_rule",
32
+ "list_providers",
33
+ "add_provider",
34
+ "update_provider",
35
+ "remove_provider",
36
+ "set_credentials",
37
+ "test_provider",
38
+ "get_stats",
39
+ "add_routing_rule",
40
+ "list_routing_rules",
41
+ "remove_routing_rule",
35
42
  ] = Field(
36
43
  default="list_providers",
37
44
  description="Proxy management operation. list_providers / get_stats / list_routing_rules need no extra params.",
@@ -57,7 +64,7 @@ class ProxyConfigParams(BaseModel):
57
64
  )
58
65
  url_template: Any = Field(
59
66
  default="{}",
60
- description="JSON template for proxy URL formatting (e.g. {\"username\": \"{user}-country-{country}\"}).",
67
+ description='JSON template for proxy URL formatting (e.g. {"username": "{user}-country-{country}"}).',
61
68
  json_schema_extra={
62
69
  "rows": 4,
63
70
  "displayOptions": {"show": {"operation": _PROVIDER_EDIT_OPS}},
@@ -75,7 +82,8 @@ class ProxyConfigParams(BaseModel):
75
82
  )
76
83
  priority: int = Field(
77
84
  default=50,
78
- ge=0, le=100,
85
+ ge=0,
86
+ le=100,
79
87
  description="Selection priority (higher ranks first).",
80
88
  json_schema_extra={"displayOptions": {"show": {"operation": _PROVIDER_EDIT_OPS}}},
81
89
  )
@@ -170,22 +178,22 @@ async def _add_provider(p: Dict[str, Any], proxy_svc) -> Dict[str, Any]:
170
178
 
171
179
  url_template_raw = p.get("url_template", "{}")
172
180
  try:
173
- url_template = (
174
- json.loads(url_template_raw) if isinstance(url_template_raw, str) else url_template_raw
175
- )
181
+ url_template = json.loads(url_template_raw) if isinstance(url_template_raw, str) else url_template_raw
176
182
  except json.JSONDecodeError:
177
183
  return {"success": False, "error": f"Invalid url_template JSON: {url_template_raw}"}
178
184
 
179
185
  db = get_database()
180
- await db.save_proxy_provider({
181
- "name": name,
182
- "enabled": p.get("enabled", True),
183
- "priority": int(p.get("priority", 50)),
184
- "cost_per_gb": float(p.get("cost_per_gb", 0)),
185
- "gateway_host": p.get("gateway_host", ""),
186
- "gateway_port": int(p.get("gateway_port", 0)),
187
- "url_template": json.dumps(url_template),
188
- })
186
+ await db.save_proxy_provider(
187
+ {
188
+ "name": name,
189
+ "enabled": p.get("enabled", True),
190
+ "priority": int(p.get("priority", 50)),
191
+ "cost_per_gb": float(p.get("cost_per_gb", 0)),
192
+ "gateway_host": p.get("gateway_host", ""),
193
+ "gateway_port": int(p.get("gateway_port", 0)),
194
+ "url_template": json.dumps(url_template),
195
+ }
196
+ )
189
197
  if proxy_svc:
190
198
  await proxy_svc.reload_providers()
191
199
  return {"success": True, "name": name}
@@ -210,9 +218,7 @@ async def _update_provider(p: Dict[str, Any], proxy_svc) -> Dict[str, Any]:
210
218
  url_template_raw = p.get("url_template")
211
219
  if url_template_raw:
212
220
  try:
213
- url_template = (
214
- json.loads(url_template_raw) if isinstance(url_template_raw, str) else url_template_raw
215
- )
221
+ url_template = json.loads(url_template_raw) if isinstance(url_template_raw, str) else url_template_raw
216
222
  updates["url_template"] = json.dumps(url_template)
217
223
  except json.JSONDecodeError:
218
224
  return {"success": False, "error": "Invalid url_template JSON"}
@@ -264,7 +270,8 @@ async def _test_provider(p: Dict[str, Any], proxy_svc) -> Dict[str, Any]:
264
270
 
265
271
  try:
266
272
  proxy_url = await proxy_svc.get_proxy_url(
267
- "https://httpbin.org/ip", {"proxyProvider": name},
273
+ "https://httpbin.org/ip",
274
+ {"proxyProvider": name},
268
275
  )
269
276
  if not proxy_url:
270
277
  return {"success": False, "error": f"Could not get proxy URL for '{name}'"}
@@ -299,19 +306,19 @@ async def _add_routing_rule(p: Dict[str, Any], proxy_svc) -> Dict[str, Any]:
299
306
 
300
307
  preferred_raw = p.get("preferred_providers", "[]")
301
308
  try:
302
- preferred = (
303
- json.loads(preferred_raw) if isinstance(preferred_raw, str) else preferred_raw
304
- )
309
+ preferred = json.loads(preferred_raw) if isinstance(preferred_raw, str) else preferred_raw
305
310
  except json.JSONDecodeError:
306
311
  preferred = []
307
312
 
308
313
  db = get_database()
309
- await db.save_proxy_routing_rule({
310
- "domain_pattern": domain_pattern,
311
- "preferred_providers": json.dumps(preferred),
312
- "required_country": p.get("required_country", ""),
313
- "session_type": p.get("session_type", "rotating"),
314
- })
314
+ await db.save_proxy_routing_rule(
315
+ {
316
+ "domain_pattern": domain_pattern,
317
+ "preferred_providers": json.dumps(preferred),
318
+ "required_country": p.get("required_country", ""),
319
+ "session_type": p.get("session_type", "rotating"),
320
+ }
321
+ )
315
322
  if proxy_svc:
316
323
  await proxy_svc.reload_providers()
317
324
  return {"success": True, "domain_pattern": domain_pattern}
@@ -369,6 +376,8 @@ class ProxyConfigNode(ActionNode):
369
376
  group = ("proxy", "tool")
370
377
  description = "Configure proxy providers and routing rules"
371
378
  component_kind = "square"
379
+ tool_name = "proxy_config"
380
+ tool_description = "Manage proxy providers and routing rules. Operations: list_providers, add_provider, update_provider, remove_provider, set_credentials, test_provider, get_stats, add_routing_rule, list_routing_rules, remove_routing_rule."
372
381
  handles = (
373
382
  {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
374
383
  {"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#ffb86c"
3
+ }
@@ -46,6 +46,8 @@ class ProxyRequestNode(ActionNode):
46
46
  group = ("proxy", "tool")
47
47
  description = "Make HTTP requests through residential proxy providers"
48
48
  component_kind = "square"
49
+ tool_name = "proxy_request"
50
+ tool_description = "Make HTTP requests through residential proxy providers with geo-targeting, session control, and automatic failover. Supports GET, POST, PUT, DELETE, PATCH methods."
49
51
  handles = (
50
52
  {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
51
53
  {"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
@@ -73,14 +75,13 @@ class ProxyRequestNode(ActionNode):
73
75
 
74
76
  from services.proxy.models import ProxyResult
75
77
  from services.proxy.service import get_proxy_service
76
- from ._usage import track_proxy_usage
78
+ from .._usage import track_proxy_usage
77
79
 
78
80
  log = get_logger(__name__)
79
81
  svc = get_proxy_service()
80
82
  if not svc or not svc.is_enabled():
81
83
  raise NodeUserError(
82
- "Proxy service not initialized. Use proxy_config tool to add a "
83
- "provider first.",
84
+ "Proxy service not initialized. Use proxy_config tool to add a " "provider first.",
84
85
  )
85
86
 
86
87
  raw = params.model_dump()
@@ -116,15 +117,21 @@ class ProxyRequestNode(ActionNode):
116
117
  latency_ms = (time.monotonic() - req_start) * 1000
117
118
  bytes_transferred = len(response.content) if response.content else 0
118
119
 
119
- svc.report_result(provider_name, ProxyResult(
120
- success=response.status_code < 400,
121
- latency_ms=latency_ms,
122
- bytes_transferred=bytes_transferred,
123
- status_code=response.status_code,
124
- ))
120
+ svc.report_result(
121
+ provider_name,
122
+ ProxyResult(
123
+ success=response.status_code < 400,
124
+ latency_ms=latency_ms,
125
+ bytes_transferred=bytes_transferred,
126
+ status_code=response.status_code,
127
+ ),
128
+ )
125
129
  await track_proxy_usage(
126
- ctx.node_id, provider_name, bytes_transferred,
127
- workflow_id=ctx.workflow_id, session_id=ctx.session_id,
130
+ ctx.node_id,
131
+ provider_name,
132
+ bytes_transferred,
133
+ workflow_id=ctx.workflow_id,
134
+ session_id=ctx.session_id,
128
135
  )
129
136
  try:
130
137
  response_data = response.json()
@@ -148,13 +155,20 @@ class ProxyRequestNode(ActionNode):
148
155
  except Exception as e:
149
156
  latency_ms = (time.monotonic() - req_start) * 1000
150
157
  last_error = str(e)
151
- svc.report_result(provider_name, ProxyResult(
152
- success=False, latency_ms=latency_ms, error=last_error,
153
- ))
158
+ svc.report_result(
159
+ provider_name,
160
+ ProxyResult(
161
+ success=False,
162
+ latency_ms=latency_ms,
163
+ error=last_error,
164
+ ),
165
+ )
154
166
  log.warning(
155
167
  "Proxy request attempt failed",
156
- node_id=ctx.node_id, attempt=attempt + 1,
157
- max_retries=max_retries, error=last_error,
168
+ node_id=ctx.node_id,
169
+ attempt=attempt + 1,
170
+ max_retries=max_retries,
171
+ error=last_error,
158
172
  )
159
173
  if not failover or attempt >= max_retries:
160
174
  break
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#ffb86c"
3
+ }
@@ -29,6 +29,8 @@ class ProxyStatusNode(ActionNode):
29
29
  group = ("proxy", "tool")
30
30
  description = "View proxy provider health, scores, and usage statistics"
31
31
  component_kind = "square"
32
+ tool_name = "proxy_status"
33
+ tool_description = "Get proxy provider health stats, scores, and usage statistics. Returns enabled status, provider list with health scores, and aggregated stats."
32
34
  handles = (
33
35
  {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
34
36
  {"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#ffb86c"
3
+ }
@@ -3,6 +3,21 @@
3
3
  Cron-expression-based scheduling trigger. Deployment-mode lifecycle
4
4
  (starting/stopping the cron job) is owned by ``deployment/triggers.py``;
5
5
  the run-button path executes this plugin once for testing.
6
+
7
+ Self-registration on import (Wave 12 C3 — Temporal Schedules canary):
8
+ - ``CronTriggerWorkflow`` (the per-firing workflow shipped in
9
+ ``._workflow``) is wrapped in :class:`temporalio.plugin.SimplePlugin`
10
+ and registered with
11
+ :func:`services.temporal.plugin_registry.register_temporal_plugin`.
12
+ The Temporal worker passes the registered list to
13
+ ``Worker(plugins=[...])`` and the SDK's plugin chain merges this
14
+ plugin's workflow class into the effective worker configuration —
15
+ framework worker stays plugin-agnostic.
16
+ - ``cronScheduler`` opts into the canary set via
17
+ :func:`services.deployment.canary_registry.register_canary_trigger_type`.
18
+ ``DeploymentManager._setup_cron_trigger`` checks the registry +
19
+ feature flag; when both are on, the deploy path creates a Temporal
20
+ ``Schedule`` instead of the in-process APScheduler job.
6
21
  """
7
22
 
8
23
  from __future__ import annotations
@@ -13,12 +28,20 @@ from datetime import datetime, timedelta
13
28
  from typing import Any, Dict, Literal, Optional
14
29
 
15
30
  from pydantic import BaseModel, ConfigDict, Field
31
+ from temporalio.plugin import SimplePlugin
16
32
 
17
33
  from core.logging import get_logger
34
+ from services.deployment.canary_registry import register_canary_trigger_type
18
35
  from services.plugin import ActionNode, NodeContext, Operation, TaskQueue
36
+ from services.temporal.plugin_registry import register_temporal_plugin
37
+
38
+ from ._workflow import CronTriggerWorkflow
19
39
 
20
40
  logger = get_logger(__name__)
21
41
 
42
+ register_temporal_plugin(SimplePlugin(name="cron-scheduler", workflows=[CronTriggerWorkflow]))
43
+ register_canary_trigger_type("cronScheduler", "com.machinaos.cron.tick")
44
+
22
45
 
23
46
  def _calculate_wait_seconds(p: Dict[str, Any]) -> int:
24
47
  frequency = p.get("frequency", "minutes")
@@ -79,30 +102,45 @@ def _get_schedule_description(p: Dict[str, Any]) -> str:
79
102
 
80
103
 
81
104
  class CronSchedulerParams(BaseModel):
82
- frequency: Literal[
83
- "seconds", "minutes", "hours", "days", "weeks", "months", "once"
84
- ] = Field(
105
+ frequency: Literal["seconds", "minutes", "hours", "days", "weeks", "months", "once"] = Field(
85
106
  default="minutes",
86
107
  description="How often the schedule fires",
87
108
  )
88
109
  interval: int = Field(
89
- default=30, ge=5, le=59,
110
+ default=30,
111
+ ge=5,
112
+ le=59,
90
113
  description="Seconds between fires (5-59)",
91
114
  json_schema_extra={"displayOptions": {"show": {"frequency": ["seconds"]}}},
92
115
  )
93
116
  interval_minutes: int = Field(
94
- default=5, ge=1, le=59,
117
+ default=5,
118
+ ge=1,
119
+ le=59,
95
120
  description="Minutes between fires (1-59)",
96
121
  json_schema_extra={"displayOptions": {"show": {"frequency": ["minutes"]}}},
97
122
  )
98
123
  interval_hours: int = Field(
99
- default=1, ge=1, le=23,
124
+ default=1,
125
+ ge=1,
126
+ le=23,
100
127
  description="Hours between fires (1-23)",
101
128
  json_schema_extra={"displayOptions": {"show": {"frequency": ["hours"]}}},
102
129
  )
103
130
  daily_time: Literal[
104
- "00:00", "02:00", "04:00", "06:00", "08:00", "09:00",
105
- "10:00", "12:00", "14:00", "16:00", "18:00", "20:00", "22:00",
131
+ "00:00",
132
+ "02:00",
133
+ "04:00",
134
+ "06:00",
135
+ "08:00",
136
+ "09:00",
137
+ "10:00",
138
+ "12:00",
139
+ "14:00",
140
+ "16:00",
141
+ "18:00",
142
+ "20:00",
143
+ "22:00",
106
144
  ] = Field(
107
145
  default="09:00",
108
146
  description="Time of day (HH:MM) for daily schedule",
@@ -114,17 +152,54 @@ class CronSchedulerParams(BaseModel):
114
152
  json_schema_extra={"displayOptions": {"show": {"frequency": ["weeks"]}}},
115
153
  )
116
154
  weekly_time: Literal[
117
- "00:00", "02:00", "04:00", "06:00", "08:00", "09:00",
118
- "10:00", "12:00", "14:00", "16:00", "18:00", "20:00", "22:00",
155
+ "00:00",
156
+ "02:00",
157
+ "04:00",
158
+ "06:00",
159
+ "08:00",
160
+ "09:00",
161
+ "10:00",
162
+ "12:00",
163
+ "14:00",
164
+ "16:00",
165
+ "18:00",
166
+ "20:00",
167
+ "22:00",
119
168
  ] = Field(
120
169
  default="09:00",
121
170
  description="Time of day for weekly schedule",
122
171
  json_schema_extra={"displayOptions": {"show": {"frequency": ["weeks"]}}},
123
172
  )
124
173
  month_day: Literal[
125
- "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
126
- "11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
127
- "21", "22", "23", "24", "25", "26", "27", "28", "L",
174
+ "1",
175
+ "2",
176
+ "3",
177
+ "4",
178
+ "5",
179
+ "6",
180
+ "7",
181
+ "8",
182
+ "9",
183
+ "10",
184
+ "11",
185
+ "12",
186
+ "13",
187
+ "14",
188
+ "15",
189
+ "16",
190
+ "17",
191
+ "18",
192
+ "19",
193
+ "20",
194
+ "21",
195
+ "22",
196
+ "23",
197
+ "24",
198
+ "25",
199
+ "26",
200
+ "27",
201
+ "28",
202
+ "L",
128
203
  ] = Field(
129
204
  default="1",
130
205
  description="Day of month (1-28, or 'L' for last day)",
@@ -171,10 +246,9 @@ class CronSchedulerNode(ActionNode):
171
246
  group = ("scheduler", "trigger", "tool")
172
247
  description = "Cron expression-based scheduling trigger"
173
248
  component_kind = "trigger"
174
- handles = (
175
- {"name": "output-main", "kind": "output", "position": "right",
176
- "label": "Output", "role": "main"},
177
- )
249
+ tool_name = "cron_scheduler"
250
+ tool_description = "Schedule a delayed or recurring execution. Supports seconds, minutes, hours, daily, weekly, monthly frequencies with timezone. Use frequency to set schedule type, then set the relevant interval/time parameters."
251
+ handles = ({"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},)
178
252
  annotations = {"destructive": False, "readonly": True, "open_world": False}
179
253
  task_queue = TaskQueue.TRIGGERS_POLL
180
254
  usable_as_tool = True
@@ -198,7 +272,8 @@ class CronSchedulerNode(ActionNode):
198
272
  trigger_time = now + timedelta(seconds=wait_seconds)
199
273
 
200
274
  await get_status_broadcaster().update_node_status(
201
- ctx.node_id, "waiting",
275
+ ctx.node_id,
276
+ "waiting",
202
277
  {
203
278
  "message": f"Waiting {schedule_desc}...",
204
279
  "trigger_time": trigger_time.isoformat(),
@@ -209,7 +284,8 @@ class CronSchedulerNode(ActionNode):
209
284
 
210
285
  logger.info(
211
286
  f"[CronScheduler] Waiting {wait_seconds}s for trigger",
212
- node_id=ctx.node_id, trigger_time=trigger_time.isoformat(),
287
+ node_id=ctx.node_id,
288
+ trigger_time=trigger_time.isoformat(),
213
289
  )
214
290
 
215
291
  try:
@@ -232,8 +308,5 @@ class CronSchedulerNode(ActionNode):
232
308
  output.message = f"Triggered after waiting {_format_wait_time(wait_seconds)}"
233
309
  else:
234
310
  output.next_run = schedule_desc
235
- output.message = (
236
- f"Triggered after {_format_wait_time(wait_seconds)}, "
237
- f"will repeat: {schedule_desc}"
238
- )
311
+ output.message = f"Triggered after {_format_wait_time(wait_seconds)}, " f"will repeat: {schedule_desc}"
239
312
  return output
@@ -0,0 +1,155 @@
1
+ """Wave 12 C3: per-firing Temporal workflow for the cron trigger.
2
+
3
+ Plugin-owned per RFC §6.1 — the cron-specific workflow lives in the
4
+ cron_scheduler plugin folder, not at the framework level. The plugin's
5
+ ``__init__.py`` publishes the class via
6
+ :func:`services.temporal.workflow_registry.register_temporal_workflow`;
7
+ the Temporal worker collects it on startup.
8
+
9
+ How it fits with the Temporal Schedule
10
+ --------------------------------------
11
+
12
+ Wave 12 C3 replaces APScheduler-driven cron with a Temporal Schedule
13
+ (``client.create_schedule``). The Schedule's action is
14
+ ``ScheduleActionStartWorkflow`` targeting THIS class. Each firing
15
+ (per the cron expression) starts one :class:`CronTriggerWorkflow`
16
+ run; the run spawns a child :class:`MachinaWorkflow` with the cron
17
+ trigger node pre-executed, then exits. ``parent_close_policy=ABANDON``
18
+ keeps the spawned MachinaWorkflow alive after this workflow returns.
19
+
20
+ Why we need a separate workflow (vs the Schedule starting MachinaWorkflow
21
+ directly): Schedule action args are **frozen at create time**. Per-tick
22
+ data (firing timestamp) must be computed inside a workflow. This thin
23
+ shim does exactly that and nothing more.
24
+
25
+ Refs:
26
+ - https://docs.temporal.io/develop/python/schedules
27
+ - https://docs.temporal.io/encyclopedia/scheduled-execution
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ from datetime import timedelta
33
+ from typing import Any, Dict
34
+
35
+ from temporalio import workflow
36
+ from temporalio.common import WorkflowIDReusePolicy
37
+ from temporalio.workflow import ParentClosePolicy
38
+
39
+
40
+ @workflow.defn(name="CronTriggerWorkflow", sandboxed=False)
41
+ class CronTriggerWorkflow:
42
+ """One-shot per-firing workflow that spawns a child MachinaWorkflow.
43
+
44
+ Determinism note: the only mutable state is the firing-time
45
+ timestamp from ``workflow.now()`` (deterministic per run);
46
+ everything else is computed from the static action args.
47
+ """
48
+
49
+ @workflow.run
50
+ async def run(self, listener_data: Dict[str, Any]) -> Dict[str, Any]:
51
+ """Spawn one MachinaWorkflow child per cron firing.
52
+
53
+ ``listener_data`` shape (deployment-supplied, frozen at
54
+ schedule creation)::
55
+
56
+ {
57
+ "workflow_id": str, # MachinaOs deployment workflow_id
58
+ "trigger_node_id": str, # cron node id
59
+ "node_type": "cronScheduler",
60
+ "cron_expression": str, # raw crontab string
61
+ "frequency": str, # human-readable bucket
62
+ "timezone": str, # IANA tz name
63
+ "schedule": str, # human-readable description
64
+ "filter_params": Dict, # plugin params
65
+ "nodes": List[Dict], # full deployment graph snapshot
66
+ "edges": List[Dict],
67
+ "session_id": str,
68
+ "tenant_id": Optional[str],
69
+ }
70
+
71
+ Returns ``{spawned_child_id, timestamp}`` for the schedule's
72
+ per-firing history visibility.
73
+ """
74
+ trigger_output = _build_trigger_output(listener_data)
75
+
76
+ # Reuse the listener filter-graph helper so cron / push / poll
77
+ # canary paths share identical n8n stop-at-trigger / config-node /
78
+ # toolkit / agent-tool semantics — single source of truth.
79
+ from services.temporal.trigger_listener_workflow import _build_run_graph
80
+
81
+ trigger_node_id = listener_data["trigger_node_id"]
82
+ nodes = listener_data["nodes"]
83
+ edges = listener_data["edges"]
84
+ session_id = listener_data.get("session_id", "default")
85
+ deployment_workflow_id = listener_data.get("workflow_id")
86
+ tenant_id = listener_data.get("tenant_id")
87
+
88
+ filtered_nodes, filtered_edges = _build_run_graph(
89
+ trigger_node_id=trigger_node_id,
90
+ trigger_output=trigger_output,
91
+ nodes=nodes,
92
+ edges=edges,
93
+ )
94
+
95
+ # Schedule fires multiple times; the firing-time component in
96
+ # the child workflow id makes each tick unique.
97
+ # WorkflowIDReusePolicy.ALLOW_DUPLICATE_FAILED_ONLY guards
98
+ # against a duplicate at the same instant (Temporal retry of
99
+ # the schedule action) double-spawning a successful run.
100
+ firing_iso = trigger_output["timestamp"]
101
+ child_id = f"cron-{deployment_workflow_id}-{trigger_node_id}-{firing_iso}"
102
+
103
+ await workflow.start_child_workflow(
104
+ "MachinaWorkflow",
105
+ args=[
106
+ {
107
+ "nodes": filtered_nodes,
108
+ "edges": filtered_edges,
109
+ "session_id": session_id,
110
+ "workflow_id": deployment_workflow_id,
111
+ "tenant_id": tenant_id,
112
+ }
113
+ ],
114
+ id=child_id,
115
+ parent_close_policy=ParentClosePolicy.ABANDON,
116
+ id_reuse_policy=WorkflowIDReusePolicy.ALLOW_DUPLICATE_FAILED_ONLY,
117
+ execution_timeout=timedelta(hours=1),
118
+ run_timeout=timedelta(hours=1),
119
+ )
120
+
121
+ workflow.logger.info(f"CronTriggerWorkflow spawned child run: child_id={child_id} " f"timestamp={firing_iso}")
122
+
123
+ return {
124
+ "spawned_child_id": child_id,
125
+ "timestamp": firing_iso,
126
+ }
127
+
128
+
129
+ def _build_trigger_output(listener_data: Dict[str, Any]) -> Dict[str, Any]:
130
+ """Construct the cron trigger's output payload for one firing.
131
+
132
+ Shape matches the pre-Wave-12 APScheduler tick callback in
133
+ ``DeploymentManager._setup_cron_trigger.on_tick`` so downstream
134
+ nodes that read ``{{cronTrigger.timestamp}}`` etc. keep working.
135
+
136
+ **Iteration counter trade-off**: APScheduler kept an in-memory
137
+ ``self._cron_iterations[node_id]`` that incremented per firing.
138
+ Temporal Schedules don't expose a built-in firing counter and
139
+ persisting one would require either a long-lived workflow (we'd
140
+ lose the one-shot simplicity) or DB writes on the hot path.
141
+ The canary intentionally sets ``iteration`` to ``None`` —
142
+ downstream nodes that need monotonic iteration can switch to the
143
+ firing ``timestamp`` (deterministic per run, sortable).
144
+ """
145
+ return {
146
+ "timestamp": workflow.now().isoformat(),
147
+ "iteration": None,
148
+ "frequency": listener_data.get("frequency"),
149
+ "timezone": listener_data.get("timezone"),
150
+ "schedule": listener_data.get("schedule"),
151
+ "cron_expression": listener_data.get("cron_expression"),
152
+ }
153
+
154
+
155
+ __all__ = ["CronTriggerWorkflow"]
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#ffb86c"
3
+ }
@@ -34,11 +34,11 @@ class TimerNode(ActionNode):
34
34
  group = ("scheduler",)
35
35
  description = "Timer-based trigger with configurable delay"
36
36
  component_kind = "square" # has input handle
37
+ tool_name = "timer"
38
+ tool_description = "Wait/sleep for a specified duration. Specify duration (1-3600) and unit (seconds, minutes, or hours). Returns timestamp and elapsed time after waiting."
37
39
  handles = (
38
- {"name": "input-main", "kind": "input", "position": "left",
39
- "label": "Input", "role": "main"},
40
- {"name": "output-main", "kind": "output", "position": "right",
41
- "label": "Output", "role": "main"},
40
+ {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
41
+ {"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
42
42
  )
43
43
  annotations = {"destructive": False, "readonly": True, "open_world": False}
44
44
  task_queue = TaskQueue.DEFAULT
@@ -68,7 +68,8 @@ class TimerNode(ActionNode):
68
68
 
69
69
  complete_time = datetime.now() + timedelta(seconds=wait_seconds)
70
70
  await get_status_broadcaster().update_node_status(
71
- ctx.node_id, "waiting",
71
+ ctx.node_id,
72
+ "waiting",
72
73
  {
73
74
  "message": f"Waiting {duration} {unit}...",
74
75
  "complete_time": complete_time.isoformat(),
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#ffb86c"
3
+ }
@@ -13,7 +13,6 @@ class ApifyCredential(ApiKeyCredential):
13
13
  id = "apify"
14
14
  display_name = "Apify"
15
15
  category = "Scrapers"
16
- icon = "asset:apify"
17
16
  key_name = "Authorization"
18
17
  key_location = "bearer"
19
18
  docs_url = "https://docs.apify.com/api/v2"