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
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — File links in agent messages: the page side
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// One click handler for the links in the messages of the four side panels
|
|
6
|
+
// (Assistant, Claude, Codex, OpenCode). A link that points at a file the code
|
|
7
|
+
// editor can open opens it there (`open-file-editor`), at its line and column;
|
|
8
|
+
// every other link keeps what its panel did with it. What a target means and
|
|
9
|
+
// what a click does are decided in file-links.js; this module gives it the
|
|
10
|
+
// page: the bus, the toast, and the server. Whether a file can be opened is
|
|
11
|
+
// the editor's own answer: GET /api/file-content, with the path checks that
|
|
12
|
+
// route applies.
|
|
13
|
+
|
|
14
|
+
import { emit } from './state.js';
|
|
15
|
+
import { t } from './i18n.js';
|
|
16
|
+
import { createFileLinkHandlers, fillFileLinkCopy } from './file-links.js';
|
|
17
|
+
|
|
18
|
+
/** A `fileLinks.*` sentence in the active locale; in English where i18n never loads (a detached session). */
|
|
19
|
+
export function fileLinkText(key, params) {
|
|
20
|
+
const id = `fileLinks.${key}`;
|
|
21
|
+
let text = id;
|
|
22
|
+
try { text = t(id, params); } catch { /* i18n is not there: the English below */ }
|
|
23
|
+
return text && text !== id ? text : fillFileLinkCopy(key, params);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** A short message over the page: the toast the editor uses. */
|
|
27
|
+
export function showFileLinkNotice(message) {
|
|
28
|
+
let toast = document.getElementById('fe-toast');
|
|
29
|
+
if (!toast) {
|
|
30
|
+
toast = document.createElement('div');
|
|
31
|
+
toast.id = 'fe-toast';
|
|
32
|
+
toast.style.cssText = 'position:fixed;bottom:60px;left:50%;transform:translateX(-50%);background:rgba(30,30,34,0.95);color:#e0e0e0;padding:6px 16px;border-radius:6px;font-size:12px;font-family:var(--ff-mono);z-index:2147483647;pointer-events:none;opacity:0;transition:opacity 0.2s;border:1px solid rgba(255,255,255,0.1);';
|
|
33
|
+
document.body.appendChild(toast);
|
|
34
|
+
}
|
|
35
|
+
toast.textContent = message;
|
|
36
|
+
toast.style.opacity = '1';
|
|
37
|
+
clearTimeout(toast._timer);
|
|
38
|
+
toast._timer = setTimeout(() => { toast.style.opacity = '0'; }, 3500);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let _home = null;
|
|
42
|
+
|
|
43
|
+
// The home folder, for `~`: the folder picker's route answers with it when no path is asked for.
|
|
44
|
+
function homeFolder() {
|
|
45
|
+
_home ??= fetch('/api/browse-directory')
|
|
46
|
+
.then((res) => (res.ok ? res.json() : null))
|
|
47
|
+
.then((data) => (typeof data?.current === 'string' ? data.current : ''))
|
|
48
|
+
.catch(() => '')
|
|
49
|
+
.then((home) => { if (!home) _home = null; return home; });
|
|
50
|
+
return _home;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function probeFile(path) {
|
|
54
|
+
const res = await fetch(`/api/file-content?path=${encodeURIComponent(path)}`);
|
|
55
|
+
// Only the answer matters: the editor reads the file itself when it opens it.
|
|
56
|
+
try { await res.body?.cancel(); } catch { /* already read or closed */ }
|
|
57
|
+
return res.status;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const handlers = createFileLinkHandlers({
|
|
61
|
+
emit,
|
|
62
|
+
probe: probeFile,
|
|
63
|
+
home: homeFolder,
|
|
64
|
+
origin: () => window.location.origin,
|
|
65
|
+
say: fileLinkText,
|
|
66
|
+
notify: showFileLinkNotice,
|
|
67
|
+
follow: (anchor) => {
|
|
68
|
+
if (anchor.target === '_blank') window.open(anchor.href, '_blank', 'noopener,noreferrer');
|
|
69
|
+
else window.location.assign(anchor.href);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Take a click on a link in an agent's message when the link points at a file (see createFileLinkHandlers).
|
|
75
|
+
* @returns {boolean} true when the click was taken: the browser no longer follows the link
|
|
76
|
+
*/
|
|
77
|
+
export function handleFileLinkClick(event, options = {}) {
|
|
78
|
+
const taken = handlers.handleClick(event, options);
|
|
79
|
+
if (!taken) return false;
|
|
80
|
+
taken.catch((error) => console.warn('[file-links] click failed', error));
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Give the links of a panel's messages their file behaviour. One listener on the container covers messages
|
|
86
|
+
* that are streaming, finished, or put back from history.
|
|
87
|
+
* @param {Element} container the element every message of the panel is rendered into
|
|
88
|
+
* @param {{ cwd?: (anchor: Element) => string, textLinks?: string, copyPath?: (anchor: Element, path: string) => any,
|
|
89
|
+
* notify?: (message: string) => void }} [options] see createFileLinkHandlers().handleClick
|
|
90
|
+
* @returns {() => void} removes the listeners
|
|
91
|
+
*/
|
|
92
|
+
export function wireFileLinks(container, options = {}) {
|
|
93
|
+
if (!container) return () => {};
|
|
94
|
+
const own = { ...options, within: container };
|
|
95
|
+
const onClick = (event) => { handleFileLinkClick(event, own); };
|
|
96
|
+
const onOver = (event) => handlers.label(event, own);
|
|
97
|
+
container.addEventListener('click', onClick);
|
|
98
|
+
container.addEventListener('mouseover', onOver);
|
|
99
|
+
return () => {
|
|
100
|
+
container.removeEventListener('click', onClick);
|
|
101
|
+
container.removeEventListener('mouseover', onOver);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — the Git Bash row of Settings
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// The page side of git-bash-view.js: the row of Settings → AI connections →
|
|
6
|
+
// Executable paths that shows the Git Bash every Claude Code SynaBun starts
|
|
7
|
+
// gets on Windows, with Download / Try again and Re-check. It asks
|
|
8
|
+
// GET /api/cli/git-bash, follows a download while it runs (a few times a
|
|
9
|
+
// second, until the row has left the page), and posts what the buttons ask
|
|
10
|
+
// with the guards of SynaBun's other local routes (a JSON body, X-SynaBun-UI).
|
|
11
|
+
// A server that has no such route (an older one), and every macOS or Linux
|
|
12
|
+
// server, leaves the row hidden.
|
|
13
|
+
|
|
14
|
+
import { gitBashText, gitBashView } from './git-bash-view.js';
|
|
15
|
+
|
|
16
|
+
const POST = Object.freeze({ method: 'POST', headers: { 'Content-Type': 'application/json', 'X-SynaBun-UI': '1' }, body: '{}' });
|
|
17
|
+
|
|
18
|
+
const ICON = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm1 2v12h16V6H4zm2.3 2.3 3.7 3.7-3.7 3.7-1.4-1.4L7.2 12 4.9 9.7l1.4-1.4zM11 15h6v2h-6v-2z"/></svg>';
|
|
19
|
+
|
|
20
|
+
const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, (char) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[char]));
|
|
21
|
+
|
|
22
|
+
/** The row's markup: hidden until the server says there is something to show (Windows). */
|
|
23
|
+
export function gitBashRowHtml() {
|
|
24
|
+
return `
|
|
25
|
+
<div class="cli-path-row" id="cli-git-bash" data-git-bash hidden>
|
|
26
|
+
<div class="cli-path-icon" style="color:var(--t-secondary)">${ICON}</div>
|
|
27
|
+
<div class="cli-path-field">
|
|
28
|
+
<span class="cli-path-label" id="cli-git-bash-label">${escapeHtml(gitBashText('label'))}</span>
|
|
29
|
+
<div class="cli-path-input-row">
|
|
30
|
+
<span class="stg-help" data-git-bash-line role="status" aria-live="polite" aria-labelledby="cli-git-bash-label" style="flex:1;min-width:0;margin:0"></span>
|
|
31
|
+
<button type="button" class="cli-detect-btn" data-git-bash-action hidden></button>
|
|
32
|
+
<button type="button" class="cli-detect-btn" data-git-bash-recheck hidden>${escapeHtml(gitBashText('recheck'))}</button>
|
|
33
|
+
<span class="cli-path-status" data-git-bash-badge></span>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="stg-help" data-git-bash-note hidden></div>
|
|
36
|
+
<div class="stg-help">${escapeHtml(gitBashText('help'))}</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Fill the row and keep it current. `fetchImpl`, `schedule` and `cancel` are the page's own unless a test gives
|
|
43
|
+
* others. Returns `{ refresh, stop }`; the row stops following a download by itself once it is off the page.
|
|
44
|
+
*/
|
|
45
|
+
export function wireGitBashRow(row, { fetchImpl = (...args) => fetch(...args), pollMs = 1500, schedule = (fn, ms) => setTimeout(fn, ms), cancel = (id) => clearTimeout(id) } = {}) {
|
|
46
|
+
if (!row) return { refresh: async () => null, stop: () => {} };
|
|
47
|
+
const badge = row.querySelector('[data-git-bash-badge]');
|
|
48
|
+
const line = row.querySelector('[data-git-bash-line]');
|
|
49
|
+
const note = row.querySelector('[data-git-bash-note]');
|
|
50
|
+
const action = row.querySelector('[data-git-bash-action]');
|
|
51
|
+
const recheck = row.querySelector('[data-git-bash-recheck]');
|
|
52
|
+
let timer = null;
|
|
53
|
+
let stopped = false;
|
|
54
|
+
|
|
55
|
+
const clearPoll = () => { if (timer !== null) { cancel(timer); timer = null; } };
|
|
56
|
+
const stop = () => { stopped = true; clearPoll(); };
|
|
57
|
+
|
|
58
|
+
function draw(status) {
|
|
59
|
+
const view = gitBashView(status);
|
|
60
|
+
row.hidden = !view.visible;
|
|
61
|
+
clearPoll();
|
|
62
|
+
if (!view.visible) return view;
|
|
63
|
+
if (badge) {
|
|
64
|
+
badge.textContent = view.badge?.text || '';
|
|
65
|
+
badge.className = `cli-path-status${view.badge?.tone ? ` ${view.badge.tone}` : ''}`;
|
|
66
|
+
}
|
|
67
|
+
if (line) line.textContent = view.line;
|
|
68
|
+
if (note) { note.textContent = view.note || ''; note.hidden = !view.note; }
|
|
69
|
+
if (action) {
|
|
70
|
+
action.hidden = !view.action;
|
|
71
|
+
action.disabled = false;
|
|
72
|
+
action.textContent = view.action ? gitBashText(view.action) : '';
|
|
73
|
+
}
|
|
74
|
+
if (recheck) {
|
|
75
|
+
recheck.hidden = !view.recheck;
|
|
76
|
+
recheck.disabled = false;
|
|
77
|
+
recheck.textContent = gitBashText('recheck');
|
|
78
|
+
}
|
|
79
|
+
if (view.busy && !stopped) {
|
|
80
|
+
timer = schedule(() => {
|
|
81
|
+
timer = null;
|
|
82
|
+
if (row.isConnected === false) { stop(); return; }
|
|
83
|
+
refresh();
|
|
84
|
+
}, pollMs);
|
|
85
|
+
}
|
|
86
|
+
return view;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function ask(path, init) {
|
|
90
|
+
const res = await fetchImpl(path, init);
|
|
91
|
+
let body = null;
|
|
92
|
+
try { body = await res.json(); } catch { body = null; }
|
|
93
|
+
// A refusal that still says how things are (422: nothing to fetch here) is drawn as it is.
|
|
94
|
+
if (!res.ok && !(body && typeof body.state === 'string')) throw new Error(body?.error || body?.code || `HTTP ${res.status}`);
|
|
95
|
+
return body;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const said = (error) => { if (line) line.textContent = gitBashText('errorRequest', { message: error?.message || String(error) }); };
|
|
99
|
+
|
|
100
|
+
async function refresh() {
|
|
101
|
+
try { return draw(await ask('/api/cli/git-bash')); } catch {
|
|
102
|
+
// An older server, or none: there is no row to show.
|
|
103
|
+
row.hidden = true;
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
action?.addEventListener('click', async () => {
|
|
109
|
+
action.disabled = true;
|
|
110
|
+
try { draw(await ask('/api/cli/git-bash/install', POST)); } catch (error) { said(error); action.disabled = false; }
|
|
111
|
+
});
|
|
112
|
+
recheck?.addEventListener('click', async () => {
|
|
113
|
+
recheck.disabled = true;
|
|
114
|
+
recheck.textContent = gitBashText('checking');
|
|
115
|
+
try { draw(await ask('/api/cli/git-bash/recheck', POST)); } catch (error) {
|
|
116
|
+
said(error);
|
|
117
|
+
recheck.disabled = false;
|
|
118
|
+
recheck.textContent = gitBashText('recheck');
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
refresh();
|
|
123
|
+
return { refresh, stop };
|
|
124
|
+
}
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import { getHelpSections, getVariant } from './registry.js';
|
|
7
7
|
import { registerAction, getDisplayKey } from './ui-keybinds.js';
|
|
8
|
+
import { t } from './i18n.js';
|
|
9
|
+
|
|
10
|
+
// The modifier of the File Explorer's keys, as this system shows it.
|
|
11
|
+
const MOD_KEY = /Mac|iPhone|iPad/.test(globalThis.navigator?.platform || '') ? '⌘' : 'Ctrl';
|
|
8
12
|
|
|
9
13
|
// Shared help sections that appear in all variants
|
|
10
14
|
// Keyboard section uses dynamic keys from central keybinds system
|
|
@@ -46,6 +50,28 @@ function getSharedHelpSections() {
|
|
|
46
50
|
<div class="help-row"><div class="help-keys"><span class="help-key">Pin</span><span class="help-key">📌</span></div><span class="help-desc">Lock panel position & size</span></div>
|
|
47
51
|
</div>`
|
|
48
52
|
},
|
|
53
|
+
{
|
|
54
|
+
// The File Explorer's tree, while it has the keyboard (shared/explorer/, docs/file-explorer.md)
|
|
55
|
+
order: 85,
|
|
56
|
+
html: `<div class="help-section">
|
|
57
|
+
<div class="help-section-title">${t('fileExplorer.help.title')}</div>
|
|
58
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">${getDisplayKey('toggle-file-explorer')}</span></div><span class="help-desc">${t('fileExplorer.help.toggle')}</span></div>
|
|
59
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">↑</span><span class="help-key">↓</span><span class="help-key">Home</span><span class="help-key">End</span></div><span class="help-desc">${t('fileExplorer.help.move')}</span></div>
|
|
60
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">→</span><span class="help-key">←</span></div><span class="help-desc">${t('fileExplorer.help.fold')}</span></div>
|
|
61
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Enter</span></div><span class="help-desc">${t('fileExplorer.help.open')}</span></div>
|
|
62
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Space</span></div><span class="help-desc">${t('fileExplorer.help.peek')}</span></div>
|
|
63
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Shift</span><span class="help-key">↑ ↓</span></div><span class="help-desc">${t('fileExplorer.help.range')}</span></div>
|
|
64
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">A–Z</span></div><span class="help-desc">${t('fileExplorer.help.typeAhead')}</span></div>
|
|
65
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">↓</span><span class="help-key">Enter</span></div><span class="help-desc">${t('fileExplorer.help.offers')}</span></div>
|
|
66
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">F2</span></div><span class="help-desc">${t('fileExplorer.help.rename')}</span></div>
|
|
67
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Del</span></div><span class="help-desc">${t('fileExplorer.help.delete')}</span></div>
|
|
68
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">${MOD_KEY}</span><span class="help-key">X / C / V</span></div><span class="help-desc">${t('fileExplorer.help.clipboard')}</span></div>
|
|
69
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">${MOD_KEY}</span><span class="help-key">Alt</span><span class="help-key">C</span></div><span class="help-desc">${t('fileExplorer.help.copyPath')}</span></div>
|
|
70
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">${MOD_KEY}</span><span class="help-key">P</span></div><span class="help-desc">${t('fileExplorer.help.goToFile')}</span></div>
|
|
71
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Shift</span><span class="help-key">F10</span></div><span class="help-desc">${t('fileExplorer.help.menu')}</span></div>
|
|
72
|
+
<div class="help-row"><div class="help-keys"><span class="help-key">Esc</span></div><span class="help-desc">${t('fileExplorer.help.escape')}</span></div>
|
|
73
|
+
</div>`
|
|
74
|
+
},
|
|
49
75
|
{
|
|
50
76
|
order: 90,
|
|
51
77
|
html: `<div class="help-section">
|
|
@@ -7,9 +7,6 @@
|
|
|
7
7
|
import { emit, on } from './state.js';
|
|
8
8
|
import {
|
|
9
9
|
fetchInviteStatus,
|
|
10
|
-
fetchTunnelStatus,
|
|
11
|
-
startTunnel,
|
|
12
|
-
stopTunnel,
|
|
13
10
|
generateInviteKey,
|
|
14
11
|
revokeInviteKey,
|
|
15
12
|
revokeAllInviteSessions,
|
|
@@ -18,15 +15,25 @@ import {
|
|
|
18
15
|
saveInvitePermissions,
|
|
19
16
|
} from './api.js';
|
|
20
17
|
import { isGuest } from './ui-sync.js';
|
|
18
|
+
import { createTunnelCard, drawInto } from './ui-tunnel.js';
|
|
21
19
|
|
|
22
20
|
const $ = (id) => document.getElementById(id);
|
|
23
21
|
|
|
24
22
|
let _isOpen = false;
|
|
25
23
|
let _data = { hasKey: false, maskedKey: null, activeSessions: 0, proxyConfig: { useProxy: false, proxyUrl: '' } };
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let
|
|
29
|
-
|
|
24
|
+
// The Cloudflare tunnel: what the server says of it, read by tunnel-view.js; asked again by itself while a
|
|
25
|
+
// download or a start is on its way, for as long as the dropdown is open (ui-tunnel.js).
|
|
26
|
+
let _tunnelKind = null;
|
|
27
|
+
const _tunnel = createTunnelCard({
|
|
28
|
+
alive: () => _isOpen,
|
|
29
|
+
onChange(view) {
|
|
30
|
+
if (!_isOpen) return;
|
|
31
|
+
// The address coming or going changes the other sections too (the invite link); anything else only this block.
|
|
32
|
+
const whole = view.kind !== _tunnelKind && (view.kind === 'running' || _tunnelKind === 'running');
|
|
33
|
+
_tunnelKind = view.kind;
|
|
34
|
+
if (whole) render(); else drawTunnel();
|
|
35
|
+
},
|
|
36
|
+
});
|
|
30
37
|
let _keyMode = 'auto'; // 'auto' | 'custom'
|
|
31
38
|
let _revealedKey = null; // shown only right after generation
|
|
32
39
|
let _permissions = { terminal: false, whiteboard: false, memories: true, skills: false, cards: true, browser: false };
|
|
@@ -60,15 +67,12 @@ function toggleDropdown() {
|
|
|
60
67
|
|
|
61
68
|
async function loadAndRender() {
|
|
62
69
|
try {
|
|
63
|
-
const [inviteRes,
|
|
70
|
+
const [inviteRes, , permRes] = await Promise.all([
|
|
64
71
|
fetchInviteStatus(),
|
|
65
|
-
|
|
72
|
+
_tunnel.refresh(),
|
|
66
73
|
fetchInvitePermissions(),
|
|
67
74
|
]);
|
|
68
75
|
_data = inviteRes;
|
|
69
|
-
_tunnelUrl = tunnelRes.url || null;
|
|
70
|
-
_tunnelAvailable = tunnelRes.available;
|
|
71
|
-
_tunnelStarting = tunnelRes.starting || false;
|
|
72
76
|
if (permRes?.permissions) _permissions = permRes.permissions;
|
|
73
77
|
} catch (err) {
|
|
74
78
|
console.warn('[invite] Failed to load status:', err);
|
|
@@ -76,38 +80,13 @@ async function loadAndRender() {
|
|
|
76
80
|
render();
|
|
77
81
|
}
|
|
78
82
|
|
|
79
|
-
// ─── Tunnel polling ─────────────────────
|
|
80
|
-
|
|
81
|
-
function pollForTunnelUrl() {
|
|
82
|
-
if (_tunnelPollTimer) clearInterval(_tunnelPollTimer);
|
|
83
|
-
let attempts = 0;
|
|
84
|
-
_tunnelPollTimer = setInterval(async () => {
|
|
85
|
-
attempts++;
|
|
86
|
-
try {
|
|
87
|
-
const res = await fetchTunnelStatus();
|
|
88
|
-
if (res.url) {
|
|
89
|
-
clearInterval(_tunnelPollTimer);
|
|
90
|
-
_tunnelPollTimer = null;
|
|
91
|
-
_tunnelUrl = res.url;
|
|
92
|
-
_tunnelStarting = false;
|
|
93
|
-
if (_isOpen) render();
|
|
94
|
-
} else if (attempts >= 30) {
|
|
95
|
-
clearInterval(_tunnelPollTimer);
|
|
96
|
-
_tunnelPollTimer = null;
|
|
97
|
-
_tunnelStarting = false;
|
|
98
|
-
if (_isOpen) render();
|
|
99
|
-
}
|
|
100
|
-
} catch {}
|
|
101
|
-
}, 1000);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
83
|
// ─── URL helpers ────────────────────────
|
|
105
84
|
|
|
106
85
|
function getBaseUrl() {
|
|
107
86
|
if (_data.proxyConfig?.useProxy && _data.proxyConfig?.proxyUrl) {
|
|
108
87
|
return _data.proxyConfig.proxyUrl.replace(/\/+$/, '');
|
|
109
88
|
}
|
|
110
|
-
return
|
|
89
|
+
return _tunnel.view().url || null;
|
|
111
90
|
}
|
|
112
91
|
|
|
113
92
|
function getInviteUrl() {
|
|
@@ -136,9 +115,7 @@ function render() {
|
|
|
136
115
|
const dd = $('invite-dropdown');
|
|
137
116
|
if (!dd) return;
|
|
138
117
|
|
|
139
|
-
const baseUrl = getBaseUrl();
|
|
140
118
|
const inviteUrl = getInviteUrl();
|
|
141
|
-
const hasUrl = !!baseUrl;
|
|
142
119
|
const useProxy = _data.proxyConfig?.useProxy || false;
|
|
143
120
|
|
|
144
121
|
dd.innerHTML = `
|
|
@@ -153,39 +130,7 @@ function render() {
|
|
|
153
130
|
<button class="invite-alt-link" id="invite-mode-tunnel">Use Cloudflare tunnel</button>
|
|
154
131
|
</div>
|
|
155
132
|
` : `
|
|
156
|
-
|
|
157
|
-
<div class="invite-status-row">
|
|
158
|
-
<span class="invite-status-dot active"></span>
|
|
159
|
-
<span class="invite-url-text">${baseUrl}</span>
|
|
160
|
-
<button class="invite-copy-icon" id="invite-copy-base-url" data-tooltip="Copy"><svg viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
|
|
161
|
-
<span class="invite-copied" id="invite-copied-url">Copied</span>
|
|
162
|
-
</div>
|
|
163
|
-
<div class="invite-action-row">
|
|
164
|
-
<button class="invite-btn" id="invite-tunnel-stop">Stop</button>
|
|
165
|
-
<button class="invite-alt-link" id="invite-mode-proxy">Use custom URL</button>
|
|
166
|
-
</div>
|
|
167
|
-
` : `
|
|
168
|
-
${_tunnelAvailable ? `
|
|
169
|
-
${_tunnelStarting ? `
|
|
170
|
-
<div class="invite-action-row">
|
|
171
|
-
<button class="invite-btn" disabled style="opacity:0.5;cursor:default">
|
|
172
|
-
<svg viewBox="0 0 24 24" class="invite-spin"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
|
|
173
|
-
Starting...
|
|
174
|
-
</button>
|
|
175
|
-
</div>
|
|
176
|
-
` : `
|
|
177
|
-
<div class="invite-action-row">
|
|
178
|
-
<button class="invite-btn primary" id="invite-tunnel-start">Start Tunnel</button>
|
|
179
|
-
<button class="invite-alt-link" id="invite-mode-proxy">Use custom URL</button>
|
|
180
|
-
</div>
|
|
181
|
-
`}
|
|
182
|
-
` : `
|
|
183
|
-
<div class="invite-action-row">
|
|
184
|
-
<span style="font-size:10px;color:var(--t-dimmed)">cloudflared not available</span>
|
|
185
|
-
<button class="invite-alt-link" id="invite-mode-proxy">Use custom URL</button>
|
|
186
|
-
</div>
|
|
187
|
-
`}
|
|
188
|
-
`}
|
|
133
|
+
<div id="invite-tunnel"></div>
|
|
189
134
|
`}
|
|
190
135
|
</div>
|
|
191
136
|
|
|
@@ -242,12 +187,118 @@ function render() {
|
|
|
242
187
|
` : ''}
|
|
243
188
|
`;
|
|
244
189
|
|
|
190
|
+
wireTunnel();
|
|
191
|
+
drawTunnel();
|
|
245
192
|
wireEvents();
|
|
246
193
|
updateBadge();
|
|
247
194
|
}
|
|
248
195
|
|
|
196
|
+
// ─── The tunnel block ───────────────────
|
|
197
|
+
// Drawn by itself: while cloudflared is being downloaded the progress changes every second, and the rest of the
|
|
198
|
+
// dropdown (a password being typed, a key just shown) must not be drawn over for that.
|
|
199
|
+
|
|
200
|
+
const COPY_ICON = '<svg viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
|
|
201
|
+
const SPINNER = '<svg viewBox="0 0 24 24" class="invite-spin invite-tunnel-spinner" aria-hidden="true"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>';
|
|
202
|
+
const USE_CUSTOM = '<button class="invite-alt-link" id="invite-mode-proxy">Use custom URL</button>';
|
|
203
|
+
|
|
204
|
+
/** The markup of the tunnel block for a reading of tunnel-view.js. */
|
|
205
|
+
function tunnelBlock(view) {
|
|
206
|
+
const label = escHtml(view.label);
|
|
207
|
+
const detail = view.detail ? `<div class="invite-tunnel-detail">${escHtml(view.detail)}</div>` : '';
|
|
208
|
+
if (view.kind === 'running') {
|
|
209
|
+
return `
|
|
210
|
+
<div class="invite-status-row" role="status">
|
|
211
|
+
<span class="invite-status-dot active" aria-hidden="true"></span>
|
|
212
|
+
<span class="invite-url-text" title="${label}">${escHtml(view.url)}</span>
|
|
213
|
+
<button class="invite-copy-icon" id="invite-copy-base-url" data-tooltip="Copy" aria-label="Copy">${COPY_ICON}</button>
|
|
214
|
+
<span class="invite-copied" id="invite-copied-url">Copied</span>
|
|
215
|
+
</div>
|
|
216
|
+
${view.copy ? `<div class="invite-tunnel-detail invite-tunnel-copy">${escHtml(view.copy)}${view.copyNote ? ` ${escHtml(view.copyNote)}` : ''}</div>` : ''}
|
|
217
|
+
<div class="invite-action-row">
|
|
218
|
+
<button class="invite-btn" id="invite-tunnel-stop">${escHtml(view.actionLabel)}</button>
|
|
219
|
+
${USE_CUSTOM}
|
|
220
|
+
</div>`;
|
|
221
|
+
}
|
|
222
|
+
if (view.kind === 'downloading' || view.kind === 'starting') {
|
|
223
|
+
return `
|
|
224
|
+
<div class="invite-status-row" role="status">
|
|
225
|
+
${SPINNER}
|
|
226
|
+
<span class="invite-tunnel-state">${label}</span>
|
|
227
|
+
${view.progress ? `<span class="invite-tunnel-percent">${escHtml(view.progress.text)}</span>` : ''}
|
|
228
|
+
</div>
|
|
229
|
+
${view.progress ? `<div class="invite-progress" role="progressbar" aria-label="${label}" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${view.progress.percent}"><span style="width:${view.progress.percent}%"></span></div>` : ''}
|
|
230
|
+
${detail}
|
|
231
|
+
<div class="invite-action-row">
|
|
232
|
+
<button class="invite-btn" id="invite-tunnel-stop">${escHtml(view.actionLabel)}</button>
|
|
233
|
+
${USE_CUSTOM}
|
|
234
|
+
</div>`;
|
|
235
|
+
}
|
|
236
|
+
if (view.kind === 'failed') {
|
|
237
|
+
return `
|
|
238
|
+
<div class="invite-status-row" role="alert">
|
|
239
|
+
<span class="invite-status-dot error" aria-hidden="true"></span>
|
|
240
|
+
<span class="invite-tunnel-state error">${label}</span>
|
|
241
|
+
</div>
|
|
242
|
+
${detail}
|
|
243
|
+
<div class="invite-action-row">
|
|
244
|
+
<button class="invite-btn primary" id="invite-tunnel-start">${escHtml(view.actionLabel)}</button>
|
|
245
|
+
${USE_CUSTOM}
|
|
246
|
+
</div>`;
|
|
247
|
+
}
|
|
248
|
+
if (view.kind === 'idle') {
|
|
249
|
+
return `
|
|
250
|
+
${detail}
|
|
251
|
+
<div class="invite-action-row">
|
|
252
|
+
<button class="invite-btn primary" id="invite-tunnel-start">${escHtml(view.actionLabel)}</button>
|
|
253
|
+
${USE_CUSTOM}
|
|
254
|
+
</div>`;
|
|
255
|
+
}
|
|
256
|
+
// No tunnel can be started from here (the server needs a restart first, or this system has no tunnel
|
|
257
|
+
// program): the state, why, and the other way to an address.
|
|
258
|
+
return `
|
|
259
|
+
<div class="invite-status-row" role="status">
|
|
260
|
+
<span class="invite-status-dot${view.tone === 'warn' ? ' warn' : ''}" aria-hidden="true"></span>
|
|
261
|
+
<span class="invite-tunnel-state">${label}</span>
|
|
262
|
+
</div>
|
|
263
|
+
${detail}
|
|
264
|
+
<div class="invite-action-row">
|
|
265
|
+
${USE_CUSTOM}
|
|
266
|
+
</div>`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function drawTunnel() {
|
|
270
|
+
const box = $('invite-tunnel');
|
|
271
|
+
if (box) drawInto(box, tunnelBlock(_tunnel.view()));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** One listener for the block: its buttons come and go with the state. */
|
|
275
|
+
function wireTunnel() {
|
|
276
|
+
const box = $('invite-tunnel');
|
|
277
|
+
if (!box) return;
|
|
278
|
+
box.addEventListener('click', async (e) => {
|
|
279
|
+
const button = e.target.closest('button');
|
|
280
|
+
if (!button || !box.contains(button)) return;
|
|
281
|
+
e.stopPropagation();
|
|
282
|
+
if (button.id === 'invite-tunnel-start') {
|
|
283
|
+
// Shown at once: the server answers immediately too, and then says what it is doing.
|
|
284
|
+
_tunnel.show({ ...(_tunnel.status() || {}), state: 'starting', starting: true, url: null, error: null });
|
|
285
|
+
await _tunnel.start();
|
|
286
|
+
} else if (button.id === 'invite-tunnel-stop') {
|
|
287
|
+
await _tunnel.stop();
|
|
288
|
+
} else if (button.id === 'invite-copy-base-url') {
|
|
289
|
+
const url = getBaseUrl();
|
|
290
|
+
if (url) copyText(url, 'invite-copied-url');
|
|
291
|
+
} else if (button.id === 'invite-mode-proxy') {
|
|
292
|
+
await saveInviteProxy({ useProxy: true, proxyUrl: _data.proxyConfig?.proxyUrl || '' });
|
|
293
|
+
_data.proxyConfig = { useProxy: true, proxyUrl: _data.proxyConfig?.proxyUrl || '' };
|
|
294
|
+
_revealedKey = null;
|
|
295
|
+
render();
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
249
300
|
function escHtml(s) {
|
|
250
|
-
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
301
|
+
return String(s ?? '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
251
302
|
}
|
|
252
303
|
|
|
253
304
|
const PERM_ICONS = {
|
|
@@ -282,48 +333,7 @@ function wireEvents() {
|
|
|
282
333
|
render();
|
|
283
334
|
});
|
|
284
335
|
|
|
285
|
-
|
|
286
|
-
e.stopPropagation();
|
|
287
|
-
await saveInviteProxy({ useProxy: true, proxyUrl: _data.proxyConfig?.proxyUrl || '' });
|
|
288
|
-
_data.proxyConfig = { useProxy: true, proxyUrl: _data.proxyConfig?.proxyUrl || '' };
|
|
289
|
-
_revealedKey = null;
|
|
290
|
-
render();
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// Copy base URL
|
|
294
|
-
$('invite-copy-base-url')?.addEventListener('click', (e) => {
|
|
295
|
-
e.stopPropagation();
|
|
296
|
-
const url = getBaseUrl();
|
|
297
|
-
if (url) copyText(url, 'invite-copied-url');
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// Tunnel start/stop
|
|
301
|
-
$('invite-tunnel-start')?.addEventListener('click', async (e) => {
|
|
302
|
-
e.stopPropagation();
|
|
303
|
-
try {
|
|
304
|
-
_tunnelStarting = true;
|
|
305
|
-
render();
|
|
306
|
-
await startTunnel();
|
|
307
|
-
pollForTunnelUrl();
|
|
308
|
-
} catch (err) {
|
|
309
|
-
console.error('[invite] Tunnel start failed:', err);
|
|
310
|
-
_tunnelStarting = false;
|
|
311
|
-
render();
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
$('invite-tunnel-stop')?.addEventListener('click', async (e) => {
|
|
316
|
-
e.stopPropagation();
|
|
317
|
-
try {
|
|
318
|
-
await stopTunnel();
|
|
319
|
-
_tunnelUrl = null;
|
|
320
|
-
_tunnelStarting = false;
|
|
321
|
-
if (_tunnelPollTimer) { clearInterval(_tunnelPollTimer); _tunnelPollTimer = null; }
|
|
322
|
-
render();
|
|
323
|
-
} catch (err) {
|
|
324
|
-
console.error('[invite] Tunnel stop failed:', err);
|
|
325
|
-
}
|
|
326
|
-
});
|
|
336
|
+
// (The tunnel block's own buttons, "Use custom URL" among them, are wired in wireTunnel.)
|
|
327
337
|
|
|
328
338
|
// Proxy save
|
|
329
339
|
$('invite-proxy-save')?.addEventListener('click', async (e) => {
|
|
@@ -862,7 +862,7 @@ export function wireJudgmentsTab(overlay, { toast = () => {}, initial = null } =
|
|
|
862
862
|
const outcome = row.outcome && typeof row.outcome === 'object' ? row.outcome : null;
|
|
863
863
|
const summary = `${clock(row.created_at)} · <code>${escapeHtml(row.surface)}</code>${riders.map(x => ` <span style="${CHIP}">+${escapeHtml(x)}</span>`).join('')} ${kit.th('settings.redesign.judgments.qMs', { origin: escapeHtml(row.origin), model: escapeHtml(row.model || ''), num: num(row.question_count), num2: num(row.latency_ms), num3: num(row.input_tokens) })}${num(row.output_tokens)}${row.cached ? ' · <span style="color:var(--accent)">' + kit.te('settings.redesign.judgments.cached') + '</span>' : ''}${row.error ? ` · <span style="color:#f66">${escapeHtml(row.error)}</span>` : ''}${row.entity_id ? ` · ${memLink(row.entity_id)}` : ''}${row.session_id ? ` · <a href="#" class="jv-session-link" data-session="${attr(row.session_id)}" title="${attr(row.session_id)}${kit.te('settings.redesign.judgments.thisSessionSJudgments')}" style="${LINK};font-family:monospace">${kit.te('settings.redesign.judgments.session')} ${escapeHtml(shortId(row.session_id))}</a>` : ''}${row.project ? ` · ${escapeHtml(row.project)}` : ''}`;
|
|
864
864
|
return `<details class="jv-log-row" data-id="${attr(row.id)}"${state.openLogIds.has(String(row.id)) ? ' open' : ''} style="font-size:12px;border:1px solid var(--s-medium);border-radius:6px;padding:4px 8px;background:var(--s-darker)">
|
|
865
|
-
<summary style="cursor:pointer;list-style:none" title="${attr(row.created_at)}">${summary}</summary>
|
|
865
|
+
<summary style="cursor:pointer;list-style:none" title="${attr(row.created_at)}">${summary}${row.surface === 'budget-split' && budgetSplitLine(row, row.answers || {}).line ? ' · ' + budgetSplitLine(row, row.answers || {}).line : ''}</summary>
|
|
866
866
|
<div class="settings-hint" style="margin:6px 0 2px">${kit.te('settings.redesign.judgments.state')}</div><pre style="margin:0;white-space:pre-wrap;font-size:11px;max-height:160px;overflow:auto">${escapeHtml(row.state_preview || '')}</pre>
|
|
867
867
|
<div class="settings-hint" style="margin:6px 0 2px">${kit.te('settings.redesign.judgments.answers')}</div><pre style="margin:0;white-space:pre-wrap;font-size:11px;max-height:200px;overflow:auto">${escapeHtml(answers || '—')}</pre>
|
|
868
868
|
${outcome ? `<div class="settings-hint" style="margin:6px 0 2px">${kit.te('settings.redesign.judgments.outcome')}</div><pre style="${PRE}">${escapeHtml(JSON.stringify(outcome, null, 2))}</pre>` : ''}
|
|
@@ -1029,7 +1029,16 @@ export function wireJudgmentsTab(overlay, { toast = () => {}, initial = null } =
|
|
|
1029
1029
|
const p = prob(a.goal_met);
|
|
1030
1030
|
return { line: p == null ? '' : flagged(kit.tx('settings.redesign.judgments.pGoalMet', { pct: pct(p) }), p >= knob('loop-goal', 'minConfidence', 0.8)) };
|
|
1031
1031
|
}
|
|
1032
|
+
function budgetSplitLine(row, answers) {
|
|
1033
|
+
const names = { share_claude_code: 'Claude Code', share_codex: 'Codex', share_opencode: 'OpenCode' };
|
|
1034
|
+
const parts = Object.entries(names).filter(([key]) => answers[key]?.type === 'score').map(([key, label]) => {
|
|
1035
|
+
const a = answers[key];
|
|
1036
|
+
return escapeHtml(kit.tx('settings.redesign.judgments.budgetShareScore', { provider: label, score: num(a.score ?? a.value), confidence: pct(a.confidence) }));
|
|
1037
|
+
});
|
|
1038
|
+
return { line: parts.join(' · ') };
|
|
1039
|
+
}
|
|
1032
1040
|
const TIMELINE = {
|
|
1041
|
+
'budget-split': budgetSplitLine,
|
|
1033
1042
|
'prompt-urgency': urgencyLine, 'rerank': rankLine, 'brief-rank': rankLine,
|
|
1034
1043
|
'agent-message': stopLine, 'turn-worth': stopLine, 'claim-check': stopLine,
|
|
1035
1044
|
'edit-stale': staleLine, 'stale-check': staleLine, 'plan-conflict': planLine, 'compact-digest': digestLine, 'loop-goal': loopLine,
|
|
@@ -25,6 +25,8 @@ let _reverseMap = new Map(); // combo string → actionId (for O(1) dispatc
|
|
|
25
25
|
let _recording = null; // { actionId, originalCombo } when recording
|
|
26
26
|
let _pendingBindings = null; // working copy during modal editing
|
|
27
27
|
let _modalOpen = false;
|
|
28
|
+
// Actions that were removed ("toggle-toolbar" was "Hide all toolbars"): a saved key for one is dropped on load.
|
|
29
|
+
const RETIRED_ACTIONS = ['toggle-toolbar'];
|
|
28
30
|
|
|
29
31
|
// ── Combo building ──
|
|
30
32
|
|
|
@@ -426,6 +428,8 @@ export async function initKeybinds() {
|
|
|
426
428
|
} catch {
|
|
427
429
|
_bindings = { ...DEFAULT_KEYBINDS };
|
|
428
430
|
}
|
|
431
|
+
// A key saved for an action that is gone does nothing and must not hold its combo (or show up as a conflict).
|
|
432
|
+
for (const actionId of RETIRED_ACTIONS) delete _bindings[actionId];
|
|
429
433
|
|
|
430
434
|
_reverseMap = buildReverseMap(_bindings);
|
|
431
435
|
|