@akon-labs/nexus-cli 0.1.0
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 +5342 -0
- package/LICENSE +22 -0
- package/README.md +677 -0
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +11 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/bun/restore-sandbox-env.d.ts +17 -0
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
- package/dist/bun/restore-sandbox-env.js +36 -0
- package/dist/bun/restore-sandbox-env.js.map +1 -0
- package/dist/cli/args.d.ts +59 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +408 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config-selector.d.ts +16 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/credential-print.d.ts +23 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +118 -0
- package/dist/cli/credential-print.js.map +1 -0
- package/dist/cli/experimental/auth.d.ts +16 -0
- package/dist/cli/experimental/auth.d.ts.map +1 -0
- package/dist/cli/experimental/auth.js +13 -0
- package/dist/cli/experimental/auth.js.map +1 -0
- package/dist/cli/experimental/cli.d.ts +6 -0
- package/dist/cli/experimental/cli.d.ts.map +1 -0
- package/dist/cli/experimental/cli.js +5 -0
- package/dist/cli/experimental/cli.js.map +1 -0
- package/dist/cli/experimental/command-options.d.ts +17 -0
- package/dist/cli/experimental/command-options.d.ts.map +1 -0
- package/dist/cli/experimental/command-options.js +35 -0
- package/dist/cli/experimental/command-options.js.map +1 -0
- package/dist/cli/experimental/command.d.ts +63 -0
- package/dist/cli/experimental/command.d.ts.map +1 -0
- package/dist/cli/experimental/command.js +130 -0
- package/dist/cli/experimental/command.js.map +1 -0
- package/dist/cli/experimental/commands/client.d.ts +13 -0
- package/dist/cli/experimental/commands/client.d.ts.map +1 -0
- package/dist/cli/experimental/commands/client.js +25 -0
- package/dist/cli/experimental/commands/client.js.map +1 -0
- package/dist/cli/experimental/commands/pi.d.ts +15 -0
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
- package/dist/cli/experimental/commands/pi.js +28 -0
- package/dist/cli/experimental/commands/pi.js.map +1 -0
- package/dist/cli/experimental/commands/server.d.ts +13 -0
- package/dist/cli/experimental/commands/server.d.ts.map +1 -0
- package/dist/cli/experimental/commands/server.js +25 -0
- package/dist/cli/experimental/commands/server.js.map +1 -0
- package/dist/cli/experimental/transport-address.d.ts +10 -0
- package/dist/cli/experimental/transport-address.d.ts.map +1 -0
- package/dist/cli/experimental/transport-address.js +38 -0
- package/dist/cli/experimental/transport-address.js.map +1 -0
- package/dist/cli/file-processor.d.ts +15 -0
- package/dist/cli/file-processor.d.ts.map +1 -0
- package/dist/cli/file-processor.js +70 -0
- package/dist/cli/file-processor.js.map +1 -0
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli/list-models.d.ts +9 -0
- package/dist/cli/list-models.d.ts.map +1 -0
- package/dist/cli/list-models.js +98 -0
- package/dist/cli/list-models.js.map +1 -0
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +48 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/require-login.d.ts +30 -0
- package/dist/cli/require-login.d.ts.map +1 -0
- package/dist/cli/require-login.js +96 -0
- package/dist/cli/require-login.js.map +1 -0
- package/dist/cli/session-picker.d.ts +10 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +36 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/startup-ui.d.ts +20 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +185 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +69740 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +425 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote-session.d.ts +53 -0
- package/dist/client/remote-session.d.ts.map +1 -0
- package/dist/client/remote-session.js +340 -0
- package/dist/client/remote-session.js.map +1 -0
- package/dist/client/transcript.d.ts +12 -0
- package/dist/client/transcript.d.ts.map +1 -0
- package/dist/client/transcript.js +98 -0
- package/dist/client/transcript.js.map +1 -0
- package/dist/config.d.ts +99 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +482 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +119 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +309 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +134 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +644 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2687 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-guidance.d.ts +5 -0
- package/dist/core/auth-guidance.d.ts.map +1 -0
- package/dist/core/auth-guidance.js +39 -0
- package/dist/core/auth-guidance.js.map +1 -0
- package/dist/core/auth-storage.d.ts +62 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +350 -0
- package/dist/core/auth-storage.js.map +1 -0
- package/dist/core/bash-executor.d.ts +32 -0
- package/dist/core/bash-executor.d.ts.map +1 -0
- package/dist/core/bash-executor.js +111 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/cache-stats.d.ts +49 -0
- package/dist/core/cache-stats.d.ts.map +1 -0
- package/dist/core/cache-stats.js +101 -0
- package/dist/core/cache-stats.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +98 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +246 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +137 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +645 -0
- package/dist/core/compaction/compaction.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.d.ts.map +1 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/index.js.map +1 -0
- package/dist/core/compaction/utils.d.ts +38 -0
- package/dist/core/compaction/utils.d.ts.map +1 -0
- package/dist/core/compaction/utils.js +142 -0
- package/dist/core/compaction/utils.js.map +1 -0
- package/dist/core/defaults.d.ts +3 -0
- package/dist/core/defaults.d.ts.map +1 -0
- package/dist/core/defaults.js +2 -0
- package/dist/core/defaults.js.map +1 -0
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +29 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +75 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/experimental.d.ts +2 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +5 -0
- package/dist/core/experimental.js.map +1 -0
- package/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/dist/core/export-html/ansi-to-html.js +249 -0
- package/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/dist/core/export-html/index.d.ts +37 -0
- package/dist/core/export-html/index.d.ts.map +1 -0
- package/dist/core/export-html/index.js +226 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +1066 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1864 -0
- package/dist/core/export-html/tool-renderer.d.ts +34 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +108 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +78 -0
- package/dist/core/extensions/index.d.ts +12 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +23 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +581 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +173 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +967 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +1288 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +45 -0
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +20 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/extensions/wrapper.js +41 -0
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +64 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +338 -0
- package/dist/core/footer-data-provider.js.map +1 -0
- package/dist/core/graph-rail-store.d.ts +94 -0
- package/dist/core/graph-rail-store.d.ts.map +1 -0
- package/dist/core/graph-rail-store.js +86 -0
- package/dist/core/graph-rail-store.js.map +1 -0
- package/dist/core/http-dispatcher.d.ts +22 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -0
- package/dist/core/http-dispatcher.js +96 -0
- package/dist/core/http-dispatcher.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/keybindings.d.ts +395 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +297 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/messages.d.ts +77 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +123 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-config.d.ts +566 -0
- package/dist/core/model-config.d.ts.map +1 -0
- package/dist/core/model-config.js +253 -0
- package/dist/core/model-config.js.map +1 -0
- package/dist/core/model-registry.d.ts +45 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +107 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +127 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +541 -0
- package/dist/core/model-resolver.js.map +1 -0
- package/dist/core/model-runtime.d.ts +97 -0
- package/dist/core/model-runtime.d.ts.map +1 -0
- package/dist/core/model-runtime.js +594 -0
- package/dist/core/model-runtime.js.map +1 -0
- package/dist/core/models-dev-catalog.d.ts +63 -0
- package/dist/core/models-dev-catalog.d.ts.map +1 -0
- package/dist/core/models-dev-catalog.js +105 -0
- package/dist/core/models-dev-catalog.js.map +1 -0
- package/dist/core/models-store.d.ts +22 -0
- package/dist/core/models-store.d.ts.map +1 -0
- package/dist/core/models-store.js +114 -0
- package/dist/core/models-store.js.map +1 -0
- package/dist/core/observatory-cache.d.ts +16 -0
- package/dist/core/observatory-cache.d.ts.map +1 -0
- package/dist/core/observatory-cache.js +55 -0
- package/dist/core/observatory-cache.js.map +1 -0
- package/dist/core/output-guard.d.ts +7 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +89 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +213 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +2169 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/pi-manifest.d.ts +8 -0
- package/dist/core/pi-manifest.d.ts.map +1 -0
- package/dist/core/pi-manifest.js +25 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +59 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +54 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +236 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +73 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-composer.d.ts +56 -0
- package/dist/core/provider-composer.d.ts.map +1 -0
- package/dist/core/provider-composer.js +395 -0
- package/dist/core/provider-composer.js.map +1 -0
- package/dist/core/radius.d.ts +2 -0
- package/dist/core/radius.d.ts.map +1 -0
- package/dist/core/radius.js +2 -0
- package/dist/core/radius.js.map +1 -0
- package/dist/core/remote-catalog-provider.d.ts +5 -0
- package/dist/core/remote-catalog-provider.d.ts.map +1 -0
- package/dist/core/remote-catalog-provider.js +106 -0
- package/dist/core/remote-catalog-provider.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +30 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +247 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +221 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +874 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/runtime-credentials.d.ts +15 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -0
- package/dist/core/runtime-credentials.js +39 -0
- package/dist/core/runtime-credentials.js.map +1 -0
- package/dist/core/sdk.d.ts +106 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +267 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/session-cwd.d.ts +19 -0
- package/dist/core/session-cwd.d.ts.map +1 -0
- package/dist/core/session-cwd.js +38 -0
- package/dist/core/session-cwd.js.map +1 -0
- package/dist/core/session-manager.d.ts +356 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +1340 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/settings-manager.d.ts +304 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +912 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +60 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +387 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/slash-commands.d.ts +21 -0
- package/dist/core/slash-commands.d.ts.map +1 -0
- package/dist/core/slash-commands.js +39 -0
- package/dist/core/slash-commands.js.map +1 -0
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts +28 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +130 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/telemetry.d.ts +3 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +10 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/timings.d.ts +6 -0
- package/dist/core/timings.d.ts.map +1 -0
- package/dist/core/timings.js +42 -0
- package/dist/core/timings.js.map +1 -0
- package/dist/core/tools/bash.d.ts +70 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +389 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +106 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +424 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +51 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +284 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +52 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +38 -0
- package/dist/core/tools/find.d.ts.map +1 -0
- package/dist/core/tools/find.js +298 -0
- package/dist/core/tools/find.js.map +1 -0
- package/dist/core/tools/grep.d.ts +37 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +304 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/index.d.ts +43 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +129 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +37 -0
- package/dist/core/tools/ls.d.ts.map +1 -0
- package/dist/core/tools/ls.js +167 -0
- package/dist/core/tools/ls.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts +52 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -0
- package/dist/core/tools/output-accumulator.js +185 -0
- package/dist/core/tools/output-accumulator.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +10 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +99 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/read.d.ts +35 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +284 -0
- package/dist/core/tools/read.js.map +1 -0
- package/dist/core/tools/render-utils.d.ts +24 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +65 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.js +36 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/truncate.d.ts +70 -0
- package/dist/core/tools/truncate.d.ts.map +1 -0
- package/dist/core/tools/truncate.js +215 -0
- package/dist/core/tools/truncate.js.map +1 -0
- package/dist/core/tools/websearch.d.ts +29 -0
- package/dist/core/tools/websearch.d.ts.map +1 -0
- package/dist/core/tools/websearch.js +145 -0
- package/dist/core/tools/websearch.js.map +1 -0
- package/dist/core/tools/write.d.ts +26 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +197 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/core/trust-manager.d.ts +36 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +202 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/core/usage-totals.d.ts +19 -0
- package/dist/core/usage-totals.d.ts.map +1 -0
- package/dist/core/usage-totals.js +52 -0
- package/dist/core/usage-totals.js.map +1 -0
- package/dist/extensions/gitnexus/augment.d.ts +4 -0
- package/dist/extensions/gitnexus/augment.d.ts.map +1 -0
- package/dist/extensions/gitnexus/augment.js +60 -0
- package/dist/extensions/gitnexus/augment.js.map +1 -0
- package/dist/extensions/gitnexus/changes.d.ts +3 -0
- package/dist/extensions/gitnexus/changes.d.ts.map +1 -0
- package/dist/extensions/gitnexus/changes.js +58 -0
- package/dist/extensions/gitnexus/changes.js.map +1 -0
- package/dist/extensions/gitnexus/client.d.ts +39 -0
- package/dist/extensions/gitnexus/client.d.ts.map +1 -0
- package/dist/extensions/gitnexus/client.js +173 -0
- package/dist/extensions/gitnexus/client.js.map +1 -0
- package/dist/extensions/gitnexus/config.d.ts +25 -0
- package/dist/extensions/gitnexus/config.d.ts.map +1 -0
- package/dist/extensions/gitnexus/config.js +42 -0
- package/dist/extensions/gitnexus/config.js.map +1 -0
- package/dist/extensions/gitnexus/device-auth.d.ts +60 -0
- package/dist/extensions/gitnexus/device-auth.d.ts.map +1 -0
- package/dist/extensions/gitnexus/device-auth.js +130 -0
- package/dist/extensions/gitnexus/device-auth.js.map +1 -0
- package/dist/extensions/gitnexus/gateway.d.ts +57 -0
- package/dist/extensions/gitnexus/gateway.d.ts.map +1 -0
- package/dist/extensions/gitnexus/gateway.js +139 -0
- package/dist/extensions/gitnexus/gateway.js.map +1 -0
- package/dist/extensions/gitnexus/index.d.ts +14 -0
- package/dist/extensions/gitnexus/index.d.ts.map +1 -0
- package/dist/extensions/gitnexus/index.js +189 -0
- package/dist/extensions/gitnexus/index.js.map +1 -0
- package/dist/extensions/gitnexus/observatory.d.ts +13 -0
- package/dist/extensions/gitnexus/observatory.d.ts.map +1 -0
- package/dist/extensions/gitnexus/observatory.js +189 -0
- package/dist/extensions/gitnexus/observatory.js.map +1 -0
- package/dist/extensions/gitnexus/prompt.d.ts +11 -0
- package/dist/extensions/gitnexus/prompt.d.ts.map +1 -0
- package/dist/extensions/gitnexus/prompt.js +50 -0
- package/dist/extensions/gitnexus/prompt.js.map +1 -0
- package/dist/extensions/gitnexus/render.d.ts +61 -0
- package/dist/extensions/gitnexus/render.d.ts.map +1 -0
- package/dist/extensions/gitnexus/render.js +391 -0
- package/dist/extensions/gitnexus/render.js.map +1 -0
- package/dist/extensions/gitnexus/resolve.d.ts +22 -0
- package/dist/extensions/gitnexus/resolve.d.ts.map +1 -0
- package/dist/extensions/gitnexus/resolve.js +54 -0
- package/dist/extensions/gitnexus/resolve.js.map +1 -0
- package/dist/extensions/gitnexus/skills/gitnexus-debugging/SKILL.md +89 -0
- package/dist/extensions/gitnexus/skills/gitnexus-debugging/mcp.json +8 -0
- package/dist/extensions/gitnexus/skills/gitnexus-exploring/SKILL.md +78 -0
- package/dist/extensions/gitnexus/skills/gitnexus-exploring/mcp.json +8 -0
- package/dist/extensions/gitnexus/skills/gitnexus-guide/SKILL.md +64 -0
- package/dist/extensions/gitnexus/skills/gitnexus-guide/mcp.json +8 -0
- package/dist/extensions/gitnexus/skills/gitnexus-impact-analysis/SKILL.md +97 -0
- package/dist/extensions/gitnexus/skills/gitnexus-impact-analysis/mcp.json +8 -0
- package/dist/extensions/gitnexus/skills/gitnexus-pr-review/SKILL.md +163 -0
- package/dist/extensions/gitnexus/skills/gitnexus-refactoring/SKILL.md +121 -0
- package/dist/extensions/gitnexus/skills/gitnexus-refactoring/mcp.json +8 -0
- package/dist/extensions/gitnexus/tools.d.ts +15 -0
- package/dist/extensions/gitnexus/tools.d.ts.map +1 -0
- package/dist/extensions/gitnexus/tools.js +187 -0
- package/dist/extensions/gitnexus/tools.js.map +1 -0
- package/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +10 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/llama/client.d.ts +61 -0
- package/dist/extensions/llama/client.d.ts.map +1 -0
- package/dist/extensions/llama/client.js +302 -0
- package/dist/extensions/llama/client.js.map +1 -0
- package/dist/extensions/llama/huggingface.d.ts +23 -0
- package/dist/extensions/llama/huggingface.d.ts.map +1 -0
- package/dist/extensions/llama/huggingface.js +141 -0
- package/dist/extensions/llama/huggingface.js.map +1 -0
- package/dist/extensions/llama/index.d.ts +3 -0
- package/dist/extensions/llama/index.d.ts.map +1 -0
- package/dist/extensions/llama/index.js +217 -0
- package/dist/extensions/llama/index.js.map +1 -0
- package/dist/extensions/llama/provider.d.ts +10 -0
- package/dist/extensions/llama/provider.d.ts.map +1 -0
- package/dist/extensions/llama/provider.js +121 -0
- package/dist/extensions/llama/provider.js.map +1 -0
- package/dist/extensions/llama/ui.d.ts +42 -0
- package/dist/extensions/llama/ui.d.ts.map +1 -0
- package/dist/extensions/llama/ui.js +416 -0
- package/dist/extensions/llama/ui.js.map +1 -0
- package/dist/extensions/mcp/client.d.ts +86 -0
- package/dist/extensions/mcp/client.d.ts.map +1 -0
- package/dist/extensions/mcp/client.js +275 -0
- package/dist/extensions/mcp/client.js.map +1 -0
- package/dist/extensions/mcp/config.d.ts +41 -0
- package/dist/extensions/mcp/config.d.ts.map +1 -0
- package/dist/extensions/mcp/config.js +85 -0
- package/dist/extensions/mcp/config.js.map +1 -0
- package/dist/extensions/mcp/index.d.ts +18 -0
- package/dist/extensions/mcp/index.d.ts.map +1 -0
- package/dist/extensions/mcp/index.js +95 -0
- package/dist/extensions/mcp/index.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69874 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +12 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +792 -0
- package/dist/main.js.map +1 -0
- package/dist/migrations.d.ts +33 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +281 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modes/index.d.ts +10 -0
- package/dist/modes/index.d.ts.map +1 -0
- package/dist/modes/index.js +8 -0
- package/dist/modes/index.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +32 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +177 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/bash-execution.js +175 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.js +54 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +44 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/command-palette.d.ts +12 -0
- package/dist/modes/interactive/components/command-palette.d.ts.map +1 -0
- package/dist/modes/interactive/components/command-palette.js +67 -0
- package/dist/modes/interactive/components/command-palette.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts +102 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +761 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.js +33 -0
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +23 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-editor.js +85 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-entry.js +52 -0
- package/dist/modes/interactive/components/custom-entry.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +22 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +87 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/dialog-frame.d.ts +37 -0
- package/dist/modes/interactive/components/dialog-frame.d.ts.map +1 -0
- package/dist/modes/interactive/components/dialog-frame.js +53 -0
- package/dist/modes/interactive/components/dialog-frame.js.map +1 -0
- package/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -0
- package/dist/modes/interactive/components/diff.js +133 -0
- package/dist/modes/interactive/components/diff.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +19 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.js +36 -0
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +21 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +98 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts +23 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-input.js +61 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +26 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-selector.js +83 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
- package/dist/modes/interactive/components/first-time-setup.js +103 -0
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +30 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -0
- package/dist/modes/interactive/components/footer.js +108 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/graph-rail.d.ts +44 -0
- package/dist/modes/interactive/components/graph-rail.d.ts.map +1 -0
- package/dist/modes/interactive/components/graph-rail.js +332 -0
- package/dist/modes/interactive/components/graph-rail.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +33 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +34 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.js +36 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
- package/dist/modes/interactive/components/landing-panel.d.ts +14 -0
- package/dist/modes/interactive/components/landing-panel.d.ts.map +1 -0
- package/dist/modes/interactive/components/landing-panel.js +141 -0
- package/dist/modes/interactive/components/landing-panel.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +52 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +188 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.js +19 -0
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
- package/dist/modes/interactive/components/mermaid.d.ts +11 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +80 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/message-layout.d.ts +4 -0
- package/dist/modes/interactive/components/message-layout.d.ts.map +1 -0
- package/dist/modes/interactive/components/message-layout.js +4 -0
- package/dist/modes/interactive/components/message-layout.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +54 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +325 -0
- package/dist/modes/interactive/components/model-selector.js.map +1 -0
- package/dist/modes/interactive/components/nexus-logo.d.ts +25 -0
- package/dist/modes/interactive/components/nexus-logo.d.ts.map +1 -0
- package/dist/modes/interactive/components/nexus-logo.js +115 -0
- package/dist/modes/interactive/components/nexus-logo.js.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.js +163 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/panel.d.ts +7 -0
- package/dist/modes/interactive/components/panel.d.ts.map +1 -0
- package/dist/modes/interactive/components/panel.js +18 -0
- package/dist/modes/interactive/components/panel.js.map +1 -0
- package/dist/modes/interactive/components/response-separator.d.ts +13 -0
- package/dist/modes/interactive/components/response-separator.d.ts.map +1 -0
- package/dist/modes/interactive/components/response-separator.js +23 -0
- package/dist/modes/interactive/components/response-separator.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +46 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +328 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.js +155 -0
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +99 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +887 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +81 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +613 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.js +39 -0
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/status-indicator.d.ts +37 -0
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
- package/dist/modes/interactive/components/status-indicator.js +116 -0
- package/dist/modes/interactive/components/status-indicator.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/theme-selector.js +50 -0
- package/dist/modes/interactive/components/theme-selector.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.js +52 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +70 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +384 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +94 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +1245 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -0
- package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +91 -0
- package/dist/modes/interactive/components/trust-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.js +114 -0
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +17 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message.js +51 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.js +33 -0
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +436 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +5462 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -0
- package/dist/modes/interactive/model-search.d.ts +12 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -0
- package/dist/modes/interactive/model-search.js +15 -0
- package/dist/modes/interactive/model-search.js.map +1 -0
- package/dist/modes/interactive/theme/brand.d.ts +38 -0
- package/dist/modes/interactive/theme/brand.d.ts.map +1 -0
- package/dist/modes/interactive/theme/brand.js +108 -0
- package/dist/modes/interactive/theme/brand.js.map +1 -0
- package/dist/modes/interactive/theme/catppuccin-mocha.json +66 -0
- package/dist/modes/interactive/theme/dark.json +93 -0
- package/dist/modes/interactive/theme/dracula.json +66 -0
- package/dist/modes/interactive/theme/ember.json +85 -0
- package/dist/modes/interactive/theme/gruvbox.json +66 -0
- package/dist/modes/interactive/theme/light.json +91 -0
- package/dist/modes/interactive/theme/nord.json +66 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +32 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +111 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +344 -0
- package/dist/modes/interactive/theme/theme.d.ts +129 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +1101 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/modes/interactive/theme/tokyonight.json +66 -0
- package/dist/modes/json-event.d.ts +28 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +12 -0
- package/dist/modes/json-event.js.map +1 -0
- package/dist/modes/print-mode.d.ts +28 -0
- package/dist/modes/print-mode.d.ts.map +1 -0
- package/dist/modes/print-mode.js +153 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +247 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +488 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts +20 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-mode.js +654 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +457 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-types.js +8 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -0
- package/dist/package-manager-cli.d.ts +8 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +777 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/dist/rpc-entry.d.ts +3 -0
- package/dist/rpc-entry.d.ts.map +1 -0
- package/dist/rpc-entry.js +69740 -0
- package/dist/rpc-entry.js.map +1 -0
- package/dist/utils/abort.d.ts +5 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +48 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/child-process.d.ts +18 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +106 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -0
- package/dist/utils/clipboard-image.js +245 -0
- package/dist/utils/clipboard-image.js.map +1 -0
- package/dist/utils/clipboard-native.d.ts +11 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -0
- package/dist/utils/clipboard-native.js +20 -0
- package/dist/utils/clipboard-native.js.map +1 -0
- package/dist/utils/clipboard.d.ts +4 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +161 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +8 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/fs-watch.d.ts +5 -0
- package/dist/utils/fs-watch.d.ts.map +1 -0
- package/dist/utils/fs-watch.js +25 -0
- package/dist/utils/fs-watch.js.map +1 -0
- package/dist/utils/git.d.ts +26 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +195 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/image-convert.d.ts +10 -0
- package/dist/utils/image-convert.d.ts.map +1 -0
- package/dist/utils/image-convert.js +45 -0
- package/dist/utils/image-convert.js.map +1 -0
- package/dist/utils/image-process.d.ts +18 -0
- package/dist/utils/image-process.d.ts.map +1 -0
- package/dist/utils/image-process.js +83 -0
- package/dist/utils/image-process.js.map +1 -0
- package/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -0
- package/dist/utils/image-resize-core.js +124 -0
- package/dist/utils/image-resize-core.js.map +1 -0
- package/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/dist/utils/image-resize-worker.js +31 -0
- package/dist/utils/image-resize-worker.js.map +1 -0
- package/dist/utils/image-resize.d.ts +16 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +97 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/management-http.d.ts +23 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +50 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/mime.d.ts +3 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +110 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/dist/utils/paths.d.ts +34 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +114 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/photon.d.ts +21 -0
- package/dist/utils/photon.d.ts.map +1 -0
- package/dist/utils/photon.js +121 -0
- package/dist/utils/photon.js.map +1 -0
- package/dist/utils/pi-user-agent.d.ts +2 -0
- package/dist/utils/pi-user-agent.d.ts.map +1 -0
- package/dist/utils/pi-user-agent.js +5 -0
- package/dist/utils/pi-user-agent.js.map +1 -0
- package/dist/utils/shell.d.ts +31 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +202 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tool-result-images.d.ts +19 -0
- package/dist/utils/tool-result-images.d.ts.map +1 -0
- package/dist/utils/tool-result-images.js +45 -0
- package/dist/utils/tool-result-images.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +326 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/dist/utils/version-check.d.ts +19 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +98 -0
- package/dist/utils/version-check.js.map +1 -0
- package/dist/utils/windows-self-update.d.ts +3 -0
- package/dist/utils/windows-self-update.d.ts.map +1 -0
- package/dist/utils/windows-self-update.js +77 -0
- package/dist/utils/windows-self-update.js.map +1 -0
- package/docs/compaction.md +401 -0
- package/docs/containerization.md +111 -0
- package/docs/custom-provider.md +774 -0
- package/docs/development.md +71 -0
- package/docs/docs.json +156 -0
- package/docs/environment-variables.md +98 -0
- package/docs/extensions.md +2987 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +84 -0
- package/docs/json.md +91 -0
- package/docs/keybindings.md +226 -0
- package/docs/llama-cpp.md +99 -0
- package/docs/models.md +565 -0
- package/docs/packages.md +228 -0
- package/docs/prompt-templates.md +96 -0
- package/docs/providers.md +310 -0
- package/docs/quickstart.md +167 -0
- package/docs/rpc.md +1578 -0
- package/docs/sdk.md +1205 -0
- package/docs/security.md +59 -0
- package/docs/session-format.md +438 -0
- package/docs/sessions.md +145 -0
- package/docs/settings.md +322 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +231 -0
- package/docs/terminal-setup.md +142 -0
- package/docs/termux.md +127 -0
- package/docs/themes.md +299 -0
- package/docs/tmux.md +63 -0
- package/docs/tui.md +942 -0
- package/docs/usage.md +305 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +213 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/border-status-editor.ts +150 -0
- package/examples/extensions/built-in-tool-renderer.ts +249 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +117 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +611 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +405 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/entry-renderer.ts +41 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +190 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/kimi-deferred-tools.ts +61 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +55 -0
- package/examples/extensions/overlay-qa-tests.ts +1450 -0
- package/examples/extensions/overlay-test.ts +153 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +66 -0
- package/examples/extensions/plan-mode/index.ts +390 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +436 -0
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +97 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +118 -0
- package/examples/extensions/question.ts +286 -0
- package/examples/extensions/questionnaire.ts +448 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +175 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +126 -0
- package/examples/extensions/subagent/index.ts +1015 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +199 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1008 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +297 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/extensions/working-indicator.ts +123 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/rpc-extension-ui.ts +641 -0
- package/examples/sdk/01-minimal.ts +26 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +75 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +48 -0
- package/examples/sdk/06-extensions.ts +99 -0
- package/examples/sdk/07-context-files.ts +47 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +52 -0
- package/examples/sdk/12-full-control.ts +74 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +140 -0
- package/npm-shrinkwrap.json +1817 -0
- package/package.json +145 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal MCP client covering the subset needed to borrow another server's
|
|
4
|
+
* tools: initialize, notifications/initialized, tools/list, tools/call.
|
|
5
|
+
*
|
|
6
|
+
* Two transports, because real servers split roughly evenly between them:
|
|
7
|
+
* stdio for anything you launch locally (filesystem, github, postgres) and
|
|
8
|
+
* Streamable HTTP for anything hosted. Both speak the same JSON-RPC, so only
|
|
9
|
+
* the framing differs.
|
|
10
|
+
*
|
|
11
|
+
* The gitnexus client is deliberately left alone: it is pinned to one server,
|
|
12
|
+
* carries hub-specific auth headers, and its error messages name the hub.
|
|
13
|
+
*/
|
|
14
|
+
export const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
15
|
+
const REQUEST_TIMEOUT_MS = 60_000;
|
|
16
|
+
export class McpClientError extends Error {
|
|
17
|
+
kind;
|
|
18
|
+
constructor(message, kind) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "McpClientError";
|
|
21
|
+
this.kind = kind;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ---------------------------------------------------------------- HTTP
|
|
25
|
+
export class HttpTransport {
|
|
26
|
+
sessionId;
|
|
27
|
+
url;
|
|
28
|
+
headers;
|
|
29
|
+
constructor(url, headers = {}) {
|
|
30
|
+
this.url = url;
|
|
31
|
+
this.headers = headers;
|
|
32
|
+
}
|
|
33
|
+
async send(body, signal) {
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
36
|
+
const onAbort = () => controller.abort();
|
|
37
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
38
|
+
try {
|
|
39
|
+
let response;
|
|
40
|
+
try {
|
|
41
|
+
response = await fetch(this.url, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
"content-type": "application/json",
|
|
45
|
+
accept: "application/json, text/event-stream",
|
|
46
|
+
...this.headers,
|
|
47
|
+
...(this.sessionId ? { "mcp-session-id": this.sessionId } : {}),
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify(body),
|
|
50
|
+
signal: controller.signal,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new McpClientError(`cannot reach MCP server ${this.url}: ${error instanceof Error ? error.message : String(error)}`, "network");
|
|
55
|
+
}
|
|
56
|
+
const newSession = response.headers.get("mcp-session-id");
|
|
57
|
+
if (newSession)
|
|
58
|
+
this.sessionId = newSession;
|
|
59
|
+
// An unconsumed body pins its socket, and under a connection-capped
|
|
60
|
+
// dispatcher that deadlocks every later call to the same server.
|
|
61
|
+
if (response.status === 202) {
|
|
62
|
+
await response.body?.cancel().catch(() => { });
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
await response.body?.cancel().catch(() => { });
|
|
67
|
+
throw new McpClientError(`MCP server ${this.url} returned HTTP ${response.status}`, "protocol");
|
|
68
|
+
}
|
|
69
|
+
const text = await response.text();
|
|
70
|
+
if (!text)
|
|
71
|
+
return undefined;
|
|
72
|
+
if ((response.headers.get("content-type") ?? "").includes("text/event-stream")) {
|
|
73
|
+
return parseSse(text);
|
|
74
|
+
}
|
|
75
|
+
return JSON.parse(text);
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
clearTimeout(timeout);
|
|
79
|
+
signal?.removeEventListener("abort", onAbort);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
close() {
|
|
83
|
+
// Nothing to tear down: each call is its own request.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Pull the last id-bearing JSON-RPC message out of an SSE body. */
|
|
87
|
+
export function parseSse(sse) {
|
|
88
|
+
let last;
|
|
89
|
+
for (const rawEvent of sse.split("\n\n")) {
|
|
90
|
+
const data = rawEvent
|
|
91
|
+
.split("\n")
|
|
92
|
+
.filter((line) => line.startsWith("data:"))
|
|
93
|
+
.map((line) => line.slice(5).trim())
|
|
94
|
+
.join("\n");
|
|
95
|
+
if (!data)
|
|
96
|
+
continue;
|
|
97
|
+
try {
|
|
98
|
+
const parsed = JSON.parse(data);
|
|
99
|
+
// Responses carry an id; server-initiated notifications do not.
|
|
100
|
+
if (parsed.id !== undefined && parsed.id !== null)
|
|
101
|
+
last = parsed;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Ignore non-JSON keepalives.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return last;
|
|
108
|
+
}
|
|
109
|
+
// ---------------------------------------------------------------- stdio
|
|
110
|
+
export class StdioTransport {
|
|
111
|
+
child;
|
|
112
|
+
buffer = "";
|
|
113
|
+
pending = new Map();
|
|
114
|
+
startError;
|
|
115
|
+
command;
|
|
116
|
+
args;
|
|
117
|
+
env;
|
|
118
|
+
cwd;
|
|
119
|
+
constructor(command, args = [], env = {}, cwd) {
|
|
120
|
+
this.command = command;
|
|
121
|
+
this.args = args;
|
|
122
|
+
this.env = env;
|
|
123
|
+
this.cwd = cwd;
|
|
124
|
+
}
|
|
125
|
+
ensureStarted() {
|
|
126
|
+
if (this.startError)
|
|
127
|
+
throw new McpClientError(this.startError, "spawn");
|
|
128
|
+
if (this.child)
|
|
129
|
+
return this.child;
|
|
130
|
+
let child;
|
|
131
|
+
try {
|
|
132
|
+
child = spawn(this.command, this.args, {
|
|
133
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
134
|
+
env: { ...process.env, ...this.env },
|
|
135
|
+
cwd: this.cwd,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
this.startError = `cannot start MCP server "${this.command}": ${error instanceof Error ? error.message : String(error)}`;
|
|
140
|
+
throw new McpClientError(this.startError, "spawn");
|
|
141
|
+
}
|
|
142
|
+
child.on("error", (error) => {
|
|
143
|
+
// ENOENT surfaces here, not from spawn(), so record it for the next call.
|
|
144
|
+
this.startError = `cannot start MCP server "${this.command}": ${error.message}`;
|
|
145
|
+
for (const resolve of this.pending.values())
|
|
146
|
+
resolve({ error: { message: this.startError } });
|
|
147
|
+
this.pending.clear();
|
|
148
|
+
});
|
|
149
|
+
child.stdout.setEncoding("utf8");
|
|
150
|
+
child.stdout.on("data", (chunk) => this.consume(chunk));
|
|
151
|
+
// stderr is the server's log stream, not protocol. Draining it keeps a
|
|
152
|
+
// chatty server from filling its pipe buffer and hanging.
|
|
153
|
+
child.stderr.resume();
|
|
154
|
+
this.child = child;
|
|
155
|
+
return child;
|
|
156
|
+
}
|
|
157
|
+
/** Messages are newline-delimited JSON, so split on newlines and keep the tail. */
|
|
158
|
+
consume(chunk) {
|
|
159
|
+
this.buffer += chunk;
|
|
160
|
+
let newline = this.buffer.indexOf("\n");
|
|
161
|
+
while (newline >= 0) {
|
|
162
|
+
const line = this.buffer.slice(0, newline).trim();
|
|
163
|
+
this.buffer = this.buffer.slice(newline + 1);
|
|
164
|
+
newline = this.buffer.indexOf("\n");
|
|
165
|
+
if (!line)
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
const message = JSON.parse(line);
|
|
169
|
+
if (message.id === undefined || message.id === null)
|
|
170
|
+
continue;
|
|
171
|
+
const resolve = this.pending.get(message.id);
|
|
172
|
+
if (resolve) {
|
|
173
|
+
this.pending.delete(message.id);
|
|
174
|
+
resolve(message);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// A server that prints non-JSON to stdout is not fatal; skip the line.
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async send(body, signal) {
|
|
183
|
+
const child = this.ensureStarted();
|
|
184
|
+
const id = body.id;
|
|
185
|
+
child.stdin.write(`${JSON.stringify(body)}\n`);
|
|
186
|
+
// Notifications carry no id and get no reply — waiting would always time out.
|
|
187
|
+
if (id === undefined || id === null)
|
|
188
|
+
return undefined;
|
|
189
|
+
return await new Promise((resolve, reject) => {
|
|
190
|
+
const timer = setTimeout(() => {
|
|
191
|
+
this.pending.delete(id);
|
|
192
|
+
reject(new McpClientError(`MCP server "${this.command}" timed out`, "timeout"));
|
|
193
|
+
}, REQUEST_TIMEOUT_MS);
|
|
194
|
+
const onAbort = () => {
|
|
195
|
+
this.pending.delete(id);
|
|
196
|
+
clearTimeout(timer);
|
|
197
|
+
reject(new McpClientError(`MCP call to "${this.command}" aborted`, "timeout"));
|
|
198
|
+
};
|
|
199
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
200
|
+
this.pending.set(id, (response) => {
|
|
201
|
+
clearTimeout(timer);
|
|
202
|
+
signal?.removeEventListener("abort", onAbort);
|
|
203
|
+
resolve(response);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
close() {
|
|
208
|
+
this.child?.kill();
|
|
209
|
+
this.child = undefined;
|
|
210
|
+
this.pending.clear();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// ---------------------------------------------------------------- client
|
|
214
|
+
export class McpClient {
|
|
215
|
+
nextId = 1;
|
|
216
|
+
initializing;
|
|
217
|
+
serverName;
|
|
218
|
+
transport;
|
|
219
|
+
constructor(serverName, transport) {
|
|
220
|
+
this.serverName = serverName;
|
|
221
|
+
this.transport = transport;
|
|
222
|
+
}
|
|
223
|
+
ensureInitialized(signal) {
|
|
224
|
+
this.initializing ??= this.initialize(signal).catch((error) => {
|
|
225
|
+
// Clear the memo so a later call can retry rather than replaying the failure.
|
|
226
|
+
this.initializing = undefined;
|
|
227
|
+
throw error;
|
|
228
|
+
});
|
|
229
|
+
return this.initializing;
|
|
230
|
+
}
|
|
231
|
+
async initialize(signal) {
|
|
232
|
+
await this.request("initialize", {
|
|
233
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
234
|
+
capabilities: {},
|
|
235
|
+
clientInfo: { name: "nexus-cli", version: "0.1.0" },
|
|
236
|
+
}, signal);
|
|
237
|
+
await this.transport.send({ jsonrpc: "2.0", method: "notifications/initialized" });
|
|
238
|
+
}
|
|
239
|
+
/** Tools this server offers. Paginates until the server stops sending a cursor. */
|
|
240
|
+
async listTools(signal) {
|
|
241
|
+
await this.ensureInitialized(signal);
|
|
242
|
+
const tools = [];
|
|
243
|
+
let cursor;
|
|
244
|
+
do {
|
|
245
|
+
const result = (await this.request("tools/list", cursor ? { cursor } : {}, signal));
|
|
246
|
+
for (const tool of result?.tools ?? []) {
|
|
247
|
+
if (tool?.name)
|
|
248
|
+
tools.push(tool);
|
|
249
|
+
}
|
|
250
|
+
const next = result?.nextCursor;
|
|
251
|
+
// A server that echoes the same cursor would loop forever.
|
|
252
|
+
cursor = next && next !== cursor ? next : undefined;
|
|
253
|
+
} while (cursor);
|
|
254
|
+
return tools;
|
|
255
|
+
}
|
|
256
|
+
async callTool(name, args, signal) {
|
|
257
|
+
await this.ensureInitialized(signal);
|
|
258
|
+
const result = await this.request("tools/call", { name, arguments: args }, signal);
|
|
259
|
+
return (result ?? {});
|
|
260
|
+
}
|
|
261
|
+
async request(method, params, signal) {
|
|
262
|
+
const id = this.nextId++;
|
|
263
|
+
const response = await this.transport.send({ jsonrpc: "2.0", id, method, params }, signal);
|
|
264
|
+
if (!response)
|
|
265
|
+
throw new McpClientError(`empty response for ${method}`, "protocol");
|
|
266
|
+
if (response.error) {
|
|
267
|
+
throw new McpClientError(`${this.serverName} ${method} failed: ${response.error.message}`, "protocol");
|
|
268
|
+
}
|
|
269
|
+
return response.result;
|
|
270
|
+
}
|
|
271
|
+
close() {
|
|
272
|
+
this.transport.close();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/extensions/mcp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { spawn } from \"node:child_process\";\n\n/**\n * Minimal MCP client covering the subset needed to borrow another server's\n * tools: initialize, notifications/initialized, tools/list, tools/call.\n *\n * Two transports, because real servers split roughly evenly between them:\n * stdio for anything you launch locally (filesystem, github, postgres) and\n * Streamable HTTP for anything hosted. Both speak the same JSON-RPC, so only\n * the framing differs.\n *\n * The gitnexus client is deliberately left alone: it is pinned to one server,\n * carries hub-specific auth headers, and its error messages name the hub.\n */\n\nexport const MCP_PROTOCOL_VERSION = \"2025-06-18\";\nconst REQUEST_TIMEOUT_MS = 60_000;\n\nexport interface McpToolSchema {\n\tname: string;\n\tdescription?: string;\n\tinputSchema?: Record<string, unknown>;\n}\n\nexport interface McpToolResult {\n\tcontent?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\tisError?: boolean;\n}\n\ninterface JsonRpcResponse {\n\tid?: number | string | null;\n\tresult?: unknown;\n\terror?: { code?: number; message?: string };\n}\n\nexport class McpClientError extends Error {\n\treadonly kind: \"spawn\" | \"network\" | \"protocol\" | \"timeout\";\n\n\tconstructor(message: string, kind: McpClientError[\"kind\"]) {\n\t\tsuper(message);\n\t\tthis.name = \"McpClientError\";\n\t\tthis.kind = kind;\n\t}\n}\n\n/** A transport carries one JSON-RPC message and returns the matching response. */\nexport interface McpTransport {\n\tsend(body: unknown, signal?: AbortSignal): Promise<JsonRpcResponse | undefined>;\n\tclose(): void;\n}\n\n// ---------------------------------------------------------------- HTTP\n\nexport class HttpTransport implements McpTransport {\n\tprivate sessionId: string | undefined;\n\tprivate readonly url: string;\n\tprivate readonly headers: Record<string, string>;\n\n\tconstructor(url: string, headers: Record<string, string> = {}) {\n\t\tthis.url = url;\n\t\tthis.headers = headers;\n\t}\n\n\tasync send(body: unknown, signal?: AbortSignal): Promise<JsonRpcResponse | undefined> {\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\t\tconst onAbort = () => controller.abort();\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\ttry {\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = await fetch(this.url, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t\taccept: \"application/json, text/event-stream\",\n\t\t\t\t\t\t...this.headers,\n\t\t\t\t\t\t...(this.sessionId ? { \"mcp-session-id\": this.sessionId } : {}),\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tthrow new McpClientError(\n\t\t\t\t\t`cannot reach MCP server ${this.url}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\"network\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst newSession = response.headers.get(\"mcp-session-id\");\n\t\t\tif (newSession) this.sessionId = newSession;\n\n\t\t\t// An unconsumed body pins its socket, and under a connection-capped\n\t\t\t// dispatcher that deadlocks every later call to the same server.\n\t\t\tif (response.status === 202) {\n\t\t\t\tawait response.body?.cancel().catch(() => {});\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tawait response.body?.cancel().catch(() => {});\n\t\t\t\tthrow new McpClientError(`MCP server ${this.url} returned HTTP ${response.status}`, \"protocol\");\n\t\t\t}\n\n\t\t\tconst text = await response.text();\n\t\t\tif (!text) return undefined;\n\t\t\tif ((response.headers.get(\"content-type\") ?? \"\").includes(\"text/event-stream\")) {\n\t\t\t\treturn parseSse(text);\n\t\t\t}\n\t\t\treturn JSON.parse(text) as JsonRpcResponse;\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t}\n\t}\n\n\tclose(): void {\n\t\t// Nothing to tear down: each call is its own request.\n\t}\n}\n\n/** Pull the last id-bearing JSON-RPC message out of an SSE body. */\nexport function parseSse(sse: string): JsonRpcResponse | undefined {\n\tlet last: JsonRpcResponse | undefined;\n\tfor (const rawEvent of sse.split(\"\\n\\n\")) {\n\t\tconst data = rawEvent\n\t\t\t.split(\"\\n\")\n\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t.map((line) => line.slice(5).trim())\n\t\t\t.join(\"\\n\");\n\t\tif (!data) continue;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(data) as JsonRpcResponse;\n\t\t\t// Responses carry an id; server-initiated notifications do not.\n\t\t\tif (parsed.id !== undefined && parsed.id !== null) last = parsed;\n\t\t} catch {\n\t\t\t// Ignore non-JSON keepalives.\n\t\t}\n\t}\n\treturn last;\n}\n\n// ---------------------------------------------------------------- stdio\n\nexport class StdioTransport implements McpTransport {\n\tprivate child: ChildProcessWithoutNullStreams | undefined;\n\tprivate buffer = \"\";\n\tprivate readonly pending = new Map<number | string, (response: JsonRpcResponse) => void>();\n\tprivate startError: string | undefined;\n\n\tprivate readonly command: string;\n\tprivate readonly args: string[];\n\tprivate readonly env: Record<string, string>;\n\tprivate readonly cwd: string | undefined;\n\n\tconstructor(command: string, args: string[] = [], env: Record<string, string> = {}, cwd?: string) {\n\t\tthis.command = command;\n\t\tthis.args = args;\n\t\tthis.env = env;\n\t\tthis.cwd = cwd;\n\t}\n\n\tprivate ensureStarted(): ChildProcessWithoutNullStreams {\n\t\tif (this.startError) throw new McpClientError(this.startError, \"spawn\");\n\t\tif (this.child) return this.child;\n\t\tlet child: ChildProcessWithoutNullStreams;\n\t\ttry {\n\t\t\tchild = spawn(this.command, this.args, {\n\t\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t\t\tenv: { ...process.env, ...this.env },\n\t\t\t\tcwd: this.cwd,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.startError = `cannot start MCP server \"${this.command}\": ${\n\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t}`;\n\t\t\tthrow new McpClientError(this.startError, \"spawn\");\n\t\t}\n\t\tchild.on(\"error\", (error) => {\n\t\t\t// ENOENT surfaces here, not from spawn(), so record it for the next call.\n\t\t\tthis.startError = `cannot start MCP server \"${this.command}\": ${error.message}`;\n\t\t\tfor (const resolve of this.pending.values()) resolve({ error: { message: this.startError } });\n\t\t\tthis.pending.clear();\n\t\t});\n\t\tchild.stdout.setEncoding(\"utf8\");\n\t\tchild.stdout.on(\"data\", (chunk: string) => this.consume(chunk));\n\t\t// stderr is the server's log stream, not protocol. Draining it keeps a\n\t\t// chatty server from filling its pipe buffer and hanging.\n\t\tchild.stderr.resume();\n\t\tthis.child = child;\n\t\treturn child;\n\t}\n\n\t/** Messages are newline-delimited JSON, so split on newlines and keep the tail. */\n\tprivate consume(chunk: string): void {\n\t\tthis.buffer += chunk;\n\t\tlet newline = this.buffer.indexOf(\"\\n\");\n\t\twhile (newline >= 0) {\n\t\t\tconst line = this.buffer.slice(0, newline).trim();\n\t\t\tthis.buffer = this.buffer.slice(newline + 1);\n\t\t\tnewline = this.buffer.indexOf(\"\\n\");\n\t\t\tif (!line) continue;\n\t\t\ttry {\n\t\t\t\tconst message = JSON.parse(line) as JsonRpcResponse;\n\t\t\t\tif (message.id === undefined || message.id === null) continue;\n\t\t\t\tconst resolve = this.pending.get(message.id);\n\t\t\t\tif (resolve) {\n\t\t\t\t\tthis.pending.delete(message.id);\n\t\t\t\t\tresolve(message);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// A server that prints non-JSON to stdout is not fatal; skip the line.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync send(body: unknown, signal?: AbortSignal): Promise<JsonRpcResponse | undefined> {\n\t\tconst child = this.ensureStarted();\n\t\tconst id = (body as { id?: number | string }).id;\n\t\tchild.stdin.write(`${JSON.stringify(body)}\\n`);\n\t\t// Notifications carry no id and get no reply — waiting would always time out.\n\t\tif (id === undefined || id === null) return undefined;\n\n\t\treturn await new Promise<JsonRpcResponse>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.pending.delete(id);\n\t\t\t\treject(new McpClientError(`MCP server \"${this.command}\" timed out`, \"timeout\"));\n\t\t\t}, REQUEST_TIMEOUT_MS);\n\t\t\tconst onAbort = () => {\n\t\t\t\tthis.pending.delete(id);\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(new McpClientError(`MCP call to \"${this.command}\" aborted`, \"timeout\"));\n\t\t\t};\n\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\tthis.pending.set(id, (response) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(response);\n\t\t\t});\n\t\t});\n\t}\n\n\tclose(): void {\n\t\tthis.child?.kill();\n\t\tthis.child = undefined;\n\t\tthis.pending.clear();\n\t}\n}\n\n// ---------------------------------------------------------------- client\n\nexport class McpClient {\n\tprivate nextId = 1;\n\tprivate initializing: Promise<void> | undefined;\n\n\treadonly serverName: string;\n\tprivate readonly transport: McpTransport;\n\n\tconstructor(serverName: string, transport: McpTransport) {\n\t\tthis.serverName = serverName;\n\t\tthis.transport = transport;\n\t}\n\n\tprivate ensureInitialized(signal?: AbortSignal): Promise<void> {\n\t\tthis.initializing ??= this.initialize(signal).catch((error) => {\n\t\t\t// Clear the memo so a later call can retry rather than replaying the failure.\n\t\t\tthis.initializing = undefined;\n\t\t\tthrow error;\n\t\t});\n\t\treturn this.initializing;\n\t}\n\n\tprivate async initialize(signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\n\t\t\t\"initialize\",\n\t\t\t{\n\t\t\t\tprotocolVersion: MCP_PROTOCOL_VERSION,\n\t\t\t\tcapabilities: {},\n\t\t\t\tclientInfo: { name: \"nexus-cli\", version: \"0.1.0\" },\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t\tawait this.transport.send({ jsonrpc: \"2.0\", method: \"notifications/initialized\" });\n\t}\n\n\t/** Tools this server offers. Paginates until the server stops sending a cursor. */\n\tasync listTools(signal?: AbortSignal): Promise<McpToolSchema[]> {\n\t\tawait this.ensureInitialized(signal);\n\t\tconst tools: McpToolSchema[] = [];\n\t\tlet cursor: string | undefined;\n\t\tdo {\n\t\t\tconst result = (await this.request(\"tools/list\", cursor ? { cursor } : {}, signal)) as\n\t\t\t\t| { tools?: McpToolSchema[]; nextCursor?: string }\n\t\t\t\t| undefined;\n\t\t\tfor (const tool of result?.tools ?? []) {\n\t\t\t\tif (tool?.name) tools.push(tool);\n\t\t\t}\n\t\t\tconst next = result?.nextCursor;\n\t\t\t// A server that echoes the same cursor would loop forever.\n\t\t\tcursor = next && next !== cursor ? next : undefined;\n\t\t} while (cursor);\n\t\treturn tools;\n\t}\n\n\tasync callTool(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<McpToolResult> {\n\t\tawait this.ensureInitialized(signal);\n\t\tconst result = await this.request(\"tools/call\", { name, arguments: args }, signal);\n\t\treturn (result ?? {}) as McpToolResult;\n\t}\n\n\tprivate async request(method: string, params: unknown, signal?: AbortSignal): Promise<unknown> {\n\t\tconst id = this.nextId++;\n\t\tconst response = await this.transport.send({ jsonrpc: \"2.0\", id, method, params }, signal);\n\t\tif (!response) throw new McpClientError(`empty response for ${method}`, \"protocol\");\n\t\tif (response.error) {\n\t\t\tthrow new McpClientError(`${this.serverName} ${method} failed: ${response.error.message}`, \"protocol\");\n\t\t}\n\t\treturn response.result;\n\t}\n\n\tclose(): void {\n\t\tthis.transport.close();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server configuration.
|
|
3
|
+
*
|
|
4
|
+
* The file format is Claude Code's `mcpServers` map, deliberately: users
|
|
5
|
+
* already have these configs, and copying one over should just work. A server
|
|
6
|
+
* is stdio when it has `command` and HTTP when it has `url`.
|
|
7
|
+
*
|
|
8
|
+
* Project config wins over user config for the same server name, so a repo can
|
|
9
|
+
* pin a server its contributors need without editing anyone's home directory.
|
|
10
|
+
*/
|
|
11
|
+
export interface McpStdioServer {
|
|
12
|
+
type: "stdio";
|
|
13
|
+
name: string;
|
|
14
|
+
command: string;
|
|
15
|
+
args: string[];
|
|
16
|
+
env: Record<string, string>;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface McpHttpServer {
|
|
21
|
+
type: "http";
|
|
22
|
+
name: string;
|
|
23
|
+
url: string;
|
|
24
|
+
headers: Record<string, string>;
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
}
|
|
27
|
+
export type McpServerConfig = McpStdioServer | McpHttpServer;
|
|
28
|
+
export interface McpConfigResult {
|
|
29
|
+
servers: McpServerConfig[];
|
|
30
|
+
/** Human-readable problems; surfaced rather than thrown, so one bad entry cannot block startup. */
|
|
31
|
+
diagnostics: string[];
|
|
32
|
+
}
|
|
33
|
+
/** Parse one `mcpServers` entry. Returns a diagnostic string when unusable. */
|
|
34
|
+
export declare function parseServerEntry(name: string, raw: unknown): McpServerConfig | string;
|
|
35
|
+
/** Parse a whole config document. */
|
|
36
|
+
export declare function parseMcpConfig(text: string, source: string): McpConfigResult;
|
|
37
|
+
/** Config paths, lowest precedence first: user config, then this project's. */
|
|
38
|
+
export declare function mcpConfigPaths(cwd: string, home?: string): string[];
|
|
39
|
+
/** Load and merge user then project config. Later files win on name collisions. */
|
|
40
|
+
export declare function loadMcpConfig(cwd: string, readFile?: (path: string) => string, home?: string): McpConfigResult;
|
|
41
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/extensions/mcp/config.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AAEH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,aAAa,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,mGAAmG;IACnG,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAWD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,MAAM,CAyBrF;AAED,qCAAqC;AACrC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CAkB5E;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,EAAE,CAE9E;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAA6C,EACzE,IAAI,CAAC,EAAE,MAAM,GACX,eAAe,CAejB","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\n\n/**\n * MCP server configuration.\n *\n * The file format is Claude Code's `mcpServers` map, deliberately: users\n * already have these configs, and copying one over should just work. A server\n * is stdio when it has `command` and HTTP when it has `url`.\n *\n * Project config wins over user config for the same server name, so a repo can\n * pin a server its contributors need without editing anyone's home directory.\n */\n\nexport interface McpStdioServer {\n\ttype: \"stdio\";\n\tname: string;\n\tcommand: string;\n\targs: string[];\n\tenv: Record<string, string>;\n\tcwd?: string;\n\tenabled: boolean;\n}\n\nexport interface McpHttpServer {\n\ttype: \"http\";\n\tname: string;\n\turl: string;\n\theaders: Record<string, string>;\n\tenabled: boolean;\n}\n\nexport type McpServerConfig = McpStdioServer | McpHttpServer;\n\nexport interface McpConfigResult {\n\tservers: McpServerConfig[];\n\t/** Human-readable problems; surfaced rather than thrown, so one bad entry cannot block startup. */\n\tdiagnostics: string[];\n}\n\nfunction stringRecord(value: unknown): Record<string, string> {\n\tif (!value || typeof value !== \"object\") return {};\n\tconst out: Record<string, string> = {};\n\tfor (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (typeof item === \"string\") out[key] = item;\n\t}\n\treturn out;\n}\n\n/** Parse one `mcpServers` entry. Returns a diagnostic string when unusable. */\nexport function parseServerEntry(name: string, raw: unknown): McpServerConfig | string {\n\tif (!raw || typeof raw !== \"object\") return `MCP server \"${name}\": entry is not an object`;\n\tconst entry = raw as Record<string, unknown>;\n\t// `disabled` is the Claude Code spelling; accept `enabled` too so either reads naturally.\n\tconst enabled = entry.disabled === true ? false : entry.enabled !== false;\n\n\tif (typeof entry.command === \"string\" && entry.command.trim()) {\n\t\treturn {\n\t\t\ttype: \"stdio\",\n\t\t\tname,\n\t\t\tcommand: entry.command.trim(),\n\t\t\targs: Array.isArray(entry.args) ? entry.args.filter((a): a is string => typeof a === \"string\") : [],\n\t\t\tenv: stringRecord(entry.env),\n\t\t\tcwd: typeof entry.cwd === \"string\" ? entry.cwd : undefined,\n\t\t\tenabled,\n\t\t};\n\t}\n\n\tconst url =\n\t\ttypeof entry.url === \"string\" ? entry.url : typeof entry.httpUrl === \"string\" ? entry.httpUrl : undefined;\n\tif (url?.trim()) {\n\t\treturn { type: \"http\", name, url: url.trim(), headers: stringRecord(entry.headers), enabled };\n\t}\n\n\treturn `MCP server \"${name}\": needs either \"command\" (stdio) or \"url\" (http)`;\n}\n\n/** Parse a whole config document. */\nexport function parseMcpConfig(text: string, source: string): McpConfigResult {\n\tconst diagnostics: string[] = [];\n\tlet document: unknown;\n\ttry {\n\t\tdocument = JSON.parse(text);\n\t} catch (error) {\n\t\treturn { servers: [], diagnostics: [`${source}: ${error instanceof Error ? error.message : String(error)}`] };\n\t}\n\tconst map = (document as { mcpServers?: unknown } | null)?.mcpServers;\n\tif (!map || typeof map !== \"object\") return { servers: [], diagnostics };\n\n\tconst servers: McpServerConfig[] = [];\n\tfor (const [name, raw] of Object.entries(map as Record<string, unknown>)) {\n\t\tconst parsed = parseServerEntry(name, raw);\n\t\tif (typeof parsed === \"string\") diagnostics.push(`${source}: ${parsed}`);\n\t\telse servers.push(parsed);\n\t}\n\treturn { servers, diagnostics };\n}\n\n/** Config paths, lowest precedence first: user config, then this project's. */\nexport function mcpConfigPaths(cwd: string, home: string = homedir()): string[] {\n\treturn [join(home, \".config\", \"nexus\", \"mcp.json\"), join(cwd, CONFIG_DIR_NAME, \"mcp.json\")];\n}\n\n/** Load and merge user then project config. Later files win on name collisions. */\nexport function loadMcpConfig(\n\tcwd: string,\n\treadFile: (path: string) => string = (path) => readFileSync(path, \"utf8\"),\n\thome?: string,\n): McpConfigResult {\n\tconst byName = new Map<string, McpServerConfig>();\n\tconst diagnostics: string[] = [];\n\tfor (const path of mcpConfigPaths(cwd, home)) {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = readFile(path);\n\t\t} catch {\n\t\t\tcontinue; // Absent config is the normal case, not an error.\n\t\t}\n\t\tconst parsed = parseMcpConfig(text, path);\n\t\tdiagnostics.push(...parsed.diagnostics);\n\t\tfor (const server of parsed.servers) byName.set(server.name, server);\n\t}\n\treturn { servers: [...byName.values()], diagnostics };\n}\n"]}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { CONFIG_DIR_NAME } from "../../config.js";
|
|
5
|
+
function stringRecord(value) {
|
|
6
|
+
if (!value || typeof value !== "object")
|
|
7
|
+
return {};
|
|
8
|
+
const out = {};
|
|
9
|
+
for (const [key, item] of Object.entries(value)) {
|
|
10
|
+
if (typeof item === "string")
|
|
11
|
+
out[key] = item;
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
/** Parse one `mcpServers` entry. Returns a diagnostic string when unusable. */
|
|
16
|
+
export function parseServerEntry(name, raw) {
|
|
17
|
+
if (!raw || typeof raw !== "object")
|
|
18
|
+
return `MCP server "${name}": entry is not an object`;
|
|
19
|
+
const entry = raw;
|
|
20
|
+
// `disabled` is the Claude Code spelling; accept `enabled` too so either reads naturally.
|
|
21
|
+
const enabled = entry.disabled === true ? false : entry.enabled !== false;
|
|
22
|
+
if (typeof entry.command === "string" && entry.command.trim()) {
|
|
23
|
+
return {
|
|
24
|
+
type: "stdio",
|
|
25
|
+
name,
|
|
26
|
+
command: entry.command.trim(),
|
|
27
|
+
args: Array.isArray(entry.args) ? entry.args.filter((a) => typeof a === "string") : [],
|
|
28
|
+
env: stringRecord(entry.env),
|
|
29
|
+
cwd: typeof entry.cwd === "string" ? entry.cwd : undefined,
|
|
30
|
+
enabled,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const url = typeof entry.url === "string" ? entry.url : typeof entry.httpUrl === "string" ? entry.httpUrl : undefined;
|
|
34
|
+
if (url?.trim()) {
|
|
35
|
+
return { type: "http", name, url: url.trim(), headers: stringRecord(entry.headers), enabled };
|
|
36
|
+
}
|
|
37
|
+
return `MCP server "${name}": needs either "command" (stdio) or "url" (http)`;
|
|
38
|
+
}
|
|
39
|
+
/** Parse a whole config document. */
|
|
40
|
+
export function parseMcpConfig(text, source) {
|
|
41
|
+
const diagnostics = [];
|
|
42
|
+
let document;
|
|
43
|
+
try {
|
|
44
|
+
document = JSON.parse(text);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return { servers: [], diagnostics: [`${source}: ${error instanceof Error ? error.message : String(error)}`] };
|
|
48
|
+
}
|
|
49
|
+
const map = document?.mcpServers;
|
|
50
|
+
if (!map || typeof map !== "object")
|
|
51
|
+
return { servers: [], diagnostics };
|
|
52
|
+
const servers = [];
|
|
53
|
+
for (const [name, raw] of Object.entries(map)) {
|
|
54
|
+
const parsed = parseServerEntry(name, raw);
|
|
55
|
+
if (typeof parsed === "string")
|
|
56
|
+
diagnostics.push(`${source}: ${parsed}`);
|
|
57
|
+
else
|
|
58
|
+
servers.push(parsed);
|
|
59
|
+
}
|
|
60
|
+
return { servers, diagnostics };
|
|
61
|
+
}
|
|
62
|
+
/** Config paths, lowest precedence first: user config, then this project's. */
|
|
63
|
+
export function mcpConfigPaths(cwd, home = homedir()) {
|
|
64
|
+
return [join(home, ".config", "nexus", "mcp.json"), join(cwd, CONFIG_DIR_NAME, "mcp.json")];
|
|
65
|
+
}
|
|
66
|
+
/** Load and merge user then project config. Later files win on name collisions. */
|
|
67
|
+
export function loadMcpConfig(cwd, readFile = (path) => readFileSync(path, "utf8"), home) {
|
|
68
|
+
const byName = new Map();
|
|
69
|
+
const diagnostics = [];
|
|
70
|
+
for (const path of mcpConfigPaths(cwd, home)) {
|
|
71
|
+
let text;
|
|
72
|
+
try {
|
|
73
|
+
text = readFile(path);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
continue; // Absent config is the normal case, not an error.
|
|
77
|
+
}
|
|
78
|
+
const parsed = parseMcpConfig(text, path);
|
|
79
|
+
diagnostics.push(...parsed.diagnostics);
|
|
80
|
+
for (const server of parsed.servers)
|
|
81
|
+
byName.set(server.name, server);
|
|
82
|
+
}
|
|
83
|
+
return { servers: [...byName.values()], diagnostics };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/extensions/mcp/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAuClD,SAAS,YAAY,CAAC,KAAc,EAA0B;IAC7D,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACnD,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC5E,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,CAAC;AAAA,CACX;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,GAAY,EAA4B;IACtF,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,eAAe,IAAI,2BAA2B,CAAC;IAC3F,MAAM,KAAK,GAAG,GAA8B,CAAC;IAC7C,0FAA0F;IAC1F,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC;IAE1E,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/D,OAAO;YACN,IAAI,EAAE,OAAO;YACb,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;YAC7B,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YACnG,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC;YAC5B,GAAG,EAAE,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;YAC1D,OAAO;SACP,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GACR,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3G,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/F,CAAC;IAED,OAAO,eAAe,IAAI,mDAAmD,CAAC;AAAA,CAC9E;AAED,qCAAqC;AACrC,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,MAAc,EAAmB;IAC7E,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACJ,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,GAAG,MAAM,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IAC/G,CAAC;IACD,MAAM,GAAG,GAAI,QAA4C,EAAE,UAAU,CAAC;IACtE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC;IAEzE,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;QAC1E,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;;YACpE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AAAA,CAChC;AAED,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,IAAI,GAAW,OAAO,EAAE,EAAY;IAC/E,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC;AAAA,CAC5F;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAC5B,GAAW,EACX,QAAQ,GAA6B,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EACzE,IAAa,EACK;IAClB,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAClD,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;QAC9C,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACJ,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACR,SAAS,CAAC,kDAAkD;QAC7D,CAAC;QACD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1C,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;AAAA,CACtD","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR_NAME } from \"../../config.ts\";\n\n/**\n * MCP server configuration.\n *\n * The file format is Claude Code's `mcpServers` map, deliberately: users\n * already have these configs, and copying one over should just work. A server\n * is stdio when it has `command` and HTTP when it has `url`.\n *\n * Project config wins over user config for the same server name, so a repo can\n * pin a server its contributors need without editing anyone's home directory.\n */\n\nexport interface McpStdioServer {\n\ttype: \"stdio\";\n\tname: string;\n\tcommand: string;\n\targs: string[];\n\tenv: Record<string, string>;\n\tcwd?: string;\n\tenabled: boolean;\n}\n\nexport interface McpHttpServer {\n\ttype: \"http\";\n\tname: string;\n\turl: string;\n\theaders: Record<string, string>;\n\tenabled: boolean;\n}\n\nexport type McpServerConfig = McpStdioServer | McpHttpServer;\n\nexport interface McpConfigResult {\n\tservers: McpServerConfig[];\n\t/** Human-readable problems; surfaced rather than thrown, so one bad entry cannot block startup. */\n\tdiagnostics: string[];\n}\n\nfunction stringRecord(value: unknown): Record<string, string> {\n\tif (!value || typeof value !== \"object\") return {};\n\tconst out: Record<string, string> = {};\n\tfor (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (typeof item === \"string\") out[key] = item;\n\t}\n\treturn out;\n}\n\n/** Parse one `mcpServers` entry. Returns a diagnostic string when unusable. */\nexport function parseServerEntry(name: string, raw: unknown): McpServerConfig | string {\n\tif (!raw || typeof raw !== \"object\") return `MCP server \"${name}\": entry is not an object`;\n\tconst entry = raw as Record<string, unknown>;\n\t// `disabled` is the Claude Code spelling; accept `enabled` too so either reads naturally.\n\tconst enabled = entry.disabled === true ? false : entry.enabled !== false;\n\n\tif (typeof entry.command === \"string\" && entry.command.trim()) {\n\t\treturn {\n\t\t\ttype: \"stdio\",\n\t\t\tname,\n\t\t\tcommand: entry.command.trim(),\n\t\t\targs: Array.isArray(entry.args) ? entry.args.filter((a): a is string => typeof a === \"string\") : [],\n\t\t\tenv: stringRecord(entry.env),\n\t\t\tcwd: typeof entry.cwd === \"string\" ? entry.cwd : undefined,\n\t\t\tenabled,\n\t\t};\n\t}\n\n\tconst url =\n\t\ttypeof entry.url === \"string\" ? entry.url : typeof entry.httpUrl === \"string\" ? entry.httpUrl : undefined;\n\tif (url?.trim()) {\n\t\treturn { type: \"http\", name, url: url.trim(), headers: stringRecord(entry.headers), enabled };\n\t}\n\n\treturn `MCP server \"${name}\": needs either \"command\" (stdio) or \"url\" (http)`;\n}\n\n/** Parse a whole config document. */\nexport function parseMcpConfig(text: string, source: string): McpConfigResult {\n\tconst diagnostics: string[] = [];\n\tlet document: unknown;\n\ttry {\n\t\tdocument = JSON.parse(text);\n\t} catch (error) {\n\t\treturn { servers: [], diagnostics: [`${source}: ${error instanceof Error ? error.message : String(error)}`] };\n\t}\n\tconst map = (document as { mcpServers?: unknown } | null)?.mcpServers;\n\tif (!map || typeof map !== \"object\") return { servers: [], diagnostics };\n\n\tconst servers: McpServerConfig[] = [];\n\tfor (const [name, raw] of Object.entries(map as Record<string, unknown>)) {\n\t\tconst parsed = parseServerEntry(name, raw);\n\t\tif (typeof parsed === \"string\") diagnostics.push(`${source}: ${parsed}`);\n\t\telse servers.push(parsed);\n\t}\n\treturn { servers, diagnostics };\n}\n\n/** Config paths, lowest precedence first: user config, then this project's. */\nexport function mcpConfigPaths(cwd: string, home: string = homedir()): string[] {\n\treturn [join(home, \".config\", \"nexus\", \"mcp.json\"), join(cwd, CONFIG_DIR_NAME, \"mcp.json\")];\n}\n\n/** Load and merge user then project config. Later files win on name collisions. */\nexport function loadMcpConfig(\n\tcwd: string,\n\treadFile: (path: string) => string = (path) => readFileSync(path, \"utf8\"),\n\thome?: string,\n): McpConfigResult {\n\tconst byName = new Map<string, McpServerConfig>();\n\tconst diagnostics: string[] = [];\n\tfor (const path of mcpConfigPaths(cwd, home)) {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = readFile(path);\n\t\t} catch {\n\t\t\tcontinue; // Absent config is the normal case, not an error.\n\t\t}\n\t\tconst parsed = parseMcpConfig(text, path);\n\t\tdiagnostics.push(...parsed.diagnostics);\n\t\tfor (const server of parsed.servers) byName.set(server.name, server);\n\t}\n\treturn { servers: [...byName.values()], diagnostics };\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ExtensionAPI, ToolDefinition } from "../../core/extensions/types.ts";
|
|
2
|
+
import { McpClient, type McpToolResult, type McpToolSchema } from "./client.ts";
|
|
3
|
+
/**
|
|
4
|
+
* MCP adapter: connects the servers named in mcp.json and exposes their tools
|
|
5
|
+
* to the model.
|
|
6
|
+
*
|
|
7
|
+
* Every failure here is non-fatal. A server that is missing, misconfigured, or
|
|
8
|
+
* down costs you its tools and a startup notice — it must never stop the agent
|
|
9
|
+
* from running, the same contract the gitnexus extension follows.
|
|
10
|
+
*/
|
|
11
|
+
/** Tool names are namespaced by server, so two servers can both export "search". */
|
|
12
|
+
export declare function toolName(serverName: string, tool: string): string;
|
|
13
|
+
/** Flatten an MCP result into the text the agent shows and feeds back to the model. */
|
|
14
|
+
export declare function resultToText(result: McpToolResult): string;
|
|
15
|
+
/** Build a nexus tool that proxies one MCP tool. */
|
|
16
|
+
export declare function defineProxyTool(client: McpClient, serverName: string, schema: McpToolSchema): ToolDefinition;
|
|
17
|
+
export default function mcpExtension(pi: ExtensionAPI): void;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/mcp/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,EAAiB,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAkB,MAAM,aAAa,CAAC;AAG/G;;;;;;;GAOG;AAEH,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAU1D;AAUD,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,cAAc,CAkB5G;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoC3D","sourcesContent":["import { Type } from \"typebox\";\nimport type { ExtensionAPI, ToolDefinition } from \"../../core/extensions/types.ts\";\nimport { HttpTransport, McpClient, type McpToolResult, type McpToolSchema, StdioTransport } from \"./client.ts\";\nimport { loadMcpConfig, type McpServerConfig } from \"./config.ts\";\n\n/**\n * MCP adapter: connects the servers named in mcp.json and exposes their tools\n * to the model.\n *\n * Every failure here is non-fatal. A server that is missing, misconfigured, or\n * down costs you its tools and a startup notice — it must never stop the agent\n * from running, the same contract the gitnexus extension follows.\n */\n\n/** Tool names are namespaced by server, so two servers can both export \"search\". */\nexport function toolName(serverName: string, tool: string): string {\n\tconst safe = `${serverName}_${tool}`.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t// Keep well under provider name limits; collisions stay unlikely because the\n\t// server prefix is preserved.\n\treturn safe.length <= 64 ? safe : safe.slice(0, 64);\n}\n\n/** Flatten an MCP result into the text the agent shows and feeds back to the model. */\nexport function resultToText(result: McpToolResult): string {\n\tconst text = (result.content ?? [])\n\t\t.filter((block) => block.type === \"text\" && typeof block.text === \"string\")\n\t\t.map((block) => block.text)\n\t\t.join(\"\\n\");\n\tif (text) return text;\n\t// A server that answers with only non-text blocks should say so rather than\n\t// handing the model a blank string it will read as success-with-no-data.\n\tconst kinds = [...new Set((result.content ?? []).map((block) => block.type))];\n\treturn kinds.length > 0 ? `[no text content: ${kinds.join(\", \")}]` : \"[no content]\";\n}\n\nfunction connect(server: McpServerConfig): McpClient {\n\tconst transport =\n\t\tserver.type === \"stdio\"\n\t\t\t? new StdioTransport(server.command, server.args, server.env, server.cwd)\n\t\t\t: new HttpTransport(server.url, server.headers);\n\treturn new McpClient(server.name, transport);\n}\n\n/** Build a nexus tool that proxies one MCP tool. */\nexport function defineProxyTool(client: McpClient, serverName: string, schema: McpToolSchema): ToolDefinition {\n\treturn {\n\t\tname: toolName(serverName, schema.name),\n\t\tlabel: `${serverName}:${schema.name}`,\n\t\tdescription: schema.description ?? `${schema.name} (via ${serverName} MCP server)`,\n\t\t// Pass the server's own JSON Schema straight through. Type.Unsafe wraps it\n\t\t// without reinterpreting it, so the model sees the parameters the server\n\t\t// documented and we never reject a payload the server would have accepted.\n\t\tparameters: Type.Unsafe(schema.inputSchema ?? { type: \"object\", properties: {} }),\n\t\texecute: async (_id: string, params: unknown, signal?: AbortSignal) => {\n\t\t\tconst result = await client.callTool(schema.name, (params ?? {}) as Record<string, unknown>, signal);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: resultToText(result) }],\n\t\t\t\tisError: result.isError === true,\n\t\t\t\tdetails: { server: serverName, tool: schema.name },\n\t\t\t};\n\t\t},\n\t} as unknown as ToolDefinition;\n}\n\nexport default function mcpExtension(pi: ExtensionAPI): void {\n\tconst clients: McpClient[] = [];\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tconst { servers, diagnostics } = loadMcpConfig(process.cwd());\n\t\tconst notices: string[] = [...diagnostics];\n\n\t\tconst enabled = servers.filter((server) => server.enabled);\n\t\tfor (const server of enabled) {\n\t\t\tconst client = connect(server);\n\t\t\ttry {\n\t\t\t\tconst tools = await client.listTools();\n\t\t\t\tif (tools.length === 0) {\n\t\t\t\t\tnotices.push(`MCP ${server.name}: connected but exposes no tools`);\n\t\t\t\t\tclient.close();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (const tool of tools) pi.registerTool(defineProxyTool(client, server.name, tool));\n\t\t\t\tclients.push(client);\n\t\t\t\tnotices.push(`MCP ${server.name}: ${tools.length} tool${tools.length === 1 ? \"\" : \"s\"}`);\n\t\t\t} catch (error) {\n\t\t\t\t// One unreachable server must not cost the others their tools.\n\t\t\t\tclient.close();\n\t\t\t\tnotices.push(`MCP ${server.name}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\n\t\tif (notices.length > 0) ctx.ui.notify(notices.join(\"\\n\"), \"info\");\n\t});\n\n\tpi.on(\"session_shutdown\", async () => {\n\t\t// stdio servers are child processes; leaving them running would leak one\n\t\t// per session.\n\t\tfor (const client of clients) client.close();\n\t\tclients.length = 0;\n\t});\n}\n"]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { HttpTransport, McpClient, StdioTransport } from "./client.js";
|
|
3
|
+
import { loadMcpConfig } from "./config.js";
|
|
4
|
+
/**
|
|
5
|
+
* MCP adapter: connects the servers named in mcp.json and exposes their tools
|
|
6
|
+
* to the model.
|
|
7
|
+
*
|
|
8
|
+
* Every failure here is non-fatal. A server that is missing, misconfigured, or
|
|
9
|
+
* down costs you its tools and a startup notice — it must never stop the agent
|
|
10
|
+
* from running, the same contract the gitnexus extension follows.
|
|
11
|
+
*/
|
|
12
|
+
/** Tool names are namespaced by server, so two servers can both export "search". */
|
|
13
|
+
export function toolName(serverName, tool) {
|
|
14
|
+
const safe = `${serverName}_${tool}`.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
15
|
+
// Keep well under provider name limits; collisions stay unlikely because the
|
|
16
|
+
// server prefix is preserved.
|
|
17
|
+
return safe.length <= 64 ? safe : safe.slice(0, 64);
|
|
18
|
+
}
|
|
19
|
+
/** Flatten an MCP result into the text the agent shows and feeds back to the model. */
|
|
20
|
+
export function resultToText(result) {
|
|
21
|
+
const text = (result.content ?? [])
|
|
22
|
+
.filter((block) => block.type === "text" && typeof block.text === "string")
|
|
23
|
+
.map((block) => block.text)
|
|
24
|
+
.join("\n");
|
|
25
|
+
if (text)
|
|
26
|
+
return text;
|
|
27
|
+
// A server that answers with only non-text blocks should say so rather than
|
|
28
|
+
// handing the model a blank string it will read as success-with-no-data.
|
|
29
|
+
const kinds = [...new Set((result.content ?? []).map((block) => block.type))];
|
|
30
|
+
return kinds.length > 0 ? `[no text content: ${kinds.join(", ")}]` : "[no content]";
|
|
31
|
+
}
|
|
32
|
+
function connect(server) {
|
|
33
|
+
const transport = server.type === "stdio"
|
|
34
|
+
? new StdioTransport(server.command, server.args, server.env, server.cwd)
|
|
35
|
+
: new HttpTransport(server.url, server.headers);
|
|
36
|
+
return new McpClient(server.name, transport);
|
|
37
|
+
}
|
|
38
|
+
/** Build a nexus tool that proxies one MCP tool. */
|
|
39
|
+
export function defineProxyTool(client, serverName, schema) {
|
|
40
|
+
return {
|
|
41
|
+
name: toolName(serverName, schema.name),
|
|
42
|
+
label: `${serverName}:${schema.name}`,
|
|
43
|
+
description: schema.description ?? `${schema.name} (via ${serverName} MCP server)`,
|
|
44
|
+
// Pass the server's own JSON Schema straight through. Type.Unsafe wraps it
|
|
45
|
+
// without reinterpreting it, so the model sees the parameters the server
|
|
46
|
+
// documented and we never reject a payload the server would have accepted.
|
|
47
|
+
parameters: Type.Unsafe(schema.inputSchema ?? { type: "object", properties: {} }),
|
|
48
|
+
execute: async (_id, params, signal) => {
|
|
49
|
+
const result = await client.callTool(schema.name, (params ?? {}), signal);
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: resultToText(result) }],
|
|
52
|
+
isError: result.isError === true,
|
|
53
|
+
details: { server: serverName, tool: schema.name },
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export default function mcpExtension(pi) {
|
|
59
|
+
const clients = [];
|
|
60
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
61
|
+
const { servers, diagnostics } = loadMcpConfig(process.cwd());
|
|
62
|
+
const notices = [...diagnostics];
|
|
63
|
+
const enabled = servers.filter((server) => server.enabled);
|
|
64
|
+
for (const server of enabled) {
|
|
65
|
+
const client = connect(server);
|
|
66
|
+
try {
|
|
67
|
+
const tools = await client.listTools();
|
|
68
|
+
if (tools.length === 0) {
|
|
69
|
+
notices.push(`MCP ${server.name}: connected but exposes no tools`);
|
|
70
|
+
client.close();
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
for (const tool of tools)
|
|
74
|
+
pi.registerTool(defineProxyTool(client, server.name, tool));
|
|
75
|
+
clients.push(client);
|
|
76
|
+
notices.push(`MCP ${server.name}: ${tools.length} tool${tools.length === 1 ? "" : "s"}`);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
// One unreachable server must not cost the others their tools.
|
|
80
|
+
client.close();
|
|
81
|
+
notices.push(`MCP ${server.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (notices.length > 0)
|
|
85
|
+
ctx.ui.notify(notices.join("\n"), "info");
|
|
86
|
+
});
|
|
87
|
+
pi.on("session_shutdown", async () => {
|
|
88
|
+
// stdio servers are child processes; leaving them running would leak one
|
|
89
|
+
// per session.
|
|
90
|
+
for (const client of clients)
|
|
91
|
+
client.close();
|
|
92
|
+
clients.length = 0;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/mcp/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"typebox\";\nimport type { ExtensionAPI, ToolDefinition } from \"../../core/extensions/types.ts\";\nimport { HttpTransport, McpClient, type McpToolResult, type McpToolSchema, StdioTransport } from \"./client.ts\";\nimport { loadMcpConfig, type McpServerConfig } from \"./config.ts\";\n\n/**\n * MCP adapter: connects the servers named in mcp.json and exposes their tools\n * to the model.\n *\n * Every failure here is non-fatal. A server that is missing, misconfigured, or\n * down costs you its tools and a startup notice — it must never stop the agent\n * from running, the same contract the gitnexus extension follows.\n */\n\n/** Tool names are namespaced by server, so two servers can both export \"search\". */\nexport function toolName(serverName: string, tool: string): string {\n\tconst safe = `${serverName}_${tool}`.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t// Keep well under provider name limits; collisions stay unlikely because the\n\t// server prefix is preserved.\n\treturn safe.length <= 64 ? safe : safe.slice(0, 64);\n}\n\n/** Flatten an MCP result into the text the agent shows and feeds back to the model. */\nexport function resultToText(result: McpToolResult): string {\n\tconst text = (result.content ?? [])\n\t\t.filter((block) => block.type === \"text\" && typeof block.text === \"string\")\n\t\t.map((block) => block.text)\n\t\t.join(\"\\n\");\n\tif (text) return text;\n\t// A server that answers with only non-text blocks should say so rather than\n\t// handing the model a blank string it will read as success-with-no-data.\n\tconst kinds = [...new Set((result.content ?? []).map((block) => block.type))];\n\treturn kinds.length > 0 ? `[no text content: ${kinds.join(\", \")}]` : \"[no content]\";\n}\n\nfunction connect(server: McpServerConfig): McpClient {\n\tconst transport =\n\t\tserver.type === \"stdio\"\n\t\t\t? new StdioTransport(server.command, server.args, server.env, server.cwd)\n\t\t\t: new HttpTransport(server.url, server.headers);\n\treturn new McpClient(server.name, transport);\n}\n\n/** Build a nexus tool that proxies one MCP tool. */\nexport function defineProxyTool(client: McpClient, serverName: string, schema: McpToolSchema): ToolDefinition {\n\treturn {\n\t\tname: toolName(serverName, schema.name),\n\t\tlabel: `${serverName}:${schema.name}`,\n\t\tdescription: schema.description ?? `${schema.name} (via ${serverName} MCP server)`,\n\t\t// Pass the server's own JSON Schema straight through. Type.Unsafe wraps it\n\t\t// without reinterpreting it, so the model sees the parameters the server\n\t\t// documented and we never reject a payload the server would have accepted.\n\t\tparameters: Type.Unsafe(schema.inputSchema ?? { type: \"object\", properties: {} }),\n\t\texecute: async (_id: string, params: unknown, signal?: AbortSignal) => {\n\t\t\tconst result = await client.callTool(schema.name, (params ?? {}) as Record<string, unknown>, signal);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: resultToText(result) }],\n\t\t\t\tisError: result.isError === true,\n\t\t\t\tdetails: { server: serverName, tool: schema.name },\n\t\t\t};\n\t\t},\n\t} as unknown as ToolDefinition;\n}\n\nexport default function mcpExtension(pi: ExtensionAPI): void {\n\tconst clients: McpClient[] = [];\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tconst { servers, diagnostics } = loadMcpConfig(process.cwd());\n\t\tconst notices: string[] = [...diagnostics];\n\n\t\tconst enabled = servers.filter((server) => server.enabled);\n\t\tfor (const server of enabled) {\n\t\t\tconst client = connect(server);\n\t\t\ttry {\n\t\t\t\tconst tools = await client.listTools();\n\t\t\t\tif (tools.length === 0) {\n\t\t\t\t\tnotices.push(`MCP ${server.name}: connected but exposes no tools`);\n\t\t\t\t\tclient.close();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (const tool of tools) pi.registerTool(defineProxyTool(client, server.name, tool));\n\t\t\t\tclients.push(client);\n\t\t\t\tnotices.push(`MCP ${server.name}: ${tools.length} tool${tools.length === 1 ? \"\" : \"s\"}`);\n\t\t\t} catch (error) {\n\t\t\t\t// One unreachable server must not cost the others their tools.\n\t\t\t\tclient.close();\n\t\t\t\tnotices.push(`MCP ${server.name}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\n\t\tif (notices.length > 0) ctx.ui.notify(notices.join(\"\\n\"), \"info\");\n\t});\n\n\tpi.on(\"session_shutdown\", async () => {\n\t\t// stdio servers are child processes; leaving them running would leak one\n\t\t// per session.\n\t\tfor (const client of clients) client.close();\n\t\tclients.length = 0;\n\t});\n}\n"]}
|