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
@@ -0,0 +1,167 @@
1
+ """Wave 12 B3: CloudEvents factories + broadcaster wrappers for telegram.
2
+
3
+ Plugin-specific event emission — replaces:
4
+ - ``broadcaster.update_telegram_status(...)`` call inside the
5
+ telegram service's ``_broadcast_status`` method
6
+ - ``event_waiter.dispatch("telegram_message_received", event_data)``
7
+ inside the message-receive handler
8
+
9
+ After B3 every telegram wire frame originates from one wrapper here —
10
+ single source of truth for shape. The cross-plugin
11
+ ``_emit_connection_typed`` helper on ``StatusBroadcaster`` retires in
12
+ the same commit since android (B1) + whatsapp (B2) + telegram (B3) are
13
+ the only callers.
14
+
15
+ Per RFC plugin_authoring_rfc.md §6.4: plugin-specific factories live in
16
+ the plugin folder.
17
+
18
+ Wire format (Wave 12 D4 — legacy ``telegram_status`` raw frame retired):
19
+ - Status: typed CloudEvent on ``plugin_connection_status`` (FE routes
20
+ by ``envelope.source``).
21
+ - Message: typed CloudEvent dispatched to ``event_waiter`` so
22
+ ``telegramReceive`` trigger nodes match it; legacy wire key
23
+ ``telegram_message_received`` preserved for FE.
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import time
29
+ from typing import Any, Dict, Mapping, Optional
30
+
31
+ from services.events.envelope import WorkflowEvent
32
+
33
+
34
+ # ---- Wire-routing keys -----------------------------------------------------
35
+
36
+ _STATUS_TYPED_WIRE_KEY = "plugin_connection_status"
37
+
38
+ # Legacy event_type the event_waiter dispatches by; trigger nodes
39
+ # subscribe on this string. Keep until Phase B11 FE migration.
40
+ _MESSAGE_LEGACY_EVENT_TYPE = "telegram_message_received"
41
+
42
+
43
+ # ---- Typed factories (plugin-specific per RFC §6.4) ------------------------
44
+
45
+
46
+ def telegram_connection_status(
47
+ *,
48
+ connected: bool,
49
+ bot_id: Optional[int] = None,
50
+ bot_username: Optional[str] = None,
51
+ bot_name: Optional[str] = None,
52
+ owner_chat_id: Optional[int] = None,
53
+ has_stored_token: Optional[bool] = None,
54
+ ) -> WorkflowEvent:
55
+ """Bot connection-state envelope. ``subject`` is the bot username
56
+ so the FE can route per-bot updates.
57
+
58
+ ``has_stored_token`` distinguishes "not connected, no token stored"
59
+ (user hasn't added a token yet) from "not connected, token stored
60
+ but bot offline" (network failure / token revoked). Used by the
61
+ auto-reconnect refresh callback (see :mod:`._refresh`).
62
+ """
63
+ data: Dict[str, Any] = {
64
+ "connected": connected,
65
+ "bot_id": bot_id,
66
+ "bot_username": bot_username,
67
+ "bot_name": bot_name,
68
+ "owner_chat_id": owner_chat_id,
69
+ }
70
+ if has_stored_token is not None:
71
+ data["has_stored_token"] = has_stored_token
72
+ return WorkflowEvent(
73
+ source="machinaos://nodes/telegram",
74
+ type=("com.machinaos.telegram.connection.opened" if connected else "com.machinaos.telegram.connection.closed"),
75
+ subject=bot_username,
76
+ data=data,
77
+ )
78
+
79
+
80
+ def telegram_message_received(event_data: Mapping[str, Any]) -> WorkflowEvent:
81
+ """Incoming Telegram message envelope. ``subject`` is the chat_id
82
+ (cast to str — Telegram chat IDs are numeric, the envelope spec
83
+ requires a string subject)."""
84
+ payload = dict(event_data)
85
+ chat_id = payload.get("chat_id")
86
+ return WorkflowEvent(
87
+ source="machinaos://nodes/telegram",
88
+ type="com.machinaos.telegram.message.received",
89
+ subject=str(chat_id) if chat_id is not None else None,
90
+ data=payload,
91
+ )
92
+
93
+
94
+ # ---- Broadcaster wrappers --------------------------------------------------
95
+
96
+
97
+ async def broadcast_telegram_status(
98
+ *,
99
+ connected: bool,
100
+ bot_id: Optional[int] = None,
101
+ bot_username: Optional[str] = None,
102
+ bot_name: Optional[str] = None,
103
+ owner_chat_id: Optional[int] = None,
104
+ has_stored_token: Optional[bool] = None,
105
+ ) -> None:
106
+ """Update the telegram status cache + emit the typed
107
+ ``plugin_connection_status`` CloudEvents envelope.
108
+
109
+ Replaces ``StatusBroadcaster.update_telegram_status``. Legacy raw
110
+ ``telegram_status`` frame retired in Wave 12 D4 — FE consumes via
111
+ the envelope-aware ``plugin_connection_status`` case.
112
+ """
113
+ from services.status_broadcaster import get_status_broadcaster
114
+
115
+ broadcaster = get_status_broadcaster()
116
+
117
+ payload: Dict[str, Any] = {
118
+ "connected": connected,
119
+ "bot_id": bot_id,
120
+ "bot_username": bot_username,
121
+ "bot_name": bot_name,
122
+ "owner_chat_id": owner_chat_id,
123
+ "timestamp": time.time(),
124
+ }
125
+ if has_stored_token is not None:
126
+ payload["has_stored_token"] = has_stored_token
127
+ broadcaster._status["telegram"] = payload
128
+
129
+ event = telegram_connection_status(
130
+ connected=connected,
131
+ bot_id=bot_id,
132
+ bot_username=bot_username,
133
+ bot_name=bot_name,
134
+ owner_chat_id=owner_chat_id,
135
+ has_stored_token=has_stored_token,
136
+ )
137
+ await broadcaster.broadcast(
138
+ {
139
+ "type": _STATUS_TYPED_WIRE_KEY,
140
+ "data": event.model_dump(mode="json"),
141
+ }
142
+ )
143
+
144
+
145
+ async def dispatch_telegram_message_received(event_data: Mapping[str, Any]) -> None:
146
+ """Dispatch an incoming Telegram message via the canary CloudEvents path.
147
+
148
+ Single delivery: :func:`services.events.dispatch.emit` Signals running
149
+ :class:`TriggerListenerWorkflow` consumers via Temporal Visibility AND
150
+ broadcasts the envelope to FE on the ``telegram_message_received``
151
+ wire key. telegramReceive is canary-registered so no legacy
152
+ ``event_waiter`` waiter is ever registered for it.
153
+ """
154
+ from services.events.dispatch import emit
155
+
156
+ await emit(
157
+ telegram_message_received(dict(event_data)),
158
+ wire_routing_key=_MESSAGE_LEGACY_EVENT_TYPE,
159
+ )
160
+
161
+
162
+ __all__ = [
163
+ "broadcast_telegram_status",
164
+ "dispatch_telegram_message_received",
165
+ "telegram_connection_status",
166
+ "telegram_message_received",
167
+ ]
@@ -55,16 +55,11 @@ def build_telegram_filter(params: Dict) -> Callable[[Dict], bool]:
55
55
  content_type_filter = params.get("content_type_filter", "all")
56
56
  chat_id_filter = params.get("chat_id", "")
57
57
  from_user_filter = params.get("from_user", "")
58
- keywords = [
59
- k.strip().lower() for k in params.get("keywords", "").split(",") if k.strip()
60
- ]
58
+ keywords = [k.strip().lower() for k in params.get("keywords", "").split(",") if k.strip()]
61
59
  ignore_bots = params.get("ignore_bots", True)
62
60
  owner_chat_id = params.get("_owner_chat_id")
63
61
 
64
- logger.debug(
65
- f"[TelegramFilter] Built: sender={sender_filter}, "
66
- f"content_type={content_type_filter}, owner_chat_id={owner_chat_id}"
67
- )
62
+ logger.debug(f"[TelegramFilter] Built: sender={sender_filter}, " f"content_type={content_type_filter}, owner_chat_id={owner_chat_id}")
68
63
 
69
64
  def _get_owner_chat_id() -> object:
70
65
  """Lazy lookup from the local service -- handles owner detected
@@ -113,10 +108,7 @@ def build_telegram_filter(params: Dict) -> Callable[[Dict], bool]:
113
108
  if sender_filter != "self" and ignore_bots and m.get("is_bot", False):
114
109
  return False
115
110
 
116
- logger.debug(
117
- f"[TelegramFilter] Matched message from "
118
- f"{m.get('from_username', m.get('from_id'))}"
119
- )
111
+ logger.debug(f"[TelegramFilter] Matched message from " f"{m.get('from_username', m.get('from_id'))}")
120
112
  return True
121
113
 
122
114
  return matches
@@ -38,7 +38,9 @@ def _send_text(svc, data, parse_mode):
38
38
  if not text:
39
39
  return None, "text required for text message"
40
40
  return svc.send_message(
41
- chat_id=data["chat_id"], text=text, parse_mode=parse_mode,
41
+ chat_id=data["chat_id"],
42
+ text=text,
43
+ parse_mode=parse_mode,
42
44
  ), None
43
45
 
44
46
 
@@ -47,8 +49,10 @@ def _send_photo(svc, data, parse_mode):
47
49
  if not photo_url:
48
50
  return None, "media_url required for photo"
49
51
  return svc.send_photo(
50
- chat_id=data["chat_id"], photo=photo_url,
51
- caption=data.get("caption"), parse_mode=parse_mode,
52
+ chat_id=data["chat_id"],
53
+ photo=photo_url,
54
+ caption=data.get("caption"),
55
+ parse_mode=parse_mode,
52
56
  ), None
53
57
 
54
58
 
@@ -57,8 +61,10 @@ def _send_document(svc, data, parse_mode):
57
61
  if not doc_url:
58
62
  return None, "media_url required for document"
59
63
  return svc.send_document(
60
- chat_id=data["chat_id"], document=doc_url,
61
- caption=data.get("caption"), parse_mode=parse_mode,
64
+ chat_id=data["chat_id"],
65
+ document=doc_url,
66
+ caption=data.get("caption"),
67
+ parse_mode=parse_mode,
62
68
  ), None
63
69
 
64
70
 
@@ -67,7 +73,9 @@ def _send_location(svc, data, parse_mode):
67
73
  if lat is None or lon is None:
68
74
  return None, "latitude and longitude required"
69
75
  return svc.send_location(
70
- chat_id=data["chat_id"], latitude=float(lat), longitude=float(lon),
76
+ chat_id=data["chat_id"],
77
+ latitude=float(lat),
78
+ longitude=float(lon),
71
79
  ), None
72
80
 
73
81
 
@@ -76,7 +84,9 @@ def _send_contact(svc, data, parse_mode):
76
84
  if not phone or not first_name:
77
85
  return None, "phone_number and first_name required"
78
86
  return svc.send_contact(
79
- chat_id=data["chat_id"], phone_number=phone, first_name=first_name,
87
+ chat_id=data["chat_id"],
88
+ phone_number=phone,
89
+ first_name=first_name,
80
90
  last_name=data.get("last_name"),
81
91
  ), None
82
92
 
@@ -15,7 +15,7 @@ into the broadcaster cache.
15
15
  from __future__ import annotations
16
16
 
17
17
  import logging
18
- from typing import Any, Dict, TYPE_CHECKING
18
+ from typing import Dict, TYPE_CHECKING
19
19
 
20
20
  from opentelemetry import trace
21
21
 
@@ -32,55 +32,49 @@ async def refresh_telegram_status(broadcaster: "StatusBroadcaster") -> None:
32
32
  Called once per ``_refresh_all_services`` cycle. OTel span emitted
33
33
  so cold-start ``getMe`` time is observable -- the historical
34
34
  bottleneck on local DNS for the first WebSocket connect.
35
+
36
+ Wave 12 B3: routes through plugin _events.py wrapper. Cache write
37
+ + dual-emit (legacy raw + typed sibling) all in one call.
35
38
  """
36
39
  with tracer.start_as_current_span("broadcaster.refresh_telegram") as span:
37
40
  try:
41
+ from ._events import broadcast_telegram_status
38
42
  from ._service import get_telegram_service
39
43
 
40
44
  service = get_telegram_service()
41
45
 
42
- def _snapshot(connected: bool, has_token: bool) -> Dict[str, Any]:
43
- s = service.get_status()
44
- return {
45
- "connected": connected,
46
- "bot_id": s.get("bot_id") if connected else None,
47
- "bot_username": s.get("bot_username") if connected else None,
48
- "bot_name": s.get("bot_name") if connected else None,
49
- "owner_chat_id": s.get("owner_chat_id") if connected else None,
50
- "has_stored_token": has_token,
51
- }
46
+ async def _emit(connected: bool, has_token: bool) -> None:
47
+ """Snapshot service state and broadcast (cache write + WS)."""
48
+ s = service.get_status() if connected else {}
49
+ await broadcast_telegram_status(
50
+ connected=connected,
51
+ bot_id=s.get("bot_id") if connected else None,
52
+ bot_username=s.get("bot_username") if connected else None,
53
+ bot_name=s.get("bot_name") if connected else None,
54
+ owner_chat_id=s.get("owner_chat_id") if connected else None,
55
+ has_stored_token=has_token,
56
+ )
52
57
 
53
58
  if service.connected:
54
- broadcaster._status["telegram"] = _snapshot(True, True)
59
+ await _emit(True, True)
55
60
  span.set_attribute("path", "already_connected")
56
61
  elif not await service.has_stored_token():
57
- broadcaster._status["telegram"] = _snapshot(False, False)
62
+ await _emit(False, False)
58
63
  span.set_attribute("path", "no_token")
59
64
  else:
60
65
  span.set_attribute("path", "auto_reconnect")
61
66
  logger.info("[StatusBroadcaster] Auto-reconnecting Telegram bot...")
62
67
  result = await service.connect()
63
68
  ok = bool(result.get("success"))
64
- broadcaster._status["telegram"] = _snapshot(ok, True)
69
+ await _emit(ok, True)
65
70
  span.set_attribute("reconnect_ok", ok)
66
71
  if ok:
67
72
  bot_username = broadcaster._status["telegram"].get("bot_username")
68
- logger.info(
69
- f"[StatusBroadcaster] Telegram auto-reconnected: @{bot_username}"
70
- )
73
+ logger.info(f"[StatusBroadcaster] Telegram auto-reconnected: @{bot_username}")
71
74
  else:
72
- logger.warning(
73
- f"[StatusBroadcaster] Telegram auto-reconnect failed: "
74
- f"{result.get('error')}"
75
- )
76
-
77
- await broadcaster.broadcast({
78
- "type": "telegram_status",
79
- "data": broadcaster._status["telegram"],
80
- })
81
- span.set_attribute(
82
- "connected", bool(broadcaster._status["telegram"]["connected"])
83
- )
75
+ logger.warning(f"[StatusBroadcaster] Telegram auto-reconnect failed: " f"{result.get('error')}")
76
+
77
+ span.set_attribute("connected", bool(broadcaster._status["telegram"]["connected"]))
84
78
  except Exception as e:
85
79
  span.record_exception(e)
86
80
  logger.debug(f"[StatusBroadcaster] Could not refresh Telegram status: {e}")
@@ -98,9 +92,5 @@ async def precheck_telegram_trigger(parameters: Dict) -> str | None:
98
92
  if not service.connected:
99
93
  return "Telegram bot not connected. Add bot token in Credentials."
100
94
  sender_filter = parameters.get("sender_filter", "all")
101
- logger.info(
102
- "[TelegramTrigger] starting "
103
- f"sender_filter={sender_filter} "
104
- f"owner_detected={service.owner_chat_id is not None}"
105
- )
95
+ logger.info("[TelegramTrigger] starting " f"sender_filter={sender_filter} " f"owner_detected={service.owner_chat_id is not None}")
106
96
  return None
@@ -30,7 +30,7 @@ Public surface (consumed by `_handlers.py`, `telegram_send.py`,
30
30
  handlers.
31
31
 
32
32
  Auth lookups go through :class:`TelegramCredential.resolve` (lifted from
33
- the per-key ``auth.get_api_key("telegram_bot_token")`` / ``..._owner_chat_id``
33
+ the per-key ``auth.get_api_key("telegram")`` / ``..._owner_chat_id``
34
34
  calls scattered across the previous handler/router code). The credential
35
35
  class stays declarative — :class:`ApiKeyCredential` does the heavy lifting,
36
36
  this service just consumes the resolved dict.
@@ -165,7 +165,7 @@ class TelegramService(ServiceSingleton):
165
165
  # =========================================================================
166
166
 
167
167
  async def has_stored_token(self) -> bool:
168
- """Whether `telegram_bot_token` is persisted in auth credentials."""
168
+ """Whether the `telegram` bot-token credential is persisted in auth."""
169
169
  try:
170
170
  secrets = await TelegramCredential.resolve()
171
171
  return bool(secrets.get("api_key"))
@@ -175,17 +175,16 @@ class TelegramService(ServiceSingleton):
175
175
  async def connect(self, token: Optional[str] = None) -> Dict[str, Any]:
176
176
  """Connect to Telegram with bot token and start polling.
177
177
 
178
- When ``token`` is omitted, falls back to the stored
179
- ``telegram_bot_token`` credential — matches the Twitter/Google
180
- OAuth pattern where the frontend saves credentials first and then
181
- calls connect.
178
+ When ``token`` is omitted, falls back to the stored ``telegram``
179
+ bot-token credential — matches the Twitter/Google OAuth pattern
180
+ where the frontend saves credentials first and then calls connect.
182
181
 
183
182
  Idempotent: if already connected, returns success without tearing
184
183
  down the working bot. See the in-line comment block for the race
185
184
  this guards against.
186
185
  """
187
186
  # Resolve credentials via the declarative class instead of raw
188
- # ``auth.get_api_key("telegram_bot_token")`` / ``..._owner_chat_id``
187
+ # ``auth.get_api_key("telegram")`` / ``..._owner_chat_id``
189
188
  # lookups. Keeps the credential id in one place.
190
189
  secrets: Dict[str, Any] = {}
191
190
  if not token:
@@ -204,15 +203,12 @@ class TelegramService(ServiceSingleton):
204
203
  # tasks fired on overlapping WebSocket connects.
205
204
  if self._connected:
206
205
  logger.debug(
207
- "[Telegram] connect() called while already connected to "
208
- f"@{self._bot_info.get('username')}, returning success",
206
+ "[Telegram] connect() called while already connected to " f"@{self._bot_info.get('username')}, returning success",
209
207
  )
210
208
  return {
211
209
  "success": True,
212
210
  "bot": self._bot_info,
213
- "message": (
214
- f"Already connected to @{self._bot_info.get('username')}"
215
- ),
211
+ "message": (f"Already connected to @{self._bot_info.get('username')}"),
216
212
  }
217
213
 
218
214
  try:
@@ -241,9 +237,7 @@ class TelegramService(ServiceSingleton):
241
237
  )
242
238
  self._bot = self._application.bot
243
239
  self._token = token
244
- self._application.add_handler(
245
- MessageHandler(filters.ALL, self._on_message_received)
246
- )
240
+ self._application.add_handler(MessageHandler(filters.ALL, self._on_message_received))
247
241
 
248
242
  await self._application.initialize()
249
243
 
@@ -265,9 +259,7 @@ class TelegramService(ServiceSingleton):
265
259
  saved_owner = secrets.get("telegram_owner_chat_id")
266
260
  if saved_owner is None:
267
261
  try:
268
- saved_owner = (await TelegramCredential.resolve()).get(
269
- "telegram_owner_chat_id"
270
- )
262
+ saved_owner = (await TelegramCredential.resolve()).get("telegram_owner_chat_id")
271
263
  except PermissionError:
272
264
  saved_owner = None
273
265
  if saved_owner:
@@ -411,6 +403,7 @@ class TelegramService(ServiceSingleton):
411
403
  captured_id = m.from_user.id
412
404
  try:
413
405
  from services.plugin.deps import get_auth_service
406
+
414
407
  await get_auth_service().store_api_key(
415
408
  "telegram_owner_chat_id",
416
409
  str(captured_id),
@@ -425,10 +418,7 @@ class TelegramService(ServiceSingleton):
425
418
  )
426
419
  return
427
420
  self._owner_chat_id = captured_id
428
- logger.info(
429
- f"[Telegram] Owner retroactively captured from pending "
430
- f"updates: @{m.from_user.username} (ID: {captured_id})"
431
- )
421
+ logger.info(f"[Telegram] Owner retroactively captured from pending " f"updates: @{m.from_user.username} (ID: {captured_id})")
432
422
  return
433
423
 
434
424
  async def _on_message_received(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -449,15 +439,12 @@ class TelegramService(ServiceSingleton):
449
439
  # what went wrong. The new order preserves the invariant
450
440
  # "in-memory has owner => DB has owner" so a restart can
451
441
  # always re-capture from the next inbound private message.
452
- if (
453
- self._owner_chat_id is None
454
- and msg.chat.type == "private"
455
- and msg.from_user
456
- ):
442
+ if self._owner_chat_id is None and msg.chat.type == "private" and msg.from_user:
457
443
  captured_id = msg.from_user.id
458
444
  persist_ok = False
459
445
  try:
460
446
  from services.plugin.deps import get_auth_service
447
+
461
448
  await get_auth_service().store_api_key(
462
449
  "telegram_owner_chat_id",
463
450
  str(captured_id),
@@ -481,10 +468,7 @@ class TelegramService(ServiceSingleton):
481
468
  )
482
469
  if persist_ok:
483
470
  self._owner_chat_id = captured_id
484
- logger.info(
485
- f"[Telegram] Owner detected and persisted: "
486
- f"@{msg.from_user.username} (ID: {captured_id})"
487
- )
471
+ logger.info(f"[Telegram] Owner detected and persisted: " f"@{msg.from_user.username} (ID: {captured_id})")
488
472
  await self._broadcast_status()
489
473
 
490
474
  event_data = self._format_message(msg)
@@ -494,9 +478,11 @@ class TelegramService(ServiceSingleton):
494
478
  f"chat_type={event_data.get('chat_type')}"
495
479
  )
496
480
 
497
- from services import event_waiter
498
- resolved = event_waiter.dispatch("telegram_message_received", event_data)
499
- logger.info(f"[Telegram] Dispatched to {resolved} waiter(s)")
481
+ # Route via plugin _events.py wrapper — canary CloudEvents
482
+ # path (Visibility-query Signal + WS broadcast).
483
+ from . import dispatch_telegram_message_received
484
+
485
+ await dispatch_telegram_message_received(event_data)
500
486
  except Exception as e:
501
487
  logger.error(f"[Telegram] Message handler error: {e}")
502
488
 
@@ -570,9 +556,10 @@ class TelegramService(ServiceSingleton):
570
556
 
571
557
  async def _broadcast_status(self):
572
558
  try:
573
- from services.status_broadcaster import get_status_broadcaster
574
- broadcaster = get_status_broadcaster()
575
- await broadcaster.update_telegram_status(
559
+ # Wave 12 B3: route via plugin _events.py wrapper.
560
+ from . import broadcast_telegram_status
561
+
562
+ await broadcast_telegram_status(
576
563
  connected=self._connected,
577
564
  bot_id=self._bot_info.get("id"),
578
565
  bot_username=self._bot_info.get("username"),
@@ -601,12 +588,11 @@ class TelegramService(ServiceSingleton):
601
588
  if not text:
602
589
  return text, "HTML"
603
590
  from services.markdown_formatter import to_telegram_html
591
+
604
592
  return to_telegram_html(text), "HTML"
605
593
 
606
594
  @classmethod
607
- def _resolve_body(
608
- cls, body: Optional[str], parse_mode: Optional[str]
609
- ) -> tuple[Optional[str], Optional[str]]:
595
+ def _resolve_body(cls, body: Optional[str], parse_mode: Optional[str]) -> tuple[Optional[str], Optional[str]]:
610
596
  """Apply parse-mode preprocessing to a text/caption. Returns
611
597
  ``(body, effective_parse_mode)``."""
612
598
  if parse_mode == "Auto":
@@ -636,10 +622,7 @@ class TelegramService(ServiceSingleton):
636
622
  )
637
623
  except BadRequest as e:
638
624
  if "can't parse entities" in str(e).lower() and effective_pm:
639
- logger.warning(
640
- f"[Telegram] Parse mode {effective_pm} failed for "
641
- f"{method.__name__}, sending as plain text"
642
- )
625
+ logger.warning(f"[Telegram] Parse mode {effective_pm} failed for " f"{method.__name__}, sending as plain text")
643
626
  return await method(
644
627
  **{body_kw: body},
645
628
  parse_mode=None,
@@ -670,7 +653,8 @@ class TelegramService(ServiceSingleton):
670
653
  if len(chunks) > 1:
671
654
  logger.info(
672
655
  "[Telegram] Splitting %d-char message into %d parts",
673
- len(text), len(chunks),
656
+ len(text),
657
+ len(chunks),
674
658
  )
675
659
 
676
660
  first_msg: Any = None
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#0088CC"
3
+ }
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#0088CC">
2
+ <path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/>
3
+ </svg>
@@ -23,15 +23,31 @@ class TelegramReceiveParams(BaseModel):
23
23
  """
24
24
 
25
25
  content_type_filter: Literal[
26
- "all", "text", "photo", "video", "audio", "voice", "document",
27
- "sticker", "location", "contact", "poll",
26
+ "all",
27
+ "text",
28
+ "photo",
29
+ "video",
30
+ "audio",
31
+ "voice",
32
+ "document",
33
+ "sticker",
34
+ "location",
35
+ "contact",
36
+ "poll",
28
37
  ] = Field(
29
38
  default="all",
30
39
  description="Filter by message content type",
31
40
  )
32
41
  sender_filter: Literal[
33
- "all", "self", "private", "group", "supergroup", "channel",
34
- "specific_chat", "specific_user", "keywords",
42
+ "all",
43
+ "self",
44
+ "private",
45
+ "group",
46
+ "supergroup",
47
+ "channel",
48
+ "specific_chat",
49
+ "specific_user",
50
+ "keywords",
35
51
  ] = Field(
36
52
  default="all",
37
53
  description="Filter which messages trigger the workflow",
@@ -61,10 +77,20 @@ class TelegramReceiveParams(BaseModel):
61
77
  default=True,
62
78
  description="Do not trigger on messages from other bots",
63
79
  json_schema_extra={
64
- "displayOptions": {"show": {"sender_filter": [
65
- "all", "private", "group", "supergroup", "channel",
66
- "specific_chat", "specific_user", "keywords",
67
- ]}},
80
+ "displayOptions": {
81
+ "show": {
82
+ "sender_filter": [
83
+ "all",
84
+ "private",
85
+ "group",
86
+ "supergroup",
87
+ "channel",
88
+ "specific_chat",
89
+ "specific_user",
90
+ "keywords",
91
+ ]
92
+ }
93
+ },
68
94
  },
69
95
  )
70
96
 
@@ -100,10 +126,7 @@ class TelegramReceiveNode(TriggerNode):
100
126
  group = ("social", "trigger")
101
127
  description = "Trigger workflow when Telegram message is received"
102
128
  component_kind = "trigger"
103
- handles = (
104
- {"name": "output-main", "kind": "output", "position": "right",
105
- "label": "Output", "role": "main"},
106
- )
129
+ handles = ({"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},)
107
130
  credentials = (TelegramCredential,)
108
131
  task_queue = TaskQueue.TRIGGERS_EVENT
109
132
  mode = "event"
@@ -116,6 +139,7 @@ class TelegramReceiveNode(TriggerNode):
116
139
  # Delegate to legacy filter builder for full feature parity —
117
140
  # 11.F ports the body and removes the legacy registry entry.
118
141
  from services.event_waiter import build_telegram_filter
142
+
119
143
  return build_telegram_filter(params.model_dump())
120
144
 
121
145
  async def execute(
@@ -136,14 +160,10 @@ class TelegramReceiveNode(TriggerNode):
136
160
  if not getattr(svc, "connected", False):
137
161
  return self._wrap_error(
138
162
  start_time=time.time(),
139
- error=(
140
- "Telegram bot not connected. Add bot token in Credentials."
141
- ),
163
+ error=("Telegram bot not connected. Add bot token in Credentials."),
142
164
  )
143
165
  return await super().execute(node_id, parameters, context)
144
166
 
145
167
  @Operation("wait")
146
168
  async def wait(self, ctx: NodeContext, params: TelegramReceiveParams) -> TelegramReceiveOutput:
147
- raise NotImplementedError(
148
- "Event triggers return via TriggerNode.execute, not the op body"
149
- )
169
+ raise NotImplementedError("Event triggers return via TriggerNode.execute, not the op body")