synabun 2.0.7 → 2.0.10
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 +67 -0
- package/README.md +1 -1
- package/THIRD-PARTY-LICENSES.md +46 -4
- package/hooks/claude-code/post-plan.mjs +6 -30
- package/hooks/claude-code/session-start.mjs +1 -4
- package/hooks/claude-code/shared.mjs +106 -72
- package/launcher.mjs +9 -3
- package/lib/package-processes.js +670 -0
- package/lib/runtime-dependencies.js +225 -0
- package/lib/start-launcher.js +6 -1
- package/mcp-server/dist/services/browser-bench.d.ts +1 -1
- package/mcp-server/dist/services/browser-bench.d.ts.map +1 -1
- package/mcp-server/dist/services/browser-bench.js +1 -1
- package/mcp-server/dist/services/browser-bench.js.map +1 -1
- package/mcp-server/dist/services/categories.d.ts +35 -2
- package/mcp-server/dist/services/categories.d.ts.map +1 -1
- package/mcp-server/dist/services/categories.js +77 -33
- package/mcp-server/dist/services/categories.js.map +1 -1
- package/mcp-server/dist/services/desktop-bench.d.ts +7 -7
- package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -1
- package/mcp-server/dist/services/desktop-bench.js +1 -1
- package/mcp-server/dist/services/desktop-bench.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +1 -1
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +1 -1
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/bluesky.js +1 -1
- package/mcp-server/dist/tools/bluesky.js.map +1 -1
- package/mcp-server/dist/tools/browser-advanced.d.ts +1 -1
- package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-advanced.js +1 -1
- package/mcp-server/dist/tools/browser-advanced.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-batch.js +1 -1
- package/mcp-server/dist/tools/browser-batch.js.map +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.js +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -1
- package/mcp-server/dist/tools/browser-interact.d.ts +1 -1
- package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-interact.js +1 -1
- package/mcp-server/dist/tools/browser-interact.js.map +1 -1
- package/mcp-server/dist/tools/browser-navigate.d.ts +1 -1
- package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-navigate.js +1 -1
- package/mcp-server/dist/tools/browser-navigate.js.map +1 -1
- package/mcp-server/dist/tools/browser-observe.d.ts +1 -1
- package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-observe.js +1 -1
- package/mcp-server/dist/tools/browser-observe.js.map +1 -1
- package/mcp-server/dist/tools/card-tools.d.ts +1 -1
- package/mcp-server/dist/tools/card-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/card-tools.js +1 -1
- package/mcp-server/dist/tools/card-tools.js.map +1 -1
- package/mcp-server/dist/tools/category.d.ts +1 -1
- package/mcp-server/dist/tools/category.d.ts.map +1 -1
- package/mcp-server/dist/tools/category.js +5 -1
- package/mcp-server/dist/tools/category.js.map +1 -1
- package/mcp-server/dist/tools/choice.d.ts +1 -1
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +1 -1
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/computer.d.ts +1 -1
- package/mcp-server/dist/tools/computer.d.ts.map +1 -1
- package/mcp-server/dist/tools/computer.js +1 -1
- package/mcp-server/dist/tools/computer.js.map +1 -1
- package/mcp-server/dist/tools/discord-channel.d.ts +1 -1
- package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-channel.js +1 -1
- package/mcp-server/dist/tools/discord-channel.js.map +1 -1
- package/mcp-server/dist/tools/discord-guild.d.ts +1 -1
- package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-guild.js +1 -1
- package/mcp-server/dist/tools/discord-guild.js.map +1 -1
- package/mcp-server/dist/tools/discord-member.d.ts +1 -1
- package/mcp-server/dist/tools/discord-member.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-member.js +1 -1
- package/mcp-server/dist/tools/discord-member.js.map +1 -1
- package/mcp-server/dist/tools/discord-message.d.ts +1 -1
- package/mcp-server/dist/tools/discord-message.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-message.js +1 -1
- package/mcp-server/dist/tools/discord-message.js.map +1 -1
- package/mcp-server/dist/tools/discord-onboarding.d.ts +1 -1
- package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-onboarding.js +1 -1
- package/mcp-server/dist/tools/discord-onboarding.js.map +1 -1
- package/mcp-server/dist/tools/discord-role.d.ts +1 -1
- package/mcp-server/dist/tools/discord-role.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-role.js +1 -1
- package/mcp-server/dist/tools/discord-role.js.map +1 -1
- package/mcp-server/dist/tools/discord-thread.d.ts +1 -1
- package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-thread.js +1 -1
- package/mcp-server/dist/tools/discord-thread.js.map +1 -1
- package/mcp-server/dist/tools/discord-webhook.d.ts +1 -1
- package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-webhook.js +1 -1
- package/mcp-server/dist/tools/discord-webhook.js.map +1 -1
- package/mcp-server/dist/tools/fb-groups.d.ts +1 -1
- package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -1
- package/mcp-server/dist/tools/fb-groups.js +1 -1
- package/mcp-server/dist/tools/fb-groups.js.map +1 -1
- package/mcp-server/dist/tools/forget.d.ts +1 -1
- package/mcp-server/dist/tools/forget.d.ts.map +1 -1
- package/mcp-server/dist/tools/forget.js +1 -1
- package/mcp-server/dist/tools/forget.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.d.ts +1 -1
- package/mcp-server/dist/tools/git-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +1 -1
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/gsc/experience.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/experience.js +1 -1
- package/mcp-server/dist/tools/gsc/experience.js.map +1 -1
- package/mcp-server/dist/tools/gsc/indexing.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/indexing.js +1 -1
- package/mcp-server/dist/tools/gsc/indexing.js.map +1 -1
- package/mcp-server/dist/tools/gsc/inspect.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/inspect.js +1 -1
- package/mcp-server/dist/tools/gsc/inspect.js.map +1 -1
- package/mcp-server/dist/tools/gsc/navigate.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/navigate.js +1 -1
- package/mcp-server/dist/tools/gsc/navigate.js.map +1 -1
- package/mcp-server/dist/tools/gsc/performance.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/performance.js +1 -1
- package/mcp-server/dist/tools/gsc/performance.js.map +1 -1
- package/mcp-server/dist/tools/gsc/settings.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/settings.js +1 -1
- package/mcp-server/dist/tools/gsc/settings.js.map +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/image-tools.js.map +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -1
- package/mcp-server/dist/tools/loop.d.ts +1 -1
- package/mcp-server/dist/tools/loop.d.ts.map +1 -1
- package/mcp-server/dist/tools/loop.js +1 -1
- package/mcp-server/dist/tools/loop.js.map +1 -1
- package/mcp-server/dist/tools/memories.d.ts +1 -1
- package/mcp-server/dist/tools/memories.d.ts.map +1 -1
- package/mcp-server/dist/tools/memories.js +1 -1
- package/mcp-server/dist/tools/memories.js.map +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +1 -1
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/profile.d.ts +1 -1
- package/mcp-server/dist/tools/profile.d.ts.map +1 -1
- package/mcp-server/dist/tools/profile.js +1 -1
- package/mcp-server/dist/tools/profile.js.map +1 -1
- package/mcp-server/dist/tools/recall.d.ts +1 -1
- package/mcp-server/dist/tools/recall.d.ts.map +1 -1
- package/mcp-server/dist/tools/recall.js +1 -1
- package/mcp-server/dist/tools/recall.js.map +1 -1
- package/mcp-server/dist/tools/reflect.d.ts +1 -1
- package/mcp-server/dist/tools/reflect.d.ts.map +1 -1
- package/mcp-server/dist/tools/reflect.js +1 -1
- package/mcp-server/dist/tools/reflect.js.map +1 -1
- package/mcp-server/dist/tools/remember.d.ts +1 -1
- package/mcp-server/dist/tools/remember.d.ts.map +1 -1
- package/mcp-server/dist/tools/remember.js +13 -11
- package/mcp-server/dist/tools/remember.js.map +1 -1
- package/mcp-server/dist/tools/restore.d.ts +1 -1
- package/mcp-server/dist/tools/restore.d.ts.map +1 -1
- package/mcp-server/dist/tools/restore.js +1 -1
- package/mcp-server/dist/tools/restore.js.map +1 -1
- package/mcp-server/dist/tools/style-guide-tools.d.ts +1 -1
- package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/style-guide-tools.js +1 -1
- package/mcp-server/dist/tools/style-guide-tools.js.map +1 -1
- package/mcp-server/dist/tools/sync.d.ts +1 -1
- package/mcp-server/dist/tools/sync.d.ts.map +1 -1
- package/mcp-server/dist/tools/sync.js +1 -1
- package/mcp-server/dist/tools/sync.js.map +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.d.ts +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.js +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -1
- package/mcp-server/dist/tools/utils.d.ts +1 -1
- package/mcp-server/dist/tools/utils.d.ts.map +1 -1
- package/mcp-server/dist/tools/utils.js +1 -1
- package/mcp-server/dist/tools/utils.js.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.js +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +3 -3
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/dist/tools/youtube/analytics.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/analytics.js +1 -1
- package/mcp-server/dist/tools/youtube/analytics.js.map +1 -1
- package/mcp-server/dist/tools/youtube/download.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/download.js +1 -1
- package/mcp-server/dist/tools/youtube/download.js.map +1 -1
- package/mcp-server/dist/tools/youtube/media.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/media.js +1 -1
- package/mcp-server/dist/tools/youtube/media.js.map +1 -1
- package/mcp-server/dist/tools/youtube/metadata.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/metadata.js +1 -1
- package/mcp-server/dist/tools/youtube/metadata.js.map +1 -1
- package/mcp-server/dist/tools/youtube/navigate.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/navigate.js +1 -1
- package/mcp-server/dist/tools/youtube/navigate.js.map +1 -1
- package/mcp-server/dist/tools/youtube/playlist.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/playlist.js +1 -1
- package/mcp-server/dist/tools/youtube/playlist.js.map +1 -1
- package/mcp-server/dist/tools/youtube/schedule.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/schedule.js +1 -1
- package/mcp-server/dist/tools/youtube/schedule.js.map +1 -1
- package/mcp-server/dist/tools/youtube/source.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/source.js +1 -1
- package/mcp-server/dist/tools/youtube/source.js.map +1 -1
- package/mcp-server/dist/tools/youtube/upload.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/upload.js +4 -9
- package/mcp-server/dist/tools/youtube/upload.js.map +1 -1
- package/mcp-server/dist/tui.js +16 -4
- package/mcp-server/dist/tui.js.map +1 -1
- package/mcp-server/package-lock.json +3 -3
- package/mcp-server/package.json +3 -3
- package/mcp-server/src/services/browser-bench.ts +1 -1
- package/mcp-server/src/services/categories.ts +77 -32
- package/mcp-server/src/services/desktop-bench.ts +1 -1
- package/mcp-server/src/tools/agents.ts +1 -1
- package/mcp-server/src/tools/bluesky.ts +1 -1
- package/mcp-server/src/tools/browser-advanced.ts +1 -1
- package/mcp-server/src/tools/browser-batch.ts +1 -1
- package/mcp-server/src/tools/browser-cheatsheet.ts +1 -1
- package/mcp-server/src/tools/browser-interact.ts +1 -1
- package/mcp-server/src/tools/browser-navigate.ts +1 -1
- package/mcp-server/src/tools/browser-observe.ts +1 -1
- package/mcp-server/src/tools/card-tools.ts +1 -1
- package/mcp-server/src/tools/category.ts +6 -1
- package/mcp-server/src/tools/choice.ts +1 -1
- package/mcp-server/src/tools/computer.ts +1 -1
- package/mcp-server/src/tools/discord-channel.ts +1 -1
- package/mcp-server/src/tools/discord-guild.ts +1 -1
- package/mcp-server/src/tools/discord-member.ts +1 -1
- package/mcp-server/src/tools/discord-message.ts +1 -1
- package/mcp-server/src/tools/discord-onboarding.ts +1 -1
- package/mcp-server/src/tools/discord-role.ts +1 -1
- package/mcp-server/src/tools/discord-thread.ts +1 -1
- package/mcp-server/src/tools/discord-webhook.ts +1 -1
- package/mcp-server/src/tools/fb-groups.ts +1 -1
- package/mcp-server/src/tools/forget.ts +1 -1
- package/mcp-server/src/tools/git-tools.ts +1 -1
- package/mcp-server/src/tools/gsc/experience.ts +1 -1
- package/mcp-server/src/tools/gsc/indexing.ts +1 -1
- package/mcp-server/src/tools/gsc/inspect.ts +1 -1
- package/mcp-server/src/tools/gsc/navigate.ts +1 -1
- package/mcp-server/src/tools/gsc/performance.ts +1 -1
- package/mcp-server/src/tools/gsc/settings.ts +1 -1
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/leonardo-browser-tools.ts +1 -1
- package/mcp-server/src/tools/loop.ts +1 -1
- package/mcp-server/src/tools/memories.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +1 -1
- package/mcp-server/src/tools/profile.ts +1 -1
- package/mcp-server/src/tools/recall.ts +1 -1
- package/mcp-server/src/tools/reflect.ts +1 -1
- package/mcp-server/src/tools/remember.ts +13 -12
- package/mcp-server/src/tools/restore.ts +1 -1
- package/mcp-server/src/tools/style-guide-tools.ts +1 -1
- package/mcp-server/src/tools/sync.ts +1 -1
- package/mcp-server/src/tools/tictactoe-tools.ts +1 -1
- package/mcp-server/src/tools/utils.ts +1 -1
- package/mcp-server/src/tools/whatsapp-send-file.ts +1 -1
- package/mcp-server/src/tools/whiteboard-tools.ts +1 -1
- package/mcp-server/src/tools/youtube/analytics.ts +1 -1
- package/mcp-server/src/tools/youtube/download.ts +1 -1
- package/mcp-server/src/tools/youtube/media.ts +1 -1
- package/mcp-server/src/tools/youtube/metadata.ts +1 -1
- package/mcp-server/src/tools/youtube/navigate.ts +1 -1
- package/mcp-server/src/tools/youtube/playlist.ts +1 -1
- package/mcp-server/src/tools/youtube/schedule.ts +1 -1
- package/mcp-server/src/tools/youtube/source.ts +1 -1
- package/mcp-server/src/tools/youtube/upload.ts +4 -12
- package/mcp-server/src/tui.ts +22 -9
- package/neural-interface/i18n/en.json +236 -7
- package/neural-interface/i18n/pt-BR.json +238 -9
- package/neural-interface/lib/account-usage.js +5 -3
- package/neural-interface/lib/agent-sandbox-elevation.js +102 -0
- package/neural-interface/lib/agent-sandbox-setting.js +57 -0
- package/neural-interface/lib/app-controls-api.js +161 -0
- package/neural-interface/lib/assistant-api.js +40 -7
- package/neural-interface/lib/assistant-brains/opencode.js +13 -1
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +44 -0
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +57 -0
- package/neural-interface/lib/assistant-catalog.js +17 -2
- package/neural-interface/lib/assistant-dispatch.js +3 -0
- package/neural-interface/lib/assistant-envelope.js +19 -1
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -1
- package/neural-interface/lib/assistant-runtime.js +131 -8
- package/neural-interface/lib/claude-model-catalog.js +64 -14
- package/neural-interface/lib/codex-account-auth.js +4 -2
- package/neural-interface/lib/codex-accounts.js +14 -1
- package/neural-interface/lib/codex-settings-schema.js +111 -47
- package/neural-interface/lib/editor-completion-opencode.js +132 -35
- package/neural-interface/lib/exec-loop-command.js +11 -2
- package/neural-interface/lib/install-details.js +23 -5
- package/neural-interface/lib/launch-cache.js +293 -0
- package/neural-interface/lib/login-start.js +524 -0
- package/neural-interface/lib/native-loop-providers.js +24 -4
- package/neural-interface/lib/native-loop-runtime.js +19 -0
- package/neural-interface/lib/opencode-db-schema.js +75 -0
- package/neural-interface/lib/opencode-history.js +16 -1
- package/neural-interface/lib/opencode-protocol.js +173 -0
- package/neural-interface/lib/opencode-provider-view.js +81 -0
- package/neural-interface/lib/opencode-runtime-config.js +10 -3
- package/neural-interface/lib/opencode-serve-records.js +606 -0
- package/neural-interface/lib/opencode-v2-client.js +33 -6
- package/neural-interface/lib/opencode-v2-ws-requests.js +19 -5
- package/neural-interface/lib/opencode-worker-activity.js +229 -0
- package/neural-interface/lib/opencode2-client.js +760 -0
- package/neural-interface/lib/opencode2-proxy.js +116 -0
- package/neural-interface/lib/opencode2-translate.js +1008 -0
- package/neural-interface/lib/process-identity.js +361 -0
- package/neural-interface/lib/provider-panel-terminal-auth.js +3 -2
- package/neural-interface/lib/session-cache-builder.js +26 -5
- package/neural-interface/lib/session-indexer.js +3 -1
- package/neural-interface/lib/session-title-generator.js +20 -0
- package/neural-interface/lib/style-guide/api.js +4 -3
- package/neural-interface/lib/untrusted-file-headers.js +27 -0
- package/neural-interface/package-lock.json +1342 -44
- package/neural-interface/package.json +5 -1
- package/neural-interface/public/index.html +2 -2
- package/neural-interface/public/shared/account-menu.js +4 -1
- package/neural-interface/public/shared/account-usage.js +62 -2
- package/neural-interface/public/shared/account-view.js +2 -1
- package/neural-interface/public/shared/agent-runtime-options.js +55 -11
- package/neural-interface/public/shared/assistant/asst-account-menu.js +298 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +172 -17
- package/neural-interface/public/shared/assistant/asst-api.js +18 -3
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +424 -152
- package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
- package/neural-interface/public/shared/assistant/asst-hosts.js +49 -2
- package/neural-interface/public/shared/assistant/asst-menu.js +275 -77
- package/neural-interface/public/shared/assistant/asst-model-chip.js +135 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +236 -35
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +28 -10
- package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
- package/neural-interface/public/shared/assistant/asst-render.js +382 -36
- package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
- package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
- package/neural-interface/public/shared/assistant/asst-scenes.js +528 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
- package/neural-interface/public/shared/assistant/asst-state.js +14 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +109 -17
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +13 -1
- package/neural-interface/public/shared/cc-dropdown.js +480 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
- package/neural-interface/public/shared/cdx/cdx-render.js +15 -3
- package/neural-interface/public/shared/cdx/cdx-styles.js +49 -5
- package/neural-interface/public/shared/cdx/cdx-tabs.js +152 -35
- package/neural-interface/public/shared/cp/cp-markdown.js +4 -57
- package/neural-interface/public/shared/data-cache.js +223 -0
- package/neural-interface/public/shared/desktop-bridge.js +11 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
- package/neural-interface/public/shared/desktop-titlebar.js +214 -28
- package/neural-interface/public/shared/desktop-update-view.js +15 -5
- package/neural-interface/public/shared/file-links.js +73 -8
- package/neural-interface/public/shared/html-shell.js +74 -80
- package/neural-interface/public/shared/launch-prefetch.js +59 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +3 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +11 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +54 -17
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +97 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +3 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +16 -9
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +60 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +83 -5
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +195 -19
- package/neural-interface/public/shared/opencode-providers.js +39 -0
- package/neural-interface/public/shared/schedules-view.js +318 -0
- package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
- package/neural-interface/public/shared/settings/settings-app.js +243 -0
- package/neural-interface/public/shared/settings/settings-data.js +88 -0
- package/neural-interface/public/shared/settings/settings-ia.js +17 -0
- package/neural-interface/public/shared/showcase-privacy.js +2 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +49 -0
- package/neural-interface/public/shared/styles.css +543 -372
- package/neural-interface/public/shared/ui-assistant.js +27 -5
- package/neural-interface/public/shared/ui-automation-studio.js +67 -27
- package/neural-interface/public/shared/ui-bookmarks.js +2 -1
- package/neural-interface/public/shared/ui-claude-panel.js +126 -12
- package/neural-interface/public/shared/ui-codex-panel.js +1 -0
- package/neural-interface/public/shared/ui-detail.js +6 -6
- package/neural-interface/public/shared/ui-explorer.js +2 -0
- package/neural-interface/public/shared/ui-file-links.js +1 -0
- package/neural-interface/public/shared/ui-image-gallery.js +6 -5
- package/neural-interface/public/shared/ui-invite.js +18 -2
- package/neural-interface/public/shared/ui-link.js +9 -9
- package/neural-interface/public/shared/ui-menubar.js +232 -33
- package/neural-interface/public/shared/ui-native-loop-router.js +2 -0
- package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
- package/neural-interface/public/shared/ui-schedules-studio.js +2099 -869
- package/neural-interface/public/shared/ui-sessions.js +15 -4
- package/neural-interface/public/shared/ui-settings.js +87 -36
- package/neural-interface/public/shared/ui-sidebar.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +55 -4
- package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
- package/neural-interface/public/shared/ui-skills.js +70 -12
- package/neural-interface/public/shared/ui-sync.js +9 -0
- package/neural-interface/public/shared/ui-terminal.js +36 -20
- package/neural-interface/public/shared/ui-trash.js +8 -1
- package/neural-interface/public/shared/ui-tutorial-steps.js +7 -3
- package/neural-interface/public/shared/ui-tutorial.js +15 -5
- package/neural-interface/public/shared/ui-update.js +87 -16
- package/neural-interface/public/shared/ui-whiteboard.js +2 -1
- package/neural-interface/public/variant/2d/main.js +4 -1
- package/neural-interface/public/variant/3d/main.js +3 -0
- package/neural-interface/public/vendor/highlight/LICENSE +29 -0
- package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
- package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
- package/neural-interface/public/vendor/highlight/manifest.json +5 -0
- package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
- package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
- package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
- package/neural-interface/public/vendor/marked/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
- package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
- package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -0
- package/neural-interface/scripts/build-vendor.mjs +84 -3
- package/neural-interface/scripts/rebuild-pty.js +14 -2
- package/neural-interface/server.js +1279 -372
- package/npm-shrinkwrap.json +4424 -0
- package/package.json +54 -2
- package/postinstall.js +61 -47
- package/preuninstall.js +8 -35
- package/setup.js +76 -44
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/schedule.md +2 -2
- package/updater.cmd +2 -2
- package/updater.mjs +97 -3
|
@@ -14,8 +14,8 @@ import { t } from './i18n.js';
|
|
|
14
14
|
import { registerAction } from './ui-keybinds.js';
|
|
15
15
|
import { isGuest, hasPermission, showGuestToast } from './ui-sync.js';
|
|
16
16
|
import { createAssistantHosts, describeBrainFallback } from './assistant/asst-hosts.js';
|
|
17
|
-
import { createAssistantSession, getAssistantSession, listAssistantSessions } from './assistant/asst-api.js';
|
|
18
|
-
import { providerShortLabel, readStoredBrain } from './assistant/asst-state.js';
|
|
17
|
+
import { createAssistantSession, getAssistantSession, listAssistantSessions, removeAssistantSession } from './assistant/asst-api.js';
|
|
18
|
+
import { providerShortLabel, readStoredBrain, tabStorageKey } from './assistant/asst-state.js';
|
|
19
19
|
|
|
20
20
|
/** Guests need the terminal permission for the Assistant, in either host. */
|
|
21
21
|
export function assistantBlocked() {
|
|
@@ -30,7 +30,7 @@ function brainFallbackText(fallback) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const hosts = createAssistantHosts({
|
|
33
|
-
api: { list: listAssistantSessions, get: getAssistantSession, create: createAssistantSession },
|
|
33
|
+
api: { list: listAssistantSessions, get: getAssistantSession, create: createAssistantSession, remove: removeAssistantSession },
|
|
34
34
|
isBlocked: assistantBlocked,
|
|
35
35
|
toast: (text) => showGuestToast(text),
|
|
36
36
|
storedBrain: () => readStoredBrain(storage),
|
|
@@ -48,6 +48,11 @@ export const noteAssistantFocus = (sessionId, hostId) => hosts.noteFocus(session
|
|
|
48
48
|
|
|
49
49
|
let _initialized = false;
|
|
50
50
|
|
|
51
|
+
/** A removed session's per-tab UI state (composer draft, dock, route mode): written by its tab as it closes, then dropped. */
|
|
52
|
+
function forgetTabState(sessionId) {
|
|
53
|
+
try { storage.removeItem(tabStorageKey(sessionId)); } catch { /* storage unavailable */ }
|
|
54
|
+
}
|
|
55
|
+
|
|
51
56
|
/** Bus events + keybinds for both hosts. Idempotent: initNavbar and initTerminal both call it. */
|
|
52
57
|
export function initAssistant() {
|
|
53
58
|
if (_initialized) return;
|
|
@@ -60,8 +65,24 @@ export function initAssistant() {
|
|
|
60
65
|
floating: data?.floating,
|
|
61
66
|
prompt: data?.prompt,
|
|
62
67
|
}));
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
// `replaces`: the session the user left by picking this one, when nobody chatted in it: it goes.
|
|
69
|
+
on('assistant:resume', async (data) => {
|
|
70
|
+
if (!data?.sessionId) return;
|
|
71
|
+
const res = await hosts.open({ resume: data.sessionId, host: data?.host || null, floating: data?.floating });
|
|
72
|
+
if (res && data.replaces && data.replaces !== data.sessionId) hosts.discard(data.replaces);
|
|
73
|
+
});
|
|
74
|
+
// Sessions menu → Remove. `done(result)` tells the menu that asked how it went.
|
|
75
|
+
on('assistant:remove', (data) => {
|
|
76
|
+
if (!data?.sessionId) return;
|
|
77
|
+
hosts.remove(data.sessionId, { host: data.host || null, fresh: data.fresh === true, brain: data.brain || null })
|
|
78
|
+
.then((result) => {
|
|
79
|
+
if (result?.ok) forgetTabState(data.sessionId);
|
|
80
|
+
try { data.done?.(result); } catch { /* the menu is gone */ }
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
// A session the server no longer has: its tab closes (a fresh one in its place when it was showing unused).
|
|
84
|
+
on('assistant:gone', (data) => {
|
|
85
|
+
if (data?.sessionId) hosts.gone(data.sessionId, { host: data.host || null, fresh: data.fresh === true, brain: data.brain || null }).finally(() => forgetTabState(data.sessionId));
|
|
65
86
|
});
|
|
66
87
|
on('assistant:toggle', () => hosts.toggle());
|
|
67
88
|
// Notification clicks (toasts and OS banners) — see ui-notifications _getNotifMeta.
|
|
@@ -71,6 +92,7 @@ export function initAssistant() {
|
|
|
71
92
|
on('sync:assistant:session-ended', (msg) => {
|
|
72
93
|
const id = msg?.sessionId || msg?.session?.id || msg?.id;
|
|
73
94
|
if (id) hosts.ended(id);
|
|
95
|
+
if (id && msg?.destroyed) forgetTabState(id); // removed for good: its tab's UI state goes too
|
|
74
96
|
});
|
|
75
97
|
registerAction('launch-assistant', () => hosts.openOrFocus());
|
|
76
98
|
registerAction('toggle-assistant', () => hosts.toggle());
|
|
@@ -9,6 +9,7 @@ import { storage } from './storage.js';
|
|
|
9
9
|
import { initI18n, isReady as i18nReady, t } from './i18n.js';
|
|
10
10
|
import { fetchStyleGuideProjects, fetchStyleGuideSummary } from './api.js';
|
|
11
11
|
import { isGuest, hasPermission, showGuestToast } from './ui-sync.js';
|
|
12
|
+
import { registerLaunchPrefetch } from './launch-prefetch.js';
|
|
12
13
|
import {
|
|
13
14
|
getNativeLoopRouterClaimToken,
|
|
14
15
|
getNativeLoopRouterWindowId,
|
|
@@ -90,6 +91,9 @@ let _prevLoopActive = false;
|
|
|
90
91
|
|
|
91
92
|
// Cleanup: stored references for document-level listeners so closePanel() can remove them
|
|
92
93
|
let _docListeners = [];
|
|
94
|
+
// What the last read found (templates, folders, the active loop, agents): a later open paints from it at once
|
|
95
|
+
// and reads it again behind it.
|
|
96
|
+
let _keptData = null;
|
|
93
97
|
|
|
94
98
|
// Detail/editor state
|
|
95
99
|
let _metaDirty = false;
|
|
@@ -283,9 +287,9 @@ function renderMcpProfileChips(presets, selected) {
|
|
|
283
287
|
return renderLaunchSelect('mcp', options, selected);
|
|
284
288
|
}
|
|
285
289
|
return entries.map(([id, p]) => `
|
|
286
|
-
<button class="as-launch-mcp-profile${id === selected ? ' active' : ''}" data-mcp-profile="${id}">
|
|
287
|
-
<span class="as-launch-mcp-profile-name">${p.label || id}</span>
|
|
288
|
-
<span class="as-launch-mcp-profile-tools">${p.tools} tools</span>
|
|
290
|
+
<button class="as-launch-mcp-profile${id === selected ? ' active' : ''}" data-mcp-profile="${_escLaunch(id)}">
|
|
291
|
+
<span class="as-launch-mcp-profile-name">${_escLaunch(p.label || id)}</span>
|
|
292
|
+
<span class="as-launch-mcp-profile-tools">${_escLaunch(p.tools)} tools</span>
|
|
289
293
|
</button>
|
|
290
294
|
`).join('');
|
|
291
295
|
}
|
|
@@ -1187,9 +1191,9 @@ function renderModelChips(profileId, selectedModel) {
|
|
|
1187
1191
|
return renderLaunchSelect('model', models, selectedModel, { groupByDesc: profileId === 'opencode' });
|
|
1188
1192
|
}
|
|
1189
1193
|
return models.map(m => `
|
|
1190
|
-
<button class="as-launch-model${modelMatchesSelector(m, selectedModel) ? ' active' : ''}${m.tier ? ` as-launch-model--${m.tier}` : ''}" data-model="${modelSelectorValue(m)}">
|
|
1191
|
-
<span class="as-launch-model-name">${m.label}</span>
|
|
1192
|
-
<span class="as-launch-model-desc">${m.desc}</span>
|
|
1194
|
+
<button class="as-launch-model${modelMatchesSelector(m, selectedModel) ? ' active' : ''}${m.tier ? ` as-launch-model--${m.tier}` : ''}" data-model="${_escLaunch(modelSelectorValue(m))}">
|
|
1195
|
+
<span class="as-launch-model-name">${_escLaunch(m.label)}</span>
|
|
1196
|
+
<span class="as-launch-model-desc">${_escLaunch(m.desc)}</span>
|
|
1193
1197
|
</button>
|
|
1194
1198
|
`).join('');
|
|
1195
1199
|
}
|
|
@@ -1299,7 +1303,10 @@ function wireLaunchSelect(root, type, onChange) {
|
|
|
1299
1303
|
});
|
|
1300
1304
|
});
|
|
1301
1305
|
|
|
1302
|
-
|
|
1306
|
+
// Outside click closes it; removed with the panel (closePanel) like the studio's other document listeners.
|
|
1307
|
+
const onOutside = e => { if (!sel.contains(e.target)) close(); };
|
|
1308
|
+
document.addEventListener('click', onOutside);
|
|
1309
|
+
_docListeners.push(['click', onOutside]);
|
|
1303
1310
|
});
|
|
1304
1311
|
}
|
|
1305
1312
|
|
|
@@ -1721,6 +1728,8 @@ function buildTemplateCommand(template) {
|
|
|
1721
1728
|
// ═══════════════════════════════════════════
|
|
1722
1729
|
|
|
1723
1730
|
export function initAutomationStudio() {
|
|
1731
|
+
// Launch: the studio's lists are read once the page has painted (launch-prefetch.js), so the first open paints at once.
|
|
1732
|
+
registerLaunchPrefetch('automation-studio', prefetchAutomationStudio, { order: 72 });
|
|
1724
1733
|
on('automations:open', (opts) => openPanel(opts || {}));
|
|
1725
1734
|
on('automations:open-wizard', () => { openPanel(); });
|
|
1726
1735
|
on('automations:import', () => { openPanel().then(() => triggerImport()); });
|
|
@@ -1759,15 +1768,44 @@ async function openPanel(opts = {}) {
|
|
|
1759
1768
|
_panel.style.top = Math.max(48, (window.innerHeight - 520) / 2) + 'px';
|
|
1760
1769
|
|
|
1761
1770
|
wirePanel();
|
|
1762
|
-
|
|
1771
|
+
const kept = _keptData;
|
|
1772
|
+
if (kept) {
|
|
1773
|
+
// The studio as last read paints at once; it is read again behind it and the sidebar follows in place.
|
|
1774
|
+
_templates = kept.templates; _folders = kept.folders; _activeLoop = kept.activeLoop; _agents = kept.agents;
|
|
1775
|
+
updateSidebarFooter();
|
|
1776
|
+
} else {
|
|
1777
|
+
await loadData();
|
|
1778
|
+
}
|
|
1763
1779
|
if (opts.templateId) {
|
|
1764
1780
|
const tpl = _templates.find(t => t.id === opts.templateId);
|
|
1765
1781
|
if (tpl) switchToDetail(tpl); else renderView();
|
|
1766
1782
|
} else {
|
|
1767
1783
|
renderView();
|
|
1768
1784
|
}
|
|
1769
|
-
requestAnimationFrame(() => { _backdrop
|
|
1785
|
+
requestAnimationFrame(() => { _backdrop?.classList.add('open'); _panel?.classList.add('open'); });
|
|
1770
1786
|
startPolling();
|
|
1787
|
+
if (kept) refreshDataInPlace();
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
// The data read again behind a studio painted from the kept one: the sidebar list is redrawn when the templates
|
|
1791
|
+
// or folders changed (an open template, the wizard and the editors keep what the user is doing).
|
|
1792
|
+
async function refreshDataInPlace() {
|
|
1793
|
+
const before = JSON.stringify([_templates, _folders]);
|
|
1794
|
+
await loadData();
|
|
1795
|
+
if (!_panel) return;
|
|
1796
|
+
if (JSON.stringify([_templates, _folders]) === before) return;
|
|
1797
|
+
const list = $('as-template-list');
|
|
1798
|
+
const scroll = list ? list.scrollTop : 0;
|
|
1799
|
+
renderSidebar();
|
|
1800
|
+
const count = $('as-total-count');
|
|
1801
|
+
if (count) count.textContent = `${PRESET_TEMPLATES.length + _templates.length}`;
|
|
1802
|
+
if (list && list.isConnected) list.scrollTop = scroll;
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
/** Launch prefetch: the studio's data read once, so the first open paints at once (nothing is drawn here). */
|
|
1806
|
+
export function prefetchAutomationStudio() {
|
|
1807
|
+
if (_keptData || _panel || (isGuest() && !hasPermission('automations'))) return Promise.resolve();
|
|
1808
|
+
return loadData().catch(() => {});
|
|
1771
1809
|
}
|
|
1772
1810
|
|
|
1773
1811
|
function closePanel() {
|
|
@@ -2326,11 +2364,15 @@ async function promptCreateFolder() {
|
|
|
2326
2364
|
// ═══════════════════════════════════════════
|
|
2327
2365
|
|
|
2328
2366
|
async function loadData() {
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2367
|
+
// One round trip for the three lists (they were asked one after another), then the agents.
|
|
2368
|
+
const [templates, folders, active] = await Promise.allSettled([fetchLoopTemplates(), fetchLoopFolders(), fetchActiveLoop()]);
|
|
2369
|
+
_templates = templates.status === 'fulfilled' ? templates.value : [];
|
|
2370
|
+
_folders = folders.status === 'fulfilled' ? folders.value : [];
|
|
2371
|
+
_activeLoop = active.status === 'fulfilled' ? active.value : null;
|
|
2332
2372
|
await refreshAgents();
|
|
2333
|
-
updateSidebarFooter();
|
|
2373
|
+
if (_panel) updateSidebarFooter();
|
|
2374
|
+
// Kept only when the templates answered (a failed read must not paint an empty studio next time).
|
|
2375
|
+
if (templates.status === 'fulfilled') _keptData = { templates: _templates, folders: _folders, activeLoop: _activeLoop, agents: _agents };
|
|
2334
2376
|
}
|
|
2335
2377
|
|
|
2336
2378
|
function startPolling() {
|
|
@@ -3754,16 +3796,14 @@ async function refreshAgents() {
|
|
|
3754
3796
|
try {
|
|
3755
3797
|
const data = await fetchAgents();
|
|
3756
3798
|
_agents = data?.agents || [];
|
|
3757
|
-
// Update local output buffers with any text we haven't captured via WebSocket
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
}
|
|
3766
|
-
}
|
|
3799
|
+
// Update local output buffers with any text we haven't captured via WebSocket (together, not one by one)
|
|
3800
|
+
await Promise.all(_agents.filter(a => !_agentOutputs[a.id] && a.textLength > 0).map(async (a) => {
|
|
3801
|
+
// Fetch full details to get textOutput
|
|
3802
|
+
try {
|
|
3803
|
+
const full = await fetchAgent(a.id);
|
|
3804
|
+
if (full?.textOutput) _agentOutputs[a.id] = full.textOutput;
|
|
3805
|
+
} catch {}
|
|
3806
|
+
}));
|
|
3767
3807
|
} catch {}
|
|
3768
3808
|
}
|
|
3769
3809
|
|
|
@@ -4742,9 +4782,9 @@ function renderSchedulesMain() {
|
|
|
4742
4782
|
? (qtModels.length > LAUNCH_CHIP_MAX
|
|
4743
4783
|
? renderLaunchSelect('qt-model', qtModels, qtCurrentModel, { groupByDesc: qtProfile === 'opencode' })
|
|
4744
4784
|
: qtModels.map(m => `
|
|
4745
|
-
<button class="as-launch-model${modelMatchesSelector(m, qtCurrentModel) ? ' active' : ''}${m.tier ? ` as-launch-model--${m.tier}` : ''}" data-action="qt-model" data-model="${modelSelectorValue(m)}">
|
|
4746
|
-
<span class="as-launch-model-name">${m.label}</span>
|
|
4747
|
-
<span class="as-launch-model-desc">${m.desc}</span>
|
|
4785
|
+
<button class="as-launch-model${modelMatchesSelector(m, qtCurrentModel) ? ' active' : ''}${m.tier ? ` as-launch-model--${m.tier}` : ''}" data-action="qt-model" data-model="${_escLaunch(modelSelectorValue(m))}">
|
|
4786
|
+
<span class="as-launch-model-name">${_escLaunch(m.label)}</span>
|
|
4787
|
+
<span class="as-launch-model-desc">${_escLaunch(m.desc)}</span>
|
|
4748
4788
|
</button>
|
|
4749
4789
|
`).join(''))
|
|
4750
4790
|
: `<span class="as-launch-no-models">${esc(dynamicModelEmptyText(qtProfile))}</span>`;
|
|
@@ -4942,7 +4982,7 @@ function renderScheduleEditorMain() {
|
|
|
4942
4982
|
</div>`).join('');
|
|
4943
4983
|
|
|
4944
4984
|
const templateOptions = allTemplates.map(t =>
|
|
4945
|
-
`<option value="${t.id}"${(s?.templateId === t.id) ? ' selected' : ''}>${esc(t.name)} (${t.category})</option>`
|
|
4985
|
+
`<option value="${esc(t.id)}"${(s?.templateId === t.id) ? ' selected' : ''}>${esc(t.name)} (${esc(t.category)})</option>`
|
|
4946
4986
|
).join('');
|
|
4947
4987
|
|
|
4948
4988
|
// Reorder: Mon(1)–Sat(6) then Sun(0) so 2-column grid pairs weekdays nicely
|
|
@@ -8,6 +8,7 @@ import { state, emit, on } from './state.js';
|
|
|
8
8
|
import { KEYS } from './constants.js';
|
|
9
9
|
import { storage } from './storage.js';
|
|
10
10
|
import { catColor } from './colors.js';
|
|
11
|
+
import { escapeHtml } from './utils.js';
|
|
11
12
|
|
|
12
13
|
const $ = (id) => document.getElementById(id);
|
|
13
14
|
|
|
@@ -120,7 +121,7 @@ export function renderBookmarks() {
|
|
|
120
121
|
item.innerHTML = `
|
|
121
122
|
<div class="dropdown-item-dot" style="background:${color}"></div>
|
|
122
123
|
<div class="dropdown-item-text">
|
|
123
|
-
<div class="dropdown-item-title">${b.title}</div>
|
|
124
|
+
<div class="dropdown-item-title">${escapeHtml(String(b.title ?? ''))}</div>
|
|
124
125
|
<div class="dropdown-item-sub">${b.category}</div>
|
|
125
126
|
</div>
|
|
126
127
|
<button class="icon-btn icon-btn--danger" style="width:22px;height:22px;font-size:13px;border:none" data-tooltip="Remove">×</button>
|
|
@@ -24,6 +24,7 @@ import { requestGeneratedSessionTitle } from './session-title.js';
|
|
|
24
24
|
import { wireFileLinks } from './ui-file-links.js';
|
|
25
25
|
import { WORKER_END_CLASS, backToAssistant, buildWorkerEndCard, endWorkerRunOnClose, forgetWorkerEnd, trackWorkerEnd, updateWorkerEndBusy } from './ui-worker-end.js';
|
|
26
26
|
import { isDispatchedRun, isEndOfRunAbort } from './worker-end.js';
|
|
27
|
+
import { runAwaitsAnswer } from './sidepanel-session-status.js';
|
|
27
28
|
// ── cp/ feature modules (SDK-engine CLI parity: diffs, agents, bash, perms, statusline) ──
|
|
28
29
|
import { setCpCtx } from './cp/cp-ctx.js';
|
|
29
30
|
import { buildDiffCard, buildDiffPreviewEl, finalizeDiffCard } from './cp/cp-diff.js';
|
|
@@ -46,7 +47,8 @@ import { historyHasResultSupport, historyResultsNotice, snapshotWantsResults, fu
|
|
|
46
47
|
import { CP_STYLES } from './cp/cp-styles.js';
|
|
47
48
|
import { TEMPORARY_CAPABILITY, keepsNothing, chooseTemporary, applyTemporary, temporaryRefusal, endTemporary, leaveTemporary, tabAfterTemporary, persistableTabs, temporaryBlocks, reattaches } from './cp/cp-temporary.js';
|
|
48
49
|
import { paintTemporary } from './cp/cp-temporary-view.js';
|
|
49
|
-
import { renderMarkdown
|
|
50
|
+
import { renderMarkdown } from './cp/cp-markdown.js';
|
|
51
|
+
import { sanitizeStoredHtml } from './assistant/asst-sanitize.js';
|
|
50
52
|
import { escapeHtml, classToken } from './cp/cp-markdown.js';
|
|
51
53
|
import { rehydrateStoredTranscript } from './cp/cp-rehydrate.js';
|
|
52
54
|
import { compactHolds, compactQueue, isCompactCommand, newConversation, nextQueued, ownsQueued, queuedRefusal, restoredQueue, QUEUED_REFUSAL_LINES } from './cp/cp-compose.js';
|
|
@@ -178,7 +180,7 @@ let _cliBanner = null;
|
|
|
178
180
|
let _marked = null;
|
|
179
181
|
(async () => {
|
|
180
182
|
try {
|
|
181
|
-
const m = await import('
|
|
183
|
+
const m = await import('/vendor/marked/marked-14.1.4.esm.js').catch(() => null);
|
|
182
184
|
if (m) {
|
|
183
185
|
_marked = m.marked || m.default;
|
|
184
186
|
if (_marked?.setOptions) _marked.setOptions({ breaks: true, gfm: true });
|
|
@@ -1905,10 +1907,44 @@ function injectStyles() {
|
|
|
1905
1907
|
background: rgba(22, 22, 26, 0.95);
|
|
1906
1908
|
z-index: 3;
|
|
1907
1909
|
box-shadow: var(--shadow-sm), 0 0 0 1px rgba(255,255,255,0.06);
|
|
1908
|
-
|
|
1910
|
+
/* A query container measured in controls: 1em is one header button (24px docked, the
|
|
1911
|
+
window's control size when detached, which follows the font scale), so the thresholds
|
|
1912
|
+
below hold at any scale. Nothing in the row inherits it; the session menu takes the
|
|
1913
|
+
panel's back. */
|
|
1914
|
+
container: cp-header / inline-size;
|
|
1915
|
+
font-size: 24px;
|
|
1916
|
+
}
|
|
1917
|
+
.sp-sidepanel.sp-floating > .cp-header { font-size: var(--fw-header-control-size); }
|
|
1918
|
+
.cp-header > .cp-session-menu { font-size: 1rem; }
|
|
1909
1919
|
.cp-header-actions {
|
|
1910
1920
|
display: flex; align-items: center; gap: 3px; margin-left: auto; flex-shrink: 0;
|
|
1911
1921
|
}
|
|
1922
|
+
/* The header buttons never shrink. The account menu's trigger (account-menu.js) is the one
|
|
1923
|
+
piece of the actions that gives way, once the session name is at its readable 88px, down to
|
|
1924
|
+
its compact 64px, and truncates. */
|
|
1925
|
+
.cp-header-actions > * { flex-shrink: 0; }
|
|
1926
|
+
.cp-header-actions:has(> .acct-menu-trigger) { flex-shrink: 1; min-width: 0; }
|
|
1927
|
+
.cp-header-actions > .acct-menu-trigger { flex-shrink: 1; }
|
|
1928
|
+
/* Narrow headers, in order: the trigger stays at its compact 64px and the name goes from 88px
|
|
1929
|
+
down to its caret; then the trigger is hidden. Room counted in controls (em) plus px: docked,
|
|
1930
|
+
the pencil and six buttons are 7em with 21px of gaps; detached, the move handle makes 8em,
|
|
1931
|
+
the window's 6px gaps 39px, the name's floor is 1em. Thresholds: name + 64px trigger + that row. */
|
|
1932
|
+
@container cp-header (width < calc(7em + 173px)) {
|
|
1933
|
+
.claude-panel:not(.sp-floating) > .cp-header .cp-session-btn { flex: 1 1 0; }
|
|
1934
|
+
.claude-panel:not(.sp-floating) > .cp-header > .cp-header-actions { flex-shrink: 0; }
|
|
1935
|
+
.claude-panel:not(.sp-floating) > .cp-header .acct-menu-trigger { flex: 0 0 64px; width: 64px; }
|
|
1936
|
+
}
|
|
1937
|
+
@container cp-header (width < calc(7em + 117px)) {
|
|
1938
|
+
.claude-panel:not(.sp-floating) > .cp-header .acct-menu-trigger { display: none; }
|
|
1939
|
+
}
|
|
1940
|
+
@container cp-header (width < calc(8em + 191px)) {
|
|
1941
|
+
.claude-panel.sp-floating > .cp-header .cp-session-btn { flex: 1 1 0; }
|
|
1942
|
+
.claude-panel.sp-floating > .cp-header > .cp-header-actions { flex-shrink: 0; }
|
|
1943
|
+
.claude-panel.sp-floating > .cp-header .acct-menu-trigger { flex: 0 0 64px; width: 64px; }
|
|
1944
|
+
}
|
|
1945
|
+
@container cp-header (width < calc(9em + 103px)) {
|
|
1946
|
+
.claude-panel.sp-floating > .cp-header .acct-menu-trigger { display: none; }
|
|
1947
|
+
}
|
|
1912
1948
|
.cp-header-btn {
|
|
1913
1949
|
display: flex; align-items: center; justify-content: center;
|
|
1914
1950
|
width: 24px; height: 24px; border-radius: 7px;
|
|
@@ -1934,14 +1970,18 @@ function injectStyles() {
|
|
|
1934
1970
|
font-size: 11px; font-family: 'JetBrains Mono', monospace;
|
|
1935
1971
|
cursor: pointer; padding: 5px 10px; border-radius: 8px 0 0 8px;
|
|
1936
1972
|
transition: background 0.15s, color 0.15s;
|
|
1937
|
-
|
|
1973
|
+
/* The session name keeps a readable 88px (about 8 characters, or its own width if shorter)
|
|
1974
|
+
and gives way first above that: it grows only into the room the pencil and the actions
|
|
1975
|
+
leave, so a long name never pushes them. Narrower, the container queries above let it go
|
|
1976
|
+
down to 32px (the caret). */
|
|
1977
|
+
flex: 1 0 88px; min-width: 32px; max-width: max-content; overflow: hidden;
|
|
1938
1978
|
}
|
|
1939
1979
|
.cp-session-btn:hover { background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.75); }
|
|
1940
1980
|
.cp-session-btn .cp-session-label {
|
|
1941
|
-
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1981
|
+
min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
1942
1982
|
}
|
|
1943
1983
|
.cp-session-btn .cp-dd-arrow {
|
|
1944
|
-
font-size: 9px; padding: 4px 6px; margin: -4px -6px -4px 0;
|
|
1984
|
+
flex-shrink: 0; font-size: 9px; padding: 4px 6px; margin: -4px -6px -4px 0;
|
|
1945
1985
|
border-radius: 0 6px 6px 0; cursor: pointer;
|
|
1946
1986
|
transition: background 0.15s, color 0.2s, transform 0.2s;
|
|
1947
1987
|
}
|
|
@@ -1956,6 +1996,7 @@ function injectStyles() {
|
|
|
1956
1996
|
-webkit-tap-highlight-color: transparent;
|
|
1957
1997
|
touch-action: manipulation;
|
|
1958
1998
|
flex-shrink: 0;
|
|
1999
|
+
margin-right: 3px; /* the actions' own gap, kept when the name fills the row */
|
|
1959
2000
|
}
|
|
1960
2001
|
.cp-header-rename-btn:hover { color: rgba(100,160,255,0.95); background: rgba(100,160,255,0.14); }
|
|
1961
2002
|
.cp-header-rename-btn:active { transform: scale(0.92); transition-duration: 0.06s; }
|
|
@@ -2299,6 +2340,11 @@ function injectStyles() {
|
|
|
2299
2340
|
.cp-session-pill.cp-pill-running .term-minimized-pill-icon { color: rgba(212, 162, 127, 1); }
|
|
2300
2341
|
.cp-session-pill:hover .term-minimized-pill-icon { color: rgba(212, 162, 127, 0.85); }
|
|
2301
2342
|
.cp-session-pill .term-minimized-pill-icon svg { width: 12px; height: 12px; }
|
|
2343
|
+
/* A session that waits on you (a permission, a plan, an MCP server's request, a question): the
|
|
2344
|
+
warn hairline and mark of the Assistant's and a detached window's pills, in place of the
|
|
2345
|
+
working look (paintPillState). */
|
|
2346
|
+
.cp-session-pill.cp-pill-attention { border-color: color-mix(in srgb, var(--accent-orange, #FFB74D) 42%, transparent); }
|
|
2347
|
+
.cp-session-pill.cp-pill-attention .term-minimized-pill-icon { color: var(--accent-orange, #FFB74D); }
|
|
2302
2348
|
.cp-session-pill.cp-pill-enter {
|
|
2303
2349
|
animation: cp-pill-pop-in 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
2304
2350
|
}
|
|
@@ -2870,6 +2916,7 @@ function newTabState(sessionId = null, label = 'New chat', id = null) {
|
|
|
2870
2916
|
mcpServers: [], // from system/init + mcp_status events
|
|
2871
2917
|
automationRunId: null,
|
|
2872
2918
|
automationActive: false,
|
|
2919
|
+
automationAwaits: false, // the run's turn ended asking the user (runAwaitsAnswer): its pill needs you
|
|
2873
2920
|
automationOwnerId: null,
|
|
2874
2921
|
releasedRunId: null, // the ended run this tab showed before the user continued it by hand
|
|
2875
2922
|
};
|
|
@@ -3162,6 +3209,9 @@ function _createTrayPill(tab) {
|
|
|
3162
3209
|
if (idx >= 0) closeTab(idx);
|
|
3163
3210
|
});
|
|
3164
3211
|
pill.style.display = 'none'; // Hidden by default; renderPills() controls visibility
|
|
3212
|
+
// A pill made after the tab started working (a tray that was not there yet) starts out working too,
|
|
3213
|
+
// or needing you.
|
|
3214
|
+
paintPillState(pill, tab);
|
|
3165
3215
|
tray.appendChild(pill);
|
|
3166
3216
|
return pill;
|
|
3167
3217
|
}
|
|
@@ -3181,8 +3231,10 @@ function _renderPillsNow() {
|
|
|
3181
3231
|
const panelOpen = _visible;
|
|
3182
3232
|
for (let i = 0; i < _tabs.length; i++) {
|
|
3183
3233
|
const tab = _tabs[i];
|
|
3184
|
-
if (!tab.pillEl) tab.pillEl = _createTrayPill(tab);
|
|
3234
|
+
if (!tab.pillEl?.isConnected) tab.pillEl = _createTrayPill(tab);
|
|
3185
3235
|
if (!tab.pillEl) continue;
|
|
3236
|
+
// Every pass says it again: a re-render never leaves a working tab's pill idle.
|
|
3237
|
+
paintPillState(tab.pillEl, tab);
|
|
3186
3238
|
const isActive = i === activeIdx;
|
|
3187
3239
|
const shouldShow = !isActive || !panelOpen;
|
|
3188
3240
|
const wasHidden = tab.pillEl.style.display === 'none';
|
|
@@ -3208,15 +3260,52 @@ function updatePillLabel(tab) {
|
|
|
3208
3260
|
if (lbl) lbl.textContent = tab.label;
|
|
3209
3261
|
}
|
|
3210
3262
|
|
|
3263
|
+
/**
|
|
3264
|
+
* A tab works while its turn runs, and also once the turn ended while background work it started
|
|
3265
|
+
* still runs (agents, shells, workflows: the CLI's own live list, non-ambient, the statusline's count):
|
|
3266
|
+
* the session reports back when they end, so its pill keeps moving, like their cards in the transcript.
|
|
3267
|
+
*/
|
|
3268
|
+
function tabWorking(tab) {
|
|
3269
|
+
return !!tab?.running || (Array.isArray(tab?.backgroundWork) && tab.backgroundWork.length > 0);
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
/**
|
|
3273
|
+
* A tab needs you while its session waits on your answer: a permission, a plan approval or an MCP
|
|
3274
|
+
* server's request (the card on screen, and the ones queued behind it), or a question; and, for a
|
|
3275
|
+
* dispatched worker, while its turn ended asking you something (the run's outcome: automationAwaits).
|
|
3276
|
+
*/
|
|
3277
|
+
function tabNeedsYou(tab) {
|
|
3278
|
+
return !!(tab?._activePerm || tab?._permQueue?.length || tab?.pendingAskRequestId || tab?.automationAwaits);
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
/** What a tab's pill says: it needs you > it works > it rests (read for a detached window's pill too). */
|
|
3282
|
+
function paintPillState(pill, tab) {
|
|
3283
|
+
const needsYou = tabNeedsYou(tab);
|
|
3284
|
+
pill.classList.toggle('cp-pill-attention', needsYou);
|
|
3285
|
+
pill.classList.toggle('cp-pill-running', !needsYou && tabWorking(tab));
|
|
3286
|
+
}
|
|
3287
|
+
|
|
3288
|
+
// Whether each tab was saved needing you: a change is written at once, for the placeholder a reload
|
|
3289
|
+
// shows and the pill of a detached window that has not loaded yet (ui-sidepanel-tray.js).
|
|
3290
|
+
const _needsYouSaved = new WeakMap();
|
|
3211
3291
|
function updatePillRunning(tab) {
|
|
3212
|
-
if (tab.pillEl) tab.pillEl
|
|
3292
|
+
if (tab.pillEl) paintPillState(tab.pillEl, tab);
|
|
3293
|
+
const needsYou = tabNeedsYou(tab);
|
|
3294
|
+
if ((_needsYouSaved.get(tab) || false) === needsYou) return;
|
|
3295
|
+
_needsYouSaved.set(tab, needsYou);
|
|
3296
|
+
saveTabs();
|
|
3213
3297
|
}
|
|
3214
3298
|
|
|
3215
3299
|
function saveTabs() {
|
|
3216
3300
|
try {
|
|
3217
3301
|
// A temporary tab is never written: not the tab, its label, its queue or its session id.
|
|
3302
|
+
// `backgroundWork`: how many background agents and shells it still ran (tabWorking). A tab whose turn
|
|
3303
|
+
// ended while they run is working too: after a reload its placeholder says so and the panel loads to ask
|
|
3304
|
+
// (ui-sidepanel-tray.js). Never restored: the reattach's live list says what still runs. `needsYou`:
|
|
3305
|
+
// a permission or a question waited on the user (tabNeedsYou): its placeholder says so and the panel
|
|
3306
|
+
// loads to ask, and the reattach brings the card back.
|
|
3218
3307
|
const kept = persistableTabs(_tabs, _activeTabIdx);
|
|
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 }));
|
|
3308
|
+
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, backgroundWork: Array.isArray(t.backgroundWork) ? t.backgroundWork.length : 0, needsYou: tabNeedsYou(t), 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 }));
|
|
3220
3309
|
const localRunIds = new Set(localTabs.map((tab) => tab.automationRunId).filter(Boolean));
|
|
3221
3310
|
let foreignAutomationTabs = [];
|
|
3222
3311
|
try {
|
|
@@ -4511,9 +4600,9 @@ function flushAllSessionSnapshots() {
|
|
|
4511
4600
|
function renderStoredSession(snapshot, $msgs, tab) {
|
|
4512
4601
|
const norm = _normalizeSnapshotEntry(snapshot);
|
|
4513
4602
|
if (!norm || !$msgs) return false;
|
|
4514
|
-
// A snapshot comes back from storage and may predate the sanitiser:
|
|
4515
|
-
//
|
|
4516
|
-
$msgs.replaceChildren(
|
|
4603
|
+
// A snapshot comes back from storage and may predate the sanitiser: it is rebuilt
|
|
4604
|
+
// from the stored-transcript allowlist every panel uses (asst-sanitize.js).
|
|
4605
|
+
$msgs.replaceChildren(sanitizeStoredHtml(norm.html));
|
|
4517
4606
|
// Restored DOM has no event handlers. Pending prompts (permission, plan, ask
|
|
4518
4607
|
// cards) are stale and go, answered ones stay inert; the read-only actions
|
|
4519
4608
|
// are wired again from what the markup saved: rewind (prompt uuid), the
|
|
@@ -5243,10 +5332,14 @@ function _setBackgroundWork(tab, tasks) {
|
|
|
5243
5332
|
// reloaded while it ran) gets one, so /tasks can show and stop it.
|
|
5244
5333
|
try { adoptLiveTasks(tab.tasks, tasks); } catch {}
|
|
5245
5334
|
try { reconcileTasks(tab.tasks, tasks); } catch {}
|
|
5335
|
+
const before = Array.isArray(tab.backgroundWork) ? tab.backgroundWork.length : 0;
|
|
5246
5336
|
tab.backgroundWork = (Array.isArray(tasks) ? tasks : [])
|
|
5247
5337
|
.filter(t => t && !t.ambient)
|
|
5248
5338
|
.map(t => ({ id: t.task_id, type: t.task_type || '', description: t.description || '' }));
|
|
5249
5339
|
if (tab === activeTab()) { try { renderStatusline(tab); } catch {} }
|
|
5340
|
+
updatePillRunning(tab);
|
|
5341
|
+
// Saved as it changes: a reload with only this left running loads the panel to ask (saveTabs).
|
|
5342
|
+
if (tab.backgroundWork.length !== before) saveTabs();
|
|
5250
5343
|
}
|
|
5251
5344
|
|
|
5252
5345
|
function _processTabMsg(tab, msg) {
|
|
@@ -5304,6 +5397,7 @@ function _processTabMsg(tab, msg) {
|
|
|
5304
5397
|
if (tab._pendingPlan?.requestId === msg.request_id) tab._pendingPlan = null;
|
|
5305
5398
|
if (tab._activePerm) { tab._activePerm = false; _showNextPerm(tab); }
|
|
5306
5399
|
else _flushMsgBuffer(tab);
|
|
5400
|
+
updatePillRunning(tab);
|
|
5307
5401
|
break;
|
|
5308
5402
|
}
|
|
5309
5403
|
case 'reattach_result': {
|
|
@@ -6846,6 +6940,7 @@ function sendAskAnswer(tab, questions, answers, annotations = null) {
|
|
|
6846
6940
|
tab.pendingAskRequestId = null;
|
|
6847
6941
|
tab.pendingAskToolUseId = null;
|
|
6848
6942
|
tab.pendingAskBufferedAnswer = null;
|
|
6943
|
+
updatePillRunning(tab); // answered: the pill no longer needs you
|
|
6849
6944
|
// Flush BEFORE clearing askRenderedViaControl — buffered assistant events
|
|
6850
6945
|
// must see the flag so buildAskFromToolUse returns a hidden placeholder
|
|
6851
6946
|
// instead of rendering a duplicate card.
|
|
@@ -7361,6 +7456,7 @@ function handleControlRequest(tab, msg) {
|
|
|
7361
7456
|
if (toolName === 'AskUserQuestion') {
|
|
7362
7457
|
// AskUserQuestion: save the request_id — answer is sent via control_response when user picks an option
|
|
7363
7458
|
tab.pendingAskRequestId = requestId;
|
|
7459
|
+
updatePillRunning(tab); // the pill needs you
|
|
7364
7460
|
// If tool_use block hasn't rendered the ask card yet, render from control_request input
|
|
7365
7461
|
// Also check askRenderedViaControl to prevent duplicate cards from denial control_requests
|
|
7366
7462
|
if (!tab.pendingAskToolUseId && !tab.askRenderedViaControl) {
|
|
@@ -8462,6 +8558,7 @@ function finishTab(tab, skipNotif) {
|
|
|
8462
8558
|
if (tab.sessionId && tab._snapshotDirty) flushSessionSnapshotSave(tab);
|
|
8463
8559
|
hideThinking(tab); setRunning(tab, false); tab._wasRunning = false; tab.currentMsgEl = null; tab.currentMsgId = null; tab.pendingAskToolUseId = null; tab.pendingAskRequestId = null; tab.pendingAskBufferedAnswer = null; tab.askRenderedViaControl = false; tab.sendStartedAt = null; tab._planContentCaptured = false; if (tab._stream?.mdTimer) clearTimeout(tab._stream.mdTimer); tab._stream = null;
|
|
8464
8560
|
tab.currentActivity = null;
|
|
8561
|
+
updatePillRunning(tab); // (its question went with the turn)
|
|
8465
8562
|
if (tab === activeTab()) { try { renderStatusline(tab); } catch {} }
|
|
8466
8563
|
if (tab.compacting) { tab.compacting = false; if (tab === activeTab()) _setCompactingUI(false); }
|
|
8467
8564
|
tab._compactSentAt = 0; // a Compact the user started ends here too (cp-compose.js)
|
|
@@ -10308,6 +10405,14 @@ function applyClaudeVisibility(visible) {
|
|
|
10308
10405
|
|
|
10309
10406
|
export function isClaudePanelOpen() { return _visible; }
|
|
10310
10407
|
|
|
10408
|
+
/**
|
|
10409
|
+
* Boot the panel without showing it (ui-sidepanel-tray.js, when a tab saved while it worked comes back
|
|
10410
|
+
* after a reload): its tabs reconnect and reattach, so their pills say what the sessions do now.
|
|
10411
|
+
*/
|
|
10412
|
+
export async function bootClaudePanel() {
|
|
10413
|
+
await _ensureClaudePanelReady();
|
|
10414
|
+
}
|
|
10415
|
+
|
|
10311
10416
|
export function endHostedClaudeSessions() {
|
|
10312
10417
|
while (_tabs.length) closeTab(_tabs.length - 1);
|
|
10313
10418
|
}
|
|
@@ -10357,6 +10462,8 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10357
10462
|
tab.project = run.cwd || tab.project;
|
|
10358
10463
|
tab.model = run.model || tab.model;
|
|
10359
10464
|
tab.effort = run.effort || tab.effort;
|
|
10465
|
+
// A warm worker whose turn ended on a question needs you, like one with a card up (setRunning repaints).
|
|
10466
|
+
tab.automationAwaits = runAwaitsAnswer(run);
|
|
10360
10467
|
setRunning(tab, running);
|
|
10361
10468
|
updatePillLabel(tab);
|
|
10362
10469
|
tab._automationIteration = run.currentIteration;
|
|
@@ -11605,6 +11712,13 @@ function wireEvents() {
|
|
|
11605
11712
|
const $sessMenu = _panel.querySelector('#cp-session-menu');
|
|
11606
11713
|
const $sessLabel = _panel.querySelector('.cp-session-label');
|
|
11607
11714
|
let _sessClickTimer = null;
|
|
11715
|
+
// The whole name as the chip's tooltip, for when the header shows only part of it. The label is
|
|
11716
|
+
// written from many places (switch, rename, title, reset), so it follows the label itself.
|
|
11717
|
+
const syncSessionTooltip = () => {
|
|
11718
|
+
if (!$sessLabel.querySelector('.cp-rename-input')) $sessBtn.title = $sessLabel.textContent;
|
|
11719
|
+
};
|
|
11720
|
+
syncSessionTooltip();
|
|
11721
|
+
new MutationObserver(syncSessionTooltip).observe($sessLabel, { childList: true, characterData: true, subtree: true });
|
|
11608
11722
|
|
|
11609
11723
|
$sessBtn.addEventListener('click', (e) => {
|
|
11610
11724
|
// Block menu toggle while rename input is active
|
|
@@ -12,7 +12,7 @@ import { updateMemory, deleteMemory, fetchMemory } from './api.js';
|
|
|
12
12
|
import { KEYS } from './constants.js';
|
|
13
13
|
import { storage } from './storage.js';
|
|
14
14
|
import { catColor } from './colors.js';
|
|
15
|
-
import { truncate, formatMemoryContent, exportMemoryAsMarkdown, rafThrottle } from './utils.js';
|
|
15
|
+
import { truncate, formatMemoryContent, exportMemoryAsMarkdown, rafThrottle, escapeHtml } from './utils.js';
|
|
16
16
|
import { t, getLocale } from './i18n.js';
|
|
17
17
|
import { savePanelLayout, restorePanelLayout } from './ui-panels.js';
|
|
18
18
|
import { sendSync as _sendSync, hasPermission, isGuest } from './ui-sync.js';
|
|
@@ -111,7 +111,7 @@ function showTagDeleteModal(tagName, onConfirm) {
|
|
|
111
111
|
overlay.innerHTML = `
|
|
112
112
|
<div class="tag-delete-modal">
|
|
113
113
|
<div class="tag-delete-modal-title">Remove tag</div>
|
|
114
|
-
<div class="tag-delete-modal-tag">${tagName}</div>
|
|
114
|
+
<div class="tag-delete-modal-tag">${escapeHtml(tagName)}</div>
|
|
115
115
|
<div class="tag-delete-modal-actions">
|
|
116
116
|
<button class="action-btn action-btn--ghost tag-modal-cancel">Cancel</button>
|
|
117
117
|
<button class="action-btn action-btn--danger tag-modal-confirm">Delete</button>
|
|
@@ -363,7 +363,7 @@ function openCategoryChangeModal(card, node) {
|
|
|
363
363
|
<div class="cat-opt-dot" style="color:${catColor(cat)}; background:${catColor(cat)}"></div>
|
|
364
364
|
<div class="cat-opt-info">
|
|
365
365
|
<span class="cat-opt-name">${cat}</span>
|
|
366
|
-
${desc ? `<span class="cat-opt-desc">${desc}</span>` : ''}
|
|
366
|
+
${desc ? `<span class="cat-opt-desc">${escapeHtml(desc)}</span>` : ''}
|
|
367
367
|
</div>
|
|
368
368
|
</div>`;
|
|
369
369
|
}
|
|
@@ -375,7 +375,7 @@ function openCategoryChangeModal(card, node) {
|
|
|
375
375
|
<div class="cat-opt-dot" style="color:${catColor(cat)}; background:${catColor(cat)}"></div>
|
|
376
376
|
<div class="cat-opt-info">
|
|
377
377
|
<span class="cat-opt-name">${cat}</span>
|
|
378
|
-
${desc ? `<span class="cat-opt-desc">${desc}</span>` : ''}
|
|
378
|
+
${desc ? `<span class="cat-opt-desc">${escapeHtml(desc)}</span>` : ''}
|
|
379
379
|
</div>
|
|
380
380
|
${isActive ? '<svg class="cat-opt-check" viewBox="0 0 24 24"><path d="M20 6L9 17l-5-5"/></svg>' : ''}
|
|
381
381
|
</div>`;
|
|
@@ -863,7 +863,7 @@ export function openMemoryCard(node, savedPosition) {
|
|
|
863
863
|
if (!value) return;
|
|
864
864
|
const row = document.createElement('div');
|
|
865
865
|
row.className = 'detail-meta-row';
|
|
866
|
-
row.innerHTML = `<span style="color:rgba(255,255,255,0.3)">${label}</span><span>${value}</span>`;
|
|
866
|
+
row.innerHTML = `<span style="color:rgba(255,255,255,0.3)">${label}</span><span>${escapeHtml(String(value))}</span>`;
|
|
867
867
|
meta.appendChild(row);
|
|
868
868
|
};
|
|
869
869
|
addMeta('Project', p.project);
|
|
@@ -893,7 +893,7 @@ export function openMemoryCard(node, savedPosition) {
|
|
|
893
893
|
const filesContent = q(card, 'files-content');
|
|
894
894
|
if (p.related_files && p.related_files.length) {
|
|
895
895
|
filesContent.innerHTML = p.related_files.map(f =>
|
|
896
|
-
`<div style="font-family:'JetBrains Mono','SF Mono',Consolas,monospace;font-size:12px;color:rgba(255,255,255,0.45);padding:2px 0">${f}</div>`
|
|
896
|
+
`<div style="font-family:'JetBrains Mono','SF Mono',Consolas,monospace;font-size:12px;color:rgba(255,255,255,0.45);padding:2px 0">${escapeHtml(String(f))}</div>`
|
|
897
897
|
).join('');
|
|
898
898
|
filesDiv.style.display = '';
|
|
899
899
|
} else {
|
|
@@ -1441,6 +1441,8 @@ export function initExplorer() {
|
|
|
1441
1441
|
if (selectAllBtn) {
|
|
1442
1442
|
selectAllBtn.addEventListener('click', () => {
|
|
1443
1443
|
Object.keys(state.categoryMetadata).forEach(c => state.activeCategories.add(c));
|
|
1444
|
+
// and the categories memories use without a registered one ("uncategorized" included), as the sidebar does
|
|
1445
|
+
(state.allNodes || []).forEach(n => { if (n.payload?.category) state.activeCategories.add(n.payload.category); });
|
|
1444
1446
|
cancelScheduledRemoval();
|
|
1445
1447
|
emit('graph:refresh');
|
|
1446
1448
|
emit('categories-changed');
|
|
@@ -65,6 +65,7 @@ const handlers = createFileLinkHandlers({
|
|
|
65
65
|
say: fileLinkText,
|
|
66
66
|
notify: showFileLinkNotice,
|
|
67
67
|
follow: (anchor) => {
|
|
68
|
+
if (anchor.protocol !== 'http:' && anchor.protocol !== 'https:') return; // an address of this app, never a script link
|
|
68
69
|
if (anchor.target === '_blank') window.open(anchor.href, '_blank', 'noopener,noreferrer');
|
|
69
70
|
else window.location.assign(anchor.href);
|
|
70
71
|
},
|