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
@@ -0,0 +1,189 @@
1
+ /**
2
+ * CommandPaletteHost — Dashboard-level command list registration.
3
+ *
4
+ * Owns the canonical command set that the global ⌘K palette surfaces.
5
+ * Receives every action as a handler prop (Dashboard already has them
6
+ * in scope) plus the active theme controls; assembles a `CommandItem[]`
7
+ * with stable IDs, hints, and keyboard shortcuts and renders the
8
+ * underlying CommandPalette.
9
+ *
10
+ * New shell action: add a handler to `Handlers`, wire it through from
11
+ * Dashboard, append a `CommandItem` to `commands` below. No edits to
12
+ * the CommandPalette primitive itself.
13
+ */
14
+
15
+ import * as React from 'react';
16
+ import {
17
+ Settings as SettingsIcon,
18
+ KeyRound,
19
+ Save,
20
+ Play,
21
+ Square,
22
+ FilePlus,
23
+ FolderOpen,
24
+ PanelLeftClose,
25
+ PanelRightClose,
26
+ Terminal,
27
+ Palette as PaletteIcon,
28
+ Download,
29
+ Upload,
30
+ } from 'lucide-react';
31
+ import { CommandPalette, type CommandItem } from './CommandPalette';
32
+ import { AVAILABLE_THEMES, useTheme, type ThemeName } from '../../contexts/ThemeContext';
33
+
34
+ interface Handlers {
35
+ save: () => void;
36
+ newWorkflow: () => void;
37
+ open: () => void;
38
+ run: () => void;
39
+ stop: () => void;
40
+ isDeploying: boolean;
41
+ exportFile: () => void;
42
+ importJSON: () => void;
43
+ openSettings: () => void;
44
+ openCredentials: () => void;
45
+ toggleSidebar: () => void;
46
+ toggleComponentPalette: () => void;
47
+ toggleConsolePanel: () => void;
48
+ }
49
+
50
+ const THEME_LABEL: Record<ThemeName, string> = {
51
+ light: 'Light',
52
+ dark: 'Dark',
53
+ renaissance: 'Renaissance',
54
+ greek: 'Greek',
55
+ edo: 'Edo',
56
+ steampunk: 'Steampunk',
57
+ atomic: 'Atomic Modern',
58
+ cyber: 'Cyber-Tyranny',
59
+ wasteland: 'Wasteland',
60
+ rot: 'Necromantic Rot',
61
+ plague: 'Plague City',
62
+ surveillance: 'Surveillance',
63
+ };
64
+
65
+ interface Props {
66
+ open: boolean;
67
+ onOpenChange: (open: boolean) => void;
68
+ handlers: Handlers;
69
+ }
70
+
71
+ export const CommandPaletteHost: React.FC<Props> = ({ open, onOpenChange, handlers }) => {
72
+ const { theme, setTheme } = useTheme();
73
+
74
+ const commands: CommandItem[] = React.useMemo(() => {
75
+ const list: CommandItem[] = [
76
+ // ── Workflow ───────────────────────────────────────────────────
77
+ {
78
+ id: 'workflow.new',
79
+ label: 'New Workflow',
80
+ group: 'Workflow',
81
+ icon: FilePlus,
82
+ onRun: handlers.newWorkflow,
83
+ },
84
+ {
85
+ id: 'workflow.open',
86
+ label: 'Open Workflow',
87
+ group: 'Workflow',
88
+ icon: FolderOpen,
89
+ onRun: handlers.open,
90
+ },
91
+ {
92
+ id: 'workflow.save',
93
+ label: 'Save Workflow',
94
+ group: 'Workflow',
95
+ icon: Save,
96
+ shortcut: '⌘S',
97
+ onRun: handlers.save,
98
+ },
99
+ {
100
+ id: 'workflow.export',
101
+ label: 'Export Workflow',
102
+ group: 'Workflow',
103
+ icon: Download,
104
+ onRun: handlers.exportFile,
105
+ },
106
+ {
107
+ id: 'workflow.import',
108
+ label: 'Import Workflow',
109
+ group: 'Workflow',
110
+ icon: Upload,
111
+ onRun: handlers.importJSON,
112
+ },
113
+
114
+ // ── Run ────────────────────────────────────────────────────────
115
+ handlers.isDeploying
116
+ ? {
117
+ id: 'run.stop',
118
+ label: 'Stop Workflow',
119
+ group: 'Run',
120
+ icon: Square,
121
+ onRun: handlers.stop,
122
+ }
123
+ : {
124
+ id: 'run.start',
125
+ label: 'Start Workflow',
126
+ group: 'Run',
127
+ icon: Play,
128
+ onRun: handlers.run,
129
+ },
130
+
131
+ // ── Open panels ────────────────────────────────────────────────
132
+ {
133
+ id: 'open.settings',
134
+ label: 'Open Settings',
135
+ group: 'Open',
136
+ icon: SettingsIcon,
137
+ onRun: handlers.openSettings,
138
+ },
139
+ {
140
+ id: 'open.credentials',
141
+ label: 'Open Credentials',
142
+ group: 'Open',
143
+ icon: KeyRound,
144
+ onRun: handlers.openCredentials,
145
+ },
146
+
147
+ // ── View toggles ───────────────────────────────────────────────
148
+ {
149
+ id: 'view.sidebar',
150
+ label: 'Toggle Sidebar',
151
+ group: 'View',
152
+ icon: PanelLeftClose,
153
+ onRun: handlers.toggleSidebar,
154
+ },
155
+ {
156
+ id: 'view.palette',
157
+ label: 'Toggle Component Palette',
158
+ group: 'View',
159
+ icon: PanelRightClose,
160
+ onRun: handlers.toggleComponentPalette,
161
+ },
162
+ {
163
+ id: 'view.console',
164
+ label: 'Toggle Console / Chat Panel',
165
+ group: 'View',
166
+ icon: Terminal,
167
+ onRun: handlers.toggleConsolePanel,
168
+ },
169
+ ];
170
+
171
+ // ── Theme switch ─────────────────────────────────────────────────
172
+ for (const name of AVAILABLE_THEMES) {
173
+ list.push({
174
+ id: `theme.${name}`,
175
+ label: `Switch theme: ${THEME_LABEL[name]}`,
176
+ group: 'Theme',
177
+ icon: PaletteIcon,
178
+ hint: name === theme ? 'active' : undefined,
179
+ onRun: () => setTheme(name),
180
+ });
181
+ }
182
+
183
+ return list;
184
+ }, [handlers, theme, setTheme]);
185
+
186
+ return <CommandPalette open={open} onOpenChange={onOpenChange} commands={commands} />;
187
+ };
188
+
189
+ export default CommandPaletteHost;
@@ -22,6 +22,8 @@ const ComponentItem: React.FC<ComponentItemProps> = ({ definition: localDefiniti
22
22
  const iconRaw = spec?.icon ?? definition.icon;
23
23
 
24
24
  return (
25
+ // bg-bg-app + border-default match the handoff `.comp` card.
26
+ // Hover lifts via translate + outline + soft tint backdrop.
25
27
  <Card
26
28
  size="sm"
27
29
  draggable
@@ -31,13 +33,17 @@ const ComponentItem: React.FC<ComponentItemProps> = ({ definition: localDefiniti
31
33
  }}
32
34
  onDragEnd={() => setIsDragging(false)}
33
35
  className={cn(
34
- 'group relative flex-row items-center gap-3 px-3 py-2 cursor-grab select-none',
35
- 'transition-all duration-150 ease-out',
36
- 'hover:-translate-y-0.5 hover:ring-2 hover:ring-foreground/15 hover:shadow-md',
36
+ // `comp` + `row` are handoff structural hooks: comp activates
37
+ // per-theme component-card decorations (left accent bar on Cyber,
38
+ // boomerang corners on Atomic, gold border on Renaissance hover);
39
+ // row enables the global hover-sound delegate.
40
+ 'comp row group relative flex-row items-center gap-3 px-3 py-2 cursor-grab select-none',
41
+ 'border-border-default bg-bg-app transition-all duration-150 ease-out',
42
+ 'hover:-translate-y-0.5 hover:bg-bg-hover hover:ring-2 hover:ring-foreground/15 hover:shadow-md',
37
43
  isDragging && 'opacity-50',
38
44
  )}
39
45
  >
40
- <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-muted ring-1 ring-foreground/10">
46
+ <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-bg-elevated ring-1 ring-border-default/40">
41
47
  <NodeIcon
42
48
  icon={iconRaw}
43
49
  className="h-5 w-5 text-lg"
@@ -46,16 +52,16 @@ const ComponentItem: React.FC<ComponentItemProps> = ({ definition: localDefiniti
46
52
  </div>
47
53
 
48
54
  <div className="min-w-0 flex-1">
49
- <div className="truncate text-sm font-medium text-foreground">
55
+ <div className="truncate font-display text-sm font-medium text-fg-default">
50
56
  {definition.displayName}
51
57
  </div>
52
- <div className="truncate text-xs leading-tight text-muted-foreground">
58
+ <div className="truncate text-xs leading-tight text-fg-muted">
53
59
  {definition.description}
54
60
  </div>
55
61
  </div>
56
62
 
57
63
  <GripVertical
58
- className="h-4 w-4 shrink-0 text-muted-foreground opacity-30 transition-opacity group-hover:opacity-60"
64
+ className="h-4 w-4 shrink-0 text-fg-faint opacity-50 transition-opacity group-hover:opacity-80"
59
65
  aria-hidden
60
66
  />
61
67
  </Card>
@@ -27,7 +27,7 @@ const ComponentPalette: React.FC<ComponentPaletteProps> = ({
27
27
  specsReady = false,
28
28
  }) => {
29
29
  const theme = useAppTheme();
30
- const { isVisible } = useNodeAllowlist();
30
+ const { isBlocked, isAllowed } = useNodeAllowlist();
31
31
 
32
32
  // Backend-driven group metadata via the shared WS-in-queryFn hook.
33
33
  // `useNodeGroups` returns the full query result so we can render a
@@ -55,9 +55,16 @@ const ComponentPalette: React.FC<ComponentPaletteProps> = ({
55
55
  const definitions = listCachedNodeSpecs().map(nodeSpecToDescription);
56
56
 
57
57
  const filteredDefinitions = definitions.filter((definition) => {
58
- // Filter by backend allowlist (server/config/node_allowlist.json).
59
- // Applied only in normal mode; dev mode shows every node.
60
- if (!proMode && !isVisible(definition.name)) return false;
58
+ // Backend allowlist (server/config/node_allowlist.json). Two-tier:
59
+ // 1. `disabled_groups` + `disabled_nodes` absolute blocklist
60
+ // enforced in BOTH normal and dev mode. The node's group
61
+ // array is passed so `disabled_groups` fires on every plugin
62
+ // in the group (e.g. all 16 android service nodes hidden by
63
+ // one entry).
64
+ // 2. `enabled_nodes` — positive allowlist applied only in
65
+ // normal mode; dev/pro mode bypasses it.
66
+ if (isBlocked(definition.name, definition.group)) return false;
67
+ if (!proMode && !isAllowed(definition.name)) return false;
61
68
 
62
69
  // Filter by search query
63
70
  if (searchQuery.trim()) {
@@ -99,7 +106,7 @@ const ComponentPalette: React.FC<ComponentPaletteProps> = ({
99
106
  });
100
107
 
101
108
  return categories;
102
- }, [searchQuery, proMode, groupIndex, isVisible, specsReady]);
109
+ }, [searchQuery, proMode, groupIndex, isBlocked, isAllowed, specsReady]);
103
110
 
104
111
  const totalComponents = Object.values(categorizedComponents).reduce(
105
112
  (acc, components) => acc + components.length,
@@ -107,19 +114,23 @@ const ComponentPalette: React.FC<ComponentPaletteProps> = ({
107
114
  );
108
115
 
109
116
  return (
110
- <div className="flex h-full w-full flex-col overflow-hidden bg-muted/30">
111
- {/* Header Section */}
112
- <div className="border-b border-border bg-card p-4">
117
+ // Palette shell: `palette` co-class activates per-theme decorations
118
+ // (panel textures, neon side-glow on Cyber, marble grain on Greek).
119
+ <div className="palette flex h-full w-full flex-col overflow-hidden border-l border-border-default bg-bg-panel">
120
+ {/* Header Section — bg-bg-app drops one elevation step. */}
121
+ <div className="border-b border-border-default bg-bg-app p-4">
113
122
  <div className="mb-3 flex items-center justify-between">
114
- <h2 className="text-base font-semibold text-foreground">Components</h2>
115
- <Badge variant="secondary" className="text-xs font-medium">
123
+ <h2 className="font-display text-base font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">
124
+ Components
125
+ </h2>
126
+ <Badge variant="secondary" className="font-mono text-xs font-medium">
116
127
  {totalComponents}
117
128
  </Badge>
118
129
  </div>
119
130
 
120
131
  {/* Search Input */}
121
132
  <div className="relative">
122
- <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
133
+ <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-faint" />
123
134
  <Input
124
135
  type="text"
125
136
  placeholder="Search..."
@@ -135,7 +146,7 @@ const ComponentPalette: React.FC<ComponentPaletteProps> = ({
135
146
  {groupsLoading ? (
136
147
  <PaletteSkeleton />
137
148
  ) : Object.keys(categorizedComponents).length === 0 ? (
138
- <div className="flex flex-col items-center px-6 py-12 text-center text-muted-foreground">
149
+ <div className="flex flex-col items-center px-6 py-12 text-center text-fg-muted">
139
150
  <Search className="mb-3 h-12 w-12 opacity-50" />
140
151
  <p className="text-sm">
141
152
  No components found matching "{searchQuery}"
@@ -167,7 +178,7 @@ const ComponentPalette: React.FC<ComponentPaletteProps> = ({
167
178
  fallback={<span>📦</span>}
168
179
  />
169
180
  </span>
170
- <span className="text-sm font-semibold text-foreground">
181
+ <span className="font-display text-sm font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">
171
182
  {config.label}
172
183
  </span>
173
184
  </div>
@@ -362,8 +362,11 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
362
362
  // ------------------------------ Render ------------------------------
363
363
 
364
364
  return (
365
+ // `chat` co-class is the design-handoff structural hook for per-theme
366
+ // panel decorations (parchment vellum on Renaissance, neon cyan
367
+ // top-glow on Cyber, washi noise on Edo, etc.).
365
368
  <div
366
- className="relative"
369
+ className="chat relative"
367
370
  onWheel={e => {
368
371
  // Prevent scroll from propagating to the canvas/page when the cursor
369
372
  // is over the panel header, resize handle, or non-scrollable areas.
@@ -386,7 +389,7 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
386
389
  {/* Panel Header */}
387
390
  <div
388
391
  onClick={onToggle}
389
- className="flex cursor-pointer items-center justify-between border-t border-border bg-card px-3 py-1.5 select-none"
392
+ className="flex cursor-pointer items-center justify-between border-t border-border-default bg-bg-elevated px-3 py-1.5 select-none"
390
393
  >
391
394
  <div className="flex items-center gap-2">
392
395
  <ChevronDown
@@ -395,7 +398,7 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
395
398
  !isOpen && 'rotate-180'
396
399
  )}
397
400
  />
398
- <span className="flex items-center gap-1.5 text-sm font-semibold text-foreground">
401
+ <span className="flex items-center gap-1.5 font-display text-sm font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">
399
402
  Chat / Console
400
403
  {(consoleLogs.length > 0 || (chatMessages && chatMessages.length > 0)) && (
401
404
  <Badge variant="secondary" className="text-xs">
@@ -411,7 +414,7 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
411
414
  ref={containerRef}
412
415
  style={{ height: isOpen ? `${panelHeight}px` : '0px' }}
413
416
  className={cn(
414
- 'flex flex-row overflow-hidden bg-background',
417
+ 'flex flex-row overflow-hidden bg-bg-app',
415
418
  'max-h-[calc(100vh-90px)]',
416
419
  (isResizing || isHorizontalResizing) ? '[transition:none]' : 'transition-[height] duration-200 ease-in-out'
417
420
  )}
@@ -422,9 +425,9 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
422
425
  className="relative flex flex-col overflow-hidden"
423
426
  >
424
427
  {/* Header */}
425
- <div className="flex min-h-[32px] items-center justify-between border-b border-border bg-card px-3 py-1.5">
428
+ <div className="flex min-h-[32px] items-center justify-between border-b border-border-default bg-bg-elevated px-3 py-1.5">
426
429
  <div className="flex items-center gap-2">
427
- <span className="flex items-center gap-1.5 text-sm font-semibold text-foreground">
430
+ <span className="flex items-center gap-1.5 font-display text-sm font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">
428
431
  Chat
429
432
  {chatMessages && chatMessages.length > 0 && (
430
433
  <Badge variant="success" className="text-xs">{chatMessages.length}</Badge>
@@ -483,10 +486,15 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
483
486
  <div
484
487
  key={`${msg.timestamp}-${index}`}
485
488
  className={cn(
486
- 'max-w-[80%] px-3 py-2 break-words',
489
+ // `chat-msg` + `chat-msg-user` / `chat-msg-bot`
490
+ // co-classes activate per-theme bubble decorations
491
+ // (Renaissance: gold-foil user / vellum bot with
492
+ // ✦ marker; Cyber: > USER:: / < NODE:: prefixes
493
+ // with neon glow; etc.).
494
+ 'chat-msg max-w-[80%] px-3 py-2 break-words',
487
495
  isUser
488
- ? 'mr-0 ml-auto rounded-l-xl rounded-tr-xl rounded-br-sm bg-node-agent-soft'
489
- : 'mr-auto ml-0 rounded-r-xl rounded-tl-xl rounded-bl-sm bg-card'
496
+ ? 'chat-msg-user mr-0 ml-auto rounded-l-xl rounded-tr-xl rounded-br-sm bg-node-agent-soft'
497
+ : 'chat-msg-bot mr-auto ml-0 rounded-r-xl rounded-tl-xl rounded-bl-sm border border-border-default bg-bg-elevated'
490
498
  )}
491
499
  >
492
500
  {isUser ? (
@@ -512,7 +520,7 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
512
520
  </div>
513
521
 
514
522
  {/* Input */}
515
- <div className="flex items-center gap-2 border-t border-border bg-card px-4 py-2.5">
523
+ <div className="flex items-center gap-2 border-t border-border-default bg-bg-elevated px-4 py-2.5">
516
524
  <Input
517
525
  ref={chatInputRef}
518
526
  type="text"
@@ -549,7 +557,7 @@ const ConsolePanel: React.FC<ConsolePanelProps> = ({
549
557
  {/* ===================== Console / Terminal Section (right) ===================== */}
550
558
  <div className="flex flex-1 flex-col overflow-hidden">
551
559
  {/* Header with tabs + filters */}
552
- <div className="flex min-h-[32px] items-center justify-between border-b border-border bg-card px-3 py-1.5">
560
+ <div className="flex min-h-[32px] items-center justify-between border-b border-border-default bg-bg-elevated px-3 py-1.5">
553
561
  {/* Tab buttons */}
554
562
  <div className="flex items-center gap-1">
555
563
  <button
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Wraps content (typically a heading or first paragraph) with the
3
+ * `v-display drop-cap` className so theme CSS rules like the
4
+ * Renaissance `.v-display.drop-cap::first-letter` rule fire on the
5
+ * first letter. Under themes that don't define a drop-cap rule it's a
6
+ * no-op (just two extra class names on the wrapper).
7
+ */
8
+ import React from 'react';
9
+
10
+ export interface DropCapProps {
11
+ as?: 'h1' | 'h2' | 'h3' | 'p' | 'span' | 'div';
12
+ className?: string;
13
+ children: React.ReactNode;
14
+ }
15
+
16
+ export const DropCap: React.FC<DropCapProps> = ({
17
+ as: Tag = 'span',
18
+ className = '',
19
+ children,
20
+ }) => {
21
+ return (
22
+ <Tag className={`v-display drop-cap ${className}`.trim()}>
23
+ {children}
24
+ </Tag>
25
+ );
26
+ };
27
+
28
+ export default DropCap;
@@ -98,7 +98,11 @@ const EditableNodeLabel: React.FC<EditableNodeLabelProps> = ({
98
98
  onBlur={handleSave}
99
99
  onClick={(e) => e.stopPropagation()}
100
100
  className={cn(
101
- 'mt-2 h-auto max-w-[120px] border-accent px-1 py-0.5 text-center text-xs font-medium',
101
+ // Both `sq-node-label` and `node-label` co-classes always emit so
102
+ // per-theme CSS rules fire for whichever parent topology this
103
+ // label sits inside (`.sq-node` for square, `.node` for
104
+ // rectangular). Wave 26.B.
105
+ 'sq-node-label node-label mt-2 h-auto max-w-[120px] border-accent px-1 py-0.5 text-center text-xs font-medium',
102
106
  className
103
107
  )}
104
108
  />
@@ -110,7 +114,11 @@ const EditableNodeLabel: React.FC<EditableNodeLabelProps> = ({
110
114
  onDoubleClick={onActivate}
111
115
  title="Double-click to rename"
112
116
  className={cn(
113
- 'mt-2 max-w-[120px] cursor-text text-center text-xs leading-tight font-medium text-foreground',
117
+ // Both `sq-node-label` and `node-label` co-classes always emit so
118
+ // per-theme CSS rules fire for whichever parent topology this
119
+ // label sits inside (`.sq-node` for square, `.node` for
120
+ // rectangular). Wave 26.B.
121
+ 'sq-node-label node-label mt-2 max-w-[120px] cursor-text text-center text-xs leading-tight font-medium text-foreground',
114
122
  className
115
123
  )}
116
124
  >
@@ -19,7 +19,7 @@ interface InputDataItem {
19
19
  }
20
20
 
21
21
  const InputNodesPanel: React.FC<InputNodesPanelProps> = ({ nodeId }) => {
22
- const { currentWorkflow } = useAppStore();
22
+ const currentWorkflow = useAppStore((s) => s.currentWorkflow);
23
23
  const { getNodeOutput } = useWebSocket();
24
24
  const [inputData, setInputData] = useState<InputDataItem[]>([]);
25
25
  const [loading, setLoading] = useState(false);
@@ -9,7 +9,7 @@
9
9
  * if you need a new prop.
10
10
  */
11
11
 
12
- import React from 'react';
12
+ import React, { useEffect, useRef } from 'react';
13
13
  import { X, Settings } from 'lucide-react';
14
14
  import {
15
15
  Dialog,
@@ -21,6 +21,7 @@ import {
21
21
  } from '@/components/ui/dialog';
22
22
  import { Dialog as DialogPrimitive } from 'radix-ui';
23
23
  import { cn } from '@/lib/utils';
24
+ import { Sounds } from '@/lib/sound';
24
25
 
25
26
  interface ModalProps {
26
27
  isOpen: boolean;
@@ -62,14 +63,40 @@ const Modal: React.FC<ModalProps> = ({
62
63
  }) => {
63
64
  const showHeader = Boolean(title || headerActions);
64
65
 
66
+ // Fire per-theme open/close sounds on isOpen transitions only — not
67
+ // on first mount (use a previous-value ref to detect the actual
68
+ // edge). Sounds.play is a no-op when the engine is disabled.
69
+ const prevOpenRef = useRef(isOpen);
70
+ useEffect(() => {
71
+ const prev = prevOpenRef.current;
72
+ if (prev !== isOpen) {
73
+ Sounds.play(isOpen ? 'modalOpen' : 'modalClose');
74
+ prevOpenRef.current = isOpen;
75
+ }
76
+ }, [isOpen]);
77
+
65
78
  return (
66
79
  <Dialog open={isOpen} onOpenChange={(next) => { if (!next) onClose(); }}>
67
80
  <DialogPortal>
68
- <DialogOverlay className="bg-black/50 supports-backdrop-filter:backdrop-blur-xs" />
81
+ {/* bg-bg-overlay reads --bg-overlay (each theme owns its own
82
+ scrim alpha + tone — Renaissance uses ink-brown, Cyber uses
83
+ void-near-black, light/dark use plain blacks). */}
84
+ <DialogOverlay className="bg-bg-overlay supports-backdrop-filter:backdrop-blur-xs" />
69
85
  <DialogPrimitive.Content
70
86
  data-slot="dialog-content"
71
87
  className={cn(
72
- 'fixed top-1/2 left-1/2 z-50 flex -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-border bg-background shadow-2xl outline-none',
88
+ // bg-bg-app + border-border-default consume the new-contract
89
+ // tokens directly so modals inherit the surface hierarchy
90
+ // defined by the active theme (parchment under Renaissance,
91
+ // void under Cyber).
92
+ //
93
+ // `modal` + `modal-frame` are the design-handoff structural
94
+ // hooks — per-theme CSS targets these classes for nailed-up
95
+ // borders (Plague), gilded corners (Renaissance), neon
96
+ // scanlines (Cyber), double-rule frames (Greek), parchment
97
+ // textures (Renaissance) on the modal content.
98
+ 'modal modal-frame',
99
+ 'fixed top-1/2 left-1/2 z-50 flex -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border border-border-default bg-bg-app shadow-2xl outline-none',
73
100
  'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 duration-100',
74
101
  className
75
102
  )}
@@ -81,15 +108,20 @@ const Modal: React.FC<ModalProps> = ({
81
108
  }}
82
109
  >
83
110
  {showHeader ? (
84
- <div className="relative flex w-full items-center border-b border-border bg-card px-5 py-3">
85
- <DialogTitle className="absolute left-5 flex items-center gap-2 text-base font-semibold text-foreground/80">
111
+ // Header: bg-bg-panel sits one elevation step above bg-bg-app
112
+ // (panel surface above page surface). font-display + tracking
113
+ // + text-transform are theme-driven so titles read as Cinzel
114
+ // uppercase under Renaissance and Major Mono Display under
115
+ // Cyber, while staying clean sans-serif under light/dark.
116
+ <div className="modal-head relative flex w-full items-center border-b border-border-default bg-bg-panel px-5 py-3">
117
+ <DialogTitle className="absolute left-5 flex items-center gap-2 font-display text-base font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">
86
118
  <Settings className="h-4 w-4 opacity-70" />
87
119
  {title}
88
120
  </DialogTitle>
89
121
  <div className="flex flex-1 items-center justify-center">{headerActions}</div>
90
122
  <DialogClose
91
123
  onClick={onClose}
92
- className="absolute right-5 inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
124
+ className="absolute right-5 inline-flex h-8 w-8 items-center justify-center rounded-md text-fg-muted transition-colors hover:bg-bg-hover hover:text-fg-default"
93
125
  aria-label="Close"
94
126
  >
95
127
  <X className="h-[18px] w-[18px]" />
@@ -156,7 +156,7 @@ const OutputDisplayPanel: React.FC<OutputDisplayPanelProps> = ({ results, onClea
156
156
  <div className="flex items-center justify-between border-b border-border bg-background px-4 py-3">
157
157
  <div className="flex items-center gap-2">
158
158
  <Play className="h-4 w-4 text-success" />
159
- <span className="text-sm font-semibold text-foreground">Execution Results</span>
159
+ <span className="font-display text-sm font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">Execution Results</span>
160
160
  <Badge variant="secondary" className="text-xs">{results.length}</Badge>
161
161
  </div>
162
162
  {onClear && (