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,3 +1,8 @@
|
|
|
1
|
+
import { providerAuthSnapshot } from './ui-provider-auth.js';
|
|
2
|
+
import { mountProviderTerminalAuth, providerApiKeyRequest, startProviderTerminalLogin } from './ui-provider-terminal-auth.js';
|
|
3
|
+
import { accountName, accountSwitchPlan, accountText, tabAccountId, serverAccountId } from './account-view.js';
|
|
4
|
+
import { mountAccountMenu } from './account-menu.js';
|
|
5
|
+
import './account-i18n.js';
|
|
1
6
|
import { hostedSidepanelId, sidepanelHost } from './ui-sidepanel-runtime.js';
|
|
2
7
|
// ═══════════════════════════════════════════
|
|
3
8
|
// SynaBun — Claude Code Panel (Main Area)
|
|
@@ -7,14 +12,18 @@ import { hostedSidepanelId, sidepanelHost } from './ui-sidepanel-runtime.js';
|
|
|
7
12
|
import { storage } from './storage.js';
|
|
8
13
|
import { fetchBlobNamespace, putBlob, deleteBlob, flushBlobs } from './blob-store.js';
|
|
9
14
|
import { state, emit, on } from './state.js';
|
|
15
|
+
import { forgetGreeting, mountGreeting } from './greeting/greeting-card.js';
|
|
10
16
|
import { fetchClaudeSessions, fetchBrowserSessions, searchSessions } from './api.js';
|
|
11
17
|
import { createFrameRenderer } from './utils.js';
|
|
12
18
|
import { notify, NOTIF_TYPE } from './ui-notifications.js';
|
|
13
19
|
import { registerSidepanel, setSidepanelVisible, syncSidepanelLayout, focusSidepanel, openAnotherSidepanelSession, isHostedSessionFocused } from './ui-sidepanel-windows.js';
|
|
14
|
-
import {
|
|
20
|
+
import { mountCliBanner } from './ui-cli-banner.js';
|
|
15
21
|
import { nativeLoopWindowId } from './ui-native-window-id.js';
|
|
16
22
|
import { createStickyScrollController } from './ui-scroll-follow.js';
|
|
17
23
|
import { requestGeneratedSessionTitle } from './session-title.js';
|
|
24
|
+
import { wireFileLinks } from './ui-file-links.js';
|
|
25
|
+
import { WORKER_END_CLASS, backToAssistant, buildWorkerEndCard, endWorkerRunOnClose, forgetWorkerEnd, trackWorkerEnd, updateWorkerEndBusy } from './ui-worker-end.js';
|
|
26
|
+
import { isDispatchedRun, isEndOfRunAbort } from './worker-end.js';
|
|
18
27
|
// ── cp/ feature modules (SDK-engine CLI parity: diffs, agents, bash, perms, statusline) ──
|
|
19
28
|
import { setCpCtx } from './cp/cp-ctx.js';
|
|
20
29
|
import { buildDiffCard, buildDiffPreviewEl, finalizeDiffCard } from './cp/cp-diff.js';
|
|
@@ -24,7 +33,7 @@ import { buildAgentCard, ensureAgentScope, noteAgentActivity, updateAgentTodoBad
|
|
|
24
33
|
import { renderPermissionCard, renderPlanApprovalCard, renderElicitationCard, decorateAskCard, askAnnotations, markAskAnswered, PERMISSION_MODES, MODE_LABELS } from './cp/cp-permissions.js';
|
|
25
34
|
import { normalizeSession, changedStartSettings, sessionFlags, sessionRows, fastModeSupported, fastModeReason, mergeSessionModels, parseMcpServerLines, formatMcpServerLines } from './cp/cp-session-model.js';
|
|
26
35
|
import { renderSessionSettingsCard } from './cp/cp-session-settings.js';
|
|
27
|
-
import { describeOrigin, reconcileTasks, adoptLiveTasks, describeHistorySystemRow, workEndedByRestart } from './cp/cp-tasks-model.js';
|
|
36
|
+
import { describeOrigin, reconcileTasks, adoptLiveTasks, describeHistorySystemRow, workEndedByRestart, isTaskRunning } from './cp/cp-tasks-model.js';
|
|
28
37
|
import { renderTasksCard } from './cp/cp-tasks.js';
|
|
29
38
|
import { sessionListLabel, collectTags, tagSession as tagClaudeSession, sessionActionsAvailable, sessionOpsSupported, labelledSessionIds, mergeSessionSearch, writeSessionTitle, forkSession as forkClaudeSession, deleteSession as deleteClaudeSession, fetchSubagentMessages, forkTitle, entryBefore, promptText, removeFrom, sessionRowParts, fillSelectOptions } from './cp/cp-sessions.js';
|
|
30
39
|
import { contextCard, usageCard, mcpRows, rewindPreviewText, rewindResultText } from './cp/cp-usage-model.js';
|
|
@@ -162,9 +171,8 @@ function activeTab() { return _tabs[_activeTabIdx] || null; }
|
|
|
162
171
|
let _browserEmbed = null; // { sessionId, ws, canvas, ctx, urlBar, container }
|
|
163
172
|
let _browserEmbedVisible = false;
|
|
164
173
|
|
|
165
|
-
// ── CLI
|
|
166
|
-
let
|
|
167
|
-
let _cliUnsub = null;
|
|
174
|
+
// ── CLI status (claude binary detection): the banner controller, ui-cli-banner.js ──
|
|
175
|
+
let _cliBanner = null;
|
|
168
176
|
|
|
169
177
|
// Marked.js (lazy loaded)
|
|
170
178
|
let _marked = null;
|
|
@@ -304,7 +312,7 @@ const SLASH_COMMANDS = [
|
|
|
304
312
|
{ name: 'plugin', desc: 'List active plugins and skills', kind: 'info' },
|
|
305
313
|
{ name: 'status', desc: 'Show session status summary', kind: 'info' },
|
|
306
314
|
{ name: 'cost', desc: 'Toggle the cost widget', kind: 'action' },
|
|
307
|
-
{ name: 'login', desc: '
|
|
315
|
+
{ name: 'login', desc: 'Sign this tab\'s Claude account in (opens the account menu)', kind: 'action' },
|
|
308
316
|
{ name: 'logout', desc: 'Open Claude account sign-out', kind: 'action' },
|
|
309
317
|
{ name: 'plan', desc: 'Toggle plan mode', kind: 'action' },
|
|
310
318
|
{ name: 'btw', desc: 'Add context while Claude is processing (Shift+Enter)', kind: 'info' },
|
|
@@ -318,7 +326,7 @@ const SLASH_COMMANDS = [
|
|
|
318
326
|
{ name: 'reload-plugins', desc: 'Reload plugins without restarting the session', kind: 'action', needs: 'reload_plugins' },
|
|
319
327
|
{ name: 'tasks', desc: 'Background work of this tab: running tasks (with stop) and scheduled wakeups', kind: 'info' },
|
|
320
328
|
{ name: 'usage', desc: 'This session\'s cost and the plan\'s usage limits', kind: 'info', needs: 'session_requests' },
|
|
321
|
-
{ name: 'account', desc: 'Choose the Claude account this tab
|
|
329
|
+
{ name: 'account', desc: 'Choose and manage the Claude account of this tab (the header account menu)', kind: 'action', needs: 'accounts' },
|
|
322
330
|
{ name: 'effective-settings', desc: 'The Claude Code settings in effect here, and the file each comes from', kind: 'info', needs: 'settings_view' },
|
|
323
331
|
];
|
|
324
332
|
|
|
@@ -540,72 +548,7 @@ function injectStyles() {
|
|
|
540
548
|
.cp-messages:has(.msg) .cp-empty,
|
|
541
549
|
.cp-messages:has(.msg-status) .cp-empty { display: none; }
|
|
542
550
|
|
|
543
|
-
/* ── CLI
|
|
544
|
-
.cp-cli-banner {
|
|
545
|
-
flex-shrink: 0;
|
|
546
|
-
display: grid;
|
|
547
|
-
grid-template-columns: auto 1fr auto;
|
|
548
|
-
gap: 10px;
|
|
549
|
-
align-items: center;
|
|
550
|
-
margin: 6px 8px 0;
|
|
551
|
-
padding: 10px 12px;
|
|
552
|
-
border: 1px solid rgba(255,180,80,0.45);
|
|
553
|
-
border-radius: 8px;
|
|
554
|
-
background: rgba(255,180,80,0.08);
|
|
555
|
-
color: rgba(255,235,200,0.92);
|
|
556
|
-
font-size: 11px;
|
|
557
|
-
line-height: 1.4;
|
|
558
|
-
pointer-events: auto;
|
|
559
|
-
position: relative;
|
|
560
|
-
z-index: 5;
|
|
561
|
-
}
|
|
562
|
-
.cp-cli-banner-icon {
|
|
563
|
-
width: 22px; height: 22px;
|
|
564
|
-
display: flex; align-items: center; justify-content: center;
|
|
565
|
-
border-radius: 50%;
|
|
566
|
-
background: rgba(255,180,80,0.25);
|
|
567
|
-
color: rgba(255,210,140,1);
|
|
568
|
-
font-weight: 700;
|
|
569
|
-
}
|
|
570
|
-
.cp-cli-banner-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
571
|
-
.cp-cli-banner-title {
|
|
572
|
-
font-size: 12px; font-weight: 600;
|
|
573
|
-
color: rgba(255,210,140,0.95);
|
|
574
|
-
}
|
|
575
|
-
.cp-cli-banner-body {
|
|
576
|
-
font-size: 11px;
|
|
577
|
-
color: rgba(255,255,255,0.7);
|
|
578
|
-
word-break: break-word;
|
|
579
|
-
}
|
|
580
|
-
.cp-cli-banner-body code {
|
|
581
|
-
padding: 1px 5px;
|
|
582
|
-
background: rgba(0,0,0,0.35);
|
|
583
|
-
border-radius: 3px;
|
|
584
|
-
font-size: 10.5px;
|
|
585
|
-
color: rgba(255,255,255,0.85);
|
|
586
|
-
}
|
|
587
|
-
.cp-cli-banner-actions { display: flex; gap: 6px; }
|
|
588
|
-
.cp-cli-banner-link, .cp-cli-banner-recheck {
|
|
589
|
-
display: inline-flex; align-items: center; gap: 4px;
|
|
590
|
-
padding: 4px 9px;
|
|
591
|
-
font-size: 11px;
|
|
592
|
-
font-weight: 500;
|
|
593
|
-
border-radius: 4px;
|
|
594
|
-
border: 1px solid rgba(255,255,255,0.2);
|
|
595
|
-
background: rgba(255,255,255,0.05);
|
|
596
|
-
color: rgba(255,255,255,0.9);
|
|
597
|
-
text-decoration: none;
|
|
598
|
-
cursor: pointer;
|
|
599
|
-
user-select: none;
|
|
600
|
-
font-family: inherit;
|
|
601
|
-
}
|
|
602
|
-
.cp-cli-banner-link:hover, .cp-cli-banner-recheck:hover {
|
|
603
|
-
background: rgba(255,255,255,0.12);
|
|
604
|
-
border-color: rgba(255,255,255,0.4);
|
|
605
|
-
}
|
|
606
|
-
.cp-cli-banner-recheck:disabled { opacity: 0.5; cursor: default; }
|
|
607
|
-
.claude-panel.cp-cli-blocked .cp-send { opacity: 0.4 !important; cursor: not-allowed !important; }
|
|
608
|
-
.claude-panel.cp-cli-blocked .cp-input { opacity: 0.7; }
|
|
551
|
+
/* ── CLI banner (ui-cli-banner.js): its rules are in cp/cp-styles.js ── */
|
|
609
552
|
|
|
610
553
|
/* ── Browser embed (live screencast inside panel) ── */
|
|
611
554
|
.cp-browser-embed {
|
|
@@ -2928,6 +2871,7 @@ function newTabState(sessionId = null, label = 'New chat', id = null) {
|
|
|
2928
2871
|
automationRunId: null,
|
|
2929
2872
|
automationActive: false,
|
|
2930
2873
|
automationOwnerId: null,
|
|
2874
|
+
releasedRunId: null, // the ended run this tab showed before the user continued it by hand
|
|
2931
2875
|
};
|
|
2932
2876
|
}
|
|
2933
2877
|
|
|
@@ -2970,6 +2914,7 @@ function connectTab(tab) {
|
|
|
2970
2914
|
ws.addEventListener('open', () => {
|
|
2971
2915
|
if (tab.ws !== ws) return;
|
|
2972
2916
|
clearTimeout(tab.reconnectTimer);
|
|
2917
|
+
_ensureClaudeTerminalAuth(tab);
|
|
2973
2918
|
connectionOpened(tab); // no statement of the tab's mode was made on this socket yet
|
|
2974
2919
|
// Reclaim this tab's server session if it outlived the old socket — a turn in
|
|
2975
2920
|
// flight, a permission card, background agents or a scheduled wakeup. The
|
|
@@ -3041,6 +2986,7 @@ function switchTab(idx) {
|
|
|
3041
2986
|
tab.messagesEl._exitToken = (tab.messagesEl._exitToken || 0) + 1; // cancel pending exits
|
|
3042
2987
|
_attachMessagesEl(tab);
|
|
3043
2988
|
tab.messagesEl.style.display = '';
|
|
2989
|
+
_ensureClaudeTerminalAuth(tab);
|
|
3044
2990
|
tab.scrollController?.setActive(true);
|
|
3045
2991
|
tab.messagesEl.classList.remove('cp-tab-exit');
|
|
3046
2992
|
tab.messagesEl.classList.add('cp-tab-enter');
|
|
@@ -3122,6 +3068,7 @@ function switchTab(idx) {
|
|
|
3122
3068
|
_setCompactingUI(!!tab.compacting);
|
|
3123
3069
|
populateViewDropdown(_panel?.querySelector('#cp-view'), tab);
|
|
3124
3070
|
populateModeDropdown(_panel?.querySelector('#cp-mode'), tab);
|
|
3071
|
+
_renderAccountMenu();
|
|
3125
3072
|
_paintTemporary(tab);
|
|
3126
3073
|
saveTabs();
|
|
3127
3074
|
}
|
|
@@ -3130,17 +3077,22 @@ function closeTab(idx, { detachAutomation = false } = {}) {
|
|
|
3130
3077
|
if (idx < 0 || idx >= _tabs.length) return;
|
|
3131
3078
|
const tab = _tabs[idx];
|
|
3132
3079
|
if (tab.automationRunId && !detachAutomation) {
|
|
3080
|
+
const runId = tab.automationRunId;
|
|
3133
3081
|
window.dispatchEvent(new CustomEvent('native-loop:dismissed', {
|
|
3134
|
-
detail: { runId
|
|
3082
|
+
detail: { runId },
|
|
3135
3083
|
}));
|
|
3136
|
-
|
|
3084
|
+
// A worker that finished its task is completed; any other run is stopped.
|
|
3085
|
+
endWorkerRunOnClose(runId, () => fetch('/api/loop/stop', {
|
|
3137
3086
|
method: 'POST',
|
|
3138
3087
|
headers: { 'Content-Type': 'application/json' },
|
|
3139
|
-
body: JSON.stringify({ runId
|
|
3140
|
-
}).catch(() => {});
|
|
3088
|
+
body: JSON.stringify({ runId }),
|
|
3089
|
+
}).catch(() => {}), { busy: hasLiveBackgroundWork(tab) });
|
|
3141
3090
|
}
|
|
3091
|
+
if (tab.automationRunId) forgetWorkerEnd(tab.automationRunId);
|
|
3142
3092
|
flushSessionSnapshotSave(tab);
|
|
3143
3093
|
recordHookEvent(tab, 'SessionEnd', tab.sessionId || '(new)');
|
|
3094
|
+
tab.authView?.dispose();
|
|
3095
|
+
tab.terminalAuthView?.dispose();
|
|
3144
3096
|
tab.closed = true;
|
|
3145
3097
|
tab.titleRequestController?.abort();
|
|
3146
3098
|
tab.titleRequestController = null;
|
|
@@ -3264,7 +3216,7 @@ function saveTabs() {
|
|
|
3264
3216
|
try {
|
|
3265
3217
|
// A temporary tab is never written: not the tab, its label, its queue or its session id.
|
|
3266
3218
|
const kept = persistableTabs(_tabs, _activeTabIdx);
|
|
3267
|
-
const localTabs = kept.tabs.map(t => ({ id: t.id, sessionId: t.sessionId, label: t.label, titleState: t.titleState === 'generating' ? 'default' : (t.titleState || 'default'), sessionCost: t.sessionCost || 0, running: t.running || false, project: t.project || '', model: t.model || '', effort: t.effort || 'off', planMode: t.planMode || false, ...savedMode(t), toolPolicy: t.toolPolicy || 'full', accountId: t.accountId || '', session: normalizeSession(t.session), transcriptAt: t.transcriptAt || null, planFilePath: t.planFilePath || '', conversation: t.conversation || '', queue: t.queue || [], queuePaused: t.queuePaused || false, automationRunId: t.automationRunId || null, automationActive: !!t.automationActive, automationOwnerId: t.automationOwnerId || null }));
|
|
3219
|
+
const localTabs = kept.tabs.map(t => ({ id: t.id, sessionId: t.sessionId, label: t.label, titleState: t.titleState === 'generating' ? 'default' : (t.titleState || 'default'), sessionCost: t.sessionCost || 0, running: t.running || false, project: t.project || '', model: t.model || '', effort: t.effort || 'off', planMode: t.planMode || false, ...savedMode(t), toolPolicy: t.toolPolicy || 'full', accountId: t.accountId || '', session: normalizeSession(t.session), transcriptAt: t.transcriptAt || null, planFilePath: t.planFilePath || '', conversation: t.conversation || '', queue: t.queue || [], queuePaused: t.queuePaused || false, automationRunId: t.automationRunId || null, automationActive: !!t.automationActive, automationOwnerId: t.automationOwnerId || null, releasedRunId: t.releasedRunId || null }));
|
|
3268
3220
|
const localRunIds = new Set(localTabs.map((tab) => tab.automationRunId).filter(Boolean));
|
|
3269
3221
|
let foreignAutomationTabs = [];
|
|
3270
3222
|
try {
|
|
@@ -3406,6 +3358,7 @@ function restoreTabs() {
|
|
|
3406
3358
|
if (t && saved.automationRunId) t.automationRunId = saved.automationRunId;
|
|
3407
3359
|
if (t && saved.automationRunId) t.automationActive = !!saved.automationActive;
|
|
3408
3360
|
if (t && saved.automationRunId) t.automationOwnerId = saved.automationOwnerId || null;
|
|
3361
|
+
if (t && saved.releasedRunId && !saved.automationRunId) t.releasedRunId = saved.releasedRunId;
|
|
3409
3362
|
}
|
|
3410
3363
|
if (_tabs.length) {
|
|
3411
3364
|
switchTab(Math.min(data.activeIdx || 0, _tabs.length - 1));
|
|
@@ -4470,7 +4423,7 @@ function writeSessionSnapshot(tab) {
|
|
|
4470
4423
|
const sid = tab?.sessionId || null;
|
|
4471
4424
|
const $msgs = tab?.messagesEl || null;
|
|
4472
4425
|
if (!sid || !$msgs) return;
|
|
4473
|
-
const html = $msgs
|
|
4426
|
+
const html = providerAuthSnapshot($msgs);
|
|
4474
4427
|
if (!html.trim()) return;
|
|
4475
4428
|
// Skip snapshot if the transcript only contains the empty-state placeholder
|
|
4476
4429
|
if ($msgs.children.length === 1 && $msgs.firstElementChild?.classList?.contains('cp-empty')) return;
|
|
@@ -5125,7 +5078,7 @@ function _contextMenuData(tab, { full = false } = {}) {
|
|
|
5125
5078
|
folder: tab.init?.cwd || tab.project || '',
|
|
5126
5079
|
// The mode as the project bar words it (it knows Bypass and "from settings").
|
|
5127
5080
|
mode: ($mode && !$mode.hidden && $mode.querySelector('.cp-dd-label')?.textContent) || tab.permissionMode || '',
|
|
5128
|
-
account: [tab.accountInfo?.email, tab.accountInfo?.organization].filter(Boolean).join(' · '),
|
|
5081
|
+
account: [tab.accountInfo?.authMethod === 'apiKey' ? 'API key' : tab.accountInfo?.email, tab.accountInfo?.organization].filter(Boolean).join(' · '),
|
|
5129
5082
|
flags: sessionFlags(tab.session, { toolPolicy: tab.toolPolicy, fastModeState: tab.fastModeState, account: tab.accountId }),
|
|
5130
5083
|
limit: tab.rateLimit?.text || '',
|
|
5131
5084
|
backgroundTasks: (tab.backgroundWork || []).length,
|
|
@@ -5314,6 +5267,7 @@ function _processTabMsg(tab, msg) {
|
|
|
5314
5267
|
if (tab === activeTab()) {
|
|
5315
5268
|
renderStatusline(tab);
|
|
5316
5269
|
populateModeDropdown(_panel?.querySelector('#cp-mode'), tab);
|
|
5270
|
+
_renderAccountMenu();
|
|
5317
5271
|
}
|
|
5318
5272
|
break;
|
|
5319
5273
|
}
|
|
@@ -5537,6 +5491,8 @@ function _processTabMsg(tab, msg) {
|
|
|
5537
5491
|
break;
|
|
5538
5492
|
}
|
|
5539
5493
|
appendError(tab, msg.message);
|
|
5494
|
+
// The tab's account is gone, or belongs to another conversation: the accounts card is where to choose.
|
|
5495
|
+
if (msg.code === 'account_unavailable' || msg.code === 'account_change_refused') _showAccounts(tab);
|
|
5540
5496
|
notify('panel', NOTIF_TYPE.ERROR, tab.label || 'Claude Code', { tabId: tab.id });
|
|
5541
5497
|
if (typeof msg.message === 'string' && /Claude CLI not found|ENOENT/i.test(msg.message)) {
|
|
5542
5498
|
flagClaudeCliInstallFailure(msg.message);
|
|
@@ -7445,7 +7401,57 @@ function handleControlRequest(tab, msg) {
|
|
|
7445
7401
|
// What a query tells the bridge about this tab's session: the permission mode
|
|
7446
7402
|
// (or that the user's own settings should pick it), the tool policy, and what
|
|
7447
7403
|
// this panel can render. Keys a server that predates them ignores.
|
|
7404
|
+
// ── Greeting (shared/greeting/, lib/greeting/) ──
|
|
7405
|
+
// What SynaBun says when a person comes back and opens a new chat: one or two sentences in the
|
|
7406
|
+
// empty state, written by SynaBun ahead of time (this session's model never greets). Only for a
|
|
7407
|
+
// tab that holds no conversation yet: never a resumed session, a temporary chat or a tab showing
|
|
7408
|
+
// an automation run (hence the short wait: those are marked right after the tab is made). The
|
|
7409
|
+
// server decides whether this opening is a return worth greeting; an older server answers nothing.
|
|
7410
|
+
// Asked from _paintTemporary(), which runs wherever the conversation area is rebuilt. Nothing of it
|
|
7411
|
+
// is kept on the tab object (what a tab carries over, and what is saved of it, is listed elsewhere).
|
|
7412
|
+
const _greetingOf = new WeakMap(); // tab → { seq, host, greeting: { id, session } | null }
|
|
7413
|
+
function _greetingState(tab) {
|
|
7414
|
+
let held = _greetingOf.get(tab);
|
|
7415
|
+
if (!held) { held = { seq: 0, host: null, greeting: null }; _greetingOf.set(tab, held); }
|
|
7416
|
+
return held;
|
|
7417
|
+
}
|
|
7418
|
+
function _offerGreetingSoon(tab) {
|
|
7419
|
+
if (!tab) return;
|
|
7420
|
+
setTimeout(() => { try { _offerGreeting(tab); } catch { /* a tab always opens */ } }, 300);
|
|
7421
|
+
}
|
|
7422
|
+
function _offerGreeting(tab) {
|
|
7423
|
+
if (!_tabs.includes(tab) || tab.sessionId || tab.temporary || tab.automationRunId || tab.automationActive || tab.running) return;
|
|
7424
|
+
const host = tab.messagesEl?.querySelector(':scope > .cp-empty');
|
|
7425
|
+
if (!host || host.dataset.greetingAsked === '1') return;
|
|
7426
|
+
host.dataset.greetingAsked = '1';
|
|
7427
|
+
const held = _greetingState(tab);
|
|
7428
|
+
// The conversation area was rebuilt: a new conversation in the same tab is a new opening.
|
|
7429
|
+
if (held.host && held.host !== host) { held.seq += 1; held.greeting = null; }
|
|
7430
|
+
held.host = host;
|
|
7431
|
+
const session = `${tab.id}.${held.seq}`;
|
|
7432
|
+
const cwd = tab.project || ddGetValue(_panel?.querySelector('#cp-project')) || '';
|
|
7433
|
+
mountGreeting(host, {
|
|
7434
|
+
surface: 'claude-panel', session, cwd,
|
|
7435
|
+
onOpenMemory: (id) => { if (id) emit('memory:open', { id }); },
|
|
7436
|
+
isCurrent: () => !tab.sessionId && !tab.temporary && !tab.automationRunId && held.host === host && tab.messagesEl?.contains(host),
|
|
7437
|
+
}).then((greeting) => {
|
|
7438
|
+
if (held.host === host) held.greeting = greeting ? { id: greeting.id, session } : null;
|
|
7439
|
+
}).catch(() => {});
|
|
7440
|
+
}
|
|
7441
|
+
|
|
7442
|
+
// The greeting a chat opened with goes back once, with its first prompt: the bridge tells the model
|
|
7443
|
+
// what was said (capability 'greeting'). A temporary chat names nothing, so it takes none.
|
|
7444
|
+
function _echoGreeting(tab, msg) {
|
|
7445
|
+
const held = msg.type === 'query' ? _greetingOf.get(tab) : null;
|
|
7446
|
+
if (!held?.greeting?.id) return;
|
|
7447
|
+
if (hasCapability(tab, 'greeting') && !tab.temporary) msg.greetingId = held.greeting.id;
|
|
7448
|
+
forgetGreeting('claude-panel', held.greeting.session);
|
|
7449
|
+
held.greeting = null;
|
|
7450
|
+
}
|
|
7451
|
+
|
|
7448
7452
|
function _applySessionOptions(tab, msg) {
|
|
7453
|
+
// The greeting this chat opened with goes back once, with its first prompt.
|
|
7454
|
+
_echoGreeting(tab, msg);
|
|
7449
7455
|
// The tab's own mode (statedMode() in cp/cp-permission-model.js: Bypass only
|
|
7450
7456
|
// as the user's recorded pick). A tab that never picked one leaves it to the
|
|
7451
7457
|
// user's Claude Code settings (permissions.defaultMode).
|
|
@@ -7471,6 +7477,8 @@ function _applySessionOptions(tab, msg) {
|
|
|
7471
7477
|
function _paintTemporary(tab) {
|
|
7472
7478
|
if (!tab) return;
|
|
7473
7479
|
paintTemporary(tab, { capable: hasCapability(tab, TEMPORARY_CAPABILITY), onToggle: (on) => _chooseTemporary(tab, on) });
|
|
7480
|
+
// The conversation area was (re)built: a new chat may open with SynaBun's greeting.
|
|
7481
|
+
_offerGreetingSoon(tab);
|
|
7474
7482
|
}
|
|
7475
7483
|
|
|
7476
7484
|
// The user's choice on a new tab. A process kept ready for the other kind of
|
|
@@ -7506,6 +7514,7 @@ function _afterTemporary(tab, sid, label) {
|
|
|
7506
7514
|
for (const waiting of tab._sessionRequests?.values() || []) { clearTimeout(waiting.timer); try { waiting.reject(new Error('The temporary chat has ended.')); } catch {} }
|
|
7507
7515
|
// An open history search lists its prompts.
|
|
7508
7516
|
if (tab === activeTab()) _panel?.querySelector('.cp-rsearch')?.remove();
|
|
7517
|
+
tab.terminalAuthView?.dispose();
|
|
7509
7518
|
tabAfterTemporary(tab, newTabState(sid, label || 'New chat', tab.id));
|
|
7510
7519
|
}
|
|
7511
7520
|
|
|
@@ -8556,47 +8565,149 @@ function _showUsage(tab) {
|
|
|
8556
8565
|
}).catch(err => appendInfoCard(tab, { title: 'Usage', kind: 'info', body: err.message }));
|
|
8557
8566
|
}
|
|
8558
8567
|
|
|
8559
|
-
//
|
|
8568
|
+
// ── Claude accounts ──
|
|
8569
|
+
// Every account and its state come from the server (lib/claude-accounts.js
|
|
8570
|
+
// describe(): its mode, whether it is signed in, its identity: an email or a
|
|
8571
|
+
// masked key, never a key); account-view.js decides the words. One list for
|
|
8572
|
+
// every tab, and one place to choose and manage accounts: the account menu in
|
|
8573
|
+
// the header (account-menu.js, the same component as the Codex panel's).
|
|
8574
|
+
// /account, /login and the sign-in screen's "Other accounts…" open it.
|
|
8575
|
+
// `claude:accounts-changed` (any window, any surface) reloads the list.
|
|
8560
8576
|
// A conversation belongs to the account it started under (its transcript lives
|
|
8561
|
-
// in that account's config directory)
|
|
8562
|
-
//
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8577
|
+
// in that account's config directory): a tab with one opens another account in
|
|
8578
|
+
// a new chat, and the tab's own account changes only before its first message.
|
|
8579
|
+
let _claudeAccountRows = null;
|
|
8580
|
+
let _claudeAccountsLoad = null;
|
|
8581
|
+
let _claudeAccountsError = '';
|
|
8582
|
+
let _accountMenu = null;
|
|
8583
|
+
function _loadClaudeAccounts({ force = false, refresh = false } = {}) {
|
|
8584
|
+
if (!force && !refresh && _claudeAccountRows) return Promise.resolve(_claudeAccountRows);
|
|
8585
|
+
if (_claudeAccountsLoad && !refresh) return _claudeAccountsLoad;
|
|
8586
|
+
const load = fetch(`/api/claude/accounts${refresh ? '?refresh=true' : ''}`, { cache: 'no-store' })
|
|
8587
|
+
.then(r => r.ok ? r.json() : Promise.reject(new Error(accountText('readFailed'))))
|
|
8588
|
+
.then((d) => {
|
|
8589
|
+
_claudeAccountRows = Array.isArray(d?.accounts) ? d.accounts : [];
|
|
8590
|
+
_claudeAccountsError = '';
|
|
8591
|
+
_claudeAccountsChanged();
|
|
8592
|
+
return _claudeAccountRows;
|
|
8593
|
+
})
|
|
8594
|
+
.catch((error) => { _claudeAccountsError = accountText('readFailed'); _claudeAccountsChanged(); throw error; })
|
|
8595
|
+
.finally(() => { if (_claudeAccountsLoad === load) _claudeAccountsLoad = null; });
|
|
8596
|
+
_claudeAccountsLoad = load;
|
|
8597
|
+
return load;
|
|
8598
|
+
}
|
|
8599
|
+
function _claudeAccountRow(id) {
|
|
8600
|
+
return (_claudeAccountRows || []).find(row => row.id === serverAccountId(id)) || null;
|
|
8601
|
+
}
|
|
8602
|
+
function _claudeAccountsChanged() {
|
|
8603
|
+
_renderAccountMenu();
|
|
8604
|
+
}
|
|
8605
|
+
|
|
8606
|
+
// The header account menu: the active tab's account and what it runs on, every account, and their
|
|
8607
|
+
// management (add, sign in with Claude, an API key, the "Uses" switch, sign out, rename, remove).
|
|
8608
|
+
function _mountAccountMenu() {
|
|
8609
|
+
if (_accountMenu || !_panel) return _accountMenu;
|
|
8610
|
+
const actions = _panel.querySelector('.cp-header-actions');
|
|
8611
|
+
if (!actions) return null;
|
|
8612
|
+
const path = id => `/api/claude/accounts/${encodeURIComponent(id)}`;
|
|
8613
|
+
_accountMenu = mountAccountMenu({
|
|
8614
|
+
provider: 'claude', container: actions, before: actions.firstChild, layer: () => _panel,
|
|
8615
|
+
read: () => {
|
|
8616
|
+
const tab = activeTab();
|
|
8617
|
+
return {
|
|
8618
|
+
rows: _claudeAccountRows || [], currentId: tab?.accountId || '', hasConversation: !!tab?.sessionId,
|
|
8619
|
+
available: !!tab && hasCapability(tab, 'accounts') && !tab.automationActive,
|
|
8620
|
+
busy: !!(tab?.running || tab?.automationActive), loading: !_claudeAccountRows, error: _claudeAccountsError,
|
|
8621
|
+
};
|
|
8622
|
+
},
|
|
8623
|
+
actions: {
|
|
8624
|
+
load: ({ refresh }) => _loadClaudeAccounts({ force: true, refresh }),
|
|
8625
|
+
pick: (id) => { const tab = activeTab(); if (tab) _pickAccount(tab, id); },
|
|
8626
|
+
add: async () => (await _claudeAuthRequest('/api/claude/accounts', { method: 'POST', body: '{}' })).account,
|
|
8627
|
+
signIn: (id) => startProviderTerminalLogin('claude', id, `Claude sign-in · ${_claudeAccountRow(id)?.label || id}`),
|
|
8628
|
+
saveKey: (id, key) => providerApiKeyRequest('claude', id, key),
|
|
8629
|
+
setMode: (id, mode) => _claudeAuthRequest(path(id), { method: 'PATCH', body: JSON.stringify({ mode }) }),
|
|
8630
|
+
signOut: (id, credential) => _claudeAuthRequest(`${path(id)}/auth/logout`, { method: 'POST', body: JSON.stringify({ credential }) }),
|
|
8631
|
+
rename: (id, label) => _claudeAuthRequest(path(id), { method: 'PATCH', body: JSON.stringify({ label }) }),
|
|
8632
|
+
remove: (id) => _claudeAuthRequest(path(id), { method: 'DELETE' }),
|
|
8633
|
+
},
|
|
8634
|
+
});
|
|
8635
|
+
return _accountMenu;
|
|
8636
|
+
}
|
|
8637
|
+
function _renderAccountMenu() {
|
|
8638
|
+
if (!_accountMenu) return;
|
|
8639
|
+
const tab = activeTab();
|
|
8640
|
+
if (tab && hasCapability(tab, 'accounts') && !_claudeAccountRows && !_claudeAccountsLoad) _loadClaudeAccounts().catch(() => {});
|
|
8641
|
+
_accountMenu.render();
|
|
8642
|
+
}
|
|
8643
|
+
|
|
8644
|
+
// Pick an account for a tab: now when it has no conversation yet, else in a new chat (a new tab).
|
|
8645
|
+
function _pickAccount(tab, id) {
|
|
8646
|
+
const rows = _claudeAccountRows || [];
|
|
8647
|
+
const plan = accountSwitchPlan({ rows, currentId: tab.accountId || '', targetId: id, hasConversation: !!tab.sessionId });
|
|
8648
|
+
const target = _claudeAccountRow(id);
|
|
8649
|
+
if (plan.effect === 'missing' || plan.effect === 'same') { appendStatus(tab, plan.message); return; }
|
|
8650
|
+
if (plan.effect === 'next-chat') {
|
|
8651
|
+
if (_tabs.length >= MAX_TABS) { appendStatus(tab, `${plan.message} ${accountText('tooManyTabs')}`); return; }
|
|
8652
|
+
const fresh = createTab(null, 'New chat');
|
|
8653
|
+
fresh.accountId = tabAccountId(id);
|
|
8654
|
+
_ensureClaudeTerminalAuth(fresh);
|
|
8655
|
+
saveTabs();
|
|
8656
|
+
if (fresh === activeTab()) _renderAccountMenu();
|
|
8657
|
+
appendStatus(fresh, accountText('newChatUnder', { label: target ? accountName(target) : id }));
|
|
8658
|
+
return;
|
|
8659
|
+
}
|
|
8660
|
+
tab.accountId = tabAccountId(id);
|
|
8661
|
+
_ensureClaudeTerminalAuth(tab);
|
|
8662
|
+
saveTabs();
|
|
8663
|
+
if (tab === activeTab()) { renderStatusline(tab); _renderAccountMenu(); }
|
|
8664
|
+
appendStatus(tab, plan.message);
|
|
8665
|
+
}
|
|
8666
|
+
|
|
8667
|
+
// /account (and /login, and the sign-in screen's "Other accounts…"): the header account menu.
|
|
8668
|
+
// `/account <name>` picks that account at once; `manage` opens one account's management.
|
|
8669
|
+
function _showAccounts(tab, wanted = '', { manage = '' } = {}) {
|
|
8670
|
+
if (!hasCapability(tab, 'accounts')) { appendStatus(tab, accountText('needsServer')); return; }
|
|
8671
|
+
if (wanted) {
|
|
8672
|
+
_loadClaudeAccounts({ force: true }).then((accounts) => {
|
|
8578
8673
|
const w = wanted.trim().toLowerCase();
|
|
8579
|
-
const match = accounts.find(a => a.id.toLowerCase() === w || String(a.label || '').toLowerCase() === w || String(a.email || '').toLowerCase() === w);
|
|
8674
|
+
const match = accounts.find(a => a.id.toLowerCase() === w || String(a.label || '').toLowerCase() === w || String(a.subscription?.email || '').toLowerCase() === w);
|
|
8580
8675
|
if (!match) { appendStatus(tab, `No account "${wanted}". Use /account to list them.`); return; }
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8676
|
+
_pickAccount(tab, match.id);
|
|
8677
|
+
}).catch(() => appendStatus(tab, accountText('readFailed')));
|
|
8678
|
+
return;
|
|
8679
|
+
}
|
|
8680
|
+
if (tab !== activeTab()) return;
|
|
8681
|
+
_mountAccountMenu()?.open(manage ? { manage } : {});
|
|
8682
|
+
}
|
|
8683
|
+
|
|
8684
|
+
async function _claudeAuthRequest(url, options = {}) {
|
|
8685
|
+
const response = await fetch(url, { ...options, cache: 'no-store', headers: { 'Content-Type': 'application/json' } });
|
|
8686
|
+
const data = await response.json().catch(() => ({}));
|
|
8687
|
+
if (!response.ok || data.error) throw new Error(data.error || 'Claude authentication request failed.');
|
|
8688
|
+
return data;
|
|
8689
|
+
}
|
|
8690
|
+
|
|
8691
|
+
function _ensureClaudeTerminalAuth(tab) {
|
|
8692
|
+
const accountId = tab.accountId || 'default';
|
|
8693
|
+
if (tab.closed || !tab.messagesEl) return;
|
|
8694
|
+
if (tab.terminalAuthView && tab.terminalAuthAccount === accountId) { void tab.terminalAuthView.refresh(); return; }
|
|
8695
|
+
tab.terminalAuthView?.dispose();
|
|
8696
|
+
tab.terminalAuthAccount = accountId;
|
|
8697
|
+
const named = accountId !== 'default' ? _claudeAccountRow(accountId) : null;
|
|
8698
|
+
tab.terminalAuthView = mountProviderTerminalAuth({
|
|
8699
|
+
host: tab.messagesEl, provider: 'claude', accountId, logo: CLAUDE_ICON,
|
|
8700
|
+
...(named ? { message: `Sign in to Claude to use ${named.label}.` } : {}),
|
|
8701
|
+
// Another account (or a new one) is one click away from the sign-in screen: the header account menu.
|
|
8702
|
+
moreAction: { label: accountText('otherAccounts'), run: () => _showAccounts(tab) },
|
|
8703
|
+
isCurrent: () => !tab.closed && (tab.accountId || 'default') === accountId,
|
|
8704
|
+
readAccount: async () => {
|
|
8705
|
+
const account = (await _claudeAuthRequest(`/api/claude/accounts/${encodeURIComponent(accountId)}/auth?refresh=true`)).account;
|
|
8706
|
+
if (!tab.closed && (tab.accountId || 'default') === accountId) tab.accountInfo = account;
|
|
8707
|
+
return account;
|
|
8708
|
+
},
|
|
8709
|
+
onSignedIn: () => { _loadClaudeAccounts({ force: true }).catch(() => {}); },
|
|
8710
|
+
});
|
|
8600
8711
|
}
|
|
8601
8712
|
|
|
8602
8713
|
// /mcp: every server of the session with its state, and what can be done about it.
|
|
@@ -9115,8 +9226,15 @@ function runSlashCommand(tab, raw) {
|
|
|
9115
9226
|
return true;
|
|
9116
9227
|
}
|
|
9117
9228
|
case 'cost': { clearInput(); emit('cost:toggle'); return true; }
|
|
9118
|
-
case 'login': { clearInput();
|
|
9119
|
-
case 'logout': {
|
|
9229
|
+
case 'login': { clearInput(); _showAccounts(tab, '', { manage: serverAccountId(tab.accountId) }); return true; }
|
|
9230
|
+
case 'logout': {
|
|
9231
|
+
clearInput();
|
|
9232
|
+
if (tab.running || tab.automationActive) { appendStatus(tab, 'Finish or stop the current turn before signing out.'); return true; }
|
|
9233
|
+
void _claudeAuthRequest(`/api/claude/accounts/${encodeURIComponent(tab.accountId || 'default')}/auth/logout`, { method: 'POST', body: '{}' })
|
|
9234
|
+
.then(() => { tab.accountInfo = null; tab.terminalAuthView?.update({ loggedIn: false }); })
|
|
9235
|
+
.catch(() => appendStatus(tab, 'Could not sign out. Try again.'));
|
|
9236
|
+
return true;
|
|
9237
|
+
}
|
|
9120
9238
|
case 'plan': {
|
|
9121
9239
|
clearInput();
|
|
9122
9240
|
// The one path for plan mode: on is the user's pick of Plan, off goes back
|
|
@@ -9138,8 +9256,9 @@ function runSlashCommand(tab, raw) {
|
|
|
9138
9256
|
function send({ shift = false } = {}) {
|
|
9139
9257
|
const tab = activeTab();
|
|
9140
9258
|
if (!tab) return;
|
|
9141
|
-
if ((
|
|
9142
|
-
|
|
9259
|
+
if (_cliBlocked() && !tab.automationActive) {
|
|
9260
|
+
// The banner above the transcript says why, and offers the way out.
|
|
9261
|
+
_cliBanner?.nudge();
|
|
9143
9262
|
return;
|
|
9144
9263
|
}
|
|
9145
9264
|
const $input = _panel?.querySelector('#cp-input');
|
|
@@ -9228,6 +9347,9 @@ function send({ shift = false } = {}) {
|
|
|
9228
9347
|
// A temporary chat that is over, or one the running server would save: nothing is sent.
|
|
9229
9348
|
{ const refusal = temporaryRefusal(tab, { capable: hasCapability(tab, TEMPORARY_CAPABILITY) }); if (refusal) { appendStatus(tab, refusal); return; } }
|
|
9230
9349
|
|
|
9350
|
+
// A message of the user's own in the tab of a run that ended: the tab is theirs from here on.
|
|
9351
|
+
releaseAutomationForManualUse(tab);
|
|
9352
|
+
|
|
9231
9353
|
// ── !bash shortcut — prefix a Bash-tool hint so Claude executes the command ──
|
|
9232
9354
|
if (text.startsWith('!') && text.length > 1) {
|
|
9233
9355
|
const cmd = text.slice(1).trim();
|
|
@@ -10030,116 +10152,50 @@ function syncReservedWidth(knownWidth) {
|
|
|
10030
10152
|
}
|
|
10031
10153
|
|
|
10032
10154
|
// ── CLI installation status (banner + send-block) ──
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
if (!
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
`;
|
|
10056
|
-
container.parentNode.insertBefore(banner, container);
|
|
10057
|
-
const btn = banner.querySelector('.cp-cli-banner-recheck');
|
|
10058
|
-
btn?.addEventListener('click', async () => {
|
|
10059
|
-
btn.disabled = true;
|
|
10060
|
-
btn.textContent = 'Checking…';
|
|
10061
|
-
try { await recheckCliStatus('claude-code'); }
|
|
10062
|
-
finally {
|
|
10063
|
-
if (btn.isConnected) {
|
|
10064
|
-
btn.disabled = false;
|
|
10065
|
-
btn.textContent = 'Re-check';
|
|
10066
|
-
}
|
|
10067
|
-
}
|
|
10068
|
-
});
|
|
10069
|
-
_renderCliBannerContent(banner);
|
|
10070
|
-
return banner;
|
|
10071
|
-
}
|
|
10072
|
-
|
|
10073
|
-
// Distinguish "never installed" from "installed but would not launch" —
|
|
10074
|
-
// telling the user to install something already present sends them chasing a
|
|
10075
|
-
// reinstall they do not need.
|
|
10076
|
-
function _renderCliBannerContent(banner) {
|
|
10077
|
-
const titleEl = banner.querySelector('.cp-cli-banner-title');
|
|
10078
|
-
const bodyEl = banner.querySelector('.cp-cli-banner-body');
|
|
10079
|
-
if (!titleEl || !bodyEl) return;
|
|
10080
|
-
const label = getCliLabel('claude-code');
|
|
10081
|
-
bodyEl.replaceChildren();
|
|
10082
|
-
|
|
10083
|
-
if (_cliInstalled === null) {
|
|
10084
|
-
titleEl.textContent = `${label} CLI not installed`;
|
|
10085
|
-
bodyEl.append('Run ');
|
|
10086
|
-
const code = document.createElement('code');
|
|
10087
|
-
code.textContent = getCliInstallCommand('claude-code');
|
|
10088
|
-
bodyEl.append(code, ' or follow the install guide.');
|
|
10089
|
-
return;
|
|
10090
|
-
}
|
|
10091
|
-
|
|
10092
|
-
titleEl.textContent = `${label} CLI failed to start`;
|
|
10093
|
-
bodyEl.append(`${label} v${_cliInstalled} is installed, but it could not be launched. `);
|
|
10094
|
-
if (_cliFailureReason) {
|
|
10095
|
-
const code = document.createElement('code');
|
|
10096
|
-
code.textContent = _cliFailureReason;
|
|
10097
|
-
bodyEl.append(code);
|
|
10098
|
-
} else {
|
|
10099
|
-
bodyEl.append('Check the CLI path in Settings, then re-check.');
|
|
10155
|
+
// One controller (ui-cli-banner.js) draws the banner above the transcript while
|
|
10156
|
+
// Claude Code is not usable: not installed (with Install, which runs Anthropic's
|
|
10157
|
+
// own installer on the server), being installed, failed to install, or found but
|
|
10158
|
+
// failed to start (with the error it gave). It also holds the class that keeps
|
|
10159
|
+
// sending off. What it says is cli-install-view.js (`cliInstall.*` strings).
|
|
10160
|
+
function _cliBannerController() {
|
|
10161
|
+
if (!_cliBanner) {
|
|
10162
|
+
_cliBanner = mountCliBanner({
|
|
10163
|
+
toolKey: 'claude-code',
|
|
10164
|
+
prefix: 'cp',
|
|
10165
|
+
panel: () => _panel,
|
|
10166
|
+
anchor: () => _panel?.querySelector('#cp-messages-container'),
|
|
10167
|
+
onBlockedChange: (blocked) => {
|
|
10168
|
+
const $send = _panel?.querySelector('#cp-send');
|
|
10169
|
+
if (!$send) return;
|
|
10170
|
+
if (blocked) { $send.disabled = true; return; }
|
|
10171
|
+
const tab = activeTab();
|
|
10172
|
+
const $input = _panel?.querySelector('#cp-input');
|
|
10173
|
+
if (tab?.running) $send.disabled = false;
|
|
10174
|
+
else $send.disabled = !$input?.value.trim() && !tab?.attachedImages?.length && !tab?.attachedFiles?.length;
|
|
10175
|
+
},
|
|
10176
|
+
});
|
|
10100
10177
|
}
|
|
10178
|
+
return _cliBanner;
|
|
10101
10179
|
}
|
|
10102
10180
|
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
banner?.remove();
|
|
10181
|
+
/** Sending is held back: Claude Code is missing, broken, failed to install, or being installed. */
|
|
10182
|
+
function _cliBlocked() {
|
|
10183
|
+
return !!_cliBanner?.blocked();
|
|
10107
10184
|
}
|
|
10108
10185
|
|
|
10109
10186
|
function _refreshCliBanners() {
|
|
10110
10187
|
if (!_panel) return;
|
|
10111
|
-
|
|
10112
|
-
_panel.classList.toggle('cp-cli-blocked', missing);
|
|
10113
|
-
if (missing) _ensureCliBannerEl();
|
|
10114
|
-
else _removeCliBannerEl();
|
|
10115
|
-
const $send = _panel.querySelector('#cp-send');
|
|
10116
|
-
if ($send && missing) $send.disabled = true;
|
|
10188
|
+
_cliBannerController().refresh();
|
|
10117
10189
|
}
|
|
10118
10190
|
|
|
10191
|
+
// A session could not start Claude Code: "failed to start" with its words at
|
|
10192
|
+
// once, then the server is asked again and its answer decides what stays.
|
|
10119
10193
|
export function flagClaudeCliInstallFailure(reason = null) {
|
|
10120
|
-
|
|
10121
|
-
_cliFailureReason = reason ? String(reason).slice(0, 300) : null;
|
|
10122
|
-
_refreshCliBanners();
|
|
10123
|
-
// Clear from the RETURNED value, not the subscriber callback: the callback
|
|
10124
|
-
// only fires when the version string changes, and a launch failure does not
|
|
10125
|
-
// change it, so the banner would otherwise latch permanently.
|
|
10126
|
-
recheckCliStatus('claude-code')
|
|
10127
|
-
.then((info) => {
|
|
10128
|
-
if (!info?.installed) return;
|
|
10129
|
-
_cliInstallFailureForced = false;
|
|
10130
|
-
_cliFailureReason = null;
|
|
10131
|
-
_refreshCliBanners();
|
|
10132
|
-
})
|
|
10133
|
-
.catch(() => {});
|
|
10194
|
+
_cliBannerController().flagFailure(reason);
|
|
10134
10195
|
}
|
|
10135
10196
|
|
|
10136
10197
|
function _ensureCliSubscription() {
|
|
10137
|
-
|
|
10138
|
-
_cliUnsub = subscribeCliStatus('claude-code', (info) => {
|
|
10139
|
-
_cliInstalled = info?.installed || null;
|
|
10140
|
-
if (_cliInstalled) { _cliInstallFailureForced = false; _cliFailureReason = null; }
|
|
10141
|
-
_refreshCliBanners();
|
|
10142
|
-
});
|
|
10198
|
+
_cliBannerController();
|
|
10143
10199
|
}
|
|
10144
10200
|
|
|
10145
10201
|
// ── Delegated transcript actions ──
|
|
@@ -10162,15 +10218,7 @@ function _onMessagesClick(e) {
|
|
|
10162
10218
|
});
|
|
10163
10219
|
return;
|
|
10164
10220
|
}
|
|
10165
|
-
|
|
10166
|
-
if (link) {
|
|
10167
|
-
e.preventDefault();
|
|
10168
|
-
const path = (link.textContent || '').replace(/:\d+$/, '');
|
|
10169
|
-
navigator.clipboard.writeText(path);
|
|
10170
|
-
link.style.opacity = '0.5';
|
|
10171
|
-
setTimeout(() => { link.style.opacity = ''; }, 300);
|
|
10172
|
-
return;
|
|
10173
|
-
}
|
|
10221
|
+
// File links (a.file-link, and the links of a message's Markdown) are taken by _fileLinkOptions below.
|
|
10174
10222
|
const hdr = e.target.closest('.tool-hdr');
|
|
10175
10223
|
if (hdr && !e.target.closest('button, a, input, select, textarea')) {
|
|
10176
10224
|
const card = hdr.closest('.tool-card');
|
|
@@ -10183,6 +10231,25 @@ function _onMessagesClick(e) {
|
|
|
10183
10231
|
}
|
|
10184
10232
|
}
|
|
10185
10233
|
|
|
10234
|
+
// ── File links ──
|
|
10235
|
+
// A link to a file the code editor can open opens it there (ui-file-links.js, shared with the other panels).
|
|
10236
|
+
// The same delegation as above: it covers streaming, finished and snapshot-restored messages of every tab.
|
|
10237
|
+
const _fileLinkOptions = {
|
|
10238
|
+
// A relative path is a path in the folder of the tab the message belongs to.
|
|
10239
|
+
cwd: (link) => {
|
|
10240
|
+
const tab = _tabs.find((t) => t.messagesEl?.contains(link)) || activeTab();
|
|
10241
|
+
return tab?.init?.cwd || tab?.project || '';
|
|
10242
|
+
},
|
|
10243
|
+
textLinks: 'a.file-link',
|
|
10244
|
+
// A path the editor does not open keeps what a click on it did: it is copied.
|
|
10245
|
+
copyPath: (link) => {
|
|
10246
|
+
const path = (link.textContent || '').replace(/:\d+$/, '');
|
|
10247
|
+
link.style.opacity = '0.5';
|
|
10248
|
+
setTimeout(() => { link.style.opacity = ''; }, 300);
|
|
10249
|
+
return navigator.clipboard.writeText(path);
|
|
10250
|
+
},
|
|
10251
|
+
};
|
|
10252
|
+
|
|
10186
10253
|
// ── Public API ──
|
|
10187
10254
|
async function _ensureClaudePanelReady() {
|
|
10188
10255
|
if (!_panel) {
|
|
@@ -10197,6 +10264,7 @@ async function _ensureClaudePanelReady() {
|
|
|
10197
10264
|
});
|
|
10198
10265
|
wireEvents();
|
|
10199
10266
|
_panel.querySelector('#cp-messages-container')?.addEventListener('click', _onMessagesClick);
|
|
10267
|
+
wireFileLinks(_panel.querySelector('#cp-messages-container'), _fileLinkOptions);
|
|
10200
10268
|
await loadConfig(); // must complete before restoreTabs — checks server boot ID
|
|
10201
10269
|
loadSkills();
|
|
10202
10270
|
restoreTabs();
|
|
@@ -10248,6 +10316,18 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10248
10316
|
if (!run?.runId || !run?.providerSessionId) return { ok: false, reason: 'identity_pending' };
|
|
10249
10317
|
await _ensureClaudePanelReady();
|
|
10250
10318
|
if (isCancelled()) return { ok: false, reason: 'dismissed' };
|
|
10319
|
+
// The user continued this run's tab by hand after the run ended: it stays theirs. The dock's
|
|
10320
|
+
// Focus raises it; the run is let go again, and nothing in the tab changes.
|
|
10321
|
+
const own = _tabs.find((entry) => !entry.automationRunId && entry.releasedRunId === run.runId && entry.sessionId === run.providerSessionId);
|
|
10322
|
+
if (own && !(run.status === 'starting' || run.status === 'running')) {
|
|
10323
|
+
window.dispatchEvent(new CustomEvent('native-loop:dismissed', { detail: { runId: run.runId } }));
|
|
10324
|
+
if (focus) {
|
|
10325
|
+
if (!_visible) await toggleClaudePanel();
|
|
10326
|
+
const ownIdx = _tabs.indexOf(own);
|
|
10327
|
+
if (ownIdx >= 0) switchTab(ownIdx);
|
|
10328
|
+
}
|
|
10329
|
+
return { ok: true, tabId: own.id, released: true };
|
|
10330
|
+
}
|
|
10251
10331
|
let tab = _tabs.find((entry) => entry.automationRunId === run.runId)
|
|
10252
10332
|
|| _tabs.find((entry) => entry.sessionId === run.providerSessionId);
|
|
10253
10333
|
if (!tab) {
|
|
@@ -10270,6 +10350,7 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10270
10350
|
tab.automationRunId = run.runId;
|
|
10271
10351
|
tab.automationActive = running;
|
|
10272
10352
|
tab.automationOwnerId = nativeLoopWindowId;
|
|
10353
|
+
tab.releasedRunId = null;
|
|
10273
10354
|
tab.sdkMode = true;
|
|
10274
10355
|
tab.sessionId = run.providerSessionId;
|
|
10275
10356
|
tab.label = run.title || tab.label || 'Automation';
|
|
@@ -10288,10 +10369,12 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10288
10369
|
return { ok: false, reason: 'dismissed' };
|
|
10289
10370
|
}
|
|
10290
10371
|
}
|
|
10291
|
-
|
|
10372
|
+
// (A dispatched worker's failure, with its reason, is on its end card.)
|
|
10373
|
+
if (run.status === 'failed' && run.error && !isDispatchedRun(run) && tab._automationLifecycleError !== run.error) {
|
|
10292
10374
|
tab._automationLifecycleError = run.error;
|
|
10293
10375
|
appendError(tab, run.error);
|
|
10294
10376
|
}
|
|
10377
|
+
trackWorkerEnd(run, { apply: (view) => showWorkerEnd(tab, view), busy: hasLiveBackgroundWork(tab) });
|
|
10295
10378
|
// The mode control is hidden while the run is active and back when it ended.
|
|
10296
10379
|
if (tab === activeTab()) populateModeDropdown(_panel?.querySelector('#cp-mode'), tab);
|
|
10297
10380
|
const idx = _tabs.indexOf(tab);
|
|
@@ -10319,10 +10402,60 @@ export function handleClaudeAutomationEvent(runId, payload) {
|
|
|
10319
10402
|
return true;
|
|
10320
10403
|
}
|
|
10321
10404
|
if (event.type === 'synabun.error') {
|
|
10405
|
+
// Every run's end disposes its SDK query, and the SDK says so in these words: not a failure.
|
|
10406
|
+
if (isEndOfRunAbort(event.message)) return true;
|
|
10322
10407
|
appendError(tab, event.message || 'Claude Code automation failed');
|
|
10323
10408
|
return true;
|
|
10324
10409
|
}
|
|
10325
10410
|
handleTabMsg(tab, { type: 'event', event, fromRun: true });
|
|
10411
|
+
// Background agents still running keep a warm worker's "Task complete" away.
|
|
10412
|
+
if (event.type === 'system' || event.type === 'result') updateWorkerEndBusy(runId, hasLiveBackgroundWork(tab));
|
|
10413
|
+
return true;
|
|
10414
|
+
}
|
|
10415
|
+
|
|
10416
|
+
function hasLiveBackgroundWork(tab) {
|
|
10417
|
+
for (const task of tab?.tasks?.values?.() || []) {
|
|
10418
|
+
if (task && !task.ambient && isTaskRunning(task)) return true;
|
|
10419
|
+
}
|
|
10420
|
+
return false;
|
|
10421
|
+
}
|
|
10422
|
+
|
|
10423
|
+
// The end of a worker the Assistant dispatched (ui-worker-end.js): one card,
|
|
10424
|
+
// the last row of its transcript. Its button closes this tab the way the X
|
|
10425
|
+
// does (a warm worker that finished its task is completed, one still at work
|
|
10426
|
+
// is stopped; its record stays for the Assistant) and shows the Assistant
|
|
10427
|
+
// session that dispatched it.
|
|
10428
|
+
function showWorkerEnd(tab, view) {
|
|
10429
|
+
tab._workerEnd = view || null;
|
|
10430
|
+
const $msgs = tab.messagesEl;
|
|
10431
|
+
if (!$msgs || tab.closed) return;
|
|
10432
|
+
$msgs.querySelectorAll(`.${WORKER_END_CLASS}`).forEach((el) => el.remove());
|
|
10433
|
+
if (!view) return;
|
|
10434
|
+
$msgs.appendChild(buildWorkerEndCard(view, {
|
|
10435
|
+
classes: { card: 'cp-worker-end', title: 'post-plan-header', actions: 'post-plan-actions', button: 'post-plan-action pp-primary' },
|
|
10436
|
+
onBack: () => {
|
|
10437
|
+
const idx = _tabs.indexOf(tab);
|
|
10438
|
+
if (idx >= 0) closeTab(idx);
|
|
10439
|
+
backToAssistant(view.assistantSessionId);
|
|
10440
|
+
},
|
|
10441
|
+
}));
|
|
10442
|
+
if (tab === activeTab()) scrollEnd(true);
|
|
10443
|
+
}
|
|
10444
|
+
|
|
10445
|
+
// The user sends a message of their own in the tab of a run that ended (Codex's
|
|
10446
|
+
// releaseAutomationForManualUse): the run's end card goes, the tab stops following
|
|
10447
|
+
// the run, and the router leaves the run alone, so nothing of it comes back here.
|
|
10448
|
+
// A run that is still going keeps its tab (the composer refuses a manual turn then).
|
|
10449
|
+
function releaseAutomationForManualUse(tab) {
|
|
10450
|
+
if (!tab?.automationRunId || tab.automationActive) return false;
|
|
10451
|
+
const runId = tab.automationRunId;
|
|
10452
|
+
forgetWorkerEnd(runId);
|
|
10453
|
+
showWorkerEnd(tab, null);
|
|
10454
|
+
tab.automationRunId = null;
|
|
10455
|
+
tab.automationOwnerId = null;
|
|
10456
|
+
tab.releasedRunId = runId;
|
|
10457
|
+
window.dispatchEvent(new CustomEvent('native-loop:dismissed', { detail: { runId } }));
|
|
10458
|
+
saveTabs();
|
|
10326
10459
|
return true;
|
|
10327
10460
|
}
|
|
10328
10461
|
|
|
@@ -11051,6 +11184,13 @@ function wireEvents() {
|
|
|
11051
11184
|
const $close = _panel.querySelector('.cp-close-btn');
|
|
11052
11185
|
const $minimize = _panel.querySelector('.cp-minimize-btn');
|
|
11053
11186
|
const $slide = _panel.querySelector('.cp-slide-btn');
|
|
11187
|
+
_mountAccountMenu();
|
|
11188
|
+
// Any window or surface changed an account (signed in, a key saved, its mode, renamed, added,
|
|
11189
|
+
// removed): the account menu re-reads the list, and the tabs on it re-check sign-in.
|
|
11190
|
+
on('sync:claude:accounts-changed', (msg) => {
|
|
11191
|
+
_loadClaudeAccounts({ force: true }).catch(() => {});
|
|
11192
|
+
for (const t of _tabs) if (!msg?.accountId || serverAccountId(t.accountId) === msg.accountId) void t.terminalAuthView?.refresh();
|
|
11193
|
+
});
|
|
11054
11194
|
const $new = _panel.querySelector('.cp-new-btn');
|
|
11055
11195
|
|
|
11056
11196
|
const $brand = _panel.querySelector('.cp-brand');
|