machinaos 0.0.1 → 0.0.6

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 (420) hide show
  1. package/.env.template +71 -71
  2. package/LICENSE +21 -21
  3. package/README.md +145 -87
  4. package/bin/cli.js +62 -106
  5. package/client/.dockerignore +45 -45
  6. package/client/Dockerfile +68 -68
  7. package/client/dist/assets/index-DFSC53FP.css +1 -0
  8. package/client/dist/assets/index-fJ-1gTf5.js +613 -0
  9. package/client/dist/index.html +14 -0
  10. package/client/eslint.config.js +34 -16
  11. package/client/nginx.conf +66 -66
  12. package/client/package.json +61 -48
  13. package/client/src/App.tsx +27 -27
  14. package/client/src/Dashboard.tsx +1200 -1172
  15. package/client/src/ParameterPanel.tsx +302 -300
  16. package/client/src/components/AIAgentNode.tsx +315 -321
  17. package/client/src/components/APIKeyValidator.tsx +117 -117
  18. package/client/src/components/ClaudeChatModelNode.tsx +17 -17
  19. package/client/src/components/CredentialsModal.tsx +1200 -306
  20. package/client/src/components/GeminiChatModelNode.tsx +17 -17
  21. package/client/src/components/GenericNode.tsx +356 -356
  22. package/client/src/components/LocationParameterPanel.tsx +153 -153
  23. package/client/src/components/ModelNode.tsx +285 -285
  24. package/client/src/components/OpenAIChatModelNode.tsx +17 -17
  25. package/client/src/components/OutputPanel.tsx +470 -470
  26. package/client/src/components/ParameterRenderer.tsx +1873 -1873
  27. package/client/src/components/SkillEditorModal.tsx +3 -3
  28. package/client/src/components/SquareNode.tsx +812 -796
  29. package/client/src/components/ToolkitNode.tsx +365 -365
  30. package/client/src/components/auth/LoginPage.tsx +247 -247
  31. package/client/src/components/auth/ProtectedRoute.tsx +59 -59
  32. package/client/src/components/base/BaseChatModelNode.tsx +270 -270
  33. package/client/src/components/icons/AIProviderIcons.tsx +50 -50
  34. package/client/src/components/maps/GoogleMapsPicker.tsx +136 -136
  35. package/client/src/components/maps/MapsPreviewPanel.tsx +109 -109
  36. package/client/src/components/maps/index.ts +25 -25
  37. package/client/src/components/parameterPanel/InputSection.tsx +1094 -1094
  38. package/client/src/components/parameterPanel/LocationPanelLayout.tsx +64 -64
  39. package/client/src/components/parameterPanel/MapsSection.tsx +91 -91
  40. package/client/src/components/parameterPanel/MiddleSection.tsx +867 -571
  41. package/client/src/components/parameterPanel/OutputSection.tsx +80 -80
  42. package/client/src/components/parameterPanel/ParameterPanelLayout.tsx +81 -81
  43. package/client/src/components/parameterPanel/ToolSchemaEditor.tsx +436 -436
  44. package/client/src/components/parameterPanel/index.ts +41 -41
  45. package/client/src/components/shared/DataPanel.tsx +142 -142
  46. package/client/src/components/shared/JSONTreeRenderer.tsx +105 -105
  47. package/client/src/components/ui/AIResultModal.tsx +203 -203
  48. package/client/src/components/ui/ApiKeyInput.tsx +93 -0
  49. package/client/src/components/ui/CodeEditor.tsx +81 -81
  50. package/client/src/components/ui/CollapsibleSection.tsx +87 -87
  51. package/client/src/components/ui/ComponentItem.tsx +153 -153
  52. package/client/src/components/ui/ComponentPalette.tsx +320 -320
  53. package/client/src/components/ui/ConsolePanel.tsx +151 -43
  54. package/client/src/components/ui/ErrorBoundary.tsx +195 -195
  55. package/client/src/components/ui/InputNodesPanel.tsx +203 -203
  56. package/client/src/components/ui/MapSelector.tsx +313 -313
  57. package/client/src/components/ui/Modal.tsx +151 -148
  58. package/client/src/components/ui/NodeOutputPanel.tsx +1150 -1150
  59. package/client/src/components/ui/OutputDisplayPanel.tsx +381 -381
  60. package/client/src/components/ui/QRCodeDisplay.tsx +182 -0
  61. package/client/src/components/ui/TopToolbar.tsx +736 -736
  62. package/client/src/components/ui/WorkflowSidebar.tsx +293 -293
  63. package/client/src/config/antdTheme.ts +186 -186
  64. package/client/src/contexts/AuthContext.tsx +221 -221
  65. package/client/src/contexts/ThemeContext.tsx +42 -42
  66. package/client/src/contexts/WebSocketContext.tsx +2144 -1971
  67. package/client/src/factories/baseChatModelFactory.ts +255 -255
  68. package/client/src/hooks/useAndroidOperations.ts +118 -164
  69. package/client/src/hooks/useApiKeyValidation.ts +106 -106
  70. package/client/src/hooks/useApiKeys.ts +238 -238
  71. package/client/src/hooks/useAppTheme.ts +17 -17
  72. package/client/src/hooks/useComponentPalette.ts +50 -50
  73. package/client/src/hooks/useDragAndDrop.ts +123 -123
  74. package/client/src/hooks/useDragVariable.ts +88 -88
  75. package/client/src/hooks/useExecution.ts +319 -313
  76. package/client/src/hooks/useParameterPanel.ts +176 -176
  77. package/client/src/hooks/useReactFlowNodes.ts +188 -188
  78. package/client/src/hooks/useToolSchema.ts +209 -209
  79. package/client/src/hooks/useWhatsApp.ts +196 -196
  80. package/client/src/hooks/useWorkflowManagement.ts +45 -45
  81. package/client/src/index.css +314 -314
  82. package/client/src/nodeDefinitions/aiAgentNodes.ts +335 -335
  83. package/client/src/nodeDefinitions/aiModelNodes.ts +340 -340
  84. package/client/src/nodeDefinitions/androidServiceNodes.ts +383 -383
  85. package/client/src/nodeDefinitions/chatNodes.ts +135 -135
  86. package/client/src/nodeDefinitions/codeNodes.ts +54 -54
  87. package/client/src/nodeDefinitions/index.ts +14 -14
  88. package/client/src/nodeDefinitions/locationNodes.ts +462 -462
  89. package/client/src/nodeDefinitions/schedulerNodes.ts +220 -220
  90. package/client/src/nodeDefinitions/skillNodes.ts +17 -5
  91. package/client/src/nodeDefinitions/utilityNodes.ts +284 -284
  92. package/client/src/nodeDefinitions/whatsappNodes.ts +821 -865
  93. package/client/src/nodeDefinitions.ts +101 -103
  94. package/client/src/services/dynamicParameterService.ts +95 -95
  95. package/client/src/services/execution/aiAgentExecutionService.ts +34 -34
  96. package/client/src/services/executionService.ts +227 -231
  97. package/client/src/services/workflowApi.ts +91 -91
  98. package/client/src/store/useAppStore.ts +578 -581
  99. package/client/src/styles/theme.ts +513 -508
  100. package/client/src/styles/zIndex.ts +16 -16
  101. package/client/src/types/ComponentTypes.ts +38 -38
  102. package/client/src/types/INodeProperties.ts +287 -287
  103. package/client/src/types/NodeTypes.ts +27 -27
  104. package/client/src/utils/formatters.ts +32 -32
  105. package/client/src/utils/googleMapsLoader.ts +139 -139
  106. package/client/src/utils/locationUtils.ts +84 -84
  107. package/client/src/utils/nodeUtils.ts +30 -30
  108. package/client/src/utils/workflow.ts +29 -29
  109. package/client/src/vite-env.d.ts +12 -12
  110. package/client/tailwind.config.js +59 -59
  111. package/client/tsconfig.json +25 -25
  112. package/client/vite.config.js +35 -35
  113. package/package.json +78 -70
  114. package/scripts/build.js +153 -45
  115. package/scripts/clean.js +40 -40
  116. package/scripts/start.js +234 -210
  117. package/scripts/stop.js +301 -325
  118. package/server/.dockerignore +44 -44
  119. package/server/Dockerfile +45 -45
  120. package/server/constants.py +244 -249
  121. package/server/core/cache.py +460 -460
  122. package/server/core/config.py +127 -127
  123. package/server/core/container.py +98 -98
  124. package/server/core/database.py +1296 -1210
  125. package/server/core/logging.py +313 -313
  126. package/server/main.py +288 -288
  127. package/server/middleware/__init__.py +5 -5
  128. package/server/middleware/auth.py +89 -89
  129. package/server/models/auth.py +52 -52
  130. package/server/models/cache.py +24 -24
  131. package/server/models/database.py +235 -210
  132. package/server/models/nodes.py +435 -455
  133. package/server/pyproject.toml +75 -72
  134. package/server/requirements.txt +83 -83
  135. package/server/routers/android.py +294 -294
  136. package/server/routers/auth.py +203 -203
  137. package/server/routers/database.py +150 -150
  138. package/server/routers/maps.py +141 -141
  139. package/server/routers/nodejs_compat.py +288 -288
  140. package/server/routers/webhook.py +90 -90
  141. package/server/routers/websocket.py +2239 -2127
  142. package/server/routers/whatsapp.py +761 -761
  143. package/server/routers/workflow.py +199 -199
  144. package/server/services/ai.py +2444 -2414
  145. package/server/services/android_service.py +588 -588
  146. package/server/services/auth.py +130 -130
  147. package/server/services/chat_client.py +160 -160
  148. package/server/services/deployment/manager.py +706 -706
  149. package/server/services/event_waiter.py +675 -785
  150. package/server/services/execution/executor.py +1351 -1351
  151. package/server/services/execution/models.py +1 -1
  152. package/server/services/handlers/__init__.py +122 -126
  153. package/server/services/handlers/ai.py +390 -355
  154. package/server/services/handlers/android.py +69 -260
  155. package/server/services/handlers/code.py +278 -278
  156. package/server/services/handlers/http.py +193 -193
  157. package/server/services/handlers/tools.py +146 -32
  158. package/server/services/handlers/triggers.py +107 -107
  159. package/server/services/handlers/utility.py +822 -822
  160. package/server/services/handlers/whatsapp.py +423 -476
  161. package/server/services/maps.py +288 -288
  162. package/server/services/memory_store.py +103 -103
  163. package/server/services/node_executor.py +372 -375
  164. package/server/services/scheduler.py +155 -155
  165. package/server/services/skill_loader.py +1 -1
  166. package/server/services/status_broadcaster.py +834 -826
  167. package/server/services/temporal/__init__.py +23 -23
  168. package/server/services/temporal/activities.py +344 -344
  169. package/server/services/temporal/client.py +76 -76
  170. package/server/services/temporal/executor.py +147 -147
  171. package/server/services/temporal/worker.py +251 -251
  172. package/server/services/temporal/workflow.py +355 -355
  173. package/server/services/temporal/ws_client.py +236 -236
  174. package/server/services/text.py +110 -110
  175. package/server/services/user_auth.py +172 -172
  176. package/server/services/websocket_client.py +29 -29
  177. package/server/services/workflow.py +597 -597
  178. package/server/skills/android-skill/SKILL.md +4 -4
  179. package/server/skills/code-skill/SKILL.md +123 -89
  180. package/server/skills/maps-skill/SKILL.md +3 -3
  181. package/server/skills/memory-skill/SKILL.md +1 -1
  182. package/server/skills/web-search-skill/SKILL.md +154 -0
  183. package/server/skills/whatsapp-skill/SKILL.md +3 -3
  184. package/server/uv.lock +461 -100
  185. package/server/whatsapp-rpc/.dockerignore +30 -30
  186. package/server/whatsapp-rpc/Dockerfile +44 -44
  187. package/server/whatsapp-rpc/Dockerfile.web +17 -17
  188. package/server/whatsapp-rpc/README.md +139 -139
  189. package/server/whatsapp-rpc/bin/whatsapp-rpc-server +0 -0
  190. package/server/whatsapp-rpc/cli.js +95 -95
  191. package/server/whatsapp-rpc/configs/config.yaml +6 -6
  192. package/server/whatsapp-rpc/docker-compose.yml +35 -35
  193. package/server/whatsapp-rpc/docs/API.md +410 -410
  194. package/server/whatsapp-rpc/node_modules/.package-lock.json +259 -0
  195. package/server/whatsapp-rpc/node_modules/chalk/license +9 -0
  196. package/server/whatsapp-rpc/node_modules/chalk/package.json +83 -0
  197. package/server/whatsapp-rpc/node_modules/chalk/readme.md +297 -0
  198. package/server/whatsapp-rpc/node_modules/chalk/source/index.d.ts +325 -0
  199. package/server/whatsapp-rpc/node_modules/chalk/source/index.js +225 -0
  200. package/server/whatsapp-rpc/node_modules/chalk/source/utilities.js +33 -0
  201. package/server/whatsapp-rpc/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
  202. package/server/whatsapp-rpc/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
  203. package/server/whatsapp-rpc/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
  204. package/server/whatsapp-rpc/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
  205. package/server/whatsapp-rpc/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
  206. package/server/whatsapp-rpc/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
  207. package/server/whatsapp-rpc/node_modules/commander/LICENSE +22 -0
  208. package/server/whatsapp-rpc/node_modules/commander/Readme.md +1148 -0
  209. package/server/whatsapp-rpc/node_modules/commander/esm.mjs +16 -0
  210. package/server/whatsapp-rpc/node_modules/commander/index.js +26 -0
  211. package/server/whatsapp-rpc/node_modules/commander/lib/argument.js +145 -0
  212. package/server/whatsapp-rpc/node_modules/commander/lib/command.js +2179 -0
  213. package/server/whatsapp-rpc/node_modules/commander/lib/error.js +43 -0
  214. package/server/whatsapp-rpc/node_modules/commander/lib/help.js +462 -0
  215. package/server/whatsapp-rpc/node_modules/commander/lib/option.js +329 -0
  216. package/server/whatsapp-rpc/node_modules/commander/lib/suggestSimilar.js +100 -0
  217. package/server/whatsapp-rpc/node_modules/commander/package-support.json +16 -0
  218. package/server/whatsapp-rpc/node_modules/commander/package.json +80 -0
  219. package/server/whatsapp-rpc/node_modules/commander/typings/esm.d.mts +3 -0
  220. package/server/whatsapp-rpc/node_modules/commander/typings/index.d.ts +884 -0
  221. package/server/whatsapp-rpc/node_modules/cross-spawn/LICENSE +21 -0
  222. package/server/whatsapp-rpc/node_modules/cross-spawn/README.md +89 -0
  223. package/server/whatsapp-rpc/node_modules/cross-spawn/index.js +39 -0
  224. package/server/whatsapp-rpc/node_modules/cross-spawn/lib/enoent.js +59 -0
  225. package/server/whatsapp-rpc/node_modules/cross-spawn/lib/parse.js +91 -0
  226. package/server/whatsapp-rpc/node_modules/cross-spawn/lib/util/escape.js +47 -0
  227. package/server/whatsapp-rpc/node_modules/cross-spawn/lib/util/readShebang.js +23 -0
  228. package/server/whatsapp-rpc/node_modules/cross-spawn/lib/util/resolveCommand.js +52 -0
  229. package/server/whatsapp-rpc/node_modules/cross-spawn/package.json +73 -0
  230. package/server/whatsapp-rpc/node_modules/execa/index.d.ts +955 -0
  231. package/server/whatsapp-rpc/node_modules/execa/index.js +309 -0
  232. package/server/whatsapp-rpc/node_modules/execa/lib/command.js +119 -0
  233. package/server/whatsapp-rpc/node_modules/execa/lib/error.js +87 -0
  234. package/server/whatsapp-rpc/node_modules/execa/lib/kill.js +102 -0
  235. package/server/whatsapp-rpc/node_modules/execa/lib/pipe.js +42 -0
  236. package/server/whatsapp-rpc/node_modules/execa/lib/promise.js +36 -0
  237. package/server/whatsapp-rpc/node_modules/execa/lib/stdio.js +49 -0
  238. package/server/whatsapp-rpc/node_modules/execa/lib/stream.js +133 -0
  239. package/server/whatsapp-rpc/node_modules/execa/lib/verbose.js +19 -0
  240. package/server/whatsapp-rpc/node_modules/execa/license +9 -0
  241. package/server/whatsapp-rpc/node_modules/execa/package.json +90 -0
  242. package/server/whatsapp-rpc/node_modules/execa/readme.md +822 -0
  243. package/server/whatsapp-rpc/node_modules/get-stream/license +9 -0
  244. package/server/whatsapp-rpc/node_modules/get-stream/package.json +53 -0
  245. package/server/whatsapp-rpc/node_modules/get-stream/readme.md +291 -0
  246. package/server/whatsapp-rpc/node_modules/get-stream/source/array-buffer.js +84 -0
  247. package/server/whatsapp-rpc/node_modules/get-stream/source/array.js +32 -0
  248. package/server/whatsapp-rpc/node_modules/get-stream/source/buffer.js +20 -0
  249. package/server/whatsapp-rpc/node_modules/get-stream/source/contents.js +101 -0
  250. package/server/whatsapp-rpc/node_modules/get-stream/source/index.d.ts +119 -0
  251. package/server/whatsapp-rpc/node_modules/get-stream/source/index.js +5 -0
  252. package/server/whatsapp-rpc/node_modules/get-stream/source/string.js +36 -0
  253. package/server/whatsapp-rpc/node_modules/get-stream/source/utils.js +11 -0
  254. package/server/whatsapp-rpc/node_modules/get-them-args/LICENSE +21 -0
  255. package/server/whatsapp-rpc/node_modules/get-them-args/README.md +95 -0
  256. package/server/whatsapp-rpc/node_modules/get-them-args/index.js +97 -0
  257. package/server/whatsapp-rpc/node_modules/get-them-args/package.json +36 -0
  258. package/server/whatsapp-rpc/node_modules/human-signals/LICENSE +201 -0
  259. package/server/whatsapp-rpc/node_modules/human-signals/README.md +168 -0
  260. package/server/whatsapp-rpc/node_modules/human-signals/build/src/core.js +273 -0
  261. package/server/whatsapp-rpc/node_modules/human-signals/build/src/main.d.ts +73 -0
  262. package/server/whatsapp-rpc/node_modules/human-signals/build/src/main.js +70 -0
  263. package/server/whatsapp-rpc/node_modules/human-signals/build/src/realtime.js +16 -0
  264. package/server/whatsapp-rpc/node_modules/human-signals/build/src/signals.js +34 -0
  265. package/server/whatsapp-rpc/node_modules/human-signals/package.json +61 -0
  266. package/server/whatsapp-rpc/node_modules/is-stream/index.d.ts +81 -0
  267. package/server/whatsapp-rpc/node_modules/is-stream/index.js +29 -0
  268. package/server/whatsapp-rpc/node_modules/is-stream/license +9 -0
  269. package/server/whatsapp-rpc/node_modules/is-stream/package.json +44 -0
  270. package/server/whatsapp-rpc/node_modules/is-stream/readme.md +60 -0
  271. package/server/whatsapp-rpc/node_modules/isexe/LICENSE +15 -0
  272. package/server/whatsapp-rpc/node_modules/isexe/README.md +51 -0
  273. package/server/whatsapp-rpc/node_modules/isexe/index.js +57 -0
  274. package/server/whatsapp-rpc/node_modules/isexe/mode.js +41 -0
  275. package/server/whatsapp-rpc/node_modules/isexe/package.json +31 -0
  276. package/server/whatsapp-rpc/node_modules/isexe/test/basic.js +221 -0
  277. package/server/whatsapp-rpc/node_modules/isexe/windows.js +42 -0
  278. package/server/whatsapp-rpc/node_modules/kill-port/.editorconfig +12 -0
  279. package/server/whatsapp-rpc/node_modules/kill-port/.gitattributes +1 -0
  280. package/server/whatsapp-rpc/node_modules/kill-port/LICENSE +21 -0
  281. package/server/whatsapp-rpc/node_modules/kill-port/README.md +140 -0
  282. package/server/whatsapp-rpc/node_modules/kill-port/cli.js +25 -0
  283. package/server/whatsapp-rpc/node_modules/kill-port/example.js +21 -0
  284. package/server/whatsapp-rpc/node_modules/kill-port/index.js +46 -0
  285. package/server/whatsapp-rpc/node_modules/kill-port/logo.png +0 -0
  286. package/server/whatsapp-rpc/node_modules/kill-port/package.json +41 -0
  287. package/server/whatsapp-rpc/node_modules/kill-port/pnpm-lock.yaml +4606 -0
  288. package/server/whatsapp-rpc/node_modules/kill-port/test.js +16 -0
  289. package/server/whatsapp-rpc/node_modules/merge-stream/LICENSE +21 -0
  290. package/server/whatsapp-rpc/node_modules/merge-stream/README.md +78 -0
  291. package/server/whatsapp-rpc/node_modules/merge-stream/index.js +41 -0
  292. package/server/whatsapp-rpc/node_modules/merge-stream/package.json +19 -0
  293. package/server/whatsapp-rpc/node_modules/mimic-fn/index.d.ts +52 -0
  294. package/server/whatsapp-rpc/node_modules/mimic-fn/index.js +71 -0
  295. package/server/whatsapp-rpc/node_modules/mimic-fn/license +9 -0
  296. package/server/whatsapp-rpc/node_modules/mimic-fn/package.json +45 -0
  297. package/server/whatsapp-rpc/node_modules/mimic-fn/readme.md +90 -0
  298. package/server/whatsapp-rpc/node_modules/npm-run-path/index.d.ts +90 -0
  299. package/server/whatsapp-rpc/node_modules/npm-run-path/index.js +52 -0
  300. package/server/whatsapp-rpc/node_modules/npm-run-path/license +9 -0
  301. package/server/whatsapp-rpc/node_modules/npm-run-path/node_modules/path-key/index.d.ts +31 -0
  302. package/server/whatsapp-rpc/node_modules/npm-run-path/node_modules/path-key/index.js +12 -0
  303. package/server/whatsapp-rpc/node_modules/npm-run-path/node_modules/path-key/license +9 -0
  304. package/server/whatsapp-rpc/node_modules/npm-run-path/node_modules/path-key/package.json +41 -0
  305. package/server/whatsapp-rpc/node_modules/npm-run-path/node_modules/path-key/readme.md +57 -0
  306. package/server/whatsapp-rpc/node_modules/npm-run-path/package.json +49 -0
  307. package/server/whatsapp-rpc/node_modules/npm-run-path/readme.md +104 -0
  308. package/server/whatsapp-rpc/node_modules/onetime/index.d.ts +59 -0
  309. package/server/whatsapp-rpc/node_modules/onetime/index.js +41 -0
  310. package/server/whatsapp-rpc/node_modules/onetime/license +9 -0
  311. package/server/whatsapp-rpc/node_modules/onetime/package.json +45 -0
  312. package/server/whatsapp-rpc/node_modules/onetime/readme.md +94 -0
  313. package/server/whatsapp-rpc/node_modules/path-key/index.d.ts +40 -0
  314. package/server/whatsapp-rpc/node_modules/path-key/index.js +16 -0
  315. package/server/whatsapp-rpc/node_modules/path-key/license +9 -0
  316. package/server/whatsapp-rpc/node_modules/path-key/package.json +39 -0
  317. package/server/whatsapp-rpc/node_modules/path-key/readme.md +61 -0
  318. package/server/whatsapp-rpc/node_modules/shebang-command/index.js +19 -0
  319. package/server/whatsapp-rpc/node_modules/shebang-command/license +9 -0
  320. package/server/whatsapp-rpc/node_modules/shebang-command/package.json +34 -0
  321. package/server/whatsapp-rpc/node_modules/shebang-command/readme.md +34 -0
  322. package/server/whatsapp-rpc/node_modules/shebang-regex/index.d.ts +22 -0
  323. package/server/whatsapp-rpc/node_modules/shebang-regex/index.js +2 -0
  324. package/server/whatsapp-rpc/node_modules/shebang-regex/license +9 -0
  325. package/server/whatsapp-rpc/node_modules/shebang-regex/package.json +35 -0
  326. package/server/whatsapp-rpc/node_modules/shebang-regex/readme.md +33 -0
  327. package/server/whatsapp-rpc/node_modules/shell-exec/LICENSE +21 -0
  328. package/server/whatsapp-rpc/node_modules/shell-exec/README.md +60 -0
  329. package/server/whatsapp-rpc/node_modules/shell-exec/index.js +47 -0
  330. package/server/whatsapp-rpc/node_modules/shell-exec/package.json +29 -0
  331. package/server/whatsapp-rpc/node_modules/signal-exit/LICENSE.txt +16 -0
  332. package/server/whatsapp-rpc/node_modules/signal-exit/README.md +74 -0
  333. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/browser.d.ts +12 -0
  334. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/browser.d.ts.map +1 -0
  335. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/browser.js +10 -0
  336. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/browser.js.map +1 -0
  337. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/index.d.ts +48 -0
  338. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/index.d.ts.map +1 -0
  339. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/index.js +279 -0
  340. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/index.js.map +1 -0
  341. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/package.json +3 -0
  342. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/signals.d.ts +29 -0
  343. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/signals.d.ts.map +1 -0
  344. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/signals.js +42 -0
  345. package/server/whatsapp-rpc/node_modules/signal-exit/dist/cjs/signals.js.map +1 -0
  346. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/browser.d.ts +12 -0
  347. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/browser.d.ts.map +1 -0
  348. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/browser.js +4 -0
  349. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/browser.js.map +1 -0
  350. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/index.d.ts +48 -0
  351. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/index.d.ts.map +1 -0
  352. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/index.js +275 -0
  353. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/index.js.map +1 -0
  354. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/package.json +3 -0
  355. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/signals.d.ts +29 -0
  356. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/signals.d.ts.map +1 -0
  357. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/signals.js +39 -0
  358. package/server/whatsapp-rpc/node_modules/signal-exit/dist/mjs/signals.js.map +1 -0
  359. package/server/whatsapp-rpc/node_modules/signal-exit/package.json +106 -0
  360. package/server/whatsapp-rpc/node_modules/strip-final-newline/index.js +14 -0
  361. package/server/whatsapp-rpc/node_modules/strip-final-newline/license +9 -0
  362. package/server/whatsapp-rpc/node_modules/strip-final-newline/package.json +43 -0
  363. package/server/whatsapp-rpc/node_modules/strip-final-newline/readme.md +35 -0
  364. package/server/whatsapp-rpc/node_modules/which/CHANGELOG.md +166 -0
  365. package/server/whatsapp-rpc/node_modules/which/LICENSE +15 -0
  366. package/server/whatsapp-rpc/node_modules/which/README.md +54 -0
  367. package/server/whatsapp-rpc/node_modules/which/bin/node-which +52 -0
  368. package/server/whatsapp-rpc/node_modules/which/package.json +43 -0
  369. package/server/whatsapp-rpc/node_modules/which/which.js +125 -0
  370. package/server/whatsapp-rpc/package-lock.json +272 -0
  371. package/server/whatsapp-rpc/package.json +30 -30
  372. package/server/whatsapp-rpc/schema.json +1294 -1294
  373. package/server/whatsapp-rpc/scripts/clean.cjs +66 -66
  374. package/server/whatsapp-rpc/scripts/cli.js +162 -162
  375. package/server/whatsapp-rpc/src/go/whatsapp/history.go +166 -166
  376. package/server/whatsapp-rpc/src/python/pyproject.toml +15 -15
  377. package/server/whatsapp-rpc/src/python/whatsapp_rpc/__init__.py +4 -4
  378. package/server/whatsapp-rpc/src/python/whatsapp_rpc/client.py +427 -427
  379. package/server/whatsapp-rpc/web/app.py +609 -609
  380. package/server/whatsapp-rpc/web/requirements.txt +6 -6
  381. package/server/whatsapp-rpc/web/rpc_client.py +427 -427
  382. package/server/whatsapp-rpc/web/static/openapi.yaml +59 -59
  383. package/server/whatsapp-rpc/web/templates/base.html +149 -149
  384. package/server/whatsapp-rpc/web/templates/contacts.html +240 -240
  385. package/server/whatsapp-rpc/web/templates/dashboard.html +319 -319
  386. package/server/whatsapp-rpc/web/templates/groups.html +328 -328
  387. package/server/whatsapp-rpc/web/templates/messages.html +465 -465
  388. package/server/whatsapp-rpc/web/templates/messaging.html +680 -680
  389. package/server/whatsapp-rpc/web/templates/send.html +258 -258
  390. package/server/whatsapp-rpc/web/templates/settings.html +459 -459
  391. package/client/src/components/ui/AndroidSettingsPanel.tsx +0 -401
  392. package/client/src/components/ui/WhatsAppSettingsPanel.tsx +0 -345
  393. package/client/src/nodeDefinitions/androidDeviceNodes.ts +0 -140
  394. package/docker-compose.prod.yml +0 -107
  395. package/docker-compose.yml +0 -104
  396. package/docs-MachinaOs/README.md +0 -85
  397. package/docs-MachinaOs/deployment/docker.mdx +0 -228
  398. package/docs-MachinaOs/deployment/production.mdx +0 -345
  399. package/docs-MachinaOs/docs.json +0 -75
  400. package/docs-MachinaOs/faq.mdx +0 -309
  401. package/docs-MachinaOs/favicon.svg +0 -5
  402. package/docs-MachinaOs/installation.mdx +0 -160
  403. package/docs-MachinaOs/introduction.mdx +0 -114
  404. package/docs-MachinaOs/logo/dark.svg +0 -6
  405. package/docs-MachinaOs/logo/light.svg +0 -6
  406. package/docs-MachinaOs/nodes/ai-agent.mdx +0 -216
  407. package/docs-MachinaOs/nodes/ai-models.mdx +0 -240
  408. package/docs-MachinaOs/nodes/android.mdx +0 -411
  409. package/docs-MachinaOs/nodes/overview.mdx +0 -181
  410. package/docs-MachinaOs/nodes/schedulers.mdx +0 -316
  411. package/docs-MachinaOs/nodes/webhooks.mdx +0 -330
  412. package/docs-MachinaOs/nodes/whatsapp.mdx +0 -305
  413. package/docs-MachinaOs/quickstart.mdx +0 -119
  414. package/docs-MachinaOs/tutorials/ai-agent-workflow.mdx +0 -177
  415. package/docs-MachinaOs/tutorials/android-automation.mdx +0 -242
  416. package/docs-MachinaOs/tutorials/first-workflow.mdx +0 -134
  417. package/docs-MachinaOs/tutorials/whatsapp-automation.mdx +0 -185
  418. package/nul +0 -0
  419. package/scripts/check-ports.ps1 +0 -33
  420. package/scripts/kill-port.ps1 +0 -154
@@ -1,193 +1,193 @@
1
- """HTTP node handlers - HTTP Request and Webhook Response."""
2
-
3
- import json
4
- import time
5
- from datetime import datetime
6
- from typing import Dict, Any
7
- from core.logging import get_logger
8
-
9
- logger = get_logger(__name__)
10
-
11
-
12
- async def handle_http_request(
13
- node_id: str,
14
- node_type: str,
15
- parameters: Dict[str, Any],
16
- context: Dict[str, Any]
17
- ) -> Dict[str, Any]:
18
- """Handle HTTP request node execution.
19
-
20
- Makes HTTP requests to external APIs.
21
-
22
- Args:
23
- node_id: The node ID
24
- node_type: The node type (httpRequest)
25
- parameters: Resolved parameters
26
- context: Execution context
27
-
28
- Returns:
29
- Execution result dict with response data
30
- """
31
- import httpx
32
- start_time = time.time()
33
-
34
- try:
35
- method = parameters.get('method', 'GET')
36
- url = parameters.get('url', '')
37
- headers_str = parameters.get('headers', '{}')
38
- body = parameters.get('body', '')
39
- timeout = float(parameters.get('timeout', 30))
40
-
41
- if not url:
42
- raise ValueError("URL is required")
43
-
44
- # Parse headers JSON
45
- try:
46
- headers = json.loads(headers_str) if headers_str else {}
47
- except json.JSONDecodeError:
48
- headers = {}
49
-
50
- logger.info("[HTTP Request] Executing", node_id=node_id, method=method, url=url)
51
-
52
- async with httpx.AsyncClient() as client:
53
- kwargs = {
54
- 'method': method,
55
- 'url': url,
56
- 'headers': headers,
57
- 'timeout': timeout
58
- }
59
-
60
- # Add body for POST/PUT/PATCH
61
- if method in ['POST', 'PUT', 'PATCH'] and body:
62
- try:
63
- kwargs['json'] = json.loads(body)
64
- except json.JSONDecodeError:
65
- kwargs['content'] = body
66
-
67
- response = await client.request(**kwargs)
68
-
69
- # Parse response data
70
- try:
71
- response_data = response.json()
72
- except:
73
- response_data = response.text
74
-
75
- result_data = {
76
- "status": response.status_code,
77
- "data": response_data,
78
- "headers": dict(response.headers),
79
- "url": str(response.url),
80
- "method": method
81
- }
82
-
83
- return {
84
- "success": response.status_code < 400,
85
- "node_id": node_id,
86
- "node_type": "httpRequest",
87
- "result": result_data,
88
- "execution_time": time.time() - start_time,
89
- "timestamp": datetime.now().isoformat()
90
- }
91
-
92
- except Exception as e:
93
- if "TimeoutException" in type(e).__name__:
94
- logger.error("HTTP request timed out", node_id=node_id, url=parameters.get('url'))
95
- return {
96
- "success": False,
97
- "node_id": node_id,
98
- "node_type": "httpRequest",
99
- "error": f"Request timed out after {parameters.get('timeout', 30)} seconds",
100
- "execution_time": time.time() - start_time,
101
- "timestamp": datetime.now().isoformat()
102
- }
103
- logger.error("HTTP request failed", node_id=node_id, error=str(e))
104
- return {
105
- "success": False,
106
- "node_id": node_id,
107
- "node_type": "httpRequest",
108
- "error": str(e),
109
- "execution_time": time.time() - start_time,
110
- "timestamp": datetime.now().isoformat()
111
- }
112
-
113
-
114
- async def handle_webhook_response(
115
- node_id: str,
116
- node_type: str,
117
- parameters: Dict[str, Any],
118
- context: Dict[str, Any],
119
- connected_outputs: Dict[str, Any] = None
120
- ) -> Dict[str, Any]:
121
- """Handle webhook response node execution.
122
-
123
- Sends response back to waiting webhook caller.
124
-
125
- Args:
126
- node_id: The node ID
127
- node_type: The node type (webhookResponse)
128
- parameters: Resolved parameters
129
- context: Execution context
130
- connected_outputs: Outputs from connected nodes
131
-
132
- Returns:
133
- Execution result dict
134
- """
135
- from routers.webhook import resolve_webhook_response
136
- start_time = time.time()
137
-
138
- try:
139
- status_code = int(parameters.get('statusCode', 200))
140
- response_body = parameters.get('responseBody', '')
141
- content_type = parameters.get('contentType', 'application/json')
142
-
143
- # Resolve template variables in response body
144
- if response_body and connected_outputs:
145
- for node_type_key, output_data in connected_outputs.items():
146
- if isinstance(output_data, dict):
147
- for key, value in output_data.items():
148
- template = f"{{{{input.{key}}}}}"
149
- response_body = response_body.replace(template, str(value))
150
- # Also support {{nodeType.key}} format
151
- template_alt = f"{{{{{node_type_key}.{key}}}}}"
152
- response_body = response_body.replace(template_alt, str(value))
153
-
154
- # If response body is empty, serialize connected outputs as JSON
155
- if not response_body and connected_outputs:
156
- # Get the first connected output
157
- first_output = next(iter(connected_outputs.values()), {})
158
- response_body = json.dumps(first_output, default=str)
159
-
160
- logger.info("[Webhook Response] Sending", node_id=node_id, status_code=status_code,
161
- content_type=content_type, body_length=len(response_body))
162
-
163
- # Resolve the pending webhook response
164
- resolve_webhook_response(node_id, {
165
- 'statusCode': status_code,
166
- 'body': response_body,
167
- 'contentType': content_type
168
- })
169
-
170
- return {
171
- "success": True,
172
- "node_id": node_id,
173
- "node_type": "webhookResponse",
174
- "result": {
175
- "sent": True,
176
- "statusCode": status_code,
177
- "contentType": content_type,
178
- "bodyLength": len(response_body)
179
- },
180
- "execution_time": time.time() - start_time,
181
- "timestamp": datetime.now().isoformat()
182
- }
183
-
184
- except Exception as e:
185
- logger.error("Webhook response failed", node_id=node_id, error=str(e))
186
- return {
187
- "success": False,
188
- "node_id": node_id,
189
- "node_type": "webhookResponse",
190
- "error": str(e),
191
- "execution_time": time.time() - start_time,
192
- "timestamp": datetime.now().isoformat()
193
- }
1
+ """HTTP node handlers - HTTP Request and Webhook Response."""
2
+
3
+ import json
4
+ import time
5
+ from datetime import datetime
6
+ from typing import Dict, Any
7
+ from core.logging import get_logger
8
+
9
+ logger = get_logger(__name__)
10
+
11
+
12
+ async def handle_http_request(
13
+ node_id: str,
14
+ node_type: str,
15
+ parameters: Dict[str, Any],
16
+ context: Dict[str, Any]
17
+ ) -> Dict[str, Any]:
18
+ """Handle HTTP request node execution.
19
+
20
+ Makes HTTP requests to external APIs.
21
+
22
+ Args:
23
+ node_id: The node ID
24
+ node_type: The node type (httpRequest)
25
+ parameters: Resolved parameters
26
+ context: Execution context
27
+
28
+ Returns:
29
+ Execution result dict with response data
30
+ """
31
+ import httpx
32
+ start_time = time.time()
33
+
34
+ try:
35
+ method = parameters.get('method', 'GET')
36
+ url = parameters.get('url', '')
37
+ headers_str = parameters.get('headers', '{}')
38
+ body = parameters.get('body', '')
39
+ timeout = float(parameters.get('timeout', 30))
40
+
41
+ if not url:
42
+ raise ValueError("URL is required")
43
+
44
+ # Parse headers JSON
45
+ try:
46
+ headers = json.loads(headers_str) if headers_str else {}
47
+ except json.JSONDecodeError:
48
+ headers = {}
49
+
50
+ logger.info("[HTTP Request] Executing", node_id=node_id, method=method, url=url)
51
+
52
+ async with httpx.AsyncClient() as client:
53
+ kwargs = {
54
+ 'method': method,
55
+ 'url': url,
56
+ 'headers': headers,
57
+ 'timeout': timeout
58
+ }
59
+
60
+ # Add body for POST/PUT/PATCH
61
+ if method in ['POST', 'PUT', 'PATCH'] and body:
62
+ try:
63
+ kwargs['json'] = json.loads(body)
64
+ except json.JSONDecodeError:
65
+ kwargs['content'] = body
66
+
67
+ response = await client.request(**kwargs)
68
+
69
+ # Parse response data
70
+ try:
71
+ response_data = response.json()
72
+ except:
73
+ response_data = response.text
74
+
75
+ result_data = {
76
+ "status": response.status_code,
77
+ "data": response_data,
78
+ "headers": dict(response.headers),
79
+ "url": str(response.url),
80
+ "method": method
81
+ }
82
+
83
+ return {
84
+ "success": response.status_code < 400,
85
+ "node_id": node_id,
86
+ "node_type": "httpRequest",
87
+ "result": result_data,
88
+ "execution_time": time.time() - start_time,
89
+ "timestamp": datetime.now().isoformat()
90
+ }
91
+
92
+ except Exception as e:
93
+ if "TimeoutException" in type(e).__name__:
94
+ logger.error("HTTP request timed out", node_id=node_id, url=parameters.get('url'))
95
+ return {
96
+ "success": False,
97
+ "node_id": node_id,
98
+ "node_type": "httpRequest",
99
+ "error": f"Request timed out after {parameters.get('timeout', 30)} seconds",
100
+ "execution_time": time.time() - start_time,
101
+ "timestamp": datetime.now().isoformat()
102
+ }
103
+ logger.error("HTTP request failed", node_id=node_id, error=str(e))
104
+ return {
105
+ "success": False,
106
+ "node_id": node_id,
107
+ "node_type": "httpRequest",
108
+ "error": str(e),
109
+ "execution_time": time.time() - start_time,
110
+ "timestamp": datetime.now().isoformat()
111
+ }
112
+
113
+
114
+ async def handle_webhook_response(
115
+ node_id: str,
116
+ node_type: str,
117
+ parameters: Dict[str, Any],
118
+ context: Dict[str, Any],
119
+ connected_outputs: Dict[str, Any] = None
120
+ ) -> Dict[str, Any]:
121
+ """Handle webhook response node execution.
122
+
123
+ Sends response back to waiting webhook caller.
124
+
125
+ Args:
126
+ node_id: The node ID
127
+ node_type: The node type (webhookResponse)
128
+ parameters: Resolved parameters
129
+ context: Execution context
130
+ connected_outputs: Outputs from connected nodes
131
+
132
+ Returns:
133
+ Execution result dict
134
+ """
135
+ from routers.webhook import resolve_webhook_response
136
+ start_time = time.time()
137
+
138
+ try:
139
+ status_code = int(parameters.get('statusCode', 200))
140
+ response_body = parameters.get('responseBody', '')
141
+ content_type = parameters.get('contentType', 'application/json')
142
+
143
+ # Resolve template variables in response body
144
+ if response_body and connected_outputs:
145
+ for node_type_key, output_data in connected_outputs.items():
146
+ if isinstance(output_data, dict):
147
+ for key, value in output_data.items():
148
+ template = f"{{{{input.{key}}}}}"
149
+ response_body = response_body.replace(template, str(value))
150
+ # Also support {{nodeType.key}} format
151
+ template_alt = f"{{{{{node_type_key}.{key}}}}}"
152
+ response_body = response_body.replace(template_alt, str(value))
153
+
154
+ # If response body is empty, serialize connected outputs as JSON
155
+ if not response_body and connected_outputs:
156
+ # Get the first connected output
157
+ first_output = next(iter(connected_outputs.values()), {})
158
+ response_body = json.dumps(first_output, default=str)
159
+
160
+ logger.info("[Webhook Response] Sending", node_id=node_id, status_code=status_code,
161
+ content_type=content_type, body_length=len(response_body))
162
+
163
+ # Resolve the pending webhook response
164
+ resolve_webhook_response(node_id, {
165
+ 'statusCode': status_code,
166
+ 'body': response_body,
167
+ 'contentType': content_type
168
+ })
169
+
170
+ return {
171
+ "success": True,
172
+ "node_id": node_id,
173
+ "node_type": "webhookResponse",
174
+ "result": {
175
+ "sent": True,
176
+ "statusCode": status_code,
177
+ "contentType": content_type,
178
+ "bodyLength": len(response_body)
179
+ },
180
+ "execution_time": time.time() - start_time,
181
+ "timestamp": datetime.now().isoformat()
182
+ }
183
+
184
+ except Exception as e:
185
+ logger.error("Webhook response failed", node_id=node_id, error=str(e))
186
+ return {
187
+ "success": False,
188
+ "node_id": node_id,
189
+ "node_type": "webhookResponse",
190
+ "error": str(e),
191
+ "execution_time": time.time() - start_time,
192
+ "timestamp": datetime.now().isoformat()
193
+ }
@@ -40,10 +40,14 @@ async def execute_tool(tool_name: str, tool_args: Dict[str, Any],
40
40
  if node_type in ('httpRequest', 'httpRequestTool'):
41
41
  return await _execute_http_request(tool_args, config.get('parameters', {}))
42
42
 
43
- # Python executor tool
43
+ # Python executor tool (dual-purpose: workflow node + AI tool)
44
44
  if node_type == 'pythonExecutor':
45
45
  return await _execute_python_code(tool_args, config.get('parameters', {}))
46
46
 
47
+ # JavaScript executor tool (dual-purpose: workflow node + AI tool)
48
+ if node_type == 'javascriptExecutor':
49
+ return await _execute_javascript_code(tool_args, config.get('parameters', {}))
50
+
47
51
  # Current time tool
48
52
  if node_type == 'currentTimeTool':
49
53
  return await _execute_current_time(tool_args, config.get('parameters', {}))
@@ -191,44 +195,64 @@ async def _execute_http_request(args: Dict[str, Any],
191
195
 
192
196
  async def _execute_python_code(args: Dict[str, Any],
193
197
  node_params: Dict[str, Any]) -> Dict[str, Any]:
194
- """Execute Python code tool.
198
+ """Execute Python code (dual-purpose: workflow node + AI tool).
195
199
 
196
200
  Args:
197
- args: Dict with 'code'
198
- node_params: Node parameters containing timeout, etc.
201
+ args: Dict with 'code' from LLM (when used as AI tool)
202
+ node_params: Node parameters containing code (when used as workflow node), timeout, etc.
199
203
 
200
204
  Returns:
201
- Dict with result or output
205
+ Dict with success, result, output, or error
202
206
  """
203
207
  import subprocess
204
208
  import tempfile
205
209
  import os
206
210
 
207
- code = args.get('code', '')
211
+ # Get code from LLM args first (AI tool mode), fall back to node parameters (workflow mode)
212
+ code = args.get('code', '') or node_params.get('code', '')
208
213
  timeout = int(node_params.get('timeout', 30))
209
214
 
210
215
  if not code:
211
- return {"error": "No code provided"}
216
+ return {"error": "No code provided. When using as AI tool, the LLM must provide the 'code' argument with Python code to execute."}
212
217
 
213
- # Create a temporary file with the code
214
- with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
215
- # Wrap code to capture the result
216
- wrapped_code = f"""
218
+ # Wrap code to capture output and result
219
+ wrapped_code = f'''
217
220
  import json
218
221
  import sys
222
+ import math
223
+ from datetime import datetime, timedelta
224
+ from collections import Counter, defaultdict
219
225
 
220
- def main():
221
- {chr(10).join(' ' + line for line in code.split(chr(10)))}
226
+ input_data = {{}}
227
+ output = None
228
+ _stdout_lines = []
229
+
230
+ class _PrintCapture:
231
+ def write(self, text):
232
+ if text.strip():
233
+ _stdout_lines.append(text.rstrip())
234
+ def flush(self):
235
+ pass
236
+
237
+ _old_stdout = sys.stdout
238
+ sys.stdout = _PrintCapture()
222
239
 
223
240
  try:
224
- result = main()
225
- if result is not None:
226
- print(json.dumps({{"result": result}}, default=str))
227
- else:
228
- print(json.dumps({{"result": "Code executed successfully"}}))
241
+ {chr(10).join(" " + line for line in code.split(chr(10)))}
242
+
243
+ sys.stdout = _old_stdout
244
+ result = {{"success": True}}
245
+ if output is not None:
246
+ result["result"] = output
247
+ if _stdout_lines:
248
+ result["output"] = chr(10).join(_stdout_lines)
249
+ print(json.dumps(result, default=str))
229
250
  except Exception as e:
251
+ sys.stdout = _old_stdout
230
252
  print(json.dumps({{"error": str(e)}}))
231
- """
253
+ '''
254
+
255
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
232
256
  f.write(wrapped_code)
233
257
  temp_path = f.name
234
258
 
@@ -243,20 +267,102 @@ except Exception as e:
243
267
 
244
268
  if result.returncode == 0:
245
269
  try:
246
- output = json.loads(result.stdout.strip())
247
- return output
270
+ return json.loads(result.stdout.strip())
248
271
  except:
249
- return {"output": result.stdout.strip()}
272
+ return {"success": True, "output": result.stdout.strip()}
250
273
  else:
251
- return {"error": result.stderr or "Code execution failed"}
274
+ return {"error": result.stderr or "Python execution failed"}
252
275
 
253
276
  except subprocess.TimeoutExpired:
254
- return {"error": f"Code execution timed out after {timeout} seconds"}
277
+ return {"error": f"Python execution timed out after {timeout} seconds"}
255
278
  except Exception as e:
256
279
  logger.error(f"[Python Tool] Error: {e}")
257
280
  return {"error": str(e)}
258
281
  finally:
259
- # Clean up temp file
282
+ try:
283
+ os.unlink(temp_path)
284
+ except:
285
+ pass
286
+
287
+
288
+ async def _execute_javascript_code(args: Dict[str, Any],
289
+ node_params: Dict[str, Any]) -> Dict[str, Any]:
290
+ """Execute JavaScript code (dual-purpose: workflow node + AI tool).
291
+
292
+ Args:
293
+ args: Dict with 'code' from LLM (when used as AI tool)
294
+ node_params: Node parameters containing code (when used as workflow node), timeout, etc.
295
+
296
+ Returns:
297
+ Dict with success, result, output, or error
298
+ """
299
+ import subprocess
300
+ import tempfile
301
+ import os
302
+
303
+ # Get code from LLM args first (AI tool mode), fall back to node parameters (workflow mode)
304
+ code = args.get('code', '') or node_params.get('code', '')
305
+ timeout = int(node_params.get('timeout', 30))
306
+
307
+ if not code:
308
+ return {"error": "No code provided. When using as AI tool, the LLM must provide the 'code' argument with JavaScript code to execute."}
309
+
310
+ # Wrap code to capture output and result
311
+ wrapped_code = f'''
312
+ const input_data = {{}};
313
+ let output = undefined;
314
+ const _stdout_lines = [];
315
+
316
+ const _originalLog = console.log;
317
+ console.log = (...args) => {{
318
+ _stdout_lines.push(args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '));
319
+ }};
320
+
321
+ try {{
322
+ {chr(10).join(" " + line for line in code.split(chr(10)))}
323
+
324
+ const result = {{ success: true }};
325
+ if (output !== undefined) {{
326
+ result.result = output;
327
+ }}
328
+ if (_stdout_lines.length > 0) {{
329
+ result.output = _stdout_lines.join('\\n');
330
+ }}
331
+ _originalLog(JSON.stringify(result));
332
+ }} catch (e) {{
333
+ _originalLog(JSON.stringify({{ error: e.message }}));
334
+ }}
335
+ '''
336
+
337
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
338
+ f.write(wrapped_code)
339
+ temp_path = f.name
340
+
341
+ try:
342
+ logger.info(f"[JavaScript Tool] Executing code (timeout: {timeout}s)")
343
+ result = subprocess.run(
344
+ ['node', temp_path],
345
+ capture_output=True,
346
+ text=True,
347
+ timeout=timeout
348
+ )
349
+
350
+ if result.returncode == 0:
351
+ try:
352
+ return json.loads(result.stdout.strip())
353
+ except:
354
+ return {"success": True, "output": result.stdout.strip()}
355
+ else:
356
+ return {"error": result.stderr or "JavaScript execution failed"}
357
+
358
+ except subprocess.TimeoutExpired:
359
+ return {"error": f"JavaScript execution timed out after {timeout} seconds"}
360
+ except FileNotFoundError:
361
+ return {"error": "Node.js is not installed. Cannot execute JavaScript code."}
362
+ except Exception as e:
363
+ logger.error(f"[JavaScript Tool] Error: {e}")
364
+ return {"error": str(e)}
365
+ finally:
260
366
  try:
261
367
  os.unlink(temp_path)
262
368
  except:
@@ -323,14 +429,14 @@ async def _execute_web_search(args: Dict[str, Any],
323
429
 
324
430
  try:
325
431
  if provider == 'duckduckgo':
326
- # Use the duckduckgo-search library for proper web search results
432
+ # Use the ddgs library for proper web search results
327
433
  try:
328
- from duckduckgo_search import DDGS
434
+ from ddgs import DDGS
329
435
 
330
436
  # Run synchronous DDGS in a thread pool to not block async
331
437
  def do_search():
332
- with DDGS() as ddgs:
333
- return list(ddgs.text(query, max_results=max_results))
438
+ ddgs = DDGS()
439
+ return list(ddgs.text(query, max_results=max_results))
334
440
 
335
441
  search_results = await asyncio.get_event_loop().run_in_executor(
336
442
  None, do_search
@@ -352,7 +458,7 @@ async def _execute_web_search(args: Dict[str, Any],
352
458
  }
353
459
 
354
460
  except ImportError:
355
- logger.warning("[WebSearch] duckduckgo-search not installed, falling back to Instant Answer API")
461
+ logger.warning("[WebSearch] ddgs not installed, falling back to Instant Answer API")
356
462
  # Fallback to Instant Answer API (limited results)
357
463
  async with httpx.AsyncClient(timeout=10.0) as client:
358
464
  response = await client.get(
@@ -743,8 +849,12 @@ async def _execute_geocoding(args: Dict[str, Any],
743
849
  from services.handlers.utility import handle_add_locations
744
850
  from core.container import container
745
851
 
852
+ # Fetch API key from database (source of truth)
853
+ auth_service = container.auth_service()
854
+ api_key = await auth_service.get_api_key("google_maps", "default") or ''
855
+
746
856
  # Args use snake_case matching Pydantic schema and node params
747
- parameters = {**args, 'api_key': node_params.get('api_key', '')}
857
+ parameters = {**args, 'api_key': api_key}
748
858
 
749
859
  service_type = parameters.get('service_type', 'geocode')
750
860
 
@@ -793,8 +903,12 @@ async def _execute_nearby_places(args: Dict[str, Any],
793
903
  from services.handlers.utility import handle_nearby_places
794
904
  from core.container import container
795
905
 
906
+ # Fetch API key from database (source of truth)
907
+ auth_service = container.auth_service()
908
+ api_key = await auth_service.get_api_key("google_maps", "default") or ''
909
+
796
910
  # Args use snake_case matching Pydantic schema and node params
797
- parameters = {**args, 'api_key': node_params.get('api_key', '')}
911
+ parameters = {**args, 'api_key': api_key}
798
912
 
799
913
  # Validate required fields
800
914
  if parameters.get('lat') is None or parameters.get('lng') is None: