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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { memo, useState, useEffect, useCallback, useMemo } from 'react';
|
|
2
2
|
import { nodePropsEqual } from './nodeMemoEquality';
|
|
3
3
|
import { Handle, Position, NodeProps, useEdges, useNodes } from 'reactflow';
|
|
4
|
-
import { NodeData } from '../types/NodeTypes';
|
|
4
|
+
import { NodeData, NodeStyle } from '../types/NodeTypes';
|
|
5
5
|
import { useAppStore } from '../store/useAppStore';
|
|
6
6
|
import { resolveNodeDescription } from '../lib/nodeSpec';
|
|
7
7
|
import { useAppTheme } from '../hooks/useAppTheme';
|
|
@@ -38,7 +38,7 @@ interface TeamStatus {
|
|
|
38
38
|
|
|
39
39
|
const TeamMonitorNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnectable, selected }) => {
|
|
40
40
|
const theme = useAppTheme();
|
|
41
|
-
const
|
|
41
|
+
const setSelectedNode = useAppStore((s) => s.setSelectedNode);
|
|
42
42
|
const { sendRequest } = useWebSocket();
|
|
43
43
|
const edges = useEdges();
|
|
44
44
|
const nodes = useNodes();
|
|
@@ -123,20 +123,19 @@ const TeamMonitorNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConn
|
|
|
123
123
|
};
|
|
124
124
|
|
|
125
125
|
return (
|
|
126
|
+
// Visual styling (background, border, radius) lives in base.css `.node`
|
|
127
|
+
// defaults + per-theme overrides; reads `var(--node-color)` for accent.
|
|
126
128
|
<div
|
|
129
|
+
className={`node ${selected ? 'selected' : ''}`}
|
|
127
130
|
onClick={handleClick}
|
|
128
131
|
style={{
|
|
132
|
+
'--node-color': nodeColor,
|
|
129
133
|
width: 200,
|
|
130
134
|
minHeight: 120,
|
|
131
|
-
borderRadius: 8,
|
|
132
|
-
background: theme.isDarkMode
|
|
133
|
-
? `linear-gradient(135deg, ${nodeColor}15 0%, ${theme.colors.background} 100%)`
|
|
134
|
-
: `linear-gradient(145deg, #ffffff 0%, ${nodeColor}08 100%)`,
|
|
135
|
-
border: `2px solid ${selected ? theme.colors.focus : nodeColor + '60'}`,
|
|
136
135
|
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
137
136
|
fontSize: 10,
|
|
138
137
|
overflow: 'hidden',
|
|
139
|
-
}}
|
|
138
|
+
} as NodeStyle}
|
|
140
139
|
>
|
|
141
140
|
{/* Header */}
|
|
142
141
|
<div style={{
|
|
@@ -231,36 +230,35 @@ const TeamMonitorNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConn
|
|
|
231
230
|
)}
|
|
232
231
|
</div>
|
|
233
232
|
|
|
234
|
-
{/* Input Handle
|
|
233
|
+
{/* Input Handle — visual styling owned by `.node-handle.in`
|
|
234
|
+
in base.css + per-theme overrides. Inline keeps layout only. */}
|
|
235
235
|
<Handle
|
|
236
236
|
id="input-team"
|
|
237
237
|
type="target"
|
|
238
238
|
position={Position.Left}
|
|
239
239
|
isConnectable={isConnectable}
|
|
240
|
+
className="node-handle in"
|
|
240
241
|
style={{
|
|
241
242
|
left: -6,
|
|
242
243
|
top: '50%',
|
|
243
244
|
width: 10,
|
|
244
245
|
height: 10,
|
|
245
|
-
backgroundColor: theme.isDarkMode ? theme.colors.background : '#ffffff',
|
|
246
|
-
border: `2px solid ${nodeColor}`,
|
|
247
246
|
borderRadius: '50%',
|
|
248
247
|
}}
|
|
249
248
|
/>
|
|
250
249
|
|
|
251
|
-
{/* Output Handle */}
|
|
250
|
+
{/* Output Handle — visual styling owned by `.node-handle.out`. */}
|
|
252
251
|
<Handle
|
|
253
252
|
id="output-main"
|
|
254
253
|
type="source"
|
|
255
254
|
position={Position.Right}
|
|
256
255
|
isConnectable={isConnectable}
|
|
256
|
+
className="node-handle out"
|
|
257
257
|
style={{
|
|
258
258
|
right: -6,
|
|
259
259
|
top: '50%',
|
|
260
260
|
width: 10,
|
|
261
261
|
height: 10,
|
|
262
|
-
backgroundColor: nodeColor,
|
|
263
|
-
border: `2px solid ${theme.isDarkMode ? theme.colors.background : '#ffffff'}`,
|
|
264
262
|
borderRadius: '50%',
|
|
265
263
|
}}
|
|
266
264
|
/>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import React, { memo, useCallback } from 'react';
|
|
14
14
|
import { nodePropsEqual } from './nodeMemoEquality';
|
|
15
15
|
import { Handle, Position, NodeProps } from 'reactflow';
|
|
16
|
-
import { NodeData } from '../types/NodeTypes';
|
|
16
|
+
import { NodeData, NodeStyle } from '../types/NodeTypes';
|
|
17
17
|
import { useAppStore } from '../store/useAppStore';
|
|
18
18
|
import { resolveNodeDescription } from '../lib/nodeSpec';
|
|
19
19
|
import { NodeIcon } from '../assets/icons';
|
|
@@ -27,7 +27,9 @@ const TOOLKIT_NODE_TYPES = ['androidTool'];
|
|
|
27
27
|
|
|
28
28
|
const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnectable, selected }) => {
|
|
29
29
|
const theme = useAppTheme();
|
|
30
|
-
const
|
|
30
|
+
const setSelectedNode = useAppStore((s) => s.setSelectedNode);
|
|
31
|
+
const setRenamingNodeId = useAppStore((s) => s.setRenamingNodeId);
|
|
32
|
+
const updateNodeData = useAppStore((s) => s.updateNodeData);
|
|
31
33
|
|
|
32
34
|
// Get node status from WebSocket context
|
|
33
35
|
const { getNodeStatus } = useWebSocket();
|
|
@@ -67,17 +69,27 @@ const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
67
69
|
const iconSpec = useNodeSpec(type);
|
|
68
70
|
const iconRef = (iconSpec?.icon as string | undefined) ?? (definition?.icon as string | undefined);
|
|
69
71
|
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
if (executionStatus === '
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
// Pip status bucket — CSS owns the visual color via per-status rules.
|
|
73
|
+
// Toolkit's idle state always reads as "success" (it's always ready).
|
|
74
|
+
const pipStatus = (() => {
|
|
75
|
+
if (isExecuting) return 'executing';
|
|
76
|
+
if (executionStatus === 'success') return 'success';
|
|
77
|
+
if (executionStatus === 'error') return 'error';
|
|
78
|
+
return 'success';
|
|
79
|
+
})();
|
|
77
80
|
|
|
78
81
|
return (
|
|
82
|
+
// `sq-node` + `selected` co-classes activate per-theme square-node
|
|
83
|
+
// decorations (Renaissance wax seal, Steampunk rivets, Edo hanko
|
|
84
|
+
// seal, Surveillance REC LED, Cyber neon underglow). Visuals
|
|
85
|
+
// (background, border, radius, shadow, executing pulse) live in
|
|
86
|
+
// base.css `.sq-node-box` defaults + per-theme overrides; reads
|
|
87
|
+
// `var(--node-color)` for the per-definition accent.
|
|
79
88
|
<div
|
|
89
|
+
className={`sq-node ${selected ? 'selected' : ''}`}
|
|
90
|
+
data-executing={isExecuting ? '' : undefined}
|
|
80
91
|
style={{
|
|
92
|
+
'--node-color': nodeColor,
|
|
81
93
|
position: 'relative',
|
|
82
94
|
display: 'flex',
|
|
83
95
|
flexDirection: 'column',
|
|
@@ -85,95 +97,62 @@ const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
85
97
|
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
86
98
|
fontSize: '11px',
|
|
87
99
|
cursor: 'pointer',
|
|
88
|
-
}}
|
|
100
|
+
} as NodeStyle}
|
|
89
101
|
>
|
|
90
|
-
{/* Main Node - rectangular for toolkit, square for skills
|
|
102
|
+
{/* Main Node - rectangular for toolkit, square for skills.
|
|
103
|
+
Layout only; visuals live in CSS. */}
|
|
91
104
|
<div
|
|
105
|
+
className="sq-node-box"
|
|
92
106
|
style={{
|
|
93
107
|
position: 'relative',
|
|
94
108
|
width: isToolkitNode ? theme.nodeSize.toolkitWidth : theme.nodeSize.square,
|
|
95
109
|
height: isToolkitNode ? theme.nodeSize.toolkitHeight : theme.nodeSize.square,
|
|
96
|
-
borderRadius: theme.borderRadius.lg,
|
|
97
|
-
background: theme.isDarkMode
|
|
98
|
-
? `linear-gradient(135deg, ${nodeColor}25 0%, ${theme.colors.background} 100%)`
|
|
99
|
-
: `linear-gradient(145deg, #ffffff 0%, ${nodeColor}08 100%)`,
|
|
100
|
-
border: `2px solid ${isExecuting
|
|
101
|
-
? (theme.isDarkMode ? theme.dracula.cyan : '#2563eb')
|
|
102
|
-
: selected
|
|
103
|
-
? theme.colors.focus
|
|
104
|
-
: theme.isDarkMode ? nodeColor + '80' : `${nodeColor}40`}`,
|
|
105
110
|
display: 'flex',
|
|
106
111
|
alignItems: 'center',
|
|
107
112
|
justifyContent: 'center',
|
|
108
113
|
color: theme.colors.text,
|
|
109
114
|
fontSize: theme.nodeSize.squareIcon,
|
|
110
115
|
fontWeight: '600',
|
|
111
|
-
transition: 'all 0.2s ease',
|
|
112
|
-
boxShadow: isExecuting
|
|
113
|
-
? theme.isDarkMode
|
|
114
|
-
? `0 4px 12px ${theme.dracula.cyan}66, 0 0 0 3px ${theme.dracula.cyan}4D`
|
|
115
|
-
: `0 0 0 3px rgba(37, 99, 235, 0.5), 0 4px 16px rgba(37, 99, 235, 0.35)`
|
|
116
|
-
: selected
|
|
117
|
-
? `0 4px 12px ${theme.colors.focusRing}, 0 0 0 1px ${theme.colors.focusRing}`
|
|
118
|
-
: theme.isDarkMode
|
|
119
|
-
? `0 2px 8px ${nodeColor}40`
|
|
120
|
-
: `0 2px 8px ${nodeColor}20, 0 4px 12px rgba(0,0,0,0.06)`,
|
|
121
|
-
animation: isExecuting ? 'pulse 1.5s ease-in-out infinite' : 'none',
|
|
122
116
|
}}
|
|
123
117
|
>
|
|
124
118
|
{/* Service Icon */}
|
|
125
119
|
<NodeIcon icon={iconRef} className="h-7 w-7 text-3xl" />
|
|
126
120
|
|
|
127
|
-
{/* Parameters Button */}
|
|
121
|
+
{/* Parameters Button — CSS owns bg/border via .sq-node-gear */}
|
|
128
122
|
<button
|
|
129
123
|
onClick={handleParametersClick}
|
|
124
|
+
className="sq-node-gear"
|
|
130
125
|
style={{
|
|
131
126
|
position: 'absolute',
|
|
132
127
|
top: '-8px',
|
|
133
128
|
right: '-8px',
|
|
134
129
|
width: theme.nodeSize.paramButton,
|
|
135
130
|
height: theme.nodeSize.paramButton,
|
|
136
|
-
borderRadius: theme.borderRadius.sm,
|
|
137
|
-
backgroundColor: theme.isDarkMode ? theme.colors.backgroundAlt : '#ffffff',
|
|
138
|
-
border: `1px solid ${theme.isDarkMode ? theme.colors.border : '#d1d5db'}`,
|
|
139
131
|
cursor: 'pointer',
|
|
140
132
|
display: 'flex',
|
|
141
133
|
alignItems: 'center',
|
|
142
134
|
justifyContent: 'center',
|
|
143
135
|
fontSize: theme.fontSize.xs,
|
|
144
|
-
color: theme.colors.textSecondary,
|
|
145
136
|
fontWeight: '400',
|
|
146
137
|
transition: theme.transitions.fast,
|
|
147
138
|
zIndex: 30,
|
|
148
|
-
boxShadow: theme.isDarkMode
|
|
149
|
-
? `0 1px 3px ${theme.colors.shadow}`
|
|
150
|
-
: '0 1px 4px rgba(0,0,0,0.1)'
|
|
151
139
|
}}
|
|
152
140
|
title="Edit Toolkit Parameters"
|
|
153
141
|
>
|
|
154
142
|
⚙️
|
|
155
143
|
</button>
|
|
156
144
|
|
|
157
|
-
{/* Status Indicator */}
|
|
145
|
+
{/* Status Indicator — CSS owns bg/animation via per-status rules. */}
|
|
158
146
|
<div
|
|
147
|
+
className="sq-node-pip"
|
|
148
|
+
data-status={pipStatus}
|
|
159
149
|
style={{
|
|
160
150
|
position: 'absolute',
|
|
161
151
|
top: '-4px',
|
|
162
152
|
left: '-4px',
|
|
163
153
|
width: theme.nodeSize.statusIndicator,
|
|
164
154
|
height: theme.nodeSize.statusIndicator,
|
|
165
|
-
borderRadius: '50%',
|
|
166
|
-
backgroundColor: getStatusIndicatorColor(),
|
|
167
|
-
border: `2px solid ${theme.isDarkMode ? theme.colors.background : '#ffffff'}`,
|
|
168
|
-
boxShadow: isExecuting
|
|
169
|
-
? theme.isDarkMode
|
|
170
|
-
? `0 0 6px ${theme.dracula.cyan}80`
|
|
171
|
-
: '0 0 4px rgba(37, 99, 235, 0.5)'
|
|
172
|
-
: theme.isDarkMode
|
|
173
|
-
? `0 1px 2px ${theme.colors.shadow}`
|
|
174
|
-
: '0 1px 3px rgba(0,0,0,0.15)',
|
|
175
155
|
zIndex: 30,
|
|
176
|
-
animation: isExecuting ? 'pulse 1s ease-in-out infinite' : 'none',
|
|
177
156
|
}}
|
|
178
157
|
title={isExecuting ? 'Executing...' : 'Toolkit ready'}
|
|
179
158
|
/>
|
|
@@ -184,6 +163,7 @@ const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
184
163
|
type="source"
|
|
185
164
|
position={Position.Top}
|
|
186
165
|
isConnectable={isConnectable}
|
|
166
|
+
className="sq-node-handle out"
|
|
187
167
|
style={{
|
|
188
168
|
position: 'absolute',
|
|
189
169
|
top: '-6px',
|
|
@@ -191,10 +171,7 @@ const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
191
171
|
transform: 'translateX(-50%)',
|
|
192
172
|
width: theme.nodeSize.handle,
|
|
193
173
|
height: theme.nodeSize.handle,
|
|
194
|
-
|
|
195
|
-
border: `2px solid ${theme.isDarkMode ? theme.colors.background : '#ffffff'}`,
|
|
196
|
-
borderRadius: '50%',
|
|
197
|
-
zIndex: 20
|
|
174
|
+
zIndex: 20,
|
|
198
175
|
}}
|
|
199
176
|
title={isToolkitNode ? "Connect to AI Agent's tool input" : "Connect to agent's skill input"}
|
|
200
177
|
/>
|
|
@@ -206,6 +183,7 @@ const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
206
183
|
type="target"
|
|
207
184
|
position={Position.Bottom}
|
|
208
185
|
isConnectable={isConnectable}
|
|
186
|
+
className="sq-node-handle in"
|
|
209
187
|
style={{
|
|
210
188
|
position: 'absolute',
|
|
211
189
|
bottom: '-6px',
|
|
@@ -213,16 +191,13 @@ const ToolkitNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
213
191
|
transform: 'translateX(-50%)',
|
|
214
192
|
width: theme.nodeSize.handle,
|
|
215
193
|
height: theme.nodeSize.handle,
|
|
216
|
-
|
|
217
|
-
border: `2px solid ${theme.isDarkMode ? theme.colors.textSecondary : '#6b7280'}`,
|
|
218
|
-
borderRadius: '50%',
|
|
219
|
-
zIndex: 20
|
|
194
|
+
zIndex: 20,
|
|
220
195
|
}}
|
|
221
196
|
title="Connect Android service nodes"
|
|
222
197
|
/>
|
|
223
198
|
)}
|
|
224
199
|
|
|
225
|
-
{/* Output Data Indicator */}
|
|
200
|
+
{/* Output Data Indicator (bespoke; keeps inline style) */}
|
|
226
201
|
{executionStatus === 'success' && nodeStatus?.data && (
|
|
227
202
|
<div
|
|
228
203
|
style={{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import React, { memo, useState, useEffect, useCallback } from 'react';
|
|
10
10
|
import { nodePropsEqual } from './nodeMemoEquality';
|
|
11
11
|
import { Handle, Position, NodeProps } from 'reactflow';
|
|
12
|
-
import { NodeData } from '../types/NodeTypes';
|
|
12
|
+
import { NodeData, NodeStyle } from '../types/NodeTypes';
|
|
13
13
|
import { useAppStore } from '../store/useAppStore';
|
|
14
14
|
import { resolveNodeDescription, useNodeSpec } from '../lib/nodeSpec';
|
|
15
15
|
import { NodeIcon } from '../assets/icons';
|
|
@@ -19,7 +19,9 @@ import EditableNodeLabel from './ui/EditableNodeLabel';
|
|
|
19
19
|
|
|
20
20
|
const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnectable, selected }) => {
|
|
21
21
|
const theme = useAppTheme();
|
|
22
|
-
const
|
|
22
|
+
const setSelectedNode = useAppStore((s) => s.setSelectedNode);
|
|
23
|
+
const setRenamingNodeId = useAppStore((s) => s.setRenamingNodeId);
|
|
24
|
+
const updateNodeData = useAppStore((s) => s.updateNodeData);
|
|
23
25
|
const [isConfigured, setIsConfigured] = useState(false);
|
|
24
26
|
const isDisabled = data?.disabled === true;
|
|
25
27
|
|
|
@@ -65,29 +67,21 @@ const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
65
67
|
setSelectedNode({ id, type, data, position: { x: 0, y: 0 } });
|
|
66
68
|
};
|
|
67
69
|
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (executionStatus === 'success')
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
if (executionStatus === 'error') {
|
|
78
|
-
return theme.dracula.red;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// WhatsApp trigger - use connection status when idle
|
|
70
|
+
// Compute pip status bucket for `data-status` attribute. CSS owns the
|
|
71
|
+
// visual color via per-status rules in base.css and per-theme overrides.
|
|
72
|
+
// For WhatsApp triggers in idle state, fold connection state into the
|
|
73
|
+
// bucket: connected -> success, pairing -> waiting, otherwise -> error.
|
|
74
|
+
const pipStatus = (() => {
|
|
75
|
+
if (executionStatus === 'executing' || executionStatus === 'waiting') return 'executing';
|
|
76
|
+
if (executionStatus === 'success') return 'success';
|
|
77
|
+
if (executionStatus === 'error') return 'error';
|
|
82
78
|
if (isWhatsAppTrigger) {
|
|
83
|
-
if (whatsappStatus.connected) return
|
|
84
|
-
if (whatsappStatus.pairing) return
|
|
85
|
-
return
|
|
79
|
+
if (whatsappStatus.connected) return 'success';
|
|
80
|
+
if (whatsappStatus.pairing) return 'waiting';
|
|
81
|
+
return 'error';
|
|
86
82
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return isConfigured ? theme.dracula.green : theme.dracula.orange;
|
|
90
|
-
};
|
|
83
|
+
return isConfigured ? 'success' : 'idle';
|
|
84
|
+
})();
|
|
91
85
|
|
|
92
86
|
const getStatusTitle = () => {
|
|
93
87
|
switch (executionStatus) {
|
|
@@ -120,8 +114,16 @@ const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
120
114
|
const nodeColor = definition?.defaults?.color || '#f59e0b';
|
|
121
115
|
|
|
122
116
|
return (
|
|
117
|
+
// `sq-node` + `node-trigger` + `selected` co-classes activate per-theme
|
|
118
|
+
// square-node decorations (Renaissance wax seal, Steampunk rivets, Edo
|
|
119
|
+
// hanko seal, Surveillance REC LED, Cyber neon underglow). The
|
|
120
|
+
// `node-trigger` co-class lets per-type theme rules narrow further.
|
|
121
|
+
// `data-executing` binds the CSS pulse animation owned by base.css.
|
|
123
122
|
<div
|
|
123
|
+
className={`sq-node node-trigger ${selected ? 'selected' : ''}`}
|
|
124
|
+
data-executing={isExecuting ? '' : undefined}
|
|
124
125
|
style={{
|
|
126
|
+
'--node-color': nodeColor,
|
|
125
127
|
position: 'relative',
|
|
126
128
|
display: 'flex',
|
|
127
129
|
flexDirection: 'column',
|
|
@@ -129,44 +131,24 @@ const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
129
131
|
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
130
132
|
fontSize: '11px',
|
|
131
133
|
cursor: 'pointer',
|
|
132
|
-
}}
|
|
134
|
+
} as NodeStyle}
|
|
133
135
|
>
|
|
134
|
-
{/* Main Trigger Node
|
|
135
|
-
|
|
136
|
+
{/* Main Trigger Node — visual styling lives in base.css + per-theme
|
|
137
|
+
CSS targeting `.sq-node-box`. Inner box keeps only layout
|
|
138
|
+
(size, flex), and per-theme decorations like Cyber neon glow,
|
|
139
|
+
Renaissance wax seal, and Steampunk rivets reach the pixels. */}
|
|
136
140
|
<div
|
|
141
|
+
className="sq-node-box"
|
|
137
142
|
style={{
|
|
138
143
|
position: 'relative',
|
|
139
144
|
width: theme.nodeSize.square,
|
|
140
145
|
height: theme.nodeSize.square,
|
|
141
|
-
borderRadius: theme.borderRadius.lg,
|
|
142
|
-
background: theme.isDarkMode
|
|
143
|
-
? `linear-gradient(135deg, ${nodeColor}25 0%, ${theme.colors.background} 100%)`
|
|
144
|
-
: `linear-gradient(145deg, #ffffff 0%, ${nodeColor}08 100%)`,
|
|
145
|
-
border: `2px solid ${
|
|
146
|
-
isExecuting
|
|
147
|
-
? (theme.isDarkMode ? theme.dracula.purple : '#2563eb')
|
|
148
|
-
: selected
|
|
149
|
-
? theme.colors.focus
|
|
150
|
-
: theme.isDarkMode ? nodeColor + '80' : `${nodeColor}40`
|
|
151
|
-
}`,
|
|
152
146
|
display: 'flex',
|
|
153
147
|
alignItems: 'center',
|
|
154
148
|
justifyContent: 'center',
|
|
155
149
|
color: theme.colors.text,
|
|
156
150
|
fontSize: theme.nodeSize.squareIcon,
|
|
157
151
|
fontWeight: '600',
|
|
158
|
-
transition: 'all 0.2s ease',
|
|
159
|
-
boxShadow: isExecuting
|
|
160
|
-
? theme.isDarkMode
|
|
161
|
-
? `0 4px 12px ${theme.dracula.purple}66, 0 0 0 3px ${theme.dracula.purple}4D`
|
|
162
|
-
: `0 0 0 3px rgba(37, 99, 235, 0.5), 0 4px 16px rgba(37, 99, 235, 0.35)`
|
|
163
|
-
: selected
|
|
164
|
-
? `0 4px 12px ${theme.colors.focusRing}, 0 0 0 1px ${theme.colors.focusRing}`
|
|
165
|
-
: theme.isDarkMode
|
|
166
|
-
? `0 2px 8px ${nodeColor}40`
|
|
167
|
-
: `0 2px 8px ${nodeColor}20, 0 4px 12px rgba(0,0,0,0.06)`,
|
|
168
|
-
// Subtle animation for both modes
|
|
169
|
-
animation: isExecuting ? 'pulse 1.5s ease-in-out infinite' : 'none',
|
|
170
152
|
opacity: isDisabled ? 0.5 : 1,
|
|
171
153
|
}}
|
|
172
154
|
>
|
|
@@ -196,62 +178,48 @@ const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
196
178
|
{/* Parameters Button */}
|
|
197
179
|
<button
|
|
198
180
|
onClick={handleParametersClick}
|
|
181
|
+
className="sq-node-gear"
|
|
199
182
|
style={{
|
|
200
183
|
position: 'absolute',
|
|
201
184
|
top: '-8px',
|
|
202
185
|
right: '-8px',
|
|
203
186
|
width: theme.nodeSize.paramButton,
|
|
204
187
|
height: theme.nodeSize.paramButton,
|
|
205
|
-
borderRadius: theme.borderRadius.sm,
|
|
206
|
-
backgroundColor: theme.isDarkMode ? theme.colors.backgroundAlt : '#ffffff',
|
|
207
|
-
border: `1px solid ${theme.isDarkMode ? theme.colors.border : '#d1d5db'}`,
|
|
208
188
|
cursor: 'pointer',
|
|
209
189
|
display: 'flex',
|
|
210
190
|
alignItems: 'center',
|
|
211
191
|
justifyContent: 'center',
|
|
212
192
|
fontSize: theme.fontSize.xs,
|
|
213
|
-
color: theme.colors.textSecondary,
|
|
214
193
|
fontWeight: '400',
|
|
215
194
|
transition: theme.transitions.fast,
|
|
216
195
|
zIndex: 30,
|
|
217
|
-
boxShadow: theme.isDarkMode
|
|
218
|
-
? `0 1px 3px ${theme.colors.shadow}`
|
|
219
|
-
: '0 1px 4px rgba(0,0,0,0.1)'
|
|
220
196
|
}}
|
|
221
197
|
title="Configure Trigger"
|
|
222
198
|
>
|
|
223
199
|
⚙️
|
|
224
200
|
</button>
|
|
225
201
|
|
|
226
|
-
{/*
|
|
227
|
-
|
|
202
|
+
{/* Status Indicator — CSS owns the bg color via per-status rule
|
|
203
|
+
on `.sq-node-pip[data-status="…"]`. Pulse on executing/waiting
|
|
204
|
+
also lives in CSS. */}
|
|
228
205
|
<div
|
|
206
|
+
className="sq-node-pip"
|
|
207
|
+
data-status={pipStatus}
|
|
229
208
|
style={{
|
|
230
209
|
position: 'absolute',
|
|
231
210
|
top: '-4px',
|
|
232
211
|
left: '-4px',
|
|
233
212
|
width: theme.nodeSize.statusIndicator,
|
|
234
213
|
height: theme.nodeSize.statusIndicator,
|
|
235
|
-
borderRadius: '50%',
|
|
236
|
-
backgroundColor: getStatusIndicatorColor(),
|
|
237
|
-
border: `2px solid ${theme.isDarkMode ? theme.colors.background : '#ffffff'}`,
|
|
238
|
-
boxShadow: isExecuting
|
|
239
|
-
? theme.isDarkMode
|
|
240
|
-
? `0 0 6px ${theme.dracula.purple}80`
|
|
241
|
-
: '0 0 4px rgba(37, 99, 235, 0.5)'
|
|
242
|
-
: theme.isDarkMode
|
|
243
|
-
? `0 1px 2px ${theme.colors.shadow}`
|
|
244
|
-
: '0 1px 3px rgba(0,0,0,0.15)',
|
|
245
214
|
zIndex: 30,
|
|
246
|
-
// Subtle pulse animation for both modes
|
|
247
|
-
animation: isExecuting ? 'pulse 1s ease-in-out infinite' : 'none',
|
|
248
215
|
}}
|
|
249
216
|
title={getStatusTitle()}
|
|
250
217
|
/>
|
|
251
218
|
|
|
252
219
|
{/* NO INPUT HANDLE - Trigger nodes don't have inputs */}
|
|
253
220
|
|
|
254
|
-
{/* Trigger Badge - Lightning bolt indicator on bottom-left
|
|
221
|
+
{/* Trigger Badge - Lightning bolt indicator on bottom-left
|
|
222
|
+
(bespoke UI element, not in design schema; keeps inline style) */}
|
|
255
223
|
<div
|
|
256
224
|
style={{
|
|
257
225
|
position: 'absolute',
|
|
@@ -276,12 +244,13 @@ const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
276
244
|
<span style={{ lineHeight: 1, color: theme.isDarkMode ? theme.colors.background : '#1a1d21' }}>⚡</span>
|
|
277
245
|
</div>
|
|
278
246
|
|
|
279
|
-
{/* Output Handle (right side) */}
|
|
247
|
+
{/* Output Handle (right side) — CSS owns bg/border via .sq-node-handle.out */}
|
|
280
248
|
<Handle
|
|
281
249
|
id="output-main"
|
|
282
250
|
type="source"
|
|
283
251
|
position={Position.Right}
|
|
284
252
|
isConnectable={isConnectable}
|
|
253
|
+
className="sq-node-handle out"
|
|
285
254
|
style={{
|
|
286
255
|
position: 'absolute',
|
|
287
256
|
right: '-6px',
|
|
@@ -289,15 +258,12 @@ const TriggerNode: React.FC<NodeProps<NodeData>> = ({ id, type, data, isConnecta
|
|
|
289
258
|
transform: 'translateY(-50%)',
|
|
290
259
|
width: theme.nodeSize.handle,
|
|
291
260
|
height: theme.nodeSize.handle,
|
|
292
|
-
|
|
293
|
-
border: `2px solid ${theme.isDarkMode ? theme.colors.background : '#ffffff'}`,
|
|
294
|
-
borderRadius: '50%',
|
|
295
|
-
zIndex: 20
|
|
261
|
+
zIndex: 20,
|
|
296
262
|
}}
|
|
297
263
|
title="Trigger Output"
|
|
298
264
|
/>
|
|
299
265
|
|
|
300
|
-
{/* Output Data Indicator */}
|
|
266
|
+
{/* Output Data Indicator (bespoke; keeps inline style) */}
|
|
301
267
|
{executionStatus === 'success' && nodeStatus?.data && (
|
|
302
268
|
<div
|
|
303
269
|
style={{
|
|
@@ -78,51 +78,55 @@ const wsMock = {
|
|
|
78
78
|
// status getters aren't actually used here -- they're consumed via the dedicated hooks below
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
81
|
+
// Replace the entire WebSocketContext module with stub exports. The
|
|
82
|
+
// `vi.importActual` + spread pattern was previously used here but failed
|
|
83
|
+
// to override `useWebSocket` reliably under React 19 — the real
|
|
84
|
+
// implementation's `useContext(WebSocketContext)` check fired against the
|
|
85
|
+
// undefined provider, throwing the "must be used within a WebSocketProvider"
|
|
86
|
+
// error before the mocked override could intercept. The full-replace style
|
|
87
|
+
// matches what useApiKeys.test.ts does and works in both vitest 1 and 2.
|
|
88
|
+
vi.mock('../../contexts/WebSocketContext', () => ({
|
|
89
|
+
useWebSocket: () => wsMock,
|
|
90
|
+
useWhatsAppStatus: () => ({
|
|
91
|
+
connected: false,
|
|
92
|
+
has_session: false,
|
|
93
|
+
running: false,
|
|
94
|
+
pairing: false,
|
|
95
|
+
device_id: null,
|
|
96
|
+
connected_phone: null,
|
|
97
|
+
qr: null,
|
|
98
|
+
}),
|
|
99
|
+
useAndroidStatus: () => ({
|
|
100
|
+
connected: false,
|
|
101
|
+
paired: false,
|
|
102
|
+
device_id: null,
|
|
103
|
+
device_name: null,
|
|
104
|
+
connected_devices: [],
|
|
105
|
+
qr_data: null,
|
|
106
|
+
session_token: null,
|
|
107
|
+
}),
|
|
108
|
+
useTwitterStatus: () => ({
|
|
109
|
+
connected: false,
|
|
110
|
+
username: null,
|
|
111
|
+
user_id: null,
|
|
112
|
+
name: null,
|
|
113
|
+
profile_image_url: null,
|
|
114
|
+
}),
|
|
115
|
+
useGoogleStatus: () => ({
|
|
116
|
+
connected: false,
|
|
117
|
+
email: null,
|
|
118
|
+
name: null,
|
|
119
|
+
profile_image_url: null,
|
|
120
|
+
}),
|
|
121
|
+
useTelegramStatus: () => ({
|
|
122
|
+
connected: false,
|
|
123
|
+
bot_username: null,
|
|
124
|
+
bot_name: null,
|
|
125
|
+
bot_id: null,
|
|
126
|
+
owner_chat_id: null,
|
|
127
|
+
}),
|
|
128
|
+
useNodeStatus: () => ({ status: 'idle', data: {} }),
|
|
129
|
+
}));
|
|
126
130
|
|
|
127
131
|
vi.mock('../../hooks/useWhatsApp', () => ({
|
|
128
132
|
useWhatsApp: () => ({
|