@akon-labs/nexus-cli 0.1.9 → 0.1.11-rc.2
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 +21 -0
- package/LICENSE +1 -0
- package/README.md +3 -2
- package/dist/app-bridge.bundle.js +67 -0
- package/dist/cli/require-login.d.ts.map +1 -1
- package/dist/cli/require-login.js +2 -2
- package/dist/cli/require-login.js.map +1 -1
- package/dist/cli.js +20866 -1882
- package/dist/core/agent-session.d.ts +3 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auto-model.d.ts +1 -1
- package/dist/core/auto-model.d.ts.map +1 -1
- package/dist/core/auto-model.js +1 -1
- package/dist/core/auto-model.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +7 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +14 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-resolver.d.ts +2 -2
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +15 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +50 -0
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -3
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +5 -5
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js +3 -3
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/extensions/gitnexus/config.d.ts +15 -1
- package/dist/extensions/gitnexus/config.d.ts.map +1 -1
- package/dist/extensions/gitnexus/config.js +86 -2
- package/dist/extensions/gitnexus/config.js.map +1 -1
- package/dist/extensions/gitnexus/gateway.d.ts +6 -6
- package/dist/extensions/gitnexus/gateway.d.ts.map +1 -1
- package/dist/extensions/gitnexus/gateway.js +4 -4
- package/dist/extensions/gitnexus/gateway.js.map +1 -1
- package/dist/extensions/gitnexus/index.d.ts.map +1 -1
- package/dist/extensions/gitnexus/index.js +6 -4
- package/dist/extensions/gitnexus/index.js.map +1 -1
- package/dist/extensions/gitnexus/observatory.d.ts.map +1 -1
- package/dist/extensions/gitnexus/observatory.js +2 -2
- package/dist/extensions/gitnexus/observatory.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +3 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/mcp/abort.d.ts +3 -0
- package/dist/extensions/mcp/abort.d.ts.map +1 -0
- package/dist/extensions/mcp/abort.js +41 -0
- package/dist/extensions/mcp/abort.js.map +1 -0
- package/dist/extensions/mcp/agent-dir.d.ts +6 -0
- package/dist/extensions/mcp/agent-dir.d.ts.map +1 -0
- package/dist/extensions/mcp/agent-dir.js +18 -0
- package/dist/extensions/mcp/agent-dir.js.map +1 -0
- package/dist/extensions/mcp/agent-plugin-loader.d.ts +9 -0
- package/dist/extensions/mcp/agent-plugin-loader.d.ts.map +1 -0
- package/dist/extensions/mcp/agent-plugin-loader.js +384 -0
- package/dist/extensions/mcp/agent-plugin-loader.js.map +1 -0
- package/dist/extensions/mcp/app-bridge.bundle.js +67 -0
- package/dist/extensions/mcp/commands.d.ts +47 -0
- package/dist/extensions/mcp/commands.d.ts.map +1 -0
- package/dist/extensions/mcp/commands.js +821 -0
- package/dist/extensions/mcp/commands.js.map +1 -0
- package/dist/extensions/mcp/config.d.ts +123 -38
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +1035 -70
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/extensions/mcp/consent-manager.d.ts +14 -0
- package/dist/extensions/mcp/consent-manager.d.ts.map +1 -0
- package/dist/extensions/mcp/consent-manager.js +60 -0
- package/dist/extensions/mcp/consent-manager.js.map +1 -0
- package/dist/extensions/mcp/direct-tools.d.ts +11 -0
- package/dist/extensions/mcp/direct-tools.d.ts.map +1 -0
- package/dist/extensions/mcp/direct-tools.js +562 -0
- package/dist/extensions/mcp/direct-tools.js.map +1 -0
- package/dist/extensions/mcp/elicitation-handler.d.ts +18 -0
- package/dist/extensions/mcp/elicitation-handler.d.ts.map +1 -0
- package/dist/extensions/mcp/elicitation-handler.js +320 -0
- package/dist/extensions/mcp/elicitation-handler.js.map +1 -0
- package/dist/extensions/mcp/error-signal.d.ts +16 -0
- package/dist/extensions/mcp/error-signal.d.ts.map +1 -0
- package/dist/extensions/mcp/error-signal.js +22 -0
- package/dist/extensions/mcp/error-signal.js.map +1 -0
- package/dist/extensions/mcp/errors.d.ts +104 -0
- package/dist/extensions/mcp/errors.d.ts.map +1 -0
- package/dist/extensions/mcp/errors.js +171 -0
- package/dist/extensions/mcp/errors.js.map +1 -0
- package/dist/extensions/mcp/glimpse-ui.d.ts +10 -0
- package/dist/extensions/mcp/glimpse-ui.d.ts.map +1 -0
- package/dist/extensions/mcp/glimpse-ui.js +67 -0
- package/dist/extensions/mcp/glimpse-ui.js.map +1 -0
- package/dist/extensions/mcp/host-html-template.d.ts +17 -0
- package/dist/extensions/mcp/host-html-template.d.ts.map +1 -0
- package/dist/extensions/mcp/host-html-template.js +442 -0
- package/dist/extensions/mcp/host-html-template.js.map +1 -0
- package/dist/extensions/mcp/index.d.ts +20 -15
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +1113 -82
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/init.d.ts +28 -0
- package/dist/extensions/mcp/init.d.ts.map +1 -0
- package/dist/extensions/mcp/init.js +631 -0
- package/dist/extensions/mcp/init.js.map +1 -0
- package/dist/extensions/mcp/json-schema-validator.d.ts +3 -0
- package/dist/extensions/mcp/json-schema-validator.d.ts.map +1 -0
- package/dist/extensions/mcp/json-schema-validator.js +53 -0
- package/dist/extensions/mcp/json-schema-validator.js.map +1 -0
- package/dist/extensions/mcp/lifecycle.d.ts +56 -0
- package/dist/extensions/mcp/lifecycle.d.ts.map +1 -0
- package/dist/extensions/mcp/lifecycle.js +395 -0
- package/dist/extensions/mcp/lifecycle.js.map +1 -0
- package/dist/extensions/mcp/logger.d.ts +52 -0
- package/dist/extensions/mcp/logger.d.ts.map +1 -0
- package/dist/extensions/mcp/logger.js +134 -0
- package/dist/extensions/mcp/logger.js.map +1 -0
- package/dist/extensions/mcp/mcp-auth-flow.d.ts +117 -0
- package/dist/extensions/mcp/mcp-auth-flow.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-auth-flow.js +869 -0
- package/dist/extensions/mcp/mcp-auth-flow.js.map +1 -0
- package/dist/extensions/mcp/mcp-auth.d.ts +162 -0
- package/dist/extensions/mcp/mcp-auth.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-auth.js +897 -0
- package/dist/extensions/mcp/mcp-auth.js.map +1 -0
- package/dist/extensions/mcp/mcp-bearer-store.d.ts +25 -0
- package/dist/extensions/mcp/mcp-bearer-store.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-bearer-store.js +350 -0
- package/dist/extensions/mcp/mcp-bearer-store.js.map +1 -0
- package/dist/extensions/mcp/mcp-callback-server.d.ts +54 -0
- package/dist/extensions/mcp/mcp-callback-server.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-callback-server.js +454 -0
- package/dist/extensions/mcp/mcp-callback-server.js.map +1 -0
- package/dist/extensions/mcp/mcp-code.d.ts +48 -0
- package/dist/extensions/mcp/mcp-code.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-code.js +358 -0
- package/dist/extensions/mcp/mcp-code.js.map +1 -0
- package/dist/extensions/mcp/mcp-keyring-helper.cjs +89 -0
- package/dist/extensions/mcp/mcp-oauth-provider.d.ts +135 -0
- package/dist/extensions/mcp/mcp-oauth-provider.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-oauth-provider.js +491 -0
- package/dist/extensions/mcp/mcp-oauth-provider.js.map +1 -0
- package/dist/extensions/mcp/mcp-output-guard.d.ts +59 -0
- package/dist/extensions/mcp/mcp-output-guard.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-output-guard.js +343 -0
- package/dist/extensions/mcp/mcp-output-guard.js.map +1 -0
- package/dist/extensions/mcp/mcp-panel.d.ts +71 -0
- package/dist/extensions/mcp/mcp-panel.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-panel.js +973 -0
- package/dist/extensions/mcp/mcp-panel.js.map +1 -0
- package/dist/extensions/mcp/mcp-probe.d.ts +7 -0
- package/dist/extensions/mcp/mcp-probe.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-probe.js +155 -0
- package/dist/extensions/mcp/mcp-probe.js.map +1 -0
- package/dist/extensions/mcp/mcp-script-worker.mjs +130 -0
- package/dist/extensions/mcp/mcp-setup-panel.d.ts +146 -0
- package/dist/extensions/mcp/mcp-setup-panel.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-setup-panel.js +1104 -0
- package/dist/extensions/mcp/mcp-setup-panel.js.map +1 -0
- package/dist/extensions/mcp/mcp-status.d.ts +12 -0
- package/dist/extensions/mcp/mcp-status.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-status.js +98 -0
- package/dist/extensions/mcp/mcp-status.js.map +1 -0
- package/dist/extensions/mcp/mcp-trace.d.ts +95 -0
- package/dist/extensions/mcp/mcp-trace.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-trace.js +252 -0
- package/dist/extensions/mcp/mcp-trace.js.map +1 -0
- package/dist/extensions/mcp/metadata-cache.d.ts +20 -0
- package/dist/extensions/mcp/metadata-cache.d.ts.map +1 -0
- package/dist/extensions/mcp/metadata-cache.js +318 -0
- package/dist/extensions/mcp/metadata-cache.js.map +1 -0
- package/dist/extensions/mcp/npx-resolver.d.ts +7 -0
- package/dist/extensions/mcp/npx-resolver.d.ts.map +1 -0
- package/dist/extensions/mcp/npx-resolver.js +505 -0
- package/dist/extensions/mcp/npx-resolver.js.map +1 -0
- package/dist/extensions/mcp/oauth.d.ts +21 -0
- package/dist/extensions/mcp/oauth.d.ts.map +1 -0
- package/dist/extensions/mcp/oauth.js +15 -0
- package/dist/extensions/mcp/oauth.js.map +1 -0
- package/dist/extensions/mcp/onboarding-state.d.ts +13 -0
- package/dist/extensions/mcp/onboarding-state.d.ts.map +1 -0
- package/dist/extensions/mcp/onboarding-state.js +65 -0
- package/dist/extensions/mcp/onboarding-state.js.map +1 -0
- package/dist/extensions/mcp/package-mcp-loader.d.ts +3 -0
- package/dist/extensions/mcp/package-mcp-loader.d.ts.map +1 -0
- package/dist/extensions/mcp/package-mcp-loader.js +170 -0
- package/dist/extensions/mcp/package-mcp-loader.js.map +1 -0
- package/dist/extensions/mcp/panel-keys.d.ts +21 -0
- package/dist/extensions/mcp/panel-keys.d.ts.map +1 -0
- package/dist/extensions/mcp/panel-keys.js +29 -0
- package/dist/extensions/mcp/panel-keys.js.map +1 -0
- package/dist/extensions/mcp/prompts.d.ts +63 -0
- package/dist/extensions/mcp/prompts.d.ts.map +1 -0
- package/dist/extensions/mcp/prompts.js +297 -0
- package/dist/extensions/mcp/prompts.js.map +1 -0
- package/dist/extensions/mcp/proxy-modes.d.ts +15 -0
- package/dist/extensions/mcp/proxy-modes.d.ts.map +1 -0
- package/dist/extensions/mcp/proxy-modes.js +1421 -0
- package/dist/extensions/mcp/proxy-modes.js.map +1 -0
- package/dist/extensions/mcp/request-headers-command.d.ts +11 -0
- package/dist/extensions/mcp/request-headers-command.d.ts.map +1 -0
- package/dist/extensions/mcp/request-headers-command.js +334 -0
- package/dist/extensions/mcp/request-headers-command.js.map +1 -0
- package/dist/extensions/mcp/resource-tools.d.ts +2 -0
- package/dist/extensions/mcp/resource-tools.d.ts.map +1 -0
- package/dist/extensions/mcp/resource-tools.js +15 -0
- package/dist/extensions/mcp/resource-tools.js.map +1 -0
- package/dist/extensions/mcp/runtime-owner.d.ts +14 -0
- package/dist/extensions/mcp/runtime-owner.d.ts.map +1 -0
- package/dist/extensions/mcp/runtime-owner.js +84 -0
- package/dist/extensions/mcp/runtime-owner.js.map +1 -0
- package/dist/extensions/mcp/sampling-handler.d.ts +18 -0
- package/dist/extensions/mcp/sampling-handler.d.ts.map +1 -0
- package/dist/extensions/mcp/sampling-handler.js +229 -0
- package/dist/extensions/mcp/sampling-handler.js.map +1 -0
- package/dist/extensions/mcp/search-ranking.d.ts +25 -0
- package/dist/extensions/mcp/search-ranking.d.ts.map +1 -0
- package/dist/extensions/mcp/search-ranking.js +234 -0
- package/dist/extensions/mcp/search-ranking.js.map +1 -0
- package/dist/extensions/mcp/server-manager.d.ts +116 -0
- package/dist/extensions/mcp/server-manager.d.ts.map +1 -0
- package/dist/extensions/mcp/server-manager.js +1052 -0
- package/dist/extensions/mcp/server-manager.js.map +1 -0
- package/dist/extensions/mcp/session-recovery.d.ts +27 -0
- package/dist/extensions/mcp/session-recovery.d.ts.map +1 -0
- package/dist/extensions/mcp/session-recovery.js +140 -0
- package/dist/extensions/mcp/session-recovery.js.map +1 -0
- package/dist/extensions/mcp/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/extensions/mcp/state.d.ts +62 -0
- package/dist/extensions/mcp/state.d.ts.map +1 -0
- package/dist/extensions/mcp/state.js +2 -0
- package/dist/extensions/mcp/state.js.map +1 -0
- package/dist/extensions/mcp/tool-approval.d.ts +11 -0
- package/dist/extensions/mcp/tool-approval.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-approval.js +156 -0
- package/dist/extensions/mcp/tool-approval.js.map +1 -0
- package/dist/extensions/mcp/tool-metadata.d.ts +11 -0
- package/dist/extensions/mcp/tool-metadata.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-metadata.js +264 -0
- package/dist/extensions/mcp/tool-metadata.js.map +1 -0
- package/dist/extensions/mcp/tool-registrar.d.ts +21 -0
- package/dist/extensions/mcp/tool-registrar.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-registrar.js +229 -0
- package/dist/extensions/mcp/tool-registrar.js.map +1 -0
- package/dist/extensions/mcp/tool-result-renderer.d.ts +83 -0
- package/dist/extensions/mcp/tool-result-renderer.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-result-renderer.js +345 -0
- package/dist/extensions/mcp/tool-result-renderer.js.map +1 -0
- package/dist/extensions/mcp/ts-shape.d.ts +3 -0
- package/dist/extensions/mcp/ts-shape.d.ts.map +1 -0
- package/dist/extensions/mcp/ts-shape.js +160 -0
- package/dist/extensions/mcp/ts-shape.js.map +1 -0
- package/dist/extensions/mcp/types.d.ts +521 -0
- package/dist/extensions/mcp/types.d.ts.map +1 -0
- package/dist/extensions/mcp/types.js +294 -0
- package/dist/extensions/mcp/types.js.map +1 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.d.ts +7 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.js +37 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.js.map +1 -0
- package/dist/extensions/mcp/ui-resource-handler.d.ts +18 -0
- package/dist/extensions/mcp/ui-resource-handler.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-resource-handler.js +210 -0
- package/dist/extensions/mcp/ui-resource-handler.js.map +1 -0
- package/dist/extensions/mcp/ui-server.d.ts +52 -0
- package/dist/extensions/mcp/ui-server.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-server.js +740 -0
- package/dist/extensions/mcp/ui-server.js.map +1 -0
- package/dist/extensions/mcp/ui-session.d.ts +40 -0
- package/dist/extensions/mcp/ui-session.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-session.js +477 -0
- package/dist/extensions/mcp/ui-session.js.map +1 -0
- package/dist/extensions/mcp/ui-stream-types.d.ts +105 -0
- package/dist/extensions/mcp/ui-stream-types.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-stream-types.js +61 -0
- package/dist/extensions/mcp/ui-stream-types.js.map +1 -0
- package/dist/extensions/mcp/ui-tool-visibility.d.ts +5 -0
- package/dist/extensions/mcp/ui-tool-visibility.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-tool-visibility.js +27 -0
- package/dist/extensions/mcp/ui-tool-visibility.js.map +1 -0
- package/dist/extensions/mcp/unix-socket-transport.d.ts +15 -0
- package/dist/extensions/mcp/unix-socket-transport.d.ts.map +1 -0
- package/dist/extensions/mcp/unix-socket-transport.js +85 -0
- package/dist/extensions/mcp/unix-socket-transport.js.map +1 -0
- package/dist/extensions/mcp/utils.d.ts +32 -0
- package/dist/extensions/mcp/utils.d.ts.map +1 -0
- package/dist/extensions/mcp/utils.js +336 -0
- package/dist/extensions/mcp/utils.js.map +1 -0
- package/dist/extensions/subagent/index.d.ts +62 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +195 -9
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent-render.d.ts +3 -0
- package/dist/extensions/subagent-render.d.ts.map +1 -0
- package/dist/extensions/subagent-render.js +39 -0
- package/dist/extensions/subagent-render.js.map +1 -0
- package/dist/extensions/web-access.d.ts.map +1 -1
- package/dist/extensions/web-access.js +1 -1
- package/dist/extensions/web-access.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20992 -2003
- package/dist/index.js.map +1 -1
- package/dist/mcp-keyring-helper.cjs +89 -0
- package/dist/mcp-script-worker.mjs +130 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/response-separator.d.ts +1 -1
- package/dist/modes/interactive/components/response-separator.d.ts.map +1 -1
- package/dist/modes/interactive/components/response-separator.js +1 -1
- package/dist/modes/interactive/components/response-separator.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -2
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +14 -8
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/rpc-entry.js +20866 -1882
- package/dist/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/utils/hidden-spawn.d.ts +29 -0
- package/dist/utils/hidden-spawn.d.ts.map +1 -0
- package/dist/utils/hidden-spawn.js +101 -0
- package/dist/utils/hidden-spawn.js.map +1 -0
- package/dist/vendor/ai.js +110 -35
- package/docs/mcp.md +178 -0
- package/docs/pi-subagents.md +75 -0
- package/docs/quickstart.md +1 -1
- package/docs/usage.md +2 -1
- package/examples/extensions/pi-subagents-worker-policy.ts +86 -0
- package/native/win32/build.mjs +95 -0
- package/native/win32/prebuilds/win32-x64/hidden-spawn.exe +0 -0
- package/native/win32/src/hidden-spawn.c +157 -0
- package/npm-shrinkwrap.json +728 -6
- package/package.json +21 -6
- package/dist/extensions/mcp/client.d.ts +0 -86
- package/dist/extensions/mcp/client.d.ts.map +0 -1
- package/dist/extensions/mcp/client.js +0 -275
- package/dist/extensions/mcp/client.js.map +0 -1
package/docs/mcp.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# MCP
|
|
2
|
+
|
|
3
|
+
Nexus includes a native Model Context Protocol client. No extension package is required.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
|---------|-------------|
|
|
9
|
+
| `/mcp` | Open the server, connection, authentication, and direct-tool panel |
|
|
10
|
+
| `/mcp status` | Show text server status |
|
|
11
|
+
| `/mcp setup` | Discover existing configurations, import them, or add a known server |
|
|
12
|
+
| `/mcp reconnect [server]` | Reconnect one server or every server |
|
|
13
|
+
| `/mcp tools` | List discovered MCP tools |
|
|
14
|
+
| `/mcp prompts` | List MCP prompts and their generated slash commands |
|
|
15
|
+
| `/mcp enable <server>` | Enable a server through a project override |
|
|
16
|
+
| `/mcp disable <server>` | Disable a server through a project override |
|
|
17
|
+
| `/mcp logout <server>` | Remove stored OAuth credentials |
|
|
18
|
+
| `/mcp token status\|remove <server>` | Inspect or remove an OS-stored bearer token |
|
|
19
|
+
| `/mcp-auth [server]` | Open OAuth management or authenticate one server |
|
|
20
|
+
|
|
21
|
+
Project configuration and project overrides are available only in trusted projects. Global MCP remains available in untrusted projects.
|
|
22
|
+
|
|
23
|
+
## Configuration
|
|
24
|
+
|
|
25
|
+
Nexus loads configuration in this order; later definitions override earlier definitions with the same server name:
|
|
26
|
+
|
|
27
|
+
1. `~/.config/nexus/mcp.json`
|
|
28
|
+
2. `.nexus/mcp.json` for trusted projects
|
|
29
|
+
|
|
30
|
+
Both files use an `mcpServers` object and optional `settings` and `imports` fields.
|
|
31
|
+
|
|
32
|
+
### Local stdio server
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"filesystem": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
|
|
40
|
+
"env": {
|
|
41
|
+
"LOG_LEVEL": "info"
|
|
42
|
+
},
|
|
43
|
+
"lifecycle": "lazy"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Hosted HTTP server with OAuth
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"notion": {
|
|
55
|
+
"url": "https://mcp.notion.com/mcp",
|
|
56
|
+
"auth": "oauth",
|
|
57
|
+
"protocolVersion": "auto"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Bearer authentication
|
|
64
|
+
|
|
65
|
+
Prefer an environment variable instead of storing a token in JSON:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"internal": {
|
|
71
|
+
"url": "https://mcp.example.com/mcp",
|
|
72
|
+
"auth": "bearer",
|
|
73
|
+
"bearerTokenEnv": "INTERNAL_MCP_TOKEN"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Header and environment values support `${NAME}`, `$env:NAME`, and `{env:NAME}` interpolation. A value beginning with `!` executes a trusted command and uses its output as the secret; `!!` escapes a literal leading `!`.
|
|
80
|
+
|
|
81
|
+
### Import another client’s configuration
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"imports": ["cursor", "claude-code", "codex", "opencode", "vscode"],
|
|
86
|
+
"mcpServers": {}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Imports are explicit. Nexus never requires another client or package at runtime.
|
|
91
|
+
|
|
92
|
+
## Server options
|
|
93
|
+
|
|
94
|
+
Common server fields include:
|
|
95
|
+
|
|
96
|
+
- Transport: `command`, `args`, `env`, `cwd`, `url`, `headers`, or `socket`
|
|
97
|
+
- Authentication: `auth`, `oauth`, `bearerTokenEnv`, `bearerTokenStore`, `requestHeadersCommand`
|
|
98
|
+
- Lifecycle: `lazy`, `eager`, `keep-alive`, or `lazy-keep-alive`
|
|
99
|
+
- Discovery: `includeTools`, `excludeTools`, `exposeResources`, `searchKeywords`
|
|
100
|
+
- Tool surface: `directTools`, `toolPrefix`, `approveTools`
|
|
101
|
+
- Runtime: `idleTimeout`, `requestTimeoutMs`, `protocolVersion`, `debug`, `trace`
|
|
102
|
+
- State: `disabled: true`
|
|
103
|
+
|
|
104
|
+
Only one transport—`command`, `url`, or `socket`—may be configured per server.
|
|
105
|
+
|
|
106
|
+
## Tool surfaces
|
|
107
|
+
|
|
108
|
+
Nexus always provides the `mcp` gateway tool for status, discovery, descriptions, authentication, connections, and individual calls. It also provides `mcpScript`, a bounded worker for multi-call JavaScript orchestration.
|
|
109
|
+
|
|
110
|
+
Frequently used MCP tools can be registered directly:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"mcpServers": {
|
|
115
|
+
"github": {
|
|
116
|
+
"url": "https://example.com/mcp",
|
|
117
|
+
"directTools": ["search_issues", "get_issue"]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"settings": {
|
|
121
|
+
"toolPrefix": "server"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Direct-tool metadata is cached and refreshed when servers reconnect or publish list-change notifications. The `/mcp` panel can enable direct tools without restarting the current session.
|
|
127
|
+
|
|
128
|
+
## Protocol capabilities
|
|
129
|
+
|
|
130
|
+
The native runtime supports:
|
|
131
|
+
|
|
132
|
+
- stdio, Streamable HTTP, legacy SSE fallback, and Unix-domain sockets
|
|
133
|
+
- modern protocol negotiation with legacy compatibility
|
|
134
|
+
- tools, resources, prompts, server instructions, and list-change notifications
|
|
135
|
+
- OAuth 2.1 with PKCE, dynamic client registration, client credentials, and manual remote completion
|
|
136
|
+
- secure OS credential storage for OAuth and optional bearer tokens
|
|
137
|
+
- MCP sampling with user approval
|
|
138
|
+
- form and URL elicitation
|
|
139
|
+
- MCP Apps/AppBridge resources in a sandboxed local viewer
|
|
140
|
+
- bounded output with private spill files
|
|
141
|
+
- lazy startup, idle shutdown, keep-alive recovery, and stale-session reconnection
|
|
142
|
+
- per-tool approval gates and metadata-only protocol tracing
|
|
143
|
+
|
|
144
|
+
Connection failures are non-fatal: Nexus reports the failed server and continues with the remaining tools.
|
|
145
|
+
|
|
146
|
+
## Settings
|
|
147
|
+
|
|
148
|
+
Useful top-level settings include:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"settings": {
|
|
153
|
+
"directTools": false,
|
|
154
|
+
"scriptMode": true,
|
|
155
|
+
"autoAuth": false,
|
|
156
|
+
"sampling": true,
|
|
157
|
+
"elicitation": true,
|
|
158
|
+
"idleTimeout": 10,
|
|
159
|
+
"mcpFooterStatus": "full",
|
|
160
|
+
"outputGuard": true,
|
|
161
|
+
"toolResultRendering": "compact"
|
|
162
|
+
},
|
|
163
|
+
"mcpServers": {}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Environment controls
|
|
168
|
+
|
|
169
|
+
| Variable | Purpose |
|
|
170
|
+
|----------|---------|
|
|
171
|
+
| `MCP_DIRECT_TOOLS` | Override direct-tool selection; use `__none__` to disable it |
|
|
172
|
+
| `MCP_OUTPUT_GUARD` | Enable or disable bounded MCP output |
|
|
173
|
+
| `MCP_OAUTH_CALLBACK_PORT` | Set the local OAuth callback port |
|
|
174
|
+
| `MCP_OAUTH_DIR` | Legacy plaintext credential import directory only |
|
|
175
|
+
| `MCP_UI_VIEWER` | Select `browser`, `glimpse`, or `none` |
|
|
176
|
+
| `MCP_UI_DEBUG` | Enable MCP UI debug logging |
|
|
177
|
+
|
|
178
|
+
Nexus consumes MCP servers; it does not expose Nexus itself as an MCP server.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Subagents (bundled pi-subagents) with worker-scope billing
|
|
2
|
+
|
|
3
|
+
Nexus ships [pi-subagents](https://github.com/nicobailon/pi-subagents) inside the CLI.
|
|
4
|
+
Nothing to install: every session has the `subagent` tool, the built-in agents
|
|
5
|
+
(`scout`, `researcher`, `worker`, `reviewer`, `oracle`, `delegate`), the fleet view,
|
|
6
|
+
and the `/parallel-research`, `/review-loop` and `/council` workflows.
|
|
7
|
+
|
|
8
|
+
## Two-tier billing, automatically
|
|
9
|
+
|
|
10
|
+
The orchestrator (your session) bills the Hub's **orchestrator** deployment. Every
|
|
11
|
+
subagent child bills the **worker** deployment, because the CLI marks each child
|
|
12
|
+
spawned by pi-subagents as a delegated worker: the child self-mints a one-time worker
|
|
13
|
+
grant per model turn (`POST /llm/worker-grants`) and the gateway consumes it and
|
|
14
|
+
reserves the request as `worker`. Minting is fail-closed — a child whose grant is
|
|
15
|
+
missing sends an invalid sentinel and the gateway rejects the request, so a child can
|
|
16
|
+
never silently bill as orchestrator.
|
|
17
|
+
|
|
18
|
+
Agents listed in `NEXUS_BIG_MODEL_AGENTS` (default `oracle`) are deliberately left
|
|
19
|
+
unmarked and bill the orchestrator deployment. That is the escalation path: ask
|
|
20
|
+
`oracle` when a subagent needs the big model.
|
|
21
|
+
|
|
22
|
+
Model identity stays server-side in the Hub's experiment groups; swapping deployments
|
|
23
|
+
never touches agent configuration.
|
|
24
|
+
|
|
25
|
+
## Orchestrator policy
|
|
26
|
+
|
|
27
|
+
With bundled subagents active, the orchestrator session:
|
|
28
|
+
|
|
29
|
+
- **cannot run `bash`, `write`, or `edit` directly** — implementation, shell, tests and
|
|
30
|
+
long tool loops go through `subagent` (this is the cost guarantee);
|
|
31
|
+
- keeps **unlimited** direct reads, greps and GitNexus graph queries;
|
|
32
|
+
- is told to fan out `scout`/`researcher` subagents (or `/parallel-research`) for
|
|
33
|
+
broad research and to run long investigations in the background.
|
|
34
|
+
|
|
35
|
+
`NEXUS_PARENT_POLICY=off` restores direct mutating tools for one session.
|
|
36
|
+
|
|
37
|
+
## Limits follow pi-subagents
|
|
38
|
+
|
|
39
|
+
No concurrency, spawn, or timeout limits are layered on top of pi-subagents: its own
|
|
40
|
+
defaults apply (20 concurrent children per run, 4 per parallel group, 64 spawns per
|
|
41
|
+
run, 30-minute run deadline). Capacity is the Hub's concern — the gateway caps in-flight
|
|
42
|
+
requests per user by role (orchestrator and worker separately), so a fan-out of cheap
|
|
43
|
+
workers never competes with the orchestrator's own turn.
|
|
44
|
+
|
|
45
|
+
The web search tool is registered under pi-web-access's canonical name `web_search`,
|
|
46
|
+
so pi-subagents' builtin `researcher` and any other pi package that expects it work
|
|
47
|
+
unmodified.
|
|
48
|
+
|
|
49
|
+
## Legacy `delegate_task`
|
|
50
|
+
|
|
51
|
+
The Hub-driven `delegate_task` worker is no longer registered by default. Set
|
|
52
|
+
`NEXUS_DELEGATION_MODE=internal` to get it back (its 5-minute worker timeout and
|
|
53
|
+
single-worker cap apply there).
|
|
54
|
+
|
|
55
|
+
## Environment knobs
|
|
56
|
+
|
|
57
|
+
| Variable | Default | Effect |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `NEXUS_DELEGATION_MODE` | `external` | `internal` re-enables `delegate_task` instead of bundled subagents. |
|
|
60
|
+
| `NEXUS_BUNDLED_PACKAGES` | on | `off` stops loading CLI-bundled packages (pi-subagents) and flips delegation to internal. |
|
|
61
|
+
| `NEXUS_BIG_MODEL_AGENTS` | `oracle` | Comma-separated agents that bill the orchestrator deployment. Empty string puts every agent on the worker deployment. |
|
|
62
|
+
| `NEXUS_WORKER_SCOPE` | on | `off` leaves all children on the orchestrator deployment. |
|
|
63
|
+
| `NEXUS_PARENT_POLICY` | on | `off` lets the orchestrator run bash/write/edit directly. |
|
|
64
|
+
| `NEXUS_SUBAGENT_BINARY` | this CLI | Executable pi-subagents spawns for children (alias of `PI_SUBAGENT_PI_BINARY`). Any `NEXUS_SUBAGENT_X` maps to `PI_SUBAGENT_X`; explicit `PI_*` wins. |
|
|
65
|
+
|
|
66
|
+
A user-installed `npm:pi-subagents` package (project or global) replaces the bundled
|
|
67
|
+
copy, so pinning a different version still works.
|
|
68
|
+
|
|
69
|
+
## Verification
|
|
70
|
+
|
|
71
|
+
`test/suite/bundled-subagents.test.ts` covers child marking, tiering, the binary
|
|
72
|
+
default and the orchestrator policy; `test/suite/worker-scope-stub-hub.test.ts` drives
|
|
73
|
+
a stub Hub end to end and asserts the exact grant/scope headers per persona.
|
|
74
|
+
`scripts/nexus-subagent-worker` remains as an optional wrapper for builds that cannot
|
|
75
|
+
mark children in-process.
|
package/docs/quickstart.md
CHANGED
|
@@ -47,7 +47,7 @@ GitNexus credentials are stored in `~/.config/nexus/auth.json`.
|
|
|
47
47
|
|
|
48
48
|
## Configure a model provider
|
|
49
49
|
|
|
50
|
-
Nexus supports provider subscriptions
|
|
50
|
+
Nexus supports other provider subscriptions and API keys through `/byok`.
|
|
51
51
|
|
|
52
52
|
### Option 1: subscription or stored API key
|
|
53
53
|
|
package/docs/usage.md
CHANGED
|
@@ -37,10 +37,11 @@ Type `/` in the editor to open command completion. Extensions can register custo
|
|
|
37
37
|
| Command | Description |
|
|
38
38
|
|---------|-------------|
|
|
39
39
|
| `/login` | Sign in to GitNexus |
|
|
40
|
-
| `/byok [provider
|
|
40
|
+
| `/byok [provider]` | Use another subscription or cloud provider |
|
|
41
41
|
| `/logout` | Remove stored model-provider credentials |
|
|
42
42
|
| `/gitnexus-status` | Show the GitNexus connection status |
|
|
43
43
|
| [`/llama`](llama-cpp.md) | Download, load, and unload llama.cpp router models |
|
|
44
|
+
| `/nexus-agent` | Switch back to Nexus Agent |
|
|
44
45
|
| `/model` | Switch models |
|
|
45
46
|
| `/scoped-models` | Enable/disable models for Ctrl+P cycling |
|
|
46
47
|
| `/settings` | Thinking level, theme, message delivery, transport |
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* worker-policy — parent-session delegation policy for the pi-subagents swap.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the old delegate_task parent gating (review-only allowlist + 8-call
|
|
5
|
+
* read budget) with the tuning we settled on:
|
|
6
|
+
* - HARD-block mutating tools on the orchestrator (bash/write/edit): all
|
|
7
|
+
* implementation goes through the `subagent` tool.
|
|
8
|
+
* - NO read budget: reads, greps and gitnexus graph calls are cheap on
|
|
9
|
+
* cached input and capping them measurably hurt output quality.
|
|
10
|
+
* - Prompt-level steering for everything else.
|
|
11
|
+
*
|
|
12
|
+
* Scope guards: the policy applies only to the top-level orchestrator session
|
|
13
|
+
* on the gitnexus/auto model. It must never fire inside delegated workers or
|
|
14
|
+
* pi-subagents children (they do the mutating work), and NEXUS_PARENT_POLICY=off
|
|
15
|
+
* disables it entirely.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Nexus-branded env aliases: users configure NEXUS_SUBAGENT_*; we map them
|
|
19
|
+
// onto the PI_SUBAGENT_* names the upstream pi-subagents package reads.
|
|
20
|
+
// Explicit PI_* values win (they are the wire format, aliases are sugar).
|
|
21
|
+
if (process.env.NEXUS_SUBAGENT_BINARY?.trim() && !process.env.PI_SUBAGENT_PI_BINARY?.trim()) {
|
|
22
|
+
process.env.PI_SUBAGENT_PI_BINARY = process.env.NEXUS_SUBAGENT_BINARY;
|
|
23
|
+
}
|
|
24
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
25
|
+
if (!key.startsWith("NEXUS_SUBAGENT_") || key === "NEXUS_SUBAGENT_BINARY" || !value?.trim()) continue;
|
|
26
|
+
const target = `PI_SUBAGENT_${key.slice("NEXUS_SUBAGENT_".length)}`;
|
|
27
|
+
if (!process.env[target]?.trim()) process.env[target] = value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Self-contained activation: plain `nexus` in this repo gets worker-scope
|
|
31
|
+
// billing with no shell setup. Explicit env always wins over these defaults.
|
|
32
|
+
const WORKER_WRAPPER = `${process.env.HOME}/.local/bin/nexus-subagent-worker`;
|
|
33
|
+
if (!process.env.PI_SUBAGENT_PI_BINARY?.trim()) {
|
|
34
|
+
process.env.PI_SUBAGENT_PI_BINARY = WORKER_WRAPPER;
|
|
35
|
+
}
|
|
36
|
+
if (!process.env.NEXUS_BIG_MODEL_AGENTS?.trim()) {
|
|
37
|
+
process.env.NEXUS_BIG_MODEL_AGENTS = "oracle";
|
|
38
|
+
}
|
|
39
|
+
if (!process.env.NEXUS_DELEGATION_MODE?.trim()) {
|
|
40
|
+
process.env.NEXUS_DELEGATION_MODE = "external";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const BLOCKED_PARENT_TOOLS = new Set(["bash", "write", "edit", "delegate_task"]);
|
|
44
|
+
|
|
45
|
+
const POLICY_PROMPT = [
|
|
46
|
+
"",
|
|
47
|
+
"Delegation policy: you are the orchestrator. Perform implementation, mutation,",
|
|
48
|
+
"shell commands, tests, and long repetitive tool loops through the `subagent`",
|
|
49
|
+
"tool (worker/reviewer/scout agents). Direct bash/write/edit are disabled in",
|
|
50
|
+
"this session. Reading files and querying the GitNexus graph directly is fine",
|
|
51
|
+
"and unlimited — prefer graph queries (gitnexus_query/context/impact) to locate",
|
|
52
|
+
"code before delegating. Keep planning, user communication, and final review here.",
|
|
53
|
+
].join("\n");
|
|
54
|
+
|
|
55
|
+
function isAuto(model: { provider?: string; id?: string } | undefined): boolean {
|
|
56
|
+
return model?.provider === "gitnexus" && model?.id === "auto";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function policyDisabled(): boolean {
|
|
60
|
+
return (
|
|
61
|
+
process.env.NEXUS_PARENT_POLICY === "off" ||
|
|
62
|
+
process.env.NEXUS_INTERNAL_DELEGATED_WORKER === "1" ||
|
|
63
|
+
Boolean(process.env.PI_SUBAGENT_CHILD_AGENT?.trim())
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default function workerPolicy(pi: any) {
|
|
68
|
+
if (policyDisabled()) return;
|
|
69
|
+
|
|
70
|
+
pi.on("before_agent_start", (event: any) => {
|
|
71
|
+
if (policyDisabled()) return;
|
|
72
|
+
return { systemPrompt: `${event.systemPrompt}\n${POLICY_PROMPT}` };
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
pi.on("tool_call", (event: any, ctx: any) => {
|
|
76
|
+
if (policyDisabled() || !isAuto(ctx?.model)) return;
|
|
77
|
+
if (!BLOCKED_PARENT_TOOLS.has(event.toolName)) return;
|
|
78
|
+
return {
|
|
79
|
+
block: true,
|
|
80
|
+
reason:
|
|
81
|
+
"This orchestrator session does not run mutating tools directly. " +
|
|
82
|
+
"Use the `subagent` tool (worker for implementation, reviewer for checks, " +
|
|
83
|
+
"scout for exploration) to execute this, then review its report.",
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const sourceFile = path.join(scriptDir, "src", "hidden-spawn.c");
|
|
9
|
+
const hostArch = process.arch === "arm64" ? "arm64" : "x64";
|
|
10
|
+
const temporaryDir = mkdtempSync(path.join(tmpdir(), "nexus-hidden-spawn-"));
|
|
11
|
+
|
|
12
|
+
function removeTemporaryDir() {
|
|
13
|
+
rmSync(temporaryDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
process.on("exit", removeTemporaryDir);
|
|
17
|
+
|
|
18
|
+
function quoteBatch(value) {
|
|
19
|
+
return `"${value.replaceAll('"', '""')}"`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function findVisualStudioDevCmd() {
|
|
23
|
+
const candidates = [];
|
|
24
|
+
const programFilesX86 = process.env["ProgramFiles(x86)"];
|
|
25
|
+
if (programFilesX86) {
|
|
26
|
+
const vswhere = path.join(programFilesX86, "Microsoft Visual Studio", "Installer", "vswhere.exe");
|
|
27
|
+
if (existsSync(vswhere)) {
|
|
28
|
+
const result = spawnSync(
|
|
29
|
+
vswhere,
|
|
30
|
+
["-latest", "-products", "*", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath"],
|
|
31
|
+
{ encoding: "utf8" },
|
|
32
|
+
);
|
|
33
|
+
for (const line of (result.stdout ?? "").split(/\r?\n/)) {
|
|
34
|
+
const installationPath = line.trim();
|
|
35
|
+
if (installationPath) candidates.push(path.join(installationPath, "Common7", "Tools", "VsDevCmd.bat"));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const base of [process.env.ProgramFiles, programFilesX86]) {
|
|
40
|
+
if (!base) continue;
|
|
41
|
+
for (const edition of ["BuildTools", "Community", "Professional", "Enterprise"]) {
|
|
42
|
+
candidates.push(path.join(base, "Microsoft Visual Studio", "2022", edition, "Common7", "Tools", "VsDevCmd.bat"));
|
|
43
|
+
candidates.push(path.join(base, "Microsoft Visual Studio", "18", edition, "Common7", "Tools", "VsDevCmd.bat"));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return candidates.find((candidate) => existsSync(candidate));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const vsDevCmd = findVisualStudioDevCmd();
|
|
50
|
+
if (!vsDevCmd) {
|
|
51
|
+
throw new Error("Microsoft C++ Build Tools are required to build hidden-spawn.exe (VsDevCmd.bat not found).");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const buildDir = path.join(temporaryDir, "msvc");
|
|
55
|
+
const temporaryOutput = path.join(buildDir, "hidden-spawn.exe");
|
|
56
|
+
mkdirSync(buildDir, { recursive: true });
|
|
57
|
+
const batchFile = path.join(buildDir, "build.cmd");
|
|
58
|
+
const msvcArch = hostArch === "arm64" ? "arm64" : "x64";
|
|
59
|
+
writeFileSync(
|
|
60
|
+
batchFile,
|
|
61
|
+
[
|
|
62
|
+
"@echo off",
|
|
63
|
+
`call ${quoteBatch(vsDevCmd)} -no_logo -arch=${msvcArch} -host_arch=${msvcArch}`,
|
|
64
|
+
"if errorlevel 1 exit /b %errorlevel%",
|
|
65
|
+
[
|
|
66
|
+
"cl",
|
|
67
|
+
"/nologo",
|
|
68
|
+
"/TC",
|
|
69
|
+
"/W4",
|
|
70
|
+
"/O1",
|
|
71
|
+
"/GS-",
|
|
72
|
+
`/Fe:${quoteBatch(temporaryOutput)}`,
|
|
73
|
+
quoteBatch(sourceFile),
|
|
74
|
+
"/link",
|
|
75
|
+
"/SUBSYSTEM:WINDOWS",
|
|
76
|
+
"/ENTRY:entry",
|
|
77
|
+
"/NODEFAULTLIB",
|
|
78
|
+
"kernel32.lib",
|
|
79
|
+
"/OPT:REF",
|
|
80
|
+
"/OPT:ICF",
|
|
81
|
+
].join(" "),
|
|
82
|
+
"if errorlevel 1 exit /b %errorlevel%",
|
|
83
|
+
].join("\r\n"),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const result = spawnSync("cmd.exe", ["/d", "/s", "/c", batchFile], { cwd: buildDir, stdio: "inherit" });
|
|
87
|
+
if (result.error) throw result.error;
|
|
88
|
+
if (result.status !== 0) throw new Error(`cl.exe failed with exit code ${result.status ?? 1}`);
|
|
89
|
+
|
|
90
|
+
const outputDir = path.join(scriptDir, "prebuilds", `win32-${hostArch}`);
|
|
91
|
+
mkdirSync(outputDir, { recursive: true });
|
|
92
|
+
const output = path.join(outputDir, "hidden-spawn.exe");
|
|
93
|
+
copyFileSync(temporaryOutput, output);
|
|
94
|
+
chmodSync(output, 0o755);
|
|
95
|
+
console.log(`Built ${output}`);
|
|
Binary file
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Windowless relauncher for Nexus child processes on Windows.
|
|
3
|
+
*
|
|
4
|
+
* Node's windowsHide flag asks libuv to both CREATE_NO_WINDOW and SW_HIDE.
|
|
5
|
+
* SW_HIDE runs after the console window has already been created, so a
|
|
6
|
+
* console-subsystem child (node.exe, nexus.exe) flashes for a frame. This
|
|
7
|
+
* process is itself built as SUBSYSTEM:WINDOWS, so spawning it allocates no
|
|
8
|
+
* console. It then starts the real CLI with CREATE_NO_WINDOW and without
|
|
9
|
+
* STARTF_USESHOWWINDOW, forwarding the stdio handles it was given.
|
|
10
|
+
*
|
|
11
|
+
* No C runtime: the only import is kernel32.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#include <windows.h>
|
|
15
|
+
|
|
16
|
+
#define CREATE_NO_WINDOW 0x08000000
|
|
17
|
+
|
|
18
|
+
static void zero_bytes(void *memory, size_t size) {
|
|
19
|
+
unsigned char *bytes = (unsigned char *)memory;
|
|
20
|
+
for (size_t index = 0; index < size; index++) bytes[index] = 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* The compiler emits memset for struct clears. Provide it so /NODEFAULTLIB still links. */
|
|
24
|
+
void *memset(void *destination, int value, size_t count) {
|
|
25
|
+
unsigned char *bytes = (unsigned char *)destination;
|
|
26
|
+
while (count-- > 0) *bytes++ = (unsigned char)value;
|
|
27
|
+
return destination;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static void *heap_alloc(size_t bytes) {
|
|
31
|
+
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytes);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static void make_inheritable(HANDLE handle) {
|
|
35
|
+
if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
|
|
36
|
+
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Skip the image name libuv placed at the front of this process's command line. */
|
|
41
|
+
static const wchar_t *skip_argv0(const wchar_t *command) {
|
|
42
|
+
if (*command == L'"') {
|
|
43
|
+
command++;
|
|
44
|
+
while (*command != L'\0' && *command != L'"') command++;
|
|
45
|
+
if (*command == L'"') command++;
|
|
46
|
+
} else {
|
|
47
|
+
while (*command != L'\0' && *command != L' ' && *command != L'\t') command++;
|
|
48
|
+
}
|
|
49
|
+
while (*command == L' ' || *command == L'\t') command++;
|
|
50
|
+
return command;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static int append_quoted(wchar_t **cursor, wchar_t *end, const wchar_t *value) {
|
|
54
|
+
wchar_t *write = *cursor;
|
|
55
|
+
if (write >= end) return 0;
|
|
56
|
+
*write++ = L'"';
|
|
57
|
+
while (*value != L'\0') {
|
|
58
|
+
if (write >= end - 1) return 0;
|
|
59
|
+
*write++ = *value++;
|
|
60
|
+
}
|
|
61
|
+
if (write >= end) return 0;
|
|
62
|
+
*write++ = L'"';
|
|
63
|
+
*cursor = write;
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static int append_raw(wchar_t **cursor, wchar_t *end, const wchar_t *value) {
|
|
68
|
+
wchar_t *write = *cursor;
|
|
69
|
+
while (*value != L'\0') {
|
|
70
|
+
if (write >= end) return 0;
|
|
71
|
+
*write++ = *value++;
|
|
72
|
+
}
|
|
73
|
+
*cursor = write;
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static DWORD read_env(const wchar_t *name, wchar_t *buffer, DWORD capacity) {
|
|
78
|
+
DWORD length = GetEnvironmentVariableW(name, buffer, capacity);
|
|
79
|
+
if (length == 0 || length >= capacity) return 0;
|
|
80
|
+
return length;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static DWORD run(void) {
|
|
84
|
+
wchar_t *target;
|
|
85
|
+
wchar_t *script;
|
|
86
|
+
wchar_t *command_line;
|
|
87
|
+
const wchar_t *tail;
|
|
88
|
+
wchar_t *cursor;
|
|
89
|
+
wchar_t *end;
|
|
90
|
+
STARTUPINFOW startup;
|
|
91
|
+
PROCESS_INFORMATION process;
|
|
92
|
+
HANDLE job;
|
|
93
|
+
JOBOBJECT_EXTENDED_LIMIT_INFORMATION limits;
|
|
94
|
+
DWORD flags;
|
|
95
|
+
DWORD exit_code = 1;
|
|
96
|
+
int have_script;
|
|
97
|
+
|
|
98
|
+
target = (wchar_t *)heap_alloc(32768 * sizeof(wchar_t));
|
|
99
|
+
script = (wchar_t *)heap_alloc(32768 * sizeof(wchar_t));
|
|
100
|
+
command_line = (wchar_t *)heap_alloc(32768 * sizeof(wchar_t));
|
|
101
|
+
if (target == NULL || script == NULL || command_line == NULL) return 1;
|
|
102
|
+
|
|
103
|
+
if (read_env(L"NEXUS_HIDDEN_SPAWN_TARGET", target, 32768) == 0) return 1;
|
|
104
|
+
have_script = read_env(L"NEXUS_HIDDEN_SPAWN_SCRIPT", script, 32768) != 0;
|
|
105
|
+
tail = skip_argv0(GetCommandLineW());
|
|
106
|
+
|
|
107
|
+
cursor = command_line;
|
|
108
|
+
end = command_line + 32767;
|
|
109
|
+
if (!append_quoted(&cursor, end, target)) return 1;
|
|
110
|
+
if (have_script) {
|
|
111
|
+
if (!append_raw(&cursor, end, L" ")) return 1;
|
|
112
|
+
if (!append_quoted(&cursor, end, script)) return 1;
|
|
113
|
+
}
|
|
114
|
+
if (*tail != L'\0') {
|
|
115
|
+
if (!append_raw(&cursor, end, L" ")) return 1;
|
|
116
|
+
if (!append_raw(&cursor, end, tail)) return 1;
|
|
117
|
+
}
|
|
118
|
+
if (cursor >= end) return 1;
|
|
119
|
+
*cursor = L'\0';
|
|
120
|
+
|
|
121
|
+
zero_bytes(&startup, sizeof startup);
|
|
122
|
+
startup.cb = sizeof startup;
|
|
123
|
+
startup.dwFlags = STARTF_USESTDHANDLES;
|
|
124
|
+
startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
125
|
+
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
126
|
+
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
|
127
|
+
make_inheritable(startup.hStdInput);
|
|
128
|
+
make_inheritable(startup.hStdOutput);
|
|
129
|
+
make_inheritable(startup.hStdError);
|
|
130
|
+
|
|
131
|
+
zero_bytes(&process, sizeof process);
|
|
132
|
+
flags = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED;
|
|
133
|
+
if (!CreateProcessW(target, command_line, NULL, NULL, TRUE, flags, NULL, NULL, &startup, &process)) {
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
job = CreateJobObjectW(NULL, NULL);
|
|
138
|
+
if (job != NULL) {
|
|
139
|
+
zero_bytes(&limits, sizeof limits);
|
|
140
|
+
limits.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
|
141
|
+
if (SetInformationJobObject(job, JobObjectExtendedLimitInformation, &limits, sizeof limits)) {
|
|
142
|
+
AssignProcessToJobObject(job, process.hProcess);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
ResumeThread(process.hThread);
|
|
147
|
+
WaitForSingleObject(process.hProcess, INFINITE);
|
|
148
|
+
if (!GetExitCodeProcess(process.hProcess, &exit_code)) exit_code = 1;
|
|
149
|
+
CloseHandle(process.hThread);
|
|
150
|
+
CloseHandle(process.hProcess);
|
|
151
|
+
if (job != NULL) CloseHandle(job);
|
|
152
|
+
return exit_code;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
void entry(void) {
|
|
156
|
+
ExitProcess(run());
|
|
157
|
+
}
|