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
@@ -11,7 +11,7 @@ Wraps the XDK SDK with:
11
11
  from __future__ import annotations
12
12
 
13
13
  import asyncio
14
- from typing import Any, Dict, List, Optional
14
+ from typing import Any, Dict, Optional
15
15
 
16
16
  from core.logging import get_logger
17
17
  from services.pricing import get_pricing_service
@@ -25,25 +25,30 @@ def _is_auth_error(e: Exception) -> bool:
25
25
 
26
26
 
27
27
  async def track_twitter_usage(
28
- node_id: str, action: str, resource_count: int, context: Dict[str, Any],
28
+ node_id: str,
29
+ action: str,
30
+ resource_count: int,
31
+ context: Dict[str, Any],
29
32
  ) -> Dict[str, float]:
30
33
  """Record a Twitter API call in ``api_usage_metrics``."""
31
34
  from services.plugin.deps import get_database
32
35
 
33
36
  pricing = get_pricing_service()
34
- cost_data = pricing.calculate_api_cost('twitter', action, resource_count)
37
+ cost_data = pricing.calculate_api_cost("twitter", action, resource_count)
35
38
 
36
39
  db = get_database()
37
- await db.save_api_usage_metric({
38
- 'session_id': context.get('session_id', 'default'),
39
- 'node_id': node_id,
40
- 'workflow_id': context.get('workflow_id'),
41
- 'service': 'twitter',
42
- 'operation': cost_data.get('operation', action),
43
- 'endpoint': action,
44
- 'resource_count': resource_count,
45
- 'cost': cost_data.get('total_cost', 0.0),
46
- })
40
+ await db.save_api_usage_metric(
41
+ {
42
+ "session_id": context.get("session_id", "default"),
43
+ "node_id": node_id,
44
+ "workflow_id": context.get("workflow_id"),
45
+ "service": "twitter",
46
+ "operation": cost_data.get("operation", action),
47
+ "endpoint": action,
48
+ "resource_count": resource_count,
49
+ "cost": cost_data.get("total_cost", 0.0),
50
+ }
51
+ )
47
52
  return cost_data
48
53
 
49
54
 
@@ -118,12 +123,12 @@ async def get_my_user_id(client) -> str:
118
123
 
119
124
 
120
125
  def format_response(response) -> Dict[str, Any]:
121
- if hasattr(response, 'data'):
126
+ if hasattr(response, "data"):
122
127
  data = response.data
123
128
  if isinstance(data, dict):
124
129
  return data
125
- if hasattr(data, '__dict__'):
126
- return {k: v for k, v in data.__dict__.items() if not k.startswith('_')}
130
+ if hasattr(data, "__dict__"):
131
+ return {k: v for k, v in data.__dict__.items() if not k.startswith("_")}
127
132
  return {"data": str(data)}
128
133
  return {"response": str(response)}
129
134
 
@@ -133,6 +138,7 @@ def format_user(user) -> Dict[str, Any]:
133
138
  if isinstance(user, dict):
134
139
  return user.get(attr, default)
135
140
  return getattr(user, attr, default)
141
+
136
142
  return {
137
143
  "id": g("id"),
138
144
  "username": g("username"),
@@ -158,14 +164,14 @@ def format_tweet(
158
164
  def g(obj, key, default=None):
159
165
  return obj.get(key, default) if isinstance(obj, dict) else getattr(obj, key, default)
160
166
 
161
- tweet_id = g(tweet, 'id')
162
- author_id = g(tweet, 'author_id')
163
- text = g(tweet, 'text', '')
167
+ tweet_id = g(tweet, "id")
168
+ author_id = g(tweet, "author_id")
169
+ text = g(tweet, "text", "")
164
170
 
165
- entities = g(tweet, 'entities') or {}
171
+ entities = g(tweet, "entities") or {}
166
172
  if isinstance(entities, dict):
167
- urls_list = entities.get('urls', [])
168
- elif hasattr(entities, 'urls'):
173
+ urls_list = entities.get("urls", [])
174
+ elif hasattr(entities, "urls"):
169
175
  urls_list = entities.urls or []
170
176
  else:
171
177
  urls_list = []
@@ -174,48 +180,56 @@ def format_tweet(
174
180
  display_text = text
175
181
  for u in urls_list:
176
182
  if isinstance(u, dict):
177
- short = u.get('url', ''); expanded = u.get('expanded_url', ''); display = u.get('display_url', '')
183
+ short = u.get("url", "")
184
+ expanded = u.get("expanded_url", "")
185
+ display = u.get("display_url", "")
178
186
  else:
179
- short = getattr(u, 'url', ''); expanded = getattr(u, 'expanded_url', ''); display = getattr(u, 'display_url', '')
187
+ short = getattr(u, "url", "")
188
+ expanded = getattr(u, "expanded_url", "")
189
+ display = getattr(u, "display_url", "")
180
190
  if short and expanded:
181
191
  expanded_urls.append({"url": short, "expanded_url": expanded, "display_url": display})
182
192
  display_text = display_text.replace(short, expanded)
183
193
 
184
- note_tweet = g(tweet, 'note_tweet')
194
+ note_tweet = g(tweet, "note_tweet")
185
195
  if note_tweet:
186
- note_text = note_tweet.get('text', '') if isinstance(note_tweet, dict) else getattr(note_tweet, 'text', '')
196
+ note_text = note_tweet.get("text", "") if isinstance(note_tweet, dict) else getattr(note_tweet, "text", "")
187
197
  if note_text:
188
198
  text = note_text
189
199
  display_text = note_text
190
200
 
191
201
  author_info = users_by_id.get(str(author_id)) if author_id else None
192
202
 
193
- attachments = g(tweet, 'attachments') or {}
203
+ attachments = g(tweet, "attachments") or {}
194
204
  if isinstance(attachments, dict):
195
- media_keys = attachments.get('media_keys', [])
196
- elif hasattr(attachments, 'media_keys'):
205
+ media_keys = attachments.get("media_keys", [])
206
+ elif hasattr(attachments, "media_keys"):
197
207
  media_keys = attachments.media_keys or []
198
208
  else:
199
209
  media_keys = []
200
210
  media_list = [media_by_key[k] for k in media_keys if k in media_by_key]
201
211
 
202
- ref_raw = g(tweet, 'referenced_tweets') or []
212
+ ref_raw = g(tweet, "referenced_tweets") or []
203
213
  referenced = []
204
214
  for ref in ref_raw:
205
215
  if isinstance(ref, dict):
206
- ref_type = ref.get('type', ''); ref_id = ref.get('id', '')
216
+ ref_type = ref.get("type", "")
217
+ ref_id = ref.get("id", "")
207
218
  else:
208
- ref_type = getattr(ref, 'type', ''); ref_id = getattr(ref, 'id', '')
219
+ ref_type = getattr(ref, "type", "")
220
+ ref_id = getattr(ref, "id", "")
209
221
  ref_data = tweets_by_id.get(str(ref_id))
210
- referenced.append({
211
- "type": ref_type,
212
- "id": ref_id,
213
- "text": ref_data.get("text", "") if ref_data else None,
214
- "author_id": ref_data.get("author_id") if ref_data else None,
215
- })
216
-
217
- metrics = g(tweet, 'public_metrics') or {}
218
- if not isinstance(metrics, dict) and hasattr(metrics, 'model_dump'):
222
+ referenced.append(
223
+ {
224
+ "type": ref_type,
225
+ "id": ref_id,
226
+ "text": ref_data.get("text", "") if ref_data else None,
227
+ "author_id": ref_data.get("author_id") if ref_data else None,
228
+ }
229
+ )
230
+
231
+ metrics = g(tweet, "public_metrics") or {}
232
+ if not isinstance(metrics, dict) and hasattr(metrics, "model_dump"):
219
233
  metrics = metrics.model_dump()
220
234
  elif not isinstance(metrics, dict):
221
235
  metrics = {}
@@ -225,12 +239,12 @@ def format_tweet(
225
239
  "text": text,
226
240
  "display_text": display_text,
227
241
  "author_id": author_id,
228
- "created_at": str(g(tweet, 'created_at', '')),
229
- "lang": g(tweet, 'lang'),
230
- "source": g(tweet, 'source'),
231
- "conversation_id": g(tweet, 'conversation_id'),
232
- "in_reply_to_user_id": g(tweet, 'in_reply_to_user_id'),
233
- "possibly_sensitive": g(tweet, 'possibly_sensitive', False),
242
+ "created_at": str(g(tweet, "created_at", "")),
243
+ "lang": g(tweet, "lang"),
244
+ "source": g(tweet, "source"),
245
+ "conversation_id": g(tweet, "conversation_id"),
246
+ "in_reply_to_user_id": g(tweet, "in_reply_to_user_id"),
247
+ "possibly_sensitive": g(tweet, "possibly_sensitive", False),
234
248
  "public_metrics": metrics,
235
249
  }
236
250
  if author_info:
@@ -247,7 +261,7 @@ def format_tweet(
247
261
  def _includes_to_dict(raw) -> Dict[str, Any]:
248
262
  if not raw:
249
263
  return {}
250
- if hasattr(raw, 'model_dump'):
264
+ if hasattr(raw, "model_dump"):
251
265
  try:
252
266
  return raw.model_dump()
253
267
  except Exception:
@@ -260,50 +274,61 @@ def _includes_to_dict(raw) -> Dict[str, Any]:
260
274
  def sync_search_recent(client, query: str, max_results: int) -> Dict[str, Any]:
261
275
  """Run ``posts.search_recent`` synchronously; returns {tweets, includes}."""
262
276
  for page in client.posts.search_recent(
263
- query=query, max_results=max_results,
277
+ query=query,
278
+ max_results=max_results,
264
279
  tweet_fields=[
265
- "author_id", "created_at", "entities", "public_metrics",
266
- "possibly_sensitive", "lang", "source",
267
- "conversation_id", "in_reply_to_user_id", "referenced_tweets",
280
+ "author_id",
281
+ "created_at",
282
+ "entities",
283
+ "public_metrics",
284
+ "possibly_sensitive",
285
+ "lang",
286
+ "source",
287
+ "conversation_id",
288
+ "in_reply_to_user_id",
289
+ "referenced_tweets",
268
290
  "note_tweet",
269
291
  ],
270
292
  expansions=[
271
- "author_id", "attachments.media_keys",
272
- "referenced_tweets.id", "referenced_tweets.id.author_id",
293
+ "author_id",
294
+ "attachments.media_keys",
295
+ "referenced_tweets.id",
296
+ "referenced_tweets.id.author_id",
273
297
  ],
274
298
  media_fields=["url", "preview_image_url", "type", "alt_text", "variants"],
275
299
  user_fields=["username", "name", "profile_image_url"],
276
300
  ):
277
301
  return {
278
- "tweets": getattr(page, 'data', []) or [],
279
- "includes": _includes_to_dict(getattr(page, 'includes', None)),
302
+ "tweets": getattr(page, "data", []) or [],
303
+ "includes": _includes_to_dict(getattr(page, "includes", None)),
280
304
  }
281
305
  return {"tweets": [], "includes": {}}
282
306
 
283
307
 
284
308
  def includes_lookups(includes: Dict[str, Any]):
285
309
  """Build {users_by_id, media_by_key, tweets_by_id} from a search-includes dict."""
310
+
286
311
  def _as_dict(obj):
287
312
  if isinstance(obj, dict):
288
313
  return obj
289
- if hasattr(obj, '__dict__'):
290
- return {k: v for k, v in obj.__dict__.items() if not k.startswith('_')}
314
+ if hasattr(obj, "__dict__"):
315
+ return {k: v for k, v in obj.__dict__.items() if not k.startswith("_")}
291
316
  return {}
292
317
 
293
318
  users_by_id = {}
294
- for u in (includes.get("users") or []):
319
+ for u in includes.get("users") or []:
295
320
  uid = u.get("id") if isinstance(u, dict) else getattr(u, "id", None)
296
321
  if uid:
297
322
  users_by_id[str(uid)] = _as_dict(u)
298
323
 
299
324
  media_by_key = {}
300
- for m in (includes.get("media") or []):
325
+ for m in includes.get("media") or []:
301
326
  mk = m.get("media_key") if isinstance(m, dict) else getattr(m, "media_key", None)
302
327
  if mk:
303
328
  media_by_key[mk] = _as_dict(m)
304
329
 
305
330
  tweets_by_id = {}
306
- for t in (includes.get("tweets") or []):
331
+ for t in includes.get("tweets") or []:
307
332
  tid = t.get("id") if isinstance(t, dict) else getattr(t, "id", None)
308
333
  if tid:
309
334
  tweets_by_id[str(tid)] = _as_dict(t)
@@ -12,7 +12,6 @@ on top; it transparently refreshes on 401/403 via this class.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- from typing import Any, Dict
16
15
 
17
16
  from services.plugin.credential import OAuth2Credential
18
17
 
@@ -21,15 +20,18 @@ class TwitterCredential(OAuth2Credential):
21
20
  id = "twitter"
22
21
  display_name = "Twitter / X"
23
22
  category = "Social"
24
- icon = "asset:x"
25
23
  authorization_url = "https://twitter.com/i/oauth2/authorize"
26
24
  token_url = "https://api.twitter.com/2/oauth2/token"
27
25
  client_id_api_key = "twitter_client_id"
28
26
  client_secret_api_key = "twitter_client_secret"
29
27
  scopes = (
30
- "tweet.read", "tweet.write", "users.read",
31
- "follows.read", "follows.write",
32
- "like.read", "like.write",
28
+ "tweet.read",
29
+ "tweet.write",
30
+ "users.read",
31
+ "follows.read",
32
+ "follows.write",
33
+ "like.read",
34
+ "like.write",
33
35
  "offline.access",
34
36
  )
35
37
  docs_url = "https://developer.x.com/en/docs/authentication/oauth-2-0"
@@ -0,0 +1,101 @@
1
+ """Wave 12: CloudEvents factories + dispatcher for twitter.
2
+
3
+ Plugin-specific event emission for Twitter/X inbound events (mentions,
4
+ search hits, timeline updates, DMs).
5
+
6
+ Per RFC plugin_authoring_rfc.md §6.4: plugin-specific factories live in
7
+ the plugin folder.
8
+
9
+ Legacy ``event_type`` (``"twitter_event_received"``) is preserved on
10
+ the dispatch path so the ``twitterReceive`` trigger node's
11
+ ``event_type`` ClassVar still matches without a coordinated
12
+ registry-side rename.
13
+
14
+ Canary status (2026-05-15):
15
+ - Typed envelope + dispatcher infrastructure: ready (this file).
16
+ - Canary registry opt-in: **deferred**. ``twitterReceive`` is a plain
17
+ ``TriggerNode`` with ``mode="polling"``; the Temporal-durable
18
+ polling canary path (``PollingTriggerWorkflow`` + ``as_poll_activity``)
19
+ requires the node class to subclass :class:`PollingTriggerNode` and
20
+ declare the 4 hooks (``setup_service`` / ``fetch_ids`` /
21
+ ``fetch_detail`` / ``post_emit``) — same shape as ``GmailReceiveNode``.
22
+ Once that refactor lands, add
23
+ ``register_canary_trigger_type("twitterReceive")`` to
24
+ ``nodes/twitter/__init__.py`` and the deployment manager picks up
25
+ the polling canary path automatically.
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ from typing import Any, Mapping
31
+
32
+ from services.events.envelope import WorkflowEvent
33
+
34
+
35
+ # Legacy event_type the event_waiter dispatches by; trigger nodes
36
+ # subscribe on this string (matches ``TwitterReceiveNode.event_type``).
37
+ _LEGACY_EVENT_TYPE = "twitter_event_received"
38
+
39
+
40
+ # ---- Typed factory ---------------------------------------------------------
41
+
42
+
43
+ def twitter_event_received(event_data: Mapping[str, Any]) -> WorkflowEvent:
44
+ """Inbound Twitter/X event envelope (mention / search hit /
45
+ timeline update / DM).
46
+
47
+ ``subject`` is the tweet/DM id when available so consumers can
48
+ dedup; the originating Twitter user id is in
49
+ ``data.author_id`` or ``data.user_id``. The event ``type``
50
+ distinguishes the kind via the data payload, not the envelope —
51
+ every twitter inbound shares ``com.machinaos.twitter.event.received``
52
+ since the producer (polling loop) doesn't always know which kind a
53
+ given tweet is until the downstream filter runs.
54
+ """
55
+ payload = dict(event_data)
56
+ subject = payload.get("tweet_id") or payload.get("id") or payload.get("dm_id")
57
+ return WorkflowEvent(
58
+ source="machinaos://nodes/twitter",
59
+ type="com.machinaos.twitter.event.received",
60
+ subject=str(subject) if subject else None,
61
+ data=payload,
62
+ )
63
+
64
+
65
+ # ---- Dispatcher wrapper ----------------------------------------------------
66
+
67
+
68
+ async def dispatch_twitter_event_received(event_data: Mapping[str, Any]) -> int:
69
+ """Dispatch an incoming Twitter/X event to waiting ``twitterReceive``
70
+ trigger nodes.
71
+
72
+ Two delivery paths (mirrors :func:`email._events.dispatch_email_received`):
73
+
74
+ 1. **Legacy event_waiter waiters** via :func:`event_waiter.dispatch`
75
+ (in-process collector/processor; the default while
76
+ ``twitterReceive`` is not in the canary registry).
77
+ 2. **Temporal-durable listeners** via
78
+ :func:`services.events.dispatch.emit`. ``emit`` is a pass-through
79
+ no-op when ``event_framework_enabled`` is off; otherwise it
80
+ fan-outs to running consumer workflows via Visibility query.
81
+
82
+ Returns the count of legacy waiters resolved.
83
+ """
84
+ from services import event_waiter
85
+ from services.events.dispatch import emit
86
+
87
+ payload = dict(event_data)
88
+ resolved = event_waiter.dispatch(_LEGACY_EVENT_TYPE, payload)
89
+
90
+ await emit(
91
+ twitter_event_received(payload),
92
+ wire_routing_key=_LEGACY_EVENT_TYPE,
93
+ )
94
+
95
+ return resolved
96
+
97
+
98
+ __all__ = [
99
+ "dispatch_twitter_event_received",
100
+ "twitter_event_received",
101
+ ]
@@ -17,20 +17,20 @@ def build_filter(params: Dict) -> Callable[[Dict], bool]:
17
17
  - ``search_query`` -- search query for ``search``
18
18
  - ``user_id`` -- user ID for ``user_timeline``
19
19
  """
20
- trigger_type = params.get('trigger_type', 'mentions')
21
- search_query = params.get('search_query', '')
22
- user_id = params.get('user_id', '')
20
+ trigger_type = params.get("trigger_type", "mentions")
21
+ search_query = params.get("search_query", "")
22
+ user_id = params.get("user_id", "")
23
23
 
24
24
  def matches(data: Dict) -> bool:
25
- event_type = data.get('trigger_type', '')
26
- if trigger_type != 'all' and event_type != trigger_type:
25
+ event_type = data.get("trigger_type", "")
26
+ if trigger_type != "all" and event_type != trigger_type:
27
27
  return False
28
- if trigger_type == 'search' and search_query:
29
- event_query = data.get('query', '')
28
+ if trigger_type == "search" and search_query:
29
+ event_query = data.get("query", "")
30
30
  if search_query.lower() not in event_query.lower():
31
31
  return False
32
- if trigger_type == 'user_timeline' and user_id:
33
- if data.get('user_id') != user_id:
32
+ if trigger_type == "user_timeline" and user_id:
33
+ if data.get("user_id") != user_id:
34
34
  return False
35
35
  return True
36
36
 
@@ -25,7 +25,9 @@ from ._oauth import TwitterOAuth
25
25
 
26
26
 
27
27
  async def _twitter_oauth_factory(
28
- *, redirect_uri: Optional[str] = None, **_kwargs,
28
+ *,
29
+ redirect_uri: Optional[str] = None,
30
+ **_kwargs,
29
31
  ) -> TwitterOAuth:
30
32
  """Build a :class:`TwitterOAuth` from stored client credentials."""
31
33
  from services.plugin.deps import get_auth_service
@@ -94,8 +94,7 @@ class TwitterOAuth(OAuth2PKCEClient):
94
94
  error_data = response.json() if response.text else {}
95
95
  return {
96
96
  "success": False,
97
- "error": error_data.get("detail")
98
- or error_data.get("title", "Failed to get user info"),
97
+ "error": error_data.get("detail") or error_data.get("title", "Failed to get user info"),
99
98
  }
100
99
 
101
100
  user = response.json().get("data", {})
@@ -35,9 +35,7 @@ async def refresh_twitter_status(broadcaster: "StatusBroadcaster") -> None:
35
35
  from services.plugin.deps import get_auth_service
36
36
 
37
37
  auth_service = get_auth_service()
38
- tokens = await auth_service.get_oauth_tokens(
39
- "twitter", customer_id="owner"
40
- )
38
+ tokens = await auth_service.get_oauth_tokens("twitter", customer_id="owner")
41
39
  if not tokens or not tokens.get("access_token"):
42
40
  broadcaster._status["twitter"] = {
43
41
  "connected": False,
@@ -64,15 +62,13 @@ async def refresh_twitter_status(broadcaster: "StatusBroadcaster") -> None:
64
62
  username,
65
63
  )
66
64
 
67
- await broadcaster.broadcast({
68
- "type": "twitter_status",
69
- "data": broadcaster._status["twitter"],
70
- })
71
- span.set_attribute(
72
- "connected", bool(broadcaster._status["twitter"]["connected"])
65
+ await broadcaster.broadcast(
66
+ {
67
+ "type": "twitter_status",
68
+ "data": broadcaster._status["twitter"],
69
+ }
73
70
  )
71
+ span.set_attribute("connected", bool(broadcaster._status["twitter"]["connected"]))
74
72
  except Exception as exc: # noqa: BLE001 -- mirror pre-migration behaviour
75
73
  span.record_exception(exc)
76
- logger.debug(
77
- "[StatusBroadcaster] Could not refresh Twitter status: %s", exc
78
- )
74
+ logger.debug("[StatusBroadcaster] Could not refresh Twitter status: %s", exc)
@@ -8,7 +8,7 @@ from pydantic import BaseModel, ConfigDict, Field
8
8
 
9
9
  from services.plugin import NodeContext, Operation, TaskQueue, TriggerNode
10
10
 
11
- from ._credentials import TwitterCredential
11
+ from .._credentials import TwitterCredential
12
12
 
13
13
 
14
14
  class TwitterReceiveParams(BaseModel):
@@ -43,10 +43,7 @@ class TwitterReceiveNode(TriggerNode):
43
43
  # ``event_waiter._auto_populate_from_plugins`` backfill
44
44
  # TRIGGER_REGISTRY without a hardcoded entry in event_waiter.
45
45
  event_type = "twitter_event_received"
46
- handles = (
47
- {"name": "output-main", "kind": "output", "position": "right",
48
- "label": "Output", "role": "main"},
49
- )
46
+ handles = ({"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},)
50
47
  credentials = (TwitterCredential,)
51
48
  task_queue = TaskQueue.TRIGGERS_POLL
52
49
  mode = "polling"
@@ -62,9 +59,12 @@ class TwitterReceiveNode(TriggerNode):
62
59
  context: NodeContext,
63
60
  ) -> Dict[str, Any]:
64
61
  from services.handlers.triggers import handle_trigger_node
62
+
65
63
  return await handle_trigger_node(
66
- node_id=node_id, node_type=self.type,
67
- parameters=parameters, context=context.raw,
64
+ node_id=node_id,
65
+ node_type=self.type,
66
+ parameters=parameters,
67
+ context=context.raw,
68
68
  )
69
69
 
70
70
  @Operation("wait")
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#1DA1F2"
3
+ }
@@ -9,11 +9,14 @@ from pydantic import BaseModel, ConfigDict, Field
9
9
 
10
10
  from services.plugin import ActionNode, NodeContext, Operation, TaskQueue
11
11
 
12
- from ._credentials import TwitterCredential
13
-
14
- from ._base import (
15
- call_with_retry, format_tweet, includes_lookups,
16
- sync_search_recent, track_twitter_usage,
12
+ from .._credentials import TwitterCredential
13
+
14
+ from .._base import (
15
+ call_with_retry,
16
+ format_tweet,
17
+ includes_lookups,
18
+ sync_search_recent,
19
+ track_twitter_usage,
17
20
  )
18
21
 
19
22
 
@@ -25,7 +28,7 @@ class TwitterSearchParams(BaseModel):
25
28
  description=(
26
29
  "X / Twitter search query for /2/tweets/search/recent. "
27
30
  "MUST include at least one STANDALONE term: a keyword, "
28
- "quoted \"phrase\", #hashtag, @mention, from:user, to:user, "
31
+ 'quoted "phrase", #hashtag, @mention, from:user, to:user, '
29
32
  "or url:domain. "
30
33
  "Operators like lang:, -is:retweet, is:reply, has:media, "
31
34
  "has:links are CONJUNCTION-REQUIRED -- they only work when "
@@ -36,7 +39,9 @@ class TwitterSearchParams(BaseModel):
36
39
  ),
37
40
  )
38
41
  max_results: int = Field(
39
- default=10, ge=10, le=100,
42
+ default=10,
43
+ ge=10,
44
+ le=100,
40
45
  description="Number of results (X API minimum 10, max 100)",
41
46
  )
42
47
  sort_order: Literal["recency", "relevancy"] = Field(
@@ -87,11 +92,11 @@ class TwitterSearchNode(ActionNode):
87
92
  group = ("social", "tool")
88
93
  description = "Search recent tweets on Twitter/X using the Search API"
89
94
  component_kind = "square"
95
+ tool_name = "twitter_search"
96
+ tool_description = "Search recent tweets on Twitter/X. Returns enriched tweets with expanded URLs, author profile, public_metrics, media, referenced_tweets, note_tweet. Supports query operators: keywords, #hashtags, @mentions, from:user, to:user, -exclude, OR, lang:, has:links/media/images/videos, is:retweet/reply/quote, url:."
90
97
  handles = (
91
- {"name": "input-main", "kind": "input", "position": "left",
92
- "label": "Input", "role": "main"},
93
- {"name": "output-main", "kind": "output", "position": "right",
94
- "label": "Output", "role": "main"},
98
+ {"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
99
+ {"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
95
100
  )
96
101
  annotations = {"destructive": False, "readonly": True, "open_world": True}
97
102
  credentials = (TwitterCredential,)
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
@@ -0,0 +1,3 @@
1
+ {
2
+ "color": "#1DA1F2"
3
+ }