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.
- package/README.md +143 -107
- package/client/dist/assets/ActionBar-Du2MSFSz.js +1 -0
- package/client/dist/assets/ApiKeyInput-k2LBmBjb.js +1 -0
- package/client/dist/assets/ApiKeyPanel-C_bV9U0X.js +1 -0
- package/client/dist/assets/ApiUsageSection-CmVfwZzL.js +1 -0
- package/client/dist/assets/EmailPanel-CeKIMGu-.js +1 -0
- package/client/dist/assets/OAuthPanel-KA3t3Q2K.js +1 -0
- package/client/dist/assets/QrPairingPanel-NgNpJNuk.js +1 -0
- package/client/dist/assets/RateLimitSection-Du5YNVIA.js +1 -0
- package/client/dist/assets/StatusCard-DNLyayXc.js +1 -0
- package/client/dist/assets/index-DQ0nwhec.js +257 -0
- package/client/dist/assets/index-DxmbVskS.css +1 -0
- package/client/dist/assets/vendor-flow-CZmBvHRo.js +1 -0
- package/client/dist/assets/vendor-icons-CVrPjN2Q.js +22 -0
- package/client/dist/assets/vendor-markdown-CRou3yQ5.js +62 -0
- package/client/dist/assets/vendor-misc-C4VxKHs5.js +1 -0
- package/client/dist/assets/vendor-query-SzWcOU0G.js +1 -0
- package/client/dist/assets/vendor-radix-Dnos29jG.js +56 -0
- package/client/dist/assets/vendor-react-DvWIbVx0.js +1 -0
- package/client/dist/index.html +37 -3
- package/client/index.html +28 -1
- package/client/package.json +44 -40
- package/client/src/App.tsx +2 -0
- package/client/src/Dashboard.tsx +157 -45
- package/client/src/ParameterPanel.tsx +3 -5
- package/client/src/adapters/nodeSpecToDescription.ts +1 -0
- package/client/src/assets/icons/NodeIcon.tsx +32 -0
- package/client/src/assets/icons/index.ts +4 -0
- package/client/src/assets/icons/stripe.svg +1 -0
- package/client/src/assets/icons/themedGlyphs.ts +404 -0
- package/client/src/components/AIAgentNode.tsx +77 -53
- package/client/src/components/GenericNode.tsx +34 -52
- package/client/src/components/OutputPanel.tsx +64 -147
- package/client/src/components/ParameterRenderer.tsx +5 -3
- package/client/src/components/SkillEditorModal.tsx +9 -18
- package/client/src/components/SquareNode.tsx +97 -115
- package/client/src/components/StartNode.tsx +32 -42
- package/client/src/components/SvgFilterDefs.tsx +54 -0
- package/client/src/components/TeamMonitorNode.tsx +12 -14
- package/client/src/components/ToolkitNode.tsx +35 -60
- package/client/src/components/TriggerNode.tsx +43 -77
- package/client/src/components/__tests__/CredentialsModal.test.tsx +49 -45
- package/client/src/components/credentials/CredentialsModal.tsx +98 -30
- package/client/src/components/credentials/CredentialsPalette.tsx +73 -5
- package/client/src/components/credentials/catalogueAdapter.ts +17 -1
- package/client/src/components/credentials/panels/ApiKeyPanel.tsx +102 -37
- package/client/src/components/credentials/panels/EmailPanel.tsx +7 -19
- package/client/src/components/credentials/panels/OAuthPanel.tsx +5 -1
- package/client/src/components/credentials/panels/QrPairingPanel.tsx +1 -3
- package/client/src/components/credentials/primitives/ActionBar.tsx +7 -11
- package/client/src/components/credentials/primitives/OAuthConnect.tsx +19 -28
- package/client/src/components/credentials/sections/ProviderDefaultsSection.tsx +24 -3
- package/client/src/components/credentials/types.ts +12 -2
- package/client/src/components/credentials/useCredentialPanel.ts +43 -19
- package/client/src/components/icons/AIProviderIcons.tsx +16 -0
- package/client/src/components/onboarding/OnboardingWizard.tsx +23 -63
- package/client/src/components/onboarding/nodeRoleClasses.ts +23 -0
- package/client/src/components/onboarding/steps/CanvasStep.tsx +15 -21
- package/client/src/components/onboarding/steps/ConceptsStep.tsx +2 -11
- package/client/src/components/onboarding/steps/GetStartedStep.tsx +2 -10
- package/client/src/components/parameterPanel/InputSection.tsx +9 -7
- package/client/src/components/parameterPanel/MasterSkillEditor.tsx +84 -198
- package/client/src/components/parameterPanel/MiddleSection.tsx +57 -80
- package/client/src/components/parameterPanel/ToolSchemaEditor.tsx +31 -25
- package/client/src/components/parameterPanel/__tests__/InputSection.test.tsx +7 -2
- package/client/src/components/ui/AIResultModal.tsx +1 -1
- package/client/src/components/ui/CollapsibleSection.tsx +9 -5
- package/client/src/components/ui/CommandPalette.tsx +147 -0
- package/client/src/components/ui/CommandPaletteHost.tsx +189 -0
- package/client/src/components/ui/ComponentItem.tsx +13 -7
- package/client/src/components/ui/ComponentPalette.tsx +24 -13
- package/client/src/components/ui/ConsolePanel.tsx +19 -11
- package/client/src/components/ui/DropCap.tsx +28 -0
- package/client/src/components/ui/EditableNodeLabel.tsx +10 -2
- package/client/src/components/ui/InputNodesPanel.tsx +1 -1
- package/client/src/components/ui/Modal.tsx +38 -6
- package/client/src/components/ui/OutputDisplayPanel.tsx +1 -1
- package/client/src/components/ui/SettingsPanel.tsx +42 -13
- package/client/src/components/ui/StatusBar.tsx +108 -0
- package/client/src/components/ui/ThemeSwitcher.tsx +109 -0
- package/client/src/components/ui/TopToolbar.tsx +42 -25
- package/client/src/components/ui/WorkflowSidebar.tsx +32 -16
- package/client/src/components/ui/action-button.tsx +40 -15
- package/client/src/components/ui/button.tsx +24 -1
- package/client/src/components/ui/dropdown-menu.tsx +24 -2
- package/client/src/components/ui/input.tsx +19 -2
- package/client/src/components/ui/select.tsx +15 -0
- package/client/src/components/ui/textarea.tsx +15 -2
- package/client/src/contexts/AuthContext.tsx +148 -109
- package/client/src/contexts/ThemeContext.tsx +93 -17
- package/client/src/contexts/WebSocketContext.tsx +373 -206
- package/client/src/contexts/__tests__/AuthContext.test.tsx +221 -0
- package/client/src/hooks/__tests__/useDragVariable.test.ts +7 -1
- package/client/src/hooks/__tests__/useWorkflowOpsListener.test.ts +142 -0
- package/client/src/hooks/useAppTheme.ts +209 -7
- package/client/src/hooks/useAutoSkillEdges.ts +7 -2
- package/client/src/hooks/useCatalogueQuery.ts +67 -1
- package/client/src/hooks/useDragVariable.ts +1 -1
- package/client/src/hooks/useNodeAllowlist.ts +115 -8
- package/client/src/hooks/useOnboarding.ts +20 -8
- package/client/src/hooks/useParameterPanel.ts +2 -1
- package/client/src/hooks/useReactFlowNodes.ts +2 -1
- package/client/src/hooks/useSound.ts +185 -0
- package/client/src/hooks/useWorkflowManagement.ts +6 -8
- package/client/src/hooks/useWorkflowOpsListener.ts +90 -0
- package/client/src/index.css +65 -3
- package/client/src/lib/__tests__/connectionConfig.test.ts +91 -0
- package/client/src/lib/aiModelProviders.ts +8 -0
- package/client/src/lib/connectionConfig.ts +107 -0
- package/client/src/lib/queryPersist.ts +13 -5
- package/client/src/lib/sound.ts +393 -0
- package/client/src/main.tsx +20 -0
- package/client/src/store/useAppStore.ts +26 -0
- package/client/src/styles/canvasAnimations.ts +37 -36
- package/client/src/styles/theme.ts +36 -20
- package/client/src/test/setup.ts +1 -0
- package/client/src/themes/atomic.css +253 -0
- package/client/src/themes/base.css +373 -0
- package/client/src/themes/cyber.css +890 -0
- package/client/src/themes/dark.css +70 -0
- package/client/src/themes/edo.css +246 -0
- package/client/src/themes/greek.css +293 -0
- package/client/src/themes/light.css +78 -0
- package/client/src/themes/plague.css +253 -0
- package/client/src/themes/renaissance.css +727 -0
- package/client/src/themes/rot.css +249 -0
- package/client/src/themes/steampunk.css +272 -0
- package/client/src/themes/surveillance.css +289 -0
- package/client/src/themes/wasteland.css +250 -0
- package/client/src/types/INodeProperties.ts +5 -0
- package/client/src/types/NodeTypes.ts +11 -1
- package/client/src/types/__tests__/cloudEvents.test.ts +99 -0
- package/client/src/types/cloudEvents.ts +78 -0
- package/client/src/vite-env.d.ts +7 -0
- package/client/tsconfig.json +1 -1
- package/client/vite.config.js +62 -2
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/machina/commands/build.py +51 -7
- package/machina/pyproject.toml +4 -0
- package/machina/supervisor.py +12 -2
- package/machina/tree.py +71 -21
- package/package.json +4 -4
- package/scripts/install.js +16 -1
- package/server/config/ai_cli_providers.json +54 -0
- package/server/config/credential_providers.json +109 -2
- package/server/config/llm_defaults.json +24 -0
- package/server/config/model_registry.json +338 -499
- package/server/config/node_allowlist.json +16 -1
- package/server/config/pricing.json +8 -0
- package/server/constants.py +38 -15
- package/server/core/container.py +2 -2
- package/server/core/credentials_database.py +35 -2
- package/server/core/logging.py +4 -3
- package/server/main.py +99 -13
- package/server/models/node_metadata.py +1 -0
- package/server/nodejs/package.json +8 -6
- package/server/nodejs/src/index.ts +22 -5
- package/server/nodes/README.md +31 -4
- package/server/nodes/agent/_inline.py +2 -0
- package/server/nodes/agent/_specialized.py +6 -3
- package/server/nodes/agent/ai_agent.py +13 -3
- package/server/nodes/agent/chat_agent.py +6 -3
- package/server/nodes/agent/claude_code_agent.py +287 -75
- package/server/nodes/agent/codex_agent.py +239 -0
- package/server/nodes/agent/deep_agent.py +3 -3
- package/server/nodes/agent/rlm_agent.py +3 -3
- package/server/nodes/android/__init__.py +31 -1
- package/server/nodes/android/_base.py +9 -5
- package/server/{services/android_service.py → nodes/android/_dispatcher.py} +2 -2
- package/server/nodes/android/_handlers.py +154 -0
- package/server/nodes/android/_option_loaders.py +44 -0
- package/server/nodes/android/_refresh.py +127 -0
- package/server/{services/android → nodes/android/_relay}/client.py +4 -4
- package/server/{routers/android.py → nodes/android/_router.py} +27 -8
- package/server/nodes/browser/browser.py +2 -2
- package/server/nodes/code/_base.py +6 -2
- package/server/nodes/code/_claude_code.py +134 -0
- package/server/nodes/document/embedding_generator.py +3 -3
- package/server/nodes/document/http_scraper.py +3 -3
- package/server/nodes/document/vector_store.py +5 -5
- package/server/nodes/email/__init__.py +11 -1
- package/server/nodes/email/_filters.py +21 -0
- package/server/{services/himalaya_service.py → nodes/email/_himalaya.py} +6 -10
- package/server/{services/email_service.py → nodes/email/_service.py} +9 -13
- package/server/nodes/email/email_read.py +1 -1
- package/server/nodes/email/email_receive.py +54 -5
- package/server/nodes/email/email_send.py +1 -1
- package/server/nodes/filesystem/shell.py +24 -1
- package/server/nodes/google/__init__.py +55 -1
- package/server/{services/handlers/google_auth.py → nodes/google/_auth_helper.py} +8 -5
- package/server/nodes/google/_base.py +2 -2
- package/server/nodes/google/_credentials.py +5 -5
- package/server/nodes/google/_filters.py +25 -0
- package/server/nodes/google/_handlers.py +57 -0
- package/server/{services/google_oauth.py → nodes/google/_oauth.py} +195 -162
- package/server/nodes/google/_option_loaders.py +107 -0
- package/server/nodes/google/_refresh.py +66 -0
- package/server/nodes/google/_router.py +131 -0
- package/server/nodes/google/gmail_receive.py +41 -4
- package/server/nodes/groups.py +1 -0
- package/server/nodes/location/_credentials.py +45 -1
- package/server/{services/maps.py → nodes/location/_service.py} +18 -3
- package/server/nodes/location/gmaps_create.py +4 -4
- package/server/nodes/location/gmaps_locations.py +4 -4
- package/server/nodes/location/gmaps_nearby_places.py +4 -4
- package/server/nodes/model/_base.py +8 -3
- package/server/nodes/model/_credentials.py +96 -8
- package/server/nodes/model/_local_validator.py +345 -0
- package/server/nodes/model/lmstudio_chat_model.py +23 -0
- package/server/nodes/model/ollama_chat_model.py +25 -0
- package/server/nodes/proxy/_usage.py +2 -2
- package/server/nodes/proxy/proxy_config.py +14 -14
- package/server/nodes/proxy/proxy_request.py +4 -4
- package/server/nodes/scraper/_credentials.py +29 -1
- package/server/nodes/scraper/apify_actor.py +9 -9
- package/server/nodes/scraper/crawlee_scraper.py +5 -5
- package/server/nodes/search/brave_search.py +4 -0
- package/server/nodes/search/perplexity_search.py +9 -0
- package/server/nodes/search/serper_search.py +3 -0
- package/server/nodes/skill/simple_memory.py +12 -0
- package/server/nodes/social/_base.py +2 -2
- package/server/nodes/stripe/__init__.py +46 -0
- package/server/nodes/stripe/_credentials.py +33 -0
- package/server/nodes/stripe/_handlers.py +270 -0
- package/server/nodes/stripe/_install.py +127 -0
- package/server/nodes/stripe/_source.py +174 -0
- package/server/nodes/stripe/stripe_action.py +81 -0
- package/server/nodes/stripe/stripe_receive.py +92 -0
- package/server/nodes/telegram/_credentials.py +52 -1
- package/server/nodes/telegram/_handlers.py +19 -18
- package/server/nodes/telegram/_service.py +134 -32
- package/server/nodes/telegram/telegram_send.py +5 -6
- package/server/nodes/text/file_handler.py +2 -2
- package/server/nodes/text/text_generator.py +2 -2
- package/server/nodes/tool/agent_builder.py +630 -0
- package/server/nodes/tool/task_manager.py +144 -2
- package/server/nodes/twitter/__init__.py +38 -1
- package/server/nodes/twitter/_base.py +7 -7
- package/server/nodes/twitter/_credentials.py +1 -1
- package/server/nodes/twitter/_filters.py +37 -0
- package/server/nodes/twitter/_handlers.py +77 -0
- package/server/nodes/twitter/_oauth.py +124 -0
- package/server/nodes/twitter/_refresh.py +78 -0
- package/server/nodes/twitter/_router.py +29 -0
- package/server/nodes/twitter/twitter_receive.py +4 -0
- package/server/nodes/visuals.json +64 -19
- package/server/nodes/whatsapp/__init__.py +45 -5
- package/server/nodes/whatsapp/_base.py +3 -3
- package/server/nodes/whatsapp/_filters.py +137 -0
- package/server/nodes/whatsapp/_handlers.py +167 -0
- package/server/nodes/whatsapp/_option_loaders.py +68 -0
- package/server/nodes/whatsapp/_refresh.py +62 -0
- package/server/nodes/whatsapp/_runtime.py +1 -1
- package/server/pyproject.toml +29 -7
- package/server/routers/schemas.py +2 -2
- package/server/routers/webhook.py +26 -9
- package/server/routers/websocket.py +149 -810
- package/server/services/ai.py +89 -8
- package/server/services/auth.py +220 -43
- package/server/services/claude_oauth.py +126 -100
- package/server/services/cli_agent/__init__.py +78 -0
- package/server/services/cli_agent/_handlers.py +237 -0
- package/server/services/cli_agent/config.py +112 -0
- package/server/services/cli_agent/factory.py +48 -0
- package/server/services/cli_agent/lockfile.py +141 -0
- package/server/services/cli_agent/mcp_server.py +482 -0
- package/server/services/cli_agent/protocol.py +173 -0
- package/server/services/cli_agent/providers/__init__.py +9 -0
- package/server/services/cli_agent/providers/anthropic_claude.py +419 -0
- package/server/services/cli_agent/providers/google_gemini.py +80 -0
- package/server/services/cli_agent/providers/openai_codex.py +310 -0
- package/server/services/cli_agent/service.py +607 -0
- package/server/services/cli_agent/session.py +618 -0
- package/server/services/cli_agent/types.py +227 -0
- package/server/services/cli_agent/workflow_tools.py +233 -0
- package/server/services/credential_registry.py +26 -1
- package/server/services/deployment/manager.py +26 -145
- package/server/services/deployment/poll_registry.py +59 -0
- package/server/services/event_waiter.py +76 -246
- package/server/services/events/__init__.py +54 -0
- package/server/services/events/cli.py +78 -0
- package/server/services/events/daemon.py +163 -0
- package/server/services/events/envelope.py +281 -0
- package/server/services/events/lifecycle.py +99 -0
- package/server/services/events/oauth_lifecycle.py +534 -0
- package/server/services/events/polling.py +60 -0
- package/server/services/events/push.py +36 -0
- package/server/services/events/source.py +63 -0
- package/server/services/events/triggers.py +118 -0
- package/server/services/events/verifiers/__init__.py +25 -0
- package/server/services/events/verifiers/base.py +28 -0
- package/server/services/events/verifiers/github.py +25 -0
- package/server/services/events/verifiers/hmac_basic.py +32 -0
- package/server/services/events/verifiers/standard_webhooks.py +47 -0
- package/server/services/events/verifiers/stripe.py +42 -0
- package/server/services/events/webhook.py +105 -0
- package/server/services/handlers/tools.py +28 -186
- package/server/services/llm/config.py +7 -0
- package/server/services/llm/factory.py +8 -2
- package/server/services/memory/__init__.py +52 -0
- package/server/services/memory/jsonl.py +80 -0
- package/server/services/memory/markdown.py +65 -0
- package/server/services/memory/state.py +112 -0
- package/server/services/memory/vector_store.py +40 -0
- package/server/services/model_registry.py +76 -0
- package/server/services/node_allowlist.py +71 -15
- package/server/services/node_executor.py +2 -2
- package/server/services/node_output_schemas.py +21 -10
- package/server/services/node_spec.py +1 -1
- package/server/services/oauth_utils.py +1 -1
- package/server/services/plugin/__init__.py +2 -0
- package/server/services/plugin/base.py +44 -2
- package/server/services/plugin/credential.py +288 -1
- package/server/services/plugin/deps.py +105 -0
- package/server/services/plugin/edge_walker.py +12 -4
- package/server/services/plugin/oauth.py +381 -0
- package/server/services/plugin/polling.py +247 -0
- package/server/services/plugin/registry.py +145 -0
- package/server/services/plugin/singleton.py +65 -0
- package/server/services/plugin/ws.py +81 -0
- package/server/services/process_service.py +31 -2
- package/server/services/status_broadcaster.py +155 -238
- package/server/services/temporal/workflow.py +7 -7
- package/server/services/workflow.py +21 -3
- package/server/services/ws_handler_registry.py +111 -28
- package/server/skills/GUIDE.md +16 -1
- package/server/skills/assistant/agent-builder-skill/SKILL.md +166 -0
- package/server/skills/payments_agent/stripe-skill/SKILL.md +306 -0
- package/server/tests/credentials/test_auth_service.py +16 -9
- package/server/tests/credentials/test_credential_broadcasts.py +219 -0
- package/server/tests/credentials/test_google_oauth.py +6 -6
- package/server/tests/credentials/test_oauth_utils.py +1 -1
- package/server/tests/credentials/test_twitter_oauth.py +2 -2
- package/server/tests/credentials/test_websocket_handlers.py +44 -20
- package/server/tests/llm/test_factory.py +1 -0
- package/server/tests/llm/test_wiring.py +5 -1
- package/server/tests/nodes/_compat.py +24 -24
- package/server/tests/nodes/test_agent_builder.py +439 -0
- package/server/tests/nodes/test_ai_tools.py +18 -14
- package/server/tests/nodes/test_code_fs_process.py +17 -8
- package/server/tests/nodes/test_email.py +10 -9
- package/server/tests/nodes/test_google_workspace.py +2 -2
- package/server/tests/nodes/test_specialized_agents.py +100 -53
- package/server/tests/nodes/test_stripe_plugin.py +293 -0
- package/server/tests/nodes/test_telegram_social.py +4 -4
- package/server/tests/nodes/test_twitter.py +1 -1
- package/server/tests/nodes/test_web_automation.py +2 -2
- package/server/tests/nodes/test_whatsapp.py +9 -9
- package/server/tests/services/cli_agent/__init__.py +0 -0
- package/server/tests/services/cli_agent/test_mcp_server.py +432 -0
- package/server/tests/services/cli_agent/test_providers.py +358 -0
- package/server/tests/services/cli_agent/test_service.py +298 -0
- package/server/tests/services/memory/__init__.py +0 -0
- package/server/tests/services/memory/test_jsonl.py +188 -0
- package/server/tests/services/test_events.py +333 -0
- package/server/tests/test_node_spec.py +56 -16
- package/server/tests/test_plugin_helpers.py +116 -0
- package/server/tests/test_plugin_self_containment.py +486 -0
- package/server/tests/test_status_broadcasts.py +425 -0
- package/workflows/{AI Assistant_workflow-1777421105154-0m4snkzjf.json → AI Assistant_workflow-1778504793388-ou1m1tz2x.json } +70 -266
- package/workflows/{AI Employee_workflow-1777720598005-u4cm858dv.json → AI Employee_example_workflow-1777720598005-u4cm858dv.json } +112 -112
- package/workflows/Claude Assistant_workflow-1778380124051-mdibn807c.json +709 -0
- package/client/dist/assets/ActionBar-vzPpSR77.js +0 -1
- package/client/dist/assets/ApiKeyInput-Ds7AKFe8.js +0 -1
- package/client/dist/assets/ApiKeyPanel-gfblELep.js +0 -1
- package/client/dist/assets/ApiUsageSection-BMNWTe2r.js +0 -1
- package/client/dist/assets/EmailPanel-B1Om64p5.js +0 -1
- package/client/dist/assets/OAuthPanel-CXyQYGBz.js +0 -1
- package/client/dist/assets/QrPairingPanel-BgNuI1we.js +0 -1
- package/client/dist/assets/RateLimitSection-YYK8sx1T.js +0 -1
- package/client/dist/assets/StatusCard-DuYA5hJR.js +0 -1
- package/client/dist/assets/index-D9tZfgvi.js +0 -363
- package/client/dist/assets/index-al7snTkG.css +0 -1
- package/client/src/components/credentials/providers.tsx +0 -177
- package/server/routers/google.py +0 -277
- package/server/routers/maps.py +0 -142
- package/server/routers/twitter.py +0 -365
- package/server/services/claude_code_service.py +0 -106
- package/server/services/memory.py +0 -159
- package/server/services/node_option_loaders/__init__.py +0 -77
- package/server/services/node_option_loaders/android_loaders.py +0 -55
- package/server/services/node_option_loaders/google_loaders.py +0 -97
- package/server/services/node_option_loaders/whatsapp_loaders.py +0 -69
- package/server/services/twitter_oauth.py +0 -411
- package/server/services/websocket_client.py +0 -29
- /package/server/{services/android → nodes/android/_relay}/__init__.py +0 -0
- /package/server/{services/android → nodes/android/_relay}/broadcaster.py +0 -0
- /package/server/{services/android → nodes/android/_relay}/manager.py +0 -0
- /package/server/{services/android → nodes/android/_relay}/protocol.py +0 -0
- /package/server/{services/browser_service.py → nodes/browser/_service.py} +0 -0
- /package/server/{services/whatsapp_service.py → nodes/whatsapp/_service.py} +0 -0
- /package/server/skills/{task_agent → assistant}/write-todos-skill/SKILL.md +0 -0
package/client/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-flow-client",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.78",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "vite --host 0.0.0.0",
|
|
8
8
|
"build": "vite build",
|
|
9
9
|
"lint": "eslint .",
|
|
10
10
|
"preview": "vite preview",
|
|
11
|
+
"typecheck": "tsgo --noEmit",
|
|
12
|
+
"typecheck:tsc": "tsc --noEmit",
|
|
11
13
|
"test": "vitest run",
|
|
12
14
|
"test:watch": "vitest",
|
|
13
15
|
"test:coverage": "vitest run --coverage",
|
|
@@ -15,59 +17,60 @@
|
|
|
15
17
|
"test:nodepanels": "vitest run src/hooks/__tests__/useDragVariable.test.ts src/hooks/__tests__/useParameterPanel.test.ts src/components/parameterPanel/__tests__ src/components/__tests__/OutputPanel.test.tsx"
|
|
16
18
|
},
|
|
17
19
|
"dependencies": {
|
|
18
|
-
"@eslint/js": "^9.
|
|
20
|
+
"@eslint/js": "^9.39.4",
|
|
19
21
|
"@fontsource-variable/geist": "^5.2.8",
|
|
20
22
|
"@hookform/resolvers": "^5.2.2",
|
|
21
|
-
"@lobehub/icons": "^2.
|
|
23
|
+
"@lobehub/icons": "^2.48.0",
|
|
22
24
|
"@lukemorales/query-key-factory": "^1.3.4",
|
|
23
25
|
"@radix-ui/react-collapsible": "^1.1.12",
|
|
24
26
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
25
27
|
"@radix-ui/react-slot": "^1.2.4",
|
|
26
28
|
"@tailwindcss/typography": "^0.5.19",
|
|
27
|
-
"@tanstack/query-sync-storage-persister": "^5.100.
|
|
28
|
-
"@tanstack/react-query": "^5.100.
|
|
29
|
-
"@tanstack/react-query-persist-client": "^5.100.
|
|
30
|
-
"@types/google.maps": "^3.
|
|
31
|
-
"@types/node": "^24.3
|
|
32
|
-
"@types/prismjs": "^1.26.
|
|
33
|
-
"@types/react": "^19.
|
|
34
|
-
"@types/react-dom": "^19.
|
|
29
|
+
"@tanstack/query-sync-storage-persister": "^5.100.10",
|
|
30
|
+
"@tanstack/react-query": "^5.100.10",
|
|
31
|
+
"@tanstack/react-query-persist-client": "^5.100.10",
|
|
32
|
+
"@types/google.maps": "^3.64.0",
|
|
33
|
+
"@types/node": "^24.12.3",
|
|
34
|
+
"@types/prismjs": "^1.26.6",
|
|
35
|
+
"@types/react": "^19.2.14",
|
|
36
|
+
"@types/react-dom": "^19.2.3",
|
|
35
37
|
"@uiw/react-json-view": "2.0.0-alpha.41",
|
|
36
|
-
"@vitejs/plugin-react": "^5.
|
|
37
|
-
"autoprefixer": "^10.
|
|
38
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
39
|
+
"autoprefixer": "^10.5.0",
|
|
38
40
|
"class-variance-authority": "^0.7.1",
|
|
39
41
|
"clsx": "^2.1.1",
|
|
40
|
-
"cmdk": "^1",
|
|
41
|
-
"eslint": "^9.
|
|
42
|
-
"eslint-plugin-react-hooks": "^7.
|
|
43
|
-
"eslint-plugin-react-refresh": "^0.4.
|
|
44
|
-
"fuzzysort": "^3",
|
|
45
|
-
"globals": "^16.
|
|
46
|
-
"idb-keyval": "^6",
|
|
47
|
-
"lucide-react": "^1.
|
|
42
|
+
"cmdk": "^1.1.1",
|
|
43
|
+
"eslint": "^9.39.4",
|
|
44
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
45
|
+
"eslint-plugin-react-refresh": "^0.4.26",
|
|
46
|
+
"fuzzysort": "^3.1.0",
|
|
47
|
+
"globals": "^16.5.0",
|
|
48
|
+
"idb-keyval": "^6.2.2",
|
|
49
|
+
"lucide-react": "^1.14.0",
|
|
48
50
|
"next-themes": "^0.4.6",
|
|
49
|
-
"
|
|
51
|
+
"partysocket": "1.1.18",
|
|
52
|
+
"postcss": "^8.5.14",
|
|
50
53
|
"prismjs": "^1.30.0",
|
|
51
54
|
"qrcode.react": "^4.2.0",
|
|
52
55
|
"radix-ui": "^1.4.3",
|
|
53
|
-
"react": "^19.
|
|
54
|
-
"react-dom": "^19.
|
|
55
|
-
"react-hook-form": "^7.
|
|
56
|
+
"react": "^19.2.6",
|
|
57
|
+
"react-dom": "^19.2.6",
|
|
58
|
+
"react-hook-form": "^7.75.0",
|
|
56
59
|
"react-markdown": "^10.1.0",
|
|
57
60
|
"react-simple-code-editor": "^0.14.1",
|
|
58
|
-
"react-virtuoso": "^4",
|
|
61
|
+
"react-virtuoso": "^4.18.7",
|
|
59
62
|
"reactflow": "^11.11.4",
|
|
60
63
|
"remark-breaks": "^4.0.0",
|
|
61
64
|
"remark-gfm": "^4.0.1",
|
|
62
|
-
"shadcn": "^4.
|
|
65
|
+
"shadcn": "^4.7.0",
|
|
63
66
|
"sonner": "^2.0.7",
|
|
64
|
-
"tailwind-merge": "^3.
|
|
65
|
-
"tailwindcss": "^4.
|
|
67
|
+
"tailwind-merge": "^3.6.0",
|
|
68
|
+
"tailwindcss": "^4.3.0",
|
|
66
69
|
"tw-animate-css": "^1.4.0",
|
|
67
|
-
"typescript": "^5.9.
|
|
68
|
-
"vite": "^7.
|
|
69
|
-
"zod": "^4.3
|
|
70
|
-
"zustand": "^5.0.
|
|
70
|
+
"typescript": "^5.9.3",
|
|
71
|
+
"vite": "^7.3.3",
|
|
72
|
+
"zod": "^4.4.3",
|
|
73
|
+
"zustand": "^5.0.13"
|
|
71
74
|
},
|
|
72
75
|
"overrides": {
|
|
73
76
|
"@emoji-mart/react": {
|
|
@@ -79,17 +82,18 @@
|
|
|
79
82
|
}
|
|
80
83
|
},
|
|
81
84
|
"devDependencies": {
|
|
82
|
-
"@tailwindcss/vite": "^4.
|
|
83
|
-
"@tanstack/react-query-devtools": "^5.100.
|
|
85
|
+
"@tailwindcss/vite": "^4.3.0",
|
|
86
|
+
"@tanstack/react-query-devtools": "^5.100.10",
|
|
84
87
|
"@testing-library/jest-dom": "^6.9.1",
|
|
85
88
|
"@testing-library/react": "^16.3.2",
|
|
86
|
-
"@testing-library/user-event": "^14.
|
|
87
|
-
"@typescript-eslint/parser": "^8.
|
|
88
|
-
"@
|
|
89
|
+
"@testing-library/user-event": "^14.6.1",
|
|
90
|
+
"@typescript-eslint/parser": "^8.59.2",
|
|
91
|
+
"@typescript/native-preview": "7.0.0-dev.20260504.1",
|
|
92
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
89
93
|
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
|
90
94
|
"jsdom": "^25.0.1",
|
|
91
95
|
"rollup-plugin-visualizer": "^7.0.1",
|
|
92
|
-
"typescript-eslint": "^8.
|
|
93
|
-
"vitest": "^
|
|
96
|
+
"typescript-eslint": "^8.59.2",
|
|
97
|
+
"vitest": "^3.0.0"
|
|
94
98
|
}
|
|
95
99
|
}
|
package/client/src/App.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
2
|
import Dashboard from './Dashboard';
|
|
3
3
|
import ProtectedRoute from './components/auth/ProtectedRoute';
|
|
4
|
+
import SvgFilterDefs from './components/SvgFilterDefs';
|
|
4
5
|
import { useTheme } from './contexts/ThemeContext';
|
|
5
6
|
import { Toaster } from '@/components/ui/sonner';
|
|
6
7
|
|
|
@@ -18,6 +19,7 @@ const App: React.FC = () => {
|
|
|
18
19
|
|
|
19
20
|
return (
|
|
20
21
|
<>
|
|
22
|
+
<SvgFilterDefs />
|
|
21
23
|
<ProtectedRoute>
|
|
22
24
|
<div className="flex h-screen w-screen">
|
|
23
25
|
<Dashboard />
|
package/client/src/Dashboard.tsx
CHANGED
|
@@ -35,6 +35,9 @@ import CredentialsModal from './components/CredentialsModal';
|
|
|
35
35
|
import OnboardingWizard from './components/onboarding/OnboardingWizard';
|
|
36
36
|
import ErrorBoundary from './components/ui/ErrorBoundary';
|
|
37
37
|
import ConsolePanel from './components/ui/ConsolePanel';
|
|
38
|
+
import StatusBar from './components/ui/StatusBar';
|
|
39
|
+
import CommandPaletteHost from './components/ui/CommandPaletteHost';
|
|
40
|
+
import { useSoundSync, withSound } from './hooks/useSound';
|
|
38
41
|
import { useAppTheme } from './hooks/useAppTheme';
|
|
39
42
|
import { useWorkflowManagement } from './hooks/useWorkflowManagement';
|
|
40
43
|
import { useWorkflowsQuery, WORKFLOWS_QUERY_KEY } from './hooks/useWorkflowsQuery';
|
|
@@ -44,10 +47,10 @@ import { useDragAndDrop } from './hooks/useDragAndDrop';
|
|
|
44
47
|
import { useComponentPalette } from './hooks/useComponentPalette';
|
|
45
48
|
import { useReactFlowNodes } from './hooks/useReactFlowNodes';
|
|
46
49
|
import { useAutoSkillEdges } from './hooks/useAutoSkillEdges';
|
|
50
|
+
import { useWorkflowOpsListener } from './hooks/useWorkflowOpsListener';
|
|
47
51
|
import { useCopyPaste } from './hooks/useCopyPaste';
|
|
48
52
|
import { useWebSocket } from './contexts/WebSocketContext';
|
|
49
53
|
import { useNodeStatusStore } from './stores/nodeStatusStore';
|
|
50
|
-
import { useTheme } from './contexts/ThemeContext';
|
|
51
54
|
import {
|
|
52
55
|
sanitizeNodesForComparison,
|
|
53
56
|
sanitizeEdgesForComparison,
|
|
@@ -95,7 +98,7 @@ const createNodeTypes = (): Record<string, React.ComponentType<any>> => {
|
|
|
95
98
|
types[spec.type] = COMPONENT_BY_KIND[kind];
|
|
96
99
|
} else if (spec.type === 'teamMonitor') {
|
|
97
100
|
types[spec.type] = TeamMonitorNode;
|
|
98
|
-
} else if (spec.
|
|
101
|
+
} else if ((spec.uiHints as any)?.isMasterSkillEditor === true) {
|
|
99
102
|
types[spec.type] = ToolkitNode;
|
|
100
103
|
} else {
|
|
101
104
|
types[spec.type] = SquareNode;
|
|
@@ -120,35 +123,36 @@ const initialEdges: Edge[] = [];
|
|
|
120
123
|
// Inner component that uses useReactFlow() - must be inside ReactFlowProvider
|
|
121
124
|
const DashboardContent: React.FC = () => {
|
|
122
125
|
const theme = useAppTheme();
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
126
|
+
// Slice selectors so a sidebar/palette toggle (or any other store
|
|
127
|
+
// mutation) does NOT re-render every node, edge, and toolbar in the
|
|
128
|
+
// Dashboard subtree. Action setters are stable refs from Zustand —
|
|
129
|
+
// single-field selectors are the cheapest way to read them.
|
|
130
|
+
const currentWorkflow = useAppStore((s) => s.currentWorkflow);
|
|
131
|
+
const hasUnsavedChanges = useAppStore((s) => s.hasUnsavedChanges);
|
|
132
|
+
const sidebarVisible = useAppStore((s) => s.sidebarVisible);
|
|
133
|
+
const componentPaletteVisible = useAppStore((s) => s.componentPaletteVisible);
|
|
134
|
+
const updateWorkflow = useAppStore((s) => s.updateWorkflow);
|
|
135
|
+
const loadWorkflow = useAppStore((s) => s.loadWorkflow);
|
|
136
|
+
const createNewWorkflow = useAppStore((s) => s.createNewWorkflow);
|
|
137
|
+
const saveWorkflow = useAppStore((s) => s.saveWorkflow);
|
|
138
|
+
const deleteWorkflow = useAppStore((s) => s.deleteWorkflow);
|
|
139
|
+
const migrateCurrentWorkflow = useAppStore((s) => s.migrateCurrentWorkflow);
|
|
140
|
+
const toggleSidebar = useAppStore((s) => s.toggleSidebar);
|
|
141
|
+
const toggleComponentPalette = useAppStore((s) => s.toggleComponentPalette);
|
|
142
|
+
const proMode = useAppStore((s) => s.proMode);
|
|
143
|
+
const toggleProMode = useAppStore((s) => s.toggleProMode);
|
|
144
|
+
const exportWorkflowToJSON = useAppStore((s) => s.exportWorkflowToJSON);
|
|
145
|
+
const exportWorkflowToFile = useAppStore((s) => s.exportWorkflowToFile);
|
|
146
|
+
const setCurrentWorkflow = useAppStore((s) => s.setCurrentWorkflow);
|
|
147
|
+
const selectedNode = useAppStore((s) => s.selectedNode);
|
|
148
|
+
const setSelectedNode = useAppStore((s) => s.setSelectedNode);
|
|
149
|
+
const renamingNodeId = useAppStore((s) => s.renamingNodeId);
|
|
150
|
+
const setRenamingNodeId = useAppStore((s) => s.setRenamingNodeId);
|
|
151
|
+
// Per-workflow UI state (n8n pattern)
|
|
152
|
+
const setWorkflowExecuting = useAppStore((s) => s.setWorkflowExecuting);
|
|
153
|
+
const setWorkflowExecutionOrder = useAppStore((s) => s.setWorkflowExecutionOrder);
|
|
154
|
+
const setWorkflowViewport = useAppStore((s) => s.setWorkflowViewport);
|
|
155
|
+
const clearWorkflowExecutionState = useAppStore((s) => s.clearWorkflowExecutionState);
|
|
152
156
|
|
|
153
157
|
// Single source-to-store sync: push currentWorkflow.id into the
|
|
154
158
|
// node-status Zustand store from the canonical app store. Previously
|
|
@@ -220,6 +224,9 @@ const DashboardContent: React.FC = () => {
|
|
|
220
224
|
setNodes,
|
|
221
225
|
setEdges,
|
|
222
226
|
});
|
|
227
|
+
// Apply runtime canvas mutations pushed from the backend (e.g.,
|
|
228
|
+
// Agent Builder tools called by the LLM mid-execution).
|
|
229
|
+
useWorkflowOpsListener({ nodes, edges, setNodes, setEdges });
|
|
223
230
|
const { copySelectedNodes, pasteNodes } = useCopyPaste({ nodes, edges, setNodes, setEdges, saveNodeParameters });
|
|
224
231
|
|
|
225
232
|
// Override all agent nodes to use the global model. Agent membership is
|
|
@@ -273,11 +280,53 @@ const DashboardContent: React.FC = () => {
|
|
|
273
280
|
const [settingsOpen, setSettingsOpen] = React.useState(false);
|
|
274
281
|
const [credentialsOpen, setCredentialsOpen] = React.useState(false);
|
|
275
282
|
const [onboardingReopenTrigger, setOnboardingReopenTrigger] = React.useState(0);
|
|
283
|
+
const [commandPaletteOpen, setCommandPaletteOpen] = React.useState(false);
|
|
276
284
|
|
|
277
285
|
// Console panel visibility from store (database-backed)
|
|
278
286
|
const consolePanelVisible = useAppStore((state) => state.consolePanelVisible);
|
|
279
287
|
const toggleConsolePanelVisible = useAppStore((state) => state.toggleConsolePanelVisible);
|
|
280
288
|
|
|
289
|
+
// Sound effects: mirror the soundEnabled slice into the WebAudio
|
|
290
|
+
// engine and re-read --sound-pack from :root on every theme change.
|
|
291
|
+
// Mounting once here keeps every event handler that calls useSound()
|
|
292
|
+
// in lockstep with the active theme + user preference.
|
|
293
|
+
useSoundSync();
|
|
294
|
+
|
|
295
|
+
// Wave 33: pause CSS animations while the tab is in the background.
|
|
296
|
+
//
|
|
297
|
+
// Without this, browsers continue advancing CSS animation timing on
|
|
298
|
+
// hidden tabs (RAF is throttled to ~1Hz but `animation` keyframes
|
|
299
|
+
// accumulate paused frames in the compositor's queue). When the user
|
|
300
|
+
// returns, all 50+ executing nodes' three-layer box-shadow `node-pulse`
|
|
301
|
+
// animations resume simultaneously and the GPU compositor stalls for
|
|
302
|
+
// 100-200ms blending the paused frames + Cyber theme's full-viewport
|
|
303
|
+
// `cyber-flicker` / `cyber-roll` decorations. During the stall, input
|
|
304
|
+
// events queue but don't dispatch — first click on tab return appears
|
|
305
|
+
// unresponsive until the composite pass finishes (then the second
|
|
306
|
+
// click works, hence the "wakes up on interaction" pattern).
|
|
307
|
+
//
|
|
308
|
+
// Setting `animation-play-state: paused` on every element via a CSS
|
|
309
|
+
// rule keyed off `<html data-page-hidden>` flushes the queue. The
|
|
310
|
+
// requestAnimationFrame on resume defers the unpause until after the
|
|
311
|
+
// first input is ready to dispatch (one frame's delay, imperceptible).
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
const handleVisibility = () => {
|
|
314
|
+
const root = document.documentElement;
|
|
315
|
+
if (document.hidden) {
|
|
316
|
+
root.setAttribute('data-page-hidden', '');
|
|
317
|
+
} else {
|
|
318
|
+
// Defer unpause to the next frame so the browser has a chance
|
|
319
|
+
// to clear the input queue before animations resume their
|
|
320
|
+
// composite work.
|
|
321
|
+
requestAnimationFrame(() => {
|
|
322
|
+
root.removeAttribute('data-page-hidden');
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
document.addEventListener('visibilitychange', handleVisibility);
|
|
327
|
+
return () => document.removeEventListener('visibilitychange', handleVisibility);
|
|
328
|
+
}, []);
|
|
329
|
+
|
|
281
330
|
// Context menu state for node right-click
|
|
282
331
|
const [contextMenu, setContextMenu] = React.useState<{
|
|
283
332
|
nodeId: string;
|
|
@@ -500,11 +549,17 @@ const DashboardContent: React.FC = () => {
|
|
|
500
549
|
strokeWidth: 2
|
|
501
550
|
}), [theme.dracula.cyan]);
|
|
502
551
|
|
|
552
|
+
// `.react-flow` is intentionally transparent so the parent
|
|
553
|
+
// `.canvas-host` / `.canvas` background-image (per-theme
|
|
554
|
+
// `--canvas-grid` + multi-layer gradient stack from
|
|
555
|
+
// client/src/themes/<theme>.css) paints through. Painting a
|
|
556
|
+
// backgroundColor here would hide every theme decoration —
|
|
557
|
+
// Cyber perspective grid, Renaissance fleur-de-lis, Surveillance
|
|
558
|
+
// CCTV reticle, Steampunk brass bolts, etc.
|
|
503
559
|
const reactFlowStyle = React.useMemo(() => ({
|
|
504
560
|
width: '100%',
|
|
505
561
|
height: '100%',
|
|
506
|
-
|
|
507
|
-
}), [theme.colors.background]);
|
|
562
|
+
}), []);
|
|
508
563
|
|
|
509
564
|
const snapGrid: [number, number] = React.useMemo(() => [20, 20], []);
|
|
510
565
|
|
|
@@ -632,8 +687,8 @@ const DashboardContent: React.FC = () => {
|
|
|
632
687
|
if (!currentWorkflow) return;
|
|
633
688
|
|
|
634
689
|
// Check if there's at least one trigger node (workflow entry points)
|
|
635
|
-
// Trigger types: start, cronScheduler, webhookTrigger, whatsappReceive, telegramReceive, twitterReceive,
|
|
636
|
-
const triggerTypes = ['start', 'cronScheduler', 'webhookTrigger', 'whatsappReceive', 'telegramReceive', 'twitterReceive', '
|
|
690
|
+
// Trigger types: start, cronScheduler, webhookTrigger, whatsappReceive, telegramReceive, twitterReceive, googleGmailReceive, workflowTrigger, chatTrigger, taskTrigger
|
|
691
|
+
const triggerTypes = ['start', 'cronScheduler', 'webhookTrigger', 'whatsappReceive', 'telegramReceive', 'twitterReceive', 'googleGmailReceive', 'emailReceive', 'workflowTrigger', 'chatTrigger', 'taskTrigger'];
|
|
637
692
|
const hasTriggerNode = nodes.some(node => triggerTypes.includes(node.type || ''));
|
|
638
693
|
if (!hasTriggerNode) {
|
|
639
694
|
alert('No trigger node found in workflow.\n\nAdd a trigger node (Cron Scheduler, WhatsApp Receive, Webhook, Chat Trigger, etc.) to begin deployment.');
|
|
@@ -1057,7 +1112,8 @@ const DashboardContent: React.FC = () => {
|
|
|
1057
1112
|
switch (event.key.toLowerCase()) {
|
|
1058
1113
|
case 's':
|
|
1059
1114
|
event.preventDefault();
|
|
1060
|
-
|
|
1115
|
+
// Match the toolbar Save button — fire the per-theme save sound.
|
|
1116
|
+
withSound('save', handleSave)();
|
|
1061
1117
|
break;
|
|
1062
1118
|
case 'c':
|
|
1063
1119
|
event.preventDefault();
|
|
@@ -1089,8 +1145,14 @@ const DashboardContent: React.FC = () => {
|
|
|
1089
1145
|
|
|
1090
1146
|
return (
|
|
1091
1147
|
<>
|
|
1092
|
-
<style>{buildCanvasStyles(theme.colors
|
|
1093
|
-
|
|
1148
|
+
<style>{buildCanvasStyles(theme.colors)}</style>
|
|
1149
|
+
{/* `app-frame` is the decorative-layer hook from the design handoff —
|
|
1150
|
+
per-theme CSS files target this class for outer ornaments
|
|
1151
|
+
(gilded corners under Renaissance, scanline overlay + corner
|
|
1152
|
+
brackets under Cyber, riveted ridged frame under Steampunk,
|
|
1153
|
+
REC dot under Surveillance, etc.). Decorations declare
|
|
1154
|
+
pointer-events: none so they don't intercept clicks. */}
|
|
1155
|
+
<div className="app-frame" style={{
|
|
1094
1156
|
width: '100%',
|
|
1095
1157
|
height: '100vh',
|
|
1096
1158
|
display: 'flex',
|
|
@@ -1102,12 +1164,16 @@ const DashboardContent: React.FC = () => {
|
|
|
1102
1164
|
<TopToolbar
|
|
1103
1165
|
workflowName={currentWorkflow?.name || 'Untitled Workflow'}
|
|
1104
1166
|
onWorkflowNameChange={handleWorkflowNameChange}
|
|
1105
|
-
|
|
1167
|
+
// `withSound('save'|'run', ...)` fires the per-theme audio
|
|
1168
|
+
// cue BEFORE the async dispatch so feedback is instant
|
|
1169
|
+
// regardless of save/deploy latency. No-op when sound is
|
|
1170
|
+
// disabled or the active pack is `none`.
|
|
1171
|
+
onSave={withSound('save', handleSave)}
|
|
1106
1172
|
onNew={handleNew}
|
|
1107
1173
|
onOpen={handleOpen}
|
|
1108
|
-
onRun={handleRun}
|
|
1174
|
+
onRun={withSound('run', handleRun)}
|
|
1109
1175
|
isRunning={isExecuting}
|
|
1110
|
-
onDeploy={handleDeploy}
|
|
1176
|
+
onDeploy={withSound('run', handleDeploy)}
|
|
1111
1177
|
onCancelDeployment={handleCancelDeployment}
|
|
1112
1178
|
isDeploying={isCurrentWorkflowActive}
|
|
1113
1179
|
hasUnsavedChanges={hasUnsavedChanges}
|
|
@@ -1158,10 +1224,27 @@ const DashboardContent: React.FC = () => {
|
|
|
1158
1224
|
display: 'flex',
|
|
1159
1225
|
position: 'relative',
|
|
1160
1226
|
}}>
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1227
|
+
{/* `canvas-host` + `canvas` activate per-theme canvas
|
|
1228
|
+
decorations (cyber grid backplane, atomic starburst, rot
|
|
1229
|
+
candlelight pools, surveillance crosshair brackets,
|
|
1230
|
+
renaissance fleur-de-lis + marginalia, greek temple key
|
|
1231
|
+
pattern). The `canvas` co-class is the handoff selector
|
|
1232
|
+
used by every per-theme CSS file. Decorative pseudo-
|
|
1233
|
+
elements declare pointer-events: none. */}
|
|
1234
|
+
<div
|
|
1235
|
+
className="canvas-host canvas"
|
|
1236
|
+
style={{
|
|
1237
|
+
flex: 1,
|
|
1238
|
+
// `backgroundColor` intentionally omitted — the per-theme
|
|
1239
|
+
// CSS in client/src/themes/<theme>.css owns the canvas
|
|
1240
|
+
// surface paint via the `:root[data-theme="..."] .canvas`
|
|
1241
|
+
// multi-layer `background` declaration (radial-gradient
|
|
1242
|
+
// vignette + grid pattern + noise texture + var(--bg-canvas)).
|
|
1243
|
+
// base.css `.canvas-host { background-image: var(--canvas-grid); }`
|
|
1244
|
+
// provides the fallback grid layer.
|
|
1245
|
+
position: 'relative',
|
|
1246
|
+
}}
|
|
1247
|
+
>
|
|
1165
1248
|
<ErrorBoundary>
|
|
1166
1249
|
<ReactFlow
|
|
1167
1250
|
nodes={styledNodes}
|
|
@@ -1236,6 +1319,35 @@ const DashboardContent: React.FC = () => {
|
|
|
1236
1319
|
nodes={nodes}
|
|
1237
1320
|
/>
|
|
1238
1321
|
|
|
1322
|
+
{/* Status bar — fixed-bottom system console line; surfaces
|
|
1323
|
+
connection state, workflow context, theme, clock. Always
|
|
1324
|
+
present below ConsolePanel. */}
|
|
1325
|
+
<StatusBar workflowName={currentWorkflow?.name} nodeCount={nodes.length} />
|
|
1326
|
+
|
|
1327
|
+
{/* Global command palette — ⌘K (Ctrl+K). Surface common shell
|
|
1328
|
+
actions; the registered list is local to this component
|
|
1329
|
+
because every handler is already in scope here. */}
|
|
1330
|
+
<CommandPaletteHost
|
|
1331
|
+
open={commandPaletteOpen}
|
|
1332
|
+
onOpenChange={setCommandPaletteOpen}
|
|
1333
|
+
handlers={{
|
|
1334
|
+
save: withSound('save', handleSave),
|
|
1335
|
+
newWorkflow: handleNew,
|
|
1336
|
+
open: handleOpen,
|
|
1337
|
+
run: withSound('run', handleDeploy),
|
|
1338
|
+
stop: handleCancelDeployment,
|
|
1339
|
+
isDeploying: isCurrentWorkflowActive,
|
|
1340
|
+
exportFile: handleExportFile,
|
|
1341
|
+
importJSON: handleImportJSON,
|
|
1342
|
+
openSettings: () => setSettingsOpen(true),
|
|
1343
|
+
openCredentials: () => setCredentialsOpen(true),
|
|
1344
|
+
toggleSidebar,
|
|
1345
|
+
toggleComponentPalette,
|
|
1346
|
+
toggleConsolePanel: toggleConsolePanelVisible,
|
|
1347
|
+
}}
|
|
1348
|
+
/>
|
|
1349
|
+
|
|
1350
|
+
|
|
1239
1351
|
{/* Parameter Panels */}
|
|
1240
1352
|
<ErrorBoundary>
|
|
1241
1353
|
<ParameterPanel />
|
|
@@ -5,12 +5,10 @@ import { useParameterPanel } from './hooks/useParameterPanel';
|
|
|
5
5
|
import { useAppStore } from './store/useAppStore';
|
|
6
6
|
import { useWebSocket } from './contexts/WebSocketContext';
|
|
7
7
|
import { ExecutionService, ExecutionResult } from './services/executionService';
|
|
8
|
-
import { useAppTheme } from './hooks/useAppTheme';
|
|
9
8
|
import { ActionButton } from './components/ui/action-button';
|
|
10
9
|
import { NodeIcon } from './assets/icons';
|
|
11
10
|
|
|
12
11
|
const ParameterPanel: React.FC = () => {
|
|
13
|
-
const theme = useAppTheme();
|
|
14
12
|
const {
|
|
15
13
|
selectedNode,
|
|
16
14
|
nodeDefinition,
|
|
@@ -22,7 +20,7 @@ const ParameterPanel: React.FC = () => {
|
|
|
22
20
|
isLoading,
|
|
23
21
|
} = useParameterPanel();
|
|
24
22
|
|
|
25
|
-
const
|
|
23
|
+
const currentWorkflow = useAppStore((s) => s.currentWorkflow);
|
|
26
24
|
const { executeNode, getNodeParameters, clearNodeStatus, cancelEventWait, getNodeStatus } = useWebSocket();
|
|
27
25
|
|
|
28
26
|
// Get current node status to check if waiting
|
|
@@ -136,13 +134,13 @@ const ParameterPanel: React.FC = () => {
|
|
|
136
134
|
// Header actions with node name and buttons in middle area
|
|
137
135
|
const headerActions = (
|
|
138
136
|
<div className="flex items-center gap-4">
|
|
139
|
-
<div className="flex items-center gap-2 text-[15px] font-semibold text-
|
|
137
|
+
<div className="flex items-center gap-2 font-display text-[15px] font-semibold tracking-[var(--type-tracking-display)] text-fg-default [text-transform:var(--type-uppercase)]">
|
|
140
138
|
<NodeIcon
|
|
141
139
|
icon={nodeDefinition.icon}
|
|
142
140
|
className="h-5 w-5 text-xl"
|
|
143
141
|
/>
|
|
144
142
|
<span>{nodeDefinition.displayName}</span>
|
|
145
|
-
{hasUnsavedChanges && <span
|
|
143
|
+
{hasUnsavedChanges && <span className="text-warning">*</span>}
|
|
146
144
|
</div>
|
|
147
145
|
<div className="flex items-center gap-2">
|
|
148
146
|
{canExecute && !hideRunButton && (
|
|
@@ -51,6 +51,7 @@ export interface NodeSpec {
|
|
|
51
51
|
componentKind?: 'square' | 'circle' | 'trigger' | 'start' | 'agent' | 'chat' | 'tool' | 'model' | 'generic';
|
|
52
52
|
handles?: NodeSpecHandle[];
|
|
53
53
|
hideOutputHandle?: boolean;
|
|
54
|
+
hideInputHandle?: boolean;
|
|
54
55
|
visibility?: 'all' | 'normal' | 'dev';
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -27,6 +27,8 @@ import * as React from 'react';
|
|
|
27
27
|
|
|
28
28
|
import { cn } from '@/lib/utils';
|
|
29
29
|
import { resolveIcon, resolveLibraryIcon, isImageIcon } from '.';
|
|
30
|
+
import { useTheme } from '../../contexts/ThemeContext';
|
|
31
|
+
import { THEMED_GLYPHS, ICON_KEYS, type IconKey } from './themedGlyphs';
|
|
30
32
|
|
|
31
33
|
export interface NodeIconProps {
|
|
32
34
|
/** Backend-declared icon string. May be undefined while the spec
|
|
@@ -44,7 +46,37 @@ export const NodeIcon: React.FC<NodeIconProps> = ({
|
|
|
44
46
|
className,
|
|
45
47
|
fallback = null,
|
|
46
48
|
}) => {
|
|
49
|
+
const { theme } = useTheme();
|
|
47
50
|
let inner: React.ReactNode;
|
|
51
|
+
|
|
52
|
+
// 1. Per-theme glyph override. Activates only when the icon prop is one
|
|
53
|
+
// of the conceptual `IconKey`s (`agent`, `trigger`, `tool`, …) AND
|
|
54
|
+
// the active theme declares an entry for it. Anything else (URLs,
|
|
55
|
+
// `asset:foo`, `lobehub:Brand`, `lucide:Bot`, emoji) skips this
|
|
56
|
+
// branch and falls through to the existing dispatch chain below.
|
|
57
|
+
// The SVG strings come from `themedGlyphs.ts` — author-trusted
|
|
58
|
+
// markup committed to the repo, never user input — so injecting
|
|
59
|
+
// via `dangerouslySetInnerHTML` is safe here. Do not extend this
|
|
60
|
+
// branch with values built from runtime input.
|
|
61
|
+
if (icon && ICON_KEYS.has(icon as IconKey)) {
|
|
62
|
+
const themedSvg = THEMED_GLYPHS[theme]?.[icon as IconKey];
|
|
63
|
+
if (themedSvg) {
|
|
64
|
+
// SAFE: `themedSvg` is an author-trusted constant from
|
|
65
|
+
// `themedGlyphs.ts` — committed-to-repo markup, never user input.
|
|
66
|
+
// The repo's ESLint config does not enable `react/no-danger`, so
|
|
67
|
+
// no eslint-disable is needed; this comment documents the trust
|
|
68
|
+
// boundary so future reviewers don't second-guess it.
|
|
69
|
+
return (
|
|
70
|
+
<span
|
|
71
|
+
className={cn('inline-flex items-center justify-center', className)}
|
|
72
|
+
dangerouslySetInnerHTML={{ __html: themedSvg }}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
// No entry for this theme/key — fall through to the default chain so
|
|
77
|
+
// the consumer's existing icon (lucide / asset / emoji) still renders.
|
|
78
|
+
}
|
|
79
|
+
|
|
48
80
|
const LibIcon = resolveLibraryIcon(icon);
|
|
49
81
|
if (LibIcon) {
|
|
50
82
|
// LibIcon is a runtime-resolved component reference; using it as a JSX
|
|
@@ -44,6 +44,8 @@ import OpenRouter from '@lobehub/icons/es/OpenRouter';
|
|
|
44
44
|
import DeepSeek from '@lobehub/icons/es/DeepSeek';
|
|
45
45
|
import Kimi from '@lobehub/icons/es/Kimi';
|
|
46
46
|
import Mistral from '@lobehub/icons/es/Mistral';
|
|
47
|
+
import Ollama from '@lobehub/icons/es/Ollama';
|
|
48
|
+
import LmStudio from '@lobehub/icons/es/LmStudio';
|
|
47
49
|
|
|
48
50
|
type RawSvg = string;
|
|
49
51
|
|
|
@@ -135,6 +137,8 @@ const LOBEHUB_BRANDS: Readonly<Record<string, any>> = {
|
|
|
135
137
|
deepseek: DeepSeek,
|
|
136
138
|
kimi: Kimi,
|
|
137
139
|
mistral: Mistral,
|
|
140
|
+
ollama: Ollama,
|
|
141
|
+
lmstudio: LmStudio,
|
|
138
142
|
};
|
|
139
143
|
|
|
140
144
|
const ICON_LIBRARIES: Readonly<Record<string, LibraryResolver>> = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="6" fill="#635BFF"/><path d="M14.4 13.2c0-.9.7-1.3 1.9-1.3 1.7 0 3.9.5 5.6 1.4V8.1c-1.9-.7-3.7-1-5.6-1-4.6 0-7.6 2.4-7.6 6.4 0 6.2 8.6 5.2 8.6 7.9 0 1.1-.9 1.4-2.2 1.4-1.9 0-4.3-.8-6.2-1.8v5.4c2.1.9 4.3 1.3 6.2 1.3 4.7 0 7.9-2.3 7.9-6.4 0-6.7-8.6-5.5-8.6-8.1z" fill="#fff"/></svg>
|