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
|
@@ -24,6 +24,7 @@ import { toggleScheduleQueue } from './ui-schedule-queue.js';
|
|
|
24
24
|
import { initUpdate } from './ui-update.js';
|
|
25
25
|
import { initToolUpdates } from './ui-tool-updates.js';
|
|
26
26
|
import { initSidepanelTrayPlaceholders } from './ui-sidepanel-tray.js';
|
|
27
|
+
import { initDesktopTitleBar } from './desktop-titlebar.js';
|
|
27
28
|
|
|
28
29
|
const $ = (id) => document.getElementById(id);
|
|
29
30
|
|
|
@@ -304,7 +305,8 @@ export function initNavbar() {
|
|
|
304
305
|
|
|
305
306
|
// ── Window Controls Overlay (PWA standalone) ──
|
|
306
307
|
// Toggles body.wco-active when the overlay chevron is clicked (traffic lights move into content).
|
|
307
|
-
|
|
308
|
+
// Inside the SynaBun desktop app the bar is the window's title bar, and desktop-titlebar.js does this and more.
|
|
309
|
+
if (!initDesktopTitleBar() && 'windowControlsOverlay' in navigator) {
|
|
308
310
|
const wco = navigator.windowControlsOverlay;
|
|
309
311
|
const updateWco = () => document.body.classList.toggle('wco-active', wco.visible);
|
|
310
312
|
updateWco();
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Small shared sign-in view; each caller supplies its panel's existing classes
|
|
2
|
+
// and native transport. Nothing here handles provider credentials.
|
|
3
|
+
export function providerAuthUrl(value) {
|
|
4
|
+
try {
|
|
5
|
+
const url = new URL(value);
|
|
6
|
+
return url.protocol === 'https:' && !url.username && !url.password ? url.href : '';
|
|
7
|
+
} catch { return ''; }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function providerAuthSnapshot(container) {
|
|
11
|
+
if (!container?.querySelector?.('[data-provider-auth-card], [data-provider-auth], [data-provider-logged-out]')) return container?.innerHTML || '';
|
|
12
|
+
const clone = container.cloneNode(true);
|
|
13
|
+
clone.querySelectorAll('[data-provider-auth-card], [data-provider-auth], [data-provider-logged-out]').forEach(node => node.remove());
|
|
14
|
+
return clone.innerHTML;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// `statusText(account, state)` (optional): what the card says while no sign-in is under way, from the
|
|
18
|
+
// caller's own account model (Claude: its subscription and API key). `providerSignedIn(account)`
|
|
19
|
+
// (optional): whether the provider's own login is there ("Sign in again" instead of "Sign in").
|
|
20
|
+
export function mountProviderAuth({ host, provider, read, start, cancel, refresh, submitCode, buttonClass, inputClass, textClass, isCurrent = () => true, onSuccess = () => {}, onAccountChange = () => {}, pollMs = 1500, statusText = null, providerSignedIn = null }) {
|
|
21
|
+
const root = document.createElement('div');
|
|
22
|
+
root.dataset.providerAuth = provider;
|
|
23
|
+
const status = document.createElement('div'); status.className = textClass; status.setAttribute('role', 'status'); status.setAttribute('aria-live', 'polite');
|
|
24
|
+
const actions = document.createElement('div');
|
|
25
|
+
const handoff = document.createElement('a'); handoff.className = buttonClass; handoff.target = '_blank'; handoff.rel = 'noopener noreferrer'; handoff.textContent = 'Open sign-in page'; handoff.hidden = true;
|
|
26
|
+
const code = document.createElement('div'); code.className = textClass; code.hidden = true;
|
|
27
|
+
const manual = document.createElement('form'); manual.hidden = true;
|
|
28
|
+
const codeInput = document.createElement('input'); codeInput.type = 'password'; codeInput.autocomplete = 'off'; codeInput.className = inputClass || ''; codeInput.setAttribute('aria-label', 'Claude sign-in code'); codeInput.placeholder = 'Paste code only if Claude asks';
|
|
29
|
+
const codeSubmit = document.createElement('button'); codeSubmit.type = 'submit'; codeSubmit.className = buttonClass; codeSubmit.textContent = 'Submit code';
|
|
30
|
+
manual.append(codeInput, codeSubmit);
|
|
31
|
+
manual.addEventListener('submit', event => { event.preventDefault(); const value = codeInput.value; codeInput.value = ''; if (value && submitCode) void perform(() => submitCode(state, value)); });
|
|
32
|
+
root.append(status, actions, handoff, code, manual); host.append(root);
|
|
33
|
+
let state = { status: 'idle' }, account = null, timer, disposed = false, busy = false, succeeded = false, version = 0, pushed = 0, transportError = '';
|
|
34
|
+
const current = () => !disposed && root.isConnected && isCurrent();
|
|
35
|
+
const pending = () => ['starting', 'pending'].includes(state.status);
|
|
36
|
+
function button(label, work) {
|
|
37
|
+
const el = document.createElement('button'); el.type = 'button'; el.className = buttonClass; el.textContent = label; el.disabled = busy;
|
|
38
|
+
el.addEventListener('click', () => void perform(work)); actions.append(el); return el;
|
|
39
|
+
}
|
|
40
|
+
function apply(result) {
|
|
41
|
+
if (result?.state) { state = result.state; if (pending()) succeeded = false; }
|
|
42
|
+
if (result?.account) {
|
|
43
|
+
account = result.account;
|
|
44
|
+
if (account.loggedIn === false && state.status === 'success') state = { ...state, status: 'idle' };
|
|
45
|
+
onAccountChange(account);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function render() {
|
|
49
|
+
actions.replaceChildren();
|
|
50
|
+
const signedIn = typeof providerSignedIn === 'function' ? providerSignedIn(account) === true : account?.loggedIn === true;
|
|
51
|
+
// Asked on every render (the caller also learns the state); used only while no sign-in is under way.
|
|
52
|
+
const own = typeof statusText === 'function' ? statusText(account, state) : '';
|
|
53
|
+
status.textContent = transportError || state.error || (['starting', 'pending', 'cancelled'].includes(state.status) ? '' : own) || ({ starting: 'Starting sign-in…', pending: 'Finish sign-in in your browser, then return here.', success: `Signed in${account?.email ? ` as ${account.email}` : ''}.`, cancelled: 'Sign-in cancelled.' }[state.status])
|
|
54
|
+
|| (signedIn ? `Signed in${account.email ? ` as ${account.email}` : ''}.` : 'Not signed in.');
|
|
55
|
+
if (pending()) button('Cancel sign-in', () => cancel(state));
|
|
56
|
+
else button(signedIn ? `Sign in again with ${provider}` : `Sign in with ${provider}`, () => start());
|
|
57
|
+
button('Refresh', async () => {
|
|
58
|
+
const result = await refresh();
|
|
59
|
+
return result;
|
|
60
|
+
});
|
|
61
|
+
const url = providerAuthUrl(state.authUrl || state.verificationUrl);
|
|
62
|
+
handoff.hidden = !pending() || !url;
|
|
63
|
+
if (url && pending()) handoff.href = url; else handoff.removeAttribute('href');
|
|
64
|
+
code.hidden = !pending() || !state.userCode;
|
|
65
|
+
code.textContent = state.userCode ? `Enter this code: ${state.userCode}` : '';
|
|
66
|
+
manual.hidden = !submitCode || state.status !== 'pending'; codeSubmit.disabled = busy;
|
|
67
|
+
if (manual.hidden) codeInput.value = '';
|
|
68
|
+
}
|
|
69
|
+
async function perform(work) {
|
|
70
|
+
if (busy || !current()) return;
|
|
71
|
+
busy = true; transportError = ''; const epoch = ++version; const push = pushed; clearTimeout(timer); render();
|
|
72
|
+
try {
|
|
73
|
+
const result = await work();
|
|
74
|
+
if (!current() || epoch !== version) return;
|
|
75
|
+
// Native notifications may have completed while a request was in flight.
|
|
76
|
+
if (push === pushed) apply(result);
|
|
77
|
+
} catch (error) { if (current() && epoch === version) transportError = error.message || 'Sign-in could not continue. Try again.'; }
|
|
78
|
+
finally {
|
|
79
|
+
busy = false;
|
|
80
|
+
if (current() && epoch === version) {
|
|
81
|
+
render();
|
|
82
|
+
schedule();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function schedule() {
|
|
87
|
+
clearTimeout(timer);
|
|
88
|
+
if (!current()) return;
|
|
89
|
+
if (pending()) timer = setTimeout(poll, pollMs);
|
|
90
|
+
else if (state.status === 'success' && !succeeded) {
|
|
91
|
+
succeeded = true;
|
|
92
|
+
void perform(async () => { const result = await refresh(); await onSuccess(result); return result; });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function poll() {
|
|
96
|
+
if (!current()) return;
|
|
97
|
+
const epoch = version, push = pushed;
|
|
98
|
+
try { const result = await read(); if (!current() || epoch !== version || push !== pushed) return; apply(result); render(); schedule(); }
|
|
99
|
+
catch (error) { if (current()) { status.textContent = error.message || 'Could not refresh sign-in. Use Refresh to retry.'; } }
|
|
100
|
+
}
|
|
101
|
+
render();
|
|
102
|
+
void perform(() => refresh());
|
|
103
|
+
return { update(result) { if (!current()) return; ++pushed; apply(result); render(); if (!busy) schedule(); }, dispose() { disposed = true; ++version; clearTimeout(timer); root.remove(); } };
|
|
104
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { apiKeyErrorText } from './account-view.js';
|
|
2
|
+
|
|
3
|
+
export const PROVIDER_TERMINAL_AUTH_STYLES = `
|
|
4
|
+
.provider-auth-required { padding: 0 !important; }
|
|
5
|
+
.provider-auth-required::before,
|
|
6
|
+
.provider-auth-required > :not([data-provider-logged-out]) { display: none !important; }
|
|
7
|
+
[data-provider-logged-out] {
|
|
8
|
+
display: flex; flex: 1; min-height: 100%; box-sizing: border-box;
|
|
9
|
+
flex-direction: column; align-items: center; justify-content: center;
|
|
10
|
+
gap: 12px; padding: 24px; text-align: center;
|
|
11
|
+
color: var(--cxp-text-2, var(--t-primary)); font: inherit;
|
|
12
|
+
}
|
|
13
|
+
[data-provider-logged-out][hidden] { display: none; }
|
|
14
|
+
.provider-auth-logo { width: 48px; height: 48px; color: var(--cxp-text, var(--t-bright)); }
|
|
15
|
+
.provider-auth-logo svg { width: 100%; height: 100%; }
|
|
16
|
+
.provider-auth-message { margin: 0; font-size: var(--cxp-fs-md, 13px); }
|
|
17
|
+
.provider-auth-button {
|
|
18
|
+
border: none; border-radius: var(--cxp-radius-sm, var(--r-small)); padding: 8px 12px;
|
|
19
|
+
background: var(--cxp-solid, var(--s-active)); color: var(--cxp-on-solid, var(--t-bright));
|
|
20
|
+
font: inherit; font-size: var(--cxp-fs-sm, 12px); font-weight: 500; cursor: pointer;
|
|
21
|
+
}
|
|
22
|
+
.provider-auth-button:disabled { opacity: .6; cursor: default; }
|
|
23
|
+
.provider-auth-button:focus-visible { outline: 2px solid var(--cxp-focus, var(--t-bright)); outline-offset: 2px; }
|
|
24
|
+
.provider-auth-secondary {
|
|
25
|
+
background: transparent; color: var(--cxp-text-2, var(--t-muted));
|
|
26
|
+
border: 1px solid var(--cxp-border, var(--b-light));
|
|
27
|
+
}
|
|
28
|
+
.provider-auth-key { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 280px; }
|
|
29
|
+
.provider-auth-key[hidden], .provider-auth-secondary[hidden] { display: none; }
|
|
30
|
+
.provider-auth-key input {
|
|
31
|
+
min-width: 0; box-sizing: border-box; width: 100%; padding: 8px 12px;
|
|
32
|
+
border: 1px solid var(--cxp-border, var(--b-light)); border-radius: var(--cxp-radius-sm, var(--r-small));
|
|
33
|
+
background: var(--cxp-surface-1, var(--s-subtle)); color: var(--cxp-text, var(--t-bright)); font: inherit;
|
|
34
|
+
}
|
|
35
|
+
.provider-auth-key input:focus-visible { outline: 2px solid var(--cxp-focus, var(--t-bright)); outline-offset: 2px; }
|
|
36
|
+
.provider-auth-key-actions { display: flex; justify-content: center; gap: 8px; }
|
|
37
|
+
.provider-auth-error { margin: 0; color: var(--cxp-danger, var(--t-muted)); font-size: var(--cxp-fs-sm, 12px); }
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
async function terminalRequest(provider, accountId, method = 'GET') {
|
|
41
|
+
const response = await fetch(`/api/provider-panel-auth/${provider}/${encodeURIComponent(accountId)}/terminal`, {
|
|
42
|
+
method, cache: 'no-store', ...(method === 'POST' ? { headers: { 'Content-Type': 'application/json' }, body: '{}' } : {}),
|
|
43
|
+
});
|
|
44
|
+
const data = await response.json();
|
|
45
|
+
if (!response.ok || data.error) throw new Error(data.error || 'Could not open the sign-in terminal.');
|
|
46
|
+
return data.terminal;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Open a provider's own sign-in for an account in SynaBun's terminal (the guarded route picks the
|
|
50
|
+
// CLI, the account's config directory and its environment; no command text leaves the page).
|
|
51
|
+
export async function startProviderTerminalLogin(provider, accountId, label = '') {
|
|
52
|
+
const terminal = await terminalRequest(provider, accountId, 'POST');
|
|
53
|
+
if (terminal.status === 'error') throw new Error(terminal.error || 'Could not open the sign-in terminal.');
|
|
54
|
+
const { openProviderLoginTerminal } = await import('./ui-terminal.js');
|
|
55
|
+
await openProviderLoginTerminal(terminal.sessionId, label || `${provider === 'claude' ? 'Claude' : 'Codex'} sign-in`);
|
|
56
|
+
return terminal;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Only local, allowlisted messages enter the DOM; never provider error text (account-view.js words them).
|
|
60
|
+
function apiKeyErrorMessage(provider, code) {
|
|
61
|
+
return apiKeyErrorText(provider, code);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// `target` is ignored by servers since keys are kept per account (an older page sent its connection's).
|
|
65
|
+
export async function providerApiKeyRequest(provider, accountId, key, target) {
|
|
66
|
+
const failure = code => Object.assign(new Error(apiKeyErrorMessage(provider, code)), { code });
|
|
67
|
+
try {
|
|
68
|
+
let response;
|
|
69
|
+
try {
|
|
70
|
+
response = await fetch(`/api/provider-panel-auth/${provider}/${encodeURIComponent(accountId)}/api-key`, {
|
|
71
|
+
method: 'POST', cache: 'no-store', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key, ...(target ? { target } : {}) }),
|
|
72
|
+
});
|
|
73
|
+
} catch { throw failure('server_unreachable'); }
|
|
74
|
+
const data = await response.json().catch(() => null);
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
let code = { 400: 'invalid_key', 401: 'key_rejected', 403: 'permission_denied', 404: 'account_unavailable', 409: 'account_busy', 413: 'invalid_key', 503: 'verification_unavailable' }[response.status] || 'storage_failed';
|
|
77
|
+
if (response.status === 400 && data?.code === 'oauth_token') code = 'oauth_token';
|
|
78
|
+
if (response.status === 503 && data?.code === 'verification_unreachable') code = 'verification_unreachable';
|
|
79
|
+
throw failure(code);
|
|
80
|
+
}
|
|
81
|
+
if (data?.ok !== true) throw failure('storage_failed');
|
|
82
|
+
} finally { key = null; }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Auth is unknown until a provider says otherwise; a failed read never means logout.
|
|
86
|
+
// `message` (optional): the line under the logo (default "Sign in to Claude to continue.").
|
|
87
|
+
// `moreAction` (optional): { label, run } — one more quiet button under the others (the header account menu).
|
|
88
|
+
export function mountProviderTerminalAuth({ host, provider, accountId, logo, readAccount, isCurrent = () => true, message: messageText = '', moreAction = null,
|
|
89
|
+
onSignedIn = () => {}, requestApiKey = providerApiKeyRequest, pollMs = 3000, requestTerminal = terminalRequest,
|
|
90
|
+
openTerminal = async terminal => {
|
|
91
|
+
const { openProviderLoginTerminal } = await import('./ui-terminal.js');
|
|
92
|
+
await openProviderLoginTerminal(terminal.sessionId, `${provider === 'claude' ? 'Claude' : 'Codex'} sign-in`);
|
|
93
|
+
} }) {
|
|
94
|
+
if (!document.getElementById('provider-terminal-auth-styles')) {
|
|
95
|
+
const style = document.createElement('style'); style.id = 'provider-terminal-auth-styles';
|
|
96
|
+
style.textContent = PROVIDER_TERMINAL_AUTH_STYLES; document.head.append(style);
|
|
97
|
+
}
|
|
98
|
+
const root = document.createElement('div'); root.dataset.providerLoggedOut = provider;
|
|
99
|
+
const icon = document.createElement('div'); icon.className = 'provider-auth-logo'; icon.setAttribute('aria-hidden', 'true');
|
|
100
|
+
icon.innerHTML = logo; // A bundled provider SVG supplied by the owning panel.
|
|
101
|
+
const message = document.createElement('p'); message.className = 'provider-auth-message';
|
|
102
|
+
message.textContent = messageText || `Sign in to ${provider === 'claude' ? 'Claude' : 'Codex'} to continue.`;
|
|
103
|
+
const button = document.createElement('button'); button.type = 'button'; button.className = 'provider-auth-button';
|
|
104
|
+
const error = document.createElement('p'); error.className = 'provider-auth-error'; error.setAttribute('role', 'status'); error.setAttribute('aria-live', 'polite');
|
|
105
|
+
const secondary = document.createElement('button'); secondary.type = 'button';
|
|
106
|
+
secondary.className = 'provider-auth-button provider-auth-secondary'; secondary.textContent = 'Use an API key instead';
|
|
107
|
+
secondary.setAttribute('aria-expanded', 'false');
|
|
108
|
+
const form = document.createElement('form'); form.className = 'provider-auth-key'; form.hidden = true;
|
|
109
|
+
const input = document.createElement('input'); input.type = 'password'; input.autocomplete = 'off'; input.spellcheck = false;
|
|
110
|
+
input.setAttribute('aria-label', 'API key'); input.placeholder = 'Paste API key'; input.required = true;
|
|
111
|
+
const actions = document.createElement('div'); actions.className = 'provider-auth-key-actions';
|
|
112
|
+
const save = document.createElement('button'); save.type = 'submit'; save.className = 'provider-auth-button provider-auth-secondary'; save.textContent = 'Save';
|
|
113
|
+
const cancel = document.createElement('button'); cancel.type = 'button'; cancel.className = 'provider-auth-button provider-auth-secondary'; cancel.textContent = 'Cancel';
|
|
114
|
+
actions.append(save, cancel); form.append(input, actions);
|
|
115
|
+
root.append(icon, message, button, secondary, form, error);
|
|
116
|
+
if (moreAction?.label && typeof moreAction.run === 'function') {
|
|
117
|
+
const more = document.createElement('button'); more.type = 'button';
|
|
118
|
+
more.className = 'provider-auth-button provider-auth-secondary provider-auth-more'; more.textContent = moreAction.label;
|
|
119
|
+
more.addEventListener('click', () => { if (current()) moreAction.run(); });
|
|
120
|
+
root.append(more);
|
|
121
|
+
}
|
|
122
|
+
let loggedIn, terminal = null, busy = false, disposed = false, suspended = false, checking = false, unattached = false, timer, push = 0, issue = '', keyOpen = false, keyBusy = false;
|
|
123
|
+
const current = () => !disposed && isCurrent();
|
|
124
|
+
const pending = () => busy || (!unattached && ['starting', 'pending'].includes(terminal?.status));
|
|
125
|
+
function render() {
|
|
126
|
+
if (!current()) return;
|
|
127
|
+
const visible = loggedIn === false && !suspended;
|
|
128
|
+
root.hidden = !visible; host.classList.toggle('provider-auth-required', visible);
|
|
129
|
+
if (visible) { if (root.parentNode !== host) host.append(root); }
|
|
130
|
+
else root.remove();
|
|
131
|
+
button.disabled = pending() || keyBusy;
|
|
132
|
+
secondary.hidden = keyOpen; secondary.disabled = pending() || keyBusy;
|
|
133
|
+
secondary.setAttribute('aria-expanded', String(keyOpen));
|
|
134
|
+
form.hidden = !keyOpen;
|
|
135
|
+
input.disabled = save.disabled = cancel.disabled = keyBusy || pending();
|
|
136
|
+
save.textContent = keyBusy ? 'Saving…' : 'Save';
|
|
137
|
+
form.setAttribute('aria-busy', String(keyBusy));
|
|
138
|
+
button.textContent = pending() ? 'Finish signing in in the terminal' : `Sign in with ${provider === 'claude' ? 'Claude' : 'Codex'}`;
|
|
139
|
+
error.textContent = issue; error.hidden = !issue;
|
|
140
|
+
}
|
|
141
|
+
function apply(account) {
|
|
142
|
+
if (typeof account?.loggedIn !== 'boolean') return;
|
|
143
|
+
const was = loggedIn; loggedIn = account.loggedIn;
|
|
144
|
+
if (loggedIn) {
|
|
145
|
+
terminal = null; issue = ''; suspended = false; unattached = false; keyOpen = false; input.value = '';
|
|
146
|
+
if (was === false) void onSignedIn();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function schedule() {
|
|
150
|
+
clearTimeout(timer);
|
|
151
|
+
if (current()) timer = setTimeout(() => void refresh(), pending() ? pollMs : pollMs * 5);
|
|
152
|
+
}
|
|
153
|
+
async function refresh() {
|
|
154
|
+
if (!current() || checking) return;
|
|
155
|
+
if (busy || keyBusy) { schedule(); return; }
|
|
156
|
+
checking = true; const epoch = push;
|
|
157
|
+
try {
|
|
158
|
+
const account = await readAccount();
|
|
159
|
+
if (!current() || epoch !== push) return;
|
|
160
|
+
apply(account);
|
|
161
|
+
if (loggedIn === false) {
|
|
162
|
+
const next = await requestTerminal(provider, accountId);
|
|
163
|
+
if (!current() || epoch !== push) return;
|
|
164
|
+
const ended = terminal?.sessionId && terminal.sessionId === next.sessionId && ['exited', 'error'].includes(next.status);
|
|
165
|
+
terminal = next;
|
|
166
|
+
if (ended || next.status === 'error') issue = next.error || 'Sign-in finished without connecting. Try again.';
|
|
167
|
+
}
|
|
168
|
+
} catch {
|
|
169
|
+
if (current() && epoch === push && pending()) {
|
|
170
|
+
issue = 'Could not check sign-in. Try again.'; terminal = null;
|
|
171
|
+
}
|
|
172
|
+
} finally { checking = false; if (current()) { render(); schedule(); } }
|
|
173
|
+
}
|
|
174
|
+
button.addEventListener('click', async () => {
|
|
175
|
+
if (!current() || pending() || keyBusy || loggedIn !== false) return;
|
|
176
|
+
input.value = ''; keyOpen = false;
|
|
177
|
+
busy = true; issue = ''; unattached = false; ++push; clearTimeout(timer); render();
|
|
178
|
+
try {
|
|
179
|
+
const next = await requestTerminal(provider, accountId, 'POST');
|
|
180
|
+
if (!current() || loggedIn === true) return;
|
|
181
|
+
terminal = next;
|
|
182
|
+
if (next.status === 'error') throw new Error(next.error);
|
|
183
|
+
await openTerminal(next);
|
|
184
|
+
} catch (failure) {
|
|
185
|
+
if (current()) { issue = failure.message || 'Could not open the sign-in terminal.'; unattached = true; }
|
|
186
|
+
} finally { busy = false; if (current()) { render(); schedule(); } }
|
|
187
|
+
});
|
|
188
|
+
secondary.addEventListener('click', () => {
|
|
189
|
+
if (!current() || pending() || keyBusy) return;
|
|
190
|
+
keyOpen = true; issue = ''; render(); input.focus?.();
|
|
191
|
+
});
|
|
192
|
+
cancel.addEventListener('click', () => {
|
|
193
|
+
if (keyBusy) return;
|
|
194
|
+
input.value = ''; keyOpen = false; issue = ''; render(); secondary.focus?.();
|
|
195
|
+
});
|
|
196
|
+
form.addEventListener('submit', async event => {
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
let key = input.value; input.value = '';
|
|
199
|
+
if (!current() || pending() || keyBusy || loggedIn !== false || !key) { key = null; return; }
|
|
200
|
+
keyBusy = true; issue = 'Saving API key…'; ++push; clearTimeout(timer); render();
|
|
201
|
+
let saved = false;
|
|
202
|
+
try {
|
|
203
|
+
await requestApiKey(provider, accountId, key);
|
|
204
|
+
key = null; saved = true;
|
|
205
|
+
if (!current()) return;
|
|
206
|
+
const epoch = push, account = await readAccount();
|
|
207
|
+
if (!current() || epoch !== push) return;
|
|
208
|
+
apply(account);
|
|
209
|
+
if (loggedIn !== true) issue = 'Key saved. Checking sign-in…';
|
|
210
|
+
} catch (failure) {
|
|
211
|
+
if (current() && loggedIn !== true) issue = saved ? 'Key saved. Could not refresh sign-in. Reload the panel.' : apiKeyErrorMessage(provider, failure.code);
|
|
212
|
+
} finally { key = null; keyBusy = false; if (current()) { render(); schedule(); } }
|
|
213
|
+
});
|
|
214
|
+
const observer = new MutationObserver(() => { if (current() && loggedIn === false && !suspended && root.parentNode !== host) render(); });
|
|
215
|
+
observer.observe(host, { childList: true });
|
|
216
|
+
render(); void refresh();
|
|
217
|
+
return {
|
|
218
|
+
refresh,
|
|
219
|
+
update(account) { if (!current()) return; ++push; apply(account); render(); schedule(); },
|
|
220
|
+
suspend() { suspended = true; input.value = ''; render(); },
|
|
221
|
+
dispose() { input.value = ''; disposed = true; ++push; clearTimeout(timer); observer.disconnect(); host.classList.remove('provider-auth-required'); root.remove(); },
|
|
222
|
+
};
|
|
223
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// ═══════════════════════════════════════════
|
|
10
10
|
|
|
11
11
|
import { emit, on } from './state.js';
|
|
12
|
-
import { getSynabunUpdateData, openSynabunUpdateModal,
|
|
12
|
+
import { getSynabunUpdateData, openSynabunUpdateModal, syncSynabunUpdateData, synabunUpdateMeta } from './ui-update.js';
|
|
13
13
|
import { getToolUpdateData, runToolUpdate, TOOL_LABELS } from './ui-tool-updates.js';
|
|
14
14
|
import { openSettingsModal } from './ui-settings.js';
|
|
15
15
|
import { getProviderMeta } from './provider-icons.js';
|
|
@@ -222,7 +222,7 @@ function computeUpdates() {
|
|
|
222
222
|
key: 'synabun',
|
|
223
223
|
title: 'SynaBun',
|
|
224
224
|
subtitle: `v${synabun.current} → v${synabun.latest}`,
|
|
225
|
-
meta: synabun
|
|
225
|
+
meta: synabunUpdateMeta(synabun),
|
|
226
226
|
action: 'Open updater',
|
|
227
227
|
severity: 'normal',
|
|
228
228
|
});
|
|
@@ -308,6 +308,12 @@ async function refreshRulesStatus() {
|
|
|
308
308
|
emitNotificationsUpdate();
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
// Inside the desktop app its updater reports on its own schedule (ui-update.js): the drawer and its count follow.
|
|
312
|
+
on('synabun-update:changed', () => {
|
|
313
|
+
emitNotificationsUpdate();
|
|
314
|
+
if (_panel) render();
|
|
315
|
+
});
|
|
316
|
+
|
|
311
317
|
// Settings > Setup re-reads the status after every rules action and passes it on.
|
|
312
318
|
on('rules:changed', (status) => {
|
|
313
319
|
_rulesStatus = status?.ok ? status : null;
|
|
@@ -894,7 +900,7 @@ async function refreshSessions() {
|
|
|
894
900
|
emitLoopsUpdate();
|
|
895
901
|
// Refresh notification feed alongside session/loop data
|
|
896
902
|
refreshRulesStatus().then(() => render()).catch(() => {});
|
|
897
|
-
|
|
903
|
+
syncSynabunUpdateData().then(() => render()).catch(() => {});
|
|
898
904
|
render();
|
|
899
905
|
} catch {}
|
|
900
906
|
}
|
|
@@ -2,6 +2,7 @@ import { mountMemoryMaintenance } from './ui-memory-maintenance.js';
|
|
|
2
2
|
import { buildJudgmentsTab, wireJudgmentsTab } from './ui-judgments.js';
|
|
3
3
|
import { buildWhatsAppTab, wireWhatsAppTab } from './ui-whatsapp.js';
|
|
4
4
|
import { buildCodeEditorTab, wireCodeEditorTab } from './settings/settings-code-editor-pane.js';
|
|
5
|
+
import { buildAboutTab, wireAboutTab } from './settings/settings-about-pane.js';
|
|
5
6
|
import { SETTINGS_GROUPS, SETTINGS_PAGES, DEFAULT_SETTINGS_PAGE, pageKeys, getSettingsPage, resolveSettingsTarget, homeOfControl } from './settings/settings-ia.js';
|
|
6
7
|
import * as kit from './settings/settings-kit.js';
|
|
7
8
|
import { RULES_HOST_LABELS, describeRulesHost, describeRulesInstall, describeRulesInstallAll } from './settings/settings-rules.js';
|
|
@@ -10,6 +11,12 @@ import { readGreetingStatus, describeGreeting, describeGreetingSaveFailure } fro
|
|
|
10
11
|
import { renderGreeting, clearGreeting } from './greeting/greeting-card.js';
|
|
11
12
|
import { createTunnelCard, drawInto, mcpKeyNeededText, readTunnel } from './ui-tunnel.js';
|
|
12
13
|
import { remoteMcpAddress } from './tunnel-view.js';
|
|
14
|
+
import { recheckCliStatus, getCliStatus, addCliToPath } from './cli-status.js';
|
|
15
|
+
import { cliInstallText, setCliInstallTranslator } from './cli-install-view.js';
|
|
16
|
+
setCliInstallTranslator((key, params) => kit.tx(`cliInstall.${key}`, params));
|
|
17
|
+
import { setGitBashTranslator } from './git-bash-view.js';
|
|
18
|
+
import { gitBashRowHtml, wireGitBashRow } from './ui-git-bash.js';
|
|
19
|
+
setGitBashTranslator((key, params) => kit.tx(`gitBash.${key}`, params));
|
|
13
20
|
import { initI18n, isReady as i18nReady, SUPPORTED_LOCALES, LOCALE_NAMES, SYSTEM_LOCALE, getLocale, getLocaleChoice, setLocaleChoice, getSystemLocale, englishTranslator, loadEnglishTranslator } from './i18n.js';
|
|
14
21
|
import { wireSettingsShell, wireSettingsSearch, collectSearchRows, revealSettingsTarget, followSettingsTarget, onSettingsTakeover, applyStoredSections, storeSectionState } from './settings/settings-shell.js';
|
|
15
22
|
import { buildSettingsSearchIndex } from './settings/settings-search.js';
|
|
@@ -18,7 +25,7 @@ import { buildSettingsSearchIndex } from './settings/settings-search.js';
|
|
|
18
25
|
// ═══════════════════════════════════════════
|
|
19
26
|
//
|
|
20
27
|
// The most complex shared UI module. Builds a floating settings panel with
|
|
21
|
-
//
|
|
28
|
+
// thirteen task pages in six groups (./settings/settings-ia.js). A page is a
|
|
22
29
|
// title, a one-line purpose and section cards (./settings/settings-kit.js);
|
|
23
30
|
// each builder below owns one pane of a page. Variant-registered tabs (the 2D
|
|
24
31
|
// Graphics tab) join the Appearance page. Old tab ids still open the right page.
|
|
@@ -69,6 +76,7 @@ const TAB_ICONS = {
|
|
|
69
76
|
whatsapp: '<svg viewBox="0 0 24 24"><path d="M3.5 20.5l1.3-3.9A8.5 8.5 0 1 1 8 19.6z"/><path d="M9.5 8.5c.4 2.6 2.9 5.2 5.5 5.6l1-1.2 1.6.8c-.3 1-1.1 1.6-2.1 1.5-2.9-.3-5.8-3.2-6.1-6.1-.1-1 .5-1.8 1.5-2.1l.8 1.6z"/></svg>',
|
|
70
77
|
morelogin: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M12 11.5a1 1 0 0 0-1 1c0 1.8-.3 3.6-1.2 5.2"/><path d="M7.8 14.5a8 8 0 0 0-.6 4.3"/><path d="M12 7.5a4.5 4.5 0 0 1 4.5 4.5c0 .6 0 1.2-.1 1.8"/><path d="M5 9.2a7 7 0 0 1 11-1.9"/><path d="M15 13a3 3 0 0 1-3 3"/></svg>',
|
|
71
78
|
editor: '<svg viewBox="0 0 24 24"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/><line x1="13.5" y1="5" x2="10.5" y2="19"/></svg>',
|
|
79
|
+
about: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="11"/><line x1="12" y1="7.5" x2="12.01" y2="7.5"/></svg>',
|
|
72
80
|
};
|
|
73
81
|
|
|
74
82
|
// ── Shared icon constants ──
|
|
@@ -1105,6 +1113,7 @@ function buildTerminalTab(cliConfig) {
|
|
|
1105
1113
|
<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
1106
1114
|
${kit.L('CLI002')}
|
|
1107
1115
|
</button>
|
|
1116
|
+
${p.id === 'gemini' ? '' : `<button type="button" class="cli-detect-btn" data-cli-add-path="${p.id}" hidden>${escapeHtml(cliInstallText('addPath'))}</button>`}
|
|
1108
1117
|
<span class="cli-path-status${isDefault ? '' : ' custom'}" id="cli-status-${p.id}" ${kit.inv('CLI007')}>${kit.te(isDefault ? 'settings.redesign.terminal.cliStatus.default' : 'settings.redesign.terminal.cliStatus.custom')}</span>
|
|
1109
1118
|
</div>
|
|
1110
1119
|
<div class="stg-help" id="cli-path-${p.id}-help">${kit.H(p.inv)}</div>
|
|
@@ -1129,9 +1138,11 @@ function buildTerminalTab(cliConfig) {
|
|
|
1129
1138
|
<p class="stg-help">${kit.th('settings.redesign.terminal.pathsIntro', { code: '<code class="stg-code">wsl</code>' })}</p>
|
|
1130
1139
|
${kit.help('CLI002', { forId: 'cli-paths-detect' })}
|
|
1131
1140
|
${cliProfiles.map(pathRow).join('')}
|
|
1141
|
+
${gitBashRowHtml()}
|
|
1132
1142
|
<button type="button" class="stg-action-btn stg-save-btn" id="cli-paths-save" ${kit.inv('CLI006')} aria-describedby="cli-paths-save-help">
|
|
1133
1143
|
${kit.L('CLI006')}
|
|
1134
1144
|
</button>
|
|
1145
|
+
<button type="button" class="cli-detect-btn" id="cli-path-diagnostics">${escapeHtml(cliInstallText('copyPathDiagnostics'))}</button>
|
|
1135
1146
|
${kit.help('CLI006', { forId: 'cli-paths-save' })}
|
|
1136
1147
|
|
|
1137
1148
|
${kit.subhead(kit.te('settings.redesign.terminal.examples'))}
|
|
@@ -3309,6 +3320,7 @@ export async function openSettingsModal(options = {}) {
|
|
|
3309
3320
|
skins: buildSkinsTab(skinsData.skins, skinsData.active),
|
|
3310
3321
|
interface: buildInterfaceTab(),
|
|
3311
3322
|
icons: buildIconsTab(customIconsData),
|
|
3323
|
+
about: buildAboutTab(),
|
|
3312
3324
|
}, variantTabs, initialPage)}
|
|
3313
3325
|
</div>
|
|
3314
3326
|
</div>
|
|
@@ -4398,6 +4410,9 @@ export async function openSettingsModal(options = {}) {
|
|
|
4398
4410
|
// ── Code editor: AI autocomplete (loads and saves itself) ──
|
|
4399
4411
|
wireCodeEditorTab(overlay);
|
|
4400
4412
|
|
|
4413
|
+
// ── About: version, links, system and dependencies (loads itself the first time its page is shown) ──
|
|
4414
|
+
wireAboutTab(overlay, { toast: showCCToast });
|
|
4415
|
+
|
|
4401
4416
|
// ── Discord tab handlers ──
|
|
4402
4417
|
{
|
|
4403
4418
|
// Token save
|
|
@@ -4539,6 +4554,36 @@ export async function openSettingsModal(options = {}) {
|
|
|
4539
4554
|
const cliDefaults = { 'claude-code': 'claude', 'codex': 'codex', 'gemini': 'gemini', 'opencode': 'opencode' };
|
|
4540
4555
|
const cliProfileIds = Object.keys(cliDefaults);
|
|
4541
4556
|
|
|
4557
|
+
const pathButtons = overlay.querySelectorAll('[data-cli-add-path]');
|
|
4558
|
+
const showPathAction = (tool, info) => {
|
|
4559
|
+
const button = overlay.querySelector(`[data-cli-add-path="${tool}"]`);
|
|
4560
|
+
if (button) button.hidden = !(info?.state === 'installed' && info.pathStatus?.canAdd === true);
|
|
4561
|
+
};
|
|
4562
|
+
pathButtons.forEach(button => {
|
|
4563
|
+
const tool = button.dataset.cliAddPath;
|
|
4564
|
+
getCliStatus(tool).then(info => showPathAction(tool, info)).catch(() => {});
|
|
4565
|
+
button.addEventListener('click', async () => {
|
|
4566
|
+
button.disabled = true; button.textContent = cliInstallText('addingPath');
|
|
4567
|
+
try {
|
|
4568
|
+
const result = await addCliToPath(tool);
|
|
4569
|
+
showCCToast(cliInstallText('doneAddedToPath', { dir: result.dir }) + (result.warning ? ` ${result.warning}` : ''));
|
|
4570
|
+
for (const pathButton of pathButtons) getCliStatus(pathButton.dataset.cliAddPath).then(info => showPathAction(pathButton.dataset.cliAddPath, info)).catch(() => {});
|
|
4571
|
+
} catch (error) { showCCToast(cliInstallText('pathFailed', { error: error.message })); }
|
|
4572
|
+
finally { button.disabled = false; button.textContent = cliInstallText('addPath'); }
|
|
4573
|
+
});
|
|
4574
|
+
});
|
|
4575
|
+
// Windows: the Git Bash every Claude Code SynaBun starts gets (ui-git-bash.js; hidden on macOS and Linux).
|
|
4576
|
+
wireGitBashRow(overlay.querySelector('#cli-git-bash'));
|
|
4577
|
+
overlay.querySelector('#cli-path-diagnostics')?.addEventListener('click', async () => {
|
|
4578
|
+
try {
|
|
4579
|
+
const response = await fetch('/api/cli/path');
|
|
4580
|
+
const diagnostics = await response.json();
|
|
4581
|
+
if (!response.ok) throw new Error(diagnostics.error || `HTTP ${response.status}`);
|
|
4582
|
+
await navigator.clipboard.writeText(JSON.stringify(diagnostics, null, 2));
|
|
4583
|
+
showCCToast(cliInstallText('copied'));
|
|
4584
|
+
} catch (error) { showCCToast(error.message); }
|
|
4585
|
+
});
|
|
4586
|
+
|
|
4542
4587
|
// Detect buttons
|
|
4543
4588
|
overlay.querySelectorAll('.cli-detect-btn[data-cli-detect]').forEach(btn => {
|
|
4544
4589
|
btn.addEventListener('click', async () => {
|
|
@@ -4552,9 +4597,13 @@ export async function openSettingsModal(options = {}) {
|
|
|
4552
4597
|
body: '{}',
|
|
4553
4598
|
});
|
|
4554
4599
|
const data = await res.json();
|
|
4555
|
-
|
|
4600
|
+
showPathAction(profileId, data);
|
|
4601
|
+
if (data.ok && data.found && data.path && data.state === 'broken') {
|
|
4602
|
+
// Found, but it does not start: not put in the field, so a broken path is never saved by accident.
|
|
4603
|
+
showCCToast(kit.tx('settings.redesign.terminal.detectionFailed', { message: data.error ? `${data.path}: ${data.error}` : data.path }));
|
|
4604
|
+
} else if (data.ok && data.found && data.path) {
|
|
4556
4605
|
input.value = data.path;
|
|
4557
|
-
showCCToast(kit.tx('settings.redesign.terminal.found', { path: data.path }));
|
|
4606
|
+
showCCToast(kit.tx('settings.redesign.terminal.found', { path: data.version ? `${data.path} (${data.version})` : data.path }));
|
|
4558
4607
|
} else {
|
|
4559
4608
|
showCCToast(kit.tx('settings.redesign.terminal.cliNotFoundInPath'));
|
|
4560
4609
|
}
|
|
@@ -4594,6 +4643,9 @@ export async function openSettingsModal(options = {}) {
|
|
|
4594
4643
|
}
|
|
4595
4644
|
});
|
|
4596
4645
|
showCCToast(kit.tx('settings.redesign.terminal.cliPathsSaved'));
|
|
4646
|
+
// The panels' CLI banners and the update badges follow the paths just saved (one forced
|
|
4647
|
+
// re-check answers for every CLI).
|
|
4648
|
+
recheckCliStatus('claude-code').catch(() => {});
|
|
4597
4649
|
} else {
|
|
4598
4650
|
alert(data.error || kit.tx('settings.redesign.terminal.failedToSave'));
|
|
4599
4651
|
}
|
|
@@ -99,7 +99,9 @@ function show(entry) {
|
|
|
99
99
|
entry.unregister = registerSidepanel({ owner: entry.id, layoutKey: entry.id, provider: entry.provider,
|
|
100
100
|
element, header, actions, buttonClass: 'sp-session-button', applyVisibility: () => renderPill(entry) });
|
|
101
101
|
if (!storage.getItem(`synabun-sidepanel-layout-${entry.id}`)) detachSidepanel(entry.id);
|
|
102
|
-
|
|
102
|
+
// A language the page address forces (?lang=, showcase captures) holds in the session's frame too.
|
|
103
|
+
const lang = new URLSearchParams(window.location.search).get('lang');
|
|
104
|
+
frame.src = `/sidepanel-session.html?provider=${entry.provider}${lang ? `&lang=${encodeURIComponent(lang)}` : ''}`;
|
|
103
105
|
}
|
|
104
106
|
setSidepanelVisible(entry.id, true);
|
|
105
107
|
}
|
|
@@ -118,11 +118,19 @@ const SYNC_HANDLERS = {
|
|
|
118
118
|
'assistant:permission-resolved': (msg) => emit('sync:assistant:permission-resolved', msg),
|
|
119
119
|
'assistant:focus': (msg) => emit('sync:assistant:focus', msg),
|
|
120
120
|
'assistant:accounts-changed': (msg) => emit('sync:assistant:accounts-changed', msg),
|
|
121
|
+
// Claude accounts (lib/claude-accounts.js): any account's state changed — signed in or out, a key saved or removed, its mode, renamed, added, removed
|
|
122
|
+
'claude:accounts-changed': (msg) => emit('sync:claude:accounts-changed', msg),
|
|
123
|
+
// Codex accounts (lib/codex-accounts.js): the same, for every Codex account
|
|
124
|
+
'codex:accounts-changed': (msg) => emit('sync:codex:accounts-changed', msg),
|
|
121
125
|
'assistant:mailbox': (msg) => emit('sync:assistant:mailbox', msg),
|
|
126
|
+
'assistant:budget': (msg) => emit('sync:assistant:budget', msg),
|
|
127
|
+
'assistant:budget-changed': (msg) => emit('sync:assistant:budget-changed', msg),
|
|
122
128
|
'assistant:cost': (msg) => emit('sync:assistant:cost', msg),
|
|
123
129
|
'assistant:desktop': (msg) => emit('sync:assistant:desktop', msg),
|
|
124
130
|
'assistant:desktop-setup': (msg) => emit('sync:assistant:desktop-setup', msg),
|
|
125
131
|
'assistant:routing-changed': (msg) => emit('sync:assistant:routing-changed', msg),
|
|
132
|
+
// Admin sandbox (lib/agent-sandbox-setting.js): the one global value changed in some window
|
|
133
|
+
'agents:admin-sandbox-changed': (msg) => emit('sync:agents:admin-sandbox-changed', msg),
|
|
126
134
|
|
|
127
135
|
// WhatsApp Link — states and counters only (never a QR, code, number or text); Settings → WhatsApp re-reads /api/whatsapp/status
|
|
128
136
|
'whatsapp:status': (msg) => emit('sync:whatsapp:status', msg),
|
|
@@ -6289,6 +6289,23 @@ export function openTerminalPanel(profile) {
|
|
|
6289
6289
|
emit('terminal:open', { profile });
|
|
6290
6290
|
}
|
|
6291
6291
|
|
|
6292
|
+
// Attach only: the guarded provider-auth route has already chosen and started
|
|
6293
|
+
// the CLI. No command text is accepted from either panel.
|
|
6294
|
+
export async function openProviderLoginTerminal(sessionId, label) {
|
|
6295
|
+
if (!/^[a-f0-9]{32}$/.test(sessionId || '')) throw new Error('Invalid sign-in terminal session.');
|
|
6296
|
+
await _whenOpenIdle();
|
|
6297
|
+
let session = _sessions.find(s => s.id === sessionId);
|
|
6298
|
+
if (!session) session = await openSession('shell', null, sessionId, { label });
|
|
6299
|
+
if (!session) throw new Error('Could not attach the sign-in terminal. Try again.');
|
|
6300
|
+
showPanel();
|
|
6301
|
+
const index = _sessions.indexOf(session);
|
|
6302
|
+
if (_detachedTabs.has(sessionId)) {
|
|
6303
|
+
bringTabToFront(sessionId);
|
|
6304
|
+
} else if (index >= 0) switchToSession(index);
|
|
6305
|
+
session.term?.focus();
|
|
6306
|
+
return session;
|
|
6307
|
+
}
|
|
6308
|
+
|
|
6292
6309
|
// ── Diagnostics (no UI) ──
|
|
6293
6310
|
// window.__synabunTermStats(): keystroke → echo-parsed latency, bytes handed
|
|
6294
6311
|
// to xterm but not yet parsed, flow-control acks pending, renderer state and
|
|
@@ -52,6 +52,11 @@ const SOURCE_LABELS = {
|
|
|
52
52
|
'winget': 'winget',
|
|
53
53
|
'scoop': 'Scoop',
|
|
54
54
|
'choco': 'Chocolatey',
|
|
55
|
+
'mise': 'mise',
|
|
56
|
+
'asdf': 'asdf',
|
|
57
|
+
'cargo': 'Cargo',
|
|
58
|
+
'snap': 'Snap',
|
|
59
|
+
'system': 'your system package manager',
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
function sourceLabel(src) {
|