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,103 @@
1
+ """Plugin-owned shutdown-hook registry for FastAPI lifespan teardown.
2
+
3
+ Closes the cross-plugin reaches in ``main.py``:
4
+
5
+ - ``from nodes.android._relay.manager import close_relay_client``
6
+ - ``from nodes.browser._service import shutdown_browser_service``
7
+
8
+ Both made the framework's lifespan code know about specific plugins'
9
+ internals. Plugins with cleanup logic now self-register a hook; the
10
+ lifespan awaits all registered hooks via :func:`run_shutdown_hooks`.
11
+
12
+ Distinct from :mod:`services._supervisor`: that registry is for
13
+ managed-subprocess supervisors (Go binaries, etc.) with a well-defined
14
+ ``shutdown()`` contract. This registry is the general async-cleanup
15
+ hatch — any coroutine-shaped teardown (close a connection, drain a
16
+ queue, flush a cache, ...) goes here.
17
+
18
+ Hook signature
19
+ --------------
20
+
21
+ ::
22
+
23
+ hook() -> Awaitable[None]
24
+
25
+ The hook is named (label) so failures during shutdown surface with a
26
+ plugin identifier instead of just a traceback. Failures DO NOT block
27
+ sibling hooks — every hook runs even if one raises, mirroring the
28
+ ``shutdown_all_supervisors`` semantics.
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ from typing import Awaitable, Callable, List, Tuple
34
+
35
+ from core.logging import get_logger
36
+ from services.plugin.registry import IdempotentRegistry
37
+
38
+ logger = get_logger(__name__)
39
+
40
+
41
+ ShutdownHook = Callable[[], Awaitable[None]]
42
+
43
+
44
+ # Registry is keyed by label so each plugin can register exactly one
45
+ # hook under a stable name. The `items` view preserves insertion order
46
+ # (CPython 3.7+ dict ordering guarantee) which gives deterministic
47
+ # shutdown ordering. Plugins that need ordering invariants should
48
+ # document them via their label naming.
49
+ _REGISTRY: IdempotentRegistry[str, ShutdownHook] = IdempotentRegistry("plugin_shutdown_hook")
50
+
51
+
52
+ def register_shutdown_hook(label: str, hook: ShutdownHook) -> None:
53
+ """Publish a shutdown hook for FastAPI lifespan teardown.
54
+
55
+ Idempotent on re-import (same callable for the same label is a
56
+ no-op). A different callable for an existing label raises
57
+ ``ValueError`` to surface plugin namespace collisions at import time.
58
+
59
+ Args:
60
+ label: Stable plugin identifier (``"android_relay"``,
61
+ ``"browser_service"``, ...). Surfaces in shutdown logs +
62
+ in the error message if the hook raises.
63
+ hook: Async function taking no arguments. Should be
64
+ idempotent (lifespan may run it multiple times during
65
+ test harness teardown).
66
+ """
67
+ _REGISTRY.register(label, hook)
68
+
69
+
70
+ def registered_labels() -> Tuple[str, ...]:
71
+ """Return registered hook labels in insertion order (snapshot)."""
72
+ return tuple(_REGISTRY.keys())
73
+
74
+
75
+ async def run_shutdown_hooks() -> None:
76
+ """Run every registered shutdown hook in registration order.
77
+
78
+ Per-hook failures are caught + logged with the hook's label so
79
+ one slow / broken plugin doesn't strand the rest of the lifespan
80
+ teardown. Mirrors ``services._supervisor.shutdown_all_supervisors``
81
+ semantics.
82
+ """
83
+ hooks: List[Tuple[str, ShutdownHook]] = list(_REGISTRY.items().items())
84
+ if not hooks:
85
+ return
86
+
87
+ logger.info(f"Running {len(hooks)} plugin shutdown hook(s): " f"{[label for label, _ in hooks]}")
88
+ for label, hook in hooks:
89
+ try:
90
+ await hook()
91
+ except Exception as exc: # noqa: BLE001 — log and continue
92
+ logger.error(
93
+ f"Plugin shutdown hook {label!r} raised; continuing: {exc}",
94
+ exc_info=True,
95
+ )
96
+
97
+
98
+ __all__ = [
99
+ "register_shutdown_hook",
100
+ "registered_labels",
101
+ "run_shutdown_hooks",
102
+ "ShutdownHook",
103
+ ]
@@ -0,0 +1,80 @@
1
+ """Plugin-owned dispatch registry for the social-messaging facade.
2
+
3
+ Closes the cross-plugin reach from ``nodes/social/_base.py:478`` —
4
+ ``from nodes.whatsapp._service import handle_whatsapp_send`` — which
5
+ made the ``social`` plugin depend on the ``whatsapp`` plugin's
6
+ internals and violated the "framework knows no plugin names" rule.
7
+
8
+ Each social platform plugin (whatsapp, telegram, slack, discord, …)
9
+ registers a send handler keyed by the platform identifier from its
10
+ own ``__init__.py``. The social node queries the registry instead of
11
+ importing platform internals — same Wave-11.I plugin-self-registration
12
+ pattern as ``register_filter_builder`` / ``register_poll_coroutine_factory``
13
+ / ``register_ws_handlers`` / ``register_canary_trigger_type``.
14
+
15
+ Handler signature
16
+ -----------------
17
+
18
+ ::
19
+
20
+ handler(params: Dict[str, Any]) -> Awaitable[Dict[str, Any]]
21
+
22
+ The social node maps its own parameter shape onto the platform's
23
+ expected shape and calls the handler. The handler returns the
24
+ platform's native result dict; the social node passes that through.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import Any, Awaitable, Callable, Dict, Optional
30
+
31
+ from services.plugin.registry import IdempotentRegistry
32
+
33
+
34
+ # (params: Dict) -> Awaitable[Dict]
35
+ SocialSendHandler = Callable[[Dict[str, Any]], Awaitable[Dict[str, Any]]]
36
+
37
+
38
+ _REGISTRY: IdempotentRegistry[str, SocialSendHandler] = IdempotentRegistry("social_send_handler")
39
+
40
+
41
+ def register_social_send_handler(platform: str, handler: SocialSendHandler) -> None:
42
+ """Publish a send handler for one social platform.
43
+
44
+ Idempotent on re-import (same callable for the same platform key
45
+ is a no-op). A different callable for an existing platform raises
46
+ ``ValueError`` to surface plugin namespace collisions at import time.
47
+
48
+ Args:
49
+ platform: Lower-case platform identifier (``"whatsapp"``,
50
+ ``"telegram"``, …). Matches the value the social node's
51
+ ``platform`` parameter holds at runtime.
52
+ handler: Async function accepting platform-specific
53
+ ``params: Dict`` and returning the platform's native
54
+ result dict. The social node builds the params dict by
55
+ mapping its generic shape onto the platform's keys.
56
+ """
57
+ _REGISTRY.register(platform, handler)
58
+
59
+
60
+ def get_social_send_handler(platform: str) -> Optional[SocialSendHandler]:
61
+ """Return the handler for ``platform``, or ``None`` if unregistered.
62
+
63
+ A ``None`` return surfaces as a clear "unsupported platform" error
64
+ at the social node call site instead of an ``ImportError`` deep
65
+ inside the platform's ``_service.py``.
66
+ """
67
+ return _REGISTRY.get(platform)
68
+
69
+
70
+ def registered_platforms() -> frozenset[str]:
71
+ """Return an immutable snapshot of registered platform identifiers."""
72
+ return frozenset(_REGISTRY.keys())
73
+
74
+
75
+ __all__ = [
76
+ "register_social_send_handler",
77
+ "get_social_send_handler",
78
+ "registered_platforms",
79
+ "SocialSendHandler",
80
+ ]
@@ -64,7 +64,8 @@ def ws_response(handler: WSHandlerFn) -> WSHandlerFn:
64
64
 
65
65
  @wraps(handler)
66
66
  async def wrapper(
67
- data: Dict[str, Any], websocket: WebSocket,
67
+ data: Dict[str, Any],
68
+ websocket: WebSocket,
68
69
  ) -> Dict[str, Any]:
69
70
  try:
70
71
  return await handler(data, websocket)
@@ -26,10 +26,11 @@ CONFIG_PATH = Path(__file__).parent.parent / "config" / "pricing.json"
26
26
  @dataclass
27
27
  class ModelPricing:
28
28
  """Pricing for a specific LLM model."""
29
- input_per_mtok: float # USD per 1M input tokens
29
+
30
+ input_per_mtok: float # USD per 1M input tokens
30
31
  output_per_mtok: float # USD per 1M output tokens
31
32
  cache_read_per_mtok: Optional[float] = None # USD per 1M cache read tokens (Anthropic)
32
- reasoning_per_mtok: Optional[float] = None # USD per 1M reasoning tokens (OpenAI o-series)
33
+ reasoning_per_mtok: Optional[float] = None # USD per 1M reasoning tokens (OpenAI o-series)
33
34
 
34
35
 
35
36
  class PricingService:
@@ -44,7 +45,7 @@ class PricingService:
44
45
  """Load pricing config from JSON file."""
45
46
  if CONFIG_PATH.exists():
46
47
  try:
47
- with open(CONFIG_PATH, 'r', encoding='utf-8') as f:
48
+ with open(CONFIG_PATH, "r", encoding="utf-8") as f:
48
49
  self._config = json.load(f)
49
50
  self._build_llm_registry()
50
51
  logger.info(f"[Pricing] Loaded pricing config v{self._config.get('version', 'unknown')}")
@@ -97,7 +98,7 @@ class PricingService:
97
98
  # Ensure config directory exists
98
99
  CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
99
100
 
100
- with open(CONFIG_PATH, 'w', encoding='utf-8') as f:
101
+ with open(CONFIG_PATH, "w", encoding="utf-8") as f:
101
102
  json.dump(config, f, indent=2)
102
103
 
103
104
  # Reload the config into memory
@@ -128,7 +129,7 @@ class PricingService:
128
129
  ModelPricing with rates per million tokens
129
130
  """
130
131
  provider_lower = provider.lower()
131
- model_lower = model.lower() if model else ''
132
+ model_lower = model.lower() if model else ""
132
133
 
133
134
  provider_pricing = self._llm_registry.get(provider_lower, {})
134
135
 
@@ -138,16 +139,16 @@ class PricingService:
138
139
 
139
140
  # Try partial match (model name starts with a known key)
140
141
  for model_key, pricing in provider_pricing.items():
141
- if model_key != '_default' and model_lower.startswith(model_key):
142
+ if model_key != "_default" and model_lower.startswith(model_key):
142
143
  return pricing
143
144
 
144
145
  # Try if any key is contained in the model name
145
146
  for model_key, pricing in provider_pricing.items():
146
- if model_key != '_default' and model_key in model_lower:
147
+ if model_key != "_default" and model_key in model_lower:
147
148
  return pricing
148
149
 
149
150
  # Fall back to provider default
150
- default_pricing = provider_pricing.get('_default')
151
+ default_pricing = provider_pricing.get("_default")
151
152
  if default_pricing:
152
153
  return default_pricing
153
154
 
@@ -163,7 +164,7 @@ class PricingService:
163
164
  output_tokens: int,
164
165
  cache_read_tokens: int = 0,
165
166
  cache_creation_tokens: int = 0,
166
- reasoning_tokens: int = 0
167
+ reasoning_tokens: int = 0,
167
168
  ) -> Dict[str, float]:
168
169
  """Calculate cost for LLM token usage.
169
170
 
@@ -206,11 +207,11 @@ class PricingService:
206
207
  total_cost = input_cost + output_cost + cache_cost + reasoning_cost
207
208
 
208
209
  return {
209
- 'input_cost': round(input_cost, 6),
210
- 'output_cost': round(output_cost, 6),
211
- 'cache_cost': round(cache_cost, 6),
212
- 'reasoning_cost': round(reasoning_cost, 6),
213
- 'total_cost': round(total_cost, 6),
210
+ "input_cost": round(input_cost, 6),
211
+ "output_cost": round(output_cost, 6),
212
+ "cache_cost": round(cache_cost, 6),
213
+ "reasoning_cost": round(reasoning_cost, 6),
214
+ "total_cost": round(total_cost, 6),
214
215
  }
215
216
 
216
217
  def get_all_pricing(self) -> Dict[str, Dict[str, Dict[str, float]]]:
@@ -224,10 +225,10 @@ class PricingService:
224
225
  result[provider] = {}
225
226
  for model, pricing in models.items():
226
227
  result[provider][model] = {
227
- 'input': pricing.input_per_mtok,
228
- 'output': pricing.output_per_mtok,
229
- 'cache_read': pricing.cache_read_per_mtok,
230
- 'reasoning': pricing.reasoning_per_mtok,
228
+ "input": pricing.input_per_mtok,
229
+ "output": pricing.output_per_mtok,
230
+ "cache_read": pricing.cache_read_per_mtok,
231
+ "reasoning": pricing.reasoning_per_mtok,
231
232
  }
232
233
  return result
233
234
 
@@ -245,7 +246,7 @@ class PricingService:
245
246
  Returns:
246
247
  USD cost per resource/request
247
248
  """
248
- api_config = self._config.get('api', {})
249
+ api_config = self._config.get("api", {})
249
250
  service_config = api_config.get(service, {})
250
251
  return service_config.get(operation, 0.0)
251
252
 
@@ -258,10 +259,10 @@ class PricingService:
258
259
  Returns:
259
260
  Dict of {operation: price} for the service
260
261
  """
261
- api_config = self._config.get('api', {})
262
+ api_config = self._config.get("api", {})
262
263
  service_config = api_config.get(service, {})
263
264
  # Filter out metadata keys starting with _
264
- return {k: v for k, v in service_config.items() if not k.startswith('_') and isinstance(v, (int, float))}
265
+ return {k: v for k, v in service_config.items() if not k.startswith("_") and isinstance(v, (int, float))}
265
266
 
266
267
  def map_action_to_operation(self, service: str, action: str) -> Optional[str]:
267
268
  """Map handler action to pricing operation.
@@ -273,16 +274,11 @@ class PricingService:
273
274
  Returns:
274
275
  Pricing operation key or None if no mapping
275
276
  """
276
- operation_map = self._config.get('operation_map', {})
277
+ operation_map = self._config.get("operation_map", {})
277
278
  service_map = operation_map.get(service, {})
278
279
  return service_map.get(action)
279
280
 
280
- def calculate_api_cost(
281
- self,
282
- service: str,
283
- action: str,
284
- resource_count: int = 1
285
- ) -> Dict[str, Any]:
281
+ def calculate_api_cost(self, service: str, action: str, resource_count: int = 1) -> Dict[str, Any]:
286
282
  """Calculate cost for API usage.
287
283
 
288
284
  Args:
@@ -299,22 +295,12 @@ class PricingService:
299
295
  """
300
296
  operation = self.map_action_to_operation(service, action)
301
297
  if not operation:
302
- return {
303
- 'operation': action,
304
- 'unit_cost': 0.0,
305
- 'resource_count': resource_count,
306
- 'total_cost': 0.0
307
- }
298
+ return {"operation": action, "unit_cost": 0.0, "resource_count": resource_count, "total_cost": 0.0}
308
299
 
309
300
  unit_cost = self.get_api_price(service, operation)
310
301
  total_cost = unit_cost * resource_count
311
302
 
312
- return {
313
- 'operation': operation,
314
- 'unit_cost': unit_cost,
315
- 'resource_count': resource_count,
316
- 'total_cost': round(total_cost, 6)
317
- }
303
+ return {"operation": operation, "unit_cost": unit_cost, "resource_count": resource_count, "total_cost": round(total_cost, 6)}
318
304
 
319
305
 
320
306
  # Singleton instance
@@ -0,0 +1,90 @@
1
+ """Pricing-domain WS handlers — Wave 13.8 extraction.
2
+
3
+ Sibling module to ``services/pricing.py`` (the PricingService singleton);
4
+ kept flat instead of a subpackage to avoid renaming the existing
5
+ ``services.pricing`` import path used across handlers.
6
+
7
+ Side-effect import (from ``main.py``) registers the 3 handlers below
8
+ into ``ws_handler_registry``:
9
+ - ``get_pricing_config`` — return full pricing config for the
10
+ Settings panel.
11
+ - ``save_pricing_config`` — persist edits.
12
+ - ``get_api_usage_summary`` — aggregated API usage / cost by service.
13
+
14
+ Note: ``get_provider_usage_summary`` (token-pricing summary, per
15
+ provider) moved into ``services/settings/handlers.py`` (Wave 13.3) —
16
+ kept there because it's surfaced in the Credentials Modal alongside
17
+ the provider-defaults panel.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from typing import Any, Dict
23
+
24
+ from fastapi import WebSocket
25
+
26
+ from core.container import container
27
+ from core.logging import get_logger
28
+ from services.ws_handler_registry import register_ws_handlers, ws_handler
29
+
30
+ logger = get_logger(__name__)
31
+
32
+
33
+ @ws_handler()
34
+ async def handle_get_pricing_config(
35
+ data: Dict[str, Any],
36
+ websocket: WebSocket,
37
+ ) -> Dict[str, Any]:
38
+ """Get full pricing configuration for display/editing."""
39
+ from services.pricing import get_pricing_service
40
+
41
+ pricing = get_pricing_service()
42
+ return {"success": True, "config": pricing.get_config()}
43
+
44
+
45
+ @ws_handler()
46
+ async def handle_save_pricing_config(
47
+ data: Dict[str, Any],
48
+ websocket: WebSocket,
49
+ ) -> Dict[str, Any]:
50
+ """Save updated pricing configuration."""
51
+ from services.pricing import get_pricing_service
52
+
53
+ config = data.get("config")
54
+ if not config:
55
+ return {"success": False, "error": "No config provided"}
56
+
57
+ pricing = get_pricing_service()
58
+ success = pricing.save_config(config)
59
+ return {"success": success}
60
+
61
+
62
+ @ws_handler()
63
+ async def handle_get_api_usage_summary(
64
+ data: Dict[str, Any],
65
+ websocket: WebSocket,
66
+ ) -> Dict[str, Any]:
67
+ """Get aggregated API usage and cost by service (Twitter, Maps, etc.)."""
68
+ database = container.database()
69
+ service = data.get("service") # Optional filter by service
70
+ services = await database.get_api_usage_summary(service)
71
+ return {"success": True, "services": services}
72
+
73
+
74
+ WS_HANDLERS: Dict[str, Any] = {
75
+ "get_pricing_config": handle_get_pricing_config,
76
+ "save_pricing_config": handle_save_pricing_config,
77
+ "get_api_usage_summary": handle_get_api_usage_summary,
78
+ }
79
+
80
+ # Self-register on import — ``main.py`` triggers via
81
+ # ``import services.pricing_handlers``.
82
+ register_ws_handlers(WS_HANDLERS)
83
+
84
+
85
+ __all__ = [
86
+ "WS_HANDLERS",
87
+ "handle_get_api_usage_summary",
88
+ "handle_get_pricing_config",
89
+ "handle_save_pricing_config",
90
+ ]
@@ -13,7 +13,7 @@ import asyncio
13
13
  import os
14
14
  import shlex
15
15
  import shutil
16
- from dataclasses import dataclass, field
16
+ from dataclasses import dataclass
17
17
  from datetime import datetime
18
18
  from pathlib import Path
19
19
  from typing import Any, Awaitable, Callable, Dict, List, Optional
@@ -96,15 +96,24 @@ class ProcessService:
96
96
  # Block destructive commands -- file ops should use the sandboxed shell node
97
97
  cmd_lower = command.lower().strip()
98
98
  blocked = (
99
- "rm ", "rm\t", "rmdir", "del ", "rd ", "remove-item",
100
- "format ", "mkfs", "dd if=", "shred",
101
- "> /dev/", "chmod 777", "chmod -r",
99
+ "rm ",
100
+ "rm\t",
101
+ "rmdir",
102
+ "del ",
103
+ "rd ",
104
+ "remove-item",
105
+ "format ",
106
+ "mkfs",
107
+ "dd if=",
108
+ "shred",
109
+ "> /dev/",
110
+ "chmod 777",
111
+ "chmod -r",
102
112
  )
103
113
  if any(cmd_lower.startswith(b) or f" {b}" in f" {cmd_lower}" for b in blocked):
104
114
  return {
105
115
  "success": False,
106
- "error": f"Destructive commands blocked in process_manager. "
107
- f"Use shell_execute for file operations (sandboxed, no PATH).",
116
+ "error": "Destructive commands blocked in process_manager. " "Use shell_execute for file operations (sandboxed, no PATH).",
108
117
  }
109
118
 
110
119
  name = name or f"proc_{id(command) % 100000}"
@@ -132,18 +141,16 @@ class ProcessService:
132
141
  if resolved is None:
133
142
  return {
134
143
  "success": False,
135
- "error": (
136
- f"Command not found: '{argv[0] if argv else ''}'. "
137
- "Check spelling or ensure the binary is on PATH."
138
- ),
144
+ "error": (f"Command not found: '{argv[0] if argv else ''}'. " "Check spelling or ensure the binary is on PATH."),
139
145
  }
140
146
  argv[0] = resolved
141
147
  env = {**os.environ, "PYTHONUNBUFFERED": "1"}
142
148
  from core.config import Settings
149
+
143
150
  workspace_base = Path(Settings().workspace_base_resolved).resolve()
144
151
 
145
152
  if not working_directory:
146
- working_directory = str(workspace_base / 'default')
153
+ working_directory = str(workspace_base / "default")
147
154
  os.makedirs(working_directory, exist_ok=True)
148
155
  cwd = working_directory
149
156
 
@@ -232,9 +239,7 @@ class ProcessService:
232
239
  result = self._info(managed)
233
240
 
234
241
  # Schedule cleanup after 60s to allow output reading
235
- asyncio.get_event_loop().call_later(
236
- 60, lambda: self._cleanup_completed(workflow_id, name)
237
- )
242
+ asyncio.get_event_loop().call_later(60, lambda: self._cleanup_completed(workflow_id, name))
238
243
 
239
244
  return {"success": True, "result": result}
240
245
 
@@ -272,11 +277,7 @@ class ProcessService:
272
277
 
273
278
  def list_processes(self, workflow_id: str = "default") -> List[Dict[str, Any]]:
274
279
  """List all processes for a workflow."""
275
- return [
276
- self._info(m)
277
- for (wid, _), m in self._processes.items()
278
- if wid == workflow_id
279
- ]
280
+ return [self._info(m) for (wid, _), m in self._processes.items() if wid == workflow_id]
280
281
 
281
282
  def get_output(
282
283
  self,
@@ -378,9 +379,7 @@ class ProcessService:
378
379
  shutil.rmtree(managed.log_dir, ignore_errors=True)
379
380
  self._processes.clear()
380
381
 
381
- async def _read_stream(
382
- self, managed: ManagedProcess, stream: asyncio.StreamReader, stream_name: str
383
- ) -> None:
382
+ async def _read_stream(self, managed: ManagedProcess, stream: asyncio.StreamReader, stream_name: str) -> None:
384
383
  """Background task: read lines, write to log file, broadcast to Terminal."""
385
384
  level = "info" if stream_name == "stdout" else "error"
386
385
  source = f"process:{managed.name}"
@@ -405,12 +404,14 @@ class ProcessService:
405
404
 
406
405
  # Broadcast to Terminal tab
407
406
  if self._broadcaster:
408
- await self._broadcaster.broadcast_terminal_log({
409
- "timestamp": datetime.now().isoformat(),
410
- "level": level,
411
- "message": text,
412
- "source": source,
413
- })
407
+ await self._broadcaster.broadcast_terminal_log(
408
+ {
409
+ "timestamp": datetime.now().isoformat(),
410
+ "level": level,
411
+ "message": text,
412
+ "source": source,
413
+ }
414
+ )
414
415
 
415
416
  # Optional framework-level subscriber.
416
417
  if managed.line_handler is not None:
@@ -419,7 +420,9 @@ class ProcessService:
419
420
  except Exception as cb_err:
420
421
  logger.debug(
421
422
  "[Process] line_handler %s/%s raised: %s",
422
- managed.name, stream_name, cb_err,
423
+ managed.name,
424
+ stream_name,
425
+ cb_err,
423
426
  )
424
427
  except asyncio.CancelledError:
425
428
  pass
@@ -436,9 +439,7 @@ class ProcessService:
436
439
  logger.info("[Process] Exited: %s (exit=%s)", managed.name, managed.exit_code)
437
440
 
438
441
  # Schedule auto-cleanup of log files and process entry after delay
439
- asyncio.get_event_loop().call_later(
440
- 60, lambda: self._cleanup_completed(managed.workflow_id, managed.name)
441
- )
442
+ asyncio.get_event_loop().call_later(60, lambda: self._cleanup_completed(managed.workflow_id, managed.name))
442
443
 
443
444
  @staticmethod
444
445
  def _info(m: ManagedProcess) -> Dict[str, Any]:
@@ -7,12 +7,14 @@ from pydantic import BaseModel, Field
7
7
 
8
8
  class SessionType(str, Enum):
9
9
  """Proxy session type controlling IP rotation behavior."""
10
- ROTATING = "rotating" # New IP per request (default)
11
- STICKY = "sticky" # Same IP for duration
10
+
11
+ ROTATING = "rotating" # New IP per request (default)
12
+ STICKY = "sticky" # Same IP for duration
12
13
 
13
14
 
14
15
  class GeoTarget(BaseModel):
15
16
  """Geographic targeting for proxy requests."""
17
+
16
18
  country: Optional[str] = Field(default=None, description="ISO 3166-1 alpha-2 country code")
17
19
  city: Optional[str] = Field(default=None, description="City name")
18
20
  state: Optional[str] = Field(default=None, description="State/region name")
@@ -20,11 +22,12 @@ class GeoTarget(BaseModel):
20
22
 
21
23
  class ProviderConfig(BaseModel):
22
24
  """Configuration for a proxy provider loaded from database."""
25
+
23
26
  name: str
24
27
  enabled: bool = True
25
- priority: int = 50 # Lower = preferred
26
- weight: float = 1.0 # For weighted random selection
27
- cost_per_gb: float = 0.0 # USD per GB
28
+ priority: int = 50 # Lower = preferred
29
+ weight: float = 1.0 # For weighted random selection
30
+ cost_per_gb: float = 0.0 # USD per GB
28
31
  gateway_host: str = ""
29
32
  gateway_port: int = 0
30
33
  geo_coverage: List[str] = Field(default_factory=list) # ISO country codes
@@ -36,9 +39,10 @@ class ProviderConfig(BaseModel):
36
39
 
37
40
  class ProviderStats(BaseModel):
38
41
  """Runtime health statistics for a proxy provider."""
42
+
39
43
  name: str
40
- score: float = 1.0 # 0.0 - 1.0 composite score
41
- success_rate: float = 1.0 # 0.0 - 1.0
44
+ score: float = 1.0 # 0.0 - 1.0 composite score
45
+ success_rate: float = 1.0 # 0.0 - 1.0
42
46
  avg_latency_ms: float = 0.0
43
47
  total_requests: int = 0
44
48
  total_bytes: int = 0
@@ -47,8 +51,9 @@ class ProviderStats(BaseModel):
47
51
 
48
52
  class RoutingRule(BaseModel):
49
53
  """Domain-based routing rule for proxy selection."""
54
+
50
55
  id: Optional[int] = None
51
- domain_pattern: str # fnmatch glob: "*.linkedin.com", "*"
56
+ domain_pattern: str # fnmatch glob: "*.linkedin.com", "*"
52
57
  preferred_providers: List[str] = Field(default_factory=list)
53
58
  required_country: Optional[str] = None
54
59
  session_type: SessionType = SessionType.ROTATING
@@ -56,11 +61,12 @@ class RoutingRule(BaseModel):
56
61
  max_retries: int = 3
57
62
  failover: bool = True
58
63
  min_success_rate: float = 0.7
59
- priority: int = 0 # Lower = evaluated first
64
+ priority: int = 0 # Lower = evaluated first
60
65
 
61
66
 
62
67
  class ProxyResult(BaseModel):
63
68
  """Result of a proxied HTTP request, reported back for scoring."""
69
+
64
70
  success: bool
65
71
  latency_ms: float = 0.0
66
72
  bytes_transferred: int = 0