synabun 2.0.0 → 2.0.7
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/CHANGELOG.md +97 -0
- package/NOTICE +5 -0
- package/README.md +2 -1
- package/THIRD-PARTY-LICENSES.md +59 -0
- package/benchmarks/fixtures/browser/README.md +1 -1
- package/benchmarks/fixtures/desktop/README.md +1 -1
- package/docs/whatsapp.md +153 -18
- package/hooks/claude-code/pre-compact.mjs +11 -0
- package/hooks/claude-code/prompt-submit.mjs +60 -184
- package/hooks/claude-code/session-start.mjs +73 -16
- package/hooks/claude-code/shared.mjs +26 -3
- package/hooks/claude-code/stop.mjs +5 -5
- package/lib/child-path.js +303 -0
- package/lib/claude-hooks.js +2 -1
- package/lib/data-home-migration.js +2 -0
- package/lib/desktop-app.js +265 -0
- package/lib/external-tools.js +7 -3
- package/lib/log-redact.js +102 -0
- package/lib/packaged-runtime.js +138 -11
- package/lib/start-launcher.js +88 -1
- package/mcp-server/dist/http.d.ts +3 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +15 -4
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +9 -6
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/budget-judgments.js +153 -0
- package/mcp-server/dist/services/budget-judgments.js.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +41 -4
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +11 -0
- package/mcp-server/dist/services/identity.d.ts.map +1 -1
- package/mcp-server/dist/services/identity.js +24 -0
- package/mcp-server/dist/services/identity.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +13 -0
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +34 -2
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
- package/mcp-server/dist/services/typesafe-config.js +4 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +10 -7
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +34 -13
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
- package/mcp-server/dist/tui.js +2 -1
- package/mcp-server/dist/tui.js.map +1 -1
- package/mcp-server/dist/version.d.ts +5 -0
- package/mcp-server/dist/version.d.ts.map +1 -0
- package/mcp-server/dist/version.js +21 -0
- package/mcp-server/dist/version.js.map +1 -0
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -3
- package/mcp-server/run.mjs +15 -9
- package/mcp-server/src/http.ts +18 -3
- package/mcp-server/src/index.ts +9 -6
- package/mcp-server/src/services/budget-judgments.ts +183 -0
- package/mcp-server/src/services/codex-config-heal.ts +35 -4
- package/mcp-server/src/services/identity.ts +27 -0
- package/mcp-server/src/services/neural-interface.ts +34 -2
- package/mcp-server/src/services/typesafe-config.ts +4 -1
- package/mcp-server/src/tools/agents.ts +33 -14
- package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
- package/mcp-server/src/tui.ts +2 -1
- package/mcp-server/src/version.ts +22 -0
- package/neural-interface/i18n/en.json +2126 -209
- package/neural-interface/i18n/pt-BR.json +2123 -207
- package/neural-interface/lib/account-usage.js +163 -0
- package/neural-interface/lib/assistant-api.js +316 -57
- package/neural-interface/lib/assistant-brains/claude.js +19 -2
- package/neural-interface/lib/assistant-brains/codex.js +3 -0
- package/neural-interface/lib/assistant-brains/opencode.js +17 -4
- package/neural-interface/lib/assistant-budget-planner.js +390 -0
- package/neural-interface/lib/assistant-budget-split.js +408 -0
- package/neural-interface/lib/assistant-budget.js +94 -95
- package/neural-interface/lib/assistant-catalog.js +179 -27
- package/neural-interface/lib/assistant-config.js +91 -14
- package/neural-interface/lib/assistant-dispatch.js +494 -138
- package/neural-interface/lib/assistant-hidden-models.js +393 -66
- package/neural-interface/lib/assistant-jev.js +26 -3
- package/neural-interface/lib/assistant-memory.js +24 -10
- package/neural-interface/lib/assistant-persona.js +73 -12
- package/neural-interface/lib/assistant-plan-permissions.js +8 -1
- package/neural-interface/lib/assistant-pricing.js +21 -6
- package/neural-interface/lib/assistant-route-accounts.js +14 -0
- package/neural-interface/lib/assistant-route-gate.js +19 -3
- package/neural-interface/lib/assistant-router.js +373 -42
- package/neural-interface/lib/assistant-runtime.js +488 -59
- package/neural-interface/lib/assistant-task-prompt.js +13 -3
- package/neural-interface/lib/assistant-test-density.js +142 -0
- package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
- package/neural-interface/lib/assistant-user-context.js +908 -0
- package/neural-interface/lib/assistant-user-knowledge.js +328 -0
- package/neural-interface/lib/assistant-user-learn.js +404 -0
- package/neural-interface/lib/assistant-user-threads.js +226 -0
- package/neural-interface/lib/assistant-user-writer.js +183 -0
- package/neural-interface/lib/augmented-path.js +317 -53
- package/neural-interface/lib/browser-background-tab.js +134 -0
- package/neural-interface/lib/browser-screenshot.js +678 -61
- package/neural-interface/lib/claude-accounts.js +342 -31
- package/neural-interface/lib/claude-agent-bridge.js +123 -9
- package/neural-interface/lib/claude-executable.js +6 -1
- package/neural-interface/lib/claude-model-catalog.js +33 -5
- package/neural-interface/lib/claude-panel-auth.js +221 -0
- package/neural-interface/lib/claude-profile-api-key.js +62 -0
- package/neural-interface/lib/claude-temporary.js +46 -7
- package/neural-interface/lib/cli-install-api.js +137 -0
- package/neural-interface/lib/cli-install.js +797 -0
- package/neural-interface/lib/cli-path.js +130 -0
- package/neural-interface/lib/cli-resolver.js +744 -0
- package/neural-interface/lib/cli-update-planner.js +143 -7
- package/neural-interface/lib/cloudflared/install.js +533 -0
- package/neural-interface/lib/cloudflared/manager.js +545 -0
- package/neural-interface/lib/cloudflared/pins.js +115 -0
- package/neural-interface/lib/cloudflared/pins.json +63 -0
- package/neural-interface/lib/cloudflared/tunnel.js +265 -0
- package/neural-interface/lib/codex-account-auth.js +178 -0
- package/neural-interface/lib/codex-accounts.js +489 -0
- package/neural-interface/lib/codex-capabilities.js +2 -1
- package/neural-interface/lib/codex-compat-rpc.js +8 -2
- package/neural-interface/lib/codex-mcp-approvals.js +5 -1
- package/neural-interface/lib/codex-panel-auth.js +62 -0
- package/neural-interface/lib/codex-session-settings.js +1 -1
- package/neural-interface/lib/codex-settings-schema.js +120 -0
- package/neural-interface/lib/desktop/config.js +3 -0
- package/neural-interface/lib/editor-completion-endpoint.js +264 -0
- package/neural-interface/lib/editor-completion-opencode.js +436 -0
- package/neural-interface/lib/editor-completion.js +714 -0
- package/neural-interface/lib/editor-config.js +149 -0
- package/neural-interface/lib/editor-files-api.js +268 -0
- package/neural-interface/lib/editor-git-api.js +134 -0
- package/neural-interface/lib/file-explorer-api.js +1039 -0
- package/neural-interface/lib/file-explorer-system.js +355 -0
- package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
- package/neural-interface/lib/file-explorer-watch.js +239 -0
- package/neural-interface/lib/git-bash/bzip2.js +339 -0
- package/neural-interface/lib/git-bash/claude-settings.js +73 -0
- package/neural-interface/lib/git-bash/extract-worker.js +34 -0
- package/neural-interface/lib/git-bash/install.js +529 -0
- package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
- package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
- package/neural-interface/lib/git-bash/manager.js +268 -0
- package/neural-interface/lib/git-bash/pins.js +206 -0
- package/neural-interface/lib/git-bash/pins.json +34 -0
- package/neural-interface/lib/git-bash/resolver.js +194 -0
- package/neural-interface/lib/git-diff-api.js +103 -0
- package/neural-interface/lib/git-read.js +234 -0
- package/neural-interface/lib/greeting/api.js +89 -0
- package/neural-interface/lib/greeting/budgets.js +90 -0
- package/neural-interface/lib/greeting/engine.js +461 -0
- package/neural-interface/lib/greeting/facts.js +320 -0
- package/neural-interface/lib/greeting/sources.js +252 -0
- package/neural-interface/lib/greeting/writer.js +139 -0
- package/neural-interface/lib/http-guards.js +189 -13
- package/neural-interface/lib/install-details.js +145 -0
- package/neural-interface/lib/machine-names.js +88 -0
- package/neural-interface/lib/mcp-installer.js +14 -2
- package/neural-interface/lib/memory-api.js +31 -7
- package/neural-interface/lib/native-loop-providers.js +26 -8
- package/neural-interface/lib/native-loop-runtime.js +9 -4
- package/neural-interface/lib/os-path.js +319 -0
- package/neural-interface/lib/plugin-installer.js +4 -2
- package/neural-interface/lib/project-storage.js +5 -7
- package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
- package/neural-interface/lib/provider-panel-terminal-auth.js +95 -0
- package/neural-interface/lib/pty-host/core.js +2 -1
- package/neural-interface/lib/pty-host/manager.js +27 -2
- package/neural-interface/lib/remote-policy.js +20 -11
- package/neural-interface/lib/request-gate.js +589 -0
- package/neural-interface/lib/session-title-generator.js +4 -3
- package/neural-interface/lib/system-about.js +340 -0
- package/neural-interface/lib/system-activity.js +66 -0
- package/neural-interface/lib/terminal-env.js +11 -3
- package/neural-interface/lib/terminal-path.js +55 -0
- package/neural-interface/lib/ui-blob-api.js +108 -0
- package/neural-interface/lib/ui-blob-store.js +68 -0
- package/neural-interface/lib/virtual-socket.js +12 -1
- package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
- package/neural-interface/lib/whatsapp/bridge.js +78 -34
- package/neural-interface/lib/whatsapp/commands.js +13 -14
- package/neural-interface/lib/whatsapp/config.js +134 -20
- package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
- package/neural-interface/lib/whatsapp/host-core.js +168 -35
- package/neural-interface/lib/whatsapp/inbound.js +5 -3
- package/neural-interface/lib/whatsapp/local-file.js +524 -0
- package/neural-interface/lib/whatsapp/manager.js +92 -32
- package/neural-interface/lib/whatsapp/paths.js +11 -1
- package/neural-interface/lib/whatsapp/protocol.js +65 -5
- package/neural-interface/lib/whatsapp/redact.js +63 -0
- package/neural-interface/lib/whatsapp/service.js +343 -91
- package/neural-interface/lib/whatsapp/transcription.js +463 -0
- package/neural-interface/package-lock.json +701 -2
- package/neural-interface/package.json +13 -2
- package/neural-interface/public/index.html +2 -0
- package/neural-interface/public/index2d.html +2 -0
- package/neural-interface/public/install-app.html +9 -6
- package/neural-interface/public/offline.html +19 -3
- package/neural-interface/public/onboarding.html +107 -2
- package/neural-interface/public/shared/account-i18n.js +7 -0
- package/neural-interface/public/shared/account-menu.js +539 -0
- package/neural-interface/public/shared/account-usage.js +19 -0
- package/neural-interface/public/shared/account-view.js +335 -0
- package/neural-interface/public/shared/agent-runtime-options.js +50 -14
- package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
- package/neural-interface/public/shared/assistant/asst-api.js +32 -2
- package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +430 -81
- package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
- package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
- package/neural-interface/public/shared/assistant/asst-mascot.js +140 -61
- package/neural-interface/public/shared/assistant/asst-menu.js +27 -11
- package/neural-interface/public/shared/assistant/asst-panel.js +198 -42
- package/neural-interface/public/shared/assistant/asst-render.js +197 -23
- package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
- package/neural-interface/public/shared/assistant/asst-route.js +95 -343
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +534 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
- package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
- package/neural-interface/public/shared/assistant/asst-state.js +186 -2
- package/neural-interface/public/shared/assistant/asst-styles.js +247 -11
- package/neural-interface/public/shared/blob-store.js +111 -22
- package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
- package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
- package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +80 -118
- package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
- package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +164 -107
- package/neural-interface/public/shared/cdx/cdx-tabs.js +348 -668
- package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
- package/neural-interface/public/shared/claude-account-view.js +3 -0
- package/neural-interface/public/shared/cli-install-view.js +392 -0
- package/neural-interface/public/shared/cli-status.js +282 -22
- package/neural-interface/public/shared/constants.js +6 -1
- package/neural-interface/public/shared/cp/cp-events.js +2 -1
- package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
- package/neural-interface/public/shared/cp/cp-styles.js +61 -0
- package/neural-interface/public/shared/desktop-bridge.js +39 -0
- package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
- package/neural-interface/public/shared/desktop-titlebar.js +153 -0
- package/neural-interface/public/shared/desktop-update-view.js +462 -0
- package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
- package/neural-interface/public/shared/editor/editor-ai.js +619 -0
- package/neural-interface/public/shared/editor/editor-commands.js +212 -0
- package/neural-interface/public/shared/editor/editor-compare.js +103 -0
- package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
- package/neural-interface/public/shared/editor/editor-doc.js +257 -0
- package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
- package/neural-interface/public/shared/editor/editor-git.js +95 -0
- package/neural-interface/public/shared/editor/editor-languages.js +156 -0
- package/neural-interface/public/shared/editor/editor-lint.js +229 -0
- package/neural-interface/public/shared/editor/editor-loader.js +51 -0
- package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
- package/neural-interface/public/shared/editor/editor-menu.js +233 -0
- package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
- package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
- package/neural-interface/public/shared/editor/editor-palette.js +125 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
- package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
- package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
- package/neural-interface/public/shared/editor/editor-safety.js +500 -0
- package/neural-interface/public/shared/editor/editor-search.js +352 -0
- package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
- package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
- package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
- package/neural-interface/public/shared/editor/editor-theme.js +244 -0
- package/neural-interface/public/shared/editor/editor-view.js +332 -0
- package/neural-interface/public/shared/explorer/fx-api.js +216 -0
- package/neural-interface/public/shared/explorer/fx-links.js +204 -0
- package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
- package/neural-interface/public/shared/explorer/fx-main.js +865 -0
- package/neural-interface/public/shared/explorer/fx-names.js +87 -0
- package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
- package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
- package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
- package/neural-interface/public/shared/file-links.js +339 -0
- package/neural-interface/public/shared/git-bash-view.js +145 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
- package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
- package/neural-interface/public/shared/html-shell.js +161 -165
- package/neural-interface/public/shared/i18n.js +19 -1
- package/neural-interface/public/shared/install-details-view.js +86 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +131 -17
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +22 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +158 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
- package/neural-interface/public/shared/pwa-install-page.js +32 -2
- package/neural-interface/public/shared/pwa-install.css +3 -3
- package/neural-interface/public/shared/pwa-install.js +100 -1
- package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
- package/neural-interface/public/shared/settings/settings-about.js +254 -0
- package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
- package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
- package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
- package/neural-interface/public/shared/settings/settings-ia.js +33 -4
- package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
- package/neural-interface/public/shared/showcase-privacy.js +489 -0
- package/neural-interface/public/shared/start-bridge.js +238 -19
- package/neural-interface/public/shared/storage.js +30 -3
- package/neural-interface/public/shared/styles.css +1710 -770
- package/neural-interface/public/shared/synabun-mascot.js +68 -58
- package/neural-interface/public/shared/tunnel-view.js +167 -0
- package/neural-interface/public/shared/ui-claude-panel.js +369 -229
- package/neural-interface/public/shared/ui-cli-banner.js +355 -0
- package/neural-interface/public/shared/ui-detail.js +15 -0
- package/neural-interface/public/shared/ui-explorer.js +22 -0
- package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
- package/neural-interface/public/shared/ui-file-links.js +103 -0
- package/neural-interface/public/shared/ui-git-bash.js +124 -0
- package/neural-interface/public/shared/ui-help.js +26 -0
- package/neural-interface/public/shared/ui-invite.js +126 -116
- package/neural-interface/public/shared/ui-judgments.js +10 -1
- package/neural-interface/public/shared/ui-keybinds.js +4 -0
- package/neural-interface/public/shared/ui-loading.js +187 -19
- package/neural-interface/public/shared/ui-menubar.js +25 -33
- package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
- package/neural-interface/public/shared/ui-navbar.js +48 -22
- package/neural-interface/public/shared/ui-provider-auth.js +104 -0
- package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
- package/neural-interface/public/shared/ui-sessions.js +9 -3
- package/neural-interface/public/shared/ui-settings.js +509 -490
- package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
- package/neural-interface/public/shared/ui-sync.js +22 -0
- package/neural-interface/public/shared/ui-terminal.js +40 -5
- package/neural-interface/public/shared/ui-tool-updates.js +5 -0
- package/neural-interface/public/shared/ui-tunnel.js +130 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
- package/neural-interface/public/shared/ui-update.js +594 -5
- package/neural-interface/public/shared/ui-whatsapp.js +21 -6
- package/neural-interface/public/shared/ui-whiteboard.js +12 -0
- package/neural-interface/public/shared/ui-worker-end.js +245 -0
- package/neural-interface/public/shared/ui-workspaces.js +41 -27
- package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
- package/neural-interface/public/shared/worker-end.js +253 -0
- package/neural-interface/public/sw.js +2 -2
- package/neural-interface/public/variant/2d/main.js +10 -1
- package/neural-interface/public/variant/3d/main.js +10 -1
- package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
- package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
- package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
- package/neural-interface/scripts/build-vendor.mjs +78 -2
- package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
- package/neural-interface/server.js +2085 -1629
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/package.json +5 -8
- package/setup.js +53 -15
- package/benchmarks/browser-live-results.json +0 -79
- package/benchmarks/browser-v2-results.json +0 -258
- package/neural-interface/lib/codex-capabilities.d.ts +0 -41
- package/neural-interface/public/category-logos/claude.svg +0 -1
- package/neural-interface/public/category-logos/gemini-color.svg +0 -1
- package/neural-interface/public/category-logos/openai.svg +0 -1
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude.svg +0 -1
- package/neural-interface/public/gallery.svg +0 -6
- package/neural-interface/public/leonardoai.svg +0 -1
- package/neural-interface/public/mcp.svg +0 -4
- package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
- package/neural-interface/public/pin-svgrepo-com.svg +0 -25
- package/neural-interface/public/sessionicon.svg +0 -8
- package/neural-interface/public/toolbar-album.svg +0 -8
- package/neural-interface/public/toolbar-question.svg +0 -6
- package/neural-interface/public/toolbar-sessions.svg +0 -6
- package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
- package/skills/synabun/synabunicon.png +0 -0
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
// the face, plus one prop drawn in the face's own pill geometry. Rigs draw
|
|
9
9
|
// from the shared ticker (shared/synabun-ticker.js): 30 fps while a pose
|
|
10
10
|
// loops, 60 fps for blends and reactions, no frames at all while still. One
|
|
11
|
-
// pointermove listener and one IntersectionObserver serve every rig,
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
11
|
+
// loop, one pointermove listener and one IntersectionObserver serve every rig,
|
|
12
|
+
// and every rig that is active and on screen plays its own pose: N rigs move
|
|
13
|
+
// at once, each on its own clock. No rig waits for another; a host that wants
|
|
14
|
+
// one moving character among several of its own (an Assistant panel's hero,
|
|
15
|
+
// stage and "Thinking" row) says so with setActive(). Under
|
|
16
|
+
// prefers-reduced-motion every pose is its still frame and changes are
|
|
17
|
+
// instant. A rig tears itself down once its SVG leaves the document.
|
|
16
18
|
//
|
|
17
19
|
// v1 callers are unchanged: createMascot(container, opts) → { el, destroy,
|
|
18
20
|
// look, blink }, idle, blinking every 3-7 s and following the cursor.
|
|
@@ -35,7 +37,8 @@
|
|
|
35
37
|
* `opts.count` 1-3 (subagent minis), `opts.mode` 'recall' | 'remember'
|
|
36
38
|
* (memory), `opts.ticks` 0-3 (plan), `opts.then` a pose to blend to once a
|
|
37
39
|
* one-shot (success, error, blocked) has played and held. The same pose with
|
|
38
|
-
* a new count or ticks keeps its loop running.
|
|
40
|
+
* a new count or ticks keeps its loop running. `opts.unlimited` selects the
|
|
41
|
+
* budget pose's relaxed infinity variant; project peeks into a folder.
|
|
39
42
|
* - `react(name)` — `MASCOT_REACTIONS`: hop (spring, at most one per 600 ms),
|
|
40
43
|
* wince, nod, pop (plan: pops the newest tick; ticks the next box too
|
|
41
44
|
* unless setPose passed `ticks`), startle, pulse, click
|
|
@@ -79,7 +82,7 @@ export const MASCOT_VIEWBOX = '0 0 280 140';
|
|
|
79
82
|
/** One pose per tool kind (shared with the activity rack's kind ids). */
|
|
80
83
|
export const MASCOT_KINDS = Object.freeze(['shell', 'read', 'edit', 'search', 'web', 'subagent', 'plan', 'memory', 'runs', 'computer', 'think', 'mcp']);
|
|
81
84
|
export const MASCOT_STATES = Object.freeze(['idle', 'sleep', 'watch', 'wait', 'success', 'error', 'blocked', 'offline']);
|
|
82
|
-
export const MASCOT_POSES = Object.freeze([...MASCOT_KINDS, ...MASCOT_STATES]);
|
|
85
|
+
export const MASCOT_POSES = Object.freeze([...MASCOT_KINDS, ...MASCOT_STATES, 'project', 'budget']);
|
|
83
86
|
export const MASCOT_REACTIONS = Object.freeze(['hop', 'wince', 'nod', 'pop', 'startle', 'pulse', 'click']);
|
|
84
87
|
|
|
85
88
|
/** The character's SVG. Colour comes from `currentColor` (the mouth at 25 %). */
|
|
@@ -143,6 +146,8 @@ export function mascotCameoSvg({ className = '' } = {}) {
|
|
|
143
146
|
|
|
144
147
|
/** Each prop's own box in face units, to draw it alone (a ledger row's glyph, a suggestion's). */
|
|
145
148
|
const PROP_BOX = Object.freeze({
|
|
149
|
+
project: [204, 77, 62, 48],
|
|
150
|
+
budget: [212, 65, 54, 60],
|
|
146
151
|
shell: [144, 116, 42, 26], // the last keycap and the caret
|
|
147
152
|
read: [65, 20, 150, 88],
|
|
148
153
|
edit: [188, 93, 56, 44],
|
|
@@ -307,12 +312,37 @@ const MINIS = [
|
|
|
307
312
|
];
|
|
308
313
|
|
|
309
314
|
/**
|
|
310
|
-
* motion: 'loop' (30 fps
|
|
315
|
+
* motion: 'loop' (30 fps), 'blink' (still between slow blinks),
|
|
311
316
|
* 'once' (plays `settle` ms, then still; `hold` before opts.then), 'still'.
|
|
312
317
|
* blinks: random blinks every 3-7 s. tracks: follows the cursor.
|
|
313
318
|
* look: follows look(), easing with this time constant (ms).
|
|
314
319
|
*/
|
|
315
320
|
const POSES = {
|
|
321
|
+
// Empty-state controls: host-directed gaze, the same ticker and prop painter as tool kinds.
|
|
322
|
+
project: {
|
|
323
|
+
motion: 'loop', blinks: true, look: 70,
|
|
324
|
+
frame(t, o) {
|
|
325
|
+
const f = blankFrame();
|
|
326
|
+
const peek = o.still ? 0.5 : (1 + Math.sin(TAU * t / 2400)) / 2;
|
|
327
|
+
f.eyes = [eye(0, 2 + 2 * peek, 1, 0.92, -2), eye(0, 2 + 2 * peek, 1, 0.96, 2)];
|
|
328
|
+
f.mouth = mouth(34, 11);
|
|
329
|
+
gaze(f, o.look, { x: 16, y: 10 });
|
|
330
|
+
f.prop = { name: 'project', peek };
|
|
331
|
+
return f;
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
budget: {
|
|
335
|
+
motion: 'loop', blinks: true, look: 70,
|
|
336
|
+
frame(t, o) {
|
|
337
|
+
const f = blankFrame();
|
|
338
|
+
const lift = o.still ? 0 : Math.sin(TAU * t / 2200);
|
|
339
|
+
f.eyes = [eye(0, 0, 1, o.unlimited ? 0.65 : 0.93, -3), eye(0, 0, 1, o.unlimited ? 0.65 : 1, 3)];
|
|
340
|
+
f.mouth = mouth(o.unlimited ? 48 : 34, o.unlimited ? 20 : 11);
|
|
341
|
+
gaze(f, o.look, { x: 16, y: 10 });
|
|
342
|
+
f.prop = { name: 'budget', lift, unlimited: o.unlimited };
|
|
343
|
+
return f;
|
|
344
|
+
},
|
|
345
|
+
},
|
|
316
346
|
// ── States ──
|
|
317
347
|
idle: {
|
|
318
348
|
motion: 'still', blinks: true, tracks: true,
|
|
@@ -596,6 +626,7 @@ function poseOptions(opts) {
|
|
|
596
626
|
count: intIn(o.count, 1, 3, 1),
|
|
597
627
|
mode: o.mode === 'remember' ? 'remember' : 'recall',
|
|
598
628
|
ticks: intIn(o.ticks, 0, 3, 1),
|
|
629
|
+
unlimited: !!o.unlimited,
|
|
599
630
|
still: !!o.still,
|
|
600
631
|
};
|
|
601
632
|
}
|
|
@@ -739,6 +770,23 @@ export function reactionFrame(frame, name, p) {
|
|
|
739
770
|
// ── Props: small, currentColor, in the face's pill geometry ──
|
|
740
771
|
|
|
741
772
|
const PROPS = {
|
|
773
|
+
project: {
|
|
774
|
+
markup: () => '<g fill="none" stroke="currentColor" stroke-opacity=".7" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M208 117V84q0-4 4-4h15l7 8h25v29z"/><path class="syna-folder-front" d="M208 117l5-23h49l-5 23z"/><path class="syna-folder-paper" d="M223 93V85h22v8M229 89h10"/></g>',
|
|
775
|
+
refs: g => ({ front: g.querySelector('.syna-folder-front'), paper: g.querySelector('.syna-folder-paper') }),
|
|
776
|
+
update(r, p, put) {
|
|
777
|
+
put(r.front, 'transform', `translate(0,${n(2 * p.peek)})`);
|
|
778
|
+
put(r.paper, 'transform', `translate(0,${n(-4 * p.peek)})`);
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
budget: {
|
|
782
|
+
markup: () => '<g fill="none" stroke="currentColor" stroke-opacity=".7" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><rect x="216" y="96" width="46" height="25" rx="4"/><path d="M250 103h12v10h-12z"/><g class="syna-budget-coin"><circle cx="236" cy="80" r="12"/><path d="M236 73v14M232 76h6q4 0 0 4h-4q-4 4 0 4h6"/></g><path class="syna-budget-infinity" d="M235 80c-16-19-25 15-8 7l17-14c17-8 8 26-9 7"/></g>',
|
|
783
|
+
refs: g => ({ coin: g.querySelector('.syna-budget-coin'), infinity: g.querySelector('.syna-budget-infinity') }),
|
|
784
|
+
update(r, p, put) {
|
|
785
|
+
put(r.coin, 'display', p.unlimited ? 'none' : null);
|
|
786
|
+
put(r.infinity, 'display', p.unlimited ? null : 'none');
|
|
787
|
+
put(p.unlimited ? r.infinity : r.coin, 'transform', `translate(0,${n(-3 * p.lift)})`);
|
|
788
|
+
},
|
|
789
|
+
},
|
|
742
790
|
shell: { // three keycaps and a block caret under the chin
|
|
743
791
|
markup: () => [0, 1, 2].map(i => `<rect class="syna-key" x="${100 + i * 24}" y="127" width="20" height="9" rx="4.5" fill="currentColor" fill-opacity=".4"/>`).join('')
|
|
744
792
|
+ '<rect class="syna-caret" x="174" y="125" width="7" height="12" rx="2" fill="currentColor" fill-opacity=".75"/>',
|
|
@@ -994,26 +1042,15 @@ export function paintMascot(svg, frame) {
|
|
|
994
1042
|
painter.paint(frame);
|
|
995
1043
|
}
|
|
996
1044
|
|
|
997
|
-
// ── Shared runtime: one observer
|
|
1045
|
+
// ── Shared runtime: one observer and one motion listener for every rig ──
|
|
1046
|
+
// Nothing here picks a rig: each one decides from its own state (active, on
|
|
1047
|
+
// screen, motion allowed) whether it moves.
|
|
998
1048
|
|
|
999
1049
|
const rigs = new Set();
|
|
1000
|
-
let leadRig = null;
|
|
1001
|
-
let promoteSeq = 0;
|
|
1002
1050
|
let stopMotionWatch = null;
|
|
1003
1051
|
let io = null;
|
|
1004
1052
|
const ioRigs = new WeakMap();
|
|
1005
1053
|
|
|
1006
|
-
/** Only one rig plays a pose loop: the most recently posed one that wants to. */
|
|
1007
|
-
function elect() {
|
|
1008
|
-
let best = null;
|
|
1009
|
-
for (const rig of rigs) if (rig.wantsLead() && (!best || rig.promotedAt() > best.promotedAt())) best = rig;
|
|
1010
|
-
if (best === leadRig) return;
|
|
1011
|
-
const prev = leadRig;
|
|
1012
|
-
leadRig = best;
|
|
1013
|
-
prev?.leadChanged();
|
|
1014
|
-
best?.leadChanged();
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
1054
|
function observe(el, rig) {
|
|
1018
1055
|
if (typeof IntersectionObserver !== 'function') return;
|
|
1019
1056
|
try {
|
|
@@ -1034,13 +1071,11 @@ function register(rig) {
|
|
|
1034
1071
|
rigs.add(rig);
|
|
1035
1072
|
stopMotionWatch ||= onReducedMotionChange(() => {
|
|
1036
1073
|
for (const r of Array.from(rigs)) r.motionChanged();
|
|
1037
|
-
elect();
|
|
1038
1074
|
});
|
|
1039
1075
|
}
|
|
1040
1076
|
|
|
1041
1077
|
function unregister(rig) {
|
|
1042
1078
|
rigs.delete(rig);
|
|
1043
|
-
if (leadRig === rig) { leadRig = null; elect(); }
|
|
1044
1079
|
if (!rigs.size && stopMotionWatch) { stopMotionWatch(); stopMotionWatch = null; }
|
|
1045
1080
|
}
|
|
1046
1081
|
|
|
@@ -1088,14 +1123,12 @@ export function createMascot(container, options) {
|
|
|
1088
1123
|
let active = startActive !== false;
|
|
1089
1124
|
let visible = true;
|
|
1090
1125
|
let seenConnected = svg.isConnected;
|
|
1091
|
-
let promotedAt = (promoteSeq += 1);
|
|
1092
1126
|
let clock = 0; // rig time in ms: the ticker's dt while drawing, real time while still
|
|
1093
1127
|
let frozenAt = tickerNow(); // while not drawing: when the clock was last brought up to date; -1 while drawing
|
|
1094
1128
|
let pose = { name: 'idle', raw: {}, start: 0, then: null };
|
|
1095
1129
|
let settled = false; // a one-shot's opts.then has fired
|
|
1096
1130
|
let blend = null; // { from, start, dur }
|
|
1097
1131
|
let lastFrame = null; // the last frame before blinks and reactions
|
|
1098
|
-
let drawn = false; // has drawn a live frame (a never-drawn rig has nothing to blend from)
|
|
1099
1132
|
let look = { x: 0, y: 0 }; // eased gaze
|
|
1100
1133
|
let track = { x: 0, y: 0 }; // idle: where the cursor (or look()) points
|
|
1101
1134
|
let hostLook = { x: 0, y: 0 };
|
|
@@ -1119,10 +1152,10 @@ export function createMascot(container, options) {
|
|
|
1119
1152
|
|
|
1120
1153
|
const def = () => POSES[pose.name];
|
|
1121
1154
|
const animating = () => !destroyed && active && visible && !isReducedMotion();
|
|
1122
|
-
const isLead = () => leadRig === rig;
|
|
1123
1155
|
const poseTime = () => clock - pose.start;
|
|
1124
1156
|
|
|
1125
|
-
|
|
1157
|
+
/** This pose moves on its own right now: a loop, a patient pose, a one-shot still playing. */
|
|
1158
|
+
function playing() {
|
|
1126
1159
|
if (!animating()) return false;
|
|
1127
1160
|
const { motion, settle } = def();
|
|
1128
1161
|
if (motion === 'loop' || motion === 'blink') return true;
|
|
@@ -1186,7 +1219,6 @@ export function createMascot(container, options) {
|
|
|
1186
1219
|
function nextRate() {
|
|
1187
1220
|
if (!animating()) return 0;
|
|
1188
1221
|
if (blend || blinkStart >= 0 || reactions.length || aim || easing() || miniPopping()) return 60;
|
|
1189
|
-
if (!isLead()) return 0;
|
|
1190
1222
|
const d = def();
|
|
1191
1223
|
const t = poseTime();
|
|
1192
1224
|
if (d.motion === 'loop') return 30;
|
|
@@ -1208,9 +1240,9 @@ export function createMascot(container, options) {
|
|
|
1208
1240
|
const d = def();
|
|
1209
1241
|
const at0 = tickerNow();
|
|
1210
1242
|
let at = Infinity;
|
|
1211
|
-
if (d.blinks
|
|
1243
|
+
if (d.blinks) at = Math.min(at, nextBlinkAt);
|
|
1212
1244
|
if (d.tracks) at = Math.min(at, nextGlanceAt, nextFidgetAt, glance ? glance.until : Infinity);
|
|
1213
|
-
if (d.motion === 'blink'
|
|
1245
|
+
if (d.motion === 'blink') at = Math.min(at, at0 + d.idleFor(poseTime()));
|
|
1214
1246
|
if (d.motion === 'once' && pose.then && !settled) at = Math.min(at, at0 + Math.max(0, d.settle + (d.hold || 0) - poseTime()));
|
|
1215
1247
|
if (!Number.isFinite(at)) return;
|
|
1216
1248
|
wakeTimer = setTimeout(() => {
|
|
@@ -1243,15 +1275,15 @@ export function createMascot(container, options) {
|
|
|
1243
1275
|
function handleDue() {
|
|
1244
1276
|
const d = def();
|
|
1245
1277
|
const t = tickerNow();
|
|
1246
|
-
if (d.blinks &&
|
|
1278
|
+
if (d.blinks && t >= nextBlinkAt) {
|
|
1247
1279
|
nextBlinkAt = t + rand(3000, 7000);
|
|
1248
1280
|
startBlink();
|
|
1249
1281
|
}
|
|
1250
1282
|
if (d.tracks) {
|
|
1251
1283
|
if (glance && t >= glance.until) glance = null;
|
|
1252
1284
|
if (t >= nextGlanceAt) {
|
|
1253
|
-
// Only while the cursor is still
|
|
1254
|
-
if (t - pointerAt < 2500
|
|
1285
|
+
// Only while the cursor is still.
|
|
1286
|
+
if (t - pointerAt < 2500) nextGlanceAt = t + 3000;
|
|
1255
1287
|
else {
|
|
1256
1288
|
const [x, y] = GLANCES[Math.floor(Math.random() * GLANCES.length)];
|
|
1257
1289
|
glance = { x, y, until: t + rand(700, 1000) };
|
|
@@ -1261,7 +1293,6 @@ export function createMascot(container, options) {
|
|
|
1261
1293
|
if (t >= nextFidgetAt) {
|
|
1262
1294
|
const quietFor = t - Math.max(lastInputAt(), pointerAt);
|
|
1263
1295
|
if (quietFor < 20000) nextFidgetAt = t + (20000 - quietFor) + rand(0, 5000);
|
|
1264
|
-
else if (leadRig) nextFidgetAt = t + 10000;
|
|
1265
1296
|
else {
|
|
1266
1297
|
nextFidgetAt = t + rand(45000, 75000);
|
|
1267
1298
|
startReaction(Math.random() < 0.5 ? 'hop' : 'wiggle');
|
|
@@ -1303,8 +1334,7 @@ export function createMascot(container, options) {
|
|
|
1303
1334
|
|
|
1304
1335
|
/** The pose frame this rig would draw now, before blends and overlays. */
|
|
1305
1336
|
function frameNow() {
|
|
1306
|
-
|
|
1307
|
-
return poseFrame(pose.name, poseTime(), { ...pose.raw, look, range, ticks, still: !loopOn });
|
|
1337
|
+
return poseFrame(pose.name, poseTime(), { ...pose.raw, look, range, ticks, still: !playing() });
|
|
1308
1338
|
}
|
|
1309
1339
|
|
|
1310
1340
|
/** Ease from what is on screen to what comes next, unless they already match. */
|
|
@@ -1400,10 +1430,7 @@ export function createMascot(container, options) {
|
|
|
1400
1430
|
handleDue();
|
|
1401
1431
|
if (aim) { aimAt(aim); aim = null; }
|
|
1402
1432
|
easeLook(dt);
|
|
1403
|
-
const wasLead = isLead();
|
|
1404
1433
|
painter.paint(compose());
|
|
1405
|
-
drawn = true;
|
|
1406
|
-
if (wasLead && def().motion === 'once' && poseTime() >= def().settle) elect();
|
|
1407
1434
|
const rate = nextRate();
|
|
1408
1435
|
setRate(rate);
|
|
1409
1436
|
if (!rate) armWake();
|
|
@@ -1497,9 +1524,7 @@ export function createMascot(container, options) {
|
|
|
1497
1524
|
}
|
|
1498
1525
|
scheduleIdle();
|
|
1499
1526
|
}
|
|
1500
|
-
promotedAt = (promoteSeq += 1);
|
|
1501
1527
|
if (animating()) requestFrames(BLEND_MS);
|
|
1502
|
-
elect();
|
|
1503
1528
|
refresh();
|
|
1504
1529
|
return api;
|
|
1505
1530
|
}
|
|
@@ -1537,8 +1562,7 @@ export function createMascot(container, options) {
|
|
|
1537
1562
|
const next = !!on;
|
|
1538
1563
|
if (destroyed || next === active) return api;
|
|
1539
1564
|
active = next;
|
|
1540
|
-
if (active)
|
|
1541
|
-
elect();
|
|
1565
|
+
if (active) revive();
|
|
1542
1566
|
refresh();
|
|
1543
1567
|
return api;
|
|
1544
1568
|
}
|
|
@@ -1560,18 +1584,6 @@ export function createMascot(container, options) {
|
|
|
1560
1584
|
}
|
|
1561
1585
|
|
|
1562
1586
|
const rig = {
|
|
1563
|
-
promotedAt: () => promotedAt,
|
|
1564
|
-
wantsLead,
|
|
1565
|
-
leadChanged() {
|
|
1566
|
-
if (destroyed) return;
|
|
1567
|
-
// Gaining or losing the loop swaps the still frame for the live one: blend
|
|
1568
|
-
// when they differ (a patient pose between blinks, a settled one-shot: no).
|
|
1569
|
-
if (drawn && animating()) {
|
|
1570
|
-
syncClock();
|
|
1571
|
-
blendIn();
|
|
1572
|
-
}
|
|
1573
|
-
refresh();
|
|
1574
|
-
},
|
|
1575
1587
|
visibilityChanged(inView) {
|
|
1576
1588
|
if (destroyed) return;
|
|
1577
1589
|
if (svg.isConnected) seenConnected = true;
|
|
@@ -1579,7 +1591,6 @@ export function createMascot(container, options) {
|
|
|
1579
1591
|
const was = visible;
|
|
1580
1592
|
visible = inView;
|
|
1581
1593
|
if (visible && !was) revive();
|
|
1582
|
-
elect();
|
|
1583
1594
|
refresh(); // also wakes a rig that was built before it was attached
|
|
1584
1595
|
},
|
|
1585
1596
|
motionChanged() {
|
|
@@ -1619,7 +1630,6 @@ export function createMascot(container, options) {
|
|
|
1619
1630
|
if (p) aim = p;
|
|
1620
1631
|
}
|
|
1621
1632
|
}
|
|
1622
|
-
elect();
|
|
1623
1633
|
refresh();
|
|
1624
1634
|
return api;
|
|
1625
1635
|
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — the public address: what the cards say
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// What the two places that start the Cloudflare tunnel show for an answer of
|
|
6
|
+
// GET /api/tunnel/status: the Share menu's Connection block (ui-invite.js) and
|
|
7
|
+
// Settings → Automations → Online access (ui-settings.js). One reading for
|
|
8
|
+
// both, so they never disagree: the state as a word, one sentence about it,
|
|
9
|
+
// the progress of a download, the action that fits, and whether to ask again.
|
|
10
|
+
//
|
|
11
|
+
// No imports and no DOM: `node --test` loads this file as it is
|
|
12
|
+
// (tests/tunnel-view.test.mjs). TUNNEL_COPY is the English of every sentence;
|
|
13
|
+
// `tunnel.*` in i18n/en.json must equal it and i18n/pt-BR.json must have the
|
|
14
|
+
// same keys (the test checks both). The page side is ui-tunnel.js.
|
|
15
|
+
//
|
|
16
|
+
// A server that was started before SynaBun brought its own tunnel program
|
|
17
|
+
// answers without the `cloudflared` part: the cards then work as they did (a
|
|
18
|
+
// tunnel starts when a cloudflared is installed), and where none is, they say
|
|
19
|
+
// that a restart is what is missing. Nothing here ever tells the user to
|
|
20
|
+
// install anything, except on a system Cloudflare publishes no file for.
|
|
21
|
+
|
|
22
|
+
export const TUNNEL_COPY = Object.freeze({
|
|
23
|
+
stateOff: 'Off',
|
|
24
|
+
stateDownloading: 'Getting the tunnel program',
|
|
25
|
+
stateStarting: 'Starting',
|
|
26
|
+
stateRunning: 'On',
|
|
27
|
+
stateFailed: 'Did not start',
|
|
28
|
+
stateUnsupported: 'Not available',
|
|
29
|
+
stateRestart: 'Restart needed',
|
|
30
|
+
idle: 'A public address through Cloudflare, for invite links and remote MCP.',
|
|
31
|
+
idleDownload: 'A public address through Cloudflare, for invite links and remote MCP. The first start downloads the tunnel program ({size} MB).',
|
|
32
|
+
downloading: 'Downloading the tunnel program: {received} of {total} MB',
|
|
33
|
+
starting: 'Waiting for Cloudflare to give an address…',
|
|
34
|
+
restart: 'Restart SynaBun to use the public address: the server that is running was started before it could download the tunnel program.',
|
|
35
|
+
unsupported: 'Cloudflare publishes no tunnel program for this system. If you install cloudflared yourself, SynaBun uses it.',
|
|
36
|
+
errorOffline: 'The tunnel program could not be downloaded: the download server was not reached. Check the connection and try again.',
|
|
37
|
+
errorHttp: 'The tunnel program could not be downloaded: the download server answered with an error. Try again in a moment.',
|
|
38
|
+
errorInterrupted: 'The download stopped before it was complete. Nothing was kept. Try again.',
|
|
39
|
+
errorTimeout: 'The download stalled. Nothing was kept. Try again.',
|
|
40
|
+
errorChecksum: 'The download was not the file SynaBun expects, so it was removed and never run. Try again; if it happens again, something on the network is changing the file.',
|
|
41
|
+
errorUnpack: 'The downloaded file could not be unpacked, so it was removed. Try again.',
|
|
42
|
+
errorDisk: 'The tunnel program could not be saved in SynaBun\'s data folder. Check free space and permissions, then try again.',
|
|
43
|
+
errorLaunch: 'The tunnel program could not be started on this computer. Try again.',
|
|
44
|
+
errorExited: 'Cloudflare gave no address. The tunnel program said: {reason}',
|
|
45
|
+
errorExitedNoReason: 'The tunnel program stopped before Cloudflare gave an address. Try again.',
|
|
46
|
+
errorNoAddress: 'Cloudflare gave no address in time. Try again.',
|
|
47
|
+
errorEnded: 'The tunnel stopped. Start it again for a new address.',
|
|
48
|
+
errorRefused: 'SynaBun refused this request. Start the tunnel from SynaBun on this computer.',
|
|
49
|
+
errorUnknown: 'The tunnel did not start: {reason}',
|
|
50
|
+
errorUnknownNoReason: 'The tunnel did not start. Try again.',
|
|
51
|
+
start: 'Start tunnel',
|
|
52
|
+
stop: 'Stop',
|
|
53
|
+
cancel: 'Cancel',
|
|
54
|
+
retry: 'Try again',
|
|
55
|
+
copyBundled: 'cloudflared {version}, included with SynaBun',
|
|
56
|
+
copyDownloaded: 'cloudflared {version}, downloaded by SynaBun',
|
|
57
|
+
copySystem: 'cloudflared {version}, installed on this computer',
|
|
58
|
+
copySystemWhy: 'SynaBun could not download its own copy, so the one installed on this computer is used.',
|
|
59
|
+
mcpKeyNeeded: 'Remote MCP needs an access key. Create one below; the address to connect is then this one followed by /mcp/ and the key.',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const ERROR_COPY = Object.freeze({
|
|
63
|
+
offline: 'errorOffline', http: 'errorHttp', interrupted: 'errorInterrupted', timeout: 'errorTimeout', checksum: 'errorChecksum',
|
|
64
|
+
unpack: 'errorUnpack', disk: 'errorDisk', launch: 'errorLaunch', no_address: 'errorNoAddress', ended: 'errorEnded',
|
|
65
|
+
unsupported: 'unsupported', refused: 'errorRefused',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/** A TUNNEL_COPY sentence with its `{params}` filled in: the translator when the page gives none. */
|
|
69
|
+
export function fillTunnelCopy(key, params = {}) {
|
|
70
|
+
return String(TUNNEL_COPY[key] ?? key).replace(/\{(\w+)\}/g, (whole, name) => (params[name] != null ? params[name] : whole));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const megabytes = (bytes) => Math.max(0, Number(bytes) || 0) / (1024 * 1024);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* What a card shows for a status.
|
|
77
|
+
*
|
|
78
|
+
* @param {object | null} status the answer of GET /api/tunnel/status (or of the start / stop that came last)
|
|
79
|
+
* @param {object} [o]
|
|
80
|
+
* @param {(key: string, params?: object) => string} [o.t] a key of TUNNEL_COPY → the sentence in the page's language
|
|
81
|
+
* @param {(value: number, digits: number) => string} [o.number] a number as the page's language writes it
|
|
82
|
+
* @returns {{
|
|
83
|
+
* kind: 'restart' | 'unsupported' | 'idle' | 'downloading' | 'starting' | 'running' | 'failed',
|
|
84
|
+
* tone: 'off' | 'busy' | 'ok' | 'warn' | 'err',
|
|
85
|
+
* on: boolean,
|
|
86
|
+
* label: string, detail: string,
|
|
87
|
+
* progress: { percent: number, text: string } | null,
|
|
88
|
+
* url: string | null,
|
|
89
|
+
* action: 'start' | 'stop' | 'cancel' | 'retry' | null, actionLabel: string,
|
|
90
|
+
* copy: string, copyNote: string,
|
|
91
|
+
* poll: boolean,
|
|
92
|
+
* }}
|
|
93
|
+
* `on`: the switch stands on (something runs or is on its way). `action`: what a press does ("cancel" and
|
|
94
|
+
* "stop" are both POST /api/tunnel/stop; "start" and "retry" both POST /api/tunnel/start). `copy`: which
|
|
95
|
+
* cloudflared runs, when one does. `poll`: the state will change by itself, ask again.
|
|
96
|
+
*/
|
|
97
|
+
export function tunnelView(status, { t = fillTunnelCopy, number = (value, digits) => value.toFixed(digits) } = {}) {
|
|
98
|
+
const s = status && typeof status === 'object' ? status : {};
|
|
99
|
+
const tool = s.cloudflared && typeof s.cloudflared === 'object' ? s.cloudflared : null;
|
|
100
|
+
const view = {
|
|
101
|
+
kind: 'idle', tone: 'off', on: false, label: t('stateOff'), detail: t('idle'), progress: null,
|
|
102
|
+
url: typeof s.url === 'string' && s.url ? s.url : null,
|
|
103
|
+
action: 'start', actionLabel: t('start'), copy: '', copyNote: '', poll: false,
|
|
104
|
+
};
|
|
105
|
+
const as = (kind, tone, labelKey, detail, action) => Object.assign(view, {
|
|
106
|
+
kind, tone, label: t(labelKey), detail, action, actionLabel: action ? t(action) : '',
|
|
107
|
+
on: kind === 'downloading' || kind === 'starting' || kind === 'running', poll: kind === 'downloading' || kind === 'starting',
|
|
108
|
+
});
|
|
109
|
+
const running = () => {
|
|
110
|
+
as('running', 'ok', 'stateRunning', view.url, 'stop');
|
|
111
|
+
const source = { bundled: 'copyBundled', downloaded: 'copyDownloaded', system: 'copySystem' }[tool?.source];
|
|
112
|
+
if (source && tool.version) {
|
|
113
|
+
view.copy = t(source, { version: tool.version });
|
|
114
|
+
if (tool.source === 'system' && tool.fallback && tool.fallback.code !== 'unsupported') view.copyNote = t('copySystemWhy');
|
|
115
|
+
}
|
|
116
|
+
return view;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Nothing is known yet (the answer has not arrived): the card as it stands before a first start.
|
|
120
|
+
if (!status || typeof status !== 'object') return view;
|
|
121
|
+
|
|
122
|
+
// A server from before the tunnel program came with SynaBun: no `cloudflared` part in its answer.
|
|
123
|
+
if (!tool) {
|
|
124
|
+
if (view.url) return running();
|
|
125
|
+
if (s.starting || s.running) return as('starting', 'busy', 'stateStarting', t('starting'), 'cancel');
|
|
126
|
+
if (s.available) return as('idle', 'off', 'stateOff', t('idle'), 'start');
|
|
127
|
+
return as('restart', 'warn', 'stateRestart', t('restart'), null);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const state = typeof s.state === 'string' ? s.state : 'idle';
|
|
131
|
+
if (state === 'running' && view.url) return running();
|
|
132
|
+
if (state === 'downloading') {
|
|
133
|
+
const total = Number(tool.progress?.total) || Number(tool.download?.size) || 0;
|
|
134
|
+
const received = Math.min(Number(tool.progress?.received) || 0, total || Infinity);
|
|
135
|
+
const percent = total ? Math.max(0, Math.min(100, Math.floor((received / total) * 100))) : 0;
|
|
136
|
+
as('downloading', 'busy', 'stateDownloading', t('downloading', { received: number(megabytes(received), 1), total: number(megabytes(total), 1) }), 'cancel');
|
|
137
|
+
view.progress = { percent, text: `${percent}%` };
|
|
138
|
+
return view;
|
|
139
|
+
}
|
|
140
|
+
if (state === 'starting' || state === 'running') return as('starting', 'busy', 'stateStarting', t('starting'), 'cancel');
|
|
141
|
+
if (state === 'failed') {
|
|
142
|
+
const error = s.error && typeof s.error === 'object' ? s.error : {};
|
|
143
|
+
if (error.code === 'unsupported') return as('unsupported', 'off', 'stateUnsupported', t('unsupported'), null);
|
|
144
|
+
const reason = typeof error.reason === 'string' && error.reason.trim() ? error.reason.trim() : '';
|
|
145
|
+
let detail;
|
|
146
|
+
if (error.code === 'exited') detail = reason ? t('errorExited', { reason }) : t('errorExitedNoReason');
|
|
147
|
+
else if (ERROR_COPY[error.code]) detail = t(ERROR_COPY[error.code]);
|
|
148
|
+
else detail = typeof error.message === 'string' && error.message.trim() ? t('errorUnknown', { reason: error.message.trim() }) : t('errorUnknownNoReason');
|
|
149
|
+
return as('failed', 'err', 'stateFailed', detail, 'retry');
|
|
150
|
+
}
|
|
151
|
+
// idle
|
|
152
|
+
if (tool.state === 'unsupported') return as('unsupported', 'off', 'stateUnsupported', t('unsupported'), null);
|
|
153
|
+
if (tool.state === 'ready') return as('idle', 'off', 'stateOff', t('idle'), 'start');
|
|
154
|
+
const size = Number(tool.download?.size) || 0;
|
|
155
|
+
return as('idle', 'off', 'stateOff', size ? t('idleDownload', { size: number(megabytes(size), 0) }) : t('idle'), 'start');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The address an assistant outside connects to, or null while there is none to give: the public address
|
|
160
|
+
* followed by /mcp/ and the access key. Without a key there is no such address: the server refuses /mcp from
|
|
161
|
+
* outside (lib/request-gate.js mcpWithoutKey), so the cards offer nothing to copy and say what is missing.
|
|
162
|
+
*/
|
|
163
|
+
export function remoteMcpAddress(url, key) {
|
|
164
|
+
const base = typeof url === 'string' ? url.trim().replace(/\/+$/, '') : '';
|
|
165
|
+
const secret = typeof key === 'string' ? key.trim() : '';
|
|
166
|
+
return base && secret ? `${base}/mcp/${secret}` : null;
|
|
167
|
+
}
|