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
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SynaBun — the desktop app's server
|
|
3
|
+
*
|
|
4
|
+
* The Electron window of a packaged build (packaging/desktop/) does not decide
|
|
5
|
+
* anything about the server itself: it runs `<entry> app-backend --json`
|
|
6
|
+
* (packaging/runtime/bootstrap.mjs), which comes here. This module finds the
|
|
7
|
+
* server the window should show, and starts one through the same Start Server
|
|
8
|
+
* launcher an npm install uses (lib/start-launcher.js runLauncher: the launch
|
|
9
|
+
* lock, the supervisor record, the health check), so two starts never race.
|
|
10
|
+
*
|
|
11
|
+
* reuse a server of this install (same entry, same version) answers:
|
|
12
|
+
* on the port the window used last, where this data home's
|
|
13
|
+
* supervisor says it listens, or on the configured port
|
|
14
|
+
* replace a server of this install from before an update answers: it is
|
|
15
|
+
* asked to shut down, and the new version starts in its place
|
|
16
|
+
* refuse another installation of SynaBun answers on the port with this
|
|
17
|
+
* same data home (or cannot say which one it uses): it is never
|
|
18
|
+
* stopped or adopted, and the window says so
|
|
19
|
+
* move the port is taken by something else (a program, a SynaBun on
|
|
20
|
+
* another data home): this install starts on a free port
|
|
21
|
+
*
|
|
22
|
+
* Every step is reported as an event ({ type: 'plan' | 'existing' | 'step' |
|
|
23
|
+
* 'supervisor' | 'ready' | 'conflict' | 'failed', ... }); the window shows them.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { createHash } from 'node:crypto';
|
|
27
|
+
import { realpathSync, readFileSync } from 'node:fs';
|
|
28
|
+
import { join, resolve } from 'node:path';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Which data home a server uses, without saying where it is: the first 16 hex
|
|
32
|
+
* characters of a SHA-256 of its real path (lower case on Windows, where case
|
|
33
|
+
* does not tell paths apart). /api/health reports it, so the app can tell a
|
|
34
|
+
* second copy on the same data from one on another.
|
|
35
|
+
*/
|
|
36
|
+
export function dataHomeId(dataHome, platform = process.platform) {
|
|
37
|
+
let path = resolve(String(dataHome || ''));
|
|
38
|
+
try { path = realpathSync.native(path); } catch {}
|
|
39
|
+
if (platform === 'win32') path = path.toLowerCase();
|
|
40
|
+
return createHash('sha256').update(path).digest('hex').slice(0, 16);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function samePath(a, b, platform) {
|
|
44
|
+
const norm = (value) => {
|
|
45
|
+
let path = String(value || '').replace(/\\/g, '/');
|
|
46
|
+
try { path = realpathSync.native(path).replace(/\\/g, '/'); } catch {}
|
|
47
|
+
return platform === 'win32' ? path.toLowerCase() : path;
|
|
48
|
+
};
|
|
49
|
+
return !!a && !!b && norm(a) === norm(b);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* What answers on a port, for this install:
|
|
54
|
+
* 'none' nothing answers
|
|
55
|
+
* 'other' something answers that is not a SynaBun server
|
|
56
|
+
* 'ours' this install, this version
|
|
57
|
+
* 'ours-stale' this install, another version (from before an update)
|
|
58
|
+
* 'foreign' another installation, on another data home
|
|
59
|
+
* 'foreign-same-data' another installation on this data home, or one that does not say
|
|
60
|
+
*/
|
|
61
|
+
export function classifyServer(health, { entry, packageRoot, version, dataHomeId: ours, platform = process.platform, answered = true } = {}) {
|
|
62
|
+
if (!health) return { kind: answered ? 'other' : 'none' };
|
|
63
|
+
if (health.ok !== true || health.storage !== 'sqlite' || typeof health.projectDir !== 'string') return { kind: 'other', health };
|
|
64
|
+
// This install: the entry it runs from (installEntry; `entry` is only the path that outlives the run, empty for a
|
|
65
|
+
// copy on its disk image or a translocated one), or the very same application folder. An AppImage's folder is a
|
|
66
|
+
// new mount every run, and its entry (the image file) is what matches.
|
|
67
|
+
const theirEntry = health.installEntry || health.entry;
|
|
68
|
+
if ((entry && theirEntry && samePath(theirEntry, entry, platform)) || (packageRoot && samePath(health.projectDir, packageRoot, platform))) {
|
|
69
|
+
return { kind: String(health.version || '') === String(version) ? 'ours' : 'ours-stale', health };
|
|
70
|
+
}
|
|
71
|
+
if (health.dataHomeId && health.dataHomeId !== ours) return { kind: 'foreign', health };
|
|
72
|
+
// Said so (the same data home), or said nothing (a server from before 2026-10-17 reports no data home).
|
|
73
|
+
return { kind: 'foreign-same-data', health, known: !!health.dataHomeId };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** A server that answers its health check completely: ready for the window. */
|
|
77
|
+
export function serverReady(health) {
|
|
78
|
+
return !!health && health.ok === true && health.storage === 'sqlite' && typeof health.projectDir === 'string' && !!health.startLauncher;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function defaultHealth(port, { fetchImpl = globalThis.fetch, timeoutMs = 1500 } = {}) {
|
|
82
|
+
try {
|
|
83
|
+
const response = await fetchImpl(`http://127.0.0.1:${port}/api/health`, { signal: AbortSignal.timeout(timeoutMs), headers: { accept: 'application/json' } });
|
|
84
|
+
if (!response.ok) return { status: response.status };
|
|
85
|
+
return await response.json();
|
|
86
|
+
} catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function readJson(path) {
|
|
92
|
+
try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return null; }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Find or start the server for the desktop app. Resolves with the final event
|
|
97
|
+
* ('ready', 'conflict' or 'failed'); `emit` receives every event on the way.
|
|
98
|
+
* Everything that touches the system is a parameter, for the tests.
|
|
99
|
+
*/
|
|
100
|
+
export async function runAppBackend({
|
|
101
|
+
env = process.env,
|
|
102
|
+
runtime,
|
|
103
|
+
packageRoot,
|
|
104
|
+
dataHome,
|
|
105
|
+
preferPort = null,
|
|
106
|
+
platform = process.platform,
|
|
107
|
+
emit = () => {},
|
|
108
|
+
launcher, // lib/start-launcher.js (runLauncher, resolvePort, portAccepts, launcherStatePaths, pidAlive)
|
|
109
|
+
backgroundCommand, // lib/desktop-pwa.js: the background start of a packaged build
|
|
110
|
+
spawn,
|
|
111
|
+
health = defaultHealth,
|
|
112
|
+
shutdown = null,
|
|
113
|
+
sleep = (ms) => new Promise(done => setTimeout(done, ms)),
|
|
114
|
+
now = () => Date.now(),
|
|
115
|
+
readyWaitMs = 5 * 60 * 1000,
|
|
116
|
+
searchSpan = 20,
|
|
117
|
+
} = {}) {
|
|
118
|
+
const ours = { entry: runtime?.entry || null, packageRoot: packageRoot || runtime?.packageRoot || null, version: runtime?.version || '', dataHomeId: dataHomeId(dataHome, platform), platform };
|
|
119
|
+
const { runLauncher, resolvePort, portAccepts, launcherStatePaths, pidAlive } = launcher;
|
|
120
|
+
const configured = resolvePort({ env, dataHome });
|
|
121
|
+
const paths = launcherStatePaths(dataHome);
|
|
122
|
+
const supervisorRecord = () => readJson(paths.supervisor);
|
|
123
|
+
const look = async (port) => {
|
|
124
|
+
const answer = await health(port);
|
|
125
|
+
if (answer && answer.ok === undefined && answer.status) return classifyServer(null, { ...ours, answered: true });
|
|
126
|
+
if (answer) return classifyServer(answer, ours);
|
|
127
|
+
return classifyServer(null, { ...ours, answered: await portAccepts(port).catch(() => false) });
|
|
128
|
+
};
|
|
129
|
+
const ready = (port, extra) => {
|
|
130
|
+
const record = supervisorRecord();
|
|
131
|
+
return { type: 'ready', port, supervisorPid: record && !record.endedAt && pidAlive(record.pid) ? record.pid : null, ...extra };
|
|
132
|
+
};
|
|
133
|
+
const conflict = (port, found) => ({ type: 'conflict', port, projectDir: found.health?.projectDir || null, install: found.health?.install || null, version: found.health?.version || null });
|
|
134
|
+
|
|
135
|
+
emit({ type: 'plan', dataHome, port: configured, preferredPort: configured, dataHomeId: ours.dataHomeId });
|
|
136
|
+
|
|
137
|
+
// This install's server from before an update: its files are gone or replaced. It goes; the new one starts.
|
|
138
|
+
const stopStale = async (stalePort, staleVersion) => {
|
|
139
|
+
const asked = shutdown ? await shutdown(stalePort) : false;
|
|
140
|
+
const deadline = now() + 20000;
|
|
141
|
+
while (await portAccepts(stalePort).catch(() => false)) {
|
|
142
|
+
if (now() >= deadline) return { type: 'failed', code: 'STALE_SERVER', message: `An older SynaBun server of this copy (v${staleVersion}) still runs on port ${stalePort} and did not stop${asked ? '' : ' when asked'}.`, log: paths.log };
|
|
143
|
+
await sleep(300);
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// 1. A server of this install that is already up: where the window was last,
|
|
149
|
+
// or where this data home's supervisor says its server listens. Another
|
|
150
|
+
// installation on this data home there is never a reason to start a second one.
|
|
151
|
+
const record = supervisorRecord();
|
|
152
|
+
const recordPort = record && !record.endedAt && pidAlive(record.pid) && record.phase === 'listening' ? Number(record.detail?.port) || null : null;
|
|
153
|
+
for (const earlier of [...new Set([preferPort, recordPort].filter(value => value && value !== configured))]) {
|
|
154
|
+
const seen = await look(earlier);
|
|
155
|
+
if (seen.kind === 'none') continue;
|
|
156
|
+
emit({ type: 'existing', port: earlier, kind: seen.kind, version: seen.health?.version || null });
|
|
157
|
+
if (seen.kind === 'ours') return finish(ready(earlier, { reused: true, started: false, version: seen.health.version }));
|
|
158
|
+
// Another installation on this data home, or one too old to say which data home it uses (every server from
|
|
159
|
+
// before 2026-10-17): the window is told where it runs. Starting this install beside it could mean two
|
|
160
|
+
// servers on one data home.
|
|
161
|
+
if (seen.kind === 'foreign-same-data') return finish(conflict(earlier, seen));
|
|
162
|
+
if (seen.kind === 'ours-stale') {
|
|
163
|
+
const failed = await stopStale(earlier, seen.health.version);
|
|
164
|
+
if (failed) return finish(failed);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 2. The configured port.
|
|
169
|
+
let port = configured;
|
|
170
|
+
let alternative = false;
|
|
171
|
+
const found = await look(configured);
|
|
172
|
+
if (found.kind !== 'none') emit({ type: 'existing', port: configured, kind: found.kind, version: found.health?.version || null });
|
|
173
|
+
if (found.kind === 'ours') return finish(ready(configured, { reused: true, started: false, version: found.health.version }));
|
|
174
|
+
if (found.kind === 'foreign-same-data') return finish(conflict(configured, found));
|
|
175
|
+
if (found.kind === 'ours-stale') {
|
|
176
|
+
const failed = await stopStale(configured, found.health.version);
|
|
177
|
+
if (failed) return finish(failed);
|
|
178
|
+
} else if (found.kind === 'foreign' || found.kind === 'other') {
|
|
179
|
+
const free = await freePort([preferPort, ...Array.from({ length: searchSpan }, (_, i) => configured + 1 + i)]);
|
|
180
|
+
if (!free) return finish({ type: 'failed', code: 'NO_PORT', message: `Port ${configured} is in use by another program, and no free port was found near it.`, log: paths.log });
|
|
181
|
+
port = free;
|
|
182
|
+
alternative = true;
|
|
183
|
+
emit({ type: 'plan', dataHome, port, preferredPort: configured, alternativePort: true, dataHomeId: ours.dataHomeId });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function freePort(candidates) {
|
|
187
|
+
for (const candidate of [...new Set(candidates.filter(value => Number.isInteger(value) && value > 0 && value < 65536))]) {
|
|
188
|
+
if (!(await portAccepts(candidate).catch(() => true))) return candidate;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 3. Start, through the launcher (lock, supervisor record, background start).
|
|
194
|
+
let launcherPid = null;
|
|
195
|
+
let lastPhase = null;
|
|
196
|
+
const reportPhase = (current) => {
|
|
197
|
+
if (!current?.phase || current.phase === lastPhase) return;
|
|
198
|
+
lastPhase = current.phase;
|
|
199
|
+
emit({ type: 'supervisor', phase: current.phase, detail: current.detail || null });
|
|
200
|
+
};
|
|
201
|
+
const reporter = () => ({
|
|
202
|
+
get listening() { return false; },
|
|
203
|
+
listen: async () => false,
|
|
204
|
+
step: (id) => emit({ type: 'step', id: String(id) }),
|
|
205
|
+
supervisor: reportPhase,
|
|
206
|
+
finish: () => {},
|
|
207
|
+
linger: async () => {},
|
|
208
|
+
close: () => {},
|
|
209
|
+
});
|
|
210
|
+
const result = await runLauncher({
|
|
211
|
+
argv: ['--port', String(port)],
|
|
212
|
+
env: { ...env, NEURAL_PORT: String(port) },
|
|
213
|
+
packageRoot,
|
|
214
|
+
background: true,
|
|
215
|
+
beacon: reporter,
|
|
216
|
+
spawnImpl: (file, args, options) => {
|
|
217
|
+
const command = backgroundCommand(runtime, options.env);
|
|
218
|
+
const child = spawn(command.file, command.args, { ...options, env: command.env, cwd: command.cwd || options.cwd });
|
|
219
|
+
launcherPid = child.pid || null;
|
|
220
|
+
return child;
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
if (result.outcome === 'failed') {
|
|
224
|
+
const failure = supervisorRecord();
|
|
225
|
+
return finish({ type: 'failed', code: failure?.error?.code || 'START_FAILED', message: failure?.phase === 'failed' && failure.error?.message ? failure.error.message : 'SynaBun\'s server could not be started.', log: paths.log });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 4. Until it answers completely (a first start downloads the automation browser and backs up the data).
|
|
229
|
+
const deadline = now() + readyWaitMs;
|
|
230
|
+
for (;;) {
|
|
231
|
+
const answer = await health(port);
|
|
232
|
+
if (serverReady(answer)) {
|
|
233
|
+
const kind = classifyServer(answer, ours).kind;
|
|
234
|
+
if (kind !== 'ours') return finish(kind === 'foreign-same-data' ? conflict(port, { health: answer }) : { type: 'failed', code: 'NOT_OURS', message: `Another program took port ${port} while SynaBun started.`, log: paths.log });
|
|
235
|
+
return finish(ready(port, { reused: result.outcome !== 'started', started: result.outcome === 'started', launcherPid, version: answer.version, alternativePort: alternative, preferredPort: configured }));
|
|
236
|
+
}
|
|
237
|
+
const current = supervisorRecord();
|
|
238
|
+
reportPhase(current);
|
|
239
|
+
if (current?.phase === 'failed' && current.error) return finish({ type: 'failed', code: current.error.code || 'START_FAILED', message: current.error.message, log: paths.log });
|
|
240
|
+
if (now() >= deadline) return finish({ type: 'failed', code: 'NO_ANSWER', message: `SynaBun's server did not answer within ${Math.round(readyWaitMs / 60000)} minutes.`, log: paths.log });
|
|
241
|
+
await sleep(400);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function finish(event) {
|
|
245
|
+
emit(event);
|
|
246
|
+
return event;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** POST /api/server/shutdown on the loopback address: the server's own graceful stop. */
|
|
251
|
+
export async function requestServerShutdown(port, { fetchImpl = globalThis.fetch } = {}) {
|
|
252
|
+
try {
|
|
253
|
+
const response = await fetchImpl(`http://127.0.0.1:${port}/api/server/shutdown`, {
|
|
254
|
+
method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}', signal: AbortSignal.timeout(3000),
|
|
255
|
+
});
|
|
256
|
+
return response.ok;
|
|
257
|
+
} catch {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Where the launcher writes its log for a data home (what "Open logs" shows). */
|
|
263
|
+
export function launcherLogOf(dataHome) {
|
|
264
|
+
return join(dataHome, 'data', 'launcher.log');
|
|
265
|
+
}
|
package/lib/external-tools.js
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* SynaBun — external tools stay external
|
|
3
3
|
*
|
|
4
4
|
* Claude Code, Codex, OpenCode and Gemini CLI are programs of their own. The
|
|
5
|
-
* user installs them; SynaBun finds what is installed (
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* user installs them; SynaBun finds what is installed (Settings, PATH and the
|
|
6
|
+
* OS PATH, the folders of every install method:
|
|
7
|
+
* neural-interface/lib/cli-resolver.js) and talks to it, through a thin
|
|
8
|
+
* JavaScript SDK where there is one. It never ships or runs a copy of its own.
|
|
9
|
+
* When one is missing, the side panels can run its vendor's official installer
|
|
10
|
+
* on the user's click (neural-interface/lib/cli-install.js), which installs it
|
|
11
|
+
* where that installer always does, as the user's own.
|
|
8
12
|
*
|
|
9
13
|
* npm has no way to say "this SDK, without the program it carries": the Claude
|
|
10
14
|
* Agent SDK brings the Claude Code executable as a per-platform optional
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SynaBun — secrets out of the install and start logs a person is shown
|
|
3
|
+
*
|
|
4
|
+
* What the setup wizard's Details (GET /api/setup/install-details) and the
|
|
5
|
+
* desktop app's start log show is what programs wrote: npm, the user's own
|
|
6
|
+
* npm, the supervisor and the server. Such output can carry a secret: npm
|
|
7
|
+
* prints an invalid setting with its value, an error names a URL with its
|
|
8
|
+
* password, a log line repeats a header or an environment variable. Before
|
|
9
|
+
* any of it is shown or kept, this takes out
|
|
10
|
+
*
|
|
11
|
+
* - npm auth settings (`//registry…/:_authToken=…`, `_auth`, `_password`)
|
|
12
|
+
* - the password in a URL (`https://user:pass@host`)
|
|
13
|
+
* - Authorization, Proxy-Authorization, Cookie and API-key headers
|
|
14
|
+
* - the token shapes of the usual services (OpenAI / Anthropic `sk-…`,
|
|
15
|
+
* GitHub, GitLab, npm, Slack, AWS, Google, Stripe, JWTs, Bearer tokens,
|
|
16
|
+
* private key blocks)
|
|
17
|
+
* - the value of a variable or setting whose name says it is secret
|
|
18
|
+
* (…TOKEN, …SECRET, …PASSWORD, …API_KEY, …CREDENTIALS, …)
|
|
19
|
+
*
|
|
20
|
+
* Each becomes [redacted]; the text around it stays. Redact before you cut a
|
|
21
|
+
* text short: half a secret no longer looks like one.
|
|
22
|
+
*
|
|
23
|
+
* No imports: packaging/desktop/src/log-redact.mjs is this file, byte for byte
|
|
24
|
+
* (the desktop window cannot reach the application's files), and
|
|
25
|
+
* packaging/tests/log-redact.test.mjs fails when the two differ.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export const REDACTED = '[redacted]';
|
|
29
|
+
|
|
30
|
+
// Names whose value is a secret: a word of the name (split on _ - .) is one of these, or it ends in one.
|
|
31
|
+
const SECRET_WORDS = 'TOKEN|TOKENS|SECRET|SECRETS|PASSWORD|PASSWD|PASSPHRASE|PASS|PWD|CREDENTIAL|CREDENTIALS|APIKEY|AUTH|AUTHTOKEN|COOKIE|SESSIONID|SESSION|PRIVATEKEY|ACCESSKEY|SECRETKEY|CLIENTSECRET|SIGNATURE';
|
|
32
|
+
const SECRET_NAME = new RegExp(`(?:^|[_.-])(?:${SECRET_WORDS})$|(?:^|[_.-])(?:${SECRET_WORDS})(?:[_.-])|(?:API|ACCESS|PRIVATE|SECRET|CLIENT|SIGNING|MASTER|ENCRYPTION|SERVICE)[_.-]?KEY(?:$|[_.-])`, 'i');
|
|
33
|
+
// The shell's working folder variables are folders, not passwords.
|
|
34
|
+
const NOT_SECRET = new Set(['PWD', 'OLDPWD', 'SSH_AUTH_SOCK', 'GIT_ASKPASS', 'SSH_ASKPASS', 'SUDO_ASKPASS']);
|
|
35
|
+
|
|
36
|
+
/** Whether a variable or setting called `name` holds a secret. */
|
|
37
|
+
export function isSecretName(name) {
|
|
38
|
+
const text = String(name || '').replace(/^[-_]+/, '');
|
|
39
|
+
if (!text || NOT_SECRET.has(text.toUpperCase())) return false;
|
|
40
|
+
// camelCase names (accessToken, apiKey) as words.
|
|
41
|
+
const words = text.replace(/([a-z0-9])([A-Z])/g, '$1_$2');
|
|
42
|
+
return SECRET_NAME.test(words) || /^(?:auth|password|token|secret)$/i.test(text);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const PATTERNS = [
|
|
46
|
+
// A private key block, whole (to the end of the text when its end is not in it yet: a log read in pieces).
|
|
47
|
+
[/-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY-----|$)/g, () => REDACTED],
|
|
48
|
+
// The rest of such a block in the next piece: its base64 lines (upper and lower case and digits, as key material
|
|
49
|
+
// has; a hex hash or a row of one letter is not) and its end line.
|
|
50
|
+
[/^(?=[A-Za-z0-9+/]*[A-Z])(?=[A-Za-z0-9+/]*[a-z])(?=[A-Za-z0-9+/]*[0-9])[A-Za-z0-9+/]{40,}={0,2}$/gm, () => REDACTED],
|
|
51
|
+
[/-----END [A-Z0-9 ]*PRIVATE KEY-----/g, () => REDACTED],
|
|
52
|
+
// npm's auth settings: `//registry.npmjs.org/:_authToken=…`, `_auth = …`, `:_password=…` (also as npm_config__auth…).
|
|
53
|
+
[/((?:\/\/[^\s=:]*(?::\d+)?[^\s=]*?:)?_(?:authToken|auth|password)\s*[=:]\s*)("[^"]*"|'[^']*'|[^\s"',;]+)/gi, (_, head, value) => {
|
|
54
|
+
const quote = /^["']/.test(value) ? value[0] : '';
|
|
55
|
+
return `${head}${quote}${REDACTED}${quote}`;
|
|
56
|
+
}],
|
|
57
|
+
// The password in a URL's user info.
|
|
58
|
+
[/\b([a-z][a-z0-9+.-]*:\/\/[^\s/?#@:'"<>]*):([^\s/?#@'"<>]+)@/gi, (_, head) => `${head}:${REDACTED}@`],
|
|
59
|
+
// Headers: the value to the end of the line.
|
|
60
|
+
[/(^|[\s"'{,(])((?:proxy-)?authorization|x-api-key|api-key|x-auth-token|x-access-token|cookie|set-cookie)(\s*["']?\s*[:=]\s*["']?)([^\r\n"']+)/gim, (_, lead, name, sep) => `${lead}${name}${sep}${REDACTED}`],
|
|
61
|
+
// Bearer / Basic / token schemes wherever they stand.
|
|
62
|
+
[/\b(Bearer|Basic|Token)\s+(?=[A-Za-z0-9._~+/=-]*[0-9+/=_-])[A-Za-z0-9._~+/=-]{12,}/g, (_, scheme) => `${scheme} ${REDACTED}`],
|
|
63
|
+
// Token shapes of the usual services.
|
|
64
|
+
[/\b(?:sk|rk|pk)[-_](?:live|test|proj|ant|or|api|svcacct|admin)?[-_]?[A-Za-z0-9_-]{16,}/g, () => REDACTED],
|
|
65
|
+
[/\b(?:gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})/g, () => REDACTED],
|
|
66
|
+
[/\bglpat-[A-Za-z0-9_-]{16,}/g, () => REDACTED],
|
|
67
|
+
[/\bnpm_[A-Za-z0-9]{30,}/g, () => REDACTED],
|
|
68
|
+
[/\bxox[abprs]-[A-Za-z0-9-]{10,}/g, () => REDACTED],
|
|
69
|
+
[/\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g, () => REDACTED],
|
|
70
|
+
[/\bAIza[0-9A-Za-z_-]{30,}/g, () => REDACTED],
|
|
71
|
+
[/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g, () => REDACTED],
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
// NAME=value, NAME: value, "NAME": "value", --name=value: the value when the name is a secret's.
|
|
75
|
+
const ASSIGNMENT = /(^|[\s,;{(\[]|--)(["']?)([A-Za-z_][A-Za-z0-9_.-]*)\2(\s*[=:]\s*)(\[redacted\]|"[^"]*"|'[^']*'|[^\s"',;)}\]]+)/gm;
|
|
76
|
+
|
|
77
|
+
/** `text` with every secret this file knows replaced by [redacted]. */
|
|
78
|
+
export function redactSecrets(text) {
|
|
79
|
+
let out = String(text ?? '');
|
|
80
|
+
if (!out) return out;
|
|
81
|
+
for (const [pattern, replace] of PATTERNS) out = out.replace(pattern, replace);
|
|
82
|
+
out = out.replace(ASSIGNMENT, (whole, lead, quote, name, sep, value) => {
|
|
83
|
+
if (!isSecretName(name)) return whole;
|
|
84
|
+
const bare = value.replace(/^["']|["']$/g, '');
|
|
85
|
+
if (!bare || bare === REDACTED) return whole;
|
|
86
|
+
const q = /^["']/.test(value) ? value[0] : '';
|
|
87
|
+
return `${lead}${quote}${name}${quote}${sep}${q}${REDACTED}${q}`;
|
|
88
|
+
});
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** redactSecrets() over every string inside `value` (objects and arrays copied, at most `depth` levels). */
|
|
93
|
+
export function redactDeep(value, depth = 8) {
|
|
94
|
+
if (typeof value === 'string') return redactSecrets(value);
|
|
95
|
+
if (!value || typeof value !== 'object' || depth <= 0) return value;
|
|
96
|
+
if (Array.isArray(value)) return value.map(item => redactDeep(item, depth - 1));
|
|
97
|
+
const out = {};
|
|
98
|
+
for (const [key, item] of Object.entries(value)) {
|
|
99
|
+
out[key] = isSecretName(key) && typeof item === 'string' && item ? REDACTED : redactDeep(item, depth - 1);
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|