synabun 2.0.7 → 2.0.10
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 +67 -0
- package/README.md +1 -1
- package/THIRD-PARTY-LICENSES.md +46 -4
- package/hooks/claude-code/post-plan.mjs +6 -30
- package/hooks/claude-code/session-start.mjs +1 -4
- package/hooks/claude-code/shared.mjs +106 -72
- package/launcher.mjs +9 -3
- package/lib/package-processes.js +670 -0
- package/lib/runtime-dependencies.js +225 -0
- package/lib/start-launcher.js +6 -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/categories.d.ts +35 -2
- package/mcp-server/dist/services/categories.d.ts.map +1 -1
- package/mcp-server/dist/services/categories.js +77 -33
- package/mcp-server/dist/services/categories.js.map +1 -1
- package/mcp-server/dist/services/desktop-bench.d.ts +7 -7
- package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -1
- package/mcp-server/dist/services/desktop-bench.js +1 -1
- package/mcp-server/dist/services/desktop-bench.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +1 -1
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +1 -1
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/bluesky.js +1 -1
- package/mcp-server/dist/tools/bluesky.js.map +1 -1
- package/mcp-server/dist/tools/browser-advanced.d.ts +1 -1
- package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-advanced.js +1 -1
- package/mcp-server/dist/tools/browser-advanced.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-batch.js +1 -1
- package/mcp-server/dist/tools/browser-batch.js.map +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.js +1 -1
- package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -1
- package/mcp-server/dist/tools/browser-interact.d.ts +1 -1
- package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-interact.js +1 -1
- package/mcp-server/dist/tools/browser-interact.js.map +1 -1
- package/mcp-server/dist/tools/browser-navigate.d.ts +1 -1
- package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-navigate.js +1 -1
- package/mcp-server/dist/tools/browser-navigate.js.map +1 -1
- package/mcp-server/dist/tools/browser-observe.d.ts +1 -1
- package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -1
- package/mcp-server/dist/tools/browser-observe.js +1 -1
- package/mcp-server/dist/tools/browser-observe.js.map +1 -1
- package/mcp-server/dist/tools/card-tools.d.ts +1 -1
- package/mcp-server/dist/tools/card-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/card-tools.js +1 -1
- package/mcp-server/dist/tools/card-tools.js.map +1 -1
- package/mcp-server/dist/tools/category.d.ts +1 -1
- package/mcp-server/dist/tools/category.d.ts.map +1 -1
- package/mcp-server/dist/tools/category.js +5 -1
- package/mcp-server/dist/tools/category.js.map +1 -1
- package/mcp-server/dist/tools/choice.d.ts +1 -1
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +1 -1
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/computer.d.ts +1 -1
- package/mcp-server/dist/tools/computer.d.ts.map +1 -1
- package/mcp-server/dist/tools/computer.js +1 -1
- package/mcp-server/dist/tools/computer.js.map +1 -1
- package/mcp-server/dist/tools/discord-channel.d.ts +1 -1
- package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-channel.js +1 -1
- package/mcp-server/dist/tools/discord-channel.js.map +1 -1
- package/mcp-server/dist/tools/discord-guild.d.ts +1 -1
- package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-guild.js +1 -1
- package/mcp-server/dist/tools/discord-guild.js.map +1 -1
- package/mcp-server/dist/tools/discord-member.d.ts +1 -1
- package/mcp-server/dist/tools/discord-member.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-member.js +1 -1
- package/mcp-server/dist/tools/discord-member.js.map +1 -1
- package/mcp-server/dist/tools/discord-message.d.ts +1 -1
- package/mcp-server/dist/tools/discord-message.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-message.js +1 -1
- package/mcp-server/dist/tools/discord-message.js.map +1 -1
- package/mcp-server/dist/tools/discord-onboarding.d.ts +1 -1
- package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-onboarding.js +1 -1
- package/mcp-server/dist/tools/discord-onboarding.js.map +1 -1
- package/mcp-server/dist/tools/discord-role.d.ts +1 -1
- package/mcp-server/dist/tools/discord-role.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-role.js +1 -1
- package/mcp-server/dist/tools/discord-role.js.map +1 -1
- package/mcp-server/dist/tools/discord-thread.d.ts +1 -1
- package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-thread.js +1 -1
- package/mcp-server/dist/tools/discord-thread.js.map +1 -1
- package/mcp-server/dist/tools/discord-webhook.d.ts +1 -1
- package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -1
- package/mcp-server/dist/tools/discord-webhook.js +1 -1
- package/mcp-server/dist/tools/discord-webhook.js.map +1 -1
- package/mcp-server/dist/tools/fb-groups.d.ts +1 -1
- package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -1
- package/mcp-server/dist/tools/fb-groups.js +1 -1
- package/mcp-server/dist/tools/fb-groups.js.map +1 -1
- package/mcp-server/dist/tools/forget.d.ts +1 -1
- package/mcp-server/dist/tools/forget.d.ts.map +1 -1
- package/mcp-server/dist/tools/forget.js +1 -1
- package/mcp-server/dist/tools/forget.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.d.ts +1 -1
- package/mcp-server/dist/tools/git-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +1 -1
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/gsc/experience.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/experience.js +1 -1
- package/mcp-server/dist/tools/gsc/experience.js.map +1 -1
- package/mcp-server/dist/tools/gsc/indexing.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/indexing.js +1 -1
- package/mcp-server/dist/tools/gsc/indexing.js.map +1 -1
- package/mcp-server/dist/tools/gsc/inspect.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/inspect.js +1 -1
- package/mcp-server/dist/tools/gsc/inspect.js.map +1 -1
- package/mcp-server/dist/tools/gsc/navigate.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/navigate.js +1 -1
- package/mcp-server/dist/tools/gsc/navigate.js.map +1 -1
- package/mcp-server/dist/tools/gsc/performance.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/performance.js +1 -1
- package/mcp-server/dist/tools/gsc/performance.js.map +1 -1
- package/mcp-server/dist/tools/gsc/settings.d.ts +1 -1
- package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -1
- package/mcp-server/dist/tools/gsc/settings.js +1 -1
- package/mcp-server/dist/tools/gsc/settings.js.map +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/image-tools.js.map +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +1 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -1
- package/mcp-server/dist/tools/loop.d.ts +1 -1
- package/mcp-server/dist/tools/loop.d.ts.map +1 -1
- package/mcp-server/dist/tools/loop.js +1 -1
- package/mcp-server/dist/tools/loop.js.map +1 -1
- package/mcp-server/dist/tools/memories.d.ts +1 -1
- package/mcp-server/dist/tools/memories.d.ts.map +1 -1
- package/mcp-server/dist/tools/memories.js +1 -1
- package/mcp-server/dist/tools/memories.js.map +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +1 -1
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/profile.d.ts +1 -1
- package/mcp-server/dist/tools/profile.d.ts.map +1 -1
- package/mcp-server/dist/tools/profile.js +1 -1
- package/mcp-server/dist/tools/profile.js.map +1 -1
- package/mcp-server/dist/tools/recall.d.ts +1 -1
- package/mcp-server/dist/tools/recall.d.ts.map +1 -1
- package/mcp-server/dist/tools/recall.js +1 -1
- package/mcp-server/dist/tools/recall.js.map +1 -1
- package/mcp-server/dist/tools/reflect.d.ts +1 -1
- package/mcp-server/dist/tools/reflect.d.ts.map +1 -1
- package/mcp-server/dist/tools/reflect.js +1 -1
- package/mcp-server/dist/tools/reflect.js.map +1 -1
- package/mcp-server/dist/tools/remember.d.ts +1 -1
- package/mcp-server/dist/tools/remember.d.ts.map +1 -1
- package/mcp-server/dist/tools/remember.js +13 -11
- package/mcp-server/dist/tools/remember.js.map +1 -1
- package/mcp-server/dist/tools/restore.d.ts +1 -1
- package/mcp-server/dist/tools/restore.d.ts.map +1 -1
- package/mcp-server/dist/tools/restore.js +1 -1
- package/mcp-server/dist/tools/restore.js.map +1 -1
- package/mcp-server/dist/tools/style-guide-tools.d.ts +1 -1
- package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/style-guide-tools.js +1 -1
- package/mcp-server/dist/tools/style-guide-tools.js.map +1 -1
- package/mcp-server/dist/tools/sync.d.ts +1 -1
- package/mcp-server/dist/tools/sync.d.ts.map +1 -1
- package/mcp-server/dist/tools/sync.js +1 -1
- package/mcp-server/dist/tools/sync.js.map +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.d.ts +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.js +1 -1
- package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -1
- package/mcp-server/dist/tools/utils.d.ts +1 -1
- package/mcp-server/dist/tools/utils.d.ts.map +1 -1
- package/mcp-server/dist/tools/utils.js +1 -1
- package/mcp-server/dist/tools/utils.js.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.js +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +3 -3
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/dist/tools/youtube/analytics.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/analytics.js +1 -1
- package/mcp-server/dist/tools/youtube/analytics.js.map +1 -1
- package/mcp-server/dist/tools/youtube/download.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/download.js +1 -1
- package/mcp-server/dist/tools/youtube/download.js.map +1 -1
- package/mcp-server/dist/tools/youtube/media.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/media.js +1 -1
- package/mcp-server/dist/tools/youtube/media.js.map +1 -1
- package/mcp-server/dist/tools/youtube/metadata.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/metadata.js +1 -1
- package/mcp-server/dist/tools/youtube/metadata.js.map +1 -1
- package/mcp-server/dist/tools/youtube/navigate.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/navigate.js +1 -1
- package/mcp-server/dist/tools/youtube/navigate.js.map +1 -1
- package/mcp-server/dist/tools/youtube/playlist.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/playlist.js +1 -1
- package/mcp-server/dist/tools/youtube/playlist.js.map +1 -1
- package/mcp-server/dist/tools/youtube/schedule.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/schedule.js +1 -1
- package/mcp-server/dist/tools/youtube/schedule.js.map +1 -1
- package/mcp-server/dist/tools/youtube/source.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/source.js +1 -1
- package/mcp-server/dist/tools/youtube/source.js.map +1 -1
- package/mcp-server/dist/tools/youtube/upload.d.ts +1 -1
- package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -1
- package/mcp-server/dist/tools/youtube/upload.js +4 -9
- package/mcp-server/dist/tools/youtube/upload.js.map +1 -1
- package/mcp-server/dist/tui.js +16 -4
- package/mcp-server/dist/tui.js.map +1 -1
- package/mcp-server/package-lock.json +3 -3
- package/mcp-server/package.json +3 -3
- package/mcp-server/src/services/browser-bench.ts +1 -1
- package/mcp-server/src/services/categories.ts +77 -32
- package/mcp-server/src/services/desktop-bench.ts +1 -1
- package/mcp-server/src/tools/agents.ts +1 -1
- package/mcp-server/src/tools/bluesky.ts +1 -1
- package/mcp-server/src/tools/browser-advanced.ts +1 -1
- package/mcp-server/src/tools/browser-batch.ts +1 -1
- package/mcp-server/src/tools/browser-cheatsheet.ts +1 -1
- package/mcp-server/src/tools/browser-interact.ts +1 -1
- package/mcp-server/src/tools/browser-navigate.ts +1 -1
- package/mcp-server/src/tools/browser-observe.ts +1 -1
- package/mcp-server/src/tools/card-tools.ts +1 -1
- package/mcp-server/src/tools/category.ts +6 -1
- package/mcp-server/src/tools/choice.ts +1 -1
- package/mcp-server/src/tools/computer.ts +1 -1
- package/mcp-server/src/tools/discord-channel.ts +1 -1
- package/mcp-server/src/tools/discord-guild.ts +1 -1
- package/mcp-server/src/tools/discord-member.ts +1 -1
- package/mcp-server/src/tools/discord-message.ts +1 -1
- package/mcp-server/src/tools/discord-onboarding.ts +1 -1
- package/mcp-server/src/tools/discord-role.ts +1 -1
- package/mcp-server/src/tools/discord-thread.ts +1 -1
- package/mcp-server/src/tools/discord-webhook.ts +1 -1
- package/mcp-server/src/tools/fb-groups.ts +1 -1
- package/mcp-server/src/tools/forget.ts +1 -1
- package/mcp-server/src/tools/git-tools.ts +1 -1
- package/mcp-server/src/tools/gsc/experience.ts +1 -1
- package/mcp-server/src/tools/gsc/indexing.ts +1 -1
- package/mcp-server/src/tools/gsc/inspect.ts +1 -1
- package/mcp-server/src/tools/gsc/navigate.ts +1 -1
- package/mcp-server/src/tools/gsc/performance.ts +1 -1
- package/mcp-server/src/tools/gsc/settings.ts +1 -1
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/leonardo-browser-tools.ts +1 -1
- package/mcp-server/src/tools/loop.ts +1 -1
- package/mcp-server/src/tools/memories.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +1 -1
- package/mcp-server/src/tools/profile.ts +1 -1
- package/mcp-server/src/tools/recall.ts +1 -1
- package/mcp-server/src/tools/reflect.ts +1 -1
- package/mcp-server/src/tools/remember.ts +13 -12
- package/mcp-server/src/tools/restore.ts +1 -1
- package/mcp-server/src/tools/style-guide-tools.ts +1 -1
- package/mcp-server/src/tools/sync.ts +1 -1
- package/mcp-server/src/tools/tictactoe-tools.ts +1 -1
- package/mcp-server/src/tools/utils.ts +1 -1
- package/mcp-server/src/tools/whatsapp-send-file.ts +1 -1
- package/mcp-server/src/tools/whiteboard-tools.ts +1 -1
- package/mcp-server/src/tools/youtube/analytics.ts +1 -1
- package/mcp-server/src/tools/youtube/download.ts +1 -1
- package/mcp-server/src/tools/youtube/media.ts +1 -1
- package/mcp-server/src/tools/youtube/metadata.ts +1 -1
- package/mcp-server/src/tools/youtube/navigate.ts +1 -1
- package/mcp-server/src/tools/youtube/playlist.ts +1 -1
- package/mcp-server/src/tools/youtube/schedule.ts +1 -1
- package/mcp-server/src/tools/youtube/source.ts +1 -1
- package/mcp-server/src/tools/youtube/upload.ts +4 -12
- package/mcp-server/src/tui.ts +22 -9
- package/neural-interface/i18n/en.json +236 -7
- package/neural-interface/i18n/pt-BR.json +238 -9
- package/neural-interface/lib/account-usage.js +5 -3
- package/neural-interface/lib/agent-sandbox-elevation.js +102 -0
- package/neural-interface/lib/agent-sandbox-setting.js +57 -0
- package/neural-interface/lib/app-controls-api.js +161 -0
- package/neural-interface/lib/assistant-api.js +40 -7
- package/neural-interface/lib/assistant-brains/opencode.js +13 -1
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +44 -0
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +57 -0
- package/neural-interface/lib/assistant-catalog.js +17 -2
- package/neural-interface/lib/assistant-dispatch.js +3 -0
- package/neural-interface/lib/assistant-envelope.js +19 -1
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -1
- package/neural-interface/lib/assistant-runtime.js +131 -8
- package/neural-interface/lib/claude-model-catalog.js +64 -14
- package/neural-interface/lib/codex-account-auth.js +4 -2
- package/neural-interface/lib/codex-accounts.js +14 -1
- package/neural-interface/lib/codex-settings-schema.js +111 -47
- package/neural-interface/lib/editor-completion-opencode.js +132 -35
- package/neural-interface/lib/exec-loop-command.js +11 -2
- package/neural-interface/lib/install-details.js +23 -5
- package/neural-interface/lib/launch-cache.js +293 -0
- package/neural-interface/lib/login-start.js +524 -0
- package/neural-interface/lib/native-loop-providers.js +24 -4
- package/neural-interface/lib/native-loop-runtime.js +19 -0
- package/neural-interface/lib/opencode-db-schema.js +75 -0
- package/neural-interface/lib/opencode-history.js +16 -1
- package/neural-interface/lib/opencode-protocol.js +173 -0
- package/neural-interface/lib/opencode-provider-view.js +81 -0
- package/neural-interface/lib/opencode-runtime-config.js +10 -3
- package/neural-interface/lib/opencode-serve-records.js +606 -0
- package/neural-interface/lib/opencode-v2-client.js +33 -6
- package/neural-interface/lib/opencode-v2-ws-requests.js +19 -5
- package/neural-interface/lib/opencode-worker-activity.js +229 -0
- package/neural-interface/lib/opencode2-client.js +760 -0
- package/neural-interface/lib/opencode2-proxy.js +116 -0
- package/neural-interface/lib/opencode2-translate.js +1008 -0
- package/neural-interface/lib/process-identity.js +361 -0
- package/neural-interface/lib/provider-panel-terminal-auth.js +3 -2
- package/neural-interface/lib/session-cache-builder.js +26 -5
- package/neural-interface/lib/session-indexer.js +3 -1
- package/neural-interface/lib/session-title-generator.js +20 -0
- package/neural-interface/lib/style-guide/api.js +4 -3
- package/neural-interface/lib/untrusted-file-headers.js +27 -0
- package/neural-interface/package-lock.json +1342 -44
- package/neural-interface/package.json +5 -1
- package/neural-interface/public/index.html +2 -2
- package/neural-interface/public/shared/account-menu.js +4 -1
- package/neural-interface/public/shared/account-usage.js +62 -2
- package/neural-interface/public/shared/account-view.js +2 -1
- package/neural-interface/public/shared/agent-runtime-options.js +55 -11
- package/neural-interface/public/shared/assistant/asst-account-menu.js +298 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +172 -17
- package/neural-interface/public/shared/assistant/asst-api.js +18 -3
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +424 -152
- package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
- package/neural-interface/public/shared/assistant/asst-hosts.js +49 -2
- package/neural-interface/public/shared/assistant/asst-menu.js +275 -77
- package/neural-interface/public/shared/assistant/asst-model-chip.js +135 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +236 -35
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +28 -10
- package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
- package/neural-interface/public/shared/assistant/asst-render.js +382 -36
- package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
- package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
- package/neural-interface/public/shared/assistant/asst-scenes.js +528 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
- package/neural-interface/public/shared/assistant/asst-state.js +14 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +109 -17
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +13 -1
- package/neural-interface/public/shared/cc-dropdown.js +480 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
- package/neural-interface/public/shared/cdx/cdx-render.js +15 -3
- package/neural-interface/public/shared/cdx/cdx-styles.js +49 -5
- package/neural-interface/public/shared/cdx/cdx-tabs.js +152 -35
- package/neural-interface/public/shared/cp/cp-markdown.js +4 -57
- package/neural-interface/public/shared/data-cache.js +223 -0
- package/neural-interface/public/shared/desktop-bridge.js +11 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
- package/neural-interface/public/shared/desktop-titlebar.js +214 -28
- package/neural-interface/public/shared/desktop-update-view.js +15 -5
- package/neural-interface/public/shared/file-links.js +73 -8
- package/neural-interface/public/shared/html-shell.js +74 -80
- package/neural-interface/public/shared/launch-prefetch.js +59 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +3 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +11 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +54 -17
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +97 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +3 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +16 -9
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +60 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +83 -5
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +195 -19
- package/neural-interface/public/shared/opencode-providers.js +39 -0
- package/neural-interface/public/shared/schedules-view.js +318 -0
- package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
- package/neural-interface/public/shared/settings/settings-app.js +243 -0
- package/neural-interface/public/shared/settings/settings-data.js +88 -0
- package/neural-interface/public/shared/settings/settings-ia.js +17 -0
- package/neural-interface/public/shared/showcase-privacy.js +2 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +49 -0
- package/neural-interface/public/shared/styles.css +543 -372
- package/neural-interface/public/shared/ui-assistant.js +27 -5
- package/neural-interface/public/shared/ui-automation-studio.js +67 -27
- package/neural-interface/public/shared/ui-bookmarks.js +2 -1
- package/neural-interface/public/shared/ui-claude-panel.js +126 -12
- package/neural-interface/public/shared/ui-codex-panel.js +1 -0
- package/neural-interface/public/shared/ui-detail.js +6 -6
- package/neural-interface/public/shared/ui-explorer.js +2 -0
- package/neural-interface/public/shared/ui-file-links.js +1 -0
- package/neural-interface/public/shared/ui-image-gallery.js +6 -5
- package/neural-interface/public/shared/ui-invite.js +18 -2
- package/neural-interface/public/shared/ui-link.js +9 -9
- package/neural-interface/public/shared/ui-menubar.js +232 -33
- package/neural-interface/public/shared/ui-native-loop-router.js +2 -0
- package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
- package/neural-interface/public/shared/ui-schedules-studio.js +2099 -869
- package/neural-interface/public/shared/ui-sessions.js +15 -4
- package/neural-interface/public/shared/ui-settings.js +87 -36
- package/neural-interface/public/shared/ui-sidebar.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +55 -4
- package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
- package/neural-interface/public/shared/ui-skills.js +70 -12
- package/neural-interface/public/shared/ui-sync.js +9 -0
- package/neural-interface/public/shared/ui-terminal.js +36 -20
- package/neural-interface/public/shared/ui-trash.js +8 -1
- package/neural-interface/public/shared/ui-tutorial-steps.js +7 -3
- package/neural-interface/public/shared/ui-tutorial.js +15 -5
- package/neural-interface/public/shared/ui-update.js +87 -16
- package/neural-interface/public/shared/ui-whiteboard.js +2 -1
- package/neural-interface/public/variant/2d/main.js +4 -1
- package/neural-interface/public/variant/3d/main.js +3 -0
- package/neural-interface/public/vendor/highlight/LICENSE +29 -0
- package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
- package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
- package/neural-interface/public/vendor/highlight/manifest.json +5 -0
- package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
- package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
- package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
- package/neural-interface/public/vendor/marked/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
- package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
- package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -0
- package/neural-interface/scripts/build-vendor.mjs +84 -3
- package/neural-interface/scripts/rebuild-pty.js +14 -2
- package/neural-interface/server.js +1279 -372
- package/npm-shrinkwrap.json +4424 -0
- package/package.json +54 -2
- package/postinstall.js +61 -47
- package/preuninstall.js +8 -35
- package/setup.js +76 -44
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/schedule.md +2 -2
- package/updater.cmd +2 -2
- package/updater.mjs +97 -3
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Which process a pid is.
|
|
3
|
+
//
|
|
4
|
+
// The OS gives a pid to a new process once the old one is gone: a server
|
|
5
|
+
// SynaBun started and recorded by its pid may have exited, and that number now
|
|
6
|
+
// belong to another program. A pid together with the time its process started
|
|
7
|
+
// and its command line, as the OS reports them, names one process and no other.
|
|
8
|
+
// SynaBun records all three when it starts a server (readProcessIdentity) and
|
|
9
|
+
// signals that pid only while the OS still reports the same three
|
|
10
|
+
// (sameProcess), checked again right before each signal. A process whose
|
|
11
|
+
// identity cannot be read is never taken for SynaBun's.
|
|
12
|
+
//
|
|
13
|
+
// A start time to the second can still be shared by two processes, and a pid,
|
|
14
|
+
// a start time and a command line mean something only on the machine, for the
|
|
15
|
+
// user and in the boot they were read in. So a serve SynaBun spawns also
|
|
16
|
+
// carries a random token in its environment (SERVE_TOKEN_ENV, newServeToken),
|
|
17
|
+
// which the OS gives back for the user's own processes (readEnvironmentHas:
|
|
18
|
+
// `ps -E` on macOS, /proc/<pid>/environ on Linux; Windows cannot read another
|
|
19
|
+
// process's environment, and its start times are to the fraction of a second),
|
|
20
|
+
// and every record says where it was written (readHostScope: the machine's id,
|
|
21
|
+
// the user, the boot). The parent chain (readProcessParentAsync) and the
|
|
22
|
+
// listeners of a port (listPortListenersAsync) tell whether what answers on a
|
|
23
|
+
// port is a process SynaBun spawned, or one that process started.
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
import { execFile, execFileSync } from 'node:child_process';
|
|
27
|
+
import { randomBytes } from 'node:crypto';
|
|
28
|
+
import { readFileSync } from 'node:fs';
|
|
29
|
+
|
|
30
|
+
/** The environment variable that carries the token of a serve SynaBun spawned. */
|
|
31
|
+
export const SERVE_TOKEN_ENV = 'SYNABUN_SERVE_TOKEN';
|
|
32
|
+
|
|
33
|
+
/** A fresh token for one spawn: 128 random bits, hex. */
|
|
34
|
+
export function newServeToken() {
|
|
35
|
+
return randomBytes(16).toString('hex');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// `ps -o uid= -o lstart=` in the C locale and UTC: " 501 Tue Oct 21 04:12:50 2026" (the day may be padded with a
|
|
39
|
+
// space). The uid is optional here: a test may hand in what an older query printed.
|
|
40
|
+
const PS_LINE = /^(?:(\d+)\s+)?(\S+\s+\S+\s+\d{1,2}\s+\d{1,2}:\d{2}:\d{2}\s+\d{4})\s+(\S.*)$/;
|
|
41
|
+
const PS_PARENT = /^(\d+)\s+(\S+\s+\S+\s+\d{1,2}\s+\d{1,2}:\d{2}:\d{2}\s+\d{4})$/;
|
|
42
|
+
// One locale and one time zone, so a record reads the same after either changes.
|
|
43
|
+
const C_ENV = () => ({ ...process.env, LC_ALL: 'C', LANG: 'C', TZ: 'UTC' });
|
|
44
|
+
|
|
45
|
+
const pidOf = (pid) => {
|
|
46
|
+
const n = Number(pid);
|
|
47
|
+
return Number.isInteger(n) && n > 0 ? n : null;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const firstLine = (out) => String(out ?? '').split('\n').map((l) => l.trim()).find(Boolean) || '';
|
|
51
|
+
|
|
52
|
+
function powershell(script, timeout = 8000) {
|
|
53
|
+
return { file: 'powershell.exe', args: ['-NoProfile', '-NonInteractive', '-Command', script], options: { encoding: 'utf8', timeout, windowsHide: true } };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// What asks the OS about one pid: `ps -ww -o uid= -o lstart= -o command=` (the user, the start time to the second,
|
|
57
|
+
// the whole command line) on macOS and Linux; the process's CreationDate and CommandLine (CIM, through PowerShell)
|
|
58
|
+
// on Windows.
|
|
59
|
+
function identityQuery(n, platform) {
|
|
60
|
+
if (platform === 'win32') {
|
|
61
|
+
return powershell(`$p = Get-CimInstance Win32_Process -Filter "ProcessId=${n}"; if ($p) { $p.CreationDate.ToUniversalTime().ToString('o'); $p.CommandLine }`);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
file: 'ps',
|
|
65
|
+
args: ['-ww', '-o', 'uid=', '-o', 'lstart=', '-o', 'command=', '-p', String(n)],
|
|
66
|
+
options: { encoding: 'utf8', timeout: 5000, env: C_ENV() },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function parseIdentity(n, platform, out) {
|
|
71
|
+
const text = String(out ?? '');
|
|
72
|
+
if (platform === 'win32') {
|
|
73
|
+
const [first = '', ...rest] = text.split(/\r?\n/);
|
|
74
|
+
const startedAt = first.trim();
|
|
75
|
+
const command = rest.join('\n').trim();
|
|
76
|
+
return startedAt && command ? { pid: n, startedAt, command } : null;
|
|
77
|
+
}
|
|
78
|
+
const match = PS_LINE.exec(firstLine(text));
|
|
79
|
+
if (!match) return null;
|
|
80
|
+
const identity = { pid: n, startedAt: match[2].replace(/\s+/g, ' '), command: match[3].trim() };
|
|
81
|
+
if (match[1] != null) identity.uid = match[1];
|
|
82
|
+
return identity;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* `{ pid, startedAt, command }` of a running process (`uid` too on macOS and Linux), or null: gone, or the OS could
|
|
87
|
+
* not be asked. macOS and Linux: `ps -ww -o uid= -o lstart= -o command=` (the start time to the second, the whole
|
|
88
|
+
* command line); Windows: the process's CreationDate (to the fraction of a second) and CommandLine (CIM, through
|
|
89
|
+
* PowerShell).
|
|
90
|
+
* @param {number} pid
|
|
91
|
+
* @param {{ platform?: string, run?: typeof execFileSync }} [o] `run`: tests hand in what the OS would answer
|
|
92
|
+
*/
|
|
93
|
+
export function readProcessIdentity(pid, { platform = process.platform, run = execFileSync } = {}) {
|
|
94
|
+
const n = pidOf(pid);
|
|
95
|
+
if (!n) return null;
|
|
96
|
+
const query = identityQuery(n, platform);
|
|
97
|
+
try {
|
|
98
|
+
return parseIdentity(n, platform, run(query.file, query.args, { ...query.options, stdio: ['ignore', 'pipe', 'ignore'] }));
|
|
99
|
+
} catch {
|
|
100
|
+
// ps exits 1 for a pid nothing runs under; a missing ps or PowerShell is "could not be asked".
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* readProcessIdentity without holding the event loop while the OS answers (PowerShell takes about a second):
|
|
107
|
+
* for a look that may read several pids, such as the sweep of SynaBun's leftover serves.
|
|
108
|
+
* @param {number} pid
|
|
109
|
+
* @param {{ platform?: string, run?: (file: string, args: string[], options: object) => Promise<string> }} [o]
|
|
110
|
+
*/
|
|
111
|
+
export async function readProcessIdentityAsync(pid, { platform = process.platform, run = runFile } = {}) {
|
|
112
|
+
const n = pidOf(pid);
|
|
113
|
+
if (!n) return null;
|
|
114
|
+
const query = identityQuery(n, platform);
|
|
115
|
+
try {
|
|
116
|
+
return parseIdentity(n, platform, await run(query.file, query.args, query.options));
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function runFile(file, args, options) {
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
execFile(file, args, options, (error, stdout, stderr) => (error ? reject(Object.assign(error, { stdout, stderr })) : resolve(stdout)));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Is `current` (readProcessIdentity now) the process `recorded` was: the same pid, start time and command line? */
|
|
129
|
+
export function sameProcess(recorded, current) {
|
|
130
|
+
if (!recorded || !current || !recorded.startedAt || !recorded.command) return false;
|
|
131
|
+
return Number(recorded.pid) === Number(current.pid)
|
|
132
|
+
&& String(recorded.startedAt) === String(current.startedAt)
|
|
133
|
+
&& String(recorded.command) === String(current.command);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Does any process run under `pid`? true, false (none: the OS said so), or null (it could not be told). Signal 0
|
|
138
|
+
* sends nothing: the OS only checks the pid. A process of another user answers EPERM, which is a process too.
|
|
139
|
+
* @param {number} pid
|
|
140
|
+
* @param {{ kill?: (pid: number, signal: number | string) => void }} [o]
|
|
141
|
+
*/
|
|
142
|
+
export function pidExists(pid, { kill = (p, s) => process.kill(p, s) } = {}) {
|
|
143
|
+
const n = pidOf(pid);
|
|
144
|
+
if (!n) return false;
|
|
145
|
+
try {
|
|
146
|
+
kill(n, 0);
|
|
147
|
+
return true;
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (error?.code === 'ESRCH') return false;
|
|
150
|
+
if (error?.code === 'EPERM') return true;
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ── The environment a process started with ──────────────────────────────────
|
|
156
|
+
|
|
157
|
+
const ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
158
|
+
const ENV_VALUE = /^[A-Za-z0-9_.:-]+$/;
|
|
159
|
+
|
|
160
|
+
// macOS prints the environment after the command line (`ps -E`) only for a process it lets the user read: the
|
|
161
|
+
// user's own, and not a binary of the system's. The line must start with the command line read for the identity
|
|
162
|
+
// (else the pid is another process's by now), and hold more than that (else the environment was not shown).
|
|
163
|
+
function parseEnvironmentHas(out, command, name, value) {
|
|
164
|
+
const text = firstLine(out);
|
|
165
|
+
const plain = String(command ?? '').trim();
|
|
166
|
+
if (!plain || !text.startsWith(plain)) return null;
|
|
167
|
+
const environment = text.slice(plain.length);
|
|
168
|
+
if (!environment.trim()) return null;
|
|
169
|
+
return new RegExp(`(?:^|\\s)${name}=${value}(?=\\s|$)`).test(environment);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function linuxEnvironmentHas(n, name, value, readFile) {
|
|
173
|
+
let text;
|
|
174
|
+
try { text = readFile(`/proc/${n}/environ`, 'utf8'); } catch { return null; } // gone, or another user's
|
|
175
|
+
const vars = String(text).split('\0').filter(Boolean);
|
|
176
|
+
if (!vars.length) return null; // a process that has ended shows none
|
|
177
|
+
return vars.includes(`${name}=${value}`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function environmentQuery(n) {
|
|
181
|
+
return { file: 'ps', args: ['-E', '-ww', '-o', 'command=', '-p', String(n)], options: { encoding: 'utf8', timeout: 5000, env: C_ENV() } };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Does the environment `pid` started with hold `name=value`? true, false (it was read, and does not), or null (it
|
|
186
|
+
* could not be read: gone, another user's, or the OS does not say). macOS: `ps -E`, given the command line just
|
|
187
|
+
* read for the process's identity; Linux: /proc/<pid>/environ; Windows and anything else: null.
|
|
188
|
+
* @param {number} pid
|
|
189
|
+
* @param {string} name
|
|
190
|
+
* @param {string} value
|
|
191
|
+
* @param {{ command?: string, platform?: string, run?: typeof execFileSync, readFile?: typeof readFileSync }} [o]
|
|
192
|
+
*/
|
|
193
|
+
export function readEnvironmentHas(pid, name, value, { command = '', platform = process.platform, run = execFileSync, readFile = readFileSync } = {}) {
|
|
194
|
+
const n = pidOf(pid);
|
|
195
|
+
if (!n || !ENV_NAME.test(String(name)) || !ENV_VALUE.test(String(value))) return null;
|
|
196
|
+
if (platform === 'linux') return linuxEnvironmentHas(n, name, value, readFile);
|
|
197
|
+
if (platform !== 'darwin') return null;
|
|
198
|
+
const query = environmentQuery(n);
|
|
199
|
+
try {
|
|
200
|
+
return parseEnvironmentHas(run(query.file, query.args, { ...query.options, stdio: ['ignore', 'pipe', 'ignore'] }), command, name, value);
|
|
201
|
+
} catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** readEnvironmentHas without holding the event loop while the OS answers. */
|
|
207
|
+
export async function readEnvironmentHasAsync(pid, name, value, { command = '', platform = process.platform, run = runFile, readFile = readFileSync } = {}) {
|
|
208
|
+
const n = pidOf(pid);
|
|
209
|
+
if (!n || !ENV_NAME.test(String(name)) || !ENV_VALUE.test(String(value))) return null;
|
|
210
|
+
if (platform === 'linux') return linuxEnvironmentHas(n, name, value, readFile);
|
|
211
|
+
if (platform !== 'darwin') return null;
|
|
212
|
+
const query = environmentQuery(n);
|
|
213
|
+
try {
|
|
214
|
+
return parseEnvironmentHas(await run(query.file, query.args, query.options), command, name, value);
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ── Where: the machine, the user, the boot ──────────────────────────────────
|
|
221
|
+
|
|
222
|
+
const WINDOWS_SCOPE = "(Get-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Cryptography').MachineGuid; "
|
|
223
|
+
+ "(Get-CimInstance Win32_OperatingSystem).LastBootUpTime.ToUniversalTime().ToString('o'); "
|
|
224
|
+
+ '[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value';
|
|
225
|
+
|
|
226
|
+
const clean = (v) => {
|
|
227
|
+
const text = String(v ?? '').trim();
|
|
228
|
+
return text || null;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
function uidOf(getuid) {
|
|
232
|
+
try { const uid = getuid?.(); return Number.isInteger(uid) && uid >= 0 ? String(uid) : null; } catch { return null; }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function readFirst(readFile, paths) {
|
|
236
|
+
for (const path of paths) {
|
|
237
|
+
try { const text = clean(readFile(path, 'utf8')); if (text) return text; } catch { /* the next one */ }
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const machineFromIoreg = (out) => clean(/"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(String(out ?? ''))?.[1]);
|
|
243
|
+
const bootFromBoottime = (out) => {
|
|
244
|
+
const sec = /sec\s*=\s*(\d+)/.exec(String(out ?? ''))?.[1];
|
|
245
|
+
return sec ? `boottime:${sec}` : null;
|
|
246
|
+
};
|
|
247
|
+
function scopeFromPowershell(out) {
|
|
248
|
+
const [machine, boot, uid] = String(out ?? '').split(/\r?\n/).map(clean);
|
|
249
|
+
return { machine: machine || null, uid: uid || null, boot: boot || null };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Where a record is written, and for whom: `{ machine, uid, boot }`, each a string, or null where the OS could not
|
|
254
|
+
* tell. macOS: the platform UUID (ioreg), the user's uid, the boot session's UUID (kern.bootsessionuuid; the boot
|
|
255
|
+
* time when that is missing); Linux: /etc/machine-id, the uid, /proc/sys/kernel/random/boot_id; Windows: the
|
|
256
|
+
* MachineGuid, the user's SID and the last boot time (one PowerShell).
|
|
257
|
+
* @param {{ platform?: string, run?: typeof execFileSync, readFile?: typeof readFileSync, getuid?: () => number }} [o]
|
|
258
|
+
*/
|
|
259
|
+
export function readHostScope({ platform = process.platform, run = execFileSync, readFile = readFileSync, getuid = process.getuid } = {}) {
|
|
260
|
+
const ask = (file, args, timeout = 5000) => {
|
|
261
|
+
try { return run(file, args, { encoding: 'utf8', timeout, env: C_ENV(), windowsHide: true, stdio: ['ignore', 'pipe', 'ignore'] }); } catch { return null; }
|
|
262
|
+
};
|
|
263
|
+
if (platform === 'darwin') {
|
|
264
|
+
return {
|
|
265
|
+
machine: machineFromIoreg(ask('ioreg', ['-rd1', '-c', 'IOPlatformExpertDevice'])),
|
|
266
|
+
uid: uidOf(getuid),
|
|
267
|
+
boot: clean(ask('sysctl', ['-n', 'kern.bootsessionuuid'])) || bootFromBoottime(ask('sysctl', ['-n', 'kern.boottime'])),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
if (platform === 'linux') {
|
|
271
|
+
return {
|
|
272
|
+
machine: readFirst(readFile, ['/etc/machine-id', '/var/lib/dbus/machine-id']),
|
|
273
|
+
uid: uidOf(getuid),
|
|
274
|
+
boot: readFirst(readFile, ['/proc/sys/kernel/random/boot_id']),
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
if (platform === 'win32') {
|
|
278
|
+
const query = powershell(WINDOWS_SCOPE, 15000);
|
|
279
|
+
return scopeFromPowershell(ask(query.file, query.args, 15000));
|
|
280
|
+
}
|
|
281
|
+
return { machine: null, uid: uidOf(getuid), boot: null };
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** readHostScope without holding the event loop while the OS answers (PowerShell takes about a second). */
|
|
285
|
+
export async function readHostScopeAsync({ platform = process.platform, run = runFile, readFile = readFileSync, getuid = process.getuid } = {}) {
|
|
286
|
+
const ask = async (file, args, timeout = 5000) => {
|
|
287
|
+
try { return await run(file, args, { encoding: 'utf8', timeout, env: C_ENV(), windowsHide: true }); } catch { return null; }
|
|
288
|
+
};
|
|
289
|
+
if (platform === 'darwin') {
|
|
290
|
+
const [ioreg, session] = await Promise.all([ask('ioreg', ['-rd1', '-c', 'IOPlatformExpertDevice']), ask('sysctl', ['-n', 'kern.bootsessionuuid'])]);
|
|
291
|
+
return {
|
|
292
|
+
machine: machineFromIoreg(ioreg),
|
|
293
|
+
uid: uidOf(getuid),
|
|
294
|
+
boot: clean(session) || bootFromBoottime(await ask('sysctl', ['-n', 'kern.boottime'])),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (platform === 'win32') {
|
|
298
|
+
const query = powershell(WINDOWS_SCOPE, 15000);
|
|
299
|
+
return scopeFromPowershell(await ask(query.file, query.args, 15000));
|
|
300
|
+
}
|
|
301
|
+
return readHostScope({ platform, readFile, getuid });
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ── The parent chain, and who listens on a port ─────────────────────────────
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* The parent of a running process and when the process started: `{ pid, ppid, startedAt }`, or null (gone, or the
|
|
308
|
+
* OS could not be asked). macOS and Linux: `ps -o ppid= -o lstart=`; Windows: CIM's ParentProcessId and CreationDate
|
|
309
|
+
* (a parent pid Windows keeps after that parent ended: the caller compares start times).
|
|
310
|
+
* @param {number} pid
|
|
311
|
+
* @param {{ platform?: string, run?: (file: string, args: string[], options: object) => Promise<string> }} [o]
|
|
312
|
+
*/
|
|
313
|
+
export async function readProcessParentAsync(pid, { platform = process.platform, run = runFile } = {}) {
|
|
314
|
+
const n = pidOf(pid);
|
|
315
|
+
if (!n) return null;
|
|
316
|
+
try {
|
|
317
|
+
if (platform === 'win32') {
|
|
318
|
+
const query = powershell(`$p = Get-CimInstance Win32_Process -Filter "ProcessId=${n}"; if ($p) { $p.ParentProcessId; $p.CreationDate.ToUniversalTime().ToString('o') }`);
|
|
319
|
+
const [ppid = '', startedAt = ''] = String(await run(query.file, query.args, query.options)).split(/\r?\n/).map((l) => l.trim());
|
|
320
|
+
return /^\d+$/.test(ppid) && startedAt ? { pid: n, ppid: Number(ppid), startedAt } : null;
|
|
321
|
+
}
|
|
322
|
+
const out = await run('ps', ['-o', 'ppid=', '-o', 'lstart=', '-p', String(n)], { encoding: 'utf8', timeout: 5000, env: C_ENV() });
|
|
323
|
+
const match = PS_PARENT.exec(firstLine(out));
|
|
324
|
+
return match ? { pid: n, ppid: Number(match[1]), startedAt: match[2].replace(/\s+/g, ' ') } : null;
|
|
325
|
+
} catch {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* The pids that listen on a local TCP port: a list (empty: nothing listens that the user may see), or null when the
|
|
332
|
+
* OS could not be asked. macOS and Linux: lsof (exit 1 with nothing printed is "none"; no lsof is null); Windows:
|
|
333
|
+
* Get-NetTCPConnection, where an empty answer is null too (it lists every user's listeners: something answered on
|
|
334
|
+
* the port a moment ago).
|
|
335
|
+
* @param {number} port
|
|
336
|
+
* @param {{ platform?: string, run?: (file: string, args: string[], options: object) => Promise<string> }} [o]
|
|
337
|
+
*/
|
|
338
|
+
export async function listPortListenersAsync(port, { platform = process.platform, run = runFile, selfPid = process.pid } = {}) {
|
|
339
|
+
const p = Number(port);
|
|
340
|
+
if (!Number.isInteger(p) || p <= 0 || p > 65535) return null;
|
|
341
|
+
const pidsIn = (out) => [...new Set(String(out ?? '').split(/\r?\n/).map((l) => l.trim()).filter((l) => /^\d+$/.test(l)).map(Number))]
|
|
342
|
+
.filter((n) => n > 0 && n !== selfPid);
|
|
343
|
+
if (platform === 'win32') {
|
|
344
|
+
const query = powershell(`Get-NetTCPConnection -LocalPort ${p} -State Listen -ErrorAction SilentlyContinue | ForEach-Object { $_.OwningProcess }`);
|
|
345
|
+
try {
|
|
346
|
+
const pids = pidsIn(await run(query.file, query.args, query.options));
|
|
347
|
+
return pids.length ? pids : null;
|
|
348
|
+
} catch {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
return pidsIn(await run('lsof', ['-nP', `-tiTCP:${p}`, '-sTCP:LISTEN'], { encoding: 'utf8', timeout: 5000, env: C_ENV() }));
|
|
354
|
+
} catch (error) {
|
|
355
|
+
// lsof exits 1 when nothing matched, and for some errors too: nothing printed but a warning is "cannot be told".
|
|
356
|
+
if (error?.code !== 1) return null;
|
|
357
|
+
const pids = pidsIn(error.stdout);
|
|
358
|
+
if (pids.length) return pids;
|
|
359
|
+
return String(error.stderr ?? '').trim() ? null : [];
|
|
360
|
+
}
|
|
361
|
+
}
|
|
@@ -4,7 +4,8 @@ import { claudeAuthEnv } from './claude-panel-auth.js';
|
|
|
4
4
|
import { applyCodexLaunchEnv } from './codex-accounts.js';
|
|
5
5
|
|
|
6
6
|
// Only server-owned account records and resolved executables enter the PTY.
|
|
7
|
-
|
|
7
|
+
// `codexConfigArgs`: the `-c` words every Codex SynaBun starts gets (the Admin sandbox setting's Windows sandbox).
|
|
8
|
+
export function providerLoginSpec({ provider, accountId, claudeAccounts, codexAccount, claudeExecutable, codexExecutable, env, codexConfigArgs = [] }) {
|
|
8
9
|
if (!['claude', 'codex'].includes(provider) || typeof accountId !== 'string' || !/^[a-z0-9-]{1,64}$/.test(accountId)) {
|
|
9
10
|
throw Object.assign(new Error('Unknown provider account'), { status: 404 });
|
|
10
11
|
}
|
|
@@ -24,7 +25,7 @@ export function providerLoginSpec({ provider, accountId, claudeAccounts, codexAc
|
|
|
24
25
|
if (!account.home) throw new Error('This Claude account has no isolated home.');
|
|
25
26
|
baseEnv = claudeAuthEnv(baseEnv, { CLAUDE_CONFIG_DIR: account.home });
|
|
26
27
|
}
|
|
27
|
-
const args = provider === 'claude' ? ['auth', 'login', '--claudeai'] : ['login'];
|
|
28
|
+
const args = provider === 'claude' ? ['auth', 'login', '--claudeai'] : ['login', ...codexConfigArgs];
|
|
28
29
|
return { launch: /\.[cm]?js$/i.test(file) ? { shell: process.execPath, args: [file, ...args] } : { shell: file, args }, baseEnv };
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from './db.js';
|
|
25
25
|
import { parseLine } from './session-chunker.js';
|
|
26
26
|
import { listCodexSessionsFromAccounts } from './codex-session-catalog.js';
|
|
27
|
+
import { opencodeDbFlavor, sessionTablesFor, v2MessageText } from './opencode-db-schema.js';
|
|
27
28
|
|
|
28
29
|
const MAX_BODY = 256 * 1024;
|
|
29
30
|
const MAX_MSG_CHARS = 8 * 1024;
|
|
@@ -380,20 +381,26 @@ export function rebuildCodexCache({ project, projects, accounts, onProgress } =
|
|
|
380
381
|
|
|
381
382
|
// --- OpenCode ---
|
|
382
383
|
|
|
383
|
-
|
|
384
|
+
// `protocol`: the OpenCode major SynaBun talks to (lib/opencode-db-schema.js
|
|
385
|
+
// opencodeDbFlavor): OpenCode 2 keeps its sessions in session_v2 and their text
|
|
386
|
+
// in session_message rows, in the same database file as OpenCode 1's tables.
|
|
387
|
+
export function rebuildOpencodeCache({ getOpencodeDb, onProgress, protocol = null } = {}) {
|
|
384
388
|
const emit = onProgress || (() => {});
|
|
385
389
|
if (typeof getOpencodeDb !== 'function') return { sessions: 0, updated: 0 };
|
|
386
390
|
|
|
387
391
|
const ocdb = getOpencodeDb();
|
|
388
392
|
if (!ocdb) return { sessions: 0, updated: 0 };
|
|
393
|
+
const flavor = opencodeDbFlavor(ocdb, protocol);
|
|
394
|
+
if (!flavor) return { sessions: 0, updated: 0 };
|
|
395
|
+
const tables = sessionTablesFor(flavor);
|
|
389
396
|
|
|
390
397
|
let sessions;
|
|
391
398
|
try {
|
|
392
399
|
sessions = ocdb.prepare(`
|
|
393
400
|
SELECT s.id, s.title, s.directory, s.time_created, s.time_updated,
|
|
394
401
|
p.worktree AS project_worktree,
|
|
395
|
-
|
|
396
|
-
FROM session s
|
|
402
|
+
${tables.messageCount} AS message_count
|
|
403
|
+
FROM ${tables.session} s
|
|
397
404
|
LEFT JOIN project p ON s.project_id = p.id
|
|
398
405
|
WHERE s.time_archived IS NULL
|
|
399
406
|
`).all();
|
|
@@ -402,11 +409,25 @@ export function rebuildOpencodeCache({ getOpencodeDb, onProgress } = {}) {
|
|
|
402
409
|
let total = sessions.length;
|
|
403
410
|
let updated = 0;
|
|
404
411
|
|
|
405
|
-
// OpenCode schema: message.data (JSON w/ role+metadata) + part.data (JSON w/ type+text).
|
|
412
|
+
// OpenCode 1 schema: message.data (JSON w/ role+metadata) + part.data (JSON w/ type+text).
|
|
406
413
|
// Pull parts per message, decode JSON, grab text where type === 'text'.
|
|
414
|
+
// OpenCode 2: one session_message row per message, its text in `data`
|
|
415
|
+
// (v2MessageText); read as the same { part_id, part_created, pdata, mdata } rows.
|
|
407
416
|
let partStmt;
|
|
408
417
|
try {
|
|
409
|
-
partStmt =
|
|
418
|
+
partStmt = flavor === 'v2'
|
|
419
|
+
? (() => {
|
|
420
|
+
const rows = ocdb.prepare(`SELECT id, type, time_created, data FROM session_message
|
|
421
|
+
WHERE session_id = ? AND type IN ('user', 'assistant')
|
|
422
|
+
ORDER BY seq ASC`);
|
|
423
|
+
return {
|
|
424
|
+
all: (sessionId) => rows.all(sessionId).map((row) => {
|
|
425
|
+
const said = v2MessageText(row.type, row.data);
|
|
426
|
+
return said ? { part_id: row.id, part_created: row.time_created, pdata: JSON.stringify({ type: 'text', text: said.text }), mdata: JSON.stringify({ role: said.role }) } : null;
|
|
427
|
+
}).filter(Boolean),
|
|
428
|
+
};
|
|
429
|
+
})()
|
|
430
|
+
: ocdb.prepare(`SELECT p.id AS part_id, p.time_created AS part_created, p.data AS pdata, m.data AS mdata
|
|
410
431
|
FROM part p
|
|
411
432
|
LEFT JOIN message m ON m.id = p.message_id
|
|
412
433
|
WHERE p.session_id = ?
|
|
@@ -227,9 +227,10 @@ export async function startIndexing(options = {}) {
|
|
|
227
227
|
* Uses vectors already stored in SQLite — no re-embedding needed.
|
|
228
228
|
* Skips chunks that already exist in memories (same UUID) or have dedup_memory_id.
|
|
229
229
|
* @param {function} [onProgress] - Progress callback
|
|
230
|
+
* @param {{ ensureCategory?: () => void }} [options] - ensureCategory creates "conversations" before the first write (a fresh install has none)
|
|
230
231
|
* @returns {Promise<{ mirrored: number, skipped: number, errors: number }>}
|
|
231
232
|
*/
|
|
232
|
-
export async function mirrorExistingChunks(onProgress) {
|
|
233
|
+
export async function mirrorExistingChunks(onProgress, { ensureCategory = null } = {}) {
|
|
233
234
|
const emit = onProgress || (() => {});
|
|
234
235
|
const d = getDb();
|
|
235
236
|
|
|
@@ -296,6 +297,7 @@ export async function mirrorExistingChunks(onProgress) {
|
|
|
296
297
|
// Batch upsert to memories
|
|
297
298
|
if (mirrorPoints.length > 0) {
|
|
298
299
|
try {
|
|
300
|
+
if (typeof ensureCategory === 'function') ensureCategory();
|
|
299
301
|
for (let i = 0; i < mirrorPoints.length; i += UPSERT_BATCH_SIZE) {
|
|
300
302
|
const batch = mirrorPoints.slice(i, i + UPSERT_BATCH_SIZE);
|
|
301
303
|
upsertMemories(batch);
|
|
@@ -118,6 +118,8 @@ async function generateCodexTitle(input, deps) {
|
|
|
118
118
|
const args = [
|
|
119
119
|
'exec', '--ephemeral', '--skip-git-repo-check', '--ignore-rules',
|
|
120
120
|
'--sandbox', 'read-only', '--color', 'never', '--json',
|
|
121
|
+
// The Windows sandbox the Admin sandbox setting allows (lib/agent-sandbox-elevation.js).
|
|
122
|
+
...(typeof deps.codexConfigArgs === 'function' ? deps.codexConfigArgs() : []),
|
|
121
123
|
];
|
|
122
124
|
if (input.cwd) args.push('-C', input.cwd);
|
|
123
125
|
if (input.model) args.push('-m', input.model);
|
|
@@ -150,6 +152,23 @@ async function generateOpenCodeTitle(input, deps) {
|
|
|
150
152
|
const timer = setTimeout(() => controller.abort(new Error('Session title request timed out')), SESSION_TITLE_TIMEOUT_MS);
|
|
151
153
|
timer.unref?.();
|
|
152
154
|
let sessionId = null;
|
|
155
|
+
// OpenCode 2 (lib/opencode2-client.js): its one-shot generator when the model
|
|
156
|
+
// allows it (OpenCode's free tier answers it 503), else a temporary session
|
|
157
|
+
// whose permissions deny every tool: OpenCode 2 has no tool switch per prompt.
|
|
158
|
+
const opencode2 = deps.openCodeClient.getProtocol?.() === 2;
|
|
159
|
+
if (opencode2) {
|
|
160
|
+
const raw = deps.openCodeClient.getClient?.();
|
|
161
|
+
try {
|
|
162
|
+
const generated = await raw?.generate?.({
|
|
163
|
+
prompt: `${TITLE_SYSTEM_PROMPT}\n\n${titlePrompt(input)}`,
|
|
164
|
+
model: input.model || undefined,
|
|
165
|
+
directory: input.cwd || undefined,
|
|
166
|
+
signal: controller.signal,
|
|
167
|
+
});
|
|
168
|
+
const text = String(generated?.data?.text || '').trim();
|
|
169
|
+
if (!generated?.error && text) { clearTimeout(timer); return text; }
|
|
170
|
+
} catch { /* the session below */ }
|
|
171
|
+
}
|
|
153
172
|
try {
|
|
154
173
|
const toolIds = new Set([
|
|
155
174
|
'bash', 'edit', 'write', 'patch', 'apply_patch', 'multiedit', 'read',
|
|
@@ -168,6 +187,7 @@ async function generateOpenCodeTitle(input, deps) {
|
|
|
168
187
|
const created = await deps.openCodeClient.session.create({
|
|
169
188
|
directory: input.cwd || undefined,
|
|
170
189
|
title: 'SessionTitleDraft',
|
|
190
|
+
...(opencode2 ? { permission: [{ permission: '*', pattern: '*', action: 'deny' }] } : {}),
|
|
171
191
|
});
|
|
172
192
|
sessionId = created?.data?.id || created?.data?.sessionID || created?.id || created?.sessionID;
|
|
173
193
|
if (!sessionId) throw new Error('OpenCode did not create a temporary title session');
|
|
@@ -47,6 +47,7 @@ import { EXPORT_FORMATS, StyleGuideError, renderFormat } from './store.js';
|
|
|
47
47
|
import { estimateTokens, styleGuideSummaryForClass } from './summary.js';
|
|
48
48
|
import { resolvedTokens } from './tokens.js';
|
|
49
49
|
import { safeLogoFile } from './security.js';
|
|
50
|
+
import { setUntrustedFileHeaders } from '../untrusted-file-headers.js';
|
|
50
51
|
|
|
51
52
|
const LOGO_TYPES = Object.freeze({ 'image/png': '.png', 'image/svg+xml': '.svg', 'image/jpeg': '.jpg', 'image/webp': '.webp' });
|
|
52
53
|
const SAVE_SOURCE_RE = /^(ui|import:[a-z-]{1,24}|preset:[a-z0-9-]{1,40})$/;
|
|
@@ -367,9 +368,9 @@ export function registerStyleGuideRoutes(app, { store, fetchImpl = null, log = (
|
|
|
367
368
|
if (!full.startsWith(store.assetsDir + sep)) return res.status(403).json({ ok: false, error: 'Forbidden' });
|
|
368
369
|
if (!existsSync(full)) return res.status(404).json({ ok: false, error: 'Not found' });
|
|
369
370
|
store.assertPath(store.assetsDir, full);
|
|
370
|
-
// An uploaded SVG is served as a file to look at, never as a page that can run script on this origin
|
|
371
|
-
|
|
372
|
-
res
|
|
371
|
+
// An uploaded SVG is served as a file to look at, never as a page that can run script on this origin
|
|
372
|
+
// (and opened by its address, a download).
|
|
373
|
+
setUntrustedFileHeaders(res, file);
|
|
373
374
|
res.sendFile(full);
|
|
374
375
|
}));
|
|
375
376
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// The headers of a file a user uploaded or an agent made, served back to the page: a pasted or generated image, a
|
|
2
|
+
// category logo, a custom file icon, a Skills Studio icon, a Style Guide logo, an Assistant run's media. An <img> or
|
|
3
|
+
// <video> in the app shows it as before (it ignores all three); opened by its address it runs nothing. An SVG is a
|
|
4
|
+
// document that can carry script, so it also comes as a download there. tests/untrusted-file-headers.test.mjs.
|
|
5
|
+
import { basename } from 'node:path';
|
|
6
|
+
|
|
7
|
+
/** No script, no request, no plugin, no form; a unique origin (sandbox). Inline styles stay, so an SVG still draws. */
|
|
8
|
+
export const UNTRUSTED_FILE_CSP = "default-src 'none'; style-src 'unsafe-inline'; sandbox";
|
|
9
|
+
|
|
10
|
+
/** Is this file an SVG, by its name or by the type it is sent as? */
|
|
11
|
+
export function isSvgFile(name, type = '') {
|
|
12
|
+
return /\.svg$/i.test(String(name || '')) || /^image\/svg\+xml\b/i.test(String(type || ''));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Set the three headers on `res` (an Express response) for the file `name` (a path or a file name) sent as `type`.
|
|
17
|
+
* Call it before the body goes out; it does not touch Content-Type.
|
|
18
|
+
*/
|
|
19
|
+
export function setUntrustedFileHeaders(res, name, type = '') {
|
|
20
|
+
res.setHeader('Content-Security-Policy', UNTRUSTED_FILE_CSP);
|
|
21
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
22
|
+
if (isSvgFile(name, type)) {
|
|
23
|
+
const file = basename(String(name || '')) || 'image.svg';
|
|
24
|
+
const ascii = file.replace(/[^\x20-\x7e]|["\\]/g, '_');
|
|
25
|
+
res.setHeader('Content-Disposition', ascii === file ? `attachment; filename="${file}"` : `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(file)}`);
|
|
26
|
+
}
|
|
27
|
+
}
|