machinaos 0.0.76 → 0.0.78

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 (393) hide show
  1. package/README.md +143 -107
  2. package/client/dist/assets/ActionBar-Du2MSFSz.js +1 -0
  3. package/client/dist/assets/ApiKeyInput-k2LBmBjb.js +1 -0
  4. package/client/dist/assets/ApiKeyPanel-C_bV9U0X.js +1 -0
  5. package/client/dist/assets/ApiUsageSection-CmVfwZzL.js +1 -0
  6. package/client/dist/assets/EmailPanel-CeKIMGu-.js +1 -0
  7. package/client/dist/assets/OAuthPanel-KA3t3Q2K.js +1 -0
  8. package/client/dist/assets/QrPairingPanel-NgNpJNuk.js +1 -0
  9. package/client/dist/assets/RateLimitSection-Du5YNVIA.js +1 -0
  10. package/client/dist/assets/StatusCard-DNLyayXc.js +1 -0
  11. package/client/dist/assets/index-DQ0nwhec.js +257 -0
  12. package/client/dist/assets/index-DxmbVskS.css +1 -0
  13. package/client/dist/assets/vendor-flow-CZmBvHRo.js +1 -0
  14. package/client/dist/assets/vendor-icons-CVrPjN2Q.js +22 -0
  15. package/client/dist/assets/vendor-markdown-CRou3yQ5.js +62 -0
  16. package/client/dist/assets/vendor-misc-C4VxKHs5.js +1 -0
  17. package/client/dist/assets/vendor-query-SzWcOU0G.js +1 -0
  18. package/client/dist/assets/vendor-radix-Dnos29jG.js +56 -0
  19. package/client/dist/assets/vendor-react-DvWIbVx0.js +1 -0
  20. package/client/dist/index.html +37 -3
  21. package/client/index.html +28 -1
  22. package/client/package.json +44 -40
  23. package/client/src/App.tsx +2 -0
  24. package/client/src/Dashboard.tsx +157 -45
  25. package/client/src/ParameterPanel.tsx +3 -5
  26. package/client/src/adapters/nodeSpecToDescription.ts +1 -0
  27. package/client/src/assets/icons/NodeIcon.tsx +32 -0
  28. package/client/src/assets/icons/index.ts +4 -0
  29. package/client/src/assets/icons/stripe.svg +1 -0
  30. package/client/src/assets/icons/themedGlyphs.ts +404 -0
  31. package/client/src/components/AIAgentNode.tsx +77 -53
  32. package/client/src/components/GenericNode.tsx +34 -52
  33. package/client/src/components/OutputPanel.tsx +64 -147
  34. package/client/src/components/ParameterRenderer.tsx +5 -3
  35. package/client/src/components/SkillEditorModal.tsx +9 -18
  36. package/client/src/components/SquareNode.tsx +97 -115
  37. package/client/src/components/StartNode.tsx +32 -42
  38. package/client/src/components/SvgFilterDefs.tsx +54 -0
  39. package/client/src/components/TeamMonitorNode.tsx +12 -14
  40. package/client/src/components/ToolkitNode.tsx +35 -60
  41. package/client/src/components/TriggerNode.tsx +43 -77
  42. package/client/src/components/__tests__/CredentialsModal.test.tsx +49 -45
  43. package/client/src/components/credentials/CredentialsModal.tsx +98 -30
  44. package/client/src/components/credentials/CredentialsPalette.tsx +73 -5
  45. package/client/src/components/credentials/catalogueAdapter.ts +17 -1
  46. package/client/src/components/credentials/panels/ApiKeyPanel.tsx +102 -37
  47. package/client/src/components/credentials/panels/EmailPanel.tsx +7 -19
  48. package/client/src/components/credentials/panels/OAuthPanel.tsx +5 -1
  49. package/client/src/components/credentials/panels/QrPairingPanel.tsx +1 -3
  50. package/client/src/components/credentials/primitives/ActionBar.tsx +7 -11
  51. package/client/src/components/credentials/primitives/OAuthConnect.tsx +19 -28
  52. package/client/src/components/credentials/sections/ProviderDefaultsSection.tsx +24 -3
  53. package/client/src/components/credentials/types.ts +12 -2
  54. package/client/src/components/credentials/useCredentialPanel.ts +43 -19
  55. package/client/src/components/icons/AIProviderIcons.tsx +16 -0
  56. package/client/src/components/onboarding/OnboardingWizard.tsx +23 -63
  57. package/client/src/components/onboarding/nodeRoleClasses.ts +23 -0
  58. package/client/src/components/onboarding/steps/CanvasStep.tsx +15 -21
  59. package/client/src/components/onboarding/steps/ConceptsStep.tsx +2 -11
  60. package/client/src/components/onboarding/steps/GetStartedStep.tsx +2 -10
  61. package/client/src/components/parameterPanel/InputSection.tsx +9 -7
  62. package/client/src/components/parameterPanel/MasterSkillEditor.tsx +84 -198
  63. package/client/src/components/parameterPanel/MiddleSection.tsx +57 -80
  64. package/client/src/components/parameterPanel/ToolSchemaEditor.tsx +31 -25
  65. package/client/src/components/parameterPanel/__tests__/InputSection.test.tsx +7 -2
  66. package/client/src/components/ui/AIResultModal.tsx +1 -1
  67. package/client/src/components/ui/CollapsibleSection.tsx +9 -5
  68. package/client/src/components/ui/CommandPalette.tsx +147 -0
  69. package/client/src/components/ui/CommandPaletteHost.tsx +189 -0
  70. package/client/src/components/ui/ComponentItem.tsx +13 -7
  71. package/client/src/components/ui/ComponentPalette.tsx +24 -13
  72. package/client/src/components/ui/ConsolePanel.tsx +19 -11
  73. package/client/src/components/ui/DropCap.tsx +28 -0
  74. package/client/src/components/ui/EditableNodeLabel.tsx +10 -2
  75. package/client/src/components/ui/InputNodesPanel.tsx +1 -1
  76. package/client/src/components/ui/Modal.tsx +38 -6
  77. package/client/src/components/ui/OutputDisplayPanel.tsx +1 -1
  78. package/client/src/components/ui/SettingsPanel.tsx +42 -13
  79. package/client/src/components/ui/StatusBar.tsx +108 -0
  80. package/client/src/components/ui/ThemeSwitcher.tsx +109 -0
  81. package/client/src/components/ui/TopToolbar.tsx +42 -25
  82. package/client/src/components/ui/WorkflowSidebar.tsx +32 -16
  83. package/client/src/components/ui/action-button.tsx +40 -15
  84. package/client/src/components/ui/button.tsx +24 -1
  85. package/client/src/components/ui/dropdown-menu.tsx +24 -2
  86. package/client/src/components/ui/input.tsx +19 -2
  87. package/client/src/components/ui/select.tsx +15 -0
  88. package/client/src/components/ui/textarea.tsx +15 -2
  89. package/client/src/contexts/AuthContext.tsx +148 -109
  90. package/client/src/contexts/ThemeContext.tsx +93 -17
  91. package/client/src/contexts/WebSocketContext.tsx +373 -206
  92. package/client/src/contexts/__tests__/AuthContext.test.tsx +221 -0
  93. package/client/src/hooks/__tests__/useDragVariable.test.ts +7 -1
  94. package/client/src/hooks/__tests__/useWorkflowOpsListener.test.ts +142 -0
  95. package/client/src/hooks/useAppTheme.ts +209 -7
  96. package/client/src/hooks/useAutoSkillEdges.ts +7 -2
  97. package/client/src/hooks/useCatalogueQuery.ts +67 -1
  98. package/client/src/hooks/useDragVariable.ts +1 -1
  99. package/client/src/hooks/useNodeAllowlist.ts +115 -8
  100. package/client/src/hooks/useOnboarding.ts +20 -8
  101. package/client/src/hooks/useParameterPanel.ts +2 -1
  102. package/client/src/hooks/useReactFlowNodes.ts +2 -1
  103. package/client/src/hooks/useSound.ts +185 -0
  104. package/client/src/hooks/useWorkflowManagement.ts +6 -8
  105. package/client/src/hooks/useWorkflowOpsListener.ts +90 -0
  106. package/client/src/index.css +65 -3
  107. package/client/src/lib/__tests__/connectionConfig.test.ts +91 -0
  108. package/client/src/lib/aiModelProviders.ts +8 -0
  109. package/client/src/lib/connectionConfig.ts +107 -0
  110. package/client/src/lib/queryPersist.ts +13 -5
  111. package/client/src/lib/sound.ts +393 -0
  112. package/client/src/main.tsx +20 -0
  113. package/client/src/store/useAppStore.ts +26 -0
  114. package/client/src/styles/canvasAnimations.ts +37 -36
  115. package/client/src/styles/theme.ts +36 -20
  116. package/client/src/test/setup.ts +1 -0
  117. package/client/src/themes/atomic.css +253 -0
  118. package/client/src/themes/base.css +373 -0
  119. package/client/src/themes/cyber.css +890 -0
  120. package/client/src/themes/dark.css +70 -0
  121. package/client/src/themes/edo.css +246 -0
  122. package/client/src/themes/greek.css +293 -0
  123. package/client/src/themes/light.css +78 -0
  124. package/client/src/themes/plague.css +253 -0
  125. package/client/src/themes/renaissance.css +727 -0
  126. package/client/src/themes/rot.css +249 -0
  127. package/client/src/themes/steampunk.css +272 -0
  128. package/client/src/themes/surveillance.css +289 -0
  129. package/client/src/themes/wasteland.css +250 -0
  130. package/client/src/types/INodeProperties.ts +5 -0
  131. package/client/src/types/NodeTypes.ts +11 -1
  132. package/client/src/types/__tests__/cloudEvents.test.ts +99 -0
  133. package/client/src/types/cloudEvents.ts +78 -0
  134. package/client/src/vite-env.d.ts +7 -0
  135. package/client/tsconfig.json +1 -1
  136. package/client/vite.config.js +62 -2
  137. package/install.ps1 +1 -1
  138. package/install.sh +1 -1
  139. package/machina/commands/build.py +51 -7
  140. package/machina/pyproject.toml +4 -0
  141. package/machina/supervisor.py +12 -2
  142. package/machina/tree.py +71 -21
  143. package/package.json +4 -4
  144. package/scripts/install.js +16 -1
  145. package/server/config/ai_cli_providers.json +54 -0
  146. package/server/config/credential_providers.json +109 -2
  147. package/server/config/llm_defaults.json +24 -0
  148. package/server/config/model_registry.json +338 -499
  149. package/server/config/node_allowlist.json +16 -1
  150. package/server/config/pricing.json +8 -0
  151. package/server/constants.py +38 -15
  152. package/server/core/container.py +2 -2
  153. package/server/core/credentials_database.py +35 -2
  154. package/server/core/logging.py +4 -3
  155. package/server/main.py +99 -13
  156. package/server/models/node_metadata.py +1 -0
  157. package/server/nodejs/package.json +8 -6
  158. package/server/nodejs/src/index.ts +22 -5
  159. package/server/nodes/README.md +31 -4
  160. package/server/nodes/agent/_inline.py +2 -0
  161. package/server/nodes/agent/_specialized.py +6 -3
  162. package/server/nodes/agent/ai_agent.py +13 -3
  163. package/server/nodes/agent/chat_agent.py +6 -3
  164. package/server/nodes/agent/claude_code_agent.py +287 -75
  165. package/server/nodes/agent/codex_agent.py +239 -0
  166. package/server/nodes/agent/deep_agent.py +3 -3
  167. package/server/nodes/agent/rlm_agent.py +3 -3
  168. package/server/nodes/android/__init__.py +31 -1
  169. package/server/nodes/android/_base.py +9 -5
  170. package/server/{services/android_service.py → nodes/android/_dispatcher.py} +2 -2
  171. package/server/nodes/android/_handlers.py +154 -0
  172. package/server/nodes/android/_option_loaders.py +44 -0
  173. package/server/nodes/android/_refresh.py +127 -0
  174. package/server/{services/android → nodes/android/_relay}/client.py +4 -4
  175. package/server/{routers/android.py → nodes/android/_router.py} +27 -8
  176. package/server/nodes/browser/browser.py +2 -2
  177. package/server/nodes/code/_base.py +6 -2
  178. package/server/nodes/code/_claude_code.py +134 -0
  179. package/server/nodes/document/embedding_generator.py +3 -3
  180. package/server/nodes/document/http_scraper.py +3 -3
  181. package/server/nodes/document/vector_store.py +5 -5
  182. package/server/nodes/email/__init__.py +11 -1
  183. package/server/nodes/email/_filters.py +21 -0
  184. package/server/{services/himalaya_service.py → nodes/email/_himalaya.py} +6 -10
  185. package/server/{services/email_service.py → nodes/email/_service.py} +9 -13
  186. package/server/nodes/email/email_read.py +1 -1
  187. package/server/nodes/email/email_receive.py +54 -5
  188. package/server/nodes/email/email_send.py +1 -1
  189. package/server/nodes/filesystem/shell.py +24 -1
  190. package/server/nodes/google/__init__.py +55 -1
  191. package/server/{services/handlers/google_auth.py → nodes/google/_auth_helper.py} +8 -5
  192. package/server/nodes/google/_base.py +2 -2
  193. package/server/nodes/google/_credentials.py +5 -5
  194. package/server/nodes/google/_filters.py +25 -0
  195. package/server/nodes/google/_handlers.py +57 -0
  196. package/server/{services/google_oauth.py → nodes/google/_oauth.py} +195 -162
  197. package/server/nodes/google/_option_loaders.py +107 -0
  198. package/server/nodes/google/_refresh.py +66 -0
  199. package/server/nodes/google/_router.py +131 -0
  200. package/server/nodes/google/gmail_receive.py +41 -4
  201. package/server/nodes/groups.py +1 -0
  202. package/server/nodes/location/_credentials.py +45 -1
  203. package/server/{services/maps.py → nodes/location/_service.py} +18 -3
  204. package/server/nodes/location/gmaps_create.py +4 -4
  205. package/server/nodes/location/gmaps_locations.py +4 -4
  206. package/server/nodes/location/gmaps_nearby_places.py +4 -4
  207. package/server/nodes/model/_base.py +8 -3
  208. package/server/nodes/model/_credentials.py +96 -8
  209. package/server/nodes/model/_local_validator.py +345 -0
  210. package/server/nodes/model/lmstudio_chat_model.py +23 -0
  211. package/server/nodes/model/ollama_chat_model.py +25 -0
  212. package/server/nodes/proxy/_usage.py +2 -2
  213. package/server/nodes/proxy/proxy_config.py +14 -14
  214. package/server/nodes/proxy/proxy_request.py +4 -4
  215. package/server/nodes/scraper/_credentials.py +29 -1
  216. package/server/nodes/scraper/apify_actor.py +9 -9
  217. package/server/nodes/scraper/crawlee_scraper.py +5 -5
  218. package/server/nodes/search/brave_search.py +4 -0
  219. package/server/nodes/search/perplexity_search.py +9 -0
  220. package/server/nodes/search/serper_search.py +3 -0
  221. package/server/nodes/skill/simple_memory.py +12 -0
  222. package/server/nodes/social/_base.py +2 -2
  223. package/server/nodes/stripe/__init__.py +46 -0
  224. package/server/nodes/stripe/_credentials.py +33 -0
  225. package/server/nodes/stripe/_handlers.py +270 -0
  226. package/server/nodes/stripe/_install.py +127 -0
  227. package/server/nodes/stripe/_source.py +174 -0
  228. package/server/nodes/stripe/stripe_action.py +81 -0
  229. package/server/nodes/stripe/stripe_receive.py +92 -0
  230. package/server/nodes/telegram/_credentials.py +52 -1
  231. package/server/nodes/telegram/_handlers.py +19 -18
  232. package/server/nodes/telegram/_service.py +134 -32
  233. package/server/nodes/telegram/telegram_send.py +5 -6
  234. package/server/nodes/text/file_handler.py +2 -2
  235. package/server/nodes/text/text_generator.py +2 -2
  236. package/server/nodes/tool/agent_builder.py +630 -0
  237. package/server/nodes/tool/task_manager.py +144 -2
  238. package/server/nodes/twitter/__init__.py +38 -1
  239. package/server/nodes/twitter/_base.py +7 -7
  240. package/server/nodes/twitter/_credentials.py +1 -1
  241. package/server/nodes/twitter/_filters.py +37 -0
  242. package/server/nodes/twitter/_handlers.py +77 -0
  243. package/server/nodes/twitter/_oauth.py +124 -0
  244. package/server/nodes/twitter/_refresh.py +78 -0
  245. package/server/nodes/twitter/_router.py +29 -0
  246. package/server/nodes/twitter/twitter_receive.py +4 -0
  247. package/server/nodes/visuals.json +64 -19
  248. package/server/nodes/whatsapp/__init__.py +45 -5
  249. package/server/nodes/whatsapp/_base.py +3 -3
  250. package/server/nodes/whatsapp/_filters.py +137 -0
  251. package/server/nodes/whatsapp/_handlers.py +167 -0
  252. package/server/nodes/whatsapp/_option_loaders.py +68 -0
  253. package/server/nodes/whatsapp/_refresh.py +62 -0
  254. package/server/nodes/whatsapp/_runtime.py +1 -1
  255. package/server/pyproject.toml +29 -7
  256. package/server/routers/schemas.py +2 -2
  257. package/server/routers/webhook.py +26 -9
  258. package/server/routers/websocket.py +149 -810
  259. package/server/services/ai.py +89 -8
  260. package/server/services/auth.py +220 -43
  261. package/server/services/claude_oauth.py +126 -100
  262. package/server/services/cli_agent/__init__.py +78 -0
  263. package/server/services/cli_agent/_handlers.py +237 -0
  264. package/server/services/cli_agent/config.py +112 -0
  265. package/server/services/cli_agent/factory.py +48 -0
  266. package/server/services/cli_agent/lockfile.py +141 -0
  267. package/server/services/cli_agent/mcp_server.py +482 -0
  268. package/server/services/cli_agent/protocol.py +173 -0
  269. package/server/services/cli_agent/providers/__init__.py +9 -0
  270. package/server/services/cli_agent/providers/anthropic_claude.py +419 -0
  271. package/server/services/cli_agent/providers/google_gemini.py +80 -0
  272. package/server/services/cli_agent/providers/openai_codex.py +310 -0
  273. package/server/services/cli_agent/service.py +607 -0
  274. package/server/services/cli_agent/session.py +618 -0
  275. package/server/services/cli_agent/types.py +227 -0
  276. package/server/services/cli_agent/workflow_tools.py +233 -0
  277. package/server/services/credential_registry.py +26 -1
  278. package/server/services/deployment/manager.py +26 -145
  279. package/server/services/deployment/poll_registry.py +59 -0
  280. package/server/services/event_waiter.py +76 -246
  281. package/server/services/events/__init__.py +54 -0
  282. package/server/services/events/cli.py +78 -0
  283. package/server/services/events/daemon.py +163 -0
  284. package/server/services/events/envelope.py +281 -0
  285. package/server/services/events/lifecycle.py +99 -0
  286. package/server/services/events/oauth_lifecycle.py +534 -0
  287. package/server/services/events/polling.py +60 -0
  288. package/server/services/events/push.py +36 -0
  289. package/server/services/events/source.py +63 -0
  290. package/server/services/events/triggers.py +118 -0
  291. package/server/services/events/verifiers/__init__.py +25 -0
  292. package/server/services/events/verifiers/base.py +28 -0
  293. package/server/services/events/verifiers/github.py +25 -0
  294. package/server/services/events/verifiers/hmac_basic.py +32 -0
  295. package/server/services/events/verifiers/standard_webhooks.py +47 -0
  296. package/server/services/events/verifiers/stripe.py +42 -0
  297. package/server/services/events/webhook.py +105 -0
  298. package/server/services/handlers/tools.py +28 -186
  299. package/server/services/llm/config.py +7 -0
  300. package/server/services/llm/factory.py +8 -2
  301. package/server/services/memory/__init__.py +52 -0
  302. package/server/services/memory/jsonl.py +80 -0
  303. package/server/services/memory/markdown.py +65 -0
  304. package/server/services/memory/state.py +112 -0
  305. package/server/services/memory/vector_store.py +40 -0
  306. package/server/services/model_registry.py +76 -0
  307. package/server/services/node_allowlist.py +71 -15
  308. package/server/services/node_executor.py +2 -2
  309. package/server/services/node_output_schemas.py +21 -10
  310. package/server/services/node_spec.py +1 -1
  311. package/server/services/oauth_utils.py +1 -1
  312. package/server/services/plugin/__init__.py +2 -0
  313. package/server/services/plugin/base.py +44 -2
  314. package/server/services/plugin/credential.py +288 -1
  315. package/server/services/plugin/deps.py +105 -0
  316. package/server/services/plugin/edge_walker.py +12 -4
  317. package/server/services/plugin/oauth.py +381 -0
  318. package/server/services/plugin/polling.py +247 -0
  319. package/server/services/plugin/registry.py +145 -0
  320. package/server/services/plugin/singleton.py +65 -0
  321. package/server/services/plugin/ws.py +81 -0
  322. package/server/services/process_service.py +31 -2
  323. package/server/services/status_broadcaster.py +155 -238
  324. package/server/services/temporal/workflow.py +7 -7
  325. package/server/services/workflow.py +21 -3
  326. package/server/services/ws_handler_registry.py +111 -28
  327. package/server/skills/GUIDE.md +16 -1
  328. package/server/skills/assistant/agent-builder-skill/SKILL.md +166 -0
  329. package/server/skills/payments_agent/stripe-skill/SKILL.md +306 -0
  330. package/server/tests/credentials/test_auth_service.py +16 -9
  331. package/server/tests/credentials/test_credential_broadcasts.py +219 -0
  332. package/server/tests/credentials/test_google_oauth.py +6 -6
  333. package/server/tests/credentials/test_oauth_utils.py +1 -1
  334. package/server/tests/credentials/test_twitter_oauth.py +2 -2
  335. package/server/tests/credentials/test_websocket_handlers.py +44 -20
  336. package/server/tests/llm/test_factory.py +1 -0
  337. package/server/tests/llm/test_wiring.py +5 -1
  338. package/server/tests/nodes/_compat.py +24 -24
  339. package/server/tests/nodes/test_agent_builder.py +439 -0
  340. package/server/tests/nodes/test_ai_tools.py +18 -14
  341. package/server/tests/nodes/test_code_fs_process.py +17 -8
  342. package/server/tests/nodes/test_email.py +10 -9
  343. package/server/tests/nodes/test_google_workspace.py +2 -2
  344. package/server/tests/nodes/test_specialized_agents.py +100 -53
  345. package/server/tests/nodes/test_stripe_plugin.py +293 -0
  346. package/server/tests/nodes/test_telegram_social.py +4 -4
  347. package/server/tests/nodes/test_twitter.py +1 -1
  348. package/server/tests/nodes/test_web_automation.py +2 -2
  349. package/server/tests/nodes/test_whatsapp.py +9 -9
  350. package/server/tests/services/cli_agent/__init__.py +0 -0
  351. package/server/tests/services/cli_agent/test_mcp_server.py +432 -0
  352. package/server/tests/services/cli_agent/test_providers.py +358 -0
  353. package/server/tests/services/cli_agent/test_service.py +298 -0
  354. package/server/tests/services/memory/__init__.py +0 -0
  355. package/server/tests/services/memory/test_jsonl.py +188 -0
  356. package/server/tests/services/test_events.py +333 -0
  357. package/server/tests/test_node_spec.py +56 -16
  358. package/server/tests/test_plugin_helpers.py +116 -0
  359. package/server/tests/test_plugin_self_containment.py +486 -0
  360. package/server/tests/test_status_broadcasts.py +425 -0
  361. package/workflows/{AI Assistant_workflow-1777421105154-0m4snkzjf.json → AI Assistant_workflow-1778504793388-ou1m1tz2x.json } +70 -266
  362. package/workflows/{AI Employee_workflow-1777720598005-u4cm858dv.json → AI Employee_example_workflow-1777720598005-u4cm858dv.json } +112 -112
  363. package/workflows/Claude Assistant_workflow-1778380124051-mdibn807c.json +709 -0
  364. package/client/dist/assets/ActionBar-vzPpSR77.js +0 -1
  365. package/client/dist/assets/ApiKeyInput-Ds7AKFe8.js +0 -1
  366. package/client/dist/assets/ApiKeyPanel-gfblELep.js +0 -1
  367. package/client/dist/assets/ApiUsageSection-BMNWTe2r.js +0 -1
  368. package/client/dist/assets/EmailPanel-B1Om64p5.js +0 -1
  369. package/client/dist/assets/OAuthPanel-CXyQYGBz.js +0 -1
  370. package/client/dist/assets/QrPairingPanel-BgNuI1we.js +0 -1
  371. package/client/dist/assets/RateLimitSection-YYK8sx1T.js +0 -1
  372. package/client/dist/assets/StatusCard-DuYA5hJR.js +0 -1
  373. package/client/dist/assets/index-D9tZfgvi.js +0 -363
  374. package/client/dist/assets/index-al7snTkG.css +0 -1
  375. package/client/src/components/credentials/providers.tsx +0 -177
  376. package/server/routers/google.py +0 -277
  377. package/server/routers/maps.py +0 -142
  378. package/server/routers/twitter.py +0 -365
  379. package/server/services/claude_code_service.py +0 -106
  380. package/server/services/memory.py +0 -159
  381. package/server/services/node_option_loaders/__init__.py +0 -77
  382. package/server/services/node_option_loaders/android_loaders.py +0 -55
  383. package/server/services/node_option_loaders/google_loaders.py +0 -97
  384. package/server/services/node_option_loaders/whatsapp_loaders.py +0 -69
  385. package/server/services/twitter_oauth.py +0 -411
  386. package/server/services/websocket_client.py +0 -29
  387. /package/server/{services/android → nodes/android/_relay}/__init__.py +0 -0
  388. /package/server/{services/android → nodes/android/_relay}/broadcaster.py +0 -0
  389. /package/server/{services/android → nodes/android/_relay}/manager.py +0 -0
  390. /package/server/{services/android → nodes/android/_relay}/protocol.py +0 -0
  391. /package/server/{services/browser_service.py → nodes/browser/_service.py} +0 -0
  392. /package/server/{services/whatsapp_service.py → nodes/whatsapp/_service.py} +0 -0
  393. /package/server/skills/{task_agent → assistant}/write-todos-skill/SKILL.md +0 -0
@@ -1,277 +0,0 @@
1
- """
2
- Google Workspace OAuth 2.0 callback and API routes.
3
-
4
- OAuth flow:
5
- 1. Frontend calls WebSocket 'google_oauth_login' handler
6
- 2. Backend generates authorization URL, opens browser
7
- 3. User authorizes on Google
8
- 4. Google redirects to /api/google/callback with code
9
- 5. Backend exchanges code for tokens, stores them via auth_service
10
- 6. Frontend polls WebSocket 'google_oauth_status' for completion
11
-
12
- Two access modes:
13
- - Owner Mode: Tokens stored via auth_service (single account)
14
- - Customer Mode: Tokens stored in google_connections table (multi-account)
15
-
16
- Supports all Google Workspace services:
17
- - Gmail, Calendar, Drive, Sheets, Tasks, Contacts
18
- """
19
-
20
- from typing import Optional
21
-
22
- from fastapi import APIRouter, Query, Request
23
- from fastapi.responses import HTMLResponse, RedirectResponse
24
-
25
- from core.container import container
26
- from core.logging import get_logger
27
- from services.google_oauth import GoogleOAuth, get_pending_state
28
-
29
- logger = get_logger(__name__)
30
- router = APIRouter(prefix="/api/google", tags=["google"])
31
-
32
-
33
- def get_auth_service():
34
- """Get auth service for API key storage."""
35
- return container.auth_service()
36
-
37
-
38
- def get_database():
39
- """Get database for customer connections (non-sensitive data only)."""
40
- return container.database()
41
-
42
-
43
-
44
-
45
- @router.get("/callback")
46
- async def google_oauth_callback(
47
- code: Optional[str] = Query(None),
48
- state: Optional[str] = Query(None),
49
- error: Optional[str] = Query(None),
50
- error_description: Optional[str] = Query(None),
51
- ):
52
- """
53
- Handle Google OAuth callback.
54
-
55
- Google redirects here after user authorizes (or denies) the app.
56
- """
57
- # Handle authorization denied
58
- if error:
59
- logger.warning(f"Google OAuth denied: {error} - {error_description}")
60
- return HTMLResponse(
61
- content=_callback_html(success=False, error=error_description or error),
62
- status_code=200,
63
- )
64
-
65
- # Validate required parameters
66
- if not code or not state:
67
- logger.error("Google OAuth callback missing code or state")
68
- return HTMLResponse(
69
- content=_callback_html(success=False, error="Missing authorization code or state"),
70
- status_code=400,
71
- )
72
-
73
- # Verify state exists (CSRF protection)
74
- pending_state = get_pending_state(state)
75
- if not pending_state:
76
- logger.error("Google OAuth callback with invalid/expired state")
77
- return HTMLResponse(
78
- content=_callback_html(success=False, error="Invalid or expired state. Please try again."),
79
- status_code=400,
80
- )
81
-
82
- # Get state data
83
- state_data = pending_state.get("data", {})
84
- mode = state_data.get("mode", "owner")
85
- customer_id = state_data.get("customer_id")
86
- redirect_after = state_data.get("redirect_after")
87
-
88
- # Retrieve redirect_uri from state (set during auth initiation)
89
- redirect_uri = pending_state.get("redirect_uri")
90
- if not redirect_uri:
91
- logger.error("Google OAuth callback missing redirect_uri in state")
92
- return HTMLResponse(
93
- content=_callback_html(success=False, error="Invalid state: missing redirect URI. Please try again."),
94
- status_code=400,
95
- )
96
-
97
- # Get credentials
98
- auth_service = get_auth_service()
99
- client_id = await auth_service.get_api_key("google_client_id") or ""
100
- client_secret = await auth_service.get_api_key("google_client_secret") or ""
101
-
102
- if not client_id or not client_secret:
103
- return HTMLResponse(
104
- content=_callback_html(success=False, error="Google not configured. Add Client ID and Secret in Credentials."),
105
- status_code=400,
106
- )
107
-
108
- oauth = GoogleOAuth(
109
- client_id=client_id,
110
- client_secret=client_secret,
111
- redirect_uri=redirect_uri,
112
- )
113
-
114
- # Exchange code for tokens
115
- result = oauth.exchange_code(code=code, state=state)
116
-
117
- if not result.get("success"):
118
- logger.error(f"Google token exchange failed: {result.get('error')}")
119
- return HTMLResponse(
120
- content=_callback_html(success=False, error=result.get("error", "Token exchange failed")),
121
- status_code=400,
122
- )
123
-
124
- email = result.get("email", "Unknown")
125
- name = result.get("name", "")
126
- access_token = result.get("access_token")
127
- refresh_token = result.get("refresh_token")
128
-
129
- # Store tokens via auth_service (single point of access for credentials)
130
- auth_service = get_auth_service()
131
-
132
- if mode == "customer" and customer_id:
133
- # Customer mode: store encrypted tokens via auth_service
134
- await auth_service.store_oauth_tokens(
135
- provider="google",
136
- access_token=access_token,
137
- refresh_token=refresh_token,
138
- email=email,
139
- name=name,
140
- scopes=",".join(result.get("scopes", [])),
141
- customer_id=customer_id,
142
- )
143
- logger.info(f"Google OAuth successful for customer {customer_id}: {email}")
144
-
145
- if redirect_after:
146
- return RedirectResponse(url=f"{redirect_after}?google_connected=true&customer={customer_id}&email={email}")
147
- else:
148
- # Owner mode: store encrypted tokens via auth_service
149
- await auth_service.store_oauth_tokens(
150
- provider="google",
151
- access_token=access_token,
152
- refresh_token=refresh_token,
153
- email=email,
154
- name=name,
155
- scopes=",".join(result.get("scopes", [])),
156
- customer_id="owner",
157
- )
158
- logger.info(f"Google OAuth successful for {email}")
159
-
160
- # Update persistent status and broadcast completion event
161
- from services.status_broadcaster import get_status_broadcaster
162
- broadcaster = get_status_broadcaster()
163
- broadcaster._status["google"] = {
164
- "connected": True,
165
- "email": email,
166
- "name": name,
167
- }
168
- await broadcaster.broadcast({
169
- "type": "google_oauth_complete",
170
- "data": {"success": True, "email": email, "name": name, "mode": mode, "customer_id": customer_id},
171
- })
172
-
173
- return HTMLResponse(content=_callback_html(success=True, email=email), status_code=200)
174
-
175
-
176
- @router.get("/status")
177
- async def get_google_status():
178
- """Get Google connection status for owner mode."""
179
- auth_service = get_auth_service()
180
- tokens = await auth_service.get_oauth_tokens("google", customer_id="owner")
181
-
182
- if not tokens:
183
- return {"connected": False, "email": None}
184
-
185
- return {
186
- "connected": True,
187
- "email": tokens.get("email"),
188
- "name": tokens.get("name"),
189
- }
190
-
191
-
192
- @router.post("/logout")
193
- async def google_logout():
194
- """Disconnect Google (owner mode)."""
195
- auth_service = get_auth_service()
196
- await auth_service.remove_oauth_tokens("google", customer_id="owner")
197
- logger.info("Google disconnected")
198
- return {"success": True, "message": "Google disconnected"}
199
-
200
-
201
- @router.post("/customer-auth-url")
202
- async def generate_customer_auth_url(request: Request, customer_id: str, redirect_after: Optional[str] = None):
203
- """Generate OAuth URL for a customer to connect their Google account."""
204
- from services.oauth_utils import get_redirect_uri
205
-
206
- auth_service = get_auth_service()
207
- client_id = await auth_service.get_api_key("google_client_id") or ""
208
- client_secret = await auth_service.get_api_key("google_client_secret") or ""
209
-
210
- if not client_id or not client_secret:
211
- return {"success": False, "error": "Google not configured. Add Client ID and Secret."}
212
-
213
- redirect_uri = get_redirect_uri(request, "google")
214
-
215
- oauth = GoogleOAuth(
216
- client_id=client_id,
217
- client_secret=client_secret,
218
- redirect_uri=redirect_uri,
219
- )
220
- result = oauth.generate_authorization_url(state_data={"customer_id": customer_id, "redirect_after": redirect_after, "mode": "customer"})
221
- return {"success": True, "url": result["url"], "state": result["state"]}
222
-
223
-
224
- @router.get("/customer/{customer_id}/status")
225
- async def get_customer_google_status(customer_id: str):
226
- """Get Google connection status for a customer."""
227
- auth_service = get_auth_service()
228
- tokens = await auth_service.get_oauth_tokens("google", customer_id=customer_id)
229
- if not tokens:
230
- return {"connected": False, "customer_id": customer_id}
231
- return {
232
- "connected": True,
233
- "customer_id": customer_id,
234
- "email": tokens.get("email"),
235
- "name": tokens.get("name"),
236
- }
237
-
238
-
239
- @router.post("/customer/{customer_id}/disconnect")
240
- async def disconnect_customer_google(customer_id: str):
241
- """Disconnect a customer's Google account."""
242
- auth_service = get_auth_service()
243
- await auth_service.remove_oauth_tokens("google", customer_id=customer_id)
244
- logger.info(f"Google disconnected for customer {customer_id}")
245
- return {"success": True, "customer_id": customer_id}
246
-
247
-
248
- def _callback_html(success: bool, email: str = None, error: str = None) -> str:
249
- """Generate callback HTML page."""
250
- if success:
251
- title, message, color = "Google Connected", f"Successfully connected as {email}!", "#34a853"
252
- else:
253
- title, message, color = "Connection Failed", error or "Failed to connect", "#ea4335"
254
-
255
- escaped_error = error.replace("'", "\\'") if error else ""
256
- return f"""<!DOCTYPE html>
257
- <html>
258
- <head><title>{title}</title>
259
- <style>
260
- *{{margin:0;padding:0;box-sizing:border-box}}
261
- body{{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:linear-gradient(135deg,#15202b,#1a1a2e);min-height:100vh;display:flex;align-items:center;justify-content:center;color:#fff}}
262
- .container{{text-align:center;padding:40px;background:rgba(255,255,255,0.05);border-radius:16px;border:1px solid rgba(255,255,255,0.1);max-width:400px}}
263
- .icon{{width:64px;height:64px;margin-bottom:20px;color:{color}}}
264
- h1{{font-size:24px;margin-bottom:12px;color:{color}}}
265
- p{{font-size:16px;color:rgba(255,255,255,0.8);margin-bottom:20px}}
266
- .close-text{{font-size:14px;color:rgba(255,255,255,0.5)}}
267
- </style></head>
268
- <body><div class="container">
269
- <svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
270
- {"<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z'/>" if success else "<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z'/>"}
271
- </svg>
272
- <h1>{title}</h1><p>{message}</p><p class="close-text">This window will close automatically...</p>
273
- </div>
274
- <script>
275
- if(window.opener){{window.opener.postMessage({{type:'google_oauth_callback',success:{str(success).lower()},{"email:'"+email+"'," if email else ""}{"error:'"+escaped_error+"'," if error else ""}}},'*')}}
276
- setTimeout(function(){{window.close()}},2000);
277
- </script></body></html>"""
@@ -1,142 +0,0 @@
1
- """Google Maps service routes."""
2
-
3
- from fastapi import APIRouter, Depends, HTTPException
4
- from pydantic import BaseModel
5
- from typing import Dict, Any, Optional
6
- import httpx
7
-
8
- from core.container import container
9
- from services.maps import MapsService
10
- from services.status_broadcaster import get_status_broadcaster
11
- from core.logging import get_logger
12
-
13
- logger = get_logger(__name__)
14
- router = APIRouter(prefix="/python", tags=["maps"])
15
-
16
-
17
- class GoogleMapsRequest(BaseModel):
18
- node_id: str
19
- node_type: str
20
- parameters: Dict[str, Any]
21
- api_key: Optional[str] = None
22
-
23
-
24
- class ApiKeyValidationRequest(BaseModel):
25
- api_key: str
26
-
27
-
28
- @router.post("/maps/validate-key")
29
- async def validate_google_maps_key(request: ApiKeyValidationRequest):
30
- """Validate Google Maps API key and broadcast status via WebSocket."""
31
- broadcaster = get_status_broadcaster()
32
-
33
- try:
34
- api_key = request.api_key.strip()
35
- if not api_key:
36
- await broadcaster.update_api_key_status(
37
- provider="google_maps",
38
- valid=False,
39
- message="API key is required"
40
- )
41
- raise HTTPException(status_code=400, detail="API key is required")
42
-
43
- # Test the API key with a simple geocoding request
44
- async with httpx.AsyncClient() as client:
45
- response = await client.get(
46
- "https://maps.googleapis.com/maps/api/geocode/json",
47
- params={
48
- "address": "1600 Amphitheatre Parkway, Mountain View, CA",
49
- "key": api_key
50
- },
51
- timeout=10.0
52
- )
53
-
54
- data = response.json()
55
-
56
- if data.get("status") == "OK":
57
- await broadcaster.update_api_key_status(
58
- provider="google_maps",
59
- valid=True,
60
- message="API key validated successfully"
61
- )
62
- return {
63
- "success": True,
64
- "valid": True,
65
- "message": "Google Maps API key is valid"
66
- }
67
- elif data.get("status") == "REQUEST_DENIED":
68
- error_msg = data.get("error_message", "Invalid API key")
69
- await broadcaster.update_api_key_status(
70
- provider="google_maps",
71
- valid=False,
72
- message=error_msg
73
- )
74
- return {
75
- "success": True,
76
- "valid": False,
77
- "message": error_msg
78
- }
79
- else:
80
- # Other statuses like ZERO_RESULTS still mean the key works
81
- await broadcaster.update_api_key_status(
82
- provider="google_maps",
83
- valid=True,
84
- message="API key validated"
85
- )
86
- return {
87
- "success": True,
88
- "valid": True,
89
- "message": f"API key is valid (status: {data.get('status')})"
90
- }
91
-
92
- except httpx.TimeoutException:
93
- await broadcaster.update_api_key_status(
94
- provider="google_maps",
95
- valid=False,
96
- message="Validation request timed out"
97
- )
98
- raise HTTPException(status_code=504, detail="Validation request timed out")
99
- except httpx.RequestError as e:
100
- await broadcaster.update_api_key_status(
101
- provider="google_maps",
102
- valid=False,
103
- message=f"Network error: {str(e)}"
104
- )
105
- raise HTTPException(status_code=503, detail=f"Network error: {str(e)}")
106
- except HTTPException:
107
- raise
108
- except Exception as e:
109
- logger.error(f"API key validation error: {e}")
110
- await broadcaster.update_api_key_status(
111
- provider="google_maps",
112
- valid=False,
113
- message=f"Validation failed: {str(e)}"
114
- )
115
- raise HTTPException(status_code=500, detail=f"Validation failed: {str(e)}")
116
-
117
-
118
- @router.post("/createmap/execute")
119
- async def execute_createmap_node(
120
- request: GoogleMapsRequest,
121
- maps_service: MapsService = Depends(lambda: container.maps_service())
122
- ):
123
- """Execute Create Map node - Google Maps initialization."""
124
- return await maps_service.create_map(request.node_id, request.parameters)
125
-
126
-
127
- @router.post("/addlocations/execute")
128
- async def execute_addlocations_node(
129
- request: GoogleMapsRequest,
130
- maps_service: MapsService = Depends(lambda: container.maps_service())
131
- ):
132
- """Execute Add Locations node - Google Maps Geocoding."""
133
- return await maps_service.geocode_location(request.node_id, request.parameters)
134
-
135
-
136
- @router.post("/shownearbyplaces/execute")
137
- async def execute_shownearbyplaces_node(
138
- request: GoogleMapsRequest,
139
- maps_service: MapsService = Depends(lambda: container.maps_service())
140
- ):
141
- """Execute Show Nearby Places node - Google Places API."""
142
- return await maps_service.find_nearby_places(request.node_id, request.parameters)