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
@@ -17,7 +17,28 @@ When TEMPORAL_ENABLED=false:
17
17
  - Falls back to the existing parallel/sequential executor
18
18
  """
19
19
 
20
- __all__ = ["TemporalExecutor", "TemporalClientWrapper"]
20
+ __all__ = [
21
+ "TemporalExecutor",
22
+ "TemporalClientWrapper",
23
+ "TemporalServerRuntime",
24
+ "get_temporal_server_runtime",
25
+ ]
21
26
 
22
27
  from .executor import TemporalExecutor
23
28
  from .client import TemporalClientWrapper
29
+ from ._runtime import (
30
+ TemporalServerRuntime,
31
+ get_temporal_server_runtime,
32
+ )
33
+
34
+ # ---- self-registration (Wave 11 plugin-folder pattern) -------------------
35
+ # WS handlers (temporal_status / _start / _stop) + WS-connect refresh
36
+ # (broadcasts current Temporal snapshot). Registries are idempotent on
37
+ # re-import; same callable for same key is a no-op.
38
+ from ._handlers import WS_HANDLERS as _WS_HANDLERS
39
+ from ._refresh import refresh_temporal_status as _refresh_temporal_status
40
+ from services.ws_handler_registry import register_ws_handlers
41
+ from services.status_broadcaster import register_service_refresh
42
+
43
+ register_ws_handlers(_WS_HANDLERS)
44
+ register_service_refresh(_refresh_temporal_status)
@@ -0,0 +1,65 @@
1
+ """WebSocket handlers for the Temporal lifecycle commands.
2
+
3
+ Wire keys registered in :mod:`services.ws_handler_registry`:
4
+
5
+ - ``temporal_status`` → status snapshot of the runtime
6
+ - ``temporal_start`` → idempotent start
7
+ - ``temporal_stop`` → idempotent stop
8
+
9
+ All three share the snapshot shape from
10
+ :func:`services.temporal._refresh.temporal_status_snapshot` — the
11
+ single source of truth for the ``{temporal}`` payload that the
12
+ WS-connect refresh callback also emits.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import Any
18
+
19
+ from fastapi import WebSocket
20
+
21
+ from core.logging import get_logger
22
+ from services.temporal._refresh import temporal_status_snapshot
23
+
24
+ logger = get_logger(__name__)
25
+
26
+
27
+ async def handle_temporal_status(
28
+ data: dict[str, Any],
29
+ websocket: WebSocket,
30
+ ) -> dict[str, Any]:
31
+ """Return the status snapshot for the Temporal runtime."""
32
+ return temporal_status_snapshot()
33
+
34
+
35
+ async def handle_temporal_start(
36
+ data: dict[str, Any],
37
+ websocket: WebSocket,
38
+ ) -> dict[str, Any]:
39
+ """Start Temporal. Idempotent — ``.start()`` returns immediately if
40
+ the runtime is already running."""
41
+ from services.temporal._runtime import get_temporal_server_runtime
42
+
43
+ await get_temporal_server_runtime().start()
44
+ return {"ok": True, **temporal_status_snapshot()}
45
+
46
+
47
+ async def handle_temporal_stop(
48
+ data: dict[str, Any],
49
+ websocket: WebSocket,
50
+ ) -> dict[str, Any]:
51
+ """Stop Temporal. Idempotent."""
52
+ from services.temporal._runtime import get_temporal_server_runtime
53
+
54
+ await get_temporal_server_runtime().stop()
55
+ return {"ok": True, **temporal_status_snapshot()}
56
+
57
+
58
+ WS_HANDLERS: dict[str, Any] = {
59
+ "temporal_status": handle_temporal_status,
60
+ "temporal_start": handle_temporal_start,
61
+ "temporal_stop": handle_temporal_stop,
62
+ }
63
+
64
+
65
+ __all__ = ["WS_HANDLERS"]
@@ -0,0 +1,158 @@
1
+ """Cross-platform Temporal CLI binary downloader using pooch.
2
+
3
+ Downloads the official ``temporal`` CLI from the URL documented at
4
+ https://docs.temporal.io/develop/python/set-up-your-local-python
5
+ (``temporal.download/cli/archive/latest?platform=<os>&arch=<arch>``).
6
+
7
+ Pooch handles XDG-aware cross-platform caching and archive extraction
8
+ (zip on Windows, tar.gz elsewhere). The ``latest`` URL rotates as new
9
+ CLI versions ship, so the download is unverified (TLS gives transport
10
+ integrity); pooch caches by local filename, not URL contents, so
11
+ re-runs after the first fetch are instant cache hits.
12
+
13
+ The downloaded ``temporal`` CLI powers ``temporal server start-dev``
14
+ (the SQLite/in-memory dev server) and ad-hoc workflow / operator
15
+ commands.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import asyncio
21
+ import platform
22
+ import stat
23
+ from pathlib import Path
24
+
25
+ import pooch
26
+
27
+ from core.config import Settings
28
+ from core.logging import get_logger
29
+
30
+ logger = get_logger(__name__)
31
+
32
+ # Official Temporal CLI download URL. Per the docs at
33
+ # https://docs.temporal.io/develop/python/set-up-your-local-python the
34
+ # CLI archive lives at ``temporal.download/cli/archive/latest`` with
35
+ # ``platform`` and ``arch`` query parameters. Contains a single
36
+ # ``temporal`` binary.
37
+ _CLI_BASE_URL = "https://temporal.download/cli/archive/latest"
38
+ _CLI_PLATFORM_MAP: dict[tuple[str, str], tuple[str, str]] = {
39
+ # platform.system, platform.machine -> (URL platform, URL arch)
40
+ ("Linux", "x86_64"): ("linux", "amd64"),
41
+ ("Linux", "aarch64"): ("linux", "arm64"),
42
+ ("Darwin", "x86_64"): ("darwin", "amd64"),
43
+ ("Darwin", "arm64"): ("darwin", "arm64"),
44
+ ("Windows", "AMD64"): ("windows", "amd64"),
45
+ ("Windows", "ARM64"): ("windows", "arm64"),
46
+ }
47
+
48
+ # pooch cache namespace. Pooch's own cache layout includes the asset
49
+ # URL so versions don't collide.
50
+ _CACHE_NAMESPACE = "machinaos-temporal"
51
+
52
+
53
+ _cached: dict[str, Path] | None = None
54
+ _lock = asyncio.Lock()
55
+
56
+
57
+ async def ensure_temporal_binaries(
58
+ settings: Settings | None = None,
59
+ ) -> dict[str, Path]:
60
+ """Return ``{"temporal": Path}`` — the official ``temporal`` CLI binary.
61
+
62
+ Idempotent — first call downloads, subsequent calls hit the pooch
63
+ cache (XDG / OS-conventional dir). Async-locked so concurrent
64
+ callers don't double-download.
65
+
66
+ The ``settings`` argument is accepted for API symmetry but currently
67
+ unused — the official ``latest`` URL has no version slot to override.
68
+ """
69
+ global _cached
70
+ # settings accepted for API symmetry; no fields consulted (the
71
+ # ``latest`` URL has no version slot).
72
+ _ = settings
73
+
74
+ async with _lock:
75
+ if _cached is not None:
76
+ return _cached
77
+ cli_path = await asyncio.to_thread(_fetch_cli_sync)
78
+ _cached = {"temporal": cli_path}
79
+ logger.info(
80
+ "[Temporal install] binary ready: %s",
81
+ {k: str(v) for k, v in _cached.items()},
82
+ )
83
+ return _cached
84
+
85
+
86
+ def _fetch_cli_sync() -> Path:
87
+ """Download the official ``temporal`` CLI archive and return the binary path.
88
+
89
+ Uses ``pooch.retrieve`` with ``known_hash=None`` because the
90
+ ``temporal.download/cli/archive/latest`` URL rotates as new CLI
91
+ versions ship — pinning a SHA would defeat the "latest" semantics
92
+ the official docs document. TLS gives us transport integrity.
93
+ """
94
+ key = (platform.system(), platform.machine())
95
+ if key not in _CLI_PLATFORM_MAP:
96
+ raise RuntimeError(f"[Temporal install] Unsupported platform for CLI: {key}. " f"Supported: {sorted(_CLI_PLATFORM_MAP.keys())}")
97
+ url_platform, url_arch = _CLI_PLATFORM_MAP[key]
98
+ url = f"{_CLI_BASE_URL}?platform={url_platform}&arch={url_arch}"
99
+
100
+ is_windows = platform.system() == "Windows"
101
+ fname = f"temporal_cli_latest_{url_platform}_{url_arch}.{'zip' if is_windows else 'tar.gz'}"
102
+ processor = pooch.Unzip() if is_windows else pooch.Untar()
103
+
104
+ extracted = pooch.retrieve(
105
+ url=url,
106
+ known_hash=None,
107
+ path=pooch.os_cache(_CACHE_NAMESPACE),
108
+ fname=fname,
109
+ processor=processor,
110
+ progressbar=True,
111
+ )
112
+
113
+ target = "temporal.exe" if is_windows else "temporal"
114
+ match = next((Path(p) for p in extracted if Path(p).name == target), None)
115
+ if match is None:
116
+ raise RuntimeError(
117
+ f"[Temporal install] CLI binary {target!r} not found in archive. " f"Extracted files: {[Path(p).name for p in extracted]}"
118
+ )
119
+ if not is_windows:
120
+ mode = match.stat().st_mode
121
+ match.chmod(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
122
+ return match
123
+
124
+
125
+ __all__ = ["ensure_temporal_binaries"]
126
+
127
+
128
+ def _main() -> int:
129
+ """Standalone entry: ``python -m services.temporal._install``.
130
+
131
+ Used by ``machina build`` step [6/6] to materialise the Temporal
132
+ CLI at build time instead of paying the download cost on first
133
+ ``machina start``. Fetches, verifies the binary exists on disk,
134
+ prints the resolved location. Non-zero exit on any failure.
135
+ """
136
+ import sys as _sys
137
+
138
+ try:
139
+ paths = asyncio.run(ensure_temporal_binaries())
140
+ except Exception as exc: # noqa: BLE001 — propagate to non-zero exit
141
+ print(f"[Temporal install] {exc}", file=_sys.stderr)
142
+ return 1
143
+
144
+ missing = [name for name, path in paths.items() if not path.exists()]
145
+ if missing:
146
+ print(
147
+ f"[Temporal install] binaries missing after fetch: {missing}",
148
+ file=_sys.stderr,
149
+ )
150
+ return 1
151
+
152
+ for name, path in paths.items():
153
+ print(f" {name}: {path}")
154
+ return 0
155
+
156
+
157
+ if __name__ == "__main__":
158
+ raise SystemExit(_main())
@@ -0,0 +1,57 @@
1
+ """WS-connect status broadcast for the Temporal stack.
2
+
3
+ Registered via ``status_broadcaster.register_service_refresh`` so the
4
+ frontend health indicator stays current — every WebSocket client
5
+ connect triggers ``_refresh_all_services()`` which fans out to every
6
+ registered callback. Same idiom :mod:`nodes.telegram._refresh` uses.
7
+
8
+ Also exposes :func:`temporal_status_snapshot` — the single source of
9
+ truth for the ``{temporal}`` status shape consumed by both this refresh
10
+ callback and ``_handlers.py``'s WS commands.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import TYPE_CHECKING, Any
16
+
17
+ from core.logging import get_logger
18
+
19
+ if TYPE_CHECKING:
20
+ from services.status_broadcaster import StatusBroadcaster
21
+
22
+ logger = get_logger(__name__)
23
+
24
+
25
+ def temporal_status_snapshot() -> dict[str, Any]:
26
+ """Return ``{"temporal": {...}}`` snapshot.
27
+
28
+ Exposes the uniform ``{name, running, started_at, last_error,
29
+ ...extras}`` shape every ``BaseSupervisor`` subclass returns.
30
+ Shared by the WS-refresh callback below and the
31
+ ``temporal_status`` / ``_start`` / ``_stop`` handlers in
32
+ :mod:`services.temporal._handlers`.
33
+ """
34
+ from services.temporal._runtime import get_temporal_server_runtime
35
+
36
+ return {"temporal": get_temporal_server_runtime().status_snapshot()}
37
+
38
+
39
+ async def refresh_temporal_status(broadcaster: "StatusBroadcaster") -> None:
40
+ """Broadcast the Temporal status snapshot on WS connect.
41
+
42
+ Signature matches the ``register_service_refresh`` callback contract
43
+ — :meth:`StatusBroadcaster._refresh_all_services` invokes every
44
+ registered callback as ``callback(self)`` (passes the broadcaster
45
+ as the sole positional argument). Without the parameter the
46
+ framework's ``TaskGroup`` swallows a ``TypeError: takes 0 positional
47
+ arguments but 1 was given`` on every server boot.
48
+ """
49
+ await broadcaster.broadcast(
50
+ {
51
+ "type": "temporal_status",
52
+ "data": temporal_status_snapshot(),
53
+ }
54
+ )
55
+
56
+
57
+ __all__ = ["refresh_temporal_status", "temporal_status_snapshot"]
@@ -0,0 +1,85 @@
1
+ """Wave 12 D1: shared Temporal RetryPolicy constants.
2
+
3
+ Replaces the duplicated inline ``RetryPolicy(1s, 30s, 3 attempts)``
4
+ declarations that lived in ``services/temporal/workflow.py:246`` and
5
+ ``services/temporal/agent_workflow.py:76`` (identical knobs, hand-typed
6
+ twice). Adds the missing ``non_retryable_error_types`` declaration so
7
+ ``NodeUserError`` (user-correctable failures: missing required field,
8
+ unknown enum value, bad regex) fails fast instead of burning all three
9
+ retry attempts.
10
+
11
+ Why these specific error types are non-retryable
12
+ ------------------------------------------------
13
+
14
+ - ``NodeUserError``: every plugin raises this for user-correctable
15
+ failures (see ``services/plugin/__init__.py``). Retrying just spends
16
+ retry budget — the input won't be different next time. The plugin
17
+ ``cls.retry_policy`` default already lists it as non-retryable
18
+ (Wave 12 A2, ``services/plugin/scaling.py``), but the WORKFLOW-side
19
+ ``workflow.execute_activity(..., retry_policy=...)`` override
20
+ silently lost that contract when the workflow author hand-typed a
21
+ fresh ``RetryPolicy(...)``. This module re-imposes it at the
22
+ workflow callsite.
23
+
24
+ - ``InvalidEvent``: when ``services/events/dispatch.py:emit`` raises
25
+ on a malformed envelope (missing ``id``, bad ``source``), the
26
+ activity's input is structurally broken and retries can't fix it.
27
+
28
+ Keep this list short. Adding error types here is a runtime contract
29
+ change — every workflow that uses these policies inherits the
30
+ non-retryability. Use ``cls.retry_policy.non_retryable_error_types``
31
+ on a specific plugin class when only ONE plugin's failure should be
32
+ non-retryable.
33
+
34
+ Refs
35
+ ----
36
+ - https://docs.temporal.io/encyclopedia/retry-policies
37
+ - https://python.temporal.io/temporalio.common.RetryPolicy.html
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ from datetime import timedelta
43
+
44
+ from temporalio.common import RetryPolicy
45
+
46
+
47
+ # Error types that surface user mistakes / structural payload bugs —
48
+ # retrying makes no difference. Plugin classes that raise their own
49
+ # domain-specific non-retryable errors should override
50
+ # ``cls.retry_policy`` rather than expand this list.
51
+ NON_RETRYABLE_ERROR_TYPES: tuple[str, ...] = (
52
+ "NodeUserError",
53
+ "InvalidEvent",
54
+ )
55
+
56
+
57
+ # Default activity policy for the orchestrator (MachinaWorkflow,
58
+ # AgentWorkflow, PollingTriggerWorkflow). 3 attempts with 1s→30s
59
+ # exponential backoff covers transient API blips (DNS, rate limits,
60
+ # brief upstream outages) without holding the whole graph hostage to a
61
+ # persistent failure.
62
+ DEFAULT_ACTIVITY_RETRY: RetryPolicy = RetryPolicy(
63
+ initial_interval=timedelta(seconds=1),
64
+ maximum_interval=timedelta(seconds=30),
65
+ maximum_attempts=3,
66
+ non_retryable_error_types=list(NON_RETRYABLE_ERROR_TYPES),
67
+ )
68
+
69
+
70
+ # Tighter policy for activities that are themselves cheap operations
71
+ # (e.g. ``emit_event_activity``, ``broadcast_progress``). Failing fast
72
+ # here surfaces wiring bugs in tests + ops without retry-budget noise.
73
+ QUICK_ACTIVITY_RETRY: RetryPolicy = RetryPolicy(
74
+ initial_interval=timedelta(milliseconds=250),
75
+ maximum_interval=timedelta(seconds=5),
76
+ maximum_attempts=2,
77
+ non_retryable_error_types=list(NON_RETRYABLE_ERROR_TYPES),
78
+ )
79
+
80
+
81
+ __all__ = [
82
+ "NON_RETRYABLE_ERROR_TYPES",
83
+ "DEFAULT_ACTIVITY_RETRY",
84
+ "QUICK_ACTIVITY_RETRY",
85
+ ]
@@ -0,0 +1,181 @@
1
+ """Temporal server lifecycle.
2
+
3
+ Single supervisor subclass: :class:`TemporalServerRuntime`. Spawns the
4
+ official ``temporal`` CLI (downloaded by :mod:`services.temporal._install`
5
+ from https://temporal.download/cli/archive/latest) with the
6
+ ``server start-dev`` subcommand against a SQLite db. Matches the local
7
+ dev install method documented at
8
+ https://docs.temporal.io/develop/python/set-up-your-local-python.
9
+
10
+ Uses the singleton accessor pattern (``Class.get_instance()``) from
11
+ ``BaseSupervisor`` — same idiom :mod:`nodes.whatsapp._runtime` uses for
12
+ ``WhatsAppRuntime``.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import asyncio
18
+ import os
19
+ import sys
20
+ from pathlib import Path
21
+ from typing import Any, Optional
22
+
23
+ from core.config import Settings
24
+ from core.logging import get_logger
25
+ from services._supervisor import BaseProcessSupervisor
26
+
27
+ logger = get_logger(__name__)
28
+
29
+ # How long each TCP-readiness probe waits per attempt. Sub-second so a
30
+ # stalled subprocess fails health fast.
31
+ _PROBE_TIMEOUT_SECONDS = 1.0
32
+
33
+
34
+ async def _probe_tcp_port(port: int, host: str = "127.0.0.1") -> bool:
35
+ """Return ``True`` iff a TCP connection to ``host:port`` succeeds
36
+ within :data:`_PROBE_TIMEOUT_SECONDS`. Loopback-friendly readiness
37
+ check used by ``health_check``. Mirrors :func:`cli.tcp.probe_tcp_port`
38
+ but keeps server-side modules independent of the ``cli`` CLI package."""
39
+ try:
40
+ _, writer = await asyncio.wait_for(
41
+ asyncio.open_connection(host, port),
42
+ timeout=_PROBE_TIMEOUT_SECONDS,
43
+ )
44
+ writer.close()
45
+ try:
46
+ await writer.wait_closed()
47
+ except (ConnectionResetError, OSError):
48
+ pass
49
+ return True
50
+ except (asyncio.TimeoutError, ConnectionRefusedError, OSError):
51
+ return False
52
+
53
+
54
+ class TemporalServerRuntime(BaseProcessSupervisor):
55
+ """Temporal dev server, supervised via BaseProcessSupervisor.
56
+
57
+ Spawns ``temporal server start-dev`` against a SQLite db at
58
+ ``settings.temporal_sqlite_path``. The ``temporal`` CLI binary is
59
+ downloaded by :func:`services.temporal._install.ensure_temporal_binaries`
60
+ from the official URL at
61
+ https://temporal.download/cli/archive/latest.
62
+
63
+ Path is env-driven via ``settings.temporal_sqlite_path``, resolved
64
+ relative to ``settings.data_dir`` unless already absolute.
65
+ """
66
+
67
+ name = "temporal"
68
+ pipe_streams = True
69
+ graceful_shutdown = sys.platform == "win32"
70
+
71
+ def __init__(self, settings: Optional[Settings] = None) -> None:
72
+ super().__init__()
73
+ if settings is None:
74
+ settings = Settings()
75
+ self.settings = settings
76
+ # SIGTERM grace = settings.temporal_graceful_shutdown_seconds —
77
+ # same knob already documented for the embedded Temporal worker.
78
+ self.terminate_grace_seconds = float(
79
+ settings.temporal_graceful_shutdown_seconds,
80
+ )
81
+ self._binaries: Optional[dict[str, Path]] = None
82
+
83
+ @property
84
+ def _sqlite_path(self) -> Path:
85
+ """Env-driven SQLite db path (``TEMPORAL_SQLITE_PATH``),
86
+ resolved relative to ``DATA_DIR`` unless absolute."""
87
+ return Path(self.settings._resolve_under_data(self.settings.temporal_sqlite_path))
88
+
89
+ # ---- BaseProcessSupervisor overrides ---------------------------------
90
+
91
+ async def _pre_spawn(self) -> None:
92
+ from services.temporal._install import ensure_temporal_binaries
93
+
94
+ self._binaries = await ensure_temporal_binaries(self.settings)
95
+ # Ensure the parent dir for the SQLite file exists before
96
+ # ``temporal server start-dev`` opens it.
97
+ self._sqlite_path.parent.mkdir(parents=True, exist_ok=True)
98
+
99
+ def binary_path(self) -> Path:
100
+ # ``_pre_spawn`` (called by ``BaseProcessSupervisor._do_start``
101
+ # before this method) populates ``self._binaries`` via the
102
+ # pooch downloader. Loud failure if that contract regresses.
103
+ assert self._binaries is not None, f"[{self.label}] binary_path() called before _pre_spawn() " "populated self._binaries"
104
+ return self._binaries["temporal"]
105
+
106
+ def argv(self) -> list[str]:
107
+ # ``temporal server start-dev`` is the official subcommand for
108
+ # the SQLite-backed dev server. Flags documented at
109
+ # https://docs.temporal.io/cli/server (subset we use):
110
+ # --port frontend gRPC port (gates ready-probe)
111
+ # --ui-port Web UI port (default ``--port + 1000``)
112
+ # --db-filename SQLite file — preserves history across
113
+ # restarts. Running workflows are not
114
+ # auto-resumed; see ``TemporalClientWrapper.
115
+ # terminate_running_workflows`` (run from
116
+ # ``main.py`` lifespan) for the boot-time
117
+ # terminate-but-preserve-history behaviour.
118
+ # --metrics-port 0 disables the Prometheus endpoint
119
+ # --log-level warn keeps the supervisor log readable
120
+ # --namespace default namespace bootstrapped at start
121
+ return [
122
+ str(self.binary_path()),
123
+ "server",
124
+ "start-dev",
125
+ "--port",
126
+ str(self.settings.temporal_frontend_grpc_port),
127
+ "--ui-port",
128
+ str(self.settings.temporal_ui_port),
129
+ "--db-filename",
130
+ str(self._sqlite_path),
131
+ "--metrics-port",
132
+ "0",
133
+ "--log-level",
134
+ "warn",
135
+ "--namespace",
136
+ self.settings.temporal_namespace,
137
+ ]
138
+
139
+ def cwd(self) -> Path:
140
+ # Land any incidental output / log files next to the SQLite
141
+ # file (when persisting) or under DATA_DIR (when in-memory) —
142
+ # either way, never the supervisor's own working directory.
143
+ return self._sqlite_path.parent
144
+
145
+ def env(self) -> dict[str, str]:
146
+ # ``temporal server start-dev`` reads everything from argv flags;
147
+ # inherit parent env only.
148
+ return {**os.environ}
149
+
150
+ async def health_check(self) -> bool:
151
+ if not self.is_running():
152
+ return False
153
+ # gRPC frontend port — configured via
154
+ # ``settings.temporal_frontend_grpc_port``. Same shared probe
155
+ # MachinaOS uses for every other supervised TCP service.
156
+ return await _probe_tcp_port(self.settings.temporal_frontend_grpc_port)
157
+
158
+ def _extra_status(self) -> dict[str, Any]:
159
+ base = super()._extra_status()
160
+ return {
161
+ **base,
162
+ "grpc_port": self.settings.temporal_frontend_grpc_port,
163
+ "ui_port": self.settings.temporal_ui_port,
164
+ "sqlite_path": str(self._sqlite_path),
165
+ }
166
+
167
+
168
+ # ---- module-level singleton accessor ------------------------------------
169
+
170
+
171
+ def get_temporal_server_runtime(
172
+ settings: Optional[Settings] = None,
173
+ ) -> TemporalServerRuntime:
174
+ """Return the Temporal server runtime singleton."""
175
+ return TemporalServerRuntime.get_instance(settings)
176
+
177
+
178
+ __all__ = [
179
+ "TemporalServerRuntime",
180
+ "get_temporal_server_runtime",
181
+ ]
@@ -0,0 +1,102 @@
1
+ """Generic bridge: run any ``BaseSupervisor`` singleton from a CLI.
2
+
3
+ The CLI's ``Manager`` supervisor (``cli/supervisor.py``) schedules
4
+ ``ServiceSpec`` entries by spawning a subprocess and supervising it.
5
+ ``BaseSupervisor``-managed runtimes (e.g. the Temporal CLI dev server)
6
+ don't ship a CLI of their own -- they're Python singletons started via
7
+ ``await runtime.start()``.
8
+
9
+ This shim bridges the two: import a runtime factory by dotted path,
10
+ call it, ``await singleton.start()``, then block on a shutdown signal.
11
+ ``Manager`` sends SIGTERM during graceful shutdown; we catch it,
12
+ ``await singleton.stop()``, then exit cleanly.
13
+
14
+ Module location: this lives inside the ``server`` package because the
15
+ factory targets it resolves
16
+ (``services.temporal._runtime:get_temporal_server_runtime``) are
17
+ server-side singletons. Hosting the shim here keeps the CLI free of
18
+ server-side imports and lets a single ``uv run python -m
19
+ services.temporal._supervised_runtime <factory>`` invocation work
20
+ against the workspace ``.venv`` -- no PYTHONPATH composition, no
21
+ cross-venv plumbing.
22
+
23
+ Invocation (inside ``ServiceSpec.argv``, built via ``cli.run.uv_run``):
24
+
25
+ uv_run("python", "-m",
26
+ "services.temporal._supervised_runtime",
27
+ "services.temporal._runtime:get_temporal_server_runtime")
28
+
29
+ Equivalent to (Python idiom):
30
+
31
+ from services.temporal._runtime import get_temporal_server_runtime
32
+ runtime = get_temporal_server_runtime()
33
+ await runtime.start()
34
+ await asyncio.Event().wait() # block on signal
35
+ """
36
+
37
+ from __future__ import annotations
38
+
39
+ import asyncio
40
+ import importlib
41
+ import signal
42
+ import sys
43
+ from typing import Awaitable, Callable
44
+
45
+
46
+ def _resolve(dotted: str) -> Callable[[], Awaitable[None]]:
47
+ """Resolve ``module.path:attr`` to a callable factory."""
48
+ if ":" not in dotted:
49
+ raise SystemExit(f"factory must be 'module.path:attr', got {dotted!r}")
50
+ mod_path, attr = dotted.split(":", 1)
51
+ mod = importlib.import_module(mod_path)
52
+ factory = getattr(mod, attr, None)
53
+ if factory is None:
54
+ raise SystemExit(f"{mod_path}.{attr} not found")
55
+ return factory
56
+
57
+
58
+ async def _run(factory_dotted: str) -> int:
59
+ factory = _resolve(factory_dotted)
60
+ runtime = factory()
61
+ stop = asyncio.Event()
62
+
63
+ def _on_signal() -> None:
64
+ if not stop.is_set():
65
+ stop.set()
66
+
67
+ loop = asyncio.get_running_loop()
68
+ for sig in (signal.SIGINT, signal.SIGTERM):
69
+ try:
70
+ loop.add_signal_handler(sig, _on_signal)
71
+ except NotImplementedError:
72
+ # Windows: add_signal_handler raises for SIGTERM. The
73
+ # Manager supervisor's tree-kill semantics (psutil-based)
74
+ # work regardless -- we just lose the graceful path on Win.
75
+ pass
76
+
77
+ print(f"[supervised_runtime] starting {factory_dotted}", flush=True)
78
+ try:
79
+ await runtime.start()
80
+ print(f"[supervised_runtime] {factory_dotted} ready", flush=True)
81
+ await stop.wait()
82
+ finally:
83
+ print(f"[supervised_runtime] stopping {factory_dotted}", flush=True)
84
+ await runtime.stop()
85
+ return 0
86
+
87
+
88
+ def main() -> int:
89
+ if len(sys.argv) != 2:
90
+ print(
91
+ "usage: python -m services.temporal._supervised_runtime " "<module.path:factory>",
92
+ file=sys.stderr,
93
+ )
94
+ return 2
95
+ try:
96
+ return asyncio.run(_run(sys.argv[1]))
97
+ except KeyboardInterrupt:
98
+ return 0
99
+
100
+
101
+ if __name__ == "__main__":
102
+ raise SystemExit(main())