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,411 +0,0 @@
1
- """
2
- Twitter/X OAuth 2.0 with PKCE - Browser-based login flow for X API v2.
3
-
4
- Based on official X API documentation:
5
- - Authorization URL: https://x.com/i/oauth2/authorize
6
- - Token URL: https://api.x.com/2/oauth2/token
7
- - Docs: https://docs.x.com/fundamentals/authentication/oauth-2-0/authorization-code
8
-
9
- Access tokens expire in 2 hours by default. Use offline.access scope for refresh tokens.
10
- Authorization codes expire in 30 seconds.
11
- """
12
-
13
- import base64
14
- import hashlib
15
- import secrets
16
- import time
17
- from typing import Any, Dict, Optional
18
- from urllib.parse import urlencode
19
-
20
- import httpx
21
-
22
- from core.logging import get_logger
23
-
24
- logger = get_logger(__name__)
25
-
26
- # X API OAuth 2.0 endpoints (updated URLs per latest docs)
27
- AUTHORIZATION_URL = "https://x.com/i/oauth2/authorize"
28
- TOKEN_URL = "https://api.x.com/2/oauth2/token"
29
- REVOKE_URL = "https://api.x.com/2/oauth2/revoke"
30
- USER_INFO_URL = "https://api.x.com/2/users/me"
31
-
32
- # Required scopes for full Twitter integration
33
- # See: https://docs.x.com/fundamentals/authentication/oauth-2-0/authorization-code
34
- DEFAULT_SCOPES = [
35
- "tweet.read", # Read tweets
36
- "tweet.write", # Post tweets
37
- "users.read", # User lookup
38
- "follows.read", # Read followers/following
39
- "like.read", # Read likes
40
- "like.write", # Like/unlike tweets
41
- "offline.access", # Enable refresh tokens (access tokens expire in 2 hours)
42
- ]
43
-
44
- # In-memory store for PKCE state (production should use Redis/database)
45
- _oauth_states: Dict[str, Dict[str, Any]] = {}
46
-
47
-
48
- def _generate_code_verifier() -> str:
49
- """
50
- Generate a cryptographically random code verifier (43-128 chars).
51
- Per RFC 7636, must be 43-128 characters from [A-Z, a-z, 0-9, -, ., _, ~].
52
- """
53
- # Generate 96 random bytes, encode to base64url (128 chars after stripping padding)
54
- random_bytes = secrets.token_bytes(96)
55
- verifier = base64.urlsafe_b64encode(random_bytes).rstrip(b"=").decode("ascii")
56
- return verifier[:128]
57
-
58
-
59
- def _generate_code_challenge(code_verifier: str) -> str:
60
- """
61
- Generate S256 code challenge from verifier.
62
- challenge = BASE64URL(SHA256(code_verifier))
63
- """
64
- digest = hashlib.sha256(code_verifier.encode("ascii")).digest()
65
- challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
66
- return challenge
67
-
68
-
69
- def _generate_state() -> str:
70
- """Generate random state parameter for CSRF protection (up to 500 chars per X docs)."""
71
- return secrets.token_urlsafe(32)
72
-
73
-
74
- class TwitterOAuth:
75
- """
76
- Twitter/X OAuth 2.0 with PKCE flow implementation.
77
-
78
- Usage:
79
- oauth = TwitterOAuth(client_id="...", redirect_uri="http://localhost:3010/api/twitter/callback") # URI derived at runtime
80
-
81
- # Step 1: Generate authorization URL
82
- auth_data = oauth.generate_authorization_url()
83
- # Redirect user to auth_data["url"]
84
-
85
- # Step 2: Handle callback and exchange code
86
- tokens = await oauth.exchange_code(code="...", state="...")
87
-
88
- # Step 3: Use access_token for API calls
89
- user_info = await oauth.get_user_info(tokens["access_token"])
90
- """
91
-
92
- def __init__(
93
- self,
94
- client_id: str,
95
- redirect_uri: str,
96
- client_secret: Optional[str] = None,
97
- scopes: Optional[list] = None,
98
- ):
99
- """
100
- Initialize Twitter OAuth client.
101
-
102
- Args:
103
- client_id: Twitter OAuth 2.0 Client ID (from Developer Portal)
104
- client_secret: Client Secret (required for confidential clients, optional for public clients with PKCE)
105
- redirect_uri: OAuth callback URL (must match Developer Portal settings exactly)
106
- scopes: List of OAuth scopes (defaults to DEFAULT_SCOPES)
107
- """
108
- self.client_id = client_id
109
- self.client_secret = client_secret
110
- self.redirect_uri = redirect_uri
111
- self.scopes = scopes or DEFAULT_SCOPES
112
-
113
- def generate_authorization_url(self) -> Dict[str, str]:
114
- """
115
- Generate OAuth authorization URL with PKCE parameters.
116
-
117
- Returns:
118
- Dict with:
119
- - url: Authorization URL to redirect user to
120
- - state: State parameter (for verification in callback)
121
- - code_verifier: PKCE code verifier (save for token exchange)
122
- """
123
- state = _generate_state()
124
- code_verifier = _generate_code_verifier()
125
- code_challenge = _generate_code_challenge(code_verifier)
126
-
127
- # Store state for verification (with expiry tracking)
128
- _oauth_states[state] = {
129
- "code_verifier": code_verifier,
130
- "created_at": time.time(),
131
- "redirect_uri": self.redirect_uri,
132
- }
133
-
134
- params = {
135
- "response_type": "code",
136
- "client_id": self.client_id,
137
- "redirect_uri": self.redirect_uri,
138
- "scope": " ".join(self.scopes),
139
- "state": state,
140
- "code_challenge": code_challenge,
141
- "code_challenge_method": "S256",
142
- }
143
-
144
- authorization_url = f"{AUTHORIZATION_URL}?{urlencode(params)}"
145
-
146
- logger.info("Generated Twitter OAuth authorization URL", state=state[:8])
147
-
148
- return {
149
- "url": authorization_url,
150
- "state": state,
151
- "code_verifier": code_verifier,
152
- }
153
-
154
- async def exchange_code(self, code: str, state: str) -> Dict[str, Any]:
155
- """
156
- Exchange authorization code for access token.
157
-
158
- Note: Authorization codes expire in 30 seconds per X docs.
159
-
160
- Args:
161
- code: Authorization code from callback
162
- state: State parameter for verification
163
-
164
- Returns:
165
- Dict with:
166
- - success: True/False
167
- - access_token: Bearer token for API calls (expires in 2 hours)
168
- - refresh_token: Token for refreshing access (if offline.access scope)
169
- - expires_in: Token expiry in seconds
170
- - scope: Granted scopes
171
- """
172
- # Verify state and get code_verifier
173
- oauth_state = _oauth_states.pop(state, None)
174
- if not oauth_state:
175
- logger.error("Invalid or expired OAuth state", state=state[:8] if state else "None")
176
- return {"success": False, "error": "Invalid or expired state"}
177
-
178
- code_verifier = oauth_state["code_verifier"]
179
-
180
- # Prepare token request body
181
- data = {
182
- "grant_type": "authorization_code",
183
- "code": code,
184
- "redirect_uri": self.redirect_uri,
185
- "code_verifier": code_verifier,
186
- }
187
-
188
- # Authentication: Basic auth for confidential clients, client_id in body for public clients
189
- headers = {"Content-Type": "application/x-www-form-urlencoded"}
190
-
191
- if self.client_secret:
192
- # Confidential client: use Basic auth
193
- credentials = base64.b64encode(
194
- f"{self.client_id}:{self.client_secret}".encode()
195
- ).decode()
196
- headers["Authorization"] = f"Basic {credentials}"
197
- else:
198
- # Public client: include client_id in body
199
- data["client_id"] = self.client_id
200
-
201
- try:
202
- async with httpx.AsyncClient(timeout=30.0) as client:
203
- response = await client.post(
204
- TOKEN_URL,
205
- data=data,
206
- headers=headers,
207
- )
208
-
209
- if response.status_code != 200:
210
- error_data = response.json() if response.text else {}
211
- logger.error(
212
- "Token exchange failed",
213
- status=response.status_code,
214
- error=error_data,
215
- )
216
- return {
217
- "success": False,
218
- "error": error_data.get("error_description", error_data.get("error", "Token exchange failed")),
219
- }
220
-
221
- token_data = response.json()
222
- logger.info("Twitter OAuth token exchange successful")
223
-
224
- return {
225
- "success": True,
226
- "access_token": token_data.get("access_token"),
227
- "refresh_token": token_data.get("refresh_token"),
228
- "expires_in": token_data.get("expires_in"),
229
- "scope": token_data.get("scope"),
230
- "token_type": token_data.get("token_type", "Bearer"),
231
- }
232
-
233
- except httpx.HTTPError as e:
234
- logger.error("HTTP error during token exchange", error=str(e))
235
- return {"success": False, "error": str(e)}
236
-
237
- async def refresh_access_token(self, refresh_token: str) -> Dict[str, Any]:
238
- """
239
- Refresh an expired access token.
240
-
241
- Args:
242
- refresh_token: The refresh token from previous authorization
243
-
244
- Returns:
245
- Dict with new access_token, refresh_token, expires_in
246
- """
247
- data = {
248
- "grant_type": "refresh_token",
249
- "refresh_token": refresh_token,
250
- }
251
-
252
- headers = {"Content-Type": "application/x-www-form-urlencoded"}
253
-
254
- if self.client_secret:
255
- credentials = base64.b64encode(
256
- f"{self.client_id}:{self.client_secret}".encode()
257
- ).decode()
258
- headers["Authorization"] = f"Basic {credentials}"
259
- else:
260
- data["client_id"] = self.client_id
261
-
262
- try:
263
- async with httpx.AsyncClient(timeout=30.0) as client:
264
- response = await client.post(
265
- TOKEN_URL,
266
- data=data,
267
- headers=headers,
268
- )
269
-
270
- if response.status_code != 200:
271
- error_data = response.json() if response.text else {}
272
- logger.error(
273
- "Token refresh failed",
274
- status=response.status_code,
275
- error=error_data,
276
- )
277
- return {
278
- "success": False,
279
- "error": error_data.get("error_description", "Token refresh failed"),
280
- }
281
-
282
- token_data = response.json()
283
- logger.info("Twitter token refresh successful")
284
-
285
- return {
286
- "success": True,
287
- "access_token": token_data.get("access_token"),
288
- "refresh_token": token_data.get("refresh_token"),
289
- "expires_in": token_data.get("expires_in"),
290
- "scope": token_data.get("scope"),
291
- }
292
-
293
- except httpx.HTTPError as e:
294
- logger.error("HTTP error during token refresh", error=str(e))
295
- return {"success": False, "error": str(e)}
296
-
297
- async def revoke_token(self, token: str, token_type: str = "access_token") -> Dict[str, Any]:
298
- """
299
- Revoke an access or refresh token.
300
-
301
- Args:
302
- token: The token to revoke
303
- token_type: 'access_token' or 'refresh_token'
304
-
305
- Returns:
306
- Dict with success status
307
- """
308
- data = {
309
- "token": token,
310
- "token_type_hint": token_type,
311
- }
312
-
313
- headers = {"Content-Type": "application/x-www-form-urlencoded"}
314
-
315
- if self.client_secret:
316
- credentials = base64.b64encode(
317
- f"{self.client_id}:{self.client_secret}".encode()
318
- ).decode()
319
- headers["Authorization"] = f"Basic {credentials}"
320
- else:
321
- data["client_id"] = self.client_id
322
-
323
- try:
324
- async with httpx.AsyncClient(timeout=30.0) as client:
325
- response = await client.post(
326
- REVOKE_URL,
327
- data=data,
328
- headers=headers,
329
- )
330
-
331
- # 200 = success, even if token was already revoked
332
- if response.status_code == 200:
333
- logger.info("Twitter token revoked successfully")
334
- return {"success": True}
335
- else:
336
- error_data = response.json() if response.text else {}
337
- return {
338
- "success": False,
339
- "error": error_data.get("error_description", "Revocation failed"),
340
- }
341
-
342
- except httpx.HTTPError as e:
343
- logger.error("HTTP error during token revocation", error=str(e))
344
- return {"success": False, "error": str(e)}
345
-
346
- async def get_user_info(self, access_token: str) -> Dict[str, Any]:
347
- """
348
- Get authenticated user information.
349
-
350
- Args:
351
- access_token: Valid Twitter access token
352
-
353
- Returns:
354
- Dict with user id, username, name, profile_image_url, verified
355
- """
356
- try:
357
- async with httpx.AsyncClient(timeout=30.0) as client:
358
- response = await client.get(
359
- USER_INFO_URL,
360
- params={"user.fields": "id,name,username,profile_image_url,verified"},
361
- headers={"Authorization": f"Bearer {access_token}"},
362
- )
363
-
364
- if response.status_code != 200:
365
- error_data = response.json() if response.text else {}
366
- error_detail = error_data.get("detail") or error_data.get("title", "Failed to get user info")
367
- return {
368
- "success": False,
369
- "error": error_detail,
370
- }
371
-
372
- data = response.json()
373
- user = data.get("data", {})
374
-
375
- return {
376
- "success": True,
377
- "id": user.get("id"),
378
- "username": user.get("username"),
379
- "name": user.get("name"),
380
- "profile_image_url": user.get("profile_image_url"),
381
- "verified": user.get("verified", False),
382
- }
383
-
384
- except httpx.HTTPError as e:
385
- logger.error("HTTP error getting user info", error=str(e))
386
- return {"success": False, "error": str(e)}
387
-
388
-
389
- def cleanup_expired_states(max_age_seconds: int = 600):
390
- """
391
- Remove OAuth states older than max_age_seconds (default 10 minutes).
392
-
393
- Authorization codes expire in 30 seconds, so states older than a few
394
- minutes are definitely stale.
395
- """
396
- current_time = time.time()
397
- expired = [
398
- state
399
- for state, data in _oauth_states.items()
400
- if current_time - data["created_at"] > max_age_seconds
401
- ]
402
- for state in expired:
403
- _oauth_states.pop(state, None)
404
-
405
- if expired:
406
- logger.debug(f"Cleaned up {len(expired)} expired OAuth states")
407
-
408
-
409
- def get_pending_state(state: str) -> Optional[Dict[str, Any]]:
410
- """Get pending OAuth state without removing it (for verification)."""
411
- return _oauth_states.get(state)
@@ -1,29 +0,0 @@
1
- """
2
- Android WebSocket Client - DEPRECATED
3
-
4
- This module is deprecated. Use services.android instead:
5
-
6
- from services.android import (
7
- RelayWebSocketClient,
8
- get_relay_client,
9
- close_relay_client,
10
- get_current_relay_client,
11
- )
12
-
13
- This file re-exports from the new module for backwards compatibility.
14
- """
15
-
16
- from services.android import (
17
- RelayWebSocketClient,
18
- get_relay_client,
19
- close_relay_client,
20
- get_current_relay_client,
21
- )
22
-
23
- # Re-export for backwards compatibility
24
- __all__ = [
25
- "RelayWebSocketClient",
26
- "get_relay_client",
27
- "close_relay_client",
28
- "get_current_relay_client",
29
- ]