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,194 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun — Git Bash: which one Claude Code runs
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Claude Code on Windows looks for Git Bash itself, in this order (read from
|
|
6
|
+
// its 2.1.302 build): CLAUDE_CODE_GIT_BASH_PATH when it names an existing
|
|
7
|
+
// bash.exe / sh.exe (the `env` block of ~/.claude/settings.json is applied
|
|
8
|
+
// before it looks, so a value there counts the same), then
|
|
9
|
+
// C:\Program Files\Git\bin\bash.exe and C:\Program Files (x86)\Git\bin\bash.exe,
|
|
10
|
+
// then the first `git` on its PATH, two folders up, bin\bash.exe. Without one,
|
|
11
|
+
// its Bash tool is gone and every hook runs in PowerShell.
|
|
12
|
+
//
|
|
13
|
+
// resolveGitBash() answers which Git Bash a Claude Code started by SynaBun ends
|
|
14
|
+
// up with, and whether SynaBun has to name it:
|
|
15
|
+
//
|
|
16
|
+
// env / settings CLAUDE_CODE_GIT_BASH_PATH of SynaBun's own environment, or
|
|
17
|
+
// of the user's ~/.claude/settings.json: the user's choice,
|
|
18
|
+
// which Claude Code reads by itself
|
|
19
|
+
// system a Git Bash of the PC's own. When Claude Code finds it by
|
|
20
|
+
// its own rules nothing is passed (SynaBun never overrides
|
|
21
|
+
// what already works); one only SynaBun finds (git on PATH
|
|
22
|
+
// in a layout Claude Code does not walk, a per-user or Scoop
|
|
23
|
+
// install that is not on PATH) is passed to it
|
|
24
|
+
// bundled SynaBun's copy inside an installed app (<resources>\git)
|
|
25
|
+
// downloaded SynaBun's copy in the data home (a Windows npm install)
|
|
26
|
+
//
|
|
27
|
+
// A path inside SynaBun's own copies is never taken for the user's, whatever
|
|
28
|
+
// variable or PATH entry leads to it (a server started from a SynaBun terminal
|
|
29
|
+
// inherits both): it is found again as SynaBun's own, last. Every file system
|
|
30
|
+
// question is injectable, so the Windows rules are tested from any system.
|
|
31
|
+
|
|
32
|
+
import { statSync } from 'node:fs';
|
|
33
|
+
import { win32 } from 'node:path';
|
|
34
|
+
|
|
35
|
+
/** The variable Claude Code reads (and the settings `env` key SynaBun writes for the user's own CLI). */
|
|
36
|
+
export const GIT_BASH_ENV = 'CLAUDE_CODE_GIT_BASH_PATH';
|
|
37
|
+
|
|
38
|
+
/** The file names Claude Code accepts in CLAUDE_CODE_GIT_BASH_PATH. */
|
|
39
|
+
const BASH_NAMES = new Set(['bash.exe', 'sh.exe', 'bash', 'sh']);
|
|
40
|
+
|
|
41
|
+
/** Where Claude Code looks before PATH: these two, literally. */
|
|
42
|
+
export const CLAUDE_FIXED_BASH = Object.freeze(['C:\\Program Files\\Git\\bin\\bash.exe', 'C:\\Program Files (x86)\\Git\\bin\\bash.exe']);
|
|
43
|
+
|
|
44
|
+
const key = (path) => win32.normalize(String(path || '')).replace(/[\\/]+$/, '').toLowerCase();
|
|
45
|
+
|
|
46
|
+
const defaultIsFile = (path) => { try { return statSync(path).isFile(); } catch { return false; } };
|
|
47
|
+
|
|
48
|
+
/** Is `path` inside one of `roots` (or one of them)? Windows rules: case and slashes do not matter. */
|
|
49
|
+
export function insideAny(path, roots) {
|
|
50
|
+
const at = key(path);
|
|
51
|
+
return roots.filter(Boolean).some((root) => { const top = key(root); return at === top || at.startsWith(`${top}\\`); });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** A value of CLAUDE_CODE_GIT_BASH_PATH that Claude Code would take: a bash.exe / sh.exe that exists. */
|
|
55
|
+
export function acceptableBashPath(value, { isFile = defaultIsFile } = {}) {
|
|
56
|
+
const path = String(value || '').trim();
|
|
57
|
+
if (!path || !BASH_NAMES.has(win32.basename(path).toLowerCase())) return false;
|
|
58
|
+
return isFile(path);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The PATH folders, in order, `%VARS%` of an unexpanded entry left as they are (they name no git either way). */
|
|
62
|
+
function pathFolders(pathValue) {
|
|
63
|
+
return String(pathValue || '').split(';').map((entry) => entry.trim().replace(/^"(.*)"$/, '$1')).filter(Boolean);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The first git on `pathValue`, as Windows finds it (git.exe, then git.cmd), skipping SynaBun's own folders. */
|
|
67
|
+
export function firstGitOnPath(pathValue, { isFile = defaultIsFile, own = [] } = {}) {
|
|
68
|
+
for (const folder of pathFolders(pathValue)) {
|
|
69
|
+
for (const name of ['git.exe', 'git.cmd']) {
|
|
70
|
+
const file = win32.join(folder, name);
|
|
71
|
+
if (!isFile(file)) continue;
|
|
72
|
+
if (insideAny(file, own)) continue;
|
|
73
|
+
return file;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** The Git Bash a git found on PATH belongs to: Claude Code's own rule first (git\..\..\bin), then one more level up. */
|
|
80
|
+
export function bashOfGit(gitFile, { isFile = defaultIsFile } = {}) {
|
|
81
|
+
if (!gitFile) return null;
|
|
82
|
+
const folder = win32.dirname(gitFile);
|
|
83
|
+
for (const candidate of [win32.join(folder, '..', 'bin', 'bash.exe'), win32.join(folder, '..', '..', 'bin', 'bash.exe')]) {
|
|
84
|
+
if (isFile(candidate)) return win32.normalize(candidate);
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The folders Git for Windows is installed in when nothing names it: every installer's default, per machine and per user, and Scoop's. */
|
|
90
|
+
export function standardGitRoots(env = {}) {
|
|
91
|
+
const roots = [];
|
|
92
|
+
const add = (base, ...rest) => { if (base) roots.push(win32.join(base, ...rest)); };
|
|
93
|
+
add(env.ProgramFiles || env.PROGRAMFILES, 'Git');
|
|
94
|
+
add(env.ProgramW6432, 'Git');
|
|
95
|
+
add(env['ProgramFiles(x86)'] || env['PROGRAMFILES(X86)'], 'Git');
|
|
96
|
+
roots.push('C:\\Program Files\\Git', 'C:\\Program Files (x86)\\Git');
|
|
97
|
+
add(env.LOCALAPPDATA, 'Programs', 'Git');
|
|
98
|
+
add(env.SCOOP, 'apps', 'git', 'current');
|
|
99
|
+
add(env.USERPROFILE, 'scoop', 'apps', 'git', 'current');
|
|
100
|
+
const seen = new Set();
|
|
101
|
+
return roots.filter((root) => { const id = key(root); if (seen.has(id)) return false; seen.add(id); return true; });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* What Claude Code finds by itself, by its own rules, or null: its variable (from SynaBun's environment, then the
|
|
106
|
+
* user's settings), its two fixed places, the first git on PATH. `{ path, source }`.
|
|
107
|
+
*/
|
|
108
|
+
export function claudeCodeFinds({ env = {}, settingsValue = null, pathValue = '', isFile = defaultIsFile, own = [] } = {}) {
|
|
109
|
+
const fromEnv = env[GIT_BASH_ENV];
|
|
110
|
+
if (fromEnv && !insideAny(fromEnv, own) && acceptableBashPath(fromEnv, { isFile })) return { path: win32.normalize(fromEnv), source: 'env' };
|
|
111
|
+
if (settingsValue && !insideAny(settingsValue, own) && acceptableBashPath(settingsValue, { isFile })) return { path: win32.normalize(settingsValue), source: 'settings' };
|
|
112
|
+
for (const fixed of CLAUDE_FIXED_BASH) if (isFile(fixed)) return { path: fixed, source: 'system' };
|
|
113
|
+
const git = firstGitOnPath(pathValue, { isFile, own });
|
|
114
|
+
if (git) {
|
|
115
|
+
const bash = win32.normalize(win32.join(win32.dirname(git), '..', 'bin', 'bash.exe'));
|
|
116
|
+
if (isFile(bash) && !insideAny(bash, own)) return { path: bash, source: 'system' };
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** The cmd folder (with its git.exe) of the Git for Windows a bin\bash.exe belongs to, or null. */
|
|
122
|
+
export function gitOfBash(bashPath, { isFile = defaultIsFile } = {}) {
|
|
123
|
+
if (!bashPath || win32.basename(win32.dirname(bashPath)).toLowerCase() !== 'bin') return null;
|
|
124
|
+
const root = win32.dirname(win32.dirname(bashPath));
|
|
125
|
+
const git = win32.join(root, 'cmd', 'git.exe');
|
|
126
|
+
return isFile(git) ? { git, cmdDir: win32.dirname(git) } : null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Which Git Bash a Claude Code started by SynaBun ends up with, and what SynaBun has to give it.
|
|
131
|
+
*
|
|
132
|
+
* @param {object} o
|
|
133
|
+
* @param {string} [o.platform]
|
|
134
|
+
* @param {object} [o.env] SynaBun's environment (CLAUDE_CODE_GIT_BASH_PATH, the folders above)
|
|
135
|
+
* @param {string|null} [o.settingsValue] env.CLAUDE_CODE_GIT_BASH_PATH of the user's ~/.claude/settings.json
|
|
136
|
+
* @param {string} [o.pathValue] the PATH a git is looked for on (this process's, then the OS PATH)
|
|
137
|
+
* @param {Array<{ source: 'bundled' | 'downloaded', root: string, ok: boolean, bash: string, git: string }>} [o.copies]
|
|
138
|
+
* SynaBun's own copies, already checked (manager.js), in this order
|
|
139
|
+
* @param {string[]} [o.ownRoots] SynaBun's own Git folders: nothing inside them is the user's
|
|
140
|
+
* @returns {{ supported: boolean, path: string|null, source: string|null, passToClaude: boolean, git: string|null, cmdDir: string|null, claudeFindsItself: boolean }}
|
|
141
|
+
*/
|
|
142
|
+
export function resolveGitBash({ platform = process.platform, env = process.env, settingsValue = null, pathValue = '', copies = [], ownRoots = [], isFile = defaultIsFile } = {}) {
|
|
143
|
+
const none = { supported: platform === 'win32', path: null, source: null, passToClaude: false, git: null, cmdDir: null, claudeFindsItself: false };
|
|
144
|
+
if (platform !== 'win32') return none;
|
|
145
|
+
const own = ownRoots.filter(Boolean);
|
|
146
|
+
|
|
147
|
+
// 1. What Claude Code finds by itself: nothing is passed, nothing downloaded.
|
|
148
|
+
const found = claudeCodeFinds({ env, settingsValue, pathValue, isFile, own });
|
|
149
|
+
if (found) {
|
|
150
|
+
const git = found.source === 'system' ? gitOfBash(found.path, { isFile }) : null;
|
|
151
|
+
return { ...none, path: found.path, source: found.source, git: git?.git || null, cmdDir: git?.cmdDir || null, claudeFindsItself: true };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 2. A Git Bash of the PC that only SynaBun finds: named to Claude Code.
|
|
155
|
+
const candidates = [];
|
|
156
|
+
const onPath = firstGitOnPath(pathValue, { isFile, own });
|
|
157
|
+
const derived = bashOfGit(onPath, { isFile });
|
|
158
|
+
if (derived) candidates.push(derived);
|
|
159
|
+
for (const root of standardGitRoots(env)) candidates.push(win32.join(root, 'bin', 'bash.exe'));
|
|
160
|
+
for (const candidate of candidates) {
|
|
161
|
+
if (insideAny(candidate, own) || !isFile(candidate)) continue;
|
|
162
|
+
const git = gitOfBash(candidate, { isFile });
|
|
163
|
+
return { ...none, path: candidate, source: 'system', passToClaude: true, git: git?.git || null, cmdDir: git?.cmdDir || null };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 3. SynaBun's own copy: the one inside the app, then the one in the data home.
|
|
167
|
+
for (const copy of copies) {
|
|
168
|
+
if (!copy?.ok) continue;
|
|
169
|
+
return { ...none, path: copy.bash, source: copy.source, passToClaude: true, git: copy.git, cmdDir: win32.dirname(copy.git) };
|
|
170
|
+
}
|
|
171
|
+
return none;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** `env` with PATH (whatever its spelling: Windows keeps one, under the first name) ending in `folder`, once. */
|
|
175
|
+
function appendToPath(env, folder) {
|
|
176
|
+
const keys = Object.keys(env).filter((name) => name.toUpperCase() === 'PATH');
|
|
177
|
+
const name = keys[0] || 'Path';
|
|
178
|
+
const parts = String(env[name] || '').split(';').filter(Boolean);
|
|
179
|
+
const out = { ...env };
|
|
180
|
+
for (const each of keys) delete out[each];
|
|
181
|
+
out[name] = [...parts.filter((part) => key(part) !== key(folder)), folder].join(';');
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The environment of a Claude Code process SynaBun starts: `env` itself, unless SynaBun has to name its Git Bash
|
|
187
|
+
* (its own copy, or one only it finds): then CLAUDE_CODE_GIT_BASH_PATH, and that Git's cmd folder at the end of
|
|
188
|
+
* PATH (Claude Code's own git commands find git there). The system's PATH and registry are never changed.
|
|
189
|
+
*/
|
|
190
|
+
export function gitBashChildEnv(env, resolution, { platform = process.platform } = {}) {
|
|
191
|
+
if (platform !== 'win32' || !resolution?.passToClaude || !resolution.path) return env;
|
|
192
|
+
const out = { ...env, [GIT_BASH_ENV]: resolution.path };
|
|
193
|
+
return resolution.cmdDir ? appendToPath(out, resolution.cmdDir) : out;
|
|
194
|
+
}
|
|
@@ -56,9 +56,15 @@
|
|
|
56
56
|
//
|
|
57
57
|
// Writes are not run through here: a commit by the owner runs the
|
|
58
58
|
// repository's hooks, and that is what a commit does.
|
|
59
|
+
//
|
|
60
|
+
// On a Windows PC without git, SynaBun's own copy of Git for Windows
|
|
61
|
+
// (lib/git-bash/) is the git of every read: its folder is put at the end of
|
|
62
|
+
// the read's PATH (setGitFallbackFolder, withGitFallback, which the commit
|
|
63
|
+
// routes use too). Nothing changes where the computer has a git of its own.
|
|
59
64
|
|
|
60
65
|
import { execFile, spawnSync } from 'node:child_process';
|
|
61
66
|
import { devNull } from 'node:os';
|
|
67
|
+
import { delimiter } from 'node:path';
|
|
62
68
|
|
|
63
69
|
/** What the environment of a read adds. */
|
|
64
70
|
export const GIT_READ_ENV = Object.freeze({
|
|
@@ -78,9 +84,35 @@ const PROBE_TIMEOUT_MS = 3000;
|
|
|
78
84
|
export const MONITOR_MEMO_MS = 10_000;
|
|
79
85
|
const MONITOR_MEMO_MAX = 200;
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
let fallbackFolder = () => null;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Where SynaBun's own git is on a computer that has none (Windows: the cmd folder of SynaBun's copy of Git for
|
|
91
|
+
* Windows, lib/git-bash/manager.js), as a function asked at every start; null while git is the computer's own.
|
|
92
|
+
* The folder goes at the end of PATH, so a git of the computer's, installed meanwhile, still comes first.
|
|
93
|
+
*/
|
|
94
|
+
export function setGitFallbackFolder(folder) {
|
|
95
|
+
fallbackFolder = typeof folder === 'function' ? folder : () => null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** `env` with the fallback folder at the end of its PATH (whatever its spelling), or `env` itself without one. */
|
|
99
|
+
export function withGitFallback(env = process.env) {
|
|
100
|
+
let folder = null;
|
|
101
|
+
try { folder = fallbackFolder(); } catch { folder = null; }
|
|
102
|
+
if (!folder) return env;
|
|
103
|
+
const keys = Object.keys(env).filter((name) => name.toUpperCase() === 'PATH');
|
|
104
|
+
const name = keys[0] || (process.platform === 'win32' ? 'Path' : 'PATH');
|
|
105
|
+
const parts = String(env[name] || '').split(delimiter).filter(Boolean);
|
|
106
|
+
if (parts.some((part) => part.toLowerCase() === folder.toLowerCase())) return env;
|
|
107
|
+
const out = { ...env };
|
|
108
|
+
for (const each of keys) delete out[each];
|
|
109
|
+
out[name] = [...parts, folder].join(delimiter);
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** The environment a read is run in: `env` and what a read adds to it (and SynaBun's git, where the computer has none). */
|
|
82
114
|
export function gitReadEnv(env = process.env) {
|
|
83
|
-
return { ...env, ...GIT_READ_ENV };
|
|
115
|
+
return withGitFallback({ ...env, ...GIT_READ_ENV });
|
|
84
116
|
}
|
|
85
117
|
|
|
86
118
|
/** Does this command compare the index with the working tree (and so ask the file system monitor)? */
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// What this install has, for the Details areas of the setup wizard (GET /api/setup/install-details): the Node.js
|
|
2
|
+
// SynaBun runs on, the npm and npx it runs (each asked for its version, the command and its answer shown as they
|
|
3
|
+
// were), where `npm i -g` puts packages, the npm a terminal finds first, every part's dependencies with the
|
|
4
|
+
// versions installed, the MCP server's build, and what a packaged application brought with it (the embedding
|
|
5
|
+
// model, cloudflared, Git for Windows, the window's Electron) and whether the automation browser is there yet.
|
|
6
|
+
//
|
|
7
|
+
// Read only: nothing is installed, written or downloaded. Every command has a short time limit and a fixed
|
|
8
|
+
// argument list; nothing a request says reaches one. A command that fails is reported with what it wrote, with
|
|
9
|
+
// secrets taken out first (lib/log-redact.js: npm prints an invalid setting with its value, an error can name a
|
|
10
|
+
// URL with its password) and then cut to OUTPUT_MAX. The whole answer goes through the same redaction before it
|
|
11
|
+
// leaves (redactDeep), and nothing of it is kept.
|
|
12
|
+
|
|
13
|
+
import { execFile as nodeExecFile } from 'node:child_process';
|
|
14
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
import { redactDeep, redactSecrets } from '../../lib/log-redact.js';
|
|
17
|
+
|
|
18
|
+
const COMMAND_TIMEOUT_MS = 8000;
|
|
19
|
+
const OUTPUT_MAX = 2000;
|
|
20
|
+
|
|
21
|
+
const readJsonFile = (file) => { try { return JSON.parse(readFileSync(file, 'utf8')); } catch { return null; } };
|
|
22
|
+
|
|
23
|
+
/** How many packages an npm install record (node_modules/.package-lock.json, or a package-lock.json) holds. */
|
|
24
|
+
export function packagesInLock(lock) {
|
|
25
|
+
const entries = lock && typeof lock.packages === 'object' ? Object.keys(lock.packages) : [];
|
|
26
|
+
return entries.filter(key => /(?:^|\/)node_modules\//.test(key)).length;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** How many packages of a lockfile are on disk under `root` (npm-shrinkwrap.json of an npm install). */
|
|
30
|
+
export function installedFromLock(lock, root, { exists = existsSync } = {}) {
|
|
31
|
+
const entries = lock && typeof lock.packages === 'object' ? Object.keys(lock.packages) : [];
|
|
32
|
+
return entries.filter(key => /(?:^|\/)node_modules\//.test(key) && exists(path.join(root, ...key.split('/')))).length;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A part's own dependencies (its package.json), each with the version Node finds for it, or null when it is not
|
|
37
|
+
* installed. Sorted by name. Found in the part's node_modules, and with `stopAt` (the package root) in each folder
|
|
38
|
+
* up to it too: `npm i -g synabun` installs every part's dependencies at the package root.
|
|
39
|
+
*/
|
|
40
|
+
export function directDependencies(dir, { readJson = readJsonFile, stopAt = null } = {}) {
|
|
41
|
+
const manifest = readJson(path.join(dir, 'package.json')) || {};
|
|
42
|
+
const wanted = { ...(manifest.optionalDependencies || {}), ...(manifest.dependencies || {}) };
|
|
43
|
+
const limit = stopAt ? path.resolve(stopAt) : null;
|
|
44
|
+
const find = (name) => {
|
|
45
|
+
for (let folder = path.resolve(dir); ; folder = path.dirname(folder)) {
|
|
46
|
+
const found = readJson(path.join(folder, 'node_modules', ...name.split('/'), 'package.json'));
|
|
47
|
+
if (found || !limit || folder === limit || path.dirname(folder) === folder) return found;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return Object.keys(wanted).sort().map((name) => {
|
|
51
|
+
const installed = find(name);
|
|
52
|
+
return { name, wanted: String(wanted[name]), installed: installed?.version ? String(installed.version) : null };
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** The first file named `name` (on Windows `name.cmd`, `.exe` or the bare name) in the PATH `entries`, skipping `skip` folders. */
|
|
57
|
+
export function firstOnPath(name, entries, { platform = process.platform, exists = existsSync, skip = [] } = {}) {
|
|
58
|
+
const impl = platform === 'win32' ? path.win32 : path.posix;
|
|
59
|
+
const id = (dir) => (platform === 'win32' ? String(dir).toLowerCase().replace(/[\\/]+$/, '') : String(dir).replace(/\/+$/, ''));
|
|
60
|
+
const skipped = new Set(skip.filter(Boolean).map(id));
|
|
61
|
+
const names = platform === 'win32' ? [`${name}.cmd`, `${name}.exe`, name] : [name];
|
|
62
|
+
for (const dir of entries || []) {
|
|
63
|
+
if (!dir || skipped.has(id(dir))) continue;
|
|
64
|
+
for (const candidate of names) {
|
|
65
|
+
const file = impl.join(dir, candidate);
|
|
66
|
+
if (exists(file)) return file;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Run `file --version` (a Windows command file through cmd.exe, the way a terminal starts it): { command, ok, output }. */
|
|
73
|
+
export function runVersion(file, { platform = process.platform, env = process.env, execFile = nodeExecFile, timeoutMs = COMMAND_TIMEOUT_MS } = {}) {
|
|
74
|
+
const command = `${/\s/.test(file) ? `"${file}"` : file} --version`;
|
|
75
|
+
return new Promise((done) => {
|
|
76
|
+
const finish = (error, stdout = '', stderr = '') => {
|
|
77
|
+
const text = redactSecrets(String(stdout || '').trim() || String(stderr || '').trim() || (error ? error.message : ''));
|
|
78
|
+
done({ command: redactSecrets(command), ok: !error, output: text.length > OUTPUT_MAX ? `${text.slice(0, OUTPUT_MAX)}…` : text });
|
|
79
|
+
};
|
|
80
|
+
try {
|
|
81
|
+
if (platform === 'win32' && /\.(cmd|bat)$/i.test(file)) {
|
|
82
|
+
execFile(env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', `""${file}" --version"`], { env, timeout: timeoutMs, windowsHide: true, windowsVerbatimArguments: true }, finish);
|
|
83
|
+
} else {
|
|
84
|
+
execFile(file, ['--version'], { env, timeout: timeoutMs, windowsHide: true }, finish);
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
finish(error);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Everything the Details areas show. `packaged` is lib/packaged-runtime.js readPackagedRuntime() (null for an
|
|
94
|
+
* npm or Git install) and `manifest` the packaged build's synabun-package.json; `osPath` the PATH a new terminal
|
|
95
|
+
* gets (lib/os-path.js); `npmPrefix` where the npm SynaBun runs puts global packages (the one absolute prefix PATH
|
|
96
|
+
* is built from: lib/child-path.js), `npmPrefixSource` why ('user' or 'synabun') and `npmPrefixFrom` what set it.
|
|
97
|
+
*/
|
|
98
|
+
export async function collectInstallDetails({
|
|
99
|
+
packageRoot,
|
|
100
|
+
packaged = null,
|
|
101
|
+
manifest = null,
|
|
102
|
+
platform = process.platform,
|
|
103
|
+
env = process.env,
|
|
104
|
+
execPath = process.execPath,
|
|
105
|
+
nodeVersion = process.version,
|
|
106
|
+
osPath = [],
|
|
107
|
+
npmPrefix = null,
|
|
108
|
+
npmPrefixSource = null,
|
|
109
|
+
npmPrefixFrom = null,
|
|
110
|
+
npmGlobalBin = null,
|
|
111
|
+
browserExecutable = null,
|
|
112
|
+
exists = existsSync,
|
|
113
|
+
readJson = readJsonFile,
|
|
114
|
+
version = runVersion,
|
|
115
|
+
} = {}) {
|
|
116
|
+
const windows = platform === 'win32';
|
|
117
|
+
const impl = windows ? path.win32 : path.posix;
|
|
118
|
+
const runtimeBin = packaged?.runtimeBin || null;
|
|
119
|
+
const ownNpm = runtimeBin ? impl.join(runtimeBin, windows ? 'npm.cmd' : 'npm') : firstOnPath('npm', String(env.PATH || env.Path || '').split(windows ? ';' : ':'), { platform, exists });
|
|
120
|
+
const ownNpx = runtimeBin ? impl.join(runtimeBin, windows ? 'npx.cmd' : 'npx') : firstOnPath('npx', String(env.PATH || env.Path || '').split(windows ? ';' : ':'), { platform, exists });
|
|
121
|
+
const [npm, npx] = await Promise.all([
|
|
122
|
+
ownNpm ? version(ownNpm, { platform, env }) : Promise.resolve(null),
|
|
123
|
+
ownNpx ? version(ownNpx, { platform, env }) : Promise.resolve(null),
|
|
124
|
+
]);
|
|
125
|
+
// The npm a terminal finds first: the user's own, when there is one outside SynaBun.
|
|
126
|
+
const userNpmPath = firstOnPath('npm', osPath, { platform, exists, skip: runtimeBin ? [runtimeBin, impl.dirname(execPath)] : [] });
|
|
127
|
+
const userNpm = userNpmPath && userNpmPath !== ownNpm ? { path: userNpmPath, ...(await version(userNpmPath, { platform, env })) } : null;
|
|
128
|
+
|
|
129
|
+
// A part's own install record when it has one (a development checkout, a desktop build); an npm install keeps
|
|
130
|
+
// both parts' dependencies at the package root instead, pinned by npm-shrinkwrap.json.
|
|
131
|
+
const shrinkwrap = readJson(path.join(packageRoot, 'npm-shrinkwrap.json'));
|
|
132
|
+
const parts = [['Neural Interface', 'neural-interface'], ['MCP server', 'mcp-server']].map(([name, folder]) => {
|
|
133
|
+
const dir = path.join(packageRoot, folder);
|
|
134
|
+
const installed = readJson(path.join(dir, 'node_modules', '.package-lock.json'));
|
|
135
|
+
const packages = installed ? packagesInLock(installed) : installedFromLock(shrinkwrap, packageRoot, { exists });
|
|
136
|
+
return { name, folder, packages, dependencies: directDependencies(dir, { readJson, stopAt: packageRoot }) };
|
|
137
|
+
});
|
|
138
|
+
const mcpBuilt = exists(path.join(packageRoot, 'mcp-server', 'dist', 'index.js'));
|
|
139
|
+
|
|
140
|
+
return redactDeep({
|
|
141
|
+
kind: packaged ? 'app' : 'source',
|
|
142
|
+
platform,
|
|
143
|
+
app: packaged ? {
|
|
144
|
+
version: packaged.version || null,
|
|
145
|
+
target: packaged.target || null,
|
|
146
|
+
electron: manifest?.shell?.electron || null,
|
|
147
|
+
builtAt: manifest?.builtAt || null,
|
|
148
|
+
} : null,
|
|
149
|
+
node: { version: nodeVersion, path: execPath, bundled: !!runtimeBin && execPath.startsWith(packaged.resources) },
|
|
150
|
+
npm: npm ? { path: ownNpm, bundled: !!runtimeBin, ...npm } : null,
|
|
151
|
+
npx: npx ? { path: ownNpx, bundled: !!runtimeBin, ...npx } : null,
|
|
152
|
+
globalPrefix: npmPrefix ? { path: npmPrefix, bin: npmGlobalBin || null, source: npmPrefixSource || null, from: npmPrefixFrom || null } : null,
|
|
153
|
+
userNpm,
|
|
154
|
+
parts,
|
|
155
|
+
mcp: { built: mcpBuilt, file: 'mcp-server/dist/index.js' },
|
|
156
|
+
bundled: packaged ? {
|
|
157
|
+
embeddingModel: manifest?.embeddingModel === 'bundled' ? 'Xenova/all-MiniLM-L6-v2' : null,
|
|
158
|
+
cloudflared: manifest?.cloudflared?.version || null,
|
|
159
|
+
gitBash: manifest?.gitBash?.version || null,
|
|
160
|
+
} : null,
|
|
161
|
+
browser: browserExecutable ? { path: browserExecutable, installed: exists(browserExecutable) } : null,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn, spawnSync } from 'child_process';
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, chmodSync } from 'fs';
|
|
3
3
|
import { join, resolve, isAbsolute } from 'path';
|
|
4
|
+
import { withPackagedPathLast } from './augmented-path.js';
|
|
4
5
|
|
|
5
6
|
const GITHUB_URL_RE = /^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+?)(?:\.git)?\/?$/i;
|
|
6
7
|
|
|
@@ -87,11 +88,22 @@ export function maskEnv(env) {
|
|
|
87
88
|
return out;
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* The environment of a git / package-manager run: this process's, with a
|
|
93
|
+
* packaged application's runtime and npm's global bin after the user's own
|
|
94
|
+
* PATH (augmented-path.js withPackagedPathLast): a repository is installed
|
|
95
|
+
* with the user's npm, pnpm, yarn, uv or pip when they have one, SynaBun's
|
|
96
|
+
* bundled npm only when they have none. Unchanged for an npm or Git install.
|
|
97
|
+
*/
|
|
98
|
+
export function installEnv(extra = {}, base = process.env) {
|
|
99
|
+
return withPackagedPathLast({ ...base, ...extra });
|
|
100
|
+
}
|
|
101
|
+
|
|
90
102
|
async function runCommand(cmd, args, opts = {}) {
|
|
91
103
|
return new Promise((resolvePromise) => {
|
|
92
104
|
const child = spawn(cmd, args, {
|
|
93
105
|
cwd: opts.cwd,
|
|
94
|
-
env:
|
|
106
|
+
env: installEnv(opts.env || {}),
|
|
95
107
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
96
108
|
shell: false,
|
|
97
109
|
});
|
|
@@ -466,7 +478,7 @@ export async function installDependencies({ dataHome, name, repoPath, onLine })
|
|
|
466
478
|
|
|
467
479
|
if (hasPyproject || hasRequirements) {
|
|
468
480
|
if (hasUvLock || hasPyproject) {
|
|
469
|
-
const uvExists = spawnSync('which', ['uv']).status === 0;
|
|
481
|
+
const uvExists = spawnSync('which', ['uv'], { env: installEnv() }).status === 0;
|
|
470
482
|
if (uvExists) {
|
|
471
483
|
logInstall(dataHome, name, 'running uv sync');
|
|
472
484
|
const res = await runCommand('uv', ['sync'], { cwd: repoPath, onLine: (line) => { logInstall(dataHome, name, line); onLine?.(line); } });
|
|
@@ -10,6 +10,7 @@ import { codexReasoningEffort } from './effort-levels.js';
|
|
|
10
10
|
import { codexStreamMedia, collectCodexMedia, openCodeMediaPart, ownCodexImages } from './assistant-media.js';
|
|
11
11
|
import { browserToolDenial } from './browser-tool-policy.js';
|
|
12
12
|
import { CODEX_BROWSER_POLICY_UNTRUSTED_NOTE, codexBrowserPolicyHook } from './assistant-route-gate-codex.js';
|
|
13
|
+
import { codexWindowsSandbox, codexWindowsSandboxConfig } from './agent-sandbox-elevation.js';
|
|
13
14
|
|
|
14
15
|
function stringEnv(source) {
|
|
15
16
|
const out = {};
|
|
@@ -248,6 +249,12 @@ export async function createCodexNativeLoopAdapter(options = {}) {
|
|
|
248
249
|
collectMedia = null,
|
|
249
250
|
// Assistant task runs: the browser policy's hook and the run's notes (a function: never in the state file).
|
|
250
251
|
runMode = 'loop', onNote = null, browserPolicyTrust = null,
|
|
252
|
+
// Inherited variables to remove before extraEnv applies (the Codex account's launch:
|
|
253
|
+
// lib/codex-accounts.js launchFor() — inherited OpenAI/Codex credentials never reach the run).
|
|
254
|
+
unsetEnv = [],
|
|
255
|
+
// The Admin sandbox setting when the run started (lib/agent-sandbox-elevation.js): the Windows
|
|
256
|
+
// sandbox every `codex exec` of the thread may use. The run keeps it while it lives.
|
|
257
|
+
adminSandbox = false,
|
|
251
258
|
} = options;
|
|
252
259
|
const permissionPolicy = normalizePermissionPolicy(rawPolicy);
|
|
253
260
|
const capability = normalizeCapability(rawCapability);
|
|
@@ -281,8 +288,10 @@ export async function createCodexNativeLoopAdapter(options = {}) {
|
|
|
281
288
|
// Computer-use workers: the grant unlocks the `computer` group in the MCP child.
|
|
282
289
|
SYNABUN_DESKTOP_GRANT: typeof desktopGrantProvider === 'function' ? desktopGrantProvider() || undefined : undefined,
|
|
283
290
|
});
|
|
284
|
-
const
|
|
285
|
-
const
|
|
291
|
+
const inherited = { ...process.env };
|
|
292
|
+
for (const key of Array.isArray(unsetEnv) ? unsetEnv : []) delete inherited[key];
|
|
293
|
+
const env = stringEnv({ ...inherited, ...pins, CODEX_HOME: codexHome, ...(browserPolicy ? { SYNABUN_BROWSER_POLICY_CWD: cwd || process.cwd() } : {}), ...stringEnv(extraEnv) });
|
|
294
|
+
const config = { ...codexWindowsSandboxConfig(adminSandbox) };
|
|
286
295
|
if (Object.keys(pins).length) config.mcp_servers = { SynaBun: { env: pins } };
|
|
287
296
|
if (extended) config.model_context_window = Math.floor(Number(modelContextWindow));
|
|
288
297
|
if (browserPolicy) Object.assign(config, browserPolicy.config);
|
|
@@ -329,6 +338,7 @@ export async function createCodexNativeLoopAdapter(options = {}) {
|
|
|
329
338
|
isAlive: () => alive,
|
|
330
339
|
describe: () => ({
|
|
331
340
|
provider: 'codex', permissionPolicy, capability, sandboxMode: codexSandboxModeFor({ permissionPolicy, capability }),
|
|
341
|
+
windowsSandbox: codexWindowsSandbox(adminSandbox),
|
|
332
342
|
...(task ? { browserPolicy: browserPolicy ? 'hook' : 'instructions' } : {}),
|
|
333
343
|
}),
|
|
334
344
|
async runTurn(prompt, meta = {}) {
|
|
@@ -423,6 +433,11 @@ export async function createClaudeNativeLoopAdapter(options = {}) {
|
|
|
423
433
|
extraEnv = {}, permissionPolicy: rawPolicy = 'auto', permissionBroker = null,
|
|
424
434
|
capability: rawCapability = 'full', maxBudgetUsd = null, outputSchema = null, runMode = 'loop',
|
|
425
435
|
desktopGrantProvider = null,
|
|
436
|
+
// Inherited variables to remove before extraEnv applies (the Claude account's launch:
|
|
437
|
+
// credentials the server was started with never reach a worker).
|
|
438
|
+
unsetEnv = [],
|
|
439
|
+
// The host's last word on the environment: on Windows the Git Bash it names (lib/git-bash/).
|
|
440
|
+
childEnv = null,
|
|
426
441
|
} = options;
|
|
427
442
|
const permissionPolicy = normalizePermissionPolicy(rawPolicy);
|
|
428
443
|
const capability = normalizeCapability(rawCapability);
|
|
@@ -432,8 +447,10 @@ export async function createClaudeNativeLoopAdapter(options = {}) {
|
|
|
432
447
|
let alive = true;
|
|
433
448
|
let sessionId = null;
|
|
434
449
|
let activeTurn = null;
|
|
435
|
-
const
|
|
436
|
-
|
|
450
|
+
const inherited = cleanClaudeEnvironment();
|
|
451
|
+
for (const key of Array.isArray(unsetEnv) ? unsetEnv : []) delete inherited[key];
|
|
452
|
+
const ownEnv = stringEnv({
|
|
453
|
+
...inherited,
|
|
437
454
|
SYNABUN_TERMINAL_SESSION: runId,
|
|
438
455
|
SYNABUN_PROJECT: cwd ? memoryProject(cwd) : 'global',
|
|
439
456
|
SYNABUN_PROFILE: 'full',
|
|
@@ -442,6 +459,7 @@ export async function createClaudeNativeLoopAdapter(options = {}) {
|
|
|
442
459
|
SYNABUN_RUN_MODE: runMode === 'task' ? 'task' : undefined,
|
|
443
460
|
...stringEnv(extraEnv),
|
|
444
461
|
});
|
|
462
|
+
const env = typeof childEnv === 'function' ? stringEnv(childEnv(ownEnv)) : ownEnv;
|
|
445
463
|
const brokerRequest = async (request) => {
|
|
446
464
|
try {
|
|
447
465
|
const reply = await permissionBroker.request({
|
|
@@ -373,9 +373,14 @@ export class NativeLoopRuntime {
|
|
|
373
373
|
record.startupCancelPromise = new Promise((resolveCancel) => { record._cancelStartup = resolveCancel; });
|
|
374
374
|
this.records.set(runId, record);
|
|
375
375
|
this._emit('sidepanel:run-created', record);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
// A task run's (assistant dispatch) maxMinutes is work time, which its dispatcher counts and
|
|
377
|
+
// enforces (assistant-dispatch.js, the work clock): idle time between its turns does not count,
|
|
378
|
+
// so it gets no wall-clock cap here. A loop's maxMinutes stays the wall clock.
|
|
379
|
+
if (record.runMode !== 'task') {
|
|
380
|
+
const maxMs = Math.max(1, Number(nativeState.maxMinutes) || 30) * 60_000;
|
|
381
|
+
record.timer = setTimeout(() => { this.stop(runId, 'time_cap').catch(() => {}); }, maxMs);
|
|
382
|
+
record.timer.unref?.();
|
|
383
|
+
}
|
|
379
384
|
|
|
380
385
|
const startupSignal = record.startupAbortController.signal;
|
|
381
386
|
const factoryPromise = Promise.resolve().then(() => factory({
|
|
@@ -510,7 +515,7 @@ export class NativeLoopRuntime {
|
|
|
510
515
|
return;
|
|
511
516
|
}
|
|
512
517
|
const elapsed = this.now() - new Date(state.startedAt || record.startedAt).getTime();
|
|
513
|
-
if (elapsed >= Math.max(1, Number(state.maxMinutes) || 30) * 60_000) {
|
|
518
|
+
if (record.runMode !== 'task' && elapsed >= Math.max(1, Number(state.maxMinutes) || 30) * 60_000) {
|
|
514
519
|
await this.stop(record.runId, 'time_cap');
|
|
515
520
|
return;
|
|
516
521
|
}
|