@stigmer/runner 3.10.0 → 3.11.1-dev.20260812192248
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/README.md +14 -1
- package/dist/.build-fingerprint +1 -1
- package/dist/activities/call-llm.js +9 -10
- package/dist/activities/call-llm.js.map +1 -1
- package/dist/activities/classify-tool-approvals.d.ts +2 -1
- package/dist/activities/classify-tool-approvals.js +28 -2
- package/dist/activities/classify-tool-approvals.js.map +1 -1
- package/dist/activities/discover-mcp-server.d.ts +39 -0
- package/dist/activities/discover-mcp-server.js +165 -28
- package/dist/activities/discover-mcp-server.js.map +1 -1
- package/dist/activities/emit-event.d.ts +14 -2
- package/dist/activities/emit-event.js +52 -17
- package/dist/activities/emit-event.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +8 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +1 -1
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +28 -2
- package/dist/activities/execute-cursor/approval-state.js +7 -1
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/attachment-resolver.d.ts +14 -0
- package/dist/activities/execute-cursor/attachment-resolver.js +18 -4
- package/dist/activities/execute-cursor/attachment-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/blueprint-resolver.d.ts +1 -9
- package/dist/activities/execute-cursor/blueprint-resolver.js +6 -22
- package/dist/activities/execute-cursor/blueprint-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/env-resolver.js +3 -1
- package/dist/activities/execute-cursor/env-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/error-classifier.d.ts +59 -3
- package/dist/activities/execute-cursor/error-classifier.js +115 -6
- package/dist/activities/execute-cursor/error-classifier.js.map +1 -1
- package/dist/activities/execute-cursor/extract-structured-output.d.ts +29 -0
- package/dist/activities/execute-cursor/extract-structured-output.js +58 -0
- package/dist/activities/execute-cursor/extract-structured-output.js.map +1 -0
- package/dist/activities/execute-cursor/hook-script.d.ts +14 -3
- package/dist/activities/execute-cursor/hook-script.js +72 -10
- package/dist/activities/execute-cursor/hook-script.js.map +1 -1
- package/dist/activities/execute-cursor/index.d.ts +51 -11
- package/dist/activities/execute-cursor/index.js +177 -93
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/mcp-resolver.d.ts +24 -1
- package/dist/activities/execute-cursor/mcp-resolver.js +5 -2
- package/dist/activities/execute-cursor/mcp-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/model-pricing-data.d.ts +2 -0
- package/dist/activities/execute-cursor/model-pricing-data.js +13 -3
- package/dist/activities/execute-cursor/model-pricing-data.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +51 -4
- package/dist/activities/execute-cursor/prompt-builder.js +49 -7
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/turn-recovery.d.ts +52 -0
- package/dist/activities/execute-cursor/turn-recovery.js +193 -0
- package/dist/activities/execute-cursor/turn-recovery.js.map +1 -0
- package/dist/activities/execute-cursor/turn-stream.js +4 -1
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +18 -1
- package/dist/activities/execute-deep-agent/attachment-injector.js +68 -23
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
- package/dist/activities/execute-deep-agent/environment.js +3 -1
- package/dist/activities/execute-deep-agent/environment.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.js +15 -0
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +7 -7
- package/dist/activities/execute-deep-agent/prompt-builder.js +8 -2
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +10 -0
- package/dist/activities/execute-deep-agent/setup.js +65 -24
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/shell-env.d.ts +5 -1
- package/dist/activities/execute-deep-agent/shell-env.js +7 -9
- package/dist/activities/execute-deep-agent/shell-env.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +18 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.js +15 -2
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +27 -6
- package/dist/activities/execute-deep-agent/subagent-wiring.js +26 -5
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/hydrate-workflow-execution.js +8 -3
- package/dist/activities/hydrate-workflow-execution.js.map +1 -1
- package/dist/activities/run-command.d.ts +5 -2
- package/dist/activities/run-command.js +22 -10
- package/dist/activities/run-command.js.map +1 -1
- package/dist/activities/run-env.d.ts +40 -0
- package/dist/activities/run-env.js +66 -0
- package/dist/activities/run-env.js.map +1 -0
- package/dist/activities/workflow-event-activities.d.ts +28 -10
- package/dist/activities/workflow-event-activities.js +87 -58
- package/dist/activities/workflow-event-activities.js.map +1 -1
- package/dist/bootstrap.js +5 -0
- package/dist/bootstrap.js.map +1 -1
- package/dist/claimcheck/payload-codec.js +21 -1
- package/dist/claimcheck/payload-codec.js.map +1 -1
- package/dist/client/stigmer-client.d.ts +83 -21
- package/dist/client/stigmer-client.js +106 -29
- package/dist/client/stigmer-client.js.map +1 -1
- package/dist/encryption/config.d.ts +64 -0
- package/dist/encryption/config.js +108 -0
- package/dist/encryption/config.js.map +1 -0
- package/dist/encryption/index.d.ts +3 -0
- package/dist/encryption/index.js +3 -0
- package/dist/encryption/index.js.map +1 -0
- package/dist/encryption/payload-codec.d.ts +41 -0
- package/dist/encryption/payload-codec.js +130 -0
- package/dist/encryption/payload-codec.js.map +1 -0
- package/dist/middleware/index.d.ts +3 -0
- package/dist/middleware/index.js +7 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/path-normalization.d.ts +57 -0
- package/dist/middleware/path-normalization.js +109 -0
- package/dist/middleware/path-normalization.js.map +1 -0
- package/dist/middleware/types.d.ts +8 -0
- package/dist/payload-codecs.d.ts +17 -0
- package/dist/payload-codecs.js +42 -0
- package/dist/payload-codecs.js.map +1 -0
- package/dist/preflight.d.ts +31 -0
- package/dist/preflight.js +43 -0
- package/dist/preflight.js.map +1 -1
- package/dist/runner-manager.js +21 -17
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +11 -18
- package/dist/runner.js.map +1 -1
- package/dist/shared/approval-policy.d.ts +9 -3
- package/dist/shared/approval-policy.js +15 -6
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/artifact-storage.d.ts +23 -1
- package/dist/shared/artifact-storage.js +51 -10
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/attachment-naming.d.ts +53 -0
- package/dist/shared/attachment-naming.js +59 -0
- package/dist/shared/attachment-naming.js.map +1 -0
- package/dist/shared/caller-identity.d.ts +23 -2
- package/dist/shared/caller-identity.js +36 -5
- package/dist/shared/caller-identity.js.map +1 -1
- package/dist/shared/channel-attachment.js +1 -0
- package/dist/shared/channel-attachment.js.map +1 -1
- package/dist/shared/checkpointer/http-saver.d.ts +26 -1
- package/dist/shared/checkpointer/http-saver.js +54 -8
- package/dist/shared/checkpointer/http-saver.js.map +1 -1
- package/dist/shared/conversation-attachment.js +1 -0
- package/dist/shared/conversation-attachment.js.map +1 -1
- package/dist/shared/conversation-catchup.d.ts +9 -2
- package/dist/shared/conversation-catchup.js +39 -6
- package/dist/shared/conversation-catchup.js.map +1 -1
- package/dist/shared/datastore-attachment.d.ts +50 -7
- package/dist/shared/datastore-attachment.js +93 -11
- package/dist/shared/datastore-attachment.js.map +1 -1
- package/dist/shared/grpc-retry.d.ts +5 -1
- package/dist/shared/grpc-retry.js +5 -1
- package/dist/shared/grpc-retry.js.map +1 -1
- package/dist/shared/http-retry.d.ts +85 -0
- package/dist/shared/http-retry.js +101 -0
- package/dist/shared/http-retry.js.map +1 -0
- package/dist/shared/llm-backend.d.ts +275 -0
- package/dist/shared/llm-backend.js +425 -0
- package/dist/shared/llm-backend.js.map +1 -0
- package/dist/shared/llm-proxy.d.ts +8 -0
- package/dist/shared/llm-proxy.js +15 -0
- package/dist/shared/llm-proxy.js.map +1 -1
- package/dist/shared/mcp-enabled-tools.d.ts +57 -0
- package/dist/shared/mcp-enabled-tools.js +86 -0
- package/dist/shared/mcp-enabled-tools.js.map +1 -0
- package/dist/shared/mcp-manager.d.ts +11 -5
- package/dist/shared/mcp-manager.js +47 -8
- package/dist/shared/mcp-manager.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +39 -2
- package/dist/shared/mcp-resolver.js +38 -2
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/mcp-schema-sanitizer.d.ts +70 -0
- package/dist/shared/mcp-schema-sanitizer.js +197 -0
- package/dist/shared/mcp-schema-sanitizer.js.map +1 -0
- package/dist/shared/model-client.d.ts +18 -5
- package/dist/shared/model-client.js +149 -18
- package/dist/shared/model-client.js.map +1 -1
- package/dist/shared/model-error.js +198 -5
- package/dist/shared/model-error.js.map +1 -1
- package/dist/shared/model-pricing-data.d.ts +2 -0
- package/dist/shared/model-pricing-data.js +13 -3
- package/dist/shared/model-pricing-data.js.map +1 -1
- package/dist/shared/model-registry.js +3 -2
- package/dist/shared/model-registry.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +33 -0
- package/dist/shared/plan-mode-permissions.js +35 -0
- package/dist/shared/plan-mode-permissions.js.map +1 -0
- package/dist/shared/registry-endpoint.d.ts +20 -0
- package/dist/shared/registry-endpoint.js +25 -0
- package/dist/shared/registry-endpoint.js.map +1 -1
- package/dist/shared/runner-credential-keys.d.ts +24 -0
- package/dist/shared/runner-credential-keys.js +47 -0
- package/dist/shared/runner-credential-keys.js.map +1 -0
- package/dist/worker.d.ts +2 -1
- package/dist/worker.js +2 -4
- package/dist/worker.js.map +1 -1
- package/dist/workflow-engine/resolve.d.ts +19 -1
- package/dist/workflow-engine/resolve.js +37 -2
- package/dist/workflow-engine/resolve.js.map +1 -1
- package/dist/workflow-engine/types.d.ts +18 -0
- package/dist/workflow-engine/types.js.map +1 -1
- package/dist/workflows/call-agent-orchestrator.d.ts +9 -0
- package/dist/workflows/call-agent-orchestrator.js +1 -0
- package/dist/workflows/call-agent-orchestrator.js.map +1 -1
- package/dist/workflows/connect-mcp-server.js +9 -0
- package/dist/workflows/connect-mcp-server.js.map +1 -1
- package/dist/workflows/engine-core.js +23 -2
- package/dist/workflows/engine-core.js.map +1 -1
- package/dist/workflows/execute-from-execution.d.ts +1 -1
- package/dist/workflows/execute-from-execution.js +11 -1
- package/dist/workflows/execute-from-execution.js.map +1 -1
- package/dist/workflows/types.d.ts +8 -0
- package/package.json +9 -4
- package/src/__test-utils__/__tests__/vitest-global-setup.test.ts +37 -0
- package/src/__test-utils__/vitest-global-setup.ts +50 -0
- package/src/__tests__/bootstrap.test.ts +43 -0
- package/src/__tests__/claimcheck-codec.test.ts +36 -0
- package/src/__tests__/encryption-codec.test.ts +287 -0
- package/src/__tests__/fixtures/encrypted-payload-fixture.json +15 -0
- package/src/__tests__/history-encryption-e2e.test.ts +243 -0
- package/src/__tests__/preflight.test.ts +65 -2
- package/src/activities/__tests__/call-llm.test.ts +75 -0
- package/src/activities/__tests__/classify-tool-approvals.test.ts +117 -1
- package/src/activities/__tests__/discover-mcp-server.hang.test.ts +103 -0
- package/src/activities/__tests__/discover-mcp-server.test.ts +242 -1
- package/src/activities/__tests__/error-classifier.test.ts +94 -2
- package/src/activities/__tests__/run-command.test.ts +221 -0
- package/src/activities/__tests__/workflow-event-activities.test.ts +107 -8
- package/src/activities/call-llm.ts +9 -16
- package/src/activities/classify-tool-approvals.ts +34 -4
- package/src/activities/discover-mcp-server.ts +203 -31
- package/src/activities/emit-event.ts +65 -21
- package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +9 -0
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +14 -0
- package/src/activities/execute-cursor/__tests__/attachment-resolver.test.ts +53 -0
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +151 -16
- package/src/activities/execute-cursor/__tests__/error-classifier-extraction.test.ts +208 -0
- package/src/activities/execute-cursor/__tests__/extract-structured-output.test.ts +120 -0
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +93 -0
- package/src/activities/execute-cursor/__tests__/mcp-resolver.test.ts +125 -0
- package/src/activities/execute-cursor/__tests__/model-pricing.test.ts +62 -1
- package/src/activities/execute-cursor/__tests__/prompt-builder-delegation.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/turn-recovery.test.ts +160 -0
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +13 -0
- package/src/activities/execute-cursor/approval-state.ts +30 -1
- package/src/activities/execute-cursor/attachment-resolver.ts +31 -3
- package/src/activities/execute-cursor/blueprint-resolver.ts +7 -27
- package/src/activities/execute-cursor/env-resolver.ts +3 -1
- package/src/activities/execute-cursor/error-classifier.ts +131 -7
- package/src/activities/execute-cursor/extract-structured-output.ts +72 -0
- package/src/activities/execute-cursor/hook-script.ts +74 -10
- package/src/activities/execute-cursor/index.ts +209 -109
- package/src/activities/execute-cursor/mcp-resolver.ts +36 -2
- package/src/activities/execute-cursor/model-pricing-data.ts +22 -3
- package/src/activities/execute-cursor/prompt-builder.ts +85 -9
- package/src/activities/execute-cursor/turn-recovery.ts +208 -0
- package/src/activities/execute-cursor/turn-stream.ts +5 -2
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +110 -8
- package/src/activities/execute-deep-agent/__tests__/datastore-degradation.test.ts +104 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +2 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +174 -0
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +34 -5
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/shell-env.test.ts +24 -10
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +178 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +12 -7
- package/src/activities/execute-deep-agent/attachment-injector.ts +94 -30
- package/src/activities/execute-deep-agent/environment.ts +3 -1
- package/src/activities/execute-deep-agent/index.ts +20 -0
- package/src/activities/execute-deep-agent/prompt-builder.ts +20 -10
- package/src/activities/execute-deep-agent/setup.ts +85 -29
- package/src/activities/execute-deep-agent/shell-env.ts +8 -9
- package/src/activities/execute-deep-agent/subagent-transformer.ts +30 -2
- package/src/activities/execute-deep-agent/subagent-wiring.ts +39 -6
- package/src/activities/hydrate-workflow-execution.ts +8 -3
- package/src/activities/run-command.ts +25 -12
- package/src/activities/run-env.ts +79 -0
- package/src/activities/workflow-event-activities.ts +96 -69
- package/src/bootstrap.ts +5 -0
- package/src/claimcheck/payload-codec.ts +33 -1
- package/src/client/__tests__/stigmer-client.test.ts +110 -11
- package/src/client/stigmer-client.ts +150 -37
- package/src/encryption/config.ts +155 -0
- package/src/encryption/index.ts +3 -0
- package/src/encryption/payload-codec.ts +152 -0
- package/src/middleware/__tests__/path-normalization.test.ts +140 -0
- package/src/middleware/index.ts +8 -0
- package/src/middleware/path-normalization.ts +125 -0
- package/src/middleware/types.ts +11 -0
- package/src/payload-codecs.ts +62 -0
- package/src/preflight.ts +45 -0
- package/src/runner-manager.ts +26 -26
- package/src/runner.ts +12 -27
- package/src/shared/__tests__/approval-policy.test.ts +82 -39
- package/src/shared/__tests__/artifact-storage.test.ts +145 -2
- package/src/shared/__tests__/attachment-naming.test.ts +159 -0
- package/src/shared/__tests__/bedrock-adapter.test.ts +213 -0
- package/src/shared/__tests__/bedrock-seam.test.ts +390 -0
- package/src/shared/__tests__/caller-identity.test.ts +25 -0
- package/src/shared/__tests__/channel-attachment.test.ts +1 -1
- package/src/shared/__tests__/connect-backfill.test.ts +1 -0
- package/src/shared/__tests__/conversation-attachment.test.ts +1 -1
- package/src/shared/__tests__/conversation-catchup.test.ts +24 -0
- package/src/shared/__tests__/datastore-attachment.test.ts +129 -1
- package/src/shared/__tests__/foundry-adapter.test.ts +276 -0
- package/src/shared/__tests__/foundry-seam.test.ts +482 -0
- package/src/shared/__tests__/http-retry.test.ts +68 -0
- package/src/shared/__tests__/llm-backend.test.ts +616 -0
- package/src/shared/__tests__/mcp-enabled-tools.test.ts +86 -0
- package/src/shared/__tests__/mcp-manager.test.ts +137 -15
- package/src/shared/__tests__/mcp-resolver.test.ts +146 -3
- package/src/shared/__tests__/mcp-schema-sanitizer.test.ts +267 -0
- package/src/shared/__tests__/model-client.test.ts +200 -0
- package/src/shared/__tests__/model-error.test.ts +289 -1
- package/src/shared/__tests__/model-pricing.test.ts +62 -2
- package/src/shared/__tests__/model-registry.test.ts +22 -0
- package/src/shared/__tests__/synthesized-attachment.test.ts +1 -0
- package/src/shared/__tests__/vertex-adapter.test.ts +169 -0
- package/src/shared/__tests__/vertex-seam.test.ts +295 -0
- package/src/shared/approval-policy.ts +14 -7
- package/src/shared/artifact-storage.ts +75 -10
- package/src/shared/attachment-naming.ts +78 -0
- package/src/shared/caller-identity.ts +40 -5
- package/src/shared/channel-attachment.ts +1 -0
- package/src/shared/checkpointer/__tests__/http-saver.test.ts +196 -1
- package/src/shared/checkpointer/http-saver.ts +71 -8
- package/src/shared/conversation-attachment.ts +1 -0
- package/src/shared/conversation-catchup.ts +39 -6
- package/src/shared/datastore-attachment.ts +106 -11
- package/src/shared/grpc-retry.ts +5 -1
- package/src/shared/http-retry.ts +139 -0
- package/src/shared/llm-backend.ts +544 -0
- package/src/shared/llm-proxy.ts +15 -0
- package/src/shared/mcp-enabled-tools.ts +105 -0
- package/src/shared/mcp-manager.ts +56 -8
- package/src/shared/mcp-resolver.ts +73 -2
- package/src/shared/mcp-schema-sanitizer.ts +224 -0
- package/src/shared/model-client.ts +179 -19
- package/src/shared/model-error.ts +222 -4
- package/src/shared/model-pricing-data.ts +22 -3
- package/src/shared/model-registry.ts +7 -2
- package/src/shared/plan-mode-permissions.ts +37 -0
- package/src/shared/registry-endpoint.ts +27 -0
- package/src/shared/runner-credential-keys.ts +46 -0
- package/src/worker.ts +4 -5
- package/src/workflow-engine/__tests__/tasks/emit-event.test.ts +127 -49
- package/src/workflow-engine/resolve.ts +48 -2
- package/src/workflow-engine/types.ts +18 -0
- package/src/workflows/__tests__/connect-mcp-server.test.ts +25 -0
- package/src/workflows/__tests__/execute-serverless-workflow.test.ts +68 -2
- package/src/workflows/call-agent-orchestrator.ts +10 -0
- package/src/workflows/connect-mcp-server.ts +9 -0
- package/src/workflows/engine-core.ts +23 -2
- package/src/workflows/execute-from-execution.ts +12 -2
- package/src/workflows/types.ts +8 -0
- package/dist/activities/execute-cursor/mcp-config.d.ts +0 -30
- package/dist/activities/execute-cursor/mcp-config.js +0 -39
- package/dist/activities/execute-cursor/mcp-config.js.map +0 -1
- package/src/activities/execute-cursor/mcp-config.ts +0 -66
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
* Wraps @langchain/mcp-adapters MultiServerMCPClient with:
|
|
5
5
|
* - Conversion from ResolvedMcpServer[] to the SDK's Connection config
|
|
6
6
|
* - Proper async cleanup via close()
|
|
7
|
-
* -
|
|
7
|
+
* - Input-schema sanitization of unicode-invalid regex patterns
|
|
8
|
+
* (issue #420; semantics in shared/mcp-schema-sanitizer.ts) — a vendor
|
|
9
|
+
* pattern that cannot compile under the /u flag must not leave its tool
|
|
10
|
+
* permanently uncallable
|
|
11
|
+
* - Tool filtering by each server's effective enabled_tools allow-list
|
|
12
|
+
* (issue #350; semantics in shared/mcp-enabled-tools.ts) — the model only
|
|
13
|
+
* ever sees the tools the agent's manifest enables
|
|
8
14
|
*
|
|
9
15
|
* Transport policy (stdio is local-runner-only) is enforced upstream at
|
|
10
16
|
* resolution time by shared/mcp-transport-guard.ts — servers reaching
|
|
@@ -16,10 +22,10 @@
|
|
|
16
22
|
* (HOME, LOGNAME, PATH, SHELL, TERM, USER — getDefaultEnvironment in
|
|
17
23
|
* @modelcontextprotocol/sdk, merged under whatever we pass). The
|
|
18
24
|
* runner's own process env is never passed: it carries runner-internal
|
|
19
|
-
* credentials (
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
25
|
+
* credentials (enumerated in runner-credential-keys.ts) that no
|
|
26
|
+
* third-party MCP subprocess may see. A declared-empty env and an
|
|
27
|
+
* undeclared env are deliberately equivalent — both yield the SDK base
|
|
28
|
+
* environment.
|
|
23
29
|
*
|
|
24
30
|
* The Cursor execution path does NOT use this manager — it passes MCP
|
|
25
31
|
* configs directly to the Cursor SDK via toCursorMcpConfig(). This
|
|
@@ -32,6 +38,8 @@ import { MultiServerMCPClient } from "@langchain/mcp-adapters";
|
|
|
32
38
|
import type { Connection } from "@langchain/mcp-adapters";
|
|
33
39
|
import type { DynamicStructuredTool } from "@langchain/core/tools";
|
|
34
40
|
import type { ResolvedMcpServer } from "./mcp-resolver.js";
|
|
41
|
+
import { filterToolsByEnabledTools } from "./mcp-enabled-tools.js";
|
|
42
|
+
import { sanitizeSchemaPatterns } from "./mcp-schema-sanitizer.js";
|
|
35
43
|
|
|
36
44
|
/**
|
|
37
45
|
* Convert harness-agnostic ResolvedMcpServer[] into the
|
|
@@ -95,11 +103,51 @@ export async function connectMcpServers(
|
|
|
95
103
|
}
|
|
96
104
|
|
|
97
105
|
const client = new MultiServerMCPClient(connectionConfig);
|
|
98
|
-
const
|
|
106
|
+
const discoveredToolMap = await client.initializeConnections();
|
|
99
107
|
|
|
108
|
+
// Drop unicode-invalid regex patterns from every discovered tool's input
|
|
109
|
+
// schema BEFORE anything downstream holds a reference (issue #420):
|
|
110
|
+
// @langchain/core re-validates against tool.schema on every invocation,
|
|
111
|
+
// so one vendor pattern that cannot compile under the /u flag would
|
|
112
|
+
// otherwise make its tool permanently uncallable. Semantics and the
|
|
113
|
+
// loosen-never-tighten invariant live in shared/mcp-schema-sanitizer.ts.
|
|
114
|
+
for (const [slug, discovered] of Object.entries(discoveredToolMap)) {
|
|
115
|
+
for (const tool of discovered) {
|
|
116
|
+
const droppedPatterns = sanitizeSchemaPatterns(tool.schema);
|
|
117
|
+
if (droppedPatterns.length > 0) {
|
|
118
|
+
console.warn(
|
|
119
|
+
`[MCP] Server '${slug}' tool '${tool.name}': dropped ` +
|
|
120
|
+
`${droppedPatterns.length} regex pattern(s) that cannot compile ` +
|
|
121
|
+
`under the unicode flag — the tool stays callable, the server ` +
|
|
122
|
+
`still validates its own inputs (issue #420): ` +
|
|
123
|
+
droppedPatterns
|
|
124
|
+
.map((d) =>
|
|
125
|
+
`${d.location} ${JSON.stringify(d.pattern)}` +
|
|
126
|
+
(d.compilesWithoutUnicodeFlag ? "" : " (invalid without /u too)"),
|
|
127
|
+
)
|
|
128
|
+
.join(", "),
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Enforce each server's effective enabled_tools allow-list (issue #350)
|
|
135
|
+
// HERE, before anything downstream sees the tools: the parent tool list,
|
|
136
|
+
// the approval gate's toolServerMap, and the sub-agent McpAccess filter
|
|
137
|
+
// (whose subset-of-parent check is only real against a narrowed map) all
|
|
138
|
+
// derive from this result. Servers without a restriction (enabledTools
|
|
139
|
+
// absent — including synthesized attachments) pass through untouched.
|
|
140
|
+
const enabledBySlug = new Map(
|
|
141
|
+
servers.map((s) => [s.slug, s.enabledTools]),
|
|
142
|
+
);
|
|
143
|
+
const serverToolMap: Record<string, DynamicStructuredTool[]> = {};
|
|
100
144
|
const tools: DynamicStructuredTool[] = [];
|
|
101
|
-
for (const
|
|
102
|
-
|
|
145
|
+
for (const [slug, discovered] of Object.entries(discoveredToolMap)) {
|
|
146
|
+
const filtered = filterToolsByEnabledTools(
|
|
147
|
+
slug, discovered, enabledBySlug.get(slug),
|
|
148
|
+
);
|
|
149
|
+
serverToolMap[slug] = filtered;
|
|
150
|
+
tools.push(...filtered);
|
|
103
151
|
}
|
|
104
152
|
|
|
105
153
|
console.log(
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* there until the two are consolidated.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type { McpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
14
|
+
import type { McpServerUsage, ToolApprovalOverride } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
15
15
|
import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
16
16
|
import type { ToolApprovalPolicy } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
|
|
17
17
|
import type { StigmerClient } from "../client/stigmer-client.js";
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
filterEnvToDeclaredKeys,
|
|
27
27
|
PlaceholderResolutionError,
|
|
28
28
|
} from "./placeholder-resolver.js";
|
|
29
|
+
import { effectiveEnabledTools } from "./mcp-enabled-tools.js";
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Harness-agnostic intermediate representation of a resolved MCP server.
|
|
@@ -45,6 +46,28 @@ export interface ResolvedMcpServer {
|
|
|
45
46
|
toolApprovals: ToolApprovalPolicy[];
|
|
46
47
|
pinnedToolApprovals: ToolApprovalPolicy[];
|
|
47
48
|
discoveredCapabilitiesEmpty: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* The EFFECTIVE tool allow-list for this server (issue #350): the usage's
|
|
51
|
+
* enabled_tools, falling back to the server's default_enabled_tools when
|
|
52
|
+
* the usage's list is empty (see shared/mcp-enabled-tools.ts). Absent when
|
|
53
|
+
* unrestricted — which keeps synthesized attachment servers (built without
|
|
54
|
+
* a usage) and the discovery path unfiltered by construction. Enforced at
|
|
55
|
+
* connect time by connectMcpServers (shared/mcp-manager.ts).
|
|
56
|
+
*/
|
|
57
|
+
enabledTools?: string[];
|
|
58
|
+
/**
|
|
59
|
+
* Layer-3 per-agent approval overrides from the usage that resolved this
|
|
60
|
+
* server (issue #349): riding the resolved server is what SCOPES an
|
|
61
|
+
* override to its own server — a flat cross-server list is how an
|
|
62
|
+
* override once leaked onto (or silently un-gated) a same-named tool on
|
|
63
|
+
* another server. Deliberately REQUIRED, not optional: empty means "no
|
|
64
|
+
* overrides", and every construction site — including the near-duplicate
|
|
65
|
+
* Cursor resolver and the synthesized attachments, which have no usage
|
|
66
|
+
* and therefore no layer 3 — must say so explicitly, so a forgotten
|
|
67
|
+
* mirror cannot compile. Consumed by mergeApprovalPolicies
|
|
68
|
+
* (shared/approval-policy.ts).
|
|
69
|
+
*/
|
|
70
|
+
toolApprovalOverrides: ToolApprovalOverride[];
|
|
48
71
|
}
|
|
49
72
|
|
|
50
73
|
export interface McpResolutionResult {
|
|
@@ -78,7 +101,13 @@ export async function resolveMcpServers(
|
|
|
78
101
|
envVars,
|
|
79
102
|
ref.slug,
|
|
80
103
|
);
|
|
81
|
-
const server = mcpServerToResolved(
|
|
104
|
+
const server = mcpServerToResolved(
|
|
105
|
+
mcpServer,
|
|
106
|
+
ref.slug,
|
|
107
|
+
serverEnv,
|
|
108
|
+
usage.enabledTools,
|
|
109
|
+
usage.toolApprovalOverrides ?? [],
|
|
110
|
+
);
|
|
82
111
|
if (server) {
|
|
83
112
|
assertTransportAllowed(server.slug, server.connectionType, transportPosture);
|
|
84
113
|
resolved.push(server);
|
|
@@ -108,6 +137,8 @@ export function mcpServerToResolved(
|
|
|
108
137
|
server: McpServer,
|
|
109
138
|
slug: string,
|
|
110
139
|
envVars: Record<string, string>,
|
|
140
|
+
usageEnabledTools?: readonly string[],
|
|
141
|
+
usageToolApprovalOverrides: ToolApprovalOverride[] = [],
|
|
111
142
|
): ResolvedMcpServer | null {
|
|
112
143
|
const spec = server.spec;
|
|
113
144
|
if (!spec) return null;
|
|
@@ -123,6 +154,13 @@ export function mcpServerToResolved(
|
|
|
123
154
|
toolApprovals,
|
|
124
155
|
pinnedToolApprovals,
|
|
125
156
|
discoveredCapabilitiesEmpty,
|
|
157
|
+
// Callers without a usage (the discovery activity) pass nothing, so the
|
|
158
|
+
// default_enabled_tools fallback still applies but a per-agent
|
|
159
|
+
// restriction cannot: discovery must see the server's full toolset.
|
|
160
|
+
enabledTools: effectiveEnabledTools(usageEnabledTools, spec.defaultEnabledTools),
|
|
161
|
+
// Same no-usage rule for layer 3: discovery has no agent context, so no
|
|
162
|
+
// per-agent overrides exist — defaulting to [] keeps that structural.
|
|
163
|
+
toolApprovalOverrides: usageToolApprovalOverrides,
|
|
126
164
|
};
|
|
127
165
|
|
|
128
166
|
switch (spec.serverType.case) {
|
|
@@ -170,4 +208,37 @@ export function extractMcpServerSlugs(usages: McpServerUsage[]): string[] {
|
|
|
170
208
|
.filter((s): s is string => !!s);
|
|
171
209
|
}
|
|
172
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Merge MCP server usages from agent (base) and session (overlay).
|
|
213
|
+
*
|
|
214
|
+
* Replicates session_context_merge.py::merge_mcp_server_usages():
|
|
215
|
+
* - Agent-level usages are the base set
|
|
216
|
+
* - Session-level usages extend or override by mcp_server_ref.slug
|
|
217
|
+
* - If both reference the same slug, session-level takes precedence —
|
|
218
|
+
* the WHOLE usage, including enabled_tools and approval overrides
|
|
219
|
+
*
|
|
220
|
+
* Shared by both harnesses (blueprint-resolver.ts for Cursor,
|
|
221
|
+
* execute-deep-agent/setup.ts for the native harness) so a duplicate slug
|
|
222
|
+
* resolves identically everywhere: exactly one usage per server, whose
|
|
223
|
+
* enabled_tools is the one the enforcement filter honors.
|
|
224
|
+
*/
|
|
225
|
+
export function mergeMcpServerUsages(
|
|
226
|
+
agentUsages: McpServerUsage[],
|
|
227
|
+
sessionUsages: McpServerUsage[],
|
|
228
|
+
): McpServerUsage[] {
|
|
229
|
+
const bySlug = new Map<string, McpServerUsage>();
|
|
230
|
+
|
|
231
|
+
for (const usage of agentUsages) {
|
|
232
|
+
const slug = usage.mcpServerRef?.slug;
|
|
233
|
+
if (slug) bySlug.set(slug, usage);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
for (const usage of sessionUsages) {
|
|
237
|
+
const slug = usage.mcpServerRef?.slug;
|
|
238
|
+
if (slug) bySlug.set(slug, usage);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return [...bySlug.values()];
|
|
242
|
+
}
|
|
243
|
+
|
|
173
244
|
export { PlaceholderResolutionError } from "./placeholder-resolver.js";
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unicode-flag regex sanitization for MCP tool input schemas (issue #420).
|
|
3
|
+
*
|
|
4
|
+
* Why this exists: real-world MCP servers ship JSON-schema `pattern` values
|
|
5
|
+
* that are legal as plain ECMAScript regexes but invalid under the unicode
|
|
6
|
+
* flag (PayPal's `^https\:\/\/` — `\:` is an invalid escape under /u).
|
|
7
|
+
* @langchain/core validates tool input on EVERY call with
|
|
8
|
+
* @cfworker/json-schema, which compiles patterns via `new RegExp(p, "u")`
|
|
9
|
+
* at exactly two uncaught sites: the `pattern` keyword and each
|
|
10
|
+
* `patternProperties` key. One bad vendor pattern therefore makes the tool
|
|
11
|
+
* permanently uncallable on the deep-agent path — every invocation dies
|
|
12
|
+
* with a cryptic SyntaxError before the tool is ever reached. (The third
|
|
13
|
+
* /u compile site, `format: "regex"`, validates instance values inside a
|
|
14
|
+
* try/catch and fails gracefully — not a crash surface.)
|
|
15
|
+
*
|
|
16
|
+
* The fix: at the deep-agent connect funnel (mcp-manager.ts
|
|
17
|
+
* connectMcpServers), drop every pattern that cannot compile under /u.
|
|
18
|
+
* Dropping is deliberate — rewriting to a /u-safe equivalent would need an
|
|
19
|
+
* Annex-B-aware regex transpiler, disproportionate machinery for what is
|
|
20
|
+
* best-effort client-side validation; the MCP server still validates its
|
|
21
|
+
* own inputs server-side. This mirrors the loosening posture of
|
|
22
|
+
* @langchain/mcp-adapters' own schema pipeline (dereferenceJsonSchema →
|
|
23
|
+
* simplifyJsonSchemaForLLM), which already normalizes schemas for this
|
|
24
|
+
* exact validator.
|
|
25
|
+
*
|
|
26
|
+
* THE INVARIANT: sanitization may only ever LOOSEN validation, never
|
|
27
|
+
* tighten it. Dropping a `patternProperties` entry naively would violate
|
|
28
|
+
* this — @cfworker marks pattern-matched keys as "evaluated" and routes
|
|
29
|
+
* unevaluated keys into the `additionalProperties` / `unevaluatedProperties`
|
|
30
|
+
* checks, so under `additionalProperties: false` the drop would flip a
|
|
31
|
+
* crash into a false REJECTION of valid inputs. Whenever a
|
|
32
|
+
* `patternProperties` entry is dropped, any restrictive
|
|
33
|
+
* `additionalProperties` / `unevaluatedProperties` at that schema level is
|
|
34
|
+
* therefore relaxed too.
|
|
35
|
+
*
|
|
36
|
+
* Scope: this sanitizer serves the EXECUTION path only. Discovery
|
|
37
|
+
* (activities/discover-mcp-server.ts) persists tool schemas verbatim from
|
|
38
|
+
* listTools — deliberately: the stored schema is the vendor's truth for
|
|
39
|
+
* display, and discovery never invokes tools, so it cannot hit the crash.
|
|
40
|
+
* Do not "extend" sanitization there.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** One dropped regex constraint, for the caller's log line. */
|
|
44
|
+
export interface DroppedPattern {
|
|
45
|
+
/** JSON-pointer-style path of the dropped constraint within the schema. */
|
|
46
|
+
location: string;
|
|
47
|
+
/** The pattern source that failed to compile under the unicode flag. */
|
|
48
|
+
pattern: string;
|
|
49
|
+
/**
|
|
50
|
+
* True when the pattern compiles WITHOUT the /u flag — vendor sloppiness
|
|
51
|
+
* (Annex B legacy syntax), the oss#420 class. False means the regex is
|
|
52
|
+
* broken outright; either way validation could only crash, so both drop.
|
|
53
|
+
*/
|
|
54
|
+
compilesWithoutUnicodeFlag: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Keywords whose value is a single subschema. */
|
|
58
|
+
const SINGLE_SCHEMA_KEYWORDS = [
|
|
59
|
+
"additionalProperties",
|
|
60
|
+
"unevaluatedProperties",
|
|
61
|
+
"propertyNames",
|
|
62
|
+
"items",
|
|
63
|
+
"additionalItems",
|
|
64
|
+
"unevaluatedItems",
|
|
65
|
+
"contains",
|
|
66
|
+
"not",
|
|
67
|
+
"if",
|
|
68
|
+
"then",
|
|
69
|
+
"else",
|
|
70
|
+
] as const;
|
|
71
|
+
|
|
72
|
+
/** Keywords whose value is an array of subschemas. */
|
|
73
|
+
const SCHEMA_ARRAY_KEYWORDS = ["anyOf", "allOf", "oneOf", "prefixItems"] as const;
|
|
74
|
+
|
|
75
|
+
/** Keywords whose value is an object mapping names to subschemas. */
|
|
76
|
+
const SCHEMA_MAP_KEYWORDS = [
|
|
77
|
+
"properties",
|
|
78
|
+
"patternProperties",
|
|
79
|
+
"dependentSchemas",
|
|
80
|
+
"$defs",
|
|
81
|
+
"definitions",
|
|
82
|
+
] as const;
|
|
83
|
+
|
|
84
|
+
function compilesUnderUnicodeFlag(pattern: string): boolean {
|
|
85
|
+
try {
|
|
86
|
+
new RegExp(pattern, "u");
|
|
87
|
+
return true;
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function compilesWithoutUnicodeFlag(pattern: string): boolean {
|
|
94
|
+
try {
|
|
95
|
+
new RegExp(pattern);
|
|
96
|
+
return true;
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
103
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** JSON-pointer token escaping (RFC 6901): `~` → `~0`, `/` → `~1`. */
|
|
107
|
+
function pointerToken(token: string): string {
|
|
108
|
+
return token.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Drop unicode-invalid regex patterns from a JSON schema, in place.
|
|
113
|
+
*
|
|
114
|
+
* Walks only schema positions (the recursion set is @cfworker's own
|
|
115
|
+
* validated-keyword list), so a property literally NAMED "pattern" under
|
|
116
|
+
* `properties` is never touched. The walker handles composition keywords
|
|
117
|
+
* (anyOf/allOf/oneOf/not/if-then-else) even though the adapter's
|
|
118
|
+
* simplifyJsonSchemaForLLM currently strips them, and carries a visited-set
|
|
119
|
+
* cycle guard even though the adapter's $ref inlining currently guarantees
|
|
120
|
+
* an acyclic result — correctness here must not depend on another
|
|
121
|
+
* package's internals holding across dependency bumps.
|
|
122
|
+
*
|
|
123
|
+
* Returns the dropped constraints (empty for clean schemas — the common
|
|
124
|
+
* case, which this walk leaves byte-identical).
|
|
125
|
+
*/
|
|
126
|
+
export function sanitizeSchemaPatterns(schema: unknown): DroppedPattern[] {
|
|
127
|
+
const dropped: DroppedPattern[] = [];
|
|
128
|
+
if (!isPlainObject(schema)) return dropped;
|
|
129
|
+
walkSchema(schema, "", dropped, new Set());
|
|
130
|
+
return dropped;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function recordDrop(dropped: DroppedPattern[], location: string, pattern: string): void {
|
|
134
|
+
dropped.push({
|
|
135
|
+
location,
|
|
136
|
+
pattern,
|
|
137
|
+
compilesWithoutUnicodeFlag: compilesWithoutUnicodeFlag(pattern),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function walkSchema(
|
|
142
|
+
node: Record<string, unknown>,
|
|
143
|
+
path: string,
|
|
144
|
+
dropped: DroppedPattern[],
|
|
145
|
+
seen: Set<object>,
|
|
146
|
+
): void {
|
|
147
|
+
if (seen.has(node)) return;
|
|
148
|
+
seen.add(node);
|
|
149
|
+
|
|
150
|
+
if (typeof node.pattern === "string" && !compilesUnderUnicodeFlag(node.pattern)) {
|
|
151
|
+
recordDrop(dropped, `${path}/pattern`, node.pattern);
|
|
152
|
+
delete node.pattern;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (isPlainObject(node.patternProperties)) {
|
|
156
|
+
const patternProperties = node.patternProperties;
|
|
157
|
+
let droppedEntry = false;
|
|
158
|
+
for (const key of Object.keys(patternProperties)) {
|
|
159
|
+
if (compilesUnderUnicodeFlag(key)) continue;
|
|
160
|
+
recordDrop(dropped, `${path}/patternProperties/${pointerToken(key)}`, key);
|
|
161
|
+
delete patternProperties[key];
|
|
162
|
+
droppedEntry = true;
|
|
163
|
+
}
|
|
164
|
+
if (droppedEntry) {
|
|
165
|
+
// Never-tighten: keys the dropped pattern used to match would now
|
|
166
|
+
// fall through to these checks and could be falsely rejected.
|
|
167
|
+
if (node.additionalProperties !== undefined && node.additionalProperties !== true) {
|
|
168
|
+
delete node.additionalProperties;
|
|
169
|
+
}
|
|
170
|
+
if (node.unevaluatedProperties !== undefined && node.unevaluatedProperties !== true) {
|
|
171
|
+
delete node.unevaluatedProperties;
|
|
172
|
+
}
|
|
173
|
+
if (Object.keys(patternProperties).length === 0) {
|
|
174
|
+
delete node.patternProperties;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const keyword of SINGLE_SCHEMA_KEYWORDS) {
|
|
180
|
+
const value = node[keyword];
|
|
181
|
+
if (isPlainObject(value)) {
|
|
182
|
+
walkSchema(value, `${path}/${keyword}`, dropped, seen);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
for (const keyword of SCHEMA_ARRAY_KEYWORDS) {
|
|
187
|
+
const value = node[keyword];
|
|
188
|
+
if (!Array.isArray(value)) continue;
|
|
189
|
+
value.forEach((entry, index) => {
|
|
190
|
+
if (isPlainObject(entry)) {
|
|
191
|
+
walkSchema(entry, `${path}/${keyword}/${index}`, dropped, seen);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
for (const keyword of SCHEMA_MAP_KEYWORDS) {
|
|
197
|
+
const value = node[keyword];
|
|
198
|
+
if (!isPlainObject(value)) continue;
|
|
199
|
+
for (const [name, entry] of Object.entries(value)) {
|
|
200
|
+
if (isPlainObject(entry)) {
|
|
201
|
+
walkSchema(entry, `${path}/${keyword}/${pointerToken(name)}`, dropped, seen);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Draft-07 `items` tuple form and `dependencies` schema form — both
|
|
207
|
+
// keywords are dual-shaped, so the typed loops above miss these arms.
|
|
208
|
+
if (Array.isArray(node.items)) {
|
|
209
|
+
node.items.forEach((entry, index) => {
|
|
210
|
+
if (isPlainObject(entry)) {
|
|
211
|
+
walkSchema(entry, `${path}/items/${index}`, dropped, seen);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (isPlainObject(node.dependencies)) {
|
|
216
|
+
for (const [name, entry] of Object.entries(node.dependencies)) {
|
|
217
|
+
// Array-valued entries are dependentRequired (property names, not
|
|
218
|
+
// schemas) — only schema-valued entries are walked.
|
|
219
|
+
if (isPlainObject(entry)) {
|
|
220
|
+
walkSchema(entry, `${path}/dependencies/${pointerToken(name)}`, dropped, seen);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|