@qodo/sdk 0.13.4 → 2.0.0-next.1
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/LICENSE +31 -118
- package/README.md +133 -121
- package/bin/qodo-skills.mjs +13 -0
- package/bundled-skills/code-review/SKILL.md +41 -0
- package/bundled-skills/pr-summary/SKILL.md +59 -0
- package/bundled-skills/test-gen/SKILL.md +47 -0
- package/dist/auth/index.browser.d.ts +38 -0
- package/dist/auth/index.browser.d.ts.map +1 -0
- package/dist/auth/index.browser.js +62 -0
- package/dist/auth/index.browser.js.map +1 -0
- package/dist/auth/index.d.ts +44 -30
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +57 -110
- package/dist/auth/index.js.map +1 -1
- package/dist/client/AgentsClient.d.ts +33 -0
- package/dist/client/AgentsClient.d.ts.map +1 -0
- package/dist/client/AgentsClient.js +40 -0
- package/dist/client/AgentsClient.js.map +1 -0
- package/dist/client/ArtifactsClient.d.ts +43 -0
- package/dist/client/ArtifactsClient.d.ts.map +1 -0
- package/dist/client/ArtifactsClient.js +54 -0
- package/dist/client/ArtifactsClient.js.map +1 -0
- package/dist/client/BulletinClient.d.ts +45 -0
- package/dist/client/BulletinClient.d.ts.map +1 -0
- package/dist/client/BulletinClient.js +51 -0
- package/dist/client/BulletinClient.js.map +1 -0
- package/dist/client/InfoClient.d.ts +58 -0
- package/dist/client/InfoClient.d.ts.map +1 -0
- package/dist/client/InfoClient.js +135 -0
- package/dist/client/InfoClient.js.map +1 -0
- package/dist/client/PipelineClient.d.ts +162 -0
- package/dist/client/PipelineClient.d.ts.map +1 -0
- package/dist/client/PipelineClient.js +340 -0
- package/dist/client/PipelineClient.js.map +1 -0
- package/dist/client/QarRegistryClient.d.ts +396 -0
- package/dist/client/QarRegistryClient.d.ts.map +1 -0
- package/dist/client/QarRegistryClient.js +536 -0
- package/dist/client/QarRegistryClient.js.map +1 -0
- package/dist/client/QodoClient.d.ts +296 -0
- package/dist/client/QodoClient.d.ts.map +1 -0
- package/dist/client/QodoClient.js +803 -0
- package/dist/client/QodoClient.js.map +1 -0
- package/dist/client/SpecsClient.d.ts +121 -0
- package/dist/client/SpecsClient.d.ts.map +1 -0
- package/dist/client/SpecsClient.js +252 -0
- package/dist/client/SpecsClient.js.map +1 -0
- package/dist/client/StateClient.d.ts +35 -0
- package/dist/client/StateClient.d.ts.map +1 -0
- package/dist/client/StateClient.js +36 -0
- package/dist/client/StateClient.js.map +1 -0
- package/dist/client/TaskClient.d.ts +706 -0
- package/dist/client/TaskClient.d.ts.map +1 -0
- package/dist/client/TaskClient.js +2522 -0
- package/dist/client/TaskClient.js.map +1 -0
- package/dist/client/ToolClient.d.ts +278 -0
- package/dist/client/ToolClient.d.ts.map +1 -0
- package/dist/client/ToolClient.js +1139 -0
- package/dist/client/ToolClient.js.map +1 -0
- package/dist/client/a2a/index.d.ts +10 -0
- package/dist/client/a2a/index.d.ts.map +1 -0
- package/dist/client/a2a/index.js +9 -0
- package/dist/client/a2a/index.js.map +1 -0
- package/dist/client/a2a/registerA2A.d.ts +170 -0
- package/dist/client/a2a/registerA2A.d.ts.map +1 -0
- package/dist/client/a2a/registerA2A.js +85 -0
- package/dist/client/a2a/registerA2A.js.map +1 -0
- package/dist/client/connection.d.ts +893 -0
- package/dist/client/connection.d.ts.map +1 -0
- package/dist/client/connection.js +2189 -0
- package/dist/client/connection.js.map +1 -0
- package/dist/client/errors.d.ts +735 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +921 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/index.d.ts +26 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +20 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/inlineGraph.d.ts +66 -0
- package/dist/client/inlineGraph.d.ts.map +1 -0
- package/dist/client/inlineGraph.js +500 -0
- package/dist/client/inlineGraph.js.map +1 -0
- package/dist/client/internal/thenable.d.ts +27 -0
- package/dist/client/internal/thenable.d.ts.map +1 -0
- package/dist/client/internal/thenable.js +31 -0
- package/dist/client/internal/thenable.js.map +1 -0
- package/dist/client/iterator.d.ts +32 -0
- package/dist/client/iterator.d.ts.map +1 -0
- package/dist/client/iterator.js +73 -0
- package/dist/client/iterator.js.map +1 -0
- package/dist/client/mcp/McpClientPool.browser.d.ts +76 -0
- package/dist/client/mcp/McpClientPool.browser.d.ts.map +1 -0
- package/dist/client/mcp/McpClientPool.browser.js +78 -0
- package/dist/client/mcp/McpClientPool.browser.js.map +1 -0
- package/dist/client/mcp/McpClientPool.d.ts +236 -0
- package/dist/client/mcp/McpClientPool.d.ts.map +1 -0
- package/dist/client/mcp/McpClientPool.js +585 -0
- package/dist/client/mcp/McpClientPool.js.map +1 -0
- package/dist/client/mcp/projection.d.ts +109 -0
- package/dist/client/mcp/projection.d.ts.map +1 -0
- package/dist/client/mcp/projection.js +446 -0
- package/dist/client/mcp/projection.js.map +1 -0
- package/dist/client/mcp/substituteEnv.browser.d.ts +18 -0
- package/dist/client/mcp/substituteEnv.browser.d.ts.map +1 -0
- package/dist/client/mcp/substituteEnv.browser.js +20 -0
- package/dist/client/mcp/substituteEnv.browser.js.map +1 -0
- package/dist/client/mcp/substituteEnv.d.ts +45 -0
- package/dist/client/mcp/substituteEnv.d.ts.map +1 -0
- package/dist/client/mcp/substituteEnv.js +63 -0
- package/dist/client/mcp/substituteEnv.js.map +1 -0
- package/dist/client/observers.d.ts +57 -0
- package/dist/client/observers.d.ts.map +1 -0
- package/dist/client/observers.js +203 -0
- package/dist/client/observers.js.map +1 -0
- package/dist/client/options.d.ts +269 -0
- package/dist/client/options.d.ts.map +1 -0
- package/dist/client/options.js +9 -0
- package/dist/client/options.js.map +1 -0
- package/dist/client/tools/_readlineApprovalPrompt.browser.d.ts +17 -0
- package/dist/client/tools/_readlineApprovalPrompt.browser.d.ts.map +1 -0
- package/dist/client/tools/_readlineApprovalPrompt.browser.js +24 -0
- package/dist/client/tools/_readlineApprovalPrompt.browser.js.map +1 -0
- package/dist/client/tools/_readlineApprovalPrompt.d.ts +33 -0
- package/dist/client/tools/_readlineApprovalPrompt.d.ts.map +1 -0
- package/dist/client/tools/_readlineApprovalPrompt.js +90 -0
- package/dist/client/tools/_readlineApprovalPrompt.js.map +1 -0
- package/dist/client/tools/approval.d.ts +280 -0
- package/dist/client/tools/approval.d.ts.map +1 -0
- package/dist/client/tools/approval.js +229 -0
- package/dist/client/tools/approval.js.map +1 -0
- package/dist/client/tools/bindFunctionToolDefs.d.ts +156 -0
- package/dist/client/tools/bindFunctionToolDefs.d.ts.map +1 -0
- package/dist/client/tools/bindFunctionToolDefs.js +360 -0
- package/dist/client/tools/bindFunctionToolDefs.js.map +1 -0
- package/dist/client/tools/defineFunctionTool.d.ts +277 -0
- package/dist/client/tools/defineFunctionTool.d.ts.map +1 -0
- package/dist/client/tools/defineFunctionTool.js +190 -0
- package/dist/client/tools/defineFunctionTool.js.map +1 -0
- package/dist/client/transport.browser.d.ts +20 -0
- package/dist/client/transport.browser.d.ts.map +1 -0
- package/dist/client/transport.browser.js +29 -0
- package/dist/client/transport.browser.js.map +1 -0
- package/dist/client/transport.d.ts +47 -0
- package/dist/client/transport.d.ts.map +1 -0
- package/dist/client/transport.js +102 -0
- package/dist/client/transport.js.map +1 -0
- package/dist/client/transport.shared.d.ts +30 -0
- package/dist/client/transport.shared.d.ts.map +1 -0
- package/dist/client/transport.shared.js +40 -0
- package/dist/client/transport.shared.js.map +1 -0
- package/dist/client/uuid.d.ts +32 -0
- package/dist/client/uuid.d.ts.map +1 -0
- package/dist/client/uuid.js +65 -0
- package/dist/client/uuid.js.map +1 -0
- package/dist/index.d.ts +88 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +166 -43
- package/dist/index.js.map +1 -1
- package/dist/observability/attributes.d.ts +136 -0
- package/dist/observability/attributes.d.ts.map +1 -0
- package/dist/observability/attributes.js +184 -0
- package/dist/observability/attributes.js.map +1 -0
- package/dist/observability/index.d.ts +14 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +11 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/resolveOTel.browser.d.ts +13 -0
- package/dist/observability/resolveOTel.browser.d.ts.map +1 -0
- package/dist/observability/resolveOTel.browser.js +14 -0
- package/dist/observability/resolveOTel.browser.js.map +1 -0
- package/dist/observability/resolveOTel.d.ts +28 -0
- package/dist/observability/resolveOTel.d.ts.map +1 -0
- package/dist/observability/resolveOTel.js +74 -0
- package/dist/observability/resolveOTel.js.map +1 -0
- package/dist/observability/spans.d.ts +198 -0
- package/dist/observability/spans.d.ts.map +1 -0
- package/dist/observability/spans.js +300 -0
- package/dist/observability/spans.js.map +1 -0
- package/dist/observability/traceContext.d.ts +51 -0
- package/dist/observability/traceContext.d.ts.map +1 -0
- package/dist/observability/traceContext.js +151 -0
- package/dist/observability/traceContext.js.map +1 -0
- package/dist/observability/transportMetrics.d.ts +58 -0
- package/dist/observability/transportMetrics.d.ts.map +1 -0
- package/dist/observability/transportMetrics.js +55 -0
- package/dist/observability/transportMetrics.js.map +1 -0
- package/dist/qar/agentSpec.d.ts +93 -0
- package/dist/qar/agentSpec.d.ts.map +1 -0
- package/dist/qar/agentSpec.js +184 -0
- package/dist/qar/agentSpec.js.map +1 -0
- package/dist/qar/clientEvents.d.ts +86 -0
- package/dist/qar/clientEvents.d.ts.map +1 -0
- package/dist/qar/clientEvents.js +36 -0
- package/dist/qar/clientEvents.js.map +1 -0
- package/dist/qar/envelopes.d.ts +227 -0
- package/dist/qar/envelopes.d.ts.map +1 -0
- package/dist/qar/envelopes.js +67 -0
- package/dist/qar/envelopes.js.map +1 -0
- package/dist/qar/generated/envelope.d.ts +332 -0
- package/dist/qar/generated/envelope.d.ts.map +1 -0
- package/dist/qar/generated/envelope.js +15 -0
- package/dist/qar/generated/envelope.js.map +1 -0
- package/dist/qar/generated/qar-info.d.ts +76 -0
- package/dist/qar/generated/qar-info.d.ts.map +1 -0
- package/dist/qar/generated/qar-info.js +15 -0
- package/dist/qar/generated/qar-info.js.map +1 -0
- package/dist/qar/generated/qodo-task-start-payload.d.ts +54 -0
- package/dist/qar/generated/qodo-task-start-payload.d.ts.map +1 -0
- package/dist/qar/generated/qodo-task-start-payload.js +15 -0
- package/dist/qar/generated/qodo-task-start-payload.js.map +1 -0
- package/dist/qar/ids.d.ts +19 -0
- package/dist/qar/ids.d.ts.map +1 -0
- package/dist/qar/ids.js +11 -0
- package/dist/qar/ids.js.map +1 -0
- package/dist/qar/index.d.ts +24 -0
- package/dist/qar/index.d.ts.map +1 -0
- package/dist/qar/index.js +16 -0
- package/dist/qar/index.js.map +1 -0
- package/dist/qar/info.d.ts +37 -0
- package/dist/qar/info.d.ts.map +1 -0
- package/dist/qar/info.js +17 -0
- package/dist/qar/info.js.map +1 -0
- package/dist/qar/json.d.ts +14 -0
- package/dist/qar/json.d.ts.map +1 -0
- package/dist/qar/json.js +9 -0
- package/dist/qar/json.js.map +1 -0
- package/dist/qar/payloads.d.ts +480 -0
- package/dist/qar/payloads.d.ts.map +1 -0
- package/dist/qar/payloads.js +37 -0
- package/dist/qar/payloads.js.map +1 -0
- package/dist/qar/specs.d.ts +604 -0
- package/dist/qar/specs.d.ts.map +1 -0
- package/dist/qar/specs.js +29 -0
- package/dist/qar/specs.js.map +1 -0
- package/dist/qar/taskEvents.d.ts +25 -0
- package/dist/qar/taskEvents.d.ts.map +1 -0
- package/dist/qar/taskEvents.js +22 -0
- package/dist/qar/taskEvents.js.map +1 -0
- package/dist/qar/trace.d.ts +12 -0
- package/dist/qar/trace.d.ts.map +1 -0
- package/dist/qar/trace.js +12 -0
- package/dist/qar/trace.js.map +1 -0
- package/dist/skills/activation.d.ts +177 -0
- package/dist/skills/activation.d.ts.map +1 -0
- package/dist/skills/activation.js +428 -0
- package/dist/skills/activation.js.map +1 -0
- package/dist/skills/cli/index.browser.d.ts +18 -0
- package/dist/skills/cli/index.browser.d.ts.map +1 -0
- package/dist/skills/cli/index.browser.js +27 -0
- package/dist/skills/cli/index.browser.js.map +1 -0
- package/dist/skills/cli/index.d.ts +37 -0
- package/dist/skills/cli/index.d.ts.map +1 -0
- package/dist/skills/cli/index.js +494 -0
- package/dist/skills/cli/index.js.map +1 -0
- package/dist/skills/events.d.ts +255 -0
- package/dist/skills/events.d.ts.map +1 -0
- package/dist/skills/events.js +224 -0
- package/dist/skills/events.js.map +1 -0
- package/dist/skills/index.d.ts +45 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +34 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/inject.d.ts +57 -0
- package/dist/skills/inject.d.ts.map +1 -0
- package/dist/skills/inject.js +162 -0
- package/dist/skills/inject.js.map +1 -0
- package/dist/skills/lockfile.browser.d.ts +56 -0
- package/dist/skills/lockfile.browser.d.ts.map +1 -0
- package/dist/skills/lockfile.browser.js +55 -0
- package/dist/skills/lockfile.browser.js.map +1 -0
- package/dist/skills/lockfile.d.ts +137 -0
- package/dist/skills/lockfile.d.ts.map +1 -0
- package/dist/skills/lockfile.js +423 -0
- package/dist/skills/lockfile.js.map +1 -0
- package/dist/skills/manager.browser.d.ts +94 -0
- package/dist/skills/manager.browser.d.ts.map +1 -0
- package/dist/skills/manager.browser.js +159 -0
- package/dist/skills/manager.browser.js.map +1 -0
- package/dist/skills/manager.d.ts +362 -0
- package/dist/skills/manager.d.ts.map +1 -0
- package/dist/skills/manager.js +1386 -0
- package/dist/skills/manager.js.map +1 -0
- package/dist/skills/mcp/index.d.ts +15 -0
- package/dist/skills/mcp/index.d.ts.map +1 -0
- package/dist/skills/mcp/index.js +12 -0
- package/dist/skills/mcp/index.js.map +1 -0
- package/dist/skills/mcp/path.browser.d.ts +27 -0
- package/dist/skills/mcp/path.browser.d.ts.map +1 -0
- package/dist/skills/mcp/path.browser.js +33 -0
- package/dist/skills/mcp/path.browser.js.map +1 -0
- package/dist/skills/mcp/path.d.ts +57 -0
- package/dist/skills/mcp/path.d.ts.map +1 -0
- package/dist/skills/mcp/path.js +150 -0
- package/dist/skills/mcp/path.js.map +1 -0
- package/dist/skills/mcp/server.browser.d.ts +32 -0
- package/dist/skills/mcp/server.browser.d.ts.map +1 -0
- package/dist/skills/mcp/server.browser.js +53 -0
- package/dist/skills/mcp/server.browser.js.map +1 -0
- package/dist/skills/mcp/server.d.ts +144 -0
- package/dist/skills/mcp/server.d.ts.map +1 -0
- package/dist/skills/mcp/server.js +841 -0
- package/dist/skills/mcp/server.js.map +1 -0
- package/dist/skills/mcp/types.d.ts +72 -0
- package/dist/skills/mcp/types.d.ts.map +1 -0
- package/dist/skills/mcp/types.js +20 -0
- package/dist/skills/mcp/types.js.map +1 -0
- package/dist/skills/mcp/wireDefs.d.ts +58 -0
- package/dist/skills/mcp/wireDefs.d.ts.map +1 -0
- package/dist/skills/mcp/wireDefs.js +141 -0
- package/dist/skills/mcp/wireDefs.js.map +1 -0
- package/dist/skills/parser.d.ts +63 -0
- package/dist/skills/parser.d.ts.map +1 -0
- package/dist/skills/parser.js +755 -0
- package/dist/skills/parser.js.map +1 -0
- package/dist/skills/prefilter.d.ts +104 -0
- package/dist/skills/prefilter.d.ts.map +1 -0
- package/dist/skills/prefilter.js +398 -0
- package/dist/skills/prefilter.js.map +1 -0
- package/dist/skills/preprocess.d.ts +169 -0
- package/dist/skills/preprocess.d.ts.map +1 -0
- package/dist/skills/preprocess.js +535 -0
- package/dist/skills/preprocess.js.map +1 -0
- package/dist/skills/render.d.ts +83 -0
- package/dist/skills/render.d.ts.map +1 -0
- package/dist/skills/render.js +397 -0
- package/dist/skills/render.js.map +1 -0
- package/dist/skills/sources/index.browser.d.ts +29 -0
- package/dist/skills/sources/index.browser.d.ts.map +1 -0
- package/dist/skills/sources/index.browser.js +16 -0
- package/dist/skills/sources/index.browser.js.map +1 -0
- package/dist/skills/sources/index.d.ts +59 -0
- package/dist/skills/sources/index.d.ts.map +1 -0
- package/dist/skills/sources/index.js +471 -0
- package/dist/skills/sources/index.js.map +1 -0
- package/dist/skills/sources/walk.browser.d.ts +17 -0
- package/dist/skills/sources/walk.browser.d.ts.map +1 -0
- package/dist/skills/sources/walk.browser.js +19 -0
- package/dist/skills/sources/walk.browser.js.map +1 -0
- package/dist/skills/sources/walk.d.ts +68 -0
- package/dist/skills/sources/walk.d.ts.map +1 -0
- package/dist/skills/sources/walk.js +264 -0
- package/dist/skills/sources/walk.js.map +1 -0
- package/dist/skills/substitute.d.ts +87 -0
- package/dist/skills/substitute.d.ts.map +1 -0
- package/dist/skills/substitute.js +322 -0
- package/dist/skills/substitute.js.map +1 -0
- package/dist/skills/testing/SkillKit.browser.d.ts +62 -0
- package/dist/skills/testing/SkillKit.browser.d.ts.map +1 -0
- package/dist/skills/testing/SkillKit.browser.js +41 -0
- package/dist/skills/testing/SkillKit.browser.js.map +1 -0
- package/dist/skills/testing/SkillKit.d.ts +130 -0
- package/dist/skills/testing/SkillKit.d.ts.map +1 -0
- package/dist/skills/testing/SkillKit.js +316 -0
- package/dist/skills/testing/SkillKit.js.map +1 -0
- package/dist/skills/testing/index.d.ts +9 -0
- package/dist/skills/testing/index.d.ts.map +1 -0
- package/dist/skills/testing/index.js +8 -0
- package/dist/skills/testing/index.js.map +1 -0
- package/dist/skills/trust.d.ts +72 -0
- package/dist/skills/trust.d.ts.map +1 -0
- package/dist/skills/trust.js +183 -0
- package/dist/skills/trust.js.map +1 -0
- package/dist/skills/types.d.ts +627 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +85 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/skills/validator.d.ts +95 -0
- package/dist/skills/validator.d.ts.map +1 -0
- package/dist/skills/validator.js +486 -0
- package/dist/skills/validator.js.map +1 -0
- package/dist/tracing/PipelineTracer.d.ts +35 -22
- package/dist/tracing/PipelineTracer.d.ts.map +1 -1
- package/dist/tracing/PipelineTracer.js +106 -61
- package/dist/tracing/PipelineTracer.js.map +1 -1
- package/dist/tracing/SdkTracer.d.ts +63 -61
- package/dist/tracing/SdkTracer.d.ts.map +1 -1
- package/dist/tracing/SdkTracer.js +185 -177
- package/dist/tracing/SdkTracer.js.map +1 -1
- package/dist/tracing/index.d.ts +10 -1
- package/dist/tracing/index.d.ts.map +1 -1
- package/dist/tracing/index.js +9 -0
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/types.d.ts +89 -16
- package/dist/tracing/types.d.ts.map +1 -1
- package/dist/tracing/types.js +17 -4
- package/dist/tracing/types.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +10 -20
- package/dist/version.js.map +1 -1
- package/package.json +53 -39
- package/.claude/skills/qodo-agent/SKILL.md +0 -974
- package/.claude/skills/qodo-agent/assets/programmatic-agent.ts +0 -407
- package/.claude/skills/qodo-agent/references/builtin-tools.md +0 -342
- package/.claude/skills/qodo-agent/references/common-issues.md +0 -537
- package/bin/rg +0 -0
- package/dist/api/agent.d.ts +0 -105
- package/dist/api/agent.d.ts.map +0 -1
- package/dist/api/agent.js +0 -963
- package/dist/api/agent.js.map +0 -1
- package/dist/api/analytics.d.ts +0 -43
- package/dist/api/analytics.d.ts.map +0 -1
- package/dist/api/analytics.js +0 -163
- package/dist/api/analytics.js.map +0 -1
- package/dist/api/http.d.ts +0 -5
- package/dist/api/http.d.ts.map +0 -1
- package/dist/api/http.js +0 -62
- package/dist/api/http.js.map +0 -1
- package/dist/api/index.d.ts +0 -12
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -17
- package/dist/api/index.js.map +0 -1
- package/dist/api/taskTracking.d.ts +0 -54
- package/dist/api/taskTracking.d.ts.map +0 -1
- package/dist/api/taskTracking.js +0 -208
- package/dist/api/taskTracking.js.map +0 -1
- package/dist/api/types.d.ts +0 -93
- package/dist/api/types.d.ts.map +0 -1
- package/dist/api/types.js +0 -2
- package/dist/api/types.js.map +0 -1
- package/dist/api/utils.d.ts +0 -8
- package/dist/api/utils.d.ts.map +0 -1
- package/dist/api/utils.js +0 -63
- package/dist/api/utils.js.map +0 -1
- package/dist/api/websocket.d.ts +0 -203
- package/dist/api/websocket.d.ts.map +0 -1
- package/dist/api/websocket.js +0 -1166
- package/dist/api/websocket.js.map +0 -1
- package/dist/bin/install-skill.d.ts +0 -14
- package/dist/bin/install-skill.d.ts.map +0 -1
- package/dist/bin/install-skill.js +0 -125
- package/dist/bin/install-skill.js.map +0 -1
- package/dist/bin/run-helpers.d.ts +0 -34
- package/dist/bin/run-helpers.d.ts.map +0 -1
- package/dist/bin/run-helpers.js +0 -186
- package/dist/bin/run-helpers.js.map +0 -1
- package/dist/bin/run.d.ts +0 -13
- package/dist/bin/run.d.ts.map +0 -1
- package/dist/bin/run.js +0 -57
- package/dist/bin/run.js.map +0 -1
- package/dist/clients/index.d.ts +0 -10
- package/dist/clients/index.d.ts.map +0 -1
- package/dist/clients/index.js +0 -8
- package/dist/clients/index.js.map +0 -1
- package/dist/clients/info/InfoClient.d.ts +0 -37
- package/dist/clients/info/InfoClient.d.ts.map +0 -1
- package/dist/clients/info/InfoClient.js +0 -69
- package/dist/clients/info/InfoClient.js.map +0 -1
- package/dist/clients/info/index.d.ts +0 -4
- package/dist/clients/info/index.d.ts.map +0 -1
- package/dist/clients/info/index.js +0 -2
- package/dist/clients/info/index.js.map +0 -1
- package/dist/clients/info/types.d.ts +0 -21
- package/dist/clients/info/types.d.ts.map +0 -1
- package/dist/clients/info/types.js +0 -2
- package/dist/clients/info/types.js.map +0 -1
- package/dist/clients/sessions/SessionsClient.d.ts +0 -34
- package/dist/clients/sessions/SessionsClient.d.ts.map +0 -1
- package/dist/clients/sessions/SessionsClient.js +0 -71
- package/dist/clients/sessions/SessionsClient.js.map +0 -1
- package/dist/clients/sessions/index.d.ts +0 -4
- package/dist/clients/sessions/index.d.ts.map +0 -1
- package/dist/clients/sessions/index.js +0 -2
- package/dist/clients/sessions/index.js.map +0 -1
- package/dist/clients/sessions/types.d.ts +0 -20
- package/dist/clients/sessions/types.d.ts.map +0 -1
- package/dist/clients/sessions/types.js +0 -2
- package/dist/clients/sessions/types.js.map +0 -1
- package/dist/clients/tools/ToolsClient.d.ts +0 -39
- package/dist/clients/tools/ToolsClient.d.ts.map +0 -1
- package/dist/clients/tools/ToolsClient.js +0 -95
- package/dist/clients/tools/ToolsClient.js.map +0 -1
- package/dist/clients/tools/index.d.ts +0 -4
- package/dist/clients/tools/index.d.ts.map +0 -1
- package/dist/clients/tools/index.js +0 -2
- package/dist/clients/tools/index.js.map +0 -1
- package/dist/clients/tools/types.d.ts +0 -14
- package/dist/clients/tools/types.d.ts.map +0 -1
- package/dist/clients/tools/types.js +0 -2
- package/dist/clients/tools/types.js.map +0 -1
- package/dist/config/ConfigManager.d.ts +0 -43
- package/dist/config/ConfigManager.d.ts.map +0 -1
- package/dist/config/ConfigManager.js +0 -472
- package/dist/config/ConfigManager.js.map +0 -1
- package/dist/config/index.d.ts +0 -6
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -7
- package/dist/config/index.js.map +0 -1
- package/dist/config/urlConfig.d.ts +0 -15
- package/dist/config/urlConfig.d.ts.map +0 -1
- package/dist/config/urlConfig.js +0 -75
- package/dist/config/urlConfig.js.map +0 -1
- package/dist/constants/errors.d.ts +0 -2
- package/dist/constants/errors.d.ts.map +0 -1
- package/dist/constants/errors.js +0 -2
- package/dist/constants/errors.js.map +0 -1
- package/dist/constants/index.d.ts +0 -7
- package/dist/constants/index.d.ts.map +0 -1
- package/dist/constants/index.js +0 -11
- package/dist/constants/index.js.map +0 -1
- package/dist/constants/tools.d.ts +0 -4
- package/dist/constants/tools.d.ts.map +0 -1
- package/dist/constants/tools.js +0 -4
- package/dist/constants/tools.js.map +0 -1
- package/dist/constants/versions.d.ts +0 -2
- package/dist/constants/versions.d.ts.map +0 -1
- package/dist/constants/versions.js +0 -2
- package/dist/constants/versions.js.map +0 -1
- package/dist/context/buildUserContext.d.ts +0 -18
- package/dist/context/buildUserContext.d.ts.map +0 -1
- package/dist/context/buildUserContext.js +0 -34
- package/dist/context/buildUserContext.js.map +0 -1
- package/dist/context/index.d.ts +0 -9
- package/dist/context/index.d.ts.map +0 -1
- package/dist/context/index.js +0 -9
- package/dist/context/index.js.map +0 -1
- package/dist/context/messageManager.d.ts +0 -42
- package/dist/context/messageManager.d.ts.map +0 -1
- package/dist/context/messageManager.js +0 -322
- package/dist/context/messageManager.js.map +0 -1
- package/dist/context/taskFocus.d.ts +0 -2
- package/dist/context/taskFocus.d.ts.map +0 -1
- package/dist/context/taskFocus.js +0 -26
- package/dist/context/taskFocus.js.map +0 -1
- package/dist/context/userInput.d.ts +0 -3
- package/dist/context/userInput.d.ts.map +0 -1
- package/dist/context/userInput.js +0 -20
- package/dist/context/userInput.js.map +0 -1
- package/dist/mcp/MCPManager.d.ts +0 -109
- package/dist/mcp/MCPManager.d.ts.map +0 -1
- package/dist/mcp/MCPManager.js +0 -592
- package/dist/mcp/MCPManager.js.map +0 -1
- package/dist/mcp/approvedTools.d.ts +0 -4
- package/dist/mcp/approvedTools.d.ts.map +0 -1
- package/dist/mcp/approvedTools.js +0 -19
- package/dist/mcp/approvedTools.js.map +0 -1
- package/dist/mcp/baseServer.d.ts +0 -75
- package/dist/mcp/baseServer.d.ts.map +0 -1
- package/dist/mcp/baseServer.js +0 -107
- package/dist/mcp/baseServer.js.map +0 -1
- package/dist/mcp/builtinServers.d.ts +0 -15
- package/dist/mcp/builtinServers.d.ts.map +0 -1
- package/dist/mcp/builtinServers.js +0 -141
- package/dist/mcp/builtinServers.js.map +0 -1
- package/dist/mcp/dynamicBEServer.d.ts +0 -20
- package/dist/mcp/dynamicBEServer.d.ts.map +0 -1
- package/dist/mcp/dynamicBEServer.js +0 -52
- package/dist/mcp/dynamicBEServer.js.map +0 -1
- package/dist/mcp/index.d.ts +0 -18
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/index.js +0 -23
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/mcpInitialization.d.ts +0 -2
- package/dist/mcp/mcpInitialization.d.ts.map +0 -1
- package/dist/mcp/mcpInitialization.js +0 -56
- package/dist/mcp/mcpInitialization.js.map +0 -1
- package/dist/mcp/servers/filesystem.d.ts +0 -44
- package/dist/mcp/servers/filesystem.d.ts.map +0 -1
- package/dist/mcp/servers/filesystem.js +0 -776
- package/dist/mcp/servers/filesystem.js.map +0 -1
- package/dist/mcp/servers/git.d.ts +0 -18
- package/dist/mcp/servers/git.d.ts.map +0 -1
- package/dist/mcp/servers/git.js +0 -441
- package/dist/mcp/servers/git.js.map +0 -1
- package/dist/mcp/servers/ripgrep.d.ts +0 -39
- package/dist/mcp/servers/ripgrep.d.ts.map +0 -1
- package/dist/mcp/servers/ripgrep.js +0 -550
- package/dist/mcp/servers/ripgrep.js.map +0 -1
- package/dist/mcp/servers/shell.d.ts +0 -20
- package/dist/mcp/servers/shell.d.ts.map +0 -1
- package/dist/mcp/servers/shell.js +0 -519
- package/dist/mcp/servers/shell.js.map +0 -1
- package/dist/mcp/serversRegistry.d.ts +0 -55
- package/dist/mcp/serversRegistry.d.ts.map +0 -1
- package/dist/mcp/serversRegistry.js +0 -416
- package/dist/mcp/serversRegistry.js.map +0 -1
- package/dist/mcp/toolProcessor.d.ts +0 -82
- package/dist/mcp/toolProcessor.d.ts.map +0 -1
- package/dist/mcp/toolProcessor.js +0 -392
- package/dist/mcp/toolProcessor.js.map +0 -1
- package/dist/mcp/types.d.ts +0 -29
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js +0 -2
- package/dist/mcp/types.js.map +0 -1
- package/dist/messages/index.d.ts +0 -8
- package/dist/messages/index.d.ts.map +0 -1
- package/dist/messages/index.js +0 -7
- package/dist/messages/index.js.map +0 -1
- package/dist/messages/openai.d.ts +0 -26
- package/dist/messages/openai.d.ts.map +0 -1
- package/dist/messages/openai.js +0 -55
- package/dist/messages/openai.js.map +0 -1
- package/dist/messages/types.d.ts +0 -73
- package/dist/messages/types.d.ts.map +0 -1
- package/dist/messages/types.js +0 -78
- package/dist/messages/types.js.map +0 -1
- package/dist/parser/index.d.ts +0 -72
- package/dist/parser/index.d.ts.map +0 -1
- package/dist/parser/index.js +0 -967
- package/dist/parser/index.js.map +0 -1
- package/dist/parser/types.d.ts +0 -153
- package/dist/parser/types.d.ts.map +0 -1
- package/dist/parser/types.js +0 -6
- package/dist/parser/types.js.map +0 -1
- package/dist/parser/utils.d.ts +0 -18
- package/dist/parser/utils.d.ts.map +0 -1
- package/dist/parser/utils.js +0 -64
- package/dist/parser/utils.js.map +0 -1
- package/dist/sdk/QodoSDK.d.ts +0 -218
- package/dist/sdk/QodoSDK.d.ts.map +0 -1
- package/dist/sdk/QodoSDK.js +0 -1115
- package/dist/sdk/QodoSDK.js.map +0 -1
- package/dist/sdk/artifacts.d.ts +0 -156
- package/dist/sdk/artifacts.d.ts.map +0 -1
- package/dist/sdk/artifacts.js +0 -166
- package/dist/sdk/artifacts.js.map +0 -1
- package/dist/sdk/bootstrap.d.ts +0 -16
- package/dist/sdk/bootstrap.d.ts.map +0 -1
- package/dist/sdk/bootstrap.js +0 -28
- package/dist/sdk/bootstrap.js.map +0 -1
- package/dist/sdk/builders.d.ts +0 -54
- package/dist/sdk/builders.d.ts.map +0 -1
- package/dist/sdk/builders.js +0 -117
- package/dist/sdk/builders.js.map +0 -1
- package/dist/sdk/defaults.d.ts +0 -11
- package/dist/sdk/defaults.d.ts.map +0 -1
- package/dist/sdk/defaults.js +0 -39
- package/dist/sdk/defaults.js.map +0 -1
- package/dist/sdk/discovery.d.ts +0 -2
- package/dist/sdk/discovery.d.ts.map +0 -1
- package/dist/sdk/discovery.js +0 -25
- package/dist/sdk/discovery.js.map +0 -1
- package/dist/sdk/events.d.ts +0 -269
- package/dist/sdk/events.d.ts.map +0 -1
- package/dist/sdk/events.js +0 -69
- package/dist/sdk/events.js.map +0 -1
- package/dist/sdk/exit-expression.d.ts +0 -13
- package/dist/sdk/exit-expression.d.ts.map +0 -1
- package/dist/sdk/exit-expression.js +0 -35
- package/dist/sdk/exit-expression.js.map +0 -1
- package/dist/sdk/index.d.ts +0 -17
- package/dist/sdk/index.d.ts.map +0 -1
- package/dist/sdk/index.js +0 -17
- package/dist/sdk/index.js.map +0 -1
- package/dist/sdk/middleware.d.ts +0 -59
- package/dist/sdk/middleware.d.ts.map +0 -1
- package/dist/sdk/middleware.js +0 -69
- package/dist/sdk/middleware.js.map +0 -1
- package/dist/sdk/pipeline/PipelineBuilder.d.ts +0 -79
- package/dist/sdk/pipeline/PipelineBuilder.d.ts.map +0 -1
- package/dist/sdk/pipeline/PipelineBuilder.js +0 -129
- package/dist/sdk/pipeline/PipelineBuilder.js.map +0 -1
- package/dist/sdk/pipeline/PipelineRunner.d.ts +0 -28
- package/dist/sdk/pipeline/PipelineRunner.d.ts.map +0 -1
- package/dist/sdk/pipeline/PipelineRunner.js +0 -326
- package/dist/sdk/pipeline/PipelineRunner.js.map +0 -1
- package/dist/sdk/pipeline/compiler.d.ts +0 -24
- package/dist/sdk/pipeline/compiler.d.ts.map +0 -1
- package/dist/sdk/pipeline/compiler.js +0 -199
- package/dist/sdk/pipeline/compiler.js.map +0 -1
- package/dist/sdk/pipeline/declarative.d.ts +0 -34
- package/dist/sdk/pipeline/declarative.d.ts.map +0 -1
- package/dist/sdk/pipeline/declarative.js +0 -9
- package/dist/sdk/pipeline/declarative.js.map +0 -1
- package/dist/sdk/pipeline/index.d.ts +0 -20
- package/dist/sdk/pipeline/index.d.ts.map +0 -1
- package/dist/sdk/pipeline/index.js +0 -19
- package/dist/sdk/pipeline/index.js.map +0 -1
- package/dist/sdk/pipeline/types.d.ts +0 -93
- package/dist/sdk/pipeline/types.d.ts.map +0 -1
- package/dist/sdk/pipeline/types.js +0 -10
- package/dist/sdk/pipeline/types.js.map +0 -1
- package/dist/sdk/policies.d.ts +0 -163
- package/dist/sdk/policies.d.ts.map +0 -1
- package/dist/sdk/policies.js +0 -243
- package/dist/sdk/policies.js.map +0 -1
- package/dist/sdk/runner/AgentRunner.d.ts +0 -22
- package/dist/sdk/runner/AgentRunner.d.ts.map +0 -1
- package/dist/sdk/runner/AgentRunner.js +0 -222
- package/dist/sdk/runner/AgentRunner.js.map +0 -1
- package/dist/sdk/runner/finalize.d.ts +0 -56
- package/dist/sdk/runner/finalize.d.ts.map +0 -1
- package/dist/sdk/runner/finalize.js +0 -155
- package/dist/sdk/runner/finalize.js.map +0 -1
- package/dist/sdk/runner/formats.d.ts +0 -7
- package/dist/sdk/runner/formats.d.ts.map +0 -1
- package/dist/sdk/runner/formats.js +0 -76
- package/dist/sdk/runner/formats.js.map +0 -1
- package/dist/sdk/runner/index.d.ts +0 -9
- package/dist/sdk/runner/index.d.ts.map +0 -1
- package/dist/sdk/runner/index.js +0 -9
- package/dist/sdk/runner/index.js.map +0 -1
- package/dist/sdk/runner/progress.d.ts +0 -3
- package/dist/sdk/runner/progress.d.ts.map +0 -1
- package/dist/sdk/runner/progress.js +0 -16
- package/dist/sdk/runner/progress.js.map +0 -1
- package/dist/sdk/schemas.d.ts +0 -72
- package/dist/sdk/schemas.d.ts.map +0 -1
- package/dist/sdk/schemas.js +0 -282
- package/dist/sdk/schemas.js.map +0 -1
- package/dist/sdk/trigger-context.d.ts +0 -24
- package/dist/sdk/trigger-context.d.ts.map +0 -1
- package/dist/sdk/trigger-context.js +0 -136
- package/dist/sdk/trigger-context.js.map +0 -1
- package/dist/session/SessionContext.d.ts +0 -89
- package/dist/session/SessionContext.d.ts.map +0 -1
- package/dist/session/SessionContext.js +0 -410
- package/dist/session/SessionContext.js.map +0 -1
- package/dist/session/environment.d.ts +0 -52
- package/dist/session/environment.d.ts.map +0 -1
- package/dist/session/environment.js +0 -27
- package/dist/session/environment.js.map +0 -1
- package/dist/session/history.d.ts +0 -18
- package/dist/session/history.d.ts.map +0 -1
- package/dist/session/history.js +0 -68
- package/dist/session/history.js.map +0 -1
- package/dist/session/index.d.ts +0 -10
- package/dist/session/index.d.ts.map +0 -1
- package/dist/session/index.js +0 -9
- package/dist/session/index.js.map +0 -1
- package/dist/session/serverData.d.ts +0 -38
- package/dist/session/serverData.d.ts.map +0 -1
- package/dist/session/serverData.js +0 -261
- package/dist/session/serverData.js.map +0 -1
- package/dist/tracing/pipelineHelpers.d.ts +0 -29
- package/dist/tracing/pipelineHelpers.d.ts.map +0 -1
- package/dist/tracing/pipelineHelpers.js +0 -224
- package/dist/tracing/pipelineHelpers.js.map +0 -1
- package/dist/tracking/Tracker.d.ts +0 -55
- package/dist/tracking/Tracker.d.ts.map +0 -1
- package/dist/tracking/Tracker.js +0 -217
- package/dist/tracking/Tracker.js.map +0 -1
- package/dist/tracking/index.d.ts +0 -8
- package/dist/tracking/index.d.ts.map +0 -1
- package/dist/tracking/index.js +0 -8
- package/dist/tracking/index.js.map +0 -1
- package/dist/tracking/schemas.d.ts +0 -292
- package/dist/tracking/schemas.d.ts.map +0 -1
- package/dist/tracking/schemas.js +0 -91
- package/dist/tracking/schemas.js.map +0 -1
- package/dist/utils/extractSetFlags.d.ts +0 -6
- package/dist/utils/extractSetFlags.d.ts.map +0 -1
- package/dist/utils/extractSetFlags.js +0 -16
- package/dist/utils/extractSetFlags.js.map +0 -1
- package/dist/utils/formatTimeAgo.d.ts +0 -2
- package/dist/utils/formatTimeAgo.d.ts.map +0 -1
- package/dist/utils/formatTimeAgo.js +0 -20
- package/dist/utils/formatTimeAgo.js.map +0 -1
- package/dist/utils/index.d.ts +0 -12
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -12
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/machineId.d.ts +0 -14
- package/dist/utils/machineId.d.ts.map +0 -1
- package/dist/utils/machineId.js +0 -66
- package/dist/utils/machineId.js.map +0 -1
- package/dist/utils/pathUtils.d.ts +0 -22
- package/dist/utils/pathUtils.d.ts.map +0 -1
- package/dist/utils/pathUtils.js +0 -54
- package/dist/utils/pathUtils.js.map +0 -1
- package/scripts/download-ripgrep.js +0 -269
|
@@ -0,0 +1,803 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `QodoClient` — the SDK 2.0 entry point.
|
|
3
|
+
*
|
|
4
|
+
* One typed wrapper layer above QAR's wire vocabulary. Sub-clients (`tasks`,
|
|
5
|
+
* `tools`, `info`, `pipeline`) mirror QAR's `kind` taxonomy; consumers `for await`
|
|
6
|
+
* the iterator returned by `tasks.start` and switch on `event.kind`.
|
|
7
|
+
*
|
|
8
|
+
* Construction is cheap and synchronous: validate options, hold the bearer, hand
|
|
9
|
+
* back sub-clients. `connect()` opens the WebSocket lazily; `disconnect()` tears
|
|
10
|
+
* it down.
|
|
11
|
+
*/
|
|
12
|
+
import { AuthProvider, QodoAuthError } from '../auth/index.js';
|
|
13
|
+
import { TaskClient } from './TaskClient.js';
|
|
14
|
+
import { ToolClient } from './ToolClient.js';
|
|
15
|
+
import { InfoClient } from './InfoClient.js';
|
|
16
|
+
import { SpecsClient } from './SpecsClient.js';
|
|
17
|
+
import { PipelineClient } from './PipelineClient.js';
|
|
18
|
+
import { BulletinClient } from './BulletinClient.js';
|
|
19
|
+
import { ArtifactsClient } from './ArtifactsClient.js';
|
|
20
|
+
import { StateClient } from './StateClient.js';
|
|
21
|
+
import { AgentsClient } from './AgentsClient.js';
|
|
22
|
+
import { QarRegistryClient } from './QarRegistryClient.js';
|
|
23
|
+
import { SkillsManager } from '../skills/manager.js';
|
|
24
|
+
import { QodoSkillsMcpServer, asMcpHandler } from '../skills/mcp/index.js';
|
|
25
|
+
import { Connection, RawSubscription } from './connection.js';
|
|
26
|
+
import { defaultTransportFactory } from './transport.js';
|
|
27
|
+
import { QodoClientOptionsError, QodoMcpToolError } from './errors.js';
|
|
28
|
+
import { resolveOTel } from '../observability/resolveOTel.js';
|
|
29
|
+
import { SpanRecorder } from '../observability/spans.js';
|
|
30
|
+
import { TraceContextProvider } from '../observability/traceContext.js';
|
|
31
|
+
import { TransportMetrics } from '../observability/transportMetrics.js';
|
|
32
|
+
import { getCurrentVersion } from '../version.js';
|
|
33
|
+
export class QodoClient {
|
|
34
|
+
/** Task lifecycle surface — `task.start` / `task.continue` / `task.cancel` / `task.resubscribe`. */
|
|
35
|
+
tasks;
|
|
36
|
+
/** Tool tunneling surface — inbound `tool.request`, outbound `tool.response`. */
|
|
37
|
+
tools;
|
|
38
|
+
/** Bootstrap surface — `GET /v1/info`, `GET /v1/auth/me`. */
|
|
39
|
+
info;
|
|
40
|
+
/** Pre-flight surface — `POST /v1/specs/validate` for inline specs. */
|
|
41
|
+
specs;
|
|
42
|
+
/** Pipeline DSL — chained over the task primitive. */
|
|
43
|
+
pipeline;
|
|
44
|
+
/** Read-only observer for QAR's `bulletin.post` envelopes (multi-agent coordination). */
|
|
45
|
+
bulletin;
|
|
46
|
+
/** Read-only observer for QAR's `artifact.add` envelopes (durable artifacts). */
|
|
47
|
+
artifacts;
|
|
48
|
+
/** Read-only observer for QAR's `state.update` envelopes (per-skill state mutations). */
|
|
49
|
+
state;
|
|
50
|
+
/** Read-only observer for QAR's `agent.spawn` envelopes (sub-agent topology). */
|
|
51
|
+
agents;
|
|
52
|
+
/**
|
|
53
|
+
* SDK-process-scoped local registries for consumer-built agents and MCP
|
|
54
|
+
* servers. See {@link QarRegistryClient} for the surface — `registerAgent`,
|
|
55
|
+
* `registerMcp`, plus unregister / lookup helpers.
|
|
56
|
+
*
|
|
57
|
+
* The SDK ships with zero built-in MCPs; everything a consumer wants
|
|
58
|
+
* their agents to call must be registered here (or be a server-side
|
|
59
|
+
* managed tool via `AgentSpec.use_managed_tools`).
|
|
60
|
+
*/
|
|
61
|
+
qar;
|
|
62
|
+
/**
|
|
63
|
+
* Skills foundation surface. Present iff `ClientOptions.skills` was
|
|
64
|
+
* provided at construction. `undefined` when skills are disabled —
|
|
65
|
+
* consumers branch on this before reaching for `.list()` / `.get()`.
|
|
66
|
+
*
|
|
67
|
+
* Discovery is lazy: the manager walks sources on the first
|
|
68
|
+
* `tasks.startWithAgent` / `tasks.startWithGraph` invocation that
|
|
69
|
+
* needs the catalog (or when the consumer calls `await
|
|
70
|
+
* client.skills.discover()` explicitly). Subsequent uses share the
|
|
71
|
+
* cached snapshot for the SDK lifetime.
|
|
72
|
+
*/
|
|
73
|
+
skills;
|
|
74
|
+
/**
|
|
75
|
+
* `qodo-skills` MCP server. Present iff `ClientOptions.skills` was
|
|
76
|
+
* provided at construction. Auto-registered via
|
|
77
|
+
* `client.qar.registerMcp('qodo-skills', { transport: 'sdk', handler })` —
|
|
78
|
+
* the SDK ships zero built-in MCPs by default, with `qodo-skills` as
|
|
79
|
+
* the per-config exception. The handler owns the three tools
|
|
80
|
+
* (`list_skills`, `get_skill`, `get_skill_file`) and the in-memory
|
|
81
|
+
* body / file caches.
|
|
82
|
+
*
|
|
83
|
+
* `undefined` when `skills` is not configured — the server isn't
|
|
84
|
+
* registered either, so the no-MCPs invariant holds for default-config
|
|
85
|
+
* consumers.
|
|
86
|
+
*/
|
|
87
|
+
skillsMcpServer;
|
|
88
|
+
/** Frozen copy of the construction options for runtime introspection. */
|
|
89
|
+
options;
|
|
90
|
+
/**
|
|
91
|
+
* Wire-level transport counters covering the reconnect + replay path.
|
|
92
|
+
* Three monotonic counters:
|
|
93
|
+
*
|
|
94
|
+
* - `replay_envelopes_received_total` — envelopes received as descendants
|
|
95
|
+
* of a `task.resubscribe` anchor.
|
|
96
|
+
* - `resubscribes_sent_total` — `task.resubscribe` envelopes the SDK
|
|
97
|
+
* emitted (auto-replay on reconnect AND manual `tasks.resubscribe`).
|
|
98
|
+
* - `replay_anchor_missing_total` — inbound `error { code:
|
|
99
|
+
* 'replay_anchor_missing' }` envelopes from QAR.
|
|
100
|
+
*
|
|
101
|
+
* Counters survive across reconnects and `disconnect()`. Read via
|
|
102
|
+
* {@link TransportMetrics.snapshot}.
|
|
103
|
+
*/
|
|
104
|
+
transportMetrics;
|
|
105
|
+
authProvider;
|
|
106
|
+
transportFactory;
|
|
107
|
+
/**
|
|
108
|
+
* OTel API the SDK emits spans against. Resolved once at construction time
|
|
109
|
+
* via the explicit `options.otel` first, then a best-effort dynamic
|
|
110
|
+
* `import('@opentelemetry/api')`. `undefined` means no OTel — every span
|
|
111
|
+
* call is a no-op and `traceparent` falls back to a fresh random.
|
|
112
|
+
*/
|
|
113
|
+
otel;
|
|
114
|
+
traceContext;
|
|
115
|
+
/** @internal — exposed to the sub-clients via `getSpanRecorder()`. */
|
|
116
|
+
spanRecorder;
|
|
117
|
+
connection = null;
|
|
118
|
+
connectInFlight = null;
|
|
119
|
+
constructor(opts) {
|
|
120
|
+
QodoClient.validateOptions(opts);
|
|
121
|
+
this.options = opts;
|
|
122
|
+
this.authProvider = QodoClient.buildAuthProvider(opts);
|
|
123
|
+
this.transportFactory = opts.transport ?? defaultTransportFactory;
|
|
124
|
+
this.otel = resolveOTel(opts.otel);
|
|
125
|
+
this.traceContext = new TraceContextProvider(this.otel);
|
|
126
|
+
this.spanRecorder = new SpanRecorder(this.otel, getCurrentVersion());
|
|
127
|
+
this.transportMetrics = new TransportMetrics();
|
|
128
|
+
this.qar = new QarRegistryClient();
|
|
129
|
+
if (opts.skills !== undefined) {
|
|
130
|
+
this.skills = new SkillsManager(opts.skills);
|
|
131
|
+
// The `qodo-skills` MCP server is the one default MCP the SDK
|
|
132
|
+
// ships, gated on the consumer opting in to skills. Tools
|
|
133
|
+
// (`list_skills`, `get_skill`, `get_skill_file`) auto-approved;
|
|
134
|
+
// effects of loaded skill bodies are gated separately by the trust
|
|
135
|
+
// model.
|
|
136
|
+
this.skillsMcpServer = new QodoSkillsMcpServer(this.skills);
|
|
137
|
+
this.qar.registerMcp('qodo-skills', {
|
|
138
|
+
transport: 'sdk',
|
|
139
|
+
handler: asMcpHandler(this.skillsMcpServer),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
this.tools = new ToolClient(() => this.requireConnection(), this.spanRecorder);
|
|
143
|
+
this.tasks = new TaskClient(() => this.requireConnection(), this.spanRecorder, this.qar,
|
|
144
|
+
// Lazy `SpecsClient` resolver — `tasks` is constructed before `specs`,
|
|
145
|
+
// so we defer the dereference until `startWithGraph({ preflight: true })`
|
|
146
|
+
// actually needs it.
|
|
147
|
+
() => this.specs, this.transportMetrics, this.skills,
|
|
148
|
+
// `defineFunctionTool` auto-bind callback. Routes through the
|
|
149
|
+
// `ToolClient`'s public `bindFunctionTools` method so the
|
|
150
|
+
// explicit + implicit registration paths share one
|
|
151
|
+
// implementation. Idempotent — calling this for the same tool
|
|
152
|
+
// repeatedly just keeps the same entry in the router's map.
|
|
153
|
+
(tools) => {
|
|
154
|
+
this.tools.bindFunctionTools(tools);
|
|
155
|
+
});
|
|
156
|
+
this.info = new InfoClient({
|
|
157
|
+
baseUrl: opts.baseUrl,
|
|
158
|
+
authProvider: this.authProvider,
|
|
159
|
+
...(opts.headers !== undefined ? { headers: opts.headers } : {}),
|
|
160
|
+
...(opts.allowInsecureTransport !== undefined
|
|
161
|
+
? { allowInsecureTransport: opts.allowInsecureTransport }
|
|
162
|
+
: {}),
|
|
163
|
+
});
|
|
164
|
+
this.specs = new SpecsClient({
|
|
165
|
+
baseUrl: opts.baseUrl,
|
|
166
|
+
authProvider: this.authProvider,
|
|
167
|
+
...(opts.headers !== undefined ? { headers: opts.headers } : {}),
|
|
168
|
+
...(opts.allowInsecureTransport !== undefined
|
|
169
|
+
? { allowInsecureTransport: opts.allowInsecureTransport }
|
|
170
|
+
: {}),
|
|
171
|
+
});
|
|
172
|
+
this.pipeline = new PipelineClient(this);
|
|
173
|
+
this.bulletin = new BulletinClient();
|
|
174
|
+
this.artifacts = new ArtifactsClient();
|
|
175
|
+
this.state = new StateClient();
|
|
176
|
+
this.agents = new AgentsClient();
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Open the underlying WebSocket. Idempotent — calling twice without an
|
|
180
|
+
* intervening `disconnect()` returns the same live connection.
|
|
181
|
+
*
|
|
182
|
+
* On a 401/403 from the upgrade, throws `QodoAuthError` with the auth source
|
|
183
|
+
* named so the caller can fix the right surface (env var, file, or explicit).
|
|
184
|
+
*/
|
|
185
|
+
async connect() {
|
|
186
|
+
if (this.connection !== null && this.connection.isOpen)
|
|
187
|
+
return;
|
|
188
|
+
if (this.connectInFlight !== null) {
|
|
189
|
+
await this.connectInFlight;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
this.authProvider.validate();
|
|
193
|
+
const { token } = this.authProvider.getAuthConfig();
|
|
194
|
+
const wsUrl = QodoClient.deriveWsUrl(this.options.baseUrl, this.options.allowInsecureTransport ?? false);
|
|
195
|
+
const maxPausedQueueSize = this.options.backpressure?.maxPausedQueueSize;
|
|
196
|
+
const reconnect = this.options.reconnect;
|
|
197
|
+
const span = this.spanRecorder.startConnectSpan();
|
|
198
|
+
// Run the WS upgrade inside the connect span's context. The `Connection`
|
|
199
|
+
// doesn't send any envelopes during `open()` (no traceparent emission to
|
|
200
|
+
// affect), but consumer code reading `getActiveSpan()` from inside an
|
|
201
|
+
// `await client.connect()` continuation will see the connect span — so
|
|
202
|
+
// any custom logging / hooks there nest correctly.
|
|
203
|
+
this.connectInFlight = span.withContext(async () => {
|
|
204
|
+
try {
|
|
205
|
+
return await Connection.open({
|
|
206
|
+
factory: this.transportFactory,
|
|
207
|
+
url: wsUrl,
|
|
208
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
209
|
+
traceContext: this.traceContext,
|
|
210
|
+
metrics: this.transportMetrics,
|
|
211
|
+
...(maxPausedQueueSize !== undefined ? { maxPausedQueueSize } : {}),
|
|
212
|
+
...(reconnect !== undefined ? { reconnect } : {}),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
if (err instanceof QodoAuthError) {
|
|
217
|
+
// Re-throw with the auth-source diagnostic so the user knows where to fix.
|
|
218
|
+
this.authProvider.handle401Error();
|
|
219
|
+
}
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
try {
|
|
224
|
+
this.connection = await this.connectInFlight;
|
|
225
|
+
// The `Connection` no longer carries a session id — each
|
|
226
|
+
// `task.start` creates a server-derived session, and the SDK
|
|
227
|
+
// tracks `task_id → session_id` per-Task. Connect/disconnect
|
|
228
|
+
// spans report only that the upgrade succeeded; session
|
|
229
|
+
// attribution lives on the per-Task `qar.client.task.*` spans
|
|
230
|
+
// where it actually applies.
|
|
231
|
+
span.succeed();
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
span.fail(err);
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
finally {
|
|
238
|
+
this.connectInFlight = null;
|
|
239
|
+
}
|
|
240
|
+
// Kick off skills discovery alongside the WS upgrade so the first
|
|
241
|
+
// `tasks.startWithAgent` / `tasks.startWithGraph` sees a populated
|
|
242
|
+
// catalog. Errors during discovery don't block connect — the
|
|
243
|
+
// manager surfaces per-source `sdk.skill.error` events through the
|
|
244
|
+
// configured telemetry sink.
|
|
245
|
+
if (this.skills !== undefined) {
|
|
246
|
+
try {
|
|
247
|
+
await this.skills.discover();
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// best-effort — telemetry already emitted at the manager
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Bind the tool-tunneling fan-out *after* the connection is committed so
|
|
254
|
+
// an inbound `tool.request` arriving with zero `onRequest` handlers
|
|
255
|
+
// deterministically emits `outcome: "denied"` rather than leaving QAR's
|
|
256
|
+
// agent loop paused on the `tool_call_id`.
|
|
257
|
+
this.tools._bindConnection(this.connection);
|
|
258
|
+
// When skills are configured, attach a `tool.request` bridge that
|
|
259
|
+
// intercepts `qodo-skills.list_skills` / `qodo-skills.get_skill` /
|
|
260
|
+
// `qodo-skills.get_skill_file` calls and dispatches them through the
|
|
261
|
+
// registered MCP handler. Bare names (no `qodo-skills.` prefix) are
|
|
262
|
+
// also matched so QAR deployments routing by short name see the same
|
|
263
|
+
// surface. Other tool names fall through to consumer-registered
|
|
264
|
+
// handlers via `client.tools.onRequest(...)`.
|
|
265
|
+
this.attachSkillsMcpBridge();
|
|
266
|
+
// Rebuild pooled MCP `Client` entries for any remote/stdio configs
|
|
267
|
+
// registered before connect (typical happy path — consumer wires
|
|
268
|
+
// `registerMcp` before `connect()`) AND any that survived a prior
|
|
269
|
+
// `disconnect()` cycle (pool was dispose()d but registry state
|
|
270
|
+
// persisted). Idempotent across reconnects.
|
|
271
|
+
this.qar._rebuildPoolEntries();
|
|
272
|
+
// Install a lifecycle hook on the registry so the generic
|
|
273
|
+
// `tool.request` MCP bridge attaches symmetric to remote / stdio MCP
|
|
274
|
+
// presence. Skipping the attach when zero remote MCPs are registered
|
|
275
|
+
// preserves `ToolClient`'s "no handler → deterministic deny" path; a
|
|
276
|
+
// bridge that returns `undefined` for every unresolved call would
|
|
277
|
+
// shadow the deny fallback. `_installRemoteMcpHook` synchronously
|
|
278
|
+
// fires `onFirstRegistered` if any remote / stdio MCPs were already
|
|
279
|
+
// registered pre-connect.
|
|
280
|
+
this.qar._installRemoteMcpHook({
|
|
281
|
+
onFirstRegistered: () => this.attachRemoteMcpBridge(),
|
|
282
|
+
onLastUnregistered: () => this.detachRemoteMcpBridge(),
|
|
283
|
+
});
|
|
284
|
+
// Wire the read-only observer sub-clients to the live connection. Each
|
|
285
|
+
// sub-client keeps its handler registry across connect/disconnect cycles
|
|
286
|
+
// — `attach` just registers a fresh `InboundSubscription` against the
|
|
287
|
+
// current `Connection` so envelopes start flowing.
|
|
288
|
+
this.bulletin.attach(this.connection);
|
|
289
|
+
this.artifacts.attach(this.connection);
|
|
290
|
+
this.state.attach(this.connection);
|
|
291
|
+
this.agents.attach(this.connection);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Subscription token returned by `attachSkillsMcpBridge`. Kept so that
|
|
295
|
+
* `disconnect()` can clean up the bridge alongside the tool dispatcher.
|
|
296
|
+
* Initialized to `null` until skills are wired.
|
|
297
|
+
*/
|
|
298
|
+
skillsMcpBridge = null;
|
|
299
|
+
/**
|
|
300
|
+
* Auto-wire a `tool.request` handler that intercepts qodo-skills tool
|
|
301
|
+
* calls and dispatches them through the registered MCP handler. Skipped
|
|
302
|
+
* when `skillsMcpServer` is undefined (consumer didn't opt into skills).
|
|
303
|
+
*
|
|
304
|
+
* **Tool-name matching.** The qodo-skills MCP exposes three tools:
|
|
305
|
+
* `list_skills`, `get_skill`, `get_skill_file`. QAR deployments may
|
|
306
|
+
* surface them either bare or under the `qodo-skills.` server prefix
|
|
307
|
+
* (the open MCP convention). The bridge accepts both shapes — anything
|
|
308
|
+
* else falls through to consumer-registered handlers via the normal
|
|
309
|
+
* `client.tools.onRequest(...)` stack.
|
|
310
|
+
*
|
|
311
|
+
* **Why the bridge lives here.** The qodo-skills tools are intrinsic
|
|
312
|
+
* to the Skills feature, not a generic MCP we registered for the
|
|
313
|
+
* consumer's convenience — the SDK owns their dispatch end to end.
|
|
314
|
+
* Auto-wiring the bridge here keeps the consumer's `onRequest` stack
|
|
315
|
+
* free of skills routing concerns.
|
|
316
|
+
*
|
|
317
|
+
* **Symmetric projection auto-include.** The dispatch end
|
|
318
|
+
* (this bridge) is only half the contract. The other half is the
|
|
319
|
+
* wire-side surface: `TaskClient.projectMcpToolsForWire` /
|
|
320
|
+
* `mergeQodoSkillsTools` auto-includes the three
|
|
321
|
+
* `qodo-skills.list_skills` / `qodo-skills.get_skill` /
|
|
322
|
+
* `qodo-skills.get_skill_file` entries in every dispatched agent's
|
|
323
|
+
* `function_tools` list when `ClientOptions.skills` is configured,
|
|
324
|
+
* regardless of the consumer's `mcpTools.allowlist`. The bridge
|
|
325
|
+
* matches what the projection advertises; the projection ships what
|
|
326
|
+
* the slim-index preamble references. Both ends move together — if
|
|
327
|
+
* you change the tool names here, mirror the change in
|
|
328
|
+
* `qodoSkillsFunctionToolDefs()` (skills/mcp/server.ts) and the
|
|
329
|
+
* `BLOCK_PREAMBLE` text (skills/render.ts).
|
|
330
|
+
*
|
|
331
|
+
* **Precedence vs. remote MCPs.** The skills bridge is attached
|
|
332
|
+
* BEFORE the generic remote-MCP bridge in `QodoClient.connect()`, so
|
|
333
|
+
* its bare-name match on `list_skills` / `get_skill` /
|
|
334
|
+
* `get_skill_file` wins over a registered remote MCP that happens to
|
|
335
|
+
* advertise the same name. This is intentional — the qodo-skills
|
|
336
|
+
* tools are intrinsic to the Skills feature surface and consumers
|
|
337
|
+
* shouldn't be able to shadow them by registering a same-named remote
|
|
338
|
+
* MCP. A consumer who legitimately needs to reach a remote MCP's
|
|
339
|
+
* same-named tool uses the prefix form: `mcp-name.list_skills` (or
|
|
340
|
+
* `mcp-name:list_skills` / `mcp-name/list_skills`) — the remote-MCP
|
|
341
|
+
* bridge resolves the prefix form against the registered MCP set, not
|
|
342
|
+
* against the skills bridge's hardcoded names.
|
|
343
|
+
*/
|
|
344
|
+
attachSkillsMcpBridge() {
|
|
345
|
+
const server = this.skillsMcpServer;
|
|
346
|
+
if (server === undefined)
|
|
347
|
+
return;
|
|
348
|
+
if (this.skillsMcpBridge !== null)
|
|
349
|
+
return;
|
|
350
|
+
const QODO_SKILLS_TOOLS = new Set(['list_skills', 'get_skill', 'get_skill_file']);
|
|
351
|
+
const stripPrefix = (name) => {
|
|
352
|
+
if (QODO_SKILLS_TOOLS.has(name))
|
|
353
|
+
return name;
|
|
354
|
+
const prefix = 'qodo-skills.';
|
|
355
|
+
if (name.startsWith(prefix)) {
|
|
356
|
+
const bare = name.slice(prefix.length);
|
|
357
|
+
if (QODO_SKILLS_TOOLS.has(bare))
|
|
358
|
+
return bare;
|
|
359
|
+
}
|
|
360
|
+
// Some MCP runtimes use a `:` separator (`qodo-skills:list_skills`).
|
|
361
|
+
const colonPrefix = 'qodo-skills:';
|
|
362
|
+
if (name.startsWith(colonPrefix)) {
|
|
363
|
+
const bare = name.slice(colonPrefix.length);
|
|
364
|
+
if (QODO_SKILLS_TOOLS.has(bare))
|
|
365
|
+
return bare;
|
|
366
|
+
}
|
|
367
|
+
return undefined;
|
|
368
|
+
};
|
|
369
|
+
// Register the skills bridge as a FALLBACK handler so the
|
|
370
|
+
// dispatcher's "no consumer handler → deterministic deny" path
|
|
371
|
+
// stays consumer-keyed. SDK auto-bridges are advisory routing
|
|
372
|
+
// layers, not consumer-side handlers.
|
|
373
|
+
this.skillsMcpBridge = this.tools._attachFallbackHandler(async (request) => {
|
|
374
|
+
const calls = request.payload.calls;
|
|
375
|
+
// Identify which calls (if any) target qodo-skills.
|
|
376
|
+
const targeting = calls.map((c) => stripPrefix(c.name));
|
|
377
|
+
if (targeting.every((t) => t === undefined)) {
|
|
378
|
+
// No qodo-skills calls in this batch — let the consumer's
|
|
379
|
+
// handler stack process the whole batch.
|
|
380
|
+
return undefined;
|
|
381
|
+
}
|
|
382
|
+
if (targeting.some((t) => t === undefined)) {
|
|
383
|
+
// Mixed batch (some qodo-skills, some not). `ToolClient`'s
|
|
384
|
+
// handler stack semantics are "first non-undefined claims the
|
|
385
|
+
// entire batch" — if we returned a partial array here, every
|
|
386
|
+
// non-qodo-skills call would be force-denied and consumer
|
|
387
|
+
// handlers would never run. Better to defer: return `undefined`
|
|
388
|
+
// so the consumer's handler sees the batch. The consumer is
|
|
389
|
+
// responsible for routing qodo-skills calls (e.g., by
|
|
390
|
+
// delegating to `client.skillsMcpServer.callTool` for those
|
|
391
|
+
// entries).
|
|
392
|
+
//
|
|
393
|
+
// QAR's current single-server-per-batch convention means this
|
|
394
|
+
// path is unreachable in normal operation; the safe-by-default
|
|
395
|
+
// posture exists so a future QAR routing change doesn't silently
|
|
396
|
+
// break mixed batches.
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
// All-qodo-skills batch — safe to claim. The handler returns
|
|
400
|
+
// ToolResponseResult[] positionally matching `calls`; the
|
|
401
|
+
// ToolClient dispatcher pairs them with each call's tool_call_id
|
|
402
|
+
// at the wire boundary.
|
|
403
|
+
const responses = await Promise.all(calls.map(async (call, i) => {
|
|
404
|
+
const bare = targeting[i];
|
|
405
|
+
const mcpResult = await server.callTool(bare, call.arguments);
|
|
406
|
+
if (mcpResult.isError === true) {
|
|
407
|
+
const message = mcpResult.content[0]?.type === 'text'
|
|
408
|
+
? mcpResult.content[0].text
|
|
409
|
+
: 'qodo-skills tool returned an error';
|
|
410
|
+
return { outcome: 'error', error: message };
|
|
411
|
+
}
|
|
412
|
+
// Success — serialize the MCP envelope as the tool's JSON
|
|
413
|
+
// result. QAR's agent loop reads this as the tool response
|
|
414
|
+
// body. The MCP envelope's `content` array is JSON-cloned so
|
|
415
|
+
// the wire payload is a plain JsonObject (no Buffers, etc. —
|
|
416
|
+
// the MCP server already base64-encodes binary content).
|
|
417
|
+
return {
|
|
418
|
+
outcome: 'success',
|
|
419
|
+
result: JSON.parse(JSON.stringify(mcpResult)),
|
|
420
|
+
};
|
|
421
|
+
}));
|
|
422
|
+
return responses;
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Subscription token returned by `attachRemoteMcpBridge`. Mirrors
|
|
427
|
+
* {@link skillsMcpBridge} — kept so `disconnect()` can detach the bridge
|
|
428
|
+
* alongside the skills variant.
|
|
429
|
+
*/
|
|
430
|
+
remoteMcpBridge = null;
|
|
431
|
+
/**
|
|
432
|
+
* Auto-wire a `tool.request` handler that resolves each call's
|
|
433
|
+
* `name` against `qar.resolveMcpForTool` and dispatches the resolved set
|
|
434
|
+
* through {@link QarRegistryClient.callMcpTool} (which round-trips via the
|
|
435
|
+
* canonical `@modelcontextprotocol/sdk` `Client.callTool`).
|
|
436
|
+
*
|
|
437
|
+
* **Claim semantics.** Three batch shapes:
|
|
438
|
+
*
|
|
439
|
+
* - **All-resolved** — every call's name routes to a registered
|
|
440
|
+
* remote / stdio MCP. Bridge claims; each call dispatches via
|
|
441
|
+
* {@link QarRegistryClient.callMcpTool}; per-call success /
|
|
442
|
+
* error responses are returned positionally.
|
|
443
|
+
*
|
|
444
|
+
* - **All-unresolved** — no call routes to any registered MCP.
|
|
445
|
+
* Bridge returns `undefined` so consumer-registered
|
|
446
|
+
* `client.tools.onRequest(...)` handlers can intercept the
|
|
447
|
+
* batch (consumers may legitimately wire unrelated custom tools
|
|
448
|
+
* alongside remote MCPs). Consumers who register remote MCPs
|
|
449
|
+
* and want unknown-tool calls handled MUST register their own
|
|
450
|
+
* `onRequest` handler; otherwise the call waits for QAR's
|
|
451
|
+
* per-task tool-response timeout (the documented wire-side safety
|
|
452
|
+
* net for the "all handlers returned undefined" case).
|
|
453
|
+
*
|
|
454
|
+
* - **Mixed batch** — some resolved, some not. Returns `undefined`
|
|
455
|
+
* so consumer-registered `client.tools.onRequest(...)` handlers
|
|
456
|
+
* can intercept. QAR's single-server-per-batch convention means
|
|
457
|
+
* this path is unreachable in normal operation; the defer posture
|
|
458
|
+
* is the safety hatch for a future QAR routing change that might
|
|
459
|
+
* produce mixed batches.
|
|
460
|
+
*
|
|
461
|
+
* **Bare-name catalog race.** First-dispatch bare-name resolution
|
|
462
|
+
* scans the cached `entry.tools` populated by `listTools()` at
|
|
463
|
+
* `commitEntry` time. A `tool.request` arriving immediately after
|
|
464
|
+
* `registerMcp` (before connect+listTools resolved) would otherwise
|
|
465
|
+
* see an empty catalog and fall into the all-unresolved defer path.
|
|
466
|
+
* The bridge awaits {@link QarRegistryClient._waitForMcpCatalogsToSettle}
|
|
467
|
+
* before deciding "unresolved" so first-call timing doesn't
|
|
468
|
+
* mis-classify a legitimate bare-name lookup as unknown.
|
|
469
|
+
*/
|
|
470
|
+
attachRemoteMcpBridge() {
|
|
471
|
+
if (this.remoteMcpBridge !== null)
|
|
472
|
+
return;
|
|
473
|
+
// No live connection — `ToolClient.onRequest` would throw because the
|
|
474
|
+
// dispatcher seam can only attach against an open WebSocket. The hook
|
|
475
|
+
// fires during the connect span; if the user invoked
|
|
476
|
+
// `qar.registerMcp(... remote ...)` before connect, the bridge attach
|
|
477
|
+
// happens on the next `connect()` via `_rebuildPoolEntries` →
|
|
478
|
+
// `_installRemoteMcpHook` ordering. Calls landing here without a live
|
|
479
|
+
// connection mean the hook fired during reconnect ordering — bail to
|
|
480
|
+
// let the install cycle complete; subsequent registers re-fire the
|
|
481
|
+
// hook with the bridge slot still empty.
|
|
482
|
+
if (this.connection === null)
|
|
483
|
+
return;
|
|
484
|
+
// Register the remote-MCP bridge as a FALLBACK handler so
|
|
485
|
+
// consumer-registered `onRequest` handlers get first claim and the
|
|
486
|
+
// dispatcher's "no consumer handler → deterministic deny" fallback
|
|
487
|
+
// fires deterministically when no consumer has wired in a handler.
|
|
488
|
+
this.remoteMcpBridge = this.tools._attachFallbackHandler(async (request) => {
|
|
489
|
+
const calls = request.payload.calls;
|
|
490
|
+
let resolved = calls.map((c) => this.qar.resolveMcpForTool(c.name));
|
|
491
|
+
if (resolved.some((r) => r === undefined)) {
|
|
492
|
+
// First-call race protection — if any name failed to resolve,
|
|
493
|
+
// wait for every pending catalog to settle and re-scan. This
|
|
494
|
+
// makes the bare-name fallback robust against the
|
|
495
|
+
// `registerMcp → tool.request` timing window where the
|
|
496
|
+
// background `listTools()` hasn't populated the cache yet.
|
|
497
|
+
await this.qar._waitForMcpCatalogsToSettle();
|
|
498
|
+
resolved = calls.map((c) => this.qar.resolveMcpForTool(c.name));
|
|
499
|
+
}
|
|
500
|
+
// Defer ANY batch with at least one unresolved name back to the
|
|
501
|
+
// consumer's handler stack. Only claim batches that are fully
|
|
502
|
+
// resolved against the registered MCP set. This preserves
|
|
503
|
+
// `client.tools.onRequest(...)` ergonomics for consumers who wire
|
|
504
|
+
// both remote MCPs and hand-crafted handlers for unrelated tools.
|
|
505
|
+
if (resolved.some((r) => r === undefined)) {
|
|
506
|
+
return undefined;
|
|
507
|
+
}
|
|
508
|
+
const responses = await Promise.all(calls.map(async (call, i) => {
|
|
509
|
+
const route = resolved[i];
|
|
510
|
+
try {
|
|
511
|
+
const mcpResult = await this.qar.callMcpTool(route.mcpName, route.toolName, call.arguments);
|
|
512
|
+
return {
|
|
513
|
+
outcome: 'success',
|
|
514
|
+
result: JSON.parse(JSON.stringify(mcpResult)),
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
catch (err) {
|
|
518
|
+
// MCP convention treats `{ isError: true, content: [...] }`
|
|
519
|
+
// as a NORMAL tool result — the structured content is meant
|
|
520
|
+
// for the LLM to read + self-correct ("invalid input: missing
|
|
521
|
+
// field X"). Collapsing it to a string `outcome:'error'`
|
|
522
|
+
// drops the very signal the LLM needs.
|
|
523
|
+
//
|
|
524
|
+
// `QodoMcpToolError.mcpResult` is populated only on the
|
|
525
|
+
// isError-envelope path; the transport-throw path leaves it
|
|
526
|
+
// undefined and falls through to `outcome:'error'` with the
|
|
527
|
+
// message (the right wire shape for SDK-side failures).
|
|
528
|
+
if (err instanceof QodoMcpToolError && err.mcpResult !== undefined) {
|
|
529
|
+
return {
|
|
530
|
+
outcome: 'success',
|
|
531
|
+
result: JSON.parse(JSON.stringify(err.mcpResult)),
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
outcome: 'error',
|
|
536
|
+
error: err instanceof Error ? err.message : String(err),
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
}));
|
|
540
|
+
return responses;
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Detach the remote-MCP bridge. Idempotent — safe to call when the
|
|
545
|
+
* bridge is already detached. Fired both from {@link disconnect} and
|
|
546
|
+
* from the registry hook when the last remote / stdio MCP is
|
|
547
|
+
* unregistered (preserves `ToolClient`'s deny fallback for subsequent
|
|
548
|
+
* `tool.request` envelopes).
|
|
549
|
+
*/
|
|
550
|
+
detachRemoteMcpBridge() {
|
|
551
|
+
if (this.remoteMcpBridge === null)
|
|
552
|
+
return;
|
|
553
|
+
this.remoteMcpBridge.unsubscribe();
|
|
554
|
+
this.remoteMcpBridge = null;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Close the underlying WebSocket and abort any in-flight task iterators.
|
|
558
|
+
* Idempotent.
|
|
559
|
+
*/
|
|
560
|
+
async disconnect() {
|
|
561
|
+
if (this.connectInFlight !== null) {
|
|
562
|
+
try {
|
|
563
|
+
await this.connectInFlight;
|
|
564
|
+
}
|
|
565
|
+
catch {
|
|
566
|
+
// Connect may have failed; either way we proceed to tear down.
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
// Null `this.connection` BEFORE the awaited pool teardown so two
|
|
570
|
+
// concurrent `disconnect()` calls don't both capture the same live
|
|
571
|
+
// connection (and emit duplicate disconnect spans / re-detach
|
|
572
|
+
// observers). `Connection.close()` is idempotent so the
|
|
573
|
+
// late-capturing call wouldn't double-close, but the duplicate
|
|
574
|
+
// span emission + redundant observer detach is wasted work worth
|
|
575
|
+
// avoiding.
|
|
576
|
+
const conn = this.connection;
|
|
577
|
+
this.connection = null;
|
|
578
|
+
// MCP pool teardown + bridge unsubscribe MUST run on every
|
|
579
|
+
// `disconnect()` call — including the "registered a stdio MCP,
|
|
580
|
+
// never called connect(), now calling disconnect()" path. Pool
|
|
581
|
+
// entries are spawned at `registerMcp` time (eager connect), so the
|
|
582
|
+
// subprocess is alive even before the QAR WebSocket is opened.
|
|
583
|
+
// Gating pool dispose on the live WS connection leaks subprocesses
|
|
584
|
+
// + reconnect-timer HTTP keep-alives whenever the consumer
|
|
585
|
+
// registers MCPs without ever calling connect().
|
|
586
|
+
//
|
|
587
|
+
// We run the bridge / pool / skills cleanups BEFORE the WS-state
|
|
588
|
+
// branch so the never-connected path still reaches them; the WS-state
|
|
589
|
+
// branch handles span emission + observer-sub-client detach only.
|
|
590
|
+
if (this.skillsMcpBridge !== null) {
|
|
591
|
+
this.skillsMcpBridge.unsubscribe();
|
|
592
|
+
this.skillsMcpBridge = null;
|
|
593
|
+
}
|
|
594
|
+
if (this.skillsMcpServer !== undefined) {
|
|
595
|
+
this.skillsMcpServer.dispose();
|
|
596
|
+
}
|
|
597
|
+
this.detachRemoteMcpBridge();
|
|
598
|
+
this.qar._clearRemoteMcpHook();
|
|
599
|
+
// Close every pooled MCP `Client` so subprocess MCPs aren't
|
|
600
|
+
// orphaned and HTTP transports drop their reconnect timers. The registry
|
|
601
|
+
// itself is process-scoped (not connection-scoped); the next connect()
|
|
602
|
+
// re-attaches the bridge and the pool will re-register entries lazily
|
|
603
|
+
// on the next `qar.registerMcp` call. Pool entries currently in the map
|
|
604
|
+
// ARE disposed — a reconnect after disconnect drops every remote/stdio
|
|
605
|
+
// registration, mirroring how `skillsMcpServer.dispose()` drops the
|
|
606
|
+
// skills caches above.
|
|
607
|
+
await this.qar._disposePool();
|
|
608
|
+
if (conn === null)
|
|
609
|
+
return;
|
|
610
|
+
// No connection-level session_id to attach. The disconnect span
|
|
611
|
+
// covers transport teardown only; per-Task session attribution is
|
|
612
|
+
// on the `qar.client.task.*` spans.
|
|
613
|
+
const span = this.spanRecorder.startDisconnectSpan({});
|
|
614
|
+
// `this.connection` was already nulled at the top of `disconnect()`
|
|
615
|
+
// (anti-duplicate-tear-down).
|
|
616
|
+
// Detach observer sub-clients before closing the connection so their
|
|
617
|
+
// ports unregister cleanly and the next `connect()` starts with a fresh
|
|
618
|
+
// `InboundSubscription` registered against the new transport.
|
|
619
|
+
this.bulletin.detach();
|
|
620
|
+
this.artifacts.detach();
|
|
621
|
+
this.state.detach();
|
|
622
|
+
this.agents.detach();
|
|
623
|
+
try {
|
|
624
|
+
span.withContext(() => conn.close());
|
|
625
|
+
span.succeed();
|
|
626
|
+
}
|
|
627
|
+
catch (err) {
|
|
628
|
+
span.fail(err);
|
|
629
|
+
throw err;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Send a raw envelope verbatim. Escape hatch for advanced consumers — most
|
|
634
|
+
* callers use `tasks.start` / `tasks.continue` / `tools.respond` instead.
|
|
635
|
+
*
|
|
636
|
+
* The envelope must already be fully populated:
|
|
637
|
+
* - `message_id`, `ts`, `envelope_version`, `trace_context` on every kind
|
|
638
|
+
* - `session_id` on every kind EXCEPT `task.start`
|
|
639
|
+
*
|
|
640
|
+
* The `task.start` envelope is a `_StartEnvelopeBase` (no `session_id`
|
|
641
|
+
* on the wire); the type narrowing on {@link TaskStartEnvelope} omits
|
|
642
|
+
* the field so raw senders cannot compile an invalid `task.start`.
|
|
643
|
+
* All other kinds inherit `_OngoingEnvelopeBase` and require
|
|
644
|
+
* `session_id`.
|
|
645
|
+
*
|
|
646
|
+
* The connection writes the envelope through the underlying transport
|
|
647
|
+
* unchanged.
|
|
648
|
+
*/
|
|
649
|
+
send(envelope) {
|
|
650
|
+
this.requireConnection().sendRawEnvelope(envelope);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Subscribe to every inbound envelope plus the SDK-internal
|
|
654
|
+
* `qar.client.*` lifecycle events. The same envelopes that drive
|
|
655
|
+
* `tasks.start()` iterators flow here too; useful for telemetry / logging /
|
|
656
|
+
* advanced consumers.
|
|
657
|
+
*
|
|
658
|
+
* Yielded type is the union `Envelope | ClientEvent`. `Envelope` arms carry
|
|
659
|
+
* the wire `kind` discriminators; `ClientEvent` arms carry `qar.client.*`
|
|
660
|
+
* keys that can never collide with QAR envelope kinds. `switch (ev.kind)`
|
|
661
|
+
* narrows cleanly between the two.
|
|
662
|
+
*/
|
|
663
|
+
receive() {
|
|
664
|
+
const conn = this.requireConnection();
|
|
665
|
+
const sub = new RawSubscription((s) => conn.unsubscribe(s));
|
|
666
|
+
conn.subscribe(sub);
|
|
667
|
+
return sub;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Whether the underlying connection is currently in `flow.pause`.
|
|
671
|
+
* `false` when not connected — disconnect always resets the flag.
|
|
672
|
+
*
|
|
673
|
+
* The SDK obeys backpressure transparently; consumers don't normally need
|
|
674
|
+
* to check this. It's exposed for richer surfaces (CLIs, UIs) that want to
|
|
675
|
+
* show a "server overloaded; waiting" indicator. Reading this is cheap and
|
|
676
|
+
* synchronous.
|
|
677
|
+
*/
|
|
678
|
+
get isPaused() {
|
|
679
|
+
return this.connection?.isPaused ?? false;
|
|
680
|
+
}
|
|
681
|
+
/** @internal — used by sub-clients to access the live connection. */
|
|
682
|
+
requireConnection() {
|
|
683
|
+
if (this.connection === null || !this.connection.isOpen) {
|
|
684
|
+
throw new Error('QodoClient is not connected. Call await client.connect() first.');
|
|
685
|
+
}
|
|
686
|
+
return this.connection;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Synchronous validation of `ClientOptions`. Runs at construction time so
|
|
690
|
+
* misconfigured callers fail fast instead of at the first `tasks.start`.
|
|
691
|
+
*
|
|
692
|
+
* Treats the construction call as a system boundary — JavaScript callers can
|
|
693
|
+
* pass `null` even though TypeScript bars it, so we check both `undefined`
|
|
694
|
+
* and `null` and refuse with a typed error rather than letting a subsequent
|
|
695
|
+
* property access throw an unhelpful `TypeError`.
|
|
696
|
+
*/
|
|
697
|
+
static validateOptions(opts) {
|
|
698
|
+
if (typeof opts.baseUrl !== 'string' || opts.baseUrl.length === 0) {
|
|
699
|
+
throw new QodoClientOptionsError('ClientOptions.baseUrl is required and must be a non-empty string');
|
|
700
|
+
}
|
|
701
|
+
if (opts.auth === undefined || opts.auth === null) {
|
|
702
|
+
throw new QodoClientOptionsError('ClientOptions.auth is required (use "env" or { apiKey })');
|
|
703
|
+
}
|
|
704
|
+
if (opts.auth !== 'env') {
|
|
705
|
+
if (typeof opts.auth !== 'object') {
|
|
706
|
+
throw new QodoClientOptionsError('ClientOptions.auth must be "env" or an object with an apiKey');
|
|
707
|
+
}
|
|
708
|
+
const apiKey = opts.auth.apiKey;
|
|
709
|
+
if (typeof apiKey !== 'string' || apiKey.length === 0) {
|
|
710
|
+
throw new QodoClientOptionsError('ClientOptions.auth.apiKey must be a non-empty string');
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// `allowInsecureTransport` gates a security-relevant codepath (sending the
|
|
714
|
+
// bearer over plaintext). Runtime-validate the type so a JS caller can't
|
|
715
|
+
// pass a truthy non-boolean (e.g. `'false'`, `1`) and silently bypass the
|
|
716
|
+
// `https://`-only default. The downstream guards check `!== true` rather
|
|
717
|
+
// than `!value` for the same reason.
|
|
718
|
+
if (opts.allowInsecureTransport !== undefined &&
|
|
719
|
+
typeof opts.allowInsecureTransport !== 'boolean') {
|
|
720
|
+
throw new QodoClientOptionsError('ClientOptions.allowInsecureTransport must be a boolean (or omitted)');
|
|
721
|
+
}
|
|
722
|
+
// Backpressure tuning is optional. When provided, validate at construction
|
|
723
|
+
// time so JS callers (which TS can't constrain) get a typed error rather
|
|
724
|
+
// than a coerced cap that silently misbehaves at the throttle boundary.
|
|
725
|
+
if (opts.backpressure !== undefined && opts.backpressure !== null) {
|
|
726
|
+
if (typeof opts.backpressure !== 'object') {
|
|
727
|
+
throw new QodoClientOptionsError('ClientOptions.backpressure must be an object (or omitted)');
|
|
728
|
+
}
|
|
729
|
+
const cap = opts.backpressure.maxPausedQueueSize;
|
|
730
|
+
if (cap !== undefined) {
|
|
731
|
+
if (typeof cap !== 'number' || !Number.isFinite(cap) || !Number.isInteger(cap) || cap < 1) {
|
|
732
|
+
throw new QodoClientOptionsError('ClientOptions.backpressure.maxPausedQueueSize must be a positive integer');
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
// Scheme + insecure-transport validation runs eagerly at construction
|
|
737
|
+
// so the docs claim ("Construction is synchronous and validates options
|
|
738
|
+
// eagerly — bad configuration throws `QodoClientOptionsError`
|
|
739
|
+
// immediately.") matches reality. `connect()` still calls `deriveWsUrl`
|
|
740
|
+
// to compute the actual WS URL, but the throwing edge moves to
|
|
741
|
+
// construction time. `deriveWsUrl` is pure; both args are validated
|
|
742
|
+
// immediately above, so the call is safe.
|
|
743
|
+
QodoClient.deriveWsUrl(opts.baseUrl, opts.allowInsecureTransport ?? false);
|
|
744
|
+
}
|
|
745
|
+
static buildAuthProvider(opts) {
|
|
746
|
+
if (opts.auth === 'env')
|
|
747
|
+
return new AuthProvider();
|
|
748
|
+
return new AuthProvider(opts.auth.apiKey);
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Map the consumer-supplied `baseUrl` (typically `https://qar.qodo.ai`) onto
|
|
752
|
+
* the WS endpoint. `https://` → `wss://`; existing `wss://` is left as-is.
|
|
753
|
+
* Trailing slashes on `baseUrl` are stripped before joining.
|
|
754
|
+
*
|
|
755
|
+
* Insecure schemes (`http://` / `ws://`) are refused unless
|
|
756
|
+
* `allowInsecureTransport` is `true`. Rationale: `connect()` always sends the
|
|
757
|
+
* bearer token in the upgrade `Authorization` header — over `ws://` that's
|
|
758
|
+
* plaintext on the wire. The opt-in keeps local-dev workflows possible
|
|
759
|
+
* without making credential leakage a default footgun.
|
|
760
|
+
*/
|
|
761
|
+
static deriveWsUrl(baseUrl, allowInsecureTransport) {
|
|
762
|
+
// Trim trailing slashes via a bounded character walk rather than the regex
|
|
763
|
+
// `/\/+$/.replace(...)`. CodeQL flags `\/+$` as a polynomial-redos pattern
|
|
764
|
+
// (js/polynomial-redos) — even though the actual time complexity is linear
|
|
765
|
+
// for this anchored single-character class, the engine's regex-pattern
|
|
766
|
+
// analyzer can't prove that. Walking the end of the string is both safer
|
|
767
|
+
// and cheaper.
|
|
768
|
+
let end = baseUrl.length;
|
|
769
|
+
while (end > 0 && baseUrl.charCodeAt(end - 1) === 0x2f /* '/' */) {
|
|
770
|
+
end -= 1;
|
|
771
|
+
}
|
|
772
|
+
const trimmed = baseUrl.slice(0, end);
|
|
773
|
+
let wsBase;
|
|
774
|
+
let insecure = false;
|
|
775
|
+
if (trimmed.startsWith('https://')) {
|
|
776
|
+
wsBase = `wss://${trimmed.slice('https://'.length)}`;
|
|
777
|
+
}
|
|
778
|
+
else if (trimmed.startsWith('http://')) {
|
|
779
|
+
wsBase = `ws://${trimmed.slice('http://'.length)}`;
|
|
780
|
+
insecure = true;
|
|
781
|
+
}
|
|
782
|
+
else if (trimmed.startsWith('wss://')) {
|
|
783
|
+
wsBase = trimmed;
|
|
784
|
+
}
|
|
785
|
+
else if (trimmed.startsWith('ws://')) {
|
|
786
|
+
wsBase = trimmed;
|
|
787
|
+
insecure = true;
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
throw new QodoClientOptionsError(`ClientOptions.baseUrl must use http(s):// or ws(s)://; got "${baseUrl}"`);
|
|
791
|
+
}
|
|
792
|
+
// `!== true` instead of `!value` — `validateOptions` already rejects
|
|
793
|
+
// non-boolean inputs, but keep the gate strict-equal so a future code
|
|
794
|
+
// path that bypasses validation can't slip a truthy non-boolean through.
|
|
795
|
+
if (insecure && allowInsecureTransport !== true) {
|
|
796
|
+
throw new QodoClientOptionsError(`ClientOptions.baseUrl uses an insecure scheme ("${baseUrl}") which would transmit ` +
|
|
797
|
+
`the bearer token in plaintext. Use https:// or wss:// in production, or set ` +
|
|
798
|
+
`allowInsecureTransport: true to opt in for local development.`);
|
|
799
|
+
}
|
|
800
|
+
return `${wsBase}/v2/qar/ws/connect`;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
//# sourceMappingURL=QodoClient.js.map
|