synabun 2.0.7 → 2.0.9
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 +38 -0
- package/README.md +1 -1
- 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/lib/package-processes.js +670 -0
- package/lib/runtime-dependencies.js +225 -0
- 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 +18 -0
- package/neural-interface/i18n/pt-BR.json +18 -0
- package/neural-interface/lib/agent-sandbox-elevation.js +102 -0
- package/neural-interface/lib/agent-sandbox-setting.js +57 -0
- package/neural-interface/lib/assistant-api.js +19 -0
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -1
- package/neural-interface/lib/assistant-runtime.js +5 -1
- 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 +5 -3
- package/neural-interface/lib/exec-loop-command.js +3 -1
- package/neural-interface/lib/install-details.js +23 -5
- package/neural-interface/lib/native-loop-providers.js +6 -1
- package/neural-interface/lib/provider-panel-terminal-auth.js +3 -2
- package/neural-interface/lib/session-indexer.js +3 -1
- package/neural-interface/lib/session-title-generator.js +2 -0
- package/neural-interface/package-lock.json +2 -2
- package/neural-interface/package.json +1 -1
- 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/assistant/asst-account-menu.js +298 -0
- package/neural-interface/public/shared/assistant/asst-api.js +7 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +232 -75
- package/neural-interface/public/shared/assistant/asst-menu.js +204 -77
- package/neural-interface/public/shared/assistant/asst-model-chip.js +135 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +39 -2
- package/neural-interface/public/shared/assistant/asst-styles.js +66 -17
- package/neural-interface/public/shared/cdx/cdx-panel.js +1 -1
- package/neural-interface/public/shared/cdx/cdx-styles.js +45 -5
- package/neural-interface/public/shared/cdx/cdx-tabs.js +3 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +4 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +51 -2
- package/neural-interface/public/shared/showcase-privacy.js +2 -1
- package/neural-interface/public/shared/styles.css +3 -1
- package/neural-interface/public/shared/ui-claude-panel.js +50 -4
- package/neural-interface/public/shared/ui-explorer.js +2 -0
- package/neural-interface/public/shared/ui-sync.js +2 -0
- package/neural-interface/public/shared/ui-update.js +4 -2
- package/neural-interface/scripts/rebuild-pty.js +14 -2
- package/neural-interface/server.js +180 -86
- 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 +1 -1
- package/updater.cmd +2 -2
- package/updater.mjs +97 -3
|
@@ -30,10 +30,12 @@ import { getHiddenModels, HIDDEN_MODELS_EVENT, hiddenModelMatch } from '../ocp-h
|
|
|
30
30
|
import { getProviderMeta } from '../provider-icons.js';
|
|
31
31
|
import { on } from '../state.js';
|
|
32
32
|
import { fetchAssistantCatalog, fetchProjects, patchClaudeAccount, patchCodexAccount, setClaudeWorkerAccount, setCodexWorkerAccount } from './asst-api.js';
|
|
33
|
-
import { accountBadge,
|
|
34
|
-
import {
|
|
33
|
+
import { accountBadge, accountIdentity, accountName, accountText } from '../account-view.js';
|
|
34
|
+
import { autoAccountLabel } from '../account-usage.js';
|
|
35
|
+
import { accountChoiceItems, accountManageItem, accountMenuRow, accountModeItem, openAccountMenu } from './asst-account-menu.js';
|
|
35
36
|
import { closeMenu, currentMenu, isMenuOpen, openMenu } from './asst-menu.js';
|
|
36
37
|
import { createMascotControl } from './asst-mascot.js';
|
|
38
|
+
import { modelChipForms, modelChipName, modelChipTag } from './asst-model-chip.js';
|
|
37
39
|
import {
|
|
38
40
|
ACCOUNT_PROVIDERS,
|
|
39
41
|
brainRequiresSwitch,
|
|
@@ -79,6 +81,10 @@ const TEST_DENSITY_COPY = {
|
|
|
79
81
|
thorough: ['Thorough', 'Full coverage, whole suite, live checks.'],
|
|
80
82
|
};
|
|
81
83
|
|
|
84
|
+
// English copy of the Admin sandbox row (i18n: assistant.adminSandbox.hint). Names only Codex: the
|
|
85
|
+
// one provider it changes (lib/agent-sandbox-elevation.js; Claude Code and OpenCode are no-ops).
|
|
86
|
+
export const ADMIN_SANDBOX_HINT = 'Only changes anything when SynaBun runs on Windows. On: Codex can set up its strongest sandbox, which asks for administrator approval once per account. Off: no admin prompt; Codex uses a sandbox that needs no admin, with weaker isolation.';
|
|
87
|
+
|
|
82
88
|
/** "Light" — the level's name (a missing or unknown level is the default one). */
|
|
83
89
|
export function testDensityLabel(level, t) {
|
|
84
90
|
const id = normalizeTestDensity(level);
|
|
@@ -416,7 +422,8 @@ function tierTag(m, tr) {
|
|
|
416
422
|
* opts: { brain, onSelect(target), includeHere, hereLabel, title, t, placement,
|
|
417
423
|
* current:{provider, model}|null, warnSwitch, providers, onToast(text),
|
|
418
424
|
* accept(provider, model) → bool (only those models), emptyLabel (when none
|
|
419
|
-
* passes), allowCustom (default true), zIndex (see asst-menu.js)
|
|
425
|
+
* passes), allowCustom (default true), zIndex (see asst-menu.js),
|
|
426
|
+
* accountItems (menu items listed first, under accountTitle) }
|
|
420
427
|
* target: { provider, model, label, tier, vision, outputs, efforts, price } | { here: true }
|
|
421
428
|
*/
|
|
422
429
|
export async function openModelMenu(anchor, opts = {}) {
|
|
@@ -444,7 +451,7 @@ export async function openModelMenu(anchor, opts = {}) {
|
|
|
444
451
|
const metadata = modelCatalogStatus();
|
|
445
452
|
const items = [];
|
|
446
453
|
if (Array.isArray(opts.accountItems) && opts.accountItems.length) {
|
|
447
|
-
items.push({ kind: 'header', label: tr('assistant.brain.account', 'Account profile') }, ...opts.accountItems, { kind: 'separator' });
|
|
454
|
+
items.push({ kind: 'header', label: opts.accountTitle || tr('assistant.brain.account', 'Account profile') }, ...opts.accountItems, { kind: 'separator' });
|
|
448
455
|
}
|
|
449
456
|
if (includeHere) {
|
|
450
457
|
items.push({ kind: 'radio', id: '__here', label: hereLabel || tr('assistant.routes.brainDecides', 'Let the brain decide'), selected: !current, onSelect: () => onSelect?.({ here: true }) });
|
|
@@ -642,11 +649,39 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
642
649
|
return name;
|
|
643
650
|
}
|
|
644
651
|
|
|
652
|
+
// The "⋯" item's value, in the account menu's words: the name and its plan, "API key" or "Signed out" ("Default · Max").
|
|
653
|
+
function accountValue(brain) {
|
|
654
|
+
const acc = accountOf(brain);
|
|
655
|
+
if (!acc) return brain.accountId === 'auto' ? autoAccountLabel(hooks.t) : (brain.accountId || t('assistant.brain.accountDefault', 'Default'));
|
|
656
|
+
const row = accountMenuRow(acc, { provider: accountProvider(brain), t: hooks.t });
|
|
657
|
+
return [row.name, row.badge.text].filter(Boolean).join(' · ');
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// The model menu's own row first: it also names the "[1m]" / "[extended]" variants the provider list lacks.
|
|
661
|
+
function modelRow(brain) {
|
|
662
|
+
return catalogModelRow(brain.provider, brain.model) || modelOf(brain);
|
|
663
|
+
}
|
|
664
|
+
|
|
645
665
|
function modelLabel(brain = currentBrain()) {
|
|
646
|
-
const model =
|
|
666
|
+
const model = modelRow(brain);
|
|
647
667
|
return model ? (model.label || modelShortName(model.id)) : (brain.model ? modelShortName(brain.model) : t('assistant.brain.modelDefault', 'Default model'));
|
|
648
668
|
}
|
|
649
669
|
|
|
670
|
+
// The composer chip's account cue: the account menu's initial avatar when the provider has more than one
|
|
671
|
+
// account (or the account is signed out), "Auto" for Auto; null otherwise. Its full words are the tooltip's.
|
|
672
|
+
function accountCue(brain) {
|
|
673
|
+
if (!ACCOUNT_PROVIDERS.has(brain.provider)) return null;
|
|
674
|
+
if (brain.accountId === 'auto') return { text: t('assistant.brain.accountAutoShort', 'Auto'), tone: 'muted' };
|
|
675
|
+
const accounts = brain.provider === 'codex' ? getCachedCodexAccounts() : getCachedClaudeAccounts();
|
|
676
|
+
const acc = accountOf(brain);
|
|
677
|
+
const signedOut = acc?.signedIn === false;
|
|
678
|
+
if (accounts.length < 2 && !signedOut) return null;
|
|
679
|
+
const initial = acc
|
|
680
|
+
? accountMenuRow(acc, { provider: accountProvider(brain), t: hooks.t }).initial
|
|
681
|
+
: Array.from(String(brain.accountId || t('assistant.brain.accountDefault', 'Default')).trim())[0]?.toLocaleUpperCase();
|
|
682
|
+
return { text: initial || '?', tone: signedOut ? 'warn' : 'muted' };
|
|
683
|
+
}
|
|
684
|
+
|
|
650
685
|
function values(brain = currentBrain()) {
|
|
651
686
|
const meta = getProviderMeta(brain.provider);
|
|
652
687
|
const efforts = effortsFor(brain);
|
|
@@ -669,6 +704,26 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
669
704
|
};
|
|
670
705
|
}
|
|
671
706
|
|
|
707
|
+
/**
|
|
708
|
+
* The permission menu's Admin sandbox row (a check: the global setting, every agent SynaBun starts),
|
|
709
|
+
* or null while the host has none to show (a server that does not serve it). Its tooltip and
|
|
710
|
+
* aria-label say the value in effect.
|
|
711
|
+
*/
|
|
712
|
+
function adminSandboxItem() {
|
|
713
|
+
const on = typeof hooks.getAdminSandbox === 'function' ? hooks.getAdminSandbox() : null;
|
|
714
|
+
if (typeof on !== 'boolean') return null;
|
|
715
|
+
const label = t('assistant.adminSandbox.label', 'Admin sandbox');
|
|
716
|
+
const value = on ? t('assistant.adminSandbox.on', 'On') : t('assistant.adminSandbox.off', 'Off');
|
|
717
|
+
const hint = t('assistant.adminSandbox.hint', ADMIN_SANDBOX_HINT);
|
|
718
|
+
return {
|
|
719
|
+
kind: 'check', id: 'admin-sandbox', label, desc: hint, checked: on,
|
|
720
|
+
className: 'asst-admin-sandbox-item',
|
|
721
|
+
title: `${label}: ${value}. ${hint}`,
|
|
722
|
+
ariaLabel: t('assistant.adminSandbox.aria', '{label}: {value}. Only changes anything when SynaBun runs on Windows.', { label, value }),
|
|
723
|
+
onSelect: () => hooks.onAdminSandbox?.(!on),
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
|
|
672
727
|
/** The session's Test density, or null while the host has none to show (a server that does not know it). */
|
|
673
728
|
function testDensity() {
|
|
674
729
|
const level = typeof hooks.getTestDensity === 'function' ? hooks.getTestDensity() : null;
|
|
@@ -689,21 +744,117 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
689
744
|
btn.setAttribute('aria-label', aria || tooltip || label || field);
|
|
690
745
|
}
|
|
691
746
|
|
|
747
|
+
// The composer's model chip (asst-model-chip.js): the model's short name, a context tag for a variant,
|
|
748
|
+
// the account cue and "API" on an API key, never the credential's name (the provider icon says it).
|
|
749
|
+
// Model label, id, account, who it is and what it runs on are the tooltip and aria-label.
|
|
750
|
+
// fitModelChip() draws the longest form that fits the row.
|
|
751
|
+
let chipForms = [];
|
|
752
|
+
let chipParts = null;
|
|
753
|
+
let chipCatalog = null;
|
|
754
|
+
function renderModelChip(brain, v) {
|
|
755
|
+
const btn = buttons.model;
|
|
756
|
+
// The catalog was dropped (a model hidden, a provider's list changed): read it again, then the label.
|
|
757
|
+
if (!cachedModelCatalog() && !chipCatalog) {
|
|
758
|
+
chipCatalog = loadModelCatalog().catch(() => null).then(() => {
|
|
759
|
+
chipCatalog = null;
|
|
760
|
+
if (!destroyed && cachedModelCatalog()) render();
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
const row = modelRow(brain);
|
|
764
|
+
const id = brain.model || row?.id || '';
|
|
765
|
+
const { name, raw } = id ? modelChipName(row?.label, id) : { name: v.model, raw: false };
|
|
766
|
+
const tag = modelChipTag(id, { contextWindow: row?.contextWindow, label: row?.label });
|
|
767
|
+
const cue = accountCue(brain);
|
|
768
|
+
const p = accountProvider(brain);
|
|
769
|
+
const acc = ACCOUNT_PROVIDERS.has(brain.provider) ? accountOf(brain) : null;
|
|
770
|
+
const api = acc && acc.signedIn !== false && acc.mode === 'apiKey' ? accountText('apiShort', {}, p) : '';
|
|
771
|
+
const names = (cachedModelCatalog()?.[brain.provider] || []).map(m => modelChipName(m.label, m.id).name);
|
|
772
|
+
chipForms = modelChipForms({ name, names, tag: !!tag, cue: !!cue, api: !!api });
|
|
773
|
+
|
|
774
|
+
const who = !ACCOUNT_PROVIDERS.has(brain.provider) ? ''
|
|
775
|
+
: brain.accountId === 'auto' ? autoAccountLabel(hooks.t)
|
|
776
|
+
: acc ? accountName(acc, p) : (brain.accountId || t('assistant.brain.accountDefault', 'Default'));
|
|
777
|
+
const model = brain.model && v.model !== brain.model ? `${v.model} · ${brain.model}` : (brain.model || v.model);
|
|
778
|
+
const tip = [
|
|
779
|
+
v.meta.label, model, who ? t('assistant.brain.asAccount', 'as {account}', { account: who }) : '',
|
|
780
|
+
acc ? accountIdentity(acc) : '', acc ? accountBadge(acc, p).text : '',
|
|
781
|
+
].filter(Boolean).join(' · ');
|
|
782
|
+
setBtn('model', { label: '', icon: v.meta.icon, color: v.meta.color, tooltip: tip, aria: `${t('assistant.brain.model', 'Model')}: ${tip}` });
|
|
783
|
+
|
|
784
|
+
const label = btn.querySelector('.asst-dd-label');
|
|
785
|
+
label.classList.add('asst-model-label');
|
|
786
|
+
chipParts = {
|
|
787
|
+
name: el('span', 'asst-model-name', name),
|
|
788
|
+
tag: el('span', 'asst-model-tag', tag),
|
|
789
|
+
cue: el('span', 'asst-acct-avatar asst-model-cue', cue?.text || ''),
|
|
790
|
+
api: el('span', 'asst-acct-badge asst-model-api', api),
|
|
791
|
+
};
|
|
792
|
+
if (cue) chipParts.cue.dataset.tone = cue.tone;
|
|
793
|
+
label.replaceChildren(chipParts.name, chipParts.tag, chipParts.cue, chipParts.api);
|
|
794
|
+
// A display name ("Sonnet 5") reads in sans; a raw id nothing names ("opus") stays mono.
|
|
795
|
+
btn.toggleAttribute('data-raw', raw);
|
|
796
|
+
fitModelChip();
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function drawChipForm(form) {
|
|
800
|
+
chipParts.name.textContent = form.name;
|
|
801
|
+
chipParts.tag.hidden = !form.tag;
|
|
802
|
+
chipParts.cue.hidden = !form.cue;
|
|
803
|
+
chipParts.api.hidden = !form.api;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// The first form, longest first, that leaves the row as the shortest one does: no part cut, no other
|
|
807
|
+
// field narrower, the row no taller (it wraps below 320px). None does: the shortest, its name squeezed.
|
|
808
|
+
function fitModelChip() {
|
|
809
|
+
const btn = buttons.model;
|
|
810
|
+
if (destroyed || !btn || !chipParts || !chipForms.length) return;
|
|
811
|
+
btn.removeAttribute('data-squeezed');
|
|
812
|
+
const label = btn.querySelector('.asst-dd-label');
|
|
813
|
+
const slot = btn.parentElement;
|
|
814
|
+
// Nothing to measure (not on screen, no layout): the whole chip, until the row has a width.
|
|
815
|
+
if (chipForms.length === 1 || !isRendered(btn) || !slot || typeof label?.getBoundingClientRect !== 'function') { drawChipForm(chipForms[0]); return; }
|
|
816
|
+
const row = slot.parentElement || null;
|
|
817
|
+
const others = [...slot.querySelectorAll('.asst-dd-label')].filter(n => n !== label && n.getClientRects().length > 0);
|
|
818
|
+
const width = n => n.getBoundingClientRect().width;
|
|
819
|
+
const cut = () => {
|
|
820
|
+
const right = label.getBoundingClientRect().right + 0.5;
|
|
821
|
+
return Object.values(chipParts).some(n => !n.hidden && n.getBoundingClientRect().right > right);
|
|
822
|
+
};
|
|
823
|
+
const shortest = chipForms[chipForms.length - 1];
|
|
824
|
+
drawChipForm(shortest);
|
|
825
|
+
const base = { height: row?.offsetHeight || 0, widths: others.map(width) };
|
|
826
|
+
const fits = () => !cut()
|
|
827
|
+
&& (row?.offsetHeight || 0) <= base.height + 0.5
|
|
828
|
+
&& others.every((n, i) => width(n) >= base.widths[i] - 0.5)
|
|
829
|
+
&& !(slot.scrollWidth > slot.clientWidth + 1);
|
|
830
|
+
for (const form of chipForms.slice(0, -1)) {
|
|
831
|
+
drawChipForm(form);
|
|
832
|
+
if (fits()) return;
|
|
833
|
+
}
|
|
834
|
+
drawChipForm(shortest);
|
|
835
|
+
btn.toggleAttribute('data-squeezed', cut());
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// The row's width decides the form (a panel resized, a tab shown, the fields that collapse to glyphs).
|
|
839
|
+
const fitHost = buttons.model.parentElement?.parentElement || buttons.model.parentElement;
|
|
840
|
+
let fitFrame = 0;
|
|
841
|
+
let fitWidth = -1;
|
|
842
|
+
const scheduleFit = () => {
|
|
843
|
+
if (fitFrame || destroyed || typeof requestAnimationFrame !== 'function') return;
|
|
844
|
+
fitFrame = requestAnimationFrame(() => { fitFrame = 0; fitModelChip(); });
|
|
845
|
+
};
|
|
846
|
+
const fitObserver = typeof ResizeObserver === 'function' && fitHost ? new ResizeObserver((entries) => {
|
|
847
|
+
const w = Math.round(entries[entries.length - 1]?.contentRect?.width || 0);
|
|
848
|
+
if (w !== fitWidth) { fitWidth = w; scheduleFit(); }
|
|
849
|
+
}) : null;
|
|
850
|
+
fitObserver?.observe(fitHost);
|
|
851
|
+
if (typeof document !== 'undefined') document.fonts?.ready?.then(scheduleFit).catch(() => {});
|
|
852
|
+
|
|
692
853
|
function render() {
|
|
693
854
|
if (destroyed) return;
|
|
694
855
|
const brain = currentBrain();
|
|
695
856
|
const v = values(brain);
|
|
696
|
-
|
|
697
|
-
setBtn('model', { label: v.model, icon: v.meta.icon, color: v.meta.color, tooltip: modelTip, aria: `${t('assistant.brain.model', 'Model')}: ${modelTip}` });
|
|
698
|
-
if (ACCOUNT_PROVIDERS.has(brain.provider)) {
|
|
699
|
-
const acc = accountOf(brain);
|
|
700
|
-
const label = buttons.model.querySelector('.asst-dd-label');
|
|
701
|
-
label.classList.add('asst-model-account-label');
|
|
702
|
-
const mode = acc ? accountCompactMode(acc, accountProvider(brain)) : t('accounts.checking', 'Checking…');
|
|
703
|
-
label.replaceChildren(el('span', 'asst-model-name', v.model), el('span', '', '·'), el('span', 'asst-model-account', acc ? accountName(acc, accountProvider(brain)) : brain.accountId || t('assistant.brain.accountDefault', 'Default')), el('span', '', '·'), el('span', 'asst-model-mode', mode));
|
|
704
|
-
} else buttons.model.querySelector('.asst-dd-label').classList.remove('asst-model-account-label');
|
|
705
|
-
// A display name ("Sonnet 5") reads in sans; a raw id nothing names ("opus[1m]") stays mono.
|
|
706
|
-
buttons.model?.toggleAttribute('data-raw', /^[a-z0-9][\w.\-[\]:/]*$/.test(String(v.model || '')));
|
|
857
|
+
renderModelChip(brain, v);
|
|
707
858
|
|
|
708
859
|
if (brain.provider === 'opencode') {
|
|
709
860
|
setBtn('effort', { label: v.effort, icon: ICON_AGENT, tooltip: `${t('assistant.brain.agent', 'OpenCode agent')}: ${v.effort}` });
|
|
@@ -791,7 +942,7 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
791
942
|
{ field: 'mode', label: t('assistant.brain.mode', 'Permission mode'), value: v.mode, icon: ICON_SHIELD, hidden: false },
|
|
792
943
|
{ field: 'tests', label: t('assistant.tests.title', 'Test density'), value: testDensity() ? testDensityLabel(testDensity(), hooks.t) : '', icon: testsIcon(testDensityBars(testDensity())), hidden: !testDensity() },
|
|
793
944
|
{ field: 'mcp', label: t('assistant.brain.mcp', 'MCP tool profile'), value: v.mcp, icon: ICON_PLUG, hidden: false },
|
|
794
|
-
{ field: 'account', label: t('assistant.brain.
|
|
945
|
+
{ field: 'account', label: t('assistant.brain.accountShort', 'Account'), value: accountValue(brain), icon: ICON_ACCOUNT, hidden: !ACCOUNT_PROVIDERS.has(brain.provider) },
|
|
795
946
|
];
|
|
796
947
|
}
|
|
797
948
|
|
|
@@ -855,7 +1006,8 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
855
1006
|
placement,
|
|
856
1007
|
current: { provider: brain.provider, model: brain.model },
|
|
857
1008
|
warnSwitch: true,
|
|
858
|
-
accountItems: ACCOUNT_PROVIDERS.has(brain.provider) ? accountItems(brain
|
|
1009
|
+
accountItems: ACCOUNT_PROVIDERS.has(brain.provider) ? accountItems(brain) : [],
|
|
1010
|
+
accountTitle: accountText('menuTitle', {}, accountProvider(brain)),
|
|
859
1011
|
onToast: hooks.onToast,
|
|
860
1012
|
onManageModels: hooks.onManageModels,
|
|
861
1013
|
onSelect: (target) => {
|
|
@@ -920,7 +1072,8 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
920
1072
|
|
|
921
1073
|
if (field === 'account') {
|
|
922
1074
|
if (!ACCOUNT_PROVIDERS.has(brain.provider)) return;
|
|
923
|
-
|
|
1075
|
+
// Kept inside the panel that holds the anchor (the sidepanel, or the tab's own root).
|
|
1076
|
+
openAccountMenu(anchor, accountMenu(brain, anchor.closest?.('.assistant-panel') || anchor.closest?.('.asst-root') || null));
|
|
924
1077
|
return;
|
|
925
1078
|
}
|
|
926
1079
|
|
|
@@ -975,70 +1128,74 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
975
1128
|
onSelect: () => commit({ permissionMode: m.id }, 'mode'),
|
|
976
1129
|
});
|
|
977
1130
|
}
|
|
1131
|
+
// The global Admin sandbox switch (every agent SynaBun starts, not this conversation), under its own header.
|
|
1132
|
+
const adminSandbox = adminSandboxItem();
|
|
1133
|
+
if (adminSandbox) items.push({ kind: 'separator' }, { kind: 'header', label: t('assistant.adminSandbox.group', 'Every agent') }, adminSandbox);
|
|
978
1134
|
menu(t('assistant.brain.mode', 'Permission mode'), items);
|
|
979
1135
|
}
|
|
980
1136
|
}
|
|
981
1137
|
|
|
982
|
-
// The
|
|
983
|
-
//
|
|
984
|
-
|
|
985
|
-
|
|
1138
|
+
// The cog's account menu (asst-account-menu.js): every account once, the conversation's and the
|
|
1139
|
+
// workers' choice, kept inside `bounds`. What each choice does is the same as the composer's.
|
|
1140
|
+
function accountMenu(brain, bounds) {
|
|
1141
|
+
const codex = brain.provider === 'codex';
|
|
1142
|
+
const refetch = () => (codex ? fetchCodexAccounts(true) : fetchClaudeAccounts(true));
|
|
1143
|
+
return {
|
|
1144
|
+
provider: codex ? 'codex' : 'claude',
|
|
1145
|
+
t: hooks.t,
|
|
1146
|
+
placement,
|
|
1147
|
+
bounds,
|
|
1148
|
+
read: () => ({
|
|
1149
|
+
accounts: codex ? getCachedCodexAccounts() : getCachedClaudeAccounts(),
|
|
1150
|
+
currentId: currentBrain().accountId,
|
|
1151
|
+
workerId: codex ? getCodexWorkerAccountId() : getClaudeWorkerAccountId(),
|
|
1152
|
+
running: hooks.getRunning?.() === true,
|
|
1153
|
+
}),
|
|
1154
|
+
onAuto: () => commit({ accountId: 'auto' }, 'account'),
|
|
1155
|
+
onPick: (id) => commit({ accountId: id }, 'account'),
|
|
1156
|
+
onSetWorker: async (id) => { await (codex ? setCodexWorkerAccount : setClaudeWorkerAccount)(id); await refetch(); render(); },
|
|
1157
|
+
onSetMode: async (id, mode) => {
|
|
1158
|
+
const before = currentBrain();
|
|
1159
|
+
try {
|
|
1160
|
+
await (codex ? patchCodexAccount : patchClaudeAccount)(id, { mode }); await refetch();
|
|
1161
|
+
hooks.onChange?.(currentBrain(), { requiresSwitch: true, restartBrain: true, field: 'accountMode', previous: before }); render();
|
|
1162
|
+
}
|
|
1163
|
+
catch (err) { hooks.onToast?.(err?.message || String(err)); }
|
|
1164
|
+
},
|
|
1165
|
+
onAdd: () => hooks.onAddAccount?.(brain.provider),
|
|
1166
|
+
onManage: (id) => (id ? hooks.onManageAccounts?.(brain.provider, id) : hooks.onManageAccounts?.(brain.provider)),
|
|
1167
|
+
onError: (err) => hooks.onToast?.(err?.message || String(err)),
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// The composer's Model menu lists the brain's accounts too (Claude or Codex), as the cog's account menu
|
|
1172
|
+
// does (asst-account-menu.js): Auto, every account once (a signed-out one opens its sign-in), the Uses
|
|
1173
|
+
// switch of an account holding both credentials, Add account… and Manage….
|
|
1174
|
+
function accountItems(brain) {
|
|
986
1175
|
const codex = brain.provider === 'codex';
|
|
987
1176
|
const p = codex ? 'codex' : 'claude';
|
|
988
1177
|
const accounts = codex ? getCachedCodexAccounts() : getCachedClaudeAccounts();
|
|
989
1178
|
const refetch = () => (codex ? fetchCodexAccounts(true) : fetchClaudeAccounts(true));
|
|
990
|
-
const items =
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
selected: a.id === brain.accountId,
|
|
998
|
-
onSelect: () => commit({ accountId: a.id }, 'account'),
|
|
999
|
-
};
|
|
1179
|
+
const items = accountChoiceItems({
|
|
1180
|
+
t: hooks.t,
|
|
1181
|
+
rows: accounts.map((a) => accountMenuRow(a, { provider: p, t: hooks.t })),
|
|
1182
|
+
currentId: brain.accountId,
|
|
1183
|
+
onAuto: () => commit({ accountId: 'auto' }, 'account'),
|
|
1184
|
+
onPick: (id) => commit({ accountId: id }, 'account'),
|
|
1185
|
+
onSignIn: (id) => hooks.onManageAccounts?.(brain.provider, id),
|
|
1000
1186
|
});
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
try {
|
|
1014
|
-
await (codex ? patchCodexAccount : patchClaudeAccount)(current.id, { mode: m.mode }); await refetch();
|
|
1015
|
-
hooks.onChange?.(currentBrain(), { requiresSwitch: true, restartBrain: true, field: 'accountMode', previous: brain }); render();
|
|
1016
|
-
}
|
|
1017
|
-
catch (err) { hooks.onToast?.(err?.message || String(err)); }
|
|
1018
|
-
},
|
|
1019
|
-
});
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
const worker = codex ? getCodexWorkerAccountId() : getClaudeWorkerAccountId();
|
|
1023
|
-
if (!composer) {
|
|
1024
|
-
items.push({ kind: 'separator' });
|
|
1025
|
-
items.push({ kind: 'header', label: codex ? t('assistant.accounts.codexWorkersHeader', 'Codex workers use') : t('assistant.accounts.workersHeader', 'Claude Code workers use') });
|
|
1026
|
-
for (const a of accounts) {
|
|
1027
|
-
const usable = accountUsable(a);
|
|
1028
|
-
items.push({
|
|
1029
|
-
kind: 'radio', id: `worker:${a.id}`, label: accountName(a, p), tag: accountBadge(a, p).text,
|
|
1030
|
-
disabled: !usable && a.id !== worker, selected: a.id === worker,
|
|
1031
|
-
onSelect: async () => {
|
|
1032
|
-
if (a.id === worker) return;
|
|
1033
|
-
try { await (codex ? setCodexWorkerAccount : setClaudeWorkerAccount)(a.id); await refetch(); render(); }
|
|
1034
|
-
catch (err) { hooks.onToast?.(err?.message || String(err)); }
|
|
1035
|
-
},
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
items.push({ kind: 'separator' });
|
|
1040
|
-
items.push({ id: '__add', label: t('assistant.accounts.add', 'Add account…'), onSelect: () => hooks.onAddAccount?.(brain.provider) });
|
|
1041
|
-
items.push({ id: '__manage', label: t('assistant.accounts.manage', 'Manage…'), onSelect: () => hooks.onManageAccounts?.(brain.provider) });
|
|
1187
|
+
const uses = accountModeItem({
|
|
1188
|
+
provider: p, t: hooks.t, account: accounts.find((a) => a.id === brain.accountId), running: hooks.getRunning?.() === true,
|
|
1189
|
+
onSetMode: async (id, mode) => {
|
|
1190
|
+
try {
|
|
1191
|
+
await (codex ? patchCodexAccount : patchClaudeAccount)(id, { mode }); await refetch();
|
|
1192
|
+
hooks.onChange?.(currentBrain(), { requiresSwitch: true, restartBrain: true, field: 'accountMode', previous: brain }); render();
|
|
1193
|
+
}
|
|
1194
|
+
catch (err) { hooks.onToast?.(err?.message || String(err)); }
|
|
1195
|
+
},
|
|
1196
|
+
});
|
|
1197
|
+
if (uses) items.push(uses);
|
|
1198
|
+
items.push(accountManageItem({ t: hooks.t, onAdd: () => hooks.onAddAccount?.(brain.provider), onManage: () => hooks.onManageAccounts?.(brain.provider) }));
|
|
1042
1199
|
return items;
|
|
1043
1200
|
}
|
|
1044
1201
|
|
|
@@ -1088,6 +1245,6 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
1088
1245
|
mountEmptyProject,
|
|
1089
1246
|
setBrain() { render(); },
|
|
1090
1247
|
close: closeMenu,
|
|
1091
|
-
destroy() { destroyed = true; for (const off of offAccounts) { try { off?.(); } catch {} } closeMenu(); heroProjectMascot?.destroy(); Object.values(buttons).forEach((b) => b.remove()); heroProject?.remove(); heroProject = null; root.remove(); },
|
|
1248
|
+
destroy() { destroyed = true; fitObserver?.disconnect(); if (fitFrame && typeof cancelAnimationFrame === 'function') cancelAnimationFrame(fitFrame); for (const off of offAccounts) { try { off?.(); } catch {} } closeMenu(); heroProjectMascot?.destroy(); Object.values(buttons).forEach((b) => b.remove()); heroProject?.remove(); heroProject = null; root.remove(); },
|
|
1092
1249
|
};
|
|
1093
1250
|
}
|