@qodo/sdk 0.13.3 → 2.0.0-next.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/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 +1115 -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 +800 -0
- package/dist/client/connection.d.ts.map +1 -0
- package/dist/client/connection.js +2020 -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 -104
- package/dist/api/agent.d.ts.map +0 -1
- package/dist/api/agent.js +0 -939
- 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,841 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `qodo-skills` MCP server implementation.
|
|
3
|
+
*
|
|
4
|
+
* Three tools, all `autoApproved: true`: `list_skills`, `get_skill`,
|
|
5
|
+
* `get_skill_file`. The server is a thin facade over a `SkillsManager`
|
|
6
|
+
* — the heavy lifting (catalog walk, parsing, validation, rendering) lives
|
|
7
|
+
* in the manager. The server owns:
|
|
8
|
+
*
|
|
9
|
+
* - Tool-routing (which handler runs for which `tool_name`).
|
|
10
|
+
* - In-memory caches keyed by `<fqn>` + `<fqn> + <rel-path>`.
|
|
11
|
+
* - Path validation for `get_skill_file` (see `path.ts`).
|
|
12
|
+
* - Telemetry emission via the manager's `forwardEvents` sink.
|
|
13
|
+
* - Structured error responses on the `isError: true` envelope.
|
|
14
|
+
*
|
|
15
|
+
* Integration: the SDK has no `InternalMCPBaseServer` interface. The
|
|
16
|
+
* integration shape is `McpInProcessHandler` from `QarRegistryClient`
|
|
17
|
+
* (`(req: { tool_name, arguments }) => Promise<...>`); the
|
|
18
|
+
* `QodoSkillsMcpServer` class is invoked via the {@link asMcpHandler}
|
|
19
|
+
* adapter. The SDK ships zero built-in MCPs by default — this server
|
|
20
|
+
* auto-registers via `client.qar.registerMcp('qodo-skills',
|
|
21
|
+
* { transport: 'sdk', handler })` when `ClientOptions.skills` is
|
|
22
|
+
* provided. Reach the registered config via
|
|
23
|
+
* `client.qar.getMcp('qodo-skills')`; the server instance itself is
|
|
24
|
+
* owned by `QodoClient`.
|
|
25
|
+
*
|
|
26
|
+
* Caches are cleared on {@link QodoSkillsMcpServer.dispose}.
|
|
27
|
+
*/
|
|
28
|
+
import { promises as fs, realpathSync as fsRealpathSync } from 'node:fs';
|
|
29
|
+
import { SKILL_FILE_HARD_BYTES } from '../types.js';
|
|
30
|
+
import { activationFailureMessage, capAgentField, lookupFromSnapshot, resolveActivationGraph, } from '../activation.js';
|
|
31
|
+
import { preprocessBody } from '../preprocess.js';
|
|
32
|
+
import { resolveSkillFilePath, SkillPathError } from './path.js';
|
|
33
|
+
import { parseArgv, substituteWithArgumentsTrailer } from '../substitute.js';
|
|
34
|
+
import { LIST_SKILLS_DEFAULT_LIMIT } from './types.js';
|
|
35
|
+
// 256 KB — mirrors the `SKILL_FILE_HARD_BYTES` cap on the SKILL.md side.
|
|
36
|
+
// Same number, deliberate: a supporting file cannot exceed what the skill
|
|
37
|
+
// itself can be, so the cap is a single constant the operator sees in both
|
|
38
|
+
// places.
|
|
39
|
+
const FILE_HARD_BYTES = SKILL_FILE_HARD_BYTES;
|
|
40
|
+
/**
|
|
41
|
+
* Extension → MIME map for `get_skill_file`. Anything not listed falls
|
|
42
|
+
* back to `application/octet-stream`; non-image binary returns render
|
|
43
|
+
* as a descriptive marker (`[binary file: N bytes, <mime>. Decode
|
|
44
|
+
* externally.]`), NOT raw base64.
|
|
45
|
+
*
|
|
46
|
+
* The text set covers what skill authors actually ship: markdown,
|
|
47
|
+
* source code, structured data. Images are a separate bucket so the
|
|
48
|
+
* MCP envelope can use the `image` content type.
|
|
49
|
+
*/
|
|
50
|
+
const TEXT_EXTENSIONS = new Map([
|
|
51
|
+
['.md', 'text/markdown'],
|
|
52
|
+
['.markdown', 'text/markdown'],
|
|
53
|
+
['.txt', 'text/plain'],
|
|
54
|
+
['.text', 'text/plain'],
|
|
55
|
+
['.json', 'application/json'],
|
|
56
|
+
['.yaml', 'application/yaml'],
|
|
57
|
+
['.yml', 'application/yaml'],
|
|
58
|
+
['.toml', 'application/toml'],
|
|
59
|
+
['.xml', 'application/xml'],
|
|
60
|
+
['.html', 'text/html'],
|
|
61
|
+
['.htm', 'text/html'],
|
|
62
|
+
['.css', 'text/css'],
|
|
63
|
+
['.js', 'text/javascript'],
|
|
64
|
+
['.mjs', 'text/javascript'],
|
|
65
|
+
['.cjs', 'text/javascript'],
|
|
66
|
+
['.ts', 'text/typescript'],
|
|
67
|
+
['.tsx', 'text/typescript'],
|
|
68
|
+
['.jsx', 'text/javascript'],
|
|
69
|
+
['.py', 'text/x-python'],
|
|
70
|
+
['.rb', 'text/x-ruby'],
|
|
71
|
+
['.sh', 'text/x-shellscript'],
|
|
72
|
+
['.bash', 'text/x-shellscript'],
|
|
73
|
+
['.zsh', 'text/x-shellscript'],
|
|
74
|
+
['.go', 'text/x-go'],
|
|
75
|
+
['.rs', 'text/x-rust'],
|
|
76
|
+
['.c', 'text/x-c'],
|
|
77
|
+
['.h', 'text/x-c'],
|
|
78
|
+
['.cpp', 'text/x-c++'],
|
|
79
|
+
['.hpp', 'text/x-c++'],
|
|
80
|
+
['.java', 'text/x-java'],
|
|
81
|
+
['.kt', 'text/x-kotlin'],
|
|
82
|
+
['.swift', 'text/x-swift'],
|
|
83
|
+
['.sql', 'application/sql'],
|
|
84
|
+
]);
|
|
85
|
+
const IMAGE_EXTENSIONS = new Map([
|
|
86
|
+
['.png', 'image/png'],
|
|
87
|
+
['.jpg', 'image/jpeg'],
|
|
88
|
+
['.jpeg', 'image/jpeg'],
|
|
89
|
+
['.gif', 'image/gif'],
|
|
90
|
+
['.webp', 'image/webp'],
|
|
91
|
+
['.bmp', 'image/bmp'],
|
|
92
|
+
['.svg', 'image/svg+xml'],
|
|
93
|
+
]);
|
|
94
|
+
/** The MCP tool names the server routes. */
|
|
95
|
+
export const QODO_SKILLS_TOOL_NAMES = ['list_skills', 'get_skill', 'get_skill_file'];
|
|
96
|
+
// Projected wire-side tool defs live in a platform-neutral module so
|
|
97
|
+
// the Node and browser builds source identical schemas. Re-exported
|
|
98
|
+
// here for compatibility with the original barrel-import shape.
|
|
99
|
+
export { qodoSkillsFunctionToolDefs } from './wireDefs.js';
|
|
100
|
+
/**
|
|
101
|
+
* Server class for the three `qodo-skills` MCP tools. Construct one per
|
|
102
|
+
* `QodoClient` instance; the SDK auto-wires it through
|
|
103
|
+
* {@link QodoClient.constructor} when `ClientOptions.skills` is configured.
|
|
104
|
+
*/
|
|
105
|
+
export class QodoSkillsMcpServer {
|
|
106
|
+
skills;
|
|
107
|
+
bodyCache = new Map();
|
|
108
|
+
fileCache = new Map();
|
|
109
|
+
/**
|
|
110
|
+
* Shared with `SkillsManager.internalActiveFqns` so caller-pin
|
|
111
|
+
* activation and LLM-driven activation surface in one place
|
|
112
|
+
* (`client.skills.getActiveSkills()` /
|
|
113
|
+
* `client.skillsMcpServer.loadedSkillFqns`). The MCP server still owns
|
|
114
|
+
* the body / file caches it manages, but it does NOT own the active
|
|
115
|
+
* set — the manager does.
|
|
116
|
+
*/
|
|
117
|
+
activeFqns;
|
|
118
|
+
emit;
|
|
119
|
+
/**
|
|
120
|
+
* Resolver for ambient substitution context. Wired in by `QodoClient` so
|
|
121
|
+
* each `get_skill` invocation sees the consumer's session ID, the active
|
|
122
|
+
* effort level, and the current `${QODO_SKILL_DIR}` (= the skill's own
|
|
123
|
+
* canonical path). When undefined, those envvar substitutions stay literal.
|
|
124
|
+
*/
|
|
125
|
+
resolveContext;
|
|
126
|
+
constructor(skills, opts) {
|
|
127
|
+
this.skills = skills;
|
|
128
|
+
this.emit = opts?.emit;
|
|
129
|
+
this.activeFqns = skills.internalActiveFqns;
|
|
130
|
+
this.resolveContext = opts?.resolveContext;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The set of skill FQNs whose body has been loaded into the current run.
|
|
134
|
+
* Surfaces for testing + for forward-looking trust-tier middleware that
|
|
135
|
+
* needs to know which skills' `allowed-tools` should be in scope.
|
|
136
|
+
*/
|
|
137
|
+
get loadedSkillFqns() {
|
|
138
|
+
return [...this.activeFqns];
|
|
139
|
+
}
|
|
140
|
+
/** Bytes currently held in the body cache. Useful for memory-pressure tests. */
|
|
141
|
+
get cachedBodyBytes() {
|
|
142
|
+
let total = 0;
|
|
143
|
+
for (const entry of this.bodyCache.values())
|
|
144
|
+
total += entry.bytes;
|
|
145
|
+
return total;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Drop the in-memory caches and active-skill set. Idempotent. Called by
|
|
149
|
+
* `QodoClient.disconnect()` so the next `connect()` starts cold.
|
|
150
|
+
*
|
|
151
|
+
* The active set is shared with `SkillsManager.internalActiveFqns`;
|
|
152
|
+
* clearing here implicitly clears the manager's surface too — both
|
|
153
|
+
* `client.skills.getActiveSkills()` and `client.skillsMcpServer.loadedSkillFqns`
|
|
154
|
+
* return empty after dispose.
|
|
155
|
+
*/
|
|
156
|
+
dispose() {
|
|
157
|
+
this.bodyCache.clear();
|
|
158
|
+
this.fileCache.clear();
|
|
159
|
+
this.activeFqns.clear();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Route a call by `tool_name` to the matching handler. Unknown names
|
|
163
|
+
* return an MCP error envelope. The handler signature matches the
|
|
164
|
+
* `McpInProcessHandler` contract so the same instance is registered via
|
|
165
|
+
* `client.qar.registerMcp(name, { transport: 'sdk', handler })`.
|
|
166
|
+
*/
|
|
167
|
+
async callTool(toolName, args) {
|
|
168
|
+
switch (toolName) {
|
|
169
|
+
case 'list_skills':
|
|
170
|
+
return this.handleListSkills(args);
|
|
171
|
+
case 'get_skill':
|
|
172
|
+
return this.handleGetSkill(args);
|
|
173
|
+
case 'get_skill_file':
|
|
174
|
+
return this.handleGetSkillFile(args);
|
|
175
|
+
default:
|
|
176
|
+
return errorEnvelope(`unknown tool: ${toolName}. Available: ${QODO_SKILLS_TOOL_NAMES.join(', ')}.`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------
|
|
180
|
+
// list_skills
|
|
181
|
+
// ---------------------------------------------------------------------
|
|
182
|
+
async handleListSkills(args) {
|
|
183
|
+
const includeAllVersions = args.includeAllVersions === true;
|
|
184
|
+
const limit = typeof args.limit === 'number' && Number.isFinite(args.limit) && args.limit > 0
|
|
185
|
+
? Math.floor(args.limit)
|
|
186
|
+
: LIST_SKILLS_DEFAULT_LIMIT;
|
|
187
|
+
const offset = typeof args.offset === 'number' && Number.isFinite(args.offset) && args.offset >= 0
|
|
188
|
+
? Math.floor(args.offset)
|
|
189
|
+
: 0;
|
|
190
|
+
const query = typeof args.query === 'string' && args.query.length > 0 ? args.query : undefined;
|
|
191
|
+
const all = await this.skills.list({ includeAllVersions });
|
|
192
|
+
const filtered = query !== undefined ? filterByQuery(all, query) : all;
|
|
193
|
+
const total = filtered.length;
|
|
194
|
+
const window = filtered.slice(offset, offset + limit);
|
|
195
|
+
const entries = window.map((skill) => toListEntry(skill));
|
|
196
|
+
const response = {
|
|
197
|
+
total,
|
|
198
|
+
shown: entries.length,
|
|
199
|
+
skills: entries,
|
|
200
|
+
truncated: offset + entries.length < total,
|
|
201
|
+
};
|
|
202
|
+
return successJsonEnvelope(response);
|
|
203
|
+
}
|
|
204
|
+
// ---------------------------------------------------------------------
|
|
205
|
+
// get_skill
|
|
206
|
+
// ---------------------------------------------------------------------
|
|
207
|
+
async handleGetSkill(args) {
|
|
208
|
+
if (typeof args.name !== 'string' || args.name.length === 0) {
|
|
209
|
+
return errorEnvelope('get_skill: `name` is required and must be a non-empty string');
|
|
210
|
+
}
|
|
211
|
+
const root = await this.skills.get(args.name);
|
|
212
|
+
if (root === null) {
|
|
213
|
+
this.emitTel({
|
|
214
|
+
kind: 'sdk.skill.invocation_denied',
|
|
215
|
+
skill: args.name,
|
|
216
|
+
reason: 'not_found',
|
|
217
|
+
});
|
|
218
|
+
return errorEnvelope(`Skill '${args.name}' not found in catalog. Use list_skills to discover available skills.`);
|
|
219
|
+
}
|
|
220
|
+
// `disable-model-invocation: true` is a gate, never overridden by
|
|
221
|
+
// LLM-driven activation. Caller-pin can override it (the SDK injects
|
|
222
|
+
// bodies eagerly in `TaskClient`); the model-driven path here cannot.
|
|
223
|
+
if (root.frontmatter['disable-model-invocation'] === true) {
|
|
224
|
+
this.emitTel({
|
|
225
|
+
kind: 'sdk.skill.invocation_denied',
|
|
226
|
+
skill: root.fqn,
|
|
227
|
+
reason: 'user_invocable_only',
|
|
228
|
+
});
|
|
229
|
+
return errorEnvelope(`Skill '${root.fqnNoVersion}' has disable-model-invocation: true. The user must invoke it directly.`);
|
|
230
|
+
}
|
|
231
|
+
// Third-party model-driven activation requires `trustedSources`
|
|
232
|
+
// opt-in. Caller-pin bypasses this gate (the SDK's `TaskClient` path
|
|
233
|
+
// handles that), but LLM-driven calls hit it.
|
|
234
|
+
if (!this.skills.isTrusted(root)) {
|
|
235
|
+
this.emitTel({
|
|
236
|
+
kind: 'sdk.skill.invocation_denied',
|
|
237
|
+
skill: root.fqn,
|
|
238
|
+
reason: 'third_party_without_trust',
|
|
239
|
+
});
|
|
240
|
+
return errorEnvelope(`Skill '${root.fqnNoVersion}' is third-party and its source is not in trustedSources. ` +
|
|
241
|
+
'Caller-pin the skill via `tasks.startWithAgent({ skills })` or add the source to ' +
|
|
242
|
+
'`SkillsConfig.trustedSources` to opt in.');
|
|
243
|
+
}
|
|
244
|
+
// Resolve the `requires:` chain with the depth / breadth / token
|
|
245
|
+
// caps applied + transitive trust gate. The shared activation
|
|
246
|
+
// pipeline emits structured failure events that the caller-pin path
|
|
247
|
+
// also uses.
|
|
248
|
+
const snapshot = await this.skills.discover();
|
|
249
|
+
const lookup = lookupFromSnapshot(snapshot.skills, this.skills);
|
|
250
|
+
const resolution = resolveActivationGraph(root, lookup);
|
|
251
|
+
if (resolution.outcome !== 'ok') {
|
|
252
|
+
// Emit the resolver-side structured event first so observers see
|
|
253
|
+
// exactly *why* the resolution failed, then the
|
|
254
|
+
// `invocation_denied` rollup keyed by reason.
|
|
255
|
+
this.emitResolverFailure(root, resolution);
|
|
256
|
+
const reason = mapResolverFailureToDeniedReason(resolution.outcome);
|
|
257
|
+
this.emitTel({
|
|
258
|
+
kind: 'sdk.skill.invocation_denied',
|
|
259
|
+
skill: root.fqn,
|
|
260
|
+
reason,
|
|
261
|
+
});
|
|
262
|
+
return errorEnvelope(activationFailureMessage(root, resolution));
|
|
263
|
+
}
|
|
264
|
+
// Argument substitution context. Args from the tool call
|
|
265
|
+
// apply only to the *root* skill (the LLM asks for `name` + `arguments`);
|
|
266
|
+
// transitive dependencies render with their own bodies untouched by the
|
|
267
|
+
// caller's args, but still honor envvar aliases.
|
|
268
|
+
const ambient = this.resolveContext !== undefined ? this.resolveContext() : {};
|
|
269
|
+
const rawArgs = normalizeArgumentsArg(args.arguments);
|
|
270
|
+
// Compose the body: deps first (so the parent body sees them), root last.
|
|
271
|
+
const texts = [];
|
|
272
|
+
for (const skill of resolution.graph.ordered) {
|
|
273
|
+
const cachedHit = this.bodyCache.has(skill.fqn);
|
|
274
|
+
if (!cachedHit) {
|
|
275
|
+
// Run `!command` preprocessing before caching. The cache
|
|
276
|
+
// key is the FQN — preprocessing is deterministic for a given
|
|
277
|
+
// (catalog snapshot + config) pair, so we cache the post-
|
|
278
|
+
// processed body verbatim. Operators wanting fresh executions
|
|
279
|
+
// each call can `dispose()` the server (clears the cache).
|
|
280
|
+
const preprocessed = await preprocessBody(skill.body, {
|
|
281
|
+
skill,
|
|
282
|
+
isTrusted: this.skills.isTrusted(skill),
|
|
283
|
+
env: process.env,
|
|
284
|
+
}, this.skills.preprocessingConfig);
|
|
285
|
+
if (preprocessed.events.length > 0) {
|
|
286
|
+
this.skills.forwardEvents(preprocessed.events);
|
|
287
|
+
}
|
|
288
|
+
const entry = {
|
|
289
|
+
body: preprocessed.body,
|
|
290
|
+
bytes: Buffer.byteLength(preprocessed.body, 'utf-8'),
|
|
291
|
+
argsHash: '',
|
|
292
|
+
};
|
|
293
|
+
this.bodyCache.set(skill.fqn, entry);
|
|
294
|
+
}
|
|
295
|
+
const cached = this.bodyCache.get(skill.fqn);
|
|
296
|
+
// Root-only argument application; dependencies render without args
|
|
297
|
+
// so a transitively-included skill body cannot consume the parent's
|
|
298
|
+
// caller-supplied args.
|
|
299
|
+
const isRoot = skill.fqn === resolution.graph.root.fqn;
|
|
300
|
+
const ctx = {
|
|
301
|
+
skill: skill.fqn,
|
|
302
|
+
...(isRoot && rawArgs !== undefined ? { argumentsText: rawArgs.text, argv: rawArgs.argv } : {}),
|
|
303
|
+
named: skill.frontmatter.arguments,
|
|
304
|
+
skillDir: skill.path,
|
|
305
|
+
...(ambient.sessionId !== undefined ? { sessionId: ambient.sessionId } : {}),
|
|
306
|
+
...(ambient.effort !== undefined ? { effort: ambient.effort } : {}),
|
|
307
|
+
};
|
|
308
|
+
const substituted = substituteWithArgumentsTrailer(cached.body, ctx);
|
|
309
|
+
this.emitSubstitutionWarnings(skill.fqn, substituted.warnings);
|
|
310
|
+
const header = `<!-- qodo-skill: ${skill.fqn} -->`;
|
|
311
|
+
texts.push(`${header}\n${substituted.text.trim()}`);
|
|
312
|
+
const newlyActive = !this.activeFqns.has(skill.fqn);
|
|
313
|
+
this.activeFqns.add(skill.fqn);
|
|
314
|
+
this.emitTel({
|
|
315
|
+
kind: 'sdk.skill.loaded',
|
|
316
|
+
skill: skill.fqn,
|
|
317
|
+
bytes: cached.bytes,
|
|
318
|
+
cached: cachedHit,
|
|
319
|
+
});
|
|
320
|
+
// Emit `sdk.skill.activated` once per fresh activation (not on
|
|
321
|
+
// cache hits). Forwarded through `forwardEvents` since the event
|
|
322
|
+
// kind isn't in the narrow `QodoSkillsMcpEvent` MCP alias.
|
|
323
|
+
if (newlyActive) {
|
|
324
|
+
this.skills.forwardEvents([
|
|
325
|
+
{
|
|
326
|
+
kind: 'sdk.skill.activated',
|
|
327
|
+
skill: skill.fqn,
|
|
328
|
+
source: 'llm',
|
|
329
|
+
tier: skill.trustTier,
|
|
330
|
+
},
|
|
331
|
+
]);
|
|
332
|
+
// Surface `allowed-tools` intent at LLM-driven activation time
|
|
333
|
+
// too. Trusted → applied; third-party → advisory (the trust
|
|
334
|
+
// gate above means we only reach here for trusted skills, so
|
|
335
|
+
// this is always `applied` in this branch — kept here so a
|
|
336
|
+
// future bypass mechanism inherits the right telemetry).
|
|
337
|
+
this.emitAllowedToolsEvents(skill);
|
|
338
|
+
// `context: fork` advisory hint. Same advisory wiring as the
|
|
339
|
+
// caller-pin path (`renderActiveSkillsBlock`), so the operator
|
|
340
|
+
// sees the same fork-declined surface regardless of how the
|
|
341
|
+
// skill was activated. SDK 2.0 has no multi-agent runtime; the
|
|
342
|
+
// body still loads inline.
|
|
343
|
+
if (skill.frontmatter.context === 'fork') {
|
|
344
|
+
this.skills.forwardEvents([
|
|
345
|
+
{
|
|
346
|
+
kind: 'sdk.skill.fork_declined',
|
|
347
|
+
skill: skill.fqn,
|
|
348
|
+
...(skill.frontmatter.agent !== undefined
|
|
349
|
+
? { agent: capAgentField(skill.frontmatter.agent) }
|
|
350
|
+
: {}),
|
|
351
|
+
reason: 'no_multi_agent',
|
|
352
|
+
},
|
|
353
|
+
]);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return successTextEnvelope(texts.join('\n\n'));
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Convert an activation-resolver failure into the matching telemetry
|
|
361
|
+
* event(s). Cycles + unresolved-dep failures piggyback on the existing
|
|
362
|
+
* `sdk.skill.error` channel; trust violations and cap breaches have
|
|
363
|
+
* dedicated event kinds.
|
|
364
|
+
*/
|
|
365
|
+
emitResolverFailure(root, failure) {
|
|
366
|
+
switch (failure.outcome) {
|
|
367
|
+
case 'requires_trust_violation':
|
|
368
|
+
this.skills.forwardEvents([
|
|
369
|
+
{
|
|
370
|
+
kind: 'sdk.skill.requires_trust_denied',
|
|
371
|
+
parent: root.fqn,
|
|
372
|
+
child: failure.child.fqn,
|
|
373
|
+
reason: failure.reason,
|
|
374
|
+
},
|
|
375
|
+
]);
|
|
376
|
+
return;
|
|
377
|
+
case 'requires_cap_exceeded':
|
|
378
|
+
this.skills.forwardEvents([
|
|
379
|
+
{
|
|
380
|
+
kind: 'sdk.skill.requires_cap_exceeded',
|
|
381
|
+
parent: root.fqn,
|
|
382
|
+
kind_breach: failure.kind,
|
|
383
|
+
limit: failure.limit,
|
|
384
|
+
actual: failure.actual,
|
|
385
|
+
},
|
|
386
|
+
]);
|
|
387
|
+
return;
|
|
388
|
+
case 'requires_cycle':
|
|
389
|
+
this.skills.forwardEvents([
|
|
390
|
+
{
|
|
391
|
+
kind: 'sdk.skill.error',
|
|
392
|
+
severity: 'error',
|
|
393
|
+
message: `requires: cycle detected at ${failure.fqn} (root ${root.fqn})`,
|
|
394
|
+
},
|
|
395
|
+
]);
|
|
396
|
+
return;
|
|
397
|
+
case 'requires_unresolved':
|
|
398
|
+
this.skills.forwardEvents([
|
|
399
|
+
{
|
|
400
|
+
kind: 'sdk.skill.error',
|
|
401
|
+
severity: 'error',
|
|
402
|
+
message: `requires: unresolved dependency ${failure.specifier} (root ${root.fqn})`,
|
|
403
|
+
},
|
|
404
|
+
]);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Emit the `allowed-tools` telemetry shape (`applied` for trusted,
|
|
410
|
+
* `advisory` for third-party). Same logic as the SDK's caller-pin
|
|
411
|
+
* activation path; kept in sync intentionally.
|
|
412
|
+
*/
|
|
413
|
+
emitAllowedToolsEvents(skill) {
|
|
414
|
+
const tools = skill.frontmatter['allowed-tools'];
|
|
415
|
+
if (tools === undefined || tools.length === 0)
|
|
416
|
+
return;
|
|
417
|
+
const tokens = tools.map((t) => (t.args !== undefined ? `${t.tool}(${t.args})` : t.tool));
|
|
418
|
+
this.skills.forwardEvents([
|
|
419
|
+
this.skills.isTrusted(skill)
|
|
420
|
+
? { kind: 'sdk.skill.allowed_tools_applied', skill: skill.fqn, tools: tokens }
|
|
421
|
+
: { kind: 'sdk.skill.allowed_tools_advisory', skill: skill.fqn, tools: tokens },
|
|
422
|
+
]);
|
|
423
|
+
}
|
|
424
|
+
// ---------------------------------------------------------------------
|
|
425
|
+
// get_skill_file
|
|
426
|
+
// ---------------------------------------------------------------------
|
|
427
|
+
async handleGetSkillFile(args) {
|
|
428
|
+
if (typeof args.name !== 'string' || args.name.length === 0) {
|
|
429
|
+
return errorEnvelope('get_skill_file: `name` is required and must be a non-empty string');
|
|
430
|
+
}
|
|
431
|
+
if (typeof args.path !== 'string' || args.path.length === 0) {
|
|
432
|
+
return errorEnvelope('get_skill_file: `path` is required and must be a non-empty string');
|
|
433
|
+
}
|
|
434
|
+
const skill = await this.skills.get(args.name);
|
|
435
|
+
if (skill === null) {
|
|
436
|
+
this.emitTel({
|
|
437
|
+
kind: 'sdk.skill.file_rejected',
|
|
438
|
+
skill: args.name,
|
|
439
|
+
path: args.path,
|
|
440
|
+
reason: 'not_found',
|
|
441
|
+
});
|
|
442
|
+
return errorEnvelope(`Skill '${args.name}' not found in catalog. Use list_skills to discover available skills.`);
|
|
443
|
+
}
|
|
444
|
+
let resolved;
|
|
445
|
+
try {
|
|
446
|
+
resolved = resolveSkillFilePath(skill.path, args.path);
|
|
447
|
+
}
|
|
448
|
+
catch (err) {
|
|
449
|
+
const reason = err instanceof SkillPathError ? err.reason : 'invalid_path';
|
|
450
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
451
|
+
this.emitTel({
|
|
452
|
+
kind: 'sdk.skill.file_rejected',
|
|
453
|
+
skill: skill.fqnNoVersion,
|
|
454
|
+
path: args.path,
|
|
455
|
+
reason,
|
|
456
|
+
});
|
|
457
|
+
return errorEnvelope(message);
|
|
458
|
+
}
|
|
459
|
+
// Disallow reading the skill's own manifest file via this tool — the
|
|
460
|
+
// slim-index + get_skill already cover that, and exposing the
|
|
461
|
+
// manifest would let a caller bypass the trust gate on body loading.
|
|
462
|
+
//
|
|
463
|
+
// Defence in depth: reject on EITHER of two checks (so a quirk in
|
|
464
|
+
// one cannot silently bypass the gate):
|
|
465
|
+
//
|
|
466
|
+
// 1. **Basename match against the known manifest names** — the
|
|
467
|
+
// walker accepts `SKILL.md` and `skill.md`. A user-supplied
|
|
468
|
+
// relative path resolving to either filename at the skill
|
|
469
|
+
// root is the manifest by construction. Match is
|
|
470
|
+
// case-insensitive at the basename level so on case-
|
|
471
|
+
// sensitive filesystems a request for `Skill.md` (typo / probe)
|
|
472
|
+
// still gets rejected with a clear reason rather than ENOENT.
|
|
473
|
+
// 2. **Canonical-path equality** with the walker-recorded
|
|
474
|
+
// `skill.skillFile` — covers symlinks that route to the
|
|
475
|
+
// manifest via a different relative path. On case-insensitive
|
|
476
|
+
// filesystems (macOS HFS+/APFS, Windows NTFS default) the two
|
|
477
|
+
// canonical strings may differ in casing yet point to the same
|
|
478
|
+
// inode; comparison is therefore also case-insensitive.
|
|
479
|
+
//
|
|
480
|
+
// (Defense against a workspace where a symlink or case-insensitive
|
|
481
|
+
// filesystem points a different relative path at the manifest.)
|
|
482
|
+
const KNOWN_MANIFEST_NAMES = ['skill.md'];
|
|
483
|
+
const relBasename = resolved.relative.includes('/')
|
|
484
|
+
? resolved.relative.slice(resolved.relative.lastIndexOf('/') + 1)
|
|
485
|
+
: resolved.relative;
|
|
486
|
+
const relDirIsRoot = !resolved.relative.includes('/');
|
|
487
|
+
const isManifestByName = relDirIsRoot && KNOWN_MANIFEST_NAMES.includes(relBasename.toLowerCase());
|
|
488
|
+
let canonManifest;
|
|
489
|
+
try {
|
|
490
|
+
canonManifest = fsRealpathSync(skill.skillFile);
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
canonManifest = '\0absent';
|
|
494
|
+
}
|
|
495
|
+
const isManifestByPath = resolved.absolute === canonManifest ||
|
|
496
|
+
resolved.absolute.toLowerCase() === canonManifest.toLowerCase();
|
|
497
|
+
if (isManifestByName || isManifestByPath) {
|
|
498
|
+
this.emitTel({
|
|
499
|
+
kind: 'sdk.skill.file_rejected',
|
|
500
|
+
skill: skill.fqnNoVersion,
|
|
501
|
+
path: args.path,
|
|
502
|
+
reason: 'invalid_path',
|
|
503
|
+
});
|
|
504
|
+
return errorEnvelope("get_skill_file cannot return the skill's manifest (SKILL.md / skill.md); use get_skill to load a skill body.");
|
|
505
|
+
}
|
|
506
|
+
const cacheKey = `${skill.fqn}|${resolved.relative}`;
|
|
507
|
+
const cached = this.fileCache.get(cacheKey);
|
|
508
|
+
if (cached !== undefined) {
|
|
509
|
+
this.emitTel({
|
|
510
|
+
kind: 'sdk.skill.file_loaded',
|
|
511
|
+
skill: skill.fqnNoVersion,
|
|
512
|
+
path: resolved.relative,
|
|
513
|
+
bytes: cached.content.byteLength,
|
|
514
|
+
cached: true,
|
|
515
|
+
});
|
|
516
|
+
return this.renderFileEnvelope(skill, cached);
|
|
517
|
+
}
|
|
518
|
+
let stat;
|
|
519
|
+
try {
|
|
520
|
+
stat = await fs.stat(resolved.absolute);
|
|
521
|
+
}
|
|
522
|
+
catch (err) {
|
|
523
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
524
|
+
this.emitTel({
|
|
525
|
+
kind: 'sdk.skill.file_rejected',
|
|
526
|
+
skill: skill.fqnNoVersion,
|
|
527
|
+
path: resolved.relative,
|
|
528
|
+
reason: 'not_found',
|
|
529
|
+
});
|
|
530
|
+
return errorEnvelope(`file not found in skill '${skill.fqnNoVersion}': ${msg}`);
|
|
531
|
+
}
|
|
532
|
+
if (!stat.isFile()) {
|
|
533
|
+
this.emitTel({
|
|
534
|
+
kind: 'sdk.skill.file_rejected',
|
|
535
|
+
skill: skill.fqnNoVersion,
|
|
536
|
+
path: resolved.relative,
|
|
537
|
+
reason: 'invalid_path',
|
|
538
|
+
});
|
|
539
|
+
return errorEnvelope(`path is not a regular file in skill '${skill.fqnNoVersion}'`);
|
|
540
|
+
}
|
|
541
|
+
if (stat.size > FILE_HARD_BYTES) {
|
|
542
|
+
this.emitTel({
|
|
543
|
+
kind: 'sdk.skill.file_rejected',
|
|
544
|
+
skill: skill.fqnNoVersion,
|
|
545
|
+
path: resolved.relative,
|
|
546
|
+
reason: 'too_large',
|
|
547
|
+
});
|
|
548
|
+
return errorEnvelope(`file size exceeds ${FILE_HARD_BYTES}-byte cap; consider splitting (${stat.size} bytes).`);
|
|
549
|
+
}
|
|
550
|
+
const data = await fs.readFile(resolved.absolute);
|
|
551
|
+
// Defensive: re-check after read; a file can grow between stat + read.
|
|
552
|
+
if (data.byteLength > FILE_HARD_BYTES) {
|
|
553
|
+
this.emitTel({
|
|
554
|
+
kind: 'sdk.skill.file_rejected',
|
|
555
|
+
skill: skill.fqnNoVersion,
|
|
556
|
+
path: resolved.relative,
|
|
557
|
+
reason: 'too_large',
|
|
558
|
+
});
|
|
559
|
+
return errorEnvelope(`file grew past ${FILE_HARD_BYTES}-byte cap during read (${data.byteLength} bytes).`);
|
|
560
|
+
}
|
|
561
|
+
const { mime, isText } = detectMime(resolved.relative);
|
|
562
|
+
const cachedEntry = { content: data, mime, isText };
|
|
563
|
+
this.fileCache.set(cacheKey, cachedEntry);
|
|
564
|
+
this.emitTel({
|
|
565
|
+
kind: 'sdk.skill.file_loaded',
|
|
566
|
+
skill: skill.fqnNoVersion,
|
|
567
|
+
path: resolved.relative,
|
|
568
|
+
bytes: data.byteLength,
|
|
569
|
+
cached: false,
|
|
570
|
+
});
|
|
571
|
+
return this.renderFileEnvelope(skill, cachedEntry);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Render the file envelope, applying substitutions to markdown / text
|
|
575
|
+
* content. Cache hits go through the same path so substitutions apply
|
|
576
|
+
* even on cached reads.
|
|
577
|
+
*/
|
|
578
|
+
renderFileEnvelope(skill, file) {
|
|
579
|
+
if (file.isText && file.mime === 'text/markdown') {
|
|
580
|
+
const ambient = this.resolveContext !== undefined ? this.resolveContext() : {};
|
|
581
|
+
const ctx = {
|
|
582
|
+
skill: skill.fqn,
|
|
583
|
+
named: skill.frontmatter.arguments,
|
|
584
|
+
skillDir: skill.path,
|
|
585
|
+
...(ambient.sessionId !== undefined ? { sessionId: ambient.sessionId } : {}),
|
|
586
|
+
...(ambient.effort !== undefined ? { effort: ambient.effort } : {}),
|
|
587
|
+
};
|
|
588
|
+
const text = file.content.toString('utf-8');
|
|
589
|
+
const substituted = substituteWithArgumentsTrailer(text, ctx);
|
|
590
|
+
this.emitSubstitutionWarnings(skill.fqn, substituted.warnings);
|
|
591
|
+
return {
|
|
592
|
+
content: [{ type: 'text', text: substituted.text }],
|
|
593
|
+
isError: false,
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
return fileResultEnvelope(file);
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Forward substitution warnings from `substitute(...)` through the
|
|
600
|
+
* manager's telemetry sink. Each `SubstitutionWarning` becomes one
|
|
601
|
+
* `sdk.skill.substitution_warn` event keyed to the skill that emitted it.
|
|
602
|
+
*/
|
|
603
|
+
emitSubstitutionWarnings(fqn, warnings) {
|
|
604
|
+
if (warnings.length === 0)
|
|
605
|
+
return;
|
|
606
|
+
this.skills.forwardEvents(warnings.map((w) => ({
|
|
607
|
+
kind: 'sdk.skill.substitution_warn',
|
|
608
|
+
skill: fqn,
|
|
609
|
+
reference: w.reference,
|
|
610
|
+
reason: w.reason,
|
|
611
|
+
})));
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Forward MCP-specific telemetry through the manager's sink. The base
|
|
615
|
+
* `SkillEvent` union doesn't include these MCP-only kinds; the
|
|
616
|
+
* manager's sink accepts a superset, so we cast through `unknown` at
|
|
617
|
+
* the boundary. Consumers reading `SkillEvent` discriminate by `kind`
|
|
618
|
+
* literal.
|
|
619
|
+
*/
|
|
620
|
+
emitTel(event) {
|
|
621
|
+
if (this.emit !== undefined) {
|
|
622
|
+
try {
|
|
623
|
+
this.emit(event);
|
|
624
|
+
}
|
|
625
|
+
catch {
|
|
626
|
+
// Telemetry sinks must never crash the MCP dispatch path.
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// Also forward to the SkillsManager's configured sink so the
|
|
630
|
+
// consumer sees one consistent event surface for the base + MCP
|
|
631
|
+
// event kinds.
|
|
632
|
+
this.skills.forwardEvents([event]);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
// ---------------------------------------------------------------------------
|
|
636
|
+
// McpInProcessHandler adapter
|
|
637
|
+
// ---------------------------------------------------------------------------
|
|
638
|
+
/**
|
|
639
|
+
* Adapt a {@link QodoSkillsMcpServer} to the {@link McpInProcessHandler}
|
|
640
|
+
* shape expected by `client.qar.registerMcp('qodo-skills', { transport:
|
|
641
|
+
* 'sdk', handler })`. The handler unwraps the wire `{ tool_name, arguments }`
|
|
642
|
+
* shape and delegates to {@link QodoSkillsMcpServer.callTool}.
|
|
643
|
+
*
|
|
644
|
+
* The returned value is the MCP envelope `{ content, isError? }`. QAR's
|
|
645
|
+
* agent loop reads `content[0].text` (or `content[0].data` for images) as
|
|
646
|
+
* the tool call's response payload.
|
|
647
|
+
*/
|
|
648
|
+
export function asMcpHandler(server) {
|
|
649
|
+
return async (req) => {
|
|
650
|
+
const result = await server.callTool(req.tool_name, req.arguments);
|
|
651
|
+
return result;
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
// ---------------------------------------------------------------------------
|
|
655
|
+
// Helpers
|
|
656
|
+
// ---------------------------------------------------------------------------
|
|
657
|
+
/**
|
|
658
|
+
* Normalize the LLM-supplied `arguments` argument into the
|
|
659
|
+
* `SubstitutionContext` shape. Accepts:
|
|
660
|
+
*
|
|
661
|
+
* - `string[]` — already shell-parsed (the documented contract). Joined
|
|
662
|
+
* with spaces to derive `argumentsText` for `$ARGUMENTS`.
|
|
663
|
+
* - `string` — bare text, parsed via {@link parseArgv} for indexed access.
|
|
664
|
+
*
|
|
665
|
+
* Returns `undefined` when the argument is missing or empty so the caller
|
|
666
|
+
* can omit the field from the context (rather than render an empty
|
|
667
|
+
* `ARGUMENTS:` trailer).
|
|
668
|
+
*/
|
|
669
|
+
function normalizeArgumentsArg(raw) {
|
|
670
|
+
if (raw === undefined || raw === null)
|
|
671
|
+
return undefined;
|
|
672
|
+
if (Array.isArray(raw)) {
|
|
673
|
+
const argv = raw.filter((s) => typeof s === 'string');
|
|
674
|
+
if (argv.length === 0)
|
|
675
|
+
return undefined;
|
|
676
|
+
return { text: argv.join(' '), argv };
|
|
677
|
+
}
|
|
678
|
+
if (typeof raw === 'string') {
|
|
679
|
+
if (raw.length === 0)
|
|
680
|
+
return undefined;
|
|
681
|
+
// Delegate to `parseArgv` from the substitute module so the parsing
|
|
682
|
+
// rules stay in one place.
|
|
683
|
+
return { text: raw, argv: parseArgv(raw) };
|
|
684
|
+
}
|
|
685
|
+
return undefined;
|
|
686
|
+
}
|
|
687
|
+
function filterByQuery(skills, q) {
|
|
688
|
+
const needle = q.toLowerCase();
|
|
689
|
+
return skills.filter((skill) => {
|
|
690
|
+
if (skill.name.toLowerCase().includes(needle))
|
|
691
|
+
return true;
|
|
692
|
+
if (skill.fqnNoVersion.toLowerCase().includes(needle))
|
|
693
|
+
return true;
|
|
694
|
+
const desc = (skill.frontmatter.description ?? '').toLowerCase();
|
|
695
|
+
if (desc.includes(needle))
|
|
696
|
+
return true;
|
|
697
|
+
const when = (skill.frontmatter.when_to_use ?? '').toLowerCase();
|
|
698
|
+
if (when.includes(needle))
|
|
699
|
+
return true;
|
|
700
|
+
return false;
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
function toListEntry(skill) {
|
|
704
|
+
const source = {
|
|
705
|
+
type: skill.source.type,
|
|
706
|
+
...(skill.source.type === 'project' || skill.source.type === 'user' || skill.source.type === 'config' || skill.source.type === 'bundled'
|
|
707
|
+
? skill.source.path !== undefined
|
|
708
|
+
? { path: skill.source.path }
|
|
709
|
+
: {}
|
|
710
|
+
: skill.source.type === 'package'
|
|
711
|
+
? { packageName: skill.source.packageName }
|
|
712
|
+
: {}),
|
|
713
|
+
};
|
|
714
|
+
const entry = {
|
|
715
|
+
fqn: skill.fqn,
|
|
716
|
+
name: skill.name,
|
|
717
|
+
vendor: skill.vendor,
|
|
718
|
+
version: skill.version,
|
|
719
|
+
description: truncateCombined(skill.frontmatter.description, skill.frontmatter.when_to_use)
|
|
720
|
+
.description,
|
|
721
|
+
...(skill.frontmatter.when_to_use !== undefined
|
|
722
|
+
? {
|
|
723
|
+
when_to_use: truncateCombined(skill.frontmatter.description, skill.frontmatter.when_to_use)
|
|
724
|
+
.when_to_use,
|
|
725
|
+
}
|
|
726
|
+
: {}),
|
|
727
|
+
tier: skill.trustTier,
|
|
728
|
+
source,
|
|
729
|
+
...(skill.frontmatter['disable-model-invocation'] === true ? { user_invocable_only: true } : {}),
|
|
730
|
+
...(skill.frontmatter.requires !== undefined && skill.frontmatter.requires.length > 0
|
|
731
|
+
? { requires: skill.frontmatter.requires }
|
|
732
|
+
: {}),
|
|
733
|
+
};
|
|
734
|
+
return entry;
|
|
735
|
+
}
|
|
736
|
+
/** Per-entry char cap on `description + when_to_use` (mirrors slim-index entry cap). */
|
|
737
|
+
const PER_ENTRY_CAP = 1536;
|
|
738
|
+
function truncateCombined(desc, when) {
|
|
739
|
+
const d = desc ?? '';
|
|
740
|
+
if (when === undefined) {
|
|
741
|
+
return {
|
|
742
|
+
description: d.length <= PER_ENTRY_CAP ? d : `${d.slice(0, PER_ENTRY_CAP - 1)}…`,
|
|
743
|
+
when_to_use: undefined,
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
const combinedLen = d.length + 1 + when.length;
|
|
747
|
+
if (combinedLen <= PER_ENTRY_CAP) {
|
|
748
|
+
return { description: d, when_to_use: when };
|
|
749
|
+
}
|
|
750
|
+
// Truncate when_to_use first; description is the load-bearing prose.
|
|
751
|
+
const remaining = Math.max(0, PER_ENTRY_CAP - d.length - 2);
|
|
752
|
+
if (remaining <= 0) {
|
|
753
|
+
return {
|
|
754
|
+
description: d.slice(0, PER_ENTRY_CAP - 1) + '…',
|
|
755
|
+
when_to_use: undefined,
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
return { description: d, when_to_use: `${when.slice(0, remaining)}…` };
|
|
759
|
+
}
|
|
760
|
+
function detectMime(relPath) {
|
|
761
|
+
const lower = relPath.toLowerCase();
|
|
762
|
+
const dotIndex = lower.lastIndexOf('.');
|
|
763
|
+
const ext = dotIndex >= 0 ? lower.slice(dotIndex) : '';
|
|
764
|
+
if (TEXT_EXTENSIONS.has(ext)) {
|
|
765
|
+
return { mime: TEXT_EXTENSIONS.get(ext), isText: true };
|
|
766
|
+
}
|
|
767
|
+
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
768
|
+
return { mime: IMAGE_EXTENSIONS.get(ext), isText: false };
|
|
769
|
+
}
|
|
770
|
+
return { mime: 'application/octet-stream', isText: false };
|
|
771
|
+
}
|
|
772
|
+
function successTextEnvelope(text) {
|
|
773
|
+
return {
|
|
774
|
+
content: [{ type: 'text', text }],
|
|
775
|
+
isError: false,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function successJsonEnvelope(value) {
|
|
779
|
+
return {
|
|
780
|
+
content: [{ type: 'text', text: JSON.stringify(value) }],
|
|
781
|
+
isError: false,
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
function errorEnvelope(message) {
|
|
785
|
+
return {
|
|
786
|
+
content: [{ type: 'text', text: message }],
|
|
787
|
+
isError: true,
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Map an activation-resolver failure variant onto the `invocation_denied`
|
|
792
|
+
* reason enum the MCP server emits via telemetry.
|
|
793
|
+
*/
|
|
794
|
+
function mapResolverFailureToDeniedReason(outcome) {
|
|
795
|
+
switch (outcome) {
|
|
796
|
+
case 'requires_trust_violation':
|
|
797
|
+
return 'requires_trust_violation';
|
|
798
|
+
case 'requires_cap_exceeded':
|
|
799
|
+
return 'requires_cap_exceeded';
|
|
800
|
+
case 'requires_cycle':
|
|
801
|
+
return 'requires_cycle';
|
|
802
|
+
case 'requires_unresolved':
|
|
803
|
+
return 'requires_unresolved';
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function fileResultEnvelope(file) {
|
|
807
|
+
if (file.isText) {
|
|
808
|
+
return {
|
|
809
|
+
content: [{ type: 'text', text: file.content.toString('utf-8') }],
|
|
810
|
+
isError: false,
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
if (file.mime.startsWith('image/')) {
|
|
814
|
+
return {
|
|
815
|
+
content: [
|
|
816
|
+
{
|
|
817
|
+
type: 'image',
|
|
818
|
+
data: file.content.toString('base64'),
|
|
819
|
+
mimeType: file.mime,
|
|
820
|
+
},
|
|
821
|
+
],
|
|
822
|
+
isError: false,
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
// Non-image binary files return a descriptive text marker, not
|
|
826
|
+
// the raw base64. Pumping arbitrary base64 into the model's conversation
|
|
827
|
+
// pollutes the context without adding signal: nothing reads multi-KB
|
|
828
|
+
// base64 from a tool result usefully, and the bytes count against the
|
|
829
|
+
// window. Authors who need binary access ship a script that decodes the
|
|
830
|
+
// file out-of-band.
|
|
831
|
+
return {
|
|
832
|
+
content: [
|
|
833
|
+
{
|
|
834
|
+
type: 'text',
|
|
835
|
+
text: `[binary file: ${file.content.byteLength} bytes, ${file.mime}. Decode externally.]`,
|
|
836
|
+
},
|
|
837
|
+
],
|
|
838
|
+
isError: false,
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
//# sourceMappingURL=server.js.map
|