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
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
// ═══════════════════════════════════════════
|
|
2
2
|
// SynaBun Neural Interface — Loading Overlay
|
|
3
|
-
// Health check, server start, server-offline retry, command copy
|
|
3
|
+
// Health check, server start, server-offline retry, command copy,
|
|
4
|
+
// and the restart the user asked for (the same screen, one more reason)
|
|
4
5
|
// ═══════════════════════════════════════════
|
|
5
6
|
|
|
6
7
|
import { fetchHealth, startHealth } from './api.js';
|
|
7
|
-
import { emit } from './state.js';
|
|
8
|
+
import { emit, on } from './state.js';
|
|
8
9
|
import { t } from './i18n.js';
|
|
9
10
|
import {
|
|
10
|
-
START_STORAGE, createStartBridge, fetchStartBeacon, isMacPlatform, isWindowsPlatform,
|
|
11
|
+
START_LIMITS, START_STORAGE, createStartBridge, fetchStartBeacon, isMacPlatform, isWindowsPlatform,
|
|
11
12
|
manualStartCommands, openStartLink, startBeaconTarget, startButtonUsable, startStatusView,
|
|
12
13
|
} from './start-bridge.js';
|
|
13
14
|
// Imported with the app, not when it is needed: once the server is down
|
|
14
15
|
// nothing more can be fetched, and that is exactly when the overlay wants it.
|
|
15
16
|
import { createMascot } from './synabun-mascot.js';
|
|
17
|
+
import { isDesktopApp } from './desktop-bridge.js';
|
|
16
18
|
|
|
17
19
|
const $ = (id) => document.getElementById(id);
|
|
18
20
|
|
|
@@ -25,6 +27,12 @@ let _offlineBridge = null;
|
|
|
25
27
|
let _offlineTitle = '';
|
|
26
28
|
// The mascot rig in the overlay, mounted the first time the server is offline.
|
|
27
29
|
let _mascot = null;
|
|
30
|
+
// The overlay was put over the running app for a restart. Everything the page
|
|
31
|
+
// held (sockets, terminals, panel sessions) was the old server's, so once the
|
|
32
|
+
// server is back the page loads again instead of carrying on.
|
|
33
|
+
let _restartShown = false;
|
|
34
|
+
// The tab's title from before the restart, for when it is refused.
|
|
35
|
+
let _restartTitle = null;
|
|
28
36
|
|
|
29
37
|
// What the mascot does for each thing the page knows about a start
|
|
30
38
|
// (startStatusView's `mascot`), as poses of the shared rig.
|
|
@@ -41,6 +49,22 @@ function stored(key) {
|
|
|
41
49
|
try { return localStorage.getItem(key); } catch { return null; }
|
|
42
50
|
}
|
|
43
51
|
|
|
52
|
+
// Inside the desktop app the app starts and restarts its server itself: no
|
|
53
|
+
// Start button, no command to type. The sentences of a start that point at
|
|
54
|
+
// them say what to do in the app instead (desktop.offline.* in i18n).
|
|
55
|
+
const DESKTOP_LINES = { stalled: 'stalled', restartStalled: 'stalled', gaveUp: 'stalled', failedHint: 'failedHint' };
|
|
56
|
+
|
|
57
|
+
function desktopLine(line) {
|
|
58
|
+
const key = isDesktopApp() ? DESKTOP_LINES[line.key] : null;
|
|
59
|
+
return key ? t(`desktop.offline.${key}`) : '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The command box under the overlay: a terminal command, which the desktop app has no use for. */
|
|
63
|
+
function showStartCommand(show) {
|
|
64
|
+
const $box = $('loading-server-cmd-box');
|
|
65
|
+
if ($box) $box.style.display = show ? '' : 'none';
|
|
66
|
+
}
|
|
67
|
+
|
|
44
68
|
// ═══════════════════════════════════════════
|
|
45
69
|
// PUBLIC API
|
|
46
70
|
// ═══════════════════════════════════════════
|
|
@@ -69,8 +93,10 @@ export function showLoadingError(title, sub, canStart, serverOffline) {
|
|
|
69
93
|
if (serverOffline) _offlineTitle = title;
|
|
70
94
|
|
|
71
95
|
// Offline, the button asks the OS to start the server (synabun://start); it
|
|
72
|
-
// is left out only when that launcher is known not to be registered
|
|
73
|
-
|
|
96
|
+
// is left out only when that launcher is known not to be registered, and in
|
|
97
|
+
// the desktop app, which starts its server itself.
|
|
98
|
+
const desktopApp = isDesktopApp();
|
|
99
|
+
const offlineStart = !!serverOffline && !desktopApp && startButtonUsable(stored(START_STORAGE.launcher));
|
|
74
100
|
const $action = $('loading-action');
|
|
75
101
|
const $btn = $('loading-action-btn');
|
|
76
102
|
if (canStart || offlineStart) {
|
|
@@ -83,10 +109,12 @@ export function showLoadingError(title, sub, canStart, serverOffline) {
|
|
|
83
109
|
}
|
|
84
110
|
|
|
85
111
|
clearStartStatus();
|
|
112
|
+
clearRestartLook();
|
|
86
113
|
|
|
87
114
|
if (serverOffline) {
|
|
88
115
|
const $hint = $('loading-server-cmd-hint');
|
|
89
|
-
if ($hint) $hint.textContent = offlineStart ? t('loading.runCommandOr') : t('loading.runCommandSetup');
|
|
116
|
+
if ($hint) $hint.textContent = desktopApp ? t('desktop.offline.hint') : offlineStart ? t('loading.runCommandOr') : t('loading.runCommandSetup');
|
|
117
|
+
if (desktopApp) showStartCommand(false);
|
|
90
118
|
watchForServer();
|
|
91
119
|
} else {
|
|
92
120
|
stopWatchingForServer();
|
|
@@ -131,6 +159,7 @@ function resetLoadingToConnecting() {
|
|
|
131
159
|
if ($action) $action.style.display = 'none';
|
|
132
160
|
if ($actionStatus) $actionStatus.textContent = '';
|
|
133
161
|
clearStartStatus();
|
|
162
|
+
clearRestartLook();
|
|
134
163
|
if (_statusDot) _statusDot.classList.remove('error');
|
|
135
164
|
}
|
|
136
165
|
|
|
@@ -222,6 +251,14 @@ function clearStartStatus() {
|
|
|
222
251
|
if ($trail) $trail.replaceChildren();
|
|
223
252
|
}
|
|
224
253
|
|
|
254
|
+
/** What a restart changed about the overlay's look, undone. */
|
|
255
|
+
function clearRestartLook() {
|
|
256
|
+
const $overlay = $('loading-overlay');
|
|
257
|
+
if ($overlay) $overlay.classList.remove('over-app', 'restart-busy', 'restart-refused');
|
|
258
|
+
const btn = $('loading-action-btn');
|
|
259
|
+
if (btn) btn.style.display = '';
|
|
260
|
+
}
|
|
261
|
+
|
|
225
262
|
/**
|
|
226
263
|
* The overlay's mascot as the shared rig, so a start can be acted out. The
|
|
227
264
|
* markup's own still drawing stays as the fallback when the rig cannot mount.
|
|
@@ -258,25 +295,53 @@ function poseMascot(state) {
|
|
|
258
295
|
function renderStart(snap) {
|
|
259
296
|
const platform = isWindowsPlatform(navigator) ? 'windows' : isMacPlatform(navigator) ? 'mac' : 'linux';
|
|
260
297
|
const view = startStatusView(snap, { platform });
|
|
261
|
-
const say = (line) => (line ? t(`loading.start.${line.key}`, line.params) : '');
|
|
298
|
+
const say = (line) => (line ? desktopLine(line) || t(`loading.start.${line.key}`, line.params) : '');
|
|
299
|
+
// A restart this page asked for or was told of, while it runs.
|
|
300
|
+
const restarting = !!snap.restart && (view.busy || view.state === 'online');
|
|
262
301
|
|
|
263
302
|
poseMascot(view.mascot);
|
|
264
303
|
|
|
304
|
+
const $overlay = $('loading-overlay');
|
|
305
|
+
if ($overlay) {
|
|
306
|
+
// While a restart runs there is nothing to press and no command to type;
|
|
307
|
+
// refused, the server is still there and only the way back is offered.
|
|
308
|
+
$overlay.classList.toggle('restart-busy', restarting);
|
|
309
|
+
$overlay.classList.toggle('restart-refused', view.state === 'refused');
|
|
310
|
+
}
|
|
311
|
+
|
|
265
312
|
const $text = $('loading-text');
|
|
266
313
|
if ($text) {
|
|
267
|
-
const title = view.
|
|
268
|
-
: view.mascot === '
|
|
269
|
-
: view.mascot === '
|
|
270
|
-
:
|
|
314
|
+
const title = view.heading ? t(`loading.start.${view.heading}`)
|
|
315
|
+
: view.mascot === 'waking' || view.mascot === 'working' ? t('loading.start.headingStarting')
|
|
316
|
+
: view.mascot === 'ready' ? t('loading.start.headingReady')
|
|
317
|
+
: view.mascot === 'failed' ? t('loading.start.headingFailed')
|
|
318
|
+
: _offlineTitle || t('loading.serverOffline');
|
|
271
319
|
if ($text.textContent !== title) $text.textContent = title;
|
|
272
320
|
}
|
|
273
321
|
|
|
322
|
+
// Under the title: whose restart this is, for as long as it is one.
|
|
323
|
+
const $sub = $('loading-sub');
|
|
324
|
+
if ($sub && _restartShown) {
|
|
325
|
+
const sub = view.state === 'refused' ? t('loading.restartSubRefused')
|
|
326
|
+
: restarting ? (snap.restart.asked ? t('loading.restartSubAsked') : t('loading.restartSubTold'))
|
|
327
|
+
: t('loading.serverNotRunning');
|
|
328
|
+
if ($sub.textContent !== sub) $sub.textContent = sub;
|
|
329
|
+
}
|
|
330
|
+
|
|
274
331
|
const btn = $('loading-action-btn');
|
|
275
332
|
const $label = $('loading-action-label');
|
|
276
|
-
if (btn)
|
|
333
|
+
if (btn) {
|
|
334
|
+
btn.disabled = view.busy || view.state === 'online';
|
|
335
|
+
// No dead button: when a restart did not bring the server back, Start is
|
|
336
|
+
// offered only if its launcher is there (the command below always is).
|
|
337
|
+
const startOffered = view.button === 'start' || view.button === 'retry';
|
|
338
|
+
// The desktop app keeps only the way back from a refused restart.
|
|
339
|
+
btn.style.display = (isDesktopApp() ? view.button !== 'back' : _restartShown && startOffered && !startButtonUsable(stored(START_STORAGE.launcher))) ? 'none' : '';
|
|
340
|
+
}
|
|
277
341
|
if ($label) {
|
|
278
342
|
$label.textContent = view.button === 'starting' ? t('loading.starting')
|
|
279
|
-
: view.button === 'retry' ? t('common.retry')
|
|
343
|
+
: view.button === 'retry' ? t('common.retry')
|
|
344
|
+
: view.button === 'back' ? t('loading.restartBack') : t('loading.startServer');
|
|
280
345
|
}
|
|
281
346
|
|
|
282
347
|
const $status = $('loading-action-status');
|
|
@@ -286,7 +351,7 @@ function renderStart(snap) {
|
|
|
286
351
|
const $elapsed = $('loading-action-elapsed');
|
|
287
352
|
if ($elapsed) {
|
|
288
353
|
$elapsed.textContent = view.elapsed;
|
|
289
|
-
$elapsed.setAttribute('aria-label', view.elapsed ? `${t(
|
|
354
|
+
$elapsed.setAttribute('aria-label', view.elapsed ? `${t(`loading.start.${view.elapsedLabel}`)}: ${view.elapsed}` : '');
|
|
290
355
|
}
|
|
291
356
|
|
|
292
357
|
const $hint = $('loading-action-hint');
|
|
@@ -319,13 +384,28 @@ function renderStart(snap) {
|
|
|
319
384
|
*/
|
|
320
385
|
function watchForServer() {
|
|
321
386
|
if (_offlineBridge) return;
|
|
387
|
+
openBridge().watch();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Is the server answering, which server is it (`bootId`), and does it say it
|
|
392
|
+
* is on its way out for a restart. One that predates those two says neither.
|
|
393
|
+
*/
|
|
394
|
+
async function probeServer() {
|
|
395
|
+
const health = await fetchHealth();
|
|
396
|
+
return {
|
|
397
|
+
up: !!health && health.ok !== false,
|
|
398
|
+
boot: typeof health?.bootId === 'string' ? health.bootId : '',
|
|
399
|
+
stopping: health?.restarting === true,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** The bridge behind the overlay, for either reason it is up: the server is offline, or it is being restarted. */
|
|
404
|
+
function openBridge() {
|
|
322
405
|
mountMascot();
|
|
323
406
|
const beaconAt = startBeaconTarget(window.location);
|
|
324
407
|
const bridge = createStartBridge({
|
|
325
|
-
probe:
|
|
326
|
-
const health = await fetchHealth();
|
|
327
|
-
return !!health && health.ok !== false;
|
|
328
|
-
},
|
|
408
|
+
probe: probeServer,
|
|
329
409
|
launch: () => openStartLink({ document, location: window.location, userAgent: navigator.userAgent }),
|
|
330
410
|
beacon: beaconAt ? () => fetchStartBeacon(beaconAt) : null,
|
|
331
411
|
port: beaconAt ? beaconAt.port : 0,
|
|
@@ -336,13 +416,94 @@ function watchForServer() {
|
|
|
336
416
|
onState(state) {
|
|
337
417
|
if (_offlineBridge !== bridge) return;
|
|
338
418
|
if (state !== 'online') return;
|
|
419
|
+
// Back from a restart: the page loads again, after the frame that says so.
|
|
420
|
+
if (_restartShown) {
|
|
421
|
+
setTimeout(() => window.location.reload(), START_LIMITS.reloadDelayMs);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
339
424
|
resetLoadingToConnecting();
|
|
340
425
|
emit('loading:retried');
|
|
341
426
|
if (_initCallback) _initCallback();
|
|
342
427
|
},
|
|
343
428
|
});
|
|
344
429
|
_offlineBridge = bridge;
|
|
345
|
-
bridge
|
|
430
|
+
return bridge;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// ═══════════════════════════════════════════
|
|
434
|
+
// Restart Server
|
|
435
|
+
// ═══════════════════════════════════════════
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* The user chose Restart Server. The screen changes here, in the click: the
|
|
439
|
+
* overlay is up and says a restart was asked for before the request has even
|
|
440
|
+
* left, and nothing on the way to that first frame waits for the network.
|
|
441
|
+
* From there it shows what is really known (start-bridge.js `restart()`): the
|
|
442
|
+
* server's answer, its own word that it is shutting down, the probe that finds
|
|
443
|
+
* it gone, the supervisor's report of bringing it back. The page loads again
|
|
444
|
+
* by itself when another server than the one that was asked answers.
|
|
445
|
+
*/
|
|
446
|
+
export function requestServerRestart() {
|
|
447
|
+
return beginRestart({ request: postRestart });
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** Ask for the restart: { ok, boot } when the server says it will, { ok: false, status, message } when it will not. */
|
|
451
|
+
async function postRestart() {
|
|
452
|
+
const res = await fetch('/api/server/restart', { method: 'POST', signal: AbortSignal.timeout(10000) });
|
|
453
|
+
let body = null;
|
|
454
|
+
try { body = await res.json(); } catch {}
|
|
455
|
+
if (!res.ok || !body || body.ok === false) {
|
|
456
|
+
return { ok: false, status: res.status, message: String(body?.error || body?.message || '') };
|
|
457
|
+
}
|
|
458
|
+
return { ok: true, boot: typeof body.bootId === 'string' ? body.bootId : '' };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Show the restart: this window asked for it (`request`), or the server told
|
|
463
|
+
* every window that it is restarting (`announced`, over the sync socket).
|
|
464
|
+
*/
|
|
465
|
+
function beginRestart({ request = null, announced = false, boot = '' } = {}) {
|
|
466
|
+
// Already on screen (this window asked, and here is the server saying so too).
|
|
467
|
+
if (_restartShown && _offlineBridge) {
|
|
468
|
+
_offlineBridge.restart({ announced, boot });
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
// The overlay is up because the server is offline: there is nothing to restart.
|
|
472
|
+
if (_offlineBridge) return false;
|
|
473
|
+
const $overlay = $('loading-overlay');
|
|
474
|
+
if (!$overlay) return false;
|
|
475
|
+
|
|
476
|
+
_restartShown = true;
|
|
477
|
+
_restartTitle = document.title;
|
|
478
|
+
document.title = t('loading.start.headingRestarting');
|
|
479
|
+
_offlineTitle = t('loading.serverOffline');
|
|
480
|
+
// `over-app`: no fade-in and above whatever is open. The screen is there in the frame of the click.
|
|
481
|
+
$overlay.classList.add('over-app', 'error', 'server-offline');
|
|
482
|
+
$overlay.classList.remove('hidden');
|
|
483
|
+
// Nothing behind the screen keeps the keyboard (a terminal, an editor).
|
|
484
|
+
try { document.activeElement?.blur?.(); } catch {}
|
|
485
|
+
if (_statusDot) _statusDot.classList.add('error');
|
|
486
|
+
const $action = $('loading-action');
|
|
487
|
+
if ($action) $action.style.display = 'block';
|
|
488
|
+
const $hint = $('loading-server-cmd-hint');
|
|
489
|
+
if (isDesktopApp()) {
|
|
490
|
+
if ($hint) $hint.textContent = t('desktop.offline.hint');
|
|
491
|
+
showStartCommand(false);
|
|
492
|
+
} else if ($hint) $hint.textContent = startButtonUsable(stored(START_STORAGE.launcher)) ? t('loading.runCommandOr') : t('loading.runCommandSetup');
|
|
493
|
+
const $retry = $('loading-retry-status');
|
|
494
|
+
if ($retry) $retry.textContent = '';
|
|
495
|
+
clearStartStatus();
|
|
496
|
+
return openBridge().restart({ request, announced, boot });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/** The restart did not happen and the server is still there: give the app back. */
|
|
500
|
+
function dismissRestart() {
|
|
501
|
+
resetLoadingToConnecting();
|
|
502
|
+
_restartShown = false;
|
|
503
|
+
if (_restartTitle !== null) document.title = _restartTitle;
|
|
504
|
+
_restartTitle = null;
|
|
505
|
+
const $overlay = $('loading-overlay');
|
|
506
|
+
if ($overlay) $overlay.classList.add('hidden');
|
|
346
507
|
}
|
|
347
508
|
|
|
348
509
|
// ═══════════════════════════════════════════
|
|
@@ -354,6 +515,8 @@ function watchForServer() {
|
|
|
354
515
|
* Calls /api/health/start and re-triggers init on success.
|
|
355
516
|
*/
|
|
356
517
|
async function handleStartAction() {
|
|
518
|
+
// A restart the server refused: the button is the way back to the app.
|
|
519
|
+
if (_offlineBridge && _offlineBridge.state === 'refused') { dismissRestart(); return; }
|
|
357
520
|
// Server offline: nothing to call, the OS starts it.
|
|
358
521
|
if (_offlineBridge) { _offlineBridge.start(); return; }
|
|
359
522
|
|
|
@@ -416,6 +579,8 @@ async function handleRetryConnection() {
|
|
|
416
579
|
// fetchHealth uses AbortSignal.timeout(3000) internally
|
|
417
580
|
if (health && health.ok !== false) {
|
|
418
581
|
if ($status) $status.textContent = t('loading.connectedLoading');
|
|
582
|
+
// After a restart the page loads again (see openBridge).
|
|
583
|
+
if (_restartShown) { window.location.reload(); return; }
|
|
419
584
|
resetLoadingToConnecting();
|
|
420
585
|
emit('loading:retried');
|
|
421
586
|
if (_initCallback) _initCallback();
|
|
@@ -463,4 +628,7 @@ export function initLoading({ onInit } = {}) {
|
|
|
463
628
|
// ── Retry connection ──
|
|
464
629
|
const retryBtn = $('loading-retry-btn');
|
|
465
630
|
if (retryBtn) retryBtn.addEventListener('click', handleRetryConnection);
|
|
631
|
+
|
|
632
|
+
// ── The server says it is restarting (ui-sync.js): every window shows it ──
|
|
633
|
+
on('server:restarting', (msg) => beginRestart({ announced: true, boot: typeof msg?.bootId === 'string' ? msg.bootId : '' }));
|
|
466
634
|
}
|
|
@@ -9,12 +9,15 @@ import { storage } from './storage.js';
|
|
|
9
9
|
import { KEYS } from './constants.js';
|
|
10
10
|
import { getMenuItems } from './registry.js';
|
|
11
11
|
import { openHelp } from './ui-help.js';
|
|
12
|
-
import { initPwaInstall, isStandalone, requestPwaInstall } from './pwa-install.js';
|
|
12
|
+
import { armPwaInstallHandoff, initPwaInstall, installGuideUrl, isStandalone, requestPwaInstall } from './pwa-install.js';
|
|
13
13
|
import { registerAction } from './ui-keybinds.js';
|
|
14
14
|
import { isGuest, hasPermission } from './ui-sync.js';
|
|
15
15
|
import { sendToPanel } from './ui-claude-panel.js';
|
|
16
16
|
import { forceCheckToolUpdates, showUpdateToast, TOOL_LABELS } from './ui-tool-updates.js';
|
|
17
|
-
import { forceCheckSynabunUpdate, openSynabunUpdateModal } from './ui-update.js';
|
|
17
|
+
import { forceCheckSynabunUpdate, openSynabunUpdateModal, synabunUpdateSourceLabel } from './ui-update.js';
|
|
18
|
+
import { requestServerRestart } from './ui-loading.js';
|
|
19
|
+
import { desktopBridge, isDesktopApp } from './desktop-bridge.js';
|
|
20
|
+
import { t } from './i18n.js';
|
|
18
21
|
|
|
19
22
|
const $ = (id) => document.getElementById(id);
|
|
20
23
|
|
|
@@ -369,6 +372,7 @@ function wireAutomationsMenu() {
|
|
|
369
372
|
// ── Apps Menu (formerly Terminal) ──
|
|
370
373
|
|
|
371
374
|
function wireTerminalMenu() {
|
|
375
|
+
let disarmInstallHandoff = () => {};
|
|
372
376
|
const items = {
|
|
373
377
|
'menu-terminal-assistant': () => emit('assistant:open'),
|
|
374
378
|
'menu-terminal-claude': () => emit('terminal:open', { profile: 'claude-code' }),
|
|
@@ -389,8 +393,7 @@ function wireTerminalMenu() {
|
|
|
389
393
|
}
|
|
390
394
|
}
|
|
391
395
|
if (syn?.updateAvailable) {
|
|
392
|
-
|
|
393
|
-
updates.push({ label: `SynaBun v${syn.current} → v${syn.latest}`, source: srcLabel });
|
|
396
|
+
updates.push({ label: `SynaBun v${syn.current} → v${syn.latest}`, source: synabunUpdateSourceLabel(syn) });
|
|
394
397
|
}
|
|
395
398
|
|
|
396
399
|
const errors = [];
|
|
@@ -415,38 +418,18 @@ function wireTerminalMenu() {
|
|
|
415
418
|
'menu-terminal-link': () => emit('link:toggle'),
|
|
416
419
|
'menu-terminal-toggle': () => emit('terminal:toggle'),
|
|
417
420
|
'menu-install-app': async () => {
|
|
421
|
+
disarmInstallHandoff(); // asked for here: this click opens the dialog, no later one does
|
|
418
422
|
const result = await requestPwaInstall();
|
|
419
|
-
if (result === 'instructions') location.assign(
|
|
420
|
-
},
|
|
421
|
-
'menu-restart-server': async () => {
|
|
422
|
-
try {
|
|
423
|
-
// Cache project path before server goes down
|
|
424
|
-
try {
|
|
425
|
-
const h = await fetch('/api/health');
|
|
426
|
-
const hd = await h.json();
|
|
427
|
-
if (hd.projectDir) localStorage.setItem('synabun-project-dir', hd.projectDir);
|
|
428
|
-
} catch {}
|
|
429
|
-
document.title = 'Restarting...';
|
|
430
|
-
await fetch('/api/server/restart', { method: 'POST' });
|
|
431
|
-
|
|
432
|
-
// Poll /api/health until the server has gone down AND come back up.
|
|
433
|
-
// The everDown flag prevents premature reload during the brief window
|
|
434
|
-
// where the old process is still serving requests during shutdown grace.
|
|
435
|
-
const deadline = Date.now() + 15000;
|
|
436
|
-
let everDown = false;
|
|
437
|
-
while (Date.now() < deadline) {
|
|
438
|
-
await new Promise(r => setTimeout(r, 250));
|
|
439
|
-
try {
|
|
440
|
-
const r = await fetch('/api/health', { cache: 'no-store' });
|
|
441
|
-
if (!r.ok) { everDown = true; continue; }
|
|
442
|
-
if (everDown) { location.reload(); return; }
|
|
443
|
-
} catch { everDown = true; }
|
|
444
|
-
}
|
|
445
|
-
// Timeout safety net — reload anyway so the user isn't stranded.
|
|
446
|
-
location.reload();
|
|
447
|
-
} catch {}
|
|
423
|
+
if (result === 'instructions') location.assign(installGuideUrl());
|
|
448
424
|
},
|
|
425
|
+
// The restart screen is drawn in this click, before anything is asked of
|
|
426
|
+
// the network; from there it follows the restart and loads the page again
|
|
427
|
+
// when the server is back (ui-loading.js requestServerRestart).
|
|
428
|
+
'menu-restart-server': () => { requestServerRestart(); },
|
|
449
429
|
'menu-stop-server': async () => {
|
|
430
|
+
// Inside the desktop app the server is the app's: stopping it is quitting SynaBun.
|
|
431
|
+
const desktop = desktopBridge();
|
|
432
|
+
if (desktop) { await desktop.quit(); return; }
|
|
450
433
|
const previousTitle = document.title;
|
|
451
434
|
try {
|
|
452
435
|
document.title = 'Stopping...';
|
|
@@ -472,12 +455,21 @@ function wireTerminalMenu() {
|
|
|
472
455
|
registerAction('toggle-terminal', () => emit('terminal:toggle'));
|
|
473
456
|
registerAction('toggle-terminal-alt', () => emit('terminal:toggle'));
|
|
474
457
|
|
|
458
|
+
// The desktop app is SynaBun's own window: no browser installs it, and Stop Server is Quit SynaBun there.
|
|
459
|
+
if (isDesktopApp()) {
|
|
460
|
+
const quitLabel = [...($('menu-stop-server')?.querySelector('.menu-text')?.childNodes || [])].filter(node => node.nodeType === 3).pop();
|
|
461
|
+
if (quitLabel) quitLabel.textContent = ` ${t('desktop.menu.quit')}`;
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
475
464
|
initPwaInstall({ changed: value => {
|
|
476
465
|
const el = $('menu-install-app');
|
|
477
466
|
if (el) el.style.display = value === 'installed' ? 'none' : '';
|
|
478
467
|
} });
|
|
479
468
|
const installItem = $('menu-install-app');
|
|
480
469
|
if (installItem && !isStandalone()) installItem.style.display = '';
|
|
470
|
+
// Sent on by the launcher's guide page: the browser's install dialog opens from the first click or key press,
|
|
471
|
+
// for this one page load. The event it uses is spent, so the menu item goes to the guide page after that.
|
|
472
|
+
disarmInstallHandoff = armPwaInstallHandoff({ leave: event => !!installItem?.contains(event.target) });
|
|
481
473
|
|
|
482
474
|
}
|
|
483
475
|
|
|
@@ -92,3 +92,14 @@ export class LocalReleaseTracker {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The saved list of dismissed runs (localStorage, `[{ runId, at }]`) without
|
|
98
|
+
* one run: what the agents dock's Focus leaves when it reopens a closed tab.
|
|
99
|
+
* Anything unreadable becomes an empty list.
|
|
100
|
+
*/
|
|
101
|
+
export function withoutDismissed(raw, runId) {
|
|
102
|
+
let stored;
|
|
103
|
+
try { stored = JSON.parse(raw || '[]'); } catch { stored = []; }
|
|
104
|
+
return JSON.stringify((Array.isArray(stored) ? stored : []).filter((entry) => entry?.runId && entry.runId !== runId));
|
|
105
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
isNewerRunDescriptor,
|
|
8
8
|
LocalReleaseTracker,
|
|
9
9
|
resolveRouteClaim,
|
|
10
|
+
withoutDismissed,
|
|
10
11
|
} from './ui-native-loop-router-state.js';
|
|
11
12
|
|
|
12
13
|
const DISMISSED_KEY = 'synabun-native-loop-dismissed';
|
|
@@ -48,6 +49,15 @@ function mergeDismissed(raw) {
|
|
|
48
49
|
|
|
49
50
|
try { mergeDismissed(localStorage.getItem(DISMISSED_KEY)); } catch {}
|
|
50
51
|
|
|
52
|
+
// A closed tab's run is dismissed: nothing routes it back here by itself (a
|
|
53
|
+
// reconcile, a late event, another window's claim). Only the user asks for it
|
|
54
|
+
// again, with the agents dock's Focus (focusNativeLoopRun with `reopen`).
|
|
55
|
+
function undismiss(runId) {
|
|
56
|
+
if (!_dismissed.delete(runId)) return false;
|
|
57
|
+
try { localStorage.setItem(DISMISSED_KEY, withoutDismissed(localStorage.getItem(DISMISSED_KEY), runId)); } catch {}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
function persistDismissed() {
|
|
52
62
|
try {
|
|
53
63
|
const existing = JSON.parse(localStorage.getItem(DISMISSED_KEY) || '[]');
|
|
@@ -279,10 +289,13 @@ export function getNativeLoopRun(runId) {
|
|
|
279
289
|
* Bring a dispatched run's sidepanel tab to the front. Attaches with
|
|
280
290
|
* focus:true even when this window already owns the claim (the normal route
|
|
281
291
|
* path only focuses on first attach). Falls back to a fetch when the run has
|
|
282
|
-
* not been broadcast to this window yet.
|
|
292
|
+
* not been broadcast to this window yet. With `reopen` (the user's own Focus,
|
|
293
|
+
* in the agents dock) a run whose tab was closed opens again: a live run
|
|
294
|
+
* attaches as it would have, an ended one with its transcript and end card.
|
|
283
295
|
*/
|
|
284
|
-
export async function focusNativeLoopRun(runId) {
|
|
296
|
+
export async function focusNativeLoopRun(runId, { reopen = false } = {}) {
|
|
285
297
|
if (!runId || _suspended) return false;
|
|
298
|
+
if (reopen) undismiss(runId);
|
|
286
299
|
let run = getNativeLoopRun(runId);
|
|
287
300
|
if (!run) {
|
|
288
301
|
try {
|
|
@@ -8,6 +8,8 @@ import { initDetachedAgentSessions } from './ui-sidepanel-sessions.js';
|
|
|
8
8
|
import { state, emit, on } from './state.js';
|
|
9
9
|
import { getVariant } from './registry.js';
|
|
10
10
|
import { KEYS } from './constants.js';
|
|
11
|
+
import { storage } from './storage.js';
|
|
12
|
+
import { t } from './i18n.js';
|
|
11
13
|
import { loadIfaceConfig, saveIfaceConfig, applyIfaceConfig } from './ui-settings.js';
|
|
12
14
|
import { registerAction } from './ui-keybinds.js';
|
|
13
15
|
import { startTutorial } from './ui-tutorial.js';
|
|
@@ -22,6 +24,7 @@ import { toggleScheduleQueue } from './ui-schedule-queue.js';
|
|
|
22
24
|
import { initUpdate } from './ui-update.js';
|
|
23
25
|
import { initToolUpdates } from './ui-tool-updates.js';
|
|
24
26
|
import { initSidepanelTrayPlaceholders } from './ui-sidepanel-tray.js';
|
|
27
|
+
import { initDesktopTitleBar } from './desktop-titlebar.js';
|
|
25
28
|
|
|
26
29
|
const $ = (id) => document.getElementById(id);
|
|
27
30
|
|
|
@@ -302,7 +305,8 @@ export function initNavbar() {
|
|
|
302
305
|
|
|
303
306
|
// ── Window Controls Overlay (PWA standalone) ──
|
|
304
307
|
// Toggles body.wco-active when the overlay chevron is clicked (traffic lights move into content).
|
|
305
|
-
|
|
308
|
+
// Inside the SynaBun desktop app the bar is the window's title bar, and desktop-titlebar.js does this and more.
|
|
309
|
+
if (!initDesktopTitleBar() && 'windowControlsOverlay' in navigator) {
|
|
306
310
|
const wco = navigator.windowControlsOverlay;
|
|
307
311
|
const updateWco = () => document.body.classList.toggle('wco-active', wco.visible);
|
|
308
312
|
updateWco();
|
|
@@ -324,33 +328,55 @@ export function initNavbar() {
|
|
|
324
328
|
document.addEventListener('visibilitychange', () => { if (!document.hidden) updateClock(); });
|
|
325
329
|
}
|
|
326
330
|
|
|
327
|
-
// ──
|
|
328
|
-
//
|
|
329
|
-
|
|
331
|
+
// ── The workspace tools toggle (#topright-tools-btn) ──
|
|
332
|
+
// A plain on/off button for the dock (the workspace switcher and the tools), remembered across reloads. The agent
|
|
333
|
+
// buttons and the session pills stay where they are either way. A menu the dock had open closes with it.
|
|
330
334
|
const controls = $('topright-controls');
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
const toolsBtn = $('topright-tools-btn');
|
|
336
|
+
if (controls && toolsBtn) {
|
|
337
|
+
const showTools = (shown) => {
|
|
338
|
+
if (!shown) emit('panel:close-all-dropdowns');
|
|
339
|
+
controls.classList.toggle('tools-hidden', !shown);
|
|
340
|
+
const label = t(shown ? 'toolbar.hideTools' : 'toolbar.showTools');
|
|
341
|
+
toolsBtn.dataset.tooltip = label;
|
|
342
|
+
toolsBtn.setAttribute('aria-label', label);
|
|
343
|
+
toolsBtn.setAttribute('aria-expanded', String(shown));
|
|
337
344
|
};
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
e.stopPropagation();
|
|
344
|
-
const hidden = !controls.classList.contains('collapsed');
|
|
345
|
-
applyToolbarsHidden(hidden);
|
|
346
|
-
localStorage.setItem('synabun-toolbar-collapsed', hidden ? '1' : '0');
|
|
347
|
-
// Close any open dropdowns when hiding
|
|
348
|
-
if (hidden) emit('panel:close-all-dropdowns');
|
|
345
|
+
showTools(storage.getItem(KEYS.TOPRIGHT_TOOLS_HIDDEN) !== 'true');
|
|
346
|
+
toolsBtn.addEventListener('click', () => {
|
|
347
|
+
const shown = controls.classList.contains('tools-hidden');
|
|
348
|
+
showTools(shown);
|
|
349
|
+
storage.setItem(KEYS.TOPRIGHT_TOOLS_HIDDEN, String(!shown));
|
|
349
350
|
});
|
|
351
|
+
}
|
|
350
352
|
|
|
351
|
-
|
|
353
|
+
// ── Session pills in the row: the whole name is the tooltip ──
|
|
354
|
+
// Laid out in a row, a pill keeps its width on hover (styles.css): widening, it would push the others onto another
|
|
355
|
+
// line under the pointer. A name cut short is read from the tooltip instead; a pill that brings a tooltip of its own
|
|
356
|
+
// (the Assistant's) keeps it.
|
|
357
|
+
const tray = $('term-minimized-tray');
|
|
358
|
+
if (controls && tray && controls.contains(tray)) {
|
|
359
|
+
const nameTips = () => {
|
|
360
|
+
for (const pill of tray.children) {
|
|
361
|
+
const name = pill.querySelector('.term-minimized-pill-label')?.textContent.trim() || '';
|
|
362
|
+
if (pill.hasAttribute('data-tooltip') && pill.dataset.tooltip !== pill.dataset.nameTip) {
|
|
363
|
+
delete pill.dataset.nameTip;
|
|
364
|
+
} else if (name) {
|
|
365
|
+
pill.dataset.tooltip = name;
|
|
366
|
+
pill.dataset.nameTip = name;
|
|
367
|
+
} else if (pill.dataset.nameTip != null) {
|
|
368
|
+
pill.removeAttribute('data-tooltip');
|
|
369
|
+
delete pill.dataset.nameTip;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
new MutationObserver(nameTips).observe(tray, { childList: true, subtree: true, characterData: true });
|
|
374
|
+
nameTips();
|
|
352
375
|
}
|
|
353
376
|
|
|
377
|
+
// "Hide all toolbars" is gone: whoever had it on gets every toolbar back, and its key goes with it.
|
|
378
|
+
try { localStorage.removeItem('synabun-toolbar-collapsed'); } catch { /* storage refused: nothing to clear */ }
|
|
379
|
+
|
|
354
380
|
// ── Update alert ──
|
|
355
381
|
initUpdate();
|
|
356
382
|
initToolUpdates();
|