@chances-ai/engine 24.0.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/dist/agents/discover.d.ts +30 -0
- package/dist/agents/discover.d.ts.map +1 -0
- package/dist/agents/discover.js +183 -0
- package/dist/agents/discover.js.map +1 -0
- package/dist/agents/index.d.ts +20 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +52 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/parse.d.ts +61 -0
- package/dist/agents/parse.d.ts.map +1 -0
- package/dist/agents/parse.js +527 -0
- package/dist/agents/parse.js.map +1 -0
- package/dist/agents/types.d.ts +52 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +8 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/ai/adapters/ai-sdk-stream.d.ts +19 -0
- package/dist/ai/adapters/ai-sdk-stream.d.ts.map +1 -0
- package/dist/ai/adapters/ai-sdk-stream.js +125 -0
- package/dist/ai/adapters/ai-sdk-stream.js.map +1 -0
- package/dist/ai/adapters/ai-sdk.d.ts +56 -0
- package/dist/ai/adapters/ai-sdk.d.ts.map +1 -0
- package/dist/ai/adapters/ai-sdk.js +112 -0
- package/dist/ai/adapters/ai-sdk.js.map +1 -0
- package/dist/ai/adapters/mock.d.ts +13 -0
- package/dist/ai/adapters/mock.d.ts.map +1 -0
- package/dist/ai/adapters/mock.js +54 -0
- package/dist/ai/adapters/mock.js.map +1 -0
- package/dist/ai/adapters/openai-compatible.d.ts +23 -0
- package/dist/ai/adapters/openai-compatible.d.ts.map +1 -0
- package/dist/ai/adapters/openai-compatible.js +45 -0
- package/dist/ai/adapters/openai-compatible.js.map +1 -0
- package/dist/ai/cost.d.ts +3 -0
- package/dist/ai/cost.d.ts.map +1 -0
- package/dist/ai/cost.js +5 -0
- package/dist/ai/cost.js.map +1 -0
- package/dist/ai/index.d.ts +12 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +11 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/known-models.d.ts +20 -0
- package/dist/ai/known-models.d.ts.map +1 -0
- package/dist/ai/known-models.js +129 -0
- package/dist/ai/known-models.js.map +1 -0
- package/dist/ai/registry.d.ts +12 -0
- package/dist/ai/registry.d.ts.map +1 -0
- package/dist/ai/registry.js +24 -0
- package/dist/ai/registry.js.map +1 -0
- package/dist/ai/retry.d.ts +11 -0
- package/dist/ai/retry.d.ts.map +1 -0
- package/dist/ai/retry.js +14 -0
- package/dist/ai/retry.js.map +1 -0
- package/dist/ai/router.d.ts +25 -0
- package/dist/ai/router.d.ts.map +1 -0
- package/dist/ai/router.js +36 -0
- package/dist/ai/router.js.map +1 -0
- package/dist/ai/setup.d.ts +23 -0
- package/dist/ai/setup.d.ts.map +1 -0
- package/dist/ai/setup.js +47 -0
- package/dist/ai/setup.js.map +1 -0
- package/dist/ai/summarizer.d.ts +24 -0
- package/dist/ai/summarizer.d.ts.map +1 -0
- package/dist/ai/summarizer.js +56 -0
- package/dist/ai/summarizer.js.map +1 -0
- package/dist/ai/types.d.ts +83 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +2 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/core/compaction/circuit-breaker.d.ts +32 -0
- package/dist/core/compaction/circuit-breaker.d.ts.map +1 -0
- package/dist/core/compaction/circuit-breaker.js +42 -0
- package/dist/core/compaction/circuit-breaker.js.map +1 -0
- package/dist/core/compaction/compactor.d.ts +75 -0
- package/dist/core/compaction/compactor.d.ts.map +1 -0
- package/dist/core/compaction/compactor.js +261 -0
- package/dist/core/compaction/compactor.js.map +1 -0
- package/dist/core/compaction/estimate.d.ts +39 -0
- package/dist/core/compaction/estimate.d.ts.map +1 -0
- package/dist/core/compaction/estimate.js +74 -0
- package/dist/core/compaction/estimate.js.map +1 -0
- package/dist/core/compaction/index.d.ts +5 -0
- package/dist/core/compaction/index.d.ts.map +1 -0
- package/dist/core/compaction/index.js +5 -0
- package/dist/core/compaction/index.js.map +1 -0
- package/dist/core/compaction/prune.d.ts +43 -0
- package/dist/core/compaction/prune.d.ts.map +1 -0
- package/dist/core/compaction/prune.js +51 -0
- package/dist/core/compaction/prune.js.map +1 -0
- package/dist/core/engine.d.ts +268 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +767 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/task-tool.d.ts +175 -0
- package/dist/core/task-tool.d.ts.map +1 -0
- package/dist/core/task-tool.js +901 -0
- package/dist/core/task-tool.js.map +1 -0
- package/dist/core/workspace-query.d.ts +83 -0
- package/dist/core/workspace-query.d.ts.map +1 -0
- package/dist/core/workspace-query.js +217 -0
- package/dist/core/workspace-query.js.map +1 -0
- package/dist/core/worktree/active-marker.d.ts +31 -0
- package/dist/core/worktree/active-marker.d.ts.map +1 -0
- package/dist/core/worktree/active-marker.js +109 -0
- package/dist/core/worktree/active-marker.js.map +1 -0
- package/dist/core/worktree/create.d.ts +40 -0
- package/dist/core/worktree/create.d.ts.map +1 -0
- package/dist/core/worktree/create.js +121 -0
- package/dist/core/worktree/create.js.map +1 -0
- package/dist/core/worktree/errors.d.ts +7 -0
- package/dist/core/worktree/errors.d.ts.map +1 -0
- package/dist/core/worktree/errors.js +11 -0
- package/dist/core/worktree/errors.js.map +1 -0
- package/dist/core/worktree/gc.d.ts +39 -0
- package/dist/core/worktree/gc.d.ts.map +1 -0
- package/dist/core/worktree/gc.js +146 -0
- package/dist/core/worktree/gc.js.map +1 -0
- package/dist/core/worktree/git.d.ts +53 -0
- package/dist/core/worktree/git.d.ts.map +1 -0
- package/dist/core/worktree/git.js +166 -0
- package/dist/core/worktree/git.js.map +1 -0
- package/dist/core/worktree/index.d.ts +8 -0
- package/dist/core/worktree/index.d.ts.map +1 -0
- package/dist/core/worktree/index.js +8 -0
- package/dist/core/worktree/index.js.map +1 -0
- package/dist/core/worktree/paths.d.ts +26 -0
- package/dist/core/worktree/paths.d.ts.map +1 -0
- package/dist/core/worktree/paths.js +57 -0
- package/dist/core/worktree/paths.js.map +1 -0
- package/dist/core/worktree/slug.d.ts +6 -0
- package/dist/core/worktree/slug.d.ts.map +1 -0
- package/dist/core/worktree/slug.js +21 -0
- package/dist/core/worktree/slug.js.map +1 -0
- package/dist/local-vault/file-store.d.ts +64 -0
- package/dist/local-vault/file-store.d.ts.map +1 -0
- package/dist/local-vault/file-store.js +225 -0
- package/dist/local-vault/file-store.js.map +1 -0
- package/dist/local-vault/index.d.ts +57 -0
- package/dist/local-vault/index.d.ts.map +1 -0
- package/dist/local-vault/index.js +68 -0
- package/dist/local-vault/index.js.map +1 -0
- package/dist/local-vault/keychain.d.ts +58 -0
- package/dist/local-vault/keychain.d.ts.map +1 -0
- package/dist/local-vault/keychain.js +200 -0
- package/dist/local-vault/keychain.js.map +1 -0
- package/dist/local-vault/mutex.d.ts +20 -0
- package/dist/local-vault/mutex.d.ts.map +1 -0
- package/dist/local-vault/mutex.js +44 -0
- package/dist/local-vault/mutex.js.map +1 -0
- package/dist/local-vault/passphrase.d.ts +30 -0
- package/dist/local-vault/passphrase.d.ts.map +1 -0
- package/dist/local-vault/passphrase.js +72 -0
- package/dist/local-vault/passphrase.js.map +1 -0
- package/dist/lsp/config.d.ts +34 -0
- package/dist/lsp/config.d.ts.map +1 -0
- package/dist/lsp/config.js +68 -0
- package/dist/lsp/config.js.map +1 -0
- package/dist/lsp/detect.d.ts +7 -0
- package/dist/lsp/detect.d.ts.map +1 -0
- package/dist/lsp/detect.js +78 -0
- package/dist/lsp/detect.js.map +1 -0
- package/dist/lsp/errors.d.ts +11 -0
- package/dist/lsp/errors.d.ts.map +1 -0
- package/dist/lsp/errors.js +11 -0
- package/dist/lsp/errors.js.map +1 -0
- package/dist/lsp/formatters.d.ts +147 -0
- package/dist/lsp/formatters.d.ts.map +1 -0
- package/dist/lsp/formatters.js +259 -0
- package/dist/lsp/formatters.js.map +1 -0
- package/dist/lsp/index.d.ts +31 -0
- package/dist/lsp/index.d.ts.map +1 -0
- package/dist/lsp/index.js +31 -0
- package/dist/lsp/index.js.map +1 -0
- package/dist/lsp/instance.d.ts +72 -0
- package/dist/lsp/instance.d.ts.map +1 -0
- package/dist/lsp/instance.js +489 -0
- package/dist/lsp/instance.js.map +1 -0
- package/dist/lsp/lazy-load.d.ts +27 -0
- package/dist/lsp/lazy-load.d.ts.map +1 -0
- package/dist/lsp/lazy-load.js +57 -0
- package/dist/lsp/lazy-load.js.map +1 -0
- package/dist/lsp/manager.d.ts +59 -0
- package/dist/lsp/manager.d.ts.map +1 -0
- package/dist/lsp/manager.js +242 -0
- package/dist/lsp/manager.js.map +1 -0
- package/dist/lsp/ops.d.ts +13 -0
- package/dist/lsp/ops.d.ts.map +1 -0
- package/dist/lsp/ops.js +225 -0
- package/dist/lsp/ops.js.map +1 -0
- package/dist/lsp/rpc.d.ts +47 -0
- package/dist/lsp/rpc.d.ts.map +1 -0
- package/dist/lsp/rpc.js +134 -0
- package/dist/lsp/rpc.js.map +1 -0
- package/dist/lsp/safe-uri.d.ts +18 -0
- package/dist/lsp/safe-uri.d.ts.map +1 -0
- package/dist/lsp/safe-uri.js +96 -0
- package/dist/lsp/safe-uri.js.map +1 -0
- package/dist/lsp/types.d.ts +70 -0
- package/dist/lsp/types.d.ts.map +1 -0
- package/dist/lsp/types.js +16 -0
- package/dist/lsp/types.js.map +1 -0
- package/dist/mcp/bridge.d.ts +57 -0
- package/dist/mcp/bridge.d.ts.map +1 -0
- package/dist/mcp/bridge.js +98 -0
- package/dist/mcp/bridge.js.map +1 -0
- package/dist/mcp/category.d.ts +22 -0
- package/dist/mcp/category.d.ts.map +1 -0
- package/dist/mcp/category.js +11 -0
- package/dist/mcp/category.js.map +1 -0
- package/dist/mcp/client.d.ts +228 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +352 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/content.d.ts +86 -0
- package/dist/mcp/content.d.ts.map +1 -0
- package/dist/mcp/content.js +147 -0
- package/dist/mcp/content.js.map +1 -0
- package/dist/mcp/env.d.ts +19 -0
- package/dist/mcp/env.d.ts.map +1 -0
- package/dist/mcp/env.js +50 -0
- package/dist/mcp/env.js.map +1 -0
- package/dist/mcp/host.d.ts +199 -0
- package/dist/mcp/host.d.ts.map +1 -0
- package/dist/mcp/host.js +530 -0
- package/dist/mcp/host.js.map +1 -0
- package/dist/mcp/index.d.ts +18 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +17 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/load-mcp-host.d.ts +32 -0
- package/dist/mcp/load-mcp-host.d.ts.map +1 -0
- package/dist/mcp/load-mcp-host.js +49 -0
- package/dist/mcp/load-mcp-host.js.map +1 -0
- package/dist/mcp/oauth/callback-server.d.ts +73 -0
- package/dist/mcp/oauth/callback-server.d.ts.map +1 -0
- package/dist/mcp/oauth/callback-server.js +280 -0
- package/dist/mcp/oauth/callback-server.js.map +1 -0
- package/dist/mcp/oauth/config-hash.d.ts +24 -0
- package/dist/mcp/oauth/config-hash.d.ts.map +1 -0
- package/dist/mcp/oauth/config-hash.js +55 -0
- package/dist/mcp/oauth/config-hash.js.map +1 -0
- package/dist/mcp/oauth/error-normalize.d.ts +39 -0
- package/dist/mcp/oauth/error-normalize.d.ts.map +1 -0
- package/dist/mcp/oauth/error-normalize.js +91 -0
- package/dist/mcp/oauth/error-normalize.js.map +1 -0
- package/dist/mcp/oauth/provider.d.ts +190 -0
- package/dist/mcp/oauth/provider.d.ts.map +1 -0
- package/dist/mcp/oauth/provider.js +305 -0
- package/dist/mcp/oauth/provider.js.map +1 -0
- package/dist/mcp/oauth/refresh-coalescer.d.ts +46 -0
- package/dist/mcp/oauth/refresh-coalescer.d.ts.map +1 -0
- package/dist/mcp/oauth/refresh-coalescer.js +77 -0
- package/dist/mcp/oauth/refresh-coalescer.js.map +1 -0
- package/dist/mcp/oauth/sdk-shapes.d.ts +77 -0
- package/dist/mcp/oauth/sdk-shapes.d.ts.map +1 -0
- package/dist/mcp/oauth/sdk-shapes.js +21 -0
- package/dist/mcp/oauth/sdk-shapes.js.map +1 -0
- package/dist/mcp/parse.d.ts +28 -0
- package/dist/mcp/parse.d.ts.map +1 -0
- package/dist/mcp/parse.js +209 -0
- package/dist/mcp/parse.js.map +1 -0
- package/dist/mcp/prompts.d.ts +31 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +71 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/redact.d.ts +62 -0
- package/dist/mcp/redact.d.ts.map +1 -0
- package/dist/mcp/redact.js +87 -0
- package/dist/mcp/redact.js.map +1 -0
- package/dist/mcp/resources.d.ts +70 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +170 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/types.d.ts +123 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/memory/frontmatter.d.ts +18 -0
- package/dist/memory/frontmatter.d.ts.map +1 -0
- package/dist/memory/frontmatter.js +81 -0
- package/dist/memory/frontmatter.js.map +1 -0
- package/dist/memory/index.d.ts +5 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +5 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/store.d.ts +44 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +237 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/tools.d.ts +11 -0
- package/dist/memory/tools.d.ts.map +1 -0
- package/dist/memory/tools.js +159 -0
- package/dist/memory/tools.js.map +1 -0
- package/dist/memory/types.d.ts +32 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +20 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/plugin-api/index.d.ts +167 -0
- package/dist/plugin-api/index.d.ts.map +1 -0
- package/dist/plugin-api/index.js +151 -0
- package/dist/plugin-api/index.js.map +1 -0
- package/dist/plugin-logger/index.d.ts +21 -0
- package/dist/plugin-logger/index.d.ts.map +1 -0
- package/dist/plugin-logger/index.js +59 -0
- package/dist/plugin-logger/index.js.map +1 -0
- package/dist/session/index.d.ts +125 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +202 -0
- package/dist/session/index.js.map +1 -0
- package/dist/tools/approval.d.ts +33 -0
- package/dist/tools/approval.d.ts.map +1 -0
- package/dist/tools/approval.js +53 -0
- package/dist/tools/approval.js.map +1 -0
- package/dist/tools/builtins/_shared.d.ts +94 -0
- package/dist/tools/builtins/_shared.d.ts.map +1 -0
- package/dist/tools/builtins/_shared.js +246 -0
- package/dist/tools/builtins/_shared.js.map +1 -0
- package/dist/tools/builtins/ask-user-question.d.ts +27 -0
- package/dist/tools/builtins/ask-user-question.d.ts.map +1 -0
- package/dist/tools/builtins/ask-user-question.js +191 -0
- package/dist/tools/builtins/ask-user-question.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts +3 -0
- package/dist/tools/builtins/bash.d.ts.map +1 -0
- package/dist/tools/builtins/bash.js +158 -0
- package/dist/tools/builtins/bash.js.map +1 -0
- package/dist/tools/builtins/diff.d.ts +3 -0
- package/dist/tools/builtins/diff.d.ts.map +1 -0
- package/dist/tools/builtins/diff.js +83 -0
- package/dist/tools/builtins/diff.js.map +1 -0
- package/dist/tools/builtins/edit.d.ts +3 -0
- package/dist/tools/builtins/edit.d.ts.map +1 -0
- package/dist/tools/builtins/edit.js +40 -0
- package/dist/tools/builtins/edit.js.map +1 -0
- package/dist/tools/builtins/glob.d.ts +3 -0
- package/dist/tools/builtins/glob.d.ts.map +1 -0
- package/dist/tools/builtins/glob.js +37 -0
- package/dist/tools/builtins/glob.js.map +1 -0
- package/dist/tools/builtins/grep.d.ts +3 -0
- package/dist/tools/builtins/grep.d.ts.map +1 -0
- package/dist/tools/builtins/grep.js +81 -0
- package/dist/tools/builtins/grep.js.map +1 -0
- package/dist/tools/builtins/lsp.d.ts +3 -0
- package/dist/tools/builtins/lsp.d.ts.map +1 -0
- package/dist/tools/builtins/lsp.js +102 -0
- package/dist/tools/builtins/lsp.js.map +1 -0
- package/dist/tools/builtins/pty.d.ts +64 -0
- package/dist/tools/builtins/pty.d.ts.map +1 -0
- package/dist/tools/builtins/pty.js +536 -0
- package/dist/tools/builtins/pty.js.map +1 -0
- package/dist/tools/builtins/read.d.ts +3 -0
- package/dist/tools/builtins/read.d.ts.map +1 -0
- package/dist/tools/builtins/read.js +18 -0
- package/dist/tools/builtins/read.js.map +1 -0
- package/dist/tools/builtins/web-fetch.d.ts +4 -0
- package/dist/tools/builtins/web-fetch.d.ts.map +1 -0
- package/dist/tools/builtins/web-fetch.js +353 -0
- package/dist/tools/builtins/web-fetch.js.map +1 -0
- package/dist/tools/builtins/write.d.ts +3 -0
- package/dist/tools/builtins/write.d.ts.map +1 -0
- package/dist/tools/builtins/write.js +48 -0
- package/dist/tools/builtins/write.js.map +1 -0
- package/dist/tools/builtins.d.ts +9 -0
- package/dist/tools/builtins.d.ts.map +1 -0
- package/dist/tools/builtins.js +29 -0
- package/dist/tools/builtins.js.map +1 -0
- package/dist/tools/diff.d.ts +18 -0
- package/dist/tools/diff.d.ts.map +1 -0
- package/dist/tools/diff.js +57 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/permission.d.ts +120 -0
- package/dist/tools/permission.d.ts.map +1 -0
- package/dist/tools/permission.js +208 -0
- package/dist/tools/permission.js.map +1 -0
- package/dist/tools/registry.d.ts +12 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +19 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +244 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +15 -0
- package/dist/tools/types.js.map +1 -0
- package/package.json +109 -0
package/dist/lsp/rpc.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (4.2) RPC layer with per-request ownership.
|
|
3
|
+
*
|
|
4
|
+
* Wraps a `vscode-jsonrpc` MessageConnection with a per-instance
|
|
5
|
+
* `pending` map. Every `sendRequest`:
|
|
6
|
+
* 1. Registers a pending entry BEFORE the wire write so a concurrent
|
|
7
|
+
* crash can `rejectAll` deterministically.
|
|
8
|
+
* 2. Drives cancellation via a vscode-jsonrpc `CancellationToken`
|
|
9
|
+
* (codex Round-2 MUST-FIX #2 — using a synthetic id sent in
|
|
10
|
+
* `$/cancelRequest` would target the WRONG request because
|
|
11
|
+
* vscode-jsonrpc owns the wire-level id internally). `signal`
|
|
12
|
+
* aborts and timeouts both `cancel()` the token; vscode-jsonrpc
|
|
13
|
+
* emits the correct `$/cancelRequest` itself.
|
|
14
|
+
* 3. On response / error / timeout / cancel: removes the entry.
|
|
15
|
+
*
|
|
16
|
+
* Tests provide a `FakeConnection` that satisfies the small
|
|
17
|
+
* `Connection` shape; the `token` parameter is optional so fakes
|
|
18
|
+
* don't need to ship a CancellationToken implementation.
|
|
19
|
+
*/
|
|
20
|
+
import { AppError, ErrorCode } from "@chances-ai/runtime";
|
|
21
|
+
import { LspError } from "./errors.js";
|
|
22
|
+
/** Tracks in-flight requests for an LSP instance. One per
|
|
23
|
+
* LspServerInstance. */
|
|
24
|
+
export class PendingRegistry {
|
|
25
|
+
entries = new Map();
|
|
26
|
+
nextId = 1;
|
|
27
|
+
/** Optional factory for cancellation token sources. Set by
|
|
28
|
+
* `LspServerInstance` when it knows vscode-jsonrpc is loaded; null
|
|
29
|
+
* in tests so the FakeConnection path stays simple. */
|
|
30
|
+
ctsFactory;
|
|
31
|
+
setCancellationFactory(factory) {
|
|
32
|
+
this.ctsFactory = factory;
|
|
33
|
+
}
|
|
34
|
+
get activeRequests() {
|
|
35
|
+
return this.entries.size;
|
|
36
|
+
}
|
|
37
|
+
/** Issues a request through the underlying connection, registering
|
|
38
|
+
* ownership BEFORE the wire write so cancellation is always safe.
|
|
39
|
+
* Cancellation propagates through the optional CancellationToken so
|
|
40
|
+
* vscode-jsonrpc emits `$/cancelRequest` with the correct id. */
|
|
41
|
+
async send(opts) {
|
|
42
|
+
const { connection, method, params, signal, requestTimeoutMs } = opts;
|
|
43
|
+
if (signal.aborted)
|
|
44
|
+
throw new AppError(ErrorCode.Cancelled, "lsp request cancelled before send");
|
|
45
|
+
const id = this.nextId++;
|
|
46
|
+
let abortListener;
|
|
47
|
+
let timer;
|
|
48
|
+
let entryReject;
|
|
49
|
+
let settled = false;
|
|
50
|
+
const cts = this.ctsFactory?.();
|
|
51
|
+
const cleanup = () => {
|
|
52
|
+
if (settled)
|
|
53
|
+
return;
|
|
54
|
+
settled = true;
|
|
55
|
+
this.entries.delete(id);
|
|
56
|
+
if (abortListener)
|
|
57
|
+
signal.removeEventListener("abort", abortListener);
|
|
58
|
+
if (timer !== undefined)
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
try {
|
|
61
|
+
cts?.dispose();
|
|
62
|
+
}
|
|
63
|
+
catch { /* ignore */ }
|
|
64
|
+
};
|
|
65
|
+
const entry = {
|
|
66
|
+
id,
|
|
67
|
+
method,
|
|
68
|
+
startedAt: Date.now(),
|
|
69
|
+
reject: (err) => {
|
|
70
|
+
if (entryReject)
|
|
71
|
+
entryReject(err);
|
|
72
|
+
},
|
|
73
|
+
cleanup,
|
|
74
|
+
cts,
|
|
75
|
+
};
|
|
76
|
+
this.entries.set(id, entry);
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
entryReject = (err) => {
|
|
79
|
+
cleanup();
|
|
80
|
+
reject(err);
|
|
81
|
+
};
|
|
82
|
+
abortListener = () => {
|
|
83
|
+
// Use the token path so vscode-jsonrpc emits $/cancelRequest with
|
|
84
|
+
// the correct wire-level id. No `connection.sendNotification`
|
|
85
|
+
// anywhere — the previous implementation invented an id that
|
|
86
|
+
// didn't correspond to any real in-flight request.
|
|
87
|
+
try {
|
|
88
|
+
cts?.cancel();
|
|
89
|
+
}
|
|
90
|
+
catch { /* ignore */ }
|
|
91
|
+
entryReject?.(new AppError(ErrorCode.Cancelled, `lsp ${method} cancelled`));
|
|
92
|
+
};
|
|
93
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
94
|
+
timer = setTimeout(() => {
|
|
95
|
+
try {
|
|
96
|
+
cts?.cancel();
|
|
97
|
+
}
|
|
98
|
+
catch { /* ignore */ }
|
|
99
|
+
entryReject?.(new LspError("REQUEST_TIMEOUT", `lsp ${method} timed out after ${requestTimeoutMs}ms`));
|
|
100
|
+
}, requestTimeoutMs);
|
|
101
|
+
void connection.sendRequest(method, params, cts?.token).then((value) => {
|
|
102
|
+
if (settled)
|
|
103
|
+
return;
|
|
104
|
+
cleanup();
|
|
105
|
+
resolve(value);
|
|
106
|
+
}, (err) => {
|
|
107
|
+
if (settled)
|
|
108
|
+
return;
|
|
109
|
+
cleanup();
|
|
110
|
+
reject(err);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/** Rejects every pending request with `cause`. Used on connection
|
|
115
|
+
* close so a subsequent restart can never resurrect a stale id.
|
|
116
|
+
* (codex Round-1 MUST-FIX #5.) */
|
|
117
|
+
rejectAll(cause) {
|
|
118
|
+
const entries = Array.from(this.entries.values());
|
|
119
|
+
this.entries.clear();
|
|
120
|
+
for (const entry of entries) {
|
|
121
|
+
try {
|
|
122
|
+
entry.cts?.cancel();
|
|
123
|
+
}
|
|
124
|
+
catch { /* ignore */ }
|
|
125
|
+
try {
|
|
126
|
+
entry.reject(cause);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
/* listener already detached; swallow */
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=rpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/lsp/rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAoCvC;yBACyB;AACzB,MAAM,OAAO,eAAe;IACT,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IACnD,MAAM,GAAG,CAAC,CAAC;IACnB;;4DAEwD;IAChD,UAAU,CAAiC;IAEnD,sBAAsB,CAAC,OAAoD;QACzE,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;IAC5B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;;sEAGkE;IAClE,KAAK,CAAC,IAAI,CAAI,IAMb;QACC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;QACtE,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,mCAAmC,CAAC,CAAC;QAEjG,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,IAAI,aAAuC,CAAC;QAC5C,IAAI,KAAgD,CAAC;QACrD,IAAI,WAA+C,CAAC;QACpD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QAEhC,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxB,IAAI,aAAa;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YACtE,IAAI,KAAK,KAAK,SAAS;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC7C,IAAI,CAAC;gBAAC,GAAG,EAAE,OAAO,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAChD,CAAC,CAAC;QAEF,MAAM,KAAK,GAAiB;YAC1B,EAAE;YACF,MAAM;YACN,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM,EAAE,CAAC,GAAU,EAAE,EAAE;gBACrB,IAAI,WAAW;oBAAE,WAAW,CAAC,GAAG,CAAC,CAAC;YACpC,CAAC;YACD,OAAO;YACP,GAAG;SACJ,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAE5B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,WAAW,GAAG,CAAC,GAAG,EAAE,EAAE;gBACpB,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC;YAEF,aAAa,GAAG,GAAG,EAAE;gBACnB,kEAAkE;gBAClE,8DAA8D;gBAC9D,6DAA6D;gBAC7D,mDAAmD;gBACnD,IAAI,CAAC;oBAAC,GAAG,EAAE,MAAM,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC7C,WAAW,EAAE,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,MAAM,YAAY,CAAC,CAAC,CAAC;YAC9E,CAAC,CAAC;YACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAEhE,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBACtB,IAAI,CAAC;oBAAC,GAAG,EAAE,MAAM,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC7C,WAAW,EAAE,CAAC,IAAI,QAAQ,CAAC,iBAAiB,EAAE,OAAO,MAAM,oBAAoB,gBAAgB,IAAI,CAAC,CAAC,CAAC;YACxG,CAAC,EAAE,gBAAgB,CAAC,CAAC;YAErB,KAAK,UAAU,CAAC,WAAW,CAAI,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,IAAI,CAC7D,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;gBACN,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;uCAEmC;IACnC,SAAS,CAAC,KAAY;QACpB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YACxB,IAAI,CAAC;gBACH,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,wCAAwC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ContainResult {
|
|
2
|
+
/** Resolved absolute path (realpath when extant). */
|
|
3
|
+
abs: string;
|
|
4
|
+
/** Path relative to `workspaceRoot`, or undefined when outside. */
|
|
5
|
+
rel?: string;
|
|
6
|
+
/** True when `abs` resolves OUTSIDE `workspaceRoot`. */
|
|
7
|
+
external: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Converts a `file://` URI (or absolute path) to a safe-containment
|
|
10
|
+
* triple. Symlinks inside the workspace are resolved through
|
|
11
|
+
* `realpath` so a symlink-to-outside is caught. Non-extant leaves
|
|
12
|
+
* walk up to the nearest existing ancestor (matches the `safePath`
|
|
13
|
+
* pattern in `_shared.ts`) so a path like `<ws>/does-not-exist.ts`
|
|
14
|
+
* on a symlinked tmpdir resolves correctly. */
|
|
15
|
+
export declare function containUri(uri: string, workspaceRoot: string): ContainResult;
|
|
16
|
+
/** For navigable results — returns the relative path or `null`. */
|
|
17
|
+
export declare function containLocationUri(uri: string, workspaceRoot: string): string | null;
|
|
18
|
+
//# sourceMappingURL=safe-uri.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-uri.d.ts","sourceRoot":"","sources":["../../src/lsp/safe-uri.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;gDAKgD;AAChD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,aAAa,CAe5E;AAwCD,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGpF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (4.2) URI containment for server-returned locations
|
|
3
|
+
* (codex Round-1 MUST-FIX #3).
|
|
4
|
+
*
|
|
5
|
+
* LSP servers can return arbitrary `file://` URIs in `Location`,
|
|
6
|
+
* `LocationLink`, `SymbolInformation`, and `CallHierarchyItem`.
|
|
7
|
+
* We must NOT format those directly as relative paths: in a
|
|
8
|
+
* worktree-isolated session a server rooted at the worktree can
|
|
9
|
+
* still return a path outside the worktree via symlinks, generated
|
|
10
|
+
* metadata, shared git storage, or external library indexes.
|
|
11
|
+
*
|
|
12
|
+
* Two helpers:
|
|
13
|
+
* - `containLocationUri` — for navigable results
|
|
14
|
+
* (`goToDefinition`/`findReferences`/`goToImplementation`/
|
|
15
|
+
* `workspaceSymbol` location-class). Returns `null` when
|
|
16
|
+
* outside; caller drops or counts as `[omitted]`.
|
|
17
|
+
* - `markExternalUri` — for `documentSymbol` /
|
|
18
|
+
* `prepareCallHierarchy` / `incomingCalls` / `outgoingCalls`
|
|
19
|
+
* where dropping silently would hide answers. Returns the
|
|
20
|
+
* absolute path and a boolean `external: true` so the
|
|
21
|
+
* formatter can prepend `[external]`.
|
|
22
|
+
*/
|
|
23
|
+
import { lstatSync, readlinkSync, realpathSync } from "node:fs";
|
|
24
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
26
|
+
const SYMLINK_RESOLVE_MAX_DEPTH = 8;
|
|
27
|
+
/** Converts a `file://` URI (or absolute path) to a safe-containment
|
|
28
|
+
* triple. Symlinks inside the workspace are resolved through
|
|
29
|
+
* `realpath` so a symlink-to-outside is caught. Non-extant leaves
|
|
30
|
+
* walk up to the nearest existing ancestor (matches the `safePath`
|
|
31
|
+
* pattern in `_shared.ts`) so a path like `<ws>/does-not-exist.ts`
|
|
32
|
+
* on a symlinked tmpdir resolves correctly. */
|
|
33
|
+
export function containUri(uri, workspaceRoot) {
|
|
34
|
+
const raw = uri.startsWith("file://") ? fileURLToPath(uri) : uri;
|
|
35
|
+
const absInput = isAbsolute(raw) ? raw : resolve(workspaceRoot, raw);
|
|
36
|
+
const absReal = realpathExtant(absInput);
|
|
37
|
+
let rootReal;
|
|
38
|
+
try {
|
|
39
|
+
rootReal = realpathSync(workspaceRoot);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
rootReal = workspaceRoot;
|
|
43
|
+
}
|
|
44
|
+
const rel = relative(rootReal, absReal);
|
|
45
|
+
const external = rel.startsWith("..") || isAbsolute(rel);
|
|
46
|
+
return external
|
|
47
|
+
? { abs: absReal, external: true }
|
|
48
|
+
: { abs: absReal, rel, external: false };
|
|
49
|
+
}
|
|
50
|
+
/** Realpath a path that may not exist. Handles dangling symlinks at
|
|
51
|
+
* the leaf the same way `packages/tools/src/builtins/_shared.ts`
|
|
52
|
+
* does (4.1 Round-2 MUST-FIX #3): `lstat` first so a leaf-symlink
|
|
53
|
+
* whose target doesn't exist still gets resolved through
|
|
54
|
+
* `readlink` and re-checked, otherwise `realpathSync` would throw
|
|
55
|
+
* ENOENT and we'd treat a path that POSIX will later follow as if
|
|
56
|
+
* it were lexically contained. */
|
|
57
|
+
function realpathExtant(p, depth = 0) {
|
|
58
|
+
try {
|
|
59
|
+
const lst = lstatSync(p);
|
|
60
|
+
if (lst.isSymbolicLink()) {
|
|
61
|
+
if (depth >= SYMLINK_RESOLVE_MAX_DEPTH)
|
|
62
|
+
return p;
|
|
63
|
+
const target = readlinkSync(p);
|
|
64
|
+
const resolved = isAbsolute(target) ? target : resolve(dirname(p), target);
|
|
65
|
+
return realpathExtant(resolved, depth + 1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* lstat ENOENT — fall through to the walk-up below. */
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
return realpathSync(p);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* fall through */
|
|
76
|
+
}
|
|
77
|
+
let current = dirname(p);
|
|
78
|
+
let tail = p.slice(current.length);
|
|
79
|
+
while (current !== dirname(current)) {
|
|
80
|
+
try {
|
|
81
|
+
const real = realpathSync(current);
|
|
82
|
+
return join(real, tail);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
tail = current.slice(dirname(current).length) + tail;
|
|
86
|
+
current = dirname(current);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return p;
|
|
90
|
+
}
|
|
91
|
+
/** For navigable results — returns the relative path or `null`. */
|
|
92
|
+
export function containLocationUri(uri, workspaceRoot) {
|
|
93
|
+
const r = containUri(uri, workspaceRoot);
|
|
94
|
+
return r.external ? null : r.rel ?? null;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=safe-uri.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-uri.js","sourceRoot":"","sources":["../../src/lsp/safe-uri.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (4.2) LSP package types — kept narrow and JSON-serialisable so config and
|
|
3
|
+
* runtime can round-trip them without coupling to vscode-languageserver-protocol.
|
|
4
|
+
*/
|
|
5
|
+
/** One language-server entry. Identical shape to `LspServerConfig` in
|
|
6
|
+
* `@chances-ai/config` — re-declared here to keep the lsp package
|
|
7
|
+
* boundary-clean (importing the type from `@chances-ai/config` is
|
|
8
|
+
* allowed at the value layer too). */
|
|
9
|
+
export interface LspServerConfig {
|
|
10
|
+
command: string;
|
|
11
|
+
args?: readonly string[];
|
|
12
|
+
extensions: readonly string[];
|
|
13
|
+
env?: Record<string, string>;
|
|
14
|
+
initializationOptions?: unknown;
|
|
15
|
+
startupTimeoutMs?: number;
|
|
16
|
+
maxRestarts?: number;
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Per-instance LRU cap on opened documents. Default 64. */
|
|
19
|
+
maxOpenDocs?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Resolved server entry with its key. Identity inside the manager. */
|
|
22
|
+
export interface ResolvedServer {
|
|
23
|
+
/** Short user-facing name, e.g. "typescript". Stable for cache keys
|
|
24
|
+
* and permission summaries. */
|
|
25
|
+
name: string;
|
|
26
|
+
config: LspServerConfig;
|
|
27
|
+
/** Absolute resolved binary path (set when detection succeeds);
|
|
28
|
+
* undefined when binary not found on PATH or in project-local bin
|
|
29
|
+
* dirs (`BINARY_MISSING` at execute time). */
|
|
30
|
+
resolvedCommand?: string;
|
|
31
|
+
}
|
|
32
|
+
export type LspOp = "goToDefinition" | "findReferences" | "hover" | "documentSymbol" | "workspaceSymbol" | "goToImplementation" | "prepareCallHierarchy" | "incomingCalls" | "outgoingCalls";
|
|
33
|
+
export declare const ALL_OPS: readonly LspOp[];
|
|
34
|
+
/** Input shape passed from the tool wrapper to `LspHost.execute`. The
|
|
35
|
+
* union is intentionally loose at the type level — the host narrows
|
|
36
|
+
* on `op` and validates per-op. */
|
|
37
|
+
export interface LspOpRequest {
|
|
38
|
+
op: LspOp;
|
|
39
|
+
filePath?: string;
|
|
40
|
+
line?: number;
|
|
41
|
+
character?: number;
|
|
42
|
+
query?: string;
|
|
43
|
+
cwd: string;
|
|
44
|
+
signal: AbortSignal;
|
|
45
|
+
}
|
|
46
|
+
/** What the wrapper returns — same shape as `ToolResult` so the
|
|
47
|
+
* wrapper can forward it without re-wrapping. */
|
|
48
|
+
export interface LspOpResult {
|
|
49
|
+
ok: boolean;
|
|
50
|
+
output: string;
|
|
51
|
+
}
|
|
52
|
+
/** Logger shape — subset of `@chances-ai/runtime`'s Logger. */
|
|
53
|
+
export interface Logger {
|
|
54
|
+
debug(msg: string): void;
|
|
55
|
+
info(msg: string): void;
|
|
56
|
+
warn(msg: string): void;
|
|
57
|
+
error(msg: string): void;
|
|
58
|
+
}
|
|
59
|
+
/** Permission resolver shape — the host calls this once per
|
|
60
|
+
* `(serverName, command, cwd)` and caches the answer for the
|
|
61
|
+
* session. */
|
|
62
|
+
export interface LspPermissionResolver {
|
|
63
|
+
(req: {
|
|
64
|
+
serverName: string;
|
|
65
|
+
command: string;
|
|
66
|
+
args: readonly string[];
|
|
67
|
+
cwd: string;
|
|
68
|
+
}): Promise<boolean>;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lsp/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;sCAGsC;AACtC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B;oCACgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB;;mDAE+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,KAAK,GACb,gBAAgB,GAChB,gBAAgB,GAChB,OAAO,GACP,gBAAgB,GAChB,iBAAiB,GACjB,oBAAoB,GACpB,sBAAsB,GACtB,eAAe,GACf,eAAe,CAAC;AAEpB,eAAO,MAAM,OAAO,EAAE,SAAS,KAAK,EAUnC,CAAC;AAEF;;oCAEoC;AACpC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,KAAK,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;kDACkD;AAClD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;eAEe;AACf,MAAM,WAAW,qBAAqB;IACpC,CAAC,GAAG,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (4.2) LSP package types — kept narrow and JSON-serialisable so config and
|
|
3
|
+
* runtime can round-trip them without coupling to vscode-languageserver-protocol.
|
|
4
|
+
*/
|
|
5
|
+
export const ALL_OPS = [
|
|
6
|
+
"goToDefinition",
|
|
7
|
+
"findReferences",
|
|
8
|
+
"hover",
|
|
9
|
+
"documentSymbol",
|
|
10
|
+
"workspaceSymbol",
|
|
11
|
+
"goToImplementation",
|
|
12
|
+
"prepareCallHierarchy",
|
|
13
|
+
"incomingCalls",
|
|
14
|
+
"outgoingCalls",
|
|
15
|
+
];
|
|
16
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lsp/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0CH,MAAM,CAAC,MAAM,OAAO,GAAqB;IACvC,gBAAgB;IAChB,gBAAgB;IAChB,OAAO;IACP,gBAAgB;IAChB,iBAAiB;IACjB,oBAAoB;IACpB,sBAAsB;IACtB,eAAe;IACf,eAAe;CAChB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { JSONValue } from "@chances-ai/runtime";
|
|
2
|
+
import type { Tool } from "../tools/index.js";
|
|
3
|
+
import { type ToolAnnotations } from "./category.js";
|
|
4
|
+
import { type McpContentPart } from "./content.js";
|
|
5
|
+
export type { McpContentPart };
|
|
6
|
+
/**
|
|
7
|
+
* Subset of the MCP `Tool` descriptor we actually consume. Defining it locally
|
|
8
|
+
* keeps `bridge.ts` decoupled from `@modelcontextprotocol/sdk` — tests
|
|
9
|
+
* construct one with a plain object, no SDK import needed.
|
|
10
|
+
*/
|
|
11
|
+
export interface McpToolDescriptor {
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
/** JSON Schema for the args object. */
|
|
15
|
+
inputSchema?: JSONValue;
|
|
16
|
+
annotations?: ToolAnnotations | null;
|
|
17
|
+
}
|
|
18
|
+
/** What the bridge calls when the model invokes a wrapped tool. The host
|
|
19
|
+
* supplies an adapter around the live MCP `Client`; tests supply a fake. */
|
|
20
|
+
export interface McpCallToolClient {
|
|
21
|
+
callTool(name: string, args: Record<string, unknown>, opts: {
|
|
22
|
+
signal: AbortSignal;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}): Promise<McpCallToolResult>;
|
|
25
|
+
}
|
|
26
|
+
/** Subset of the MCP `CallToolResult` we surface to the engine. */
|
|
27
|
+
export interface McpCallToolResult {
|
|
28
|
+
content?: ReadonlyArray<McpContentPart>;
|
|
29
|
+
isError?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface BridgeOptions {
|
|
32
|
+
/** Per-server config-supplied default; falls through to 30 000 ms. */
|
|
33
|
+
defaultTimeoutMs?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Optional scrubber for error messages. Server hosts supply one bound to
|
|
36
|
+
* the per-server secret bag (env values, header values, URL userinfo) so
|
|
37
|
+
* any SDK error that quotes back the bearer token or env var does not
|
|
38
|
+
* reach the bus / tool result.
|
|
39
|
+
*/
|
|
40
|
+
redact?: (message: string) => string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Wraps a single MCP tool as a chances `Tool` the engine can dispatch.
|
|
44
|
+
*
|
|
45
|
+
* Naming: `mcp__<serverId>__<toolName>` (double underscore, claude-code
|
|
46
|
+
* convention). Both segments are normalized via `sanitizeMcpName` so the
|
|
47
|
+
* resulting name is safe to thread through provider APIs that restrict tool
|
|
48
|
+
* names to `[A-Za-z0-9_-]`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function bridgeMcpTool(serverId: string, descriptor: McpToolDescriptor, client: McpCallToolClient, options?: BridgeOptions): Tool;
|
|
51
|
+
/**
|
|
52
|
+
* MCP spec allows alphanumerics + underscore in tool names; provider APIs
|
|
53
|
+
* sometimes also reject dashes mid-name. Conservative: keep `[A-Za-z0-9_]`,
|
|
54
|
+
* everything else collapses to `_`. Consecutive `_` collapse to one.
|
|
55
|
+
*/
|
|
56
|
+
export declare function sanitizeMcpName(raw: string): string;
|
|
57
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/mcp/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,KAAK,eAAe,EAA2B,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,KAAK,cAAc,EAAyB,MAAM,cAAc,CAAC;AAI1E,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CACtC;AAED;4EAC4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAChD,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/B;AAED,mEAAmE;AACnE,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,aAAkB,GAC1B,IAAI,CAiDN;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { AppError, ErrorCode } from "@chances-ai/runtime";
|
|
2
|
+
import { categoryFromAnnotations } from "./category.js";
|
|
3
|
+
import { renderMcpContentParts } from "./content.js";
|
|
4
|
+
/**
|
|
5
|
+
* Wraps a single MCP tool as a chances `Tool` the engine can dispatch.
|
|
6
|
+
*
|
|
7
|
+
* Naming: `mcp__<serverId>__<toolName>` (double underscore, claude-code
|
|
8
|
+
* convention). Both segments are normalized via `sanitizeMcpName` so the
|
|
9
|
+
* resulting name is safe to thread through provider APIs that restrict tool
|
|
10
|
+
* names to `[A-Za-z0-9_-]`.
|
|
11
|
+
*/
|
|
12
|
+
export function bridgeMcpTool(serverId, descriptor, client, options = {}) {
|
|
13
|
+
const sanitizedServer = sanitizeMcpName(serverId);
|
|
14
|
+
const sanitizedTool = sanitizeMcpName(descriptor.name);
|
|
15
|
+
const name = `mcp__${sanitizedServer}__${sanitizedTool}`;
|
|
16
|
+
const category = categoryFromAnnotations(descriptor.annotations);
|
|
17
|
+
const description = descriptor.description
|
|
18
|
+
? `[mcp:${serverId}] ${descriptor.description}`
|
|
19
|
+
: `[mcp:${serverId}] tool ${descriptor.name}`;
|
|
20
|
+
const parameters = sanitizeInputSchema(descriptor.inputSchema);
|
|
21
|
+
return {
|
|
22
|
+
name,
|
|
23
|
+
description,
|
|
24
|
+
category,
|
|
25
|
+
parameters,
|
|
26
|
+
summarize: (args) => summarize(name, args),
|
|
27
|
+
async execute(args, ctx) {
|
|
28
|
+
const redact = options.redact ?? ((m) => m);
|
|
29
|
+
try {
|
|
30
|
+
const argObj = toRecord(args);
|
|
31
|
+
const result = await client.callTool(descriptor.name, argObj, {
|
|
32
|
+
signal: ctx.signal,
|
|
33
|
+
timeoutMs: options.defaultTimeoutMs,
|
|
34
|
+
});
|
|
35
|
+
// Apply the per-server redactor to *all* MCP output, not just the
|
|
36
|
+
// catch path. A malicious or careless server can echo Authorization
|
|
37
|
+
// headers or env values in its own response body — `isError` is the
|
|
38
|
+
// most likely vector but a successful response is not safe either.
|
|
39
|
+
// (5.4) `renderMcpContentParts` strips terminal controls then redacts.
|
|
40
|
+
const text = renderMcpContentParts(result.content, { redact });
|
|
41
|
+
if (result.isError)
|
|
42
|
+
return { ok: false, output: text || "MCP tool reported an error" };
|
|
43
|
+
return { ok: true, output: text };
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
// Cancellation must terminate the whole turn — never swallow it as a
|
|
47
|
+
// tool error. The SDK rejects with its own McpError on abort (not an
|
|
48
|
+
// AppError), so check the signal first and re-raise as
|
|
49
|
+
// AppError(Cancelled) before the generic AppError branch.
|
|
50
|
+
if (ctx.signal.aborted) {
|
|
51
|
+
throw new AppError(ErrorCode.Cancelled, "Operation cancelled");
|
|
52
|
+
}
|
|
53
|
+
if (e instanceof AppError && e.code === ErrorCode.Cancelled)
|
|
54
|
+
throw e;
|
|
55
|
+
// Everything else (validation, transport, server-side error) surfaces
|
|
56
|
+
// as `ok: false` so the engine can show the failure inline. Run the
|
|
57
|
+
// message through the host-supplied redactor first — SDK HTTP errors
|
|
58
|
+
// can echo back bearer tokens in their error bodies.
|
|
59
|
+
return { ok: false, output: redact(e.message) };
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* MCP spec allows alphanumerics + underscore in tool names; provider APIs
|
|
66
|
+
* sometimes also reject dashes mid-name. Conservative: keep `[A-Za-z0-9_]`,
|
|
67
|
+
* everything else collapses to `_`. Consecutive `_` collapse to one.
|
|
68
|
+
*/
|
|
69
|
+
export function sanitizeMcpName(raw) {
|
|
70
|
+
return raw.replace(/[^A-Za-z0-9_]/g, "_").replace(/_+/g, "_");
|
|
71
|
+
}
|
|
72
|
+
function summarize(toolName, args) {
|
|
73
|
+
const preview = args && typeof args === "object" ? Object.keys(args).slice(0, 3).join(",") : "";
|
|
74
|
+
return preview ? `${toolName}(${preview})` : toolName;
|
|
75
|
+
}
|
|
76
|
+
function toRecord(args) {
|
|
77
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) {
|
|
78
|
+
throw new AppError(ErrorCode.Tool, "MCP tool args must be a JSON object");
|
|
79
|
+
}
|
|
80
|
+
return args;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* MCP `inputSchema` is a JSON Schema. Provider APIs (Anthropic / OpenAI)
|
|
84
|
+
* expect `{ type: "object", properties: {...} }`; some MCP servers omit
|
|
85
|
+
* `type` and only ship `properties`. Coerce defensively so the engine never
|
|
86
|
+
* forwards a malformed schema to the provider.
|
|
87
|
+
*/
|
|
88
|
+
function sanitizeInputSchema(raw) {
|
|
89
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
90
|
+
return { type: "object", properties: {} };
|
|
91
|
+
}
|
|
92
|
+
const obj = raw;
|
|
93
|
+
if (obj["type"] !== "object") {
|
|
94
|
+
return { type: "object", properties: {}, ...obj };
|
|
95
|
+
}
|
|
96
|
+
return obj;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/mcp/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ToolCategory } from "@chances-ai/runtime/config";
|
|
2
|
+
/**
|
|
3
|
+
* MCP tools advertise behavior via three optional annotations
|
|
4
|
+
* (`readOnlyHint` / `destructiveHint` / `openWorldHint`) — see the MCP spec's
|
|
5
|
+
* `ToolAnnotations`. We translate them into the chances `ToolCategory` so MCP
|
|
6
|
+
* tools naturally inherit the user's existing per-category permission policy
|
|
7
|
+
* instead of needing a parallel gate.
|
|
8
|
+
*
|
|
9
|
+
* Mapping rationale (matches claude-code's behavior flags):
|
|
10
|
+
* - `readOnlyHint: true` → file-read (default policy: allow)
|
|
11
|
+
* - `destructiveHint: true` + `openWorldHint: true` → shell (prompt)
|
|
12
|
+
* - `destructiveHint: true` → file-write (prompt)
|
|
13
|
+
* - no annotation → integration (prompt; the user added the server, so we
|
|
14
|
+
* prompt per-tool first time rather than silently allowing)
|
|
15
|
+
*/
|
|
16
|
+
export interface ToolAnnotations {
|
|
17
|
+
readOnlyHint?: boolean;
|
|
18
|
+
destructiveHint?: boolean;
|
|
19
|
+
openWorldHint?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function categoryFromAnnotations(annotations?: ToolAnnotations | null): ToolCategory;
|
|
22
|
+
//# sourceMappingURL=category.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"category.d.ts","sourceRoot":"","sources":["../../src/mcp/category.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,uBAAuB,CAAC,WAAW,CAAC,EAAE,eAAe,GAAG,IAAI,GAAG,YAAY,CAO1F"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function categoryFromAnnotations(annotations) {
|
|
2
|
+
if (!annotations)
|
|
3
|
+
return "integration";
|
|
4
|
+
if (annotations.readOnlyHint === true)
|
|
5
|
+
return "file-read";
|
|
6
|
+
if (annotations.destructiveHint === true) {
|
|
7
|
+
return annotations.openWorldHint === true ? "shell" : "file-write";
|
|
8
|
+
}
|
|
9
|
+
return "integration";
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=category.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"category.js","sourceRoot":"","sources":["../../src/mcp/category.ts"],"names":[],"mappings":"AAsBA,MAAM,UAAU,uBAAuB,CAAC,WAAoC;IAC1E,IAAI,CAAC,WAAW;QAAE,OAAO,aAAa,CAAC;IACvC,IAAI,WAAW,CAAC,YAAY,KAAK,IAAI;QAAE,OAAO,WAAW,CAAC;IAC1D,IAAI,WAAW,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACzC,OAAO,WAAW,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC;IACrE,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC"}
|