synabun 2.0.5 → 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 +78 -0
- package/README.md +2 -1
- package/THIRD-PARTY-LICENSES.md +13 -0
- package/docs/whatsapp.md +151 -16
- package/hooks/claude-code/post-plan.mjs +6 -30
- package/hooks/claude-code/session-start.mjs +1 -4
- package/hooks/claude-code/shared.mjs +112 -75
- package/lib/child-path.js +303 -0
- package/lib/claude-hooks.js +2 -1
- package/lib/data-home-migration.js +2 -0
- package/lib/desktop-app.js +265 -0
- package/lib/external-tools.js +7 -3
- package/lib/log-redact.js +102 -0
- package/lib/package-processes.js +670 -0
- package/lib/packaged-runtime.js +138 -11
- package/lib/runtime-dependencies.js +225 -0
- package/mcp-server/dist/http.d.ts +3 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +15 -4
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +9 -6
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/services/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/budget-judgments.d.ts +108 -0
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/budget-judgments.js +153 -0
- package/mcp-server/dist/services/budget-judgments.js.map +1 -0
- package/mcp-server/dist/services/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/codex-config-heal.d.ts +5 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +41 -4
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/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/services/identity.d.ts +11 -0
- package/mcp-server/dist/services/identity.d.ts.map +1 -1
- package/mcp-server/dist/services/identity.js +24 -0
- package/mcp-server/dist/services/identity.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +13 -0
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +34 -2
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
- package/mcp-server/dist/services/typesafe-config.js +4 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +11 -8
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +35 -14
- 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 +17 -0
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
- package/mcp-server/dist/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 +18 -5
- package/mcp-server/dist/tui.js.map +1 -1
- package/mcp-server/dist/version.d.ts +5 -0
- package/mcp-server/dist/version.d.ts.map +1 -0
- package/mcp-server/dist/version.js +21 -0
- package/mcp-server/dist/version.js.map +1 -0
- package/mcp-server/package-lock.json +3 -3
- package/mcp-server/package.json +3 -3
- package/mcp-server/run.mjs +15 -9
- package/mcp-server/src/http.ts +18 -3
- package/mcp-server/src/index.ts +9 -6
- package/mcp-server/src/services/browser-bench.ts +1 -1
- package/mcp-server/src/services/budget-judgments.ts +183 -0
- package/mcp-server/src/services/categories.ts +77 -32
- package/mcp-server/src/services/codex-config-heal.ts +35 -4
- package/mcp-server/src/services/desktop-bench.ts +1 -1
- package/mcp-server/src/services/identity.ts +27 -0
- package/mcp-server/src/services/neural-interface.ts +34 -2
- package/mcp-server/src/services/typesafe-config.ts +4 -1
- package/mcp-server/src/tools/agents.ts +34 -15
- 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 +51 -0
- 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 +24 -10
- package/mcp-server/src/version.ts +22 -0
- package/neural-interface/i18n/en.json +645 -57
- package/neural-interface/i18n/pt-BR.json +644 -56
- package/neural-interface/lib/account-usage.js +163 -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 +274 -52
- package/neural-interface/lib/assistant-brains/claude.js +15 -2
- package/neural-interface/lib/assistant-brains/codex.js +3 -0
- package/neural-interface/lib/assistant-brains/opencode.js +17 -4
- package/neural-interface/lib/assistant-budget-planner.js +390 -0
- package/neural-interface/lib/assistant-budget-split.js +408 -0
- package/neural-interface/lib/assistant-budget.js +94 -95
- package/neural-interface/lib/assistant-config.js +62 -14
- package/neural-interface/lib/assistant-dispatch.js +432 -125
- package/neural-interface/lib/assistant-jev.js +26 -3
- package/neural-interface/lib/assistant-persona.js +68 -11
- package/neural-interface/lib/assistant-plan-permissions.js +8 -1
- package/neural-interface/lib/assistant-route-accounts.js +14 -0
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -1
- package/neural-interface/lib/assistant-route-gate.js +19 -3
- package/neural-interface/lib/assistant-router.js +373 -42
- package/neural-interface/lib/assistant-runtime.js +312 -48
- package/neural-interface/lib/assistant-user-writer.js +4 -2
- package/neural-interface/lib/augmented-path.js +317 -53
- package/neural-interface/lib/claude-accounts.js +342 -31
- package/neural-interface/lib/claude-agent-bridge.js +90 -3
- package/neural-interface/lib/claude-executable.js +6 -1
- package/neural-interface/lib/claude-model-catalog.js +3 -3
- package/neural-interface/lib/claude-panel-auth.js +221 -0
- package/neural-interface/lib/claude-profile-api-key.js +62 -0
- package/neural-interface/lib/cli-install-api.js +137 -0
- package/neural-interface/lib/cli-install.js +797 -0
- package/neural-interface/lib/cli-path.js +130 -0
- package/neural-interface/lib/cli-resolver.js +744 -0
- package/neural-interface/lib/cli-update-planner.js +143 -7
- package/neural-interface/lib/codex-account-auth.js +180 -0
- package/neural-interface/lib/codex-accounts.js +502 -0
- package/neural-interface/lib/codex-capabilities.js +2 -1
- package/neural-interface/lib/codex-compat-rpc.js +8 -2
- package/neural-interface/lib/codex-mcp-approvals.js +5 -1
- package/neural-interface/lib/codex-panel-auth.js +62 -0
- package/neural-interface/lib/codex-session-settings.js +1 -1
- package/neural-interface/lib/codex-settings-schema.js +122 -0
- package/neural-interface/lib/desktop/config.js +3 -0
- package/neural-interface/lib/exec-loop-command.js +3 -1
- package/neural-interface/lib/git-bash/bzip2.js +339 -0
- package/neural-interface/lib/git-bash/claude-settings.js +73 -0
- package/neural-interface/lib/git-bash/extract-worker.js +34 -0
- package/neural-interface/lib/git-bash/install.js +529 -0
- package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
- package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
- package/neural-interface/lib/git-bash/manager.js +268 -0
- package/neural-interface/lib/git-bash/pins.js +206 -0
- package/neural-interface/lib/git-bash/pins.json +34 -0
- package/neural-interface/lib/git-bash/resolver.js +194 -0
- package/neural-interface/lib/git-read.js +34 -2
- package/neural-interface/lib/install-details.js +163 -0
- package/neural-interface/lib/mcp-installer.js +14 -2
- package/neural-interface/lib/native-loop-providers.js +22 -4
- package/neural-interface/lib/native-loop-runtime.js +9 -4
- package/neural-interface/lib/os-path.js +319 -0
- package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
- package/neural-interface/lib/provider-panel-terminal-auth.js +96 -0
- package/neural-interface/lib/pty-host/core.js +2 -1
- package/neural-interface/lib/pty-host/manager.js +27 -2
- package/neural-interface/lib/remote-policy.js +20 -11
- package/neural-interface/lib/session-indexer.js +3 -1
- package/neural-interface/lib/session-title-generator.js +6 -3
- package/neural-interface/lib/system-about.js +340 -0
- package/neural-interface/lib/system-activity.js +66 -0
- package/neural-interface/lib/terminal-env.js +11 -3
- package/neural-interface/lib/terminal-path.js +55 -0
- package/neural-interface/lib/virtual-socket.js +12 -1
- package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
- package/neural-interface/lib/whatsapp/bridge.js +78 -34
- package/neural-interface/lib/whatsapp/commands.js +13 -14
- package/neural-interface/lib/whatsapp/config.js +134 -20
- package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
- package/neural-interface/lib/whatsapp/host-core.js +168 -35
- package/neural-interface/lib/whatsapp/inbound.js +5 -3
- package/neural-interface/lib/whatsapp/local-file.js +524 -0
- package/neural-interface/lib/whatsapp/manager.js +92 -32
- package/neural-interface/lib/whatsapp/paths.js +11 -1
- package/neural-interface/lib/whatsapp/protocol.js +65 -5
- package/neural-interface/lib/whatsapp/redact.js +63 -0
- package/neural-interface/lib/whatsapp/service.js +343 -91
- package/neural-interface/lib/whatsapp/transcription.js +463 -0
- package/neural-interface/package-lock.json +2 -2
- package/neural-interface/package.json +1 -1
- package/neural-interface/public/index.html +2 -0
- package/neural-interface/public/index2d.html +2 -0
- package/neural-interface/public/offline.html +16 -1
- package/neural-interface/public/onboarding.html +96 -2
- package/neural-interface/public/shared/account-i18n.js +7 -0
- package/neural-interface/public/shared/account-menu.js +542 -0
- package/neural-interface/public/shared/account-usage.js +79 -0
- package/neural-interface/public/shared/account-view.js +336 -0
- package/neural-interface/public/shared/agent-runtime-options.js +28 -8
- package/neural-interface/public/shared/assistant/asst-account-menu.js +298 -0
- package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
- package/neural-interface/public/shared/assistant/asst-api.js +39 -2
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +288 -32
- package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
- package/neural-interface/public/shared/assistant/asst-mascot.js +126 -7
- package/neural-interface/public/shared/assistant/asst-menu.js +219 -80
- package/neural-interface/public/shared/assistant/asst-model-chip.js +135 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +87 -16
- package/neural-interface/public/shared/assistant/asst-render.js +38 -7
- package/neural-interface/public/shared/assistant/asst-route.js +72 -14
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +45 -6
- package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
- package/neural-interface/public/shared/assistant/asst-state.js +1 -1
- package/neural-interface/public/shared/assistant/asst-styles.js +160 -29
- package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
- package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
- package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +49 -108
- package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +172 -111
- package/neural-interface/public/shared/cdx/cdx-tabs.js +264 -664
- package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
- package/neural-interface/public/shared/claude-account-view.js +3 -0
- package/neural-interface/public/shared/cli-install-view.js +392 -0
- package/neural-interface/public/shared/cli-status.js +282 -22
- package/neural-interface/public/shared/cp/cp-events.js +2 -1
- package/neural-interface/public/shared/cp/cp-styles.js +46 -0
- package/neural-interface/public/shared/desktop-bridge.js +39 -0
- package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
- package/neural-interface/public/shared/desktop-titlebar.js +153 -0
- package/neural-interface/public/shared/desktop-update-view.js +462 -0
- package/neural-interface/public/shared/editor/editor-panel.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +1 -1
- package/neural-interface/public/shared/git-bash-view.js +145 -0
- package/neural-interface/public/shared/html-shell.js +1 -0
- package/neural-interface/public/shared/i18n.js +19 -1
- package/neural-interface/public/shared/install-details-view.js +86 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +36 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +17 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +169 -2
- package/neural-interface/public/shared/pwa-install-page.js +3 -1
- package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
- package/neural-interface/public/shared/settings/settings-about.js +254 -0
- package/neural-interface/public/shared/settings/settings-ia.js +15 -0
- package/neural-interface/public/shared/showcase-privacy.js +490 -0
- package/neural-interface/public/shared/storage.js +30 -3
- package/neural-interface/public/shared/styles.css +281 -32
- package/neural-interface/public/shared/synabun-mascot.js +48 -2
- package/neural-interface/public/shared/ui-claude-panel.js +262 -217
- package/neural-interface/public/shared/ui-cli-banner.js +355 -0
- package/neural-interface/public/shared/ui-explorer.js +2 -0
- package/neural-interface/public/shared/ui-git-bash.js +124 -0
- package/neural-interface/public/shared/ui-judgments.js +10 -1
- package/neural-interface/public/shared/ui-loading.js +30 -6
- package/neural-interface/public/shared/ui-menubar.js +13 -3
- package/neural-interface/public/shared/ui-navbar.js +3 -1
- package/neural-interface/public/shared/ui-provider-auth.js +104 -0
- package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
- package/neural-interface/public/shared/ui-sessions.js +9 -3
- package/neural-interface/public/shared/ui-settings.js +55 -3
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
- package/neural-interface/public/shared/ui-sync.js +8 -0
- package/neural-interface/public/shared/ui-terminal.js +17 -0
- package/neural-interface/public/shared/ui-tool-updates.js +5 -0
- package/neural-interface/public/shared/ui-update.js +598 -7
- package/neural-interface/public/shared/ui-whatsapp.js +21 -6
- package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
- package/neural-interface/public/shared/worker-end.js +2 -0
- package/neural-interface/public/sw.js +1 -1
- package/neural-interface/public/variant/2d/main.js +10 -1
- package/neural-interface/public/variant/3d/main.js +10 -1
- package/neural-interface/scripts/rebuild-pty.js +14 -2
- package/neural-interface/server.js +1384 -679
- package/npm-shrinkwrap.json +4424 -0
- package/package.json +57 -2
- package/postinstall.js +61 -47
- package/preuninstall.js +8 -35
- package/setup.js +80 -47
- 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
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
getCachedCodexAccounts,
|
|
20
20
|
getCachedMcpProfilePresets,
|
|
21
21
|
getCachedOpencodeAgents,
|
|
22
|
+
getClaudeWorkerAccountId,
|
|
23
|
+
getCodexWorkerAccountId,
|
|
22
24
|
getEffortLevelsForModel,
|
|
23
25
|
getModelsForProfile,
|
|
24
26
|
modelEffortIds,
|
|
@@ -27,8 +29,13 @@ import {
|
|
|
27
29
|
import { getHiddenModels, HIDDEN_MODELS_EVENT, hiddenModelMatch } from '../ocp-hidden-models.js';
|
|
28
30
|
import { getProviderMeta } from '../provider-icons.js';
|
|
29
31
|
import { on } from '../state.js';
|
|
30
|
-
import { fetchAssistantCatalog, fetchProjects } from './asst-api.js';
|
|
32
|
+
import { fetchAssistantCatalog, fetchProjects, patchClaudeAccount, patchCodexAccount, setClaudeWorkerAccount, setCodexWorkerAccount } from './asst-api.js';
|
|
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';
|
|
31
36
|
import { closeMenu, currentMenu, isMenuOpen, openMenu } from './asst-menu.js';
|
|
37
|
+
import { createMascotControl } from './asst-mascot.js';
|
|
38
|
+
import { modelChipForms, modelChipName, modelChipTag } from './asst-model-chip.js';
|
|
32
39
|
import {
|
|
33
40
|
ACCOUNT_PROVIDERS,
|
|
34
41
|
brainRequiresSwitch,
|
|
@@ -74,6 +81,10 @@ const TEST_DENSITY_COPY = {
|
|
|
74
81
|
thorough: ['Thorough', 'Full coverage, whole suite, live checks.'],
|
|
75
82
|
};
|
|
76
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
|
+
|
|
77
88
|
/** "Light" — the level's name (a missing or unknown level is the default one). */
|
|
78
89
|
export function testDensityLabel(level, t) {
|
|
79
90
|
const id = normalizeTestDensity(level);
|
|
@@ -411,7 +422,8 @@ function tierTag(m, tr) {
|
|
|
411
422
|
* opts: { brain, onSelect(target), includeHere, hereLabel, title, t, placement,
|
|
412
423
|
* current:{provider, model}|null, warnSwitch, providers, onToast(text),
|
|
413
424
|
* accept(provider, model) → bool (only those models), emptyLabel (when none
|
|
414
|
-
* 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) }
|
|
415
427
|
* target: { provider, model, label, tier, vision, outputs, efforts, price } | { here: true }
|
|
416
428
|
*/
|
|
417
429
|
export async function openModelMenu(anchor, opts = {}) {
|
|
@@ -438,6 +450,9 @@ export async function openModelMenu(anchor, opts = {}) {
|
|
|
438
450
|
if (!anchor.isConnected || (loading && currentMenu() !== loading.el)) return null;
|
|
439
451
|
const metadata = modelCatalogStatus();
|
|
440
452
|
const items = [];
|
|
453
|
+
if (Array.isArray(opts.accountItems) && opts.accountItems.length) {
|
|
454
|
+
items.push({ kind: 'header', label: opts.accountTitle || tr('assistant.brain.account', 'Account profile') }, ...opts.accountItems, { kind: 'separator' });
|
|
455
|
+
}
|
|
441
456
|
if (includeHere) {
|
|
442
457
|
items.push({ kind: 'radio', id: '__here', label: hereLabel || tr('assistant.routes.brainDecides', 'Let the brain decide'), selected: !current, onSelect: () => onSelect?.({ here: true }) });
|
|
443
458
|
}
|
|
@@ -498,7 +513,7 @@ export async function openModelMenu(anchor, opts = {}) {
|
|
|
498
513
|
role: 'menu',
|
|
499
514
|
className: `asst-model-menu${opts.routingEditor ? ' asst-route-model-menu' : ''}`,
|
|
500
515
|
zIndex: opts.zIndex ?? null,
|
|
501
|
-
repositionOnResize:
|
|
516
|
+
repositionOnResize: true,
|
|
502
517
|
filterEmptyLabel: tr('assistant.routes.menu.noMatches', 'No matching models. Check Models for hidden choices.'),
|
|
503
518
|
});
|
|
504
519
|
if (opts.routingEditor && menu) {
|
|
@@ -582,6 +597,7 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
582
597
|
let loading = null;
|
|
583
598
|
// The empty state's "Choose a project" (mountEmptyProject): the project field's second button.
|
|
584
599
|
let heroProject = null;
|
|
600
|
+
let heroProjectMascot = null;
|
|
585
601
|
|
|
586
602
|
function currentBrain() {
|
|
587
603
|
return normalizeBrain(hooks.getBrain?.());
|
|
@@ -621,16 +637,51 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
621
637
|
return accounts.find(a => a.id === brain.accountId) || null;
|
|
622
638
|
}
|
|
623
639
|
|
|
640
|
+
const accountProvider = (brain) => (brain.provider === 'codex' ? 'codex' : 'claude');
|
|
624
641
|
function accountLabel(brain) {
|
|
625
642
|
const acc = accountOf(brain);
|
|
626
|
-
|
|
643
|
+
const name = acc ? accountName(acc, accountProvider(brain)) : (brain.accountId || t('assistant.brain.accountDefault', 'Default'));
|
|
644
|
+
// An account says what it runs on (its subscription or its API key), or that it is signed out.
|
|
645
|
+
if (acc && acc.mode !== undefined) {
|
|
646
|
+
const badge = accountBadge(acc, accountProvider(brain));
|
|
647
|
+
return badge.text ? `${name} · ${badge.text}` : name;
|
|
648
|
+
}
|
|
649
|
+
return name;
|
|
650
|
+
}
|
|
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);
|
|
627
663
|
}
|
|
628
664
|
|
|
629
665
|
function modelLabel(brain = currentBrain()) {
|
|
630
|
-
const model =
|
|
666
|
+
const model = modelRow(brain);
|
|
631
667
|
return model ? (model.label || modelShortName(model.id)) : (brain.model ? modelShortName(brain.model) : t('assistant.brain.modelDefault', 'Default model'));
|
|
632
668
|
}
|
|
633
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
|
+
|
|
634
685
|
function values(brain = currentBrain()) {
|
|
635
686
|
const meta = getProviderMeta(brain.provider);
|
|
636
687
|
const efforts = effortsFor(brain);
|
|
@@ -653,6 +704,26 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
653
704
|
};
|
|
654
705
|
}
|
|
655
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
|
+
|
|
656
727
|
/** The session's Test density, or null while the host has none to show (a server that does not know it). */
|
|
657
728
|
function testDensity() {
|
|
658
729
|
const level = typeof hooks.getTestDensity === 'function' ? hooks.getTestDensity() : null;
|
|
@@ -673,14 +744,117 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
673
744
|
btn.setAttribute('aria-label', aria || tooltip || label || field);
|
|
674
745
|
}
|
|
675
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
|
+
|
|
676
853
|
function render() {
|
|
677
854
|
if (destroyed) return;
|
|
678
855
|
const brain = currentBrain();
|
|
679
856
|
const v = values(brain);
|
|
680
|
-
|
|
681
|
-
setBtn('model', { label: v.model, icon: v.meta.icon, color: v.meta.color, tooltip: modelTip, aria: `${t('assistant.brain.model', 'Model')}: ${modelTip}` });
|
|
682
|
-
// A display name ("Sonnet 5") reads in sans; a raw id nothing names ("opus[1m]") stays mono.
|
|
683
|
-
buttons.model?.toggleAttribute('data-raw', /^[a-z0-9][\w.\-[\]:/]*$/.test(String(v.model || '')));
|
|
857
|
+
renderModelChip(brain, v);
|
|
684
858
|
|
|
685
859
|
if (brain.provider === 'opencode') {
|
|
686
860
|
setBtn('effort', { label: v.effort, icon: ICON_AGENT, tooltip: `${t('assistant.brain.agent', 'OpenCode agent')}: ${v.effort}` });
|
|
@@ -688,9 +862,12 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
688
862
|
setBtn('effort', { label: v.effort, icon: ICON_EFFORT, hidden: !v.effortSupported, tooltip: `${t('assistant.brain.effort', 'Thinking effort')}: ${v.effort}` });
|
|
689
863
|
}
|
|
690
864
|
setBtn('variant', { label: v.variant, icon: ICON_EFFORT, hidden: !v.variantSupported, tooltip: `${t('assistant.brain.variant', 'Model variant')}: ${v.variant}` });
|
|
691
|
-
//
|
|
692
|
-
|
|
693
|
-
|
|
865
|
+
// A Claude or Codex brain always shows it: which account and which credential (its subscription or
|
|
866
|
+
// its API key) it runs on, or that the account is signed out.
|
|
867
|
+
const brainAcc = ACCOUNT_PROVIDERS.has(brain.provider) ? accountOf(brain) : null;
|
|
868
|
+
const accountTip = [v.account, brainAcc ? accountIdentity(brainAcc) : ''].filter(Boolean).join(' · ');
|
|
869
|
+
setBtn('account', { label: v.account, icon: ICON_ACCOUNT, hidden: true, tooltip: `${t('assistant.brain.account', 'Account profile')}: ${accountTip}` });
|
|
870
|
+
buttons.account?.classList.toggle('asst-dd-warn', !!brainAcc && brainAcc.signedIn === false);
|
|
694
871
|
setBtn('project', { label: v.project, icon: ICON_FOLDER, tooltip: brain.project || t('assistant.brain.projectNoneTip', 'Working project: home directory'), aria: `${t('assistant.brain.project', 'Working project')}: ${brain.project || v.project}` });
|
|
695
872
|
setBtn('mode', { label: v.mode, icon: ICON_SHIELD, tooltip: `${t('assistant.brain.mode', 'Permission mode')}: ${v.mode}` });
|
|
696
873
|
const tests = testDensity();
|
|
@@ -721,10 +898,13 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
721
898
|
* sends focus back to it. A new slot replaces the last one; null removes it.
|
|
722
899
|
*/
|
|
723
900
|
function mountEmptyProject(slot) {
|
|
901
|
+
if (heroProject && isMenuOpen(heroProject)) closeMenu();
|
|
902
|
+
heroProjectMascot?.destroy();
|
|
903
|
+
heroProjectMascot = null;
|
|
724
904
|
heroProject?.remove();
|
|
725
905
|
heroProject = null;
|
|
726
906
|
if (destroyed || !slot || typeof slot.appendChild !== 'function') return null;
|
|
727
|
-
const btn = el('button', 'asst-dd asst-empty-project-btn');
|
|
907
|
+
const btn = el('button', 'asst-dd asst-empty-control-btn asst-empty-project-btn');
|
|
728
908
|
btn.type = 'button';
|
|
729
909
|
btn.dataset.field = 'project';
|
|
730
910
|
btn.setAttribute('aria-haspopup', 'menu');
|
|
@@ -743,6 +923,7 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
743
923
|
});
|
|
744
924
|
slot.appendChild(btn);
|
|
745
925
|
heroProject = btn;
|
|
926
|
+
heroProjectMascot = createMascotControl(btn, { director: hooks.mascot, pose: 'project' });
|
|
746
927
|
renderEmptyProject();
|
|
747
928
|
return btn;
|
|
748
929
|
}
|
|
@@ -761,7 +942,7 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
761
942
|
{ field: 'mode', label: t('assistant.brain.mode', 'Permission mode'), value: v.mode, icon: ICON_SHIELD, hidden: false },
|
|
762
943
|
{ field: 'tests', label: t('assistant.tests.title', 'Test density'), value: testDensity() ? testDensityLabel(testDensity(), hooks.t) : '', icon: testsIcon(testDensityBars(testDensity())), hidden: !testDensity() },
|
|
763
944
|
{ field: 'mcp', label: t('assistant.brain.mcp', 'MCP tool profile'), value: v.mcp, icon: ICON_PLUG, hidden: false },
|
|
764
|
-
{ 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) },
|
|
765
946
|
];
|
|
766
947
|
}
|
|
767
948
|
|
|
@@ -818,12 +999,15 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
818
999
|
const anchor = anchorFor(field, anchorOverride);
|
|
819
1000
|
const brain = currentBrain();
|
|
820
1001
|
if (field === 'model') {
|
|
1002
|
+
if (ACCOUNT_PROVIDERS.has(brain.provider)) await ensureLoaded(brain.provider);
|
|
821
1003
|
await openModelMenu(anchor, {
|
|
822
1004
|
brain,
|
|
823
1005
|
t: hooks.t,
|
|
824
1006
|
placement,
|
|
825
1007
|
current: { provider: brain.provider, model: brain.model },
|
|
826
1008
|
warnSwitch: true,
|
|
1009
|
+
accountItems: ACCOUNT_PROVIDERS.has(brain.provider) ? accountItems(brain) : [],
|
|
1010
|
+
accountTitle: accountText('menuTitle', {}, accountProvider(brain)),
|
|
827
1011
|
onToast: hooks.onToast,
|
|
828
1012
|
onManageModels: hooks.onManageModels,
|
|
829
1013
|
onSelect: (target) => {
|
|
@@ -888,29 +1072,24 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
888
1072
|
|
|
889
1073
|
if (field === 'account') {
|
|
890
1074
|
if (!ACCOUNT_PROVIDERS.has(brain.provider)) return;
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
kind: 'radio',
|
|
894
|
-
id: a.id,
|
|
895
|
-
label: a.label || a.email || a.id,
|
|
896
|
-
desc: a.email && a.email !== a.label ? a.email : (a.isDefault ? t('assistant.accounts.ambient', 'ambient config') : ''),
|
|
897
|
-
selected: a.id === brain.accountId,
|
|
898
|
-
onSelect: () => commit({ accountId: a.id }, 'account'),
|
|
899
|
-
}));
|
|
900
|
-
items.push({ kind: 'separator' });
|
|
901
|
-
items.push({ id: '__add', label: t('assistant.accounts.add', 'Add account…'), onSelect: () => hooks.onAddAccount?.(brain.provider) });
|
|
902
|
-
items.push({ id: '__manage', label: t('assistant.accounts.manage', 'Manage…'), onSelect: () => hooks.onManageAccounts?.(brain.provider) });
|
|
903
|
-
menu(t('assistant.brain.account', 'Account profile'), items);
|
|
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));
|
|
904
1077
|
return;
|
|
905
1078
|
}
|
|
906
1079
|
|
|
907
1080
|
if (field === 'project') {
|
|
1081
|
+
const actor = anchor === heroProject ? heroProjectMascot : null;
|
|
1082
|
+
const pick = project => {
|
|
1083
|
+
const changed = (currentBrain().project || null) !== (project || null);
|
|
1084
|
+
commit({ project }, 'project');
|
|
1085
|
+
actor?.commit(changed ? 'hop' : 'nod');
|
|
1086
|
+
};
|
|
908
1087
|
const projects = _projectsCache || [];
|
|
909
|
-
const items = [{ kind: 'radio', id: '', label: t('assistant.brain.projectNone', 'Home directory'), desc: t('assistant.brain.projectNoneDesc', 'no project'), selected: !brain.project, restoreFocus, onSelect: () =>
|
|
910
|
-
for (const p of projects) items.push({ kind: 'radio', id: p.path, label: p.label || basename(p.path), desc: p.path, selected: p.path === brain.project, restoreFocus, onSelect: () =>
|
|
1088
|
+
const items = [{ kind: 'radio', id: '', label: t('assistant.brain.projectNone', 'Home directory'), desc: t('assistant.brain.projectNoneDesc', 'no project'), selected: !brain.project, restoreFocus, onSelect: () => pick(null) }];
|
|
1089
|
+
for (const p of projects) items.push({ kind: 'radio', id: p.path, label: p.label || basename(p.path), desc: p.path, selected: p.path === brain.project, restoreFocus, onSelect: () => pick(p.path) });
|
|
911
1090
|
items.push({ kind: 'separator' });
|
|
912
|
-
items.push({ kind: 'input', placeholder: t('assistant.brain.projectCustom', 'Type a directory path…'), value: brain.project && !projects.some(p => p.path === brain.project) ? brain.project : '', restoreFocus, onSubmit:
|
|
913
|
-
menu(t('assistant.brain.project', 'Working project'), items, { width: 280, filter: projects.length > 8, filterPlaceholder: t('assistant.brain.filterProjects', 'Filter projects…') });
|
|
1091
|
+
items.push({ kind: 'input', placeholder: t('assistant.brain.projectCustom', 'Type a directory path…'), value: brain.project && !projects.some(p => p.path === brain.project) ? brain.project : '', restoreFocus, onSubmit: pick });
|
|
1092
|
+
menu(t('assistant.brain.project', 'Working project'), items, { width: 280, filter: projects.length > 8, filterPlaceholder: t('assistant.brain.filterProjects', 'Filter projects…'), onOpen: node => actor?.open(node), onClose: () => actor?.close() });
|
|
914
1093
|
return;
|
|
915
1094
|
}
|
|
916
1095
|
|
|
@@ -949,10 +1128,77 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
949
1128
|
onSelect: () => commit({ permissionMode: m.id }, 'mode'),
|
|
950
1129
|
});
|
|
951
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);
|
|
952
1134
|
menu(t('assistant.brain.mode', 'Permission mode'), items);
|
|
953
1135
|
}
|
|
954
1136
|
}
|
|
955
1137
|
|
|
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) {
|
|
1175
|
+
const codex = brain.provider === 'codex';
|
|
1176
|
+
const p = codex ? 'codex' : 'claude';
|
|
1177
|
+
const accounts = codex ? getCachedCodexAccounts() : getCachedClaudeAccounts();
|
|
1178
|
+
const refetch = () => (codex ? fetchCodexAccounts(true) : fetchClaudeAccounts(true));
|
|
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),
|
|
1186
|
+
});
|
|
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) }));
|
|
1199
|
+
return items;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
956
1202
|
async function switchProvider(provider, model = '') {
|
|
957
1203
|
const before = currentBrain();
|
|
958
1204
|
if (provider === before.provider) return;
|
|
@@ -976,6 +1222,16 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
976
1222
|
|
|
977
1223
|
render();
|
|
978
1224
|
refresh().catch(() => {});
|
|
1225
|
+
// Any window changed a Claude or Codex account (signed in or out, a key, its mode, the worker choice,
|
|
1226
|
+
// added, removed): its list is read again and the picker re-drawn, so it never shows a stale state.
|
|
1227
|
+
const accountsChanged = (provider) => (msg) => {
|
|
1228
|
+
const which = provider || (msg?.provider === 'codex' ? 'codex' : msg?.provider === 'claude-code' ? 'claude-code' : null);
|
|
1229
|
+
const jobs = [];
|
|
1230
|
+
if (!which || which === 'claude-code') jobs.push(fetchClaudeAccounts(true));
|
|
1231
|
+
if (!which || which === 'codex') jobs.push(fetchCodexAccounts(true));
|
|
1232
|
+
Promise.all(jobs).then(() => { if (!destroyed) render(); }).catch(() => {});
|
|
1233
|
+
};
|
|
1234
|
+
const offAccounts = [on('sync:claude:accounts-changed', accountsChanged('claude-code')), on('sync:codex:accounts-changed', accountsChanged('codex')), on('sync:assistant:accounts-changed', accountsChanged(null))];
|
|
979
1235
|
|
|
980
1236
|
return {
|
|
981
1237
|
el: root,
|
|
@@ -989,6 +1245,6 @@ export function createBrainPicker(host, hooks = {}) {
|
|
|
989
1245
|
mountEmptyProject,
|
|
990
1246
|
setBrain() { render(); },
|
|
991
1247
|
close: closeMenu,
|
|
992
|
-
destroy() { destroyed = true; closeMenu(); 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(); },
|
|
993
1249
|
};
|
|
994
1250
|
}
|