@aiwg/cli 2026.10.1 → 2026.10.4
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 +2 -2
- package/agentic/code/providers/capability-matrix.yaml +270 -0
- package/agentic/code/providers/model-capabilities.v1.json +3183 -24
- package/bin/aiwg.mjs +135 -47
- package/dist/src/a2a/codecs.js +9 -0
- package/dist/src/agents/grounding/knowledge-base.js +54 -6
- package/dist/src/artifacts/browser-export.js +6 -0
- package/dist/src/artifacts/checksum-manifest.js +1 -0
- package/dist/src/artifacts/citation-parser.js +173 -92
- package/dist/src/artifacts/citation-table-schema.js +59 -0
- package/dist/src/artifacts/cli.js +57 -18
- package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
- package/dist/src/artifacts/corpus-tools/vision-extract.js +107 -15
- package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
- package/dist/src/artifacts/corpus-views/renderers.js +3 -3
- package/dist/src/artifacts/discovery-eval.js +6 -4
- package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
- package/dist/src/artifacts/fortemi-core-sync.js +166 -40
- package/dist/src/artifacts/framework-capabilities.js +171 -0
- package/dist/src/artifacts/framework-index-paths.js +73 -0
- package/dist/src/artifacts/framework-source-digest.js +75 -0
- package/dist/src/artifacts/index-builder.js +285 -131
- package/dist/src/artifacts/index-files.js +132 -18
- package/dist/src/artifacts/index-preparation.js +65 -0
- package/dist/src/artifacts/index-refresh.js +576 -0
- package/dist/src/artifacts/index-worker.mjs +9 -0
- package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
- package/dist/src/artifacts/prebuilt-deployment.js +46 -0
- package/dist/src/artifacts/prebuilt-relations.js +80 -0
- package/dist/src/artifacts/query-engine.js +410 -88
- package/dist/src/artifacts/relations-builder.js +168 -0
- package/dist/src/artifacts/relations.js +148 -0
- package/dist/src/artifacts/repair.js +9 -4
- package/dist/src/artifacts/stats.js +5 -2
- package/dist/src/artifacts/types.js +30 -10
- package/dist/src/artifacts/watcher.js +1 -1
- package/dist/src/auth/credential-store.js +2 -1
- package/dist/src/catalog/cli.d.mts +5 -0
- package/dist/src/channel/manager.d.mts +20 -0
- package/dist/src/channel/manager.mjs +78 -12
- package/dist/src/cli/child-process-result.js +40 -0
- package/dist/src/cli/command-log.js +2 -3
- package/dist/src/cli/env.js +38 -16
- package/dist/src/cli/flag-parsing.js +236 -0
- package/dist/src/cli/handlers/artifacts.js +3 -0
- package/dist/src/cli/handlers/auth.js +3 -0
- package/dist/src/cli/handlers/decision.js +218 -5
- package/dist/src/cli/handlers/diagnose.js +13 -5
- package/dist/src/cli/handlers/effect.js +4 -2
- package/dist/src/cli/handlers/evidence.js +3 -0
- package/dist/src/cli/handlers/feedback.js +14 -5
- package/dist/src/cli/handlers/help.js +1 -0
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/init.js +248 -30
- package/dist/src/cli/handlers/lint.js +5 -0
- package/dist/src/cli/handlers/mc.js +23 -0
- package/dist/src/cli/handlers/models.js +169 -10
- package/dist/src/cli/handlers/ralph-launcher.js +2 -0
- package/dist/src/cli/handlers/ralph.js +3 -0
- package/dist/src/cli/handlers/refresh.js +28 -0
- package/dist/src/cli/handlers/regenerate.js +14 -0
- package/dist/src/cli/handlers/resource-versions.js +3 -0
- package/dist/src/cli/handlers/rules.js +195 -0
- package/dist/src/cli/handlers/run.js +4 -0
- package/dist/src/cli/handlers/runtime-info.js +25 -11
- package/dist/src/cli/handlers/script-runner.js +19 -8
- package/dist/src/cli/handlers/session.js +406 -62
- package/dist/src/cli/handlers/sessions.js +243 -76
- package/dist/src/cli/handlers/setup-manifest.js +474 -79
- package/dist/src/cli/handlers/setup.js +180 -39
- package/dist/src/cli/handlers/steward.js +11 -0
- package/dist/src/cli/handlers/subcommands.js +60 -3
- package/dist/src/cli/handlers/team.js +18 -8
- package/dist/src/cli/handlers/uhp.js +3 -0
- package/dist/src/cli/handlers/use.js +307 -55
- package/dist/src/cli/handlers/utilities.js +125 -26
- package/dist/src/cli/handlers/version.js +8 -0
- package/dist/src/cli/prompt-utils.js +72 -0
- package/dist/src/cli/provider-resolution.js +11 -0
- package/dist/src/cli/router.js +15 -1
- package/dist/src/cli/services/deployment-verification.js +19 -9
- package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
- package/dist/src/cli/skill-usage.js +2 -3
- package/dist/src/config/aiwg-config.js +349 -35
- package/dist/src/config/cli.js +256 -23
- package/dist/src/config/decision-config.js +106 -0
- package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
- package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
- package/dist/src/config/gitignore.js +50 -0
- package/dist/src/config/index-graph-overrides.js +36 -0
- package/dist/src/config/project-artifacts-health.d.mts +37 -0
- package/dist/src/config/project-artifacts-health.mjs +14 -3
- package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
- package/dist/src/config/user-config-dir.d.mts +9 -0
- package/dist/src/config/user-config.js +38 -11
- package/dist/src/config/user-registry.js +23 -15
- package/dist/src/config/user-state.js +7 -0
- package/dist/src/decision/adapters/jev.js +75 -27
- package/dist/src/decision/ask.js +203 -43
- package/dist/src/decision/context-live-qualification.js +2 -2
- package/dist/src/decision/driver.js +14 -7
- package/dist/src/decision/ensemble/aggregate.js +23 -10
- package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
- package/dist/src/decision/entry.js +25 -6
- package/dist/src/decision/graph-live-qualification.js +1 -1
- package/dist/src/decision/graph-run.js +9 -0
- package/dist/src/decision/heldout/collector.js +15 -14
- package/dist/src/decision/heldout/contract.js +30 -7
- package/dist/src/decision/index.js +1 -0
- package/dist/src/decision/interop.js +60 -8
- package/dist/src/decision/jev-credentials.js +15 -1
- package/dist/src/decision/ledger.js +942 -0
- package/dist/src/decision/offload-activation.js +137 -0
- package/dist/src/decision/offload.js +550 -0
- package/dist/src/decision/qualification/load.js +4 -6
- package/dist/src/decision/savings.js +28 -0
- package/dist/src/decision/validate.js +6 -3
- package/dist/src/effects/dispatch-verifier.js +252 -0
- package/dist/src/effects/index.js +1 -0
- package/dist/src/effects/types.js +5 -1
- package/dist/src/effects/verifiers/git.js +2 -1
- package/dist/src/effects/verifiers/tracker.js +26 -14
- package/dist/src/extensions/commands/definitions.js +19 -0
- package/dist/src/extensions/project-local-remove.js +36 -1
- package/dist/src/features/installer.js +2 -2
- package/dist/src/flow/graph-metadata.js +5 -0
- package/dist/src/gates/providers/loader.js +64 -18
- package/dist/src/installation/manager-command.d.mts +18 -0
- package/dist/src/installation/manager-command.mjs +15 -3
- package/dist/src/installation/manager.d.mts +49 -0
- package/dist/src/installation/manager.mjs +95 -5
- package/dist/src/issues/cli.js +4 -4
- package/dist/src/issues/local.js +24 -5
- package/dist/src/jobs/runner.js +1 -1
- package/dist/src/lint/cli.js +27 -1
- package/dist/src/lint/loader.js +2 -1
- package/dist/src/lint/reporters.js +25 -1
- package/dist/src/lint/rule-activation.js +43 -0
- package/dist/src/lint/runner.js +137 -62
- package/dist/src/mcp/adapters/codex-runtime.js +366 -56
- package/dist/src/mcp/claude-install.d.mts +4 -0
- package/dist/src/mcp/claude-install.mjs +41 -0
- package/dist/src/mcp/cli.d.mts +1 -0
- package/dist/src/mcp/cli.mjs +620 -85
- package/dist/src/mcp/config-file.d.mts +28 -0
- package/dist/src/mcp/config-file.mjs +279 -0
- package/dist/src/mcp/config-layers.d.mts +36 -0
- package/dist/src/mcp/config-layers.mjs +348 -0
- package/dist/src/mcp/credentials.d.mts +51 -0
- package/dist/src/mcp/credentials.mjs +484 -0
- package/dist/src/mcp/grok-build-config.d.mts +6 -0
- package/dist/src/mcp/grok-build-config.mjs +17 -27
- package/dist/src/mcp/helpers.mjs +109 -4
- package/dist/src/mcp/muse-native-config.d.mts +13 -0
- package/dist/src/mcp/muse-native-config.mjs +1 -0
- package/dist/src/mcp/omp-config.d.mts +4 -0
- package/dist/src/mcp/omp-config.mjs +50 -29
- package/dist/src/mcp/profiles.js +97 -23
- package/dist/src/mcp/profiles.mjs +99 -27
- package/dist/src/mcp/registry.js +248 -131
- package/dist/src/mcp/registry.mjs +169 -100
- package/dist/src/mcp/server-config.d.mts +3 -0
- package/dist/src/mcp/server-config.mjs +89 -0
- package/dist/src/mcp/server.mjs +127 -82
- package/dist/src/mcp/test-simple.mjs +2 -1
- package/dist/src/mcp/toml-editor.d.mts +4 -0
- package/dist/src/mcp/toml-string.d.mts +1 -0
- package/dist/src/mcp/toml-string.mjs +9 -0
- package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
- package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
- package/dist/src/mcp/tool-filters.d.mts +46 -0
- package/dist/src/mcp/tool-filters.mjs +357 -0
- package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
- package/dist/src/mcp/tools/decision.mjs +22 -3
- package/dist/src/mcp/tools/discovery.mjs +62 -55
- package/dist/src/mcp/tools/orchestration.mjs +50 -2
- package/dist/src/mcp/tools/subsystems.mjs +39 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +2856 -0
- package/dist/src/mcp/tools/worker-shell-control.mjs +289 -0
- package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
- package/dist/src/memory/project-registry.js +2 -2
- package/dist/src/mission-protocol/codecs.js +647 -1
- package/dist/src/mission-protocol/types.js +110 -0
- package/dist/src/mission-protocol/worker-status.js +2 -0
- package/dist/src/models/config-loader.js +76 -14
- package/dist/src/models/grok-build-models.js +93 -41
- package/dist/src/models/model-capabilities.v1.json +3183 -24
- package/dist/src/models/model-discovery.js +931 -67
- package/dist/src/models/provider-policy.js +719 -11
- package/dist/src/models/qualification-digest.d.mts +2 -0
- package/dist/src/models/qualification-digest.mjs +17 -0
- package/dist/src/models/resolver.js +261 -0
- package/dist/src/models/worker-direct-readiness.js +550 -0
- package/dist/src/models/worker-dispatch-offer.js +169 -0
- package/dist/src/models/worker-health-readiness.js +144 -0
- package/dist/src/models/worker-installation.d.mts +39 -0
- package/dist/src/models/worker-installation.mjs +986 -0
- package/dist/src/models/wrapper-route.js +18 -0
- package/dist/src/ops/registry.js +9 -14
- package/dist/src/plugins/standalone-packager.js +4 -3
- package/dist/src/process/bounded-child-process.d.mts +84 -0
- package/dist/src/process/bounded-child-process.mjs +430 -0
- package/dist/src/process/cli-command.d.mts +16 -0
- package/dist/src/process/cli-command.mjs +75 -0
- package/dist/src/process/signal-child.d.mts +6 -0
- package/dist/src/process/signal-child.mjs +7 -0
- package/dist/src/providers/capability-matrix.js +8 -0
- package/dist/src/providers/capability-matrix.yaml +270 -0
- package/dist/src/providers/deployed-skill-roots.js +20 -0
- package/dist/src/providers/grok-build-acp.js +3 -2
- package/dist/src/providers/grok-build-headless.js +53 -23
- package/dist/src/providers/grok-build-inspect.js +1 -0
- package/dist/src/providers/omp-agent.d.mts +8 -0
- package/dist/src/providers/omp-diagnostics.d.mts +1 -0
- package/dist/src/providers/omp-paths.d.mts +13 -0
- package/dist/src/providers/provider-definitions.js +9 -1
- package/dist/src/providers/provider-definitions.mjs +9 -2
- package/dist/src/providers/skill-ownership.d.mts +9 -0
- package/dist/src/providers/skill-ownership.mjs +88 -0
- package/dist/src/rules/activation.d.mts +21 -0
- package/dist/src/rules/activation.mjs +62 -0
- package/dist/src/rules/inline-budget.d.mts +26 -0
- package/dist/src/rules/inline-budget.mjs +66 -0
- package/dist/src/rules/inventory.js +129 -0
- package/dist/src/rules/pin-state.js +73 -0
- package/dist/src/rules/pins.d.mts +14 -0
- package/dist/src/rules/pins.mjs +112 -0
- package/dist/src/rules/rule-frontmatter.schema.json +197 -0
- package/dist/src/serve/executor-registry.js +16 -24
- package/dist/src/serve/fleet-mission-conductor.js +9 -0
- package/dist/src/serve/mission-conductor.js +47 -12
- package/dist/src/serve/shared-host-scheduler.js +2 -0
- package/dist/src/serve/worker-invocation.js +558 -0
- package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
- package/dist/src/serve/worker-stdin-frame.mjs +107 -0
- package/dist/src/sessions/adapter-registry.js +49 -0
- package/dist/src/sessions/adapters/claude.js +39 -54
- package/dist/src/sessions/adapters/codex.js +82 -67
- package/dist/src/sessions/adapters/copilot.js +4 -4
- package/dist/src/sessions/adapters/cursor.js +40 -57
- package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
- package/dist/src/sessions/adapters/factory.js +31 -27
- package/dist/src/sessions/adapters/generic.js +43 -9
- package/dist/src/sessions/adapters/grok-build.js +11 -11
- package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
- package/dist/src/sessions/adapters/grokbot.js +434 -24
- package/dist/src/sessions/adapters/hermes.js +27 -29
- package/dist/src/sessions/adapters/muse-workspace-scan.js +128 -0
- package/dist/src/sessions/adapters/muse.js +200 -104
- package/dist/src/sessions/adapters/omp.js +28 -14
- package/dist/src/sessions/adapters/openclaw.js +89 -79
- package/dist/src/sessions/adapters/opencode.js +27 -24
- package/dist/src/sessions/adapters/openhuman.js +18 -60
- package/dist/src/sessions/adapters/pi.js +30 -14
- package/dist/src/sessions/adapters/warp.js +3 -3
- package/dist/src/sessions/adapters/windsurf.js +19 -48
- package/dist/src/sessions/batch-contracts.js +25 -5
- package/dist/src/sessions/batch-import.js +72 -51
- package/dist/src/sessions/candidates.js +47 -11
- package/dist/src/sessions/contracts.js +75 -2
- package/dist/src/sessions/coverage-preflight.js +134 -0
- package/dist/src/sessions/discovery.js +3 -0
- package/dist/src/sessions/export-plan.js +4 -3
- package/dist/src/sessions/grok-build-cli.js +67 -5
- package/dist/src/sessions/import-exclusions.js +72 -0
- package/dist/src/sessions/import-lease.js +34 -18
- package/dist/src/sessions/import-limits.js +37 -0
- package/dist/src/sessions/importer.js +84 -46
- package/dist/src/sessions/index.js +2 -0
- package/dist/src/sessions/lifecycle.js +45 -0
- package/dist/src/sessions/policy.js +133 -25
- package/dist/src/sessions/readers.js +106 -53
- package/dist/src/sessions/refresh.js +106 -0
- package/dist/src/sessions/repository.js +199 -63
- package/dist/src/sessions/workspace-discovery.js +315 -88
- package/dist/src/sessions/workspace-matching.js +107 -0
- package/dist/src/skills/adapters/clawhub.js +10 -8
- package/dist/src/skills/adapters/openclaw.js +10 -7
- package/dist/src/skills/importer.js +1 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
- package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
- package/dist/src/smiths/context-pipeline/finalization.js +6 -5
- package/dist/src/smiths/context-pipeline/generator.js +21 -4
- package/dist/src/smiths/context-pipeline/parallelism-section.js +195 -14
- package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
- package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
- package/dist/src/smiths/mcpsmith/example.js +1 -1
- package/dist/src/smiths/mcpsmith/generator.js +1 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +85 -31
- package/dist/src/storage/backends/fs.js +18 -76
- package/dist/src/storage/backends/logseq.js +68 -7
- package/dist/src/storage/backends/obsidian.js +1 -0
- package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
- package/dist/src/testing/generators/test-code-generator.js +57 -30
- package/dist/src/tracker/forge-http.js +2 -1
- package/dist/src/uhp/client.js +11 -1
- package/dist/src/uhp/mission.js +5 -0
- package/dist/src/update/checker.d.mts +2 -0
- package/dist/src/update/checker.mjs +5 -5
- package/dist/src/update/notifier.mjs +54 -2
- package/dist/src/update/service.d.mts +22 -0
- package/dist/src/utils/contained-filesystem.d.mts +37 -0
- package/dist/src/utils/contained-filesystem.mjs +683 -0
- package/dist/src/utils/temporary-directory.js +36 -0
- package/dist/src/writing/example-generator.js +1 -1
- package/dist/src/writing/fidelity.js +18 -1
- package/package.json +32 -2
- package/schemas/mission-v1.schema.json +2429 -0
- package/schemas/models/model-catalog.v1.schema.json +301 -0
- package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
- package/schemas/models/model-policy.v1.schema.json +14 -0
- package/schemas/models/provider-model-capabilities.v1.schema.json +1072 -0
- package/tools/_resolve-impl.mjs +39 -2
- package/tools/agents/deploy-agents.mjs +64 -23
- package/tools/agents/providers/base.mjs +153 -166
- package/tools/agents/providers/claude.mjs +8 -24
- package/tools/agents/providers/codex.mjs +18 -11
- package/tools/agents/providers/cursor.mjs +19 -18
- package/tools/agents/providers/grok-build.mjs +3 -1
- package/tools/agents/providers/grokbot.mjs +11 -12
- package/tools/agents/providers/hermes.mjs +62 -49
- package/tools/agents/providers/omp.mjs +5 -2
- package/tools/agents/providers/openclaw-translator.mjs +19 -5
- package/tools/agents/providers/openclaw.mjs +9 -4
- package/tools/agents/providers/pi.mjs +5 -0
- package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
- package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
- package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
- package/tools/agents/providers/rule-delivery.mjs +1270 -0
- package/tools/agents/providers/warp.mjs +20 -26
- package/tools/cli/decision-offload-report.mjs +40 -0
- package/tools/cli/workspace-status.mjs +862 -0
- package/tools/plugin/package-plugins.mjs +186 -8
- package/tools/plugin/plugin-links.mjs +114 -0
- package/tools/providers/antigravity-transport.mjs +3 -1
- package/tools/providers/deepseek-harness-transport.mjs +360 -0
- package/tools/providers/omp-transport.mjs +194 -0
- package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
- package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
- package/tools/ralph-external/lib/consecutive-failure-circuit-breaker.mjs +1748 -0
- package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
- package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
- package/tools/ralph-external/lib/launcher-recovery-evidence.mjs +55 -0
- package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
- package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
- package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
- package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
- package/tools/ralph-external/lib/pi-adapter.mjs +329 -0
- package/tools/ralph-external/lib/provider-adapter.mjs +748 -0
- package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
- package/tools/ralph-external/lib/session-environment.mjs +28 -0
- package/tools/ralph-external/lib/systemd-client.mjs +49 -0
- package/tools/ralph-external/lib/worker-health.mjs +439 -0
- package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
- package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
- package/tools/ralph-external/process-monitor.mjs +1017 -0
- package/tools/ralph-external/session-launcher.mjs +5057 -0
- package/tools/scripts/resource-preflight.mjs +541 -0
- package/tools/skills/deploy-skills-codex.mjs +2 -1
- package/vscode-extension/schemas/aiwg.config.v1.json +2916 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layered MCP configuration roots.
|
|
3
|
+
*
|
|
4
|
+
* AIWG_CONFIG_LAYERS lists configuration directories separated by the
|
|
5
|
+
* platform path delimiter (`:` on POSIX, `;` on Windows), lowest precedence
|
|
6
|
+
* first. Each directory may hold mcp-servers.json and mcp-profiles.json. An
|
|
7
|
+
* entry (server or profile) in a later directory replaces the entry of the
|
|
8
|
+
* same name in an earlier one; entries are not merged field by field.
|
|
9
|
+
*
|
|
10
|
+
* The last directory is the write layer: add, update and recordInjection
|
|
11
|
+
* write there, and nothing from an earlier layer is copied into it unless
|
|
12
|
+
* that entry is updated.
|
|
13
|
+
*
|
|
14
|
+
* When AIWG_CONFIG_LAYERS is unset, or a registry is constructed with an
|
|
15
|
+
* explicit directory, the single-directory behaviour applies unchanged.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { lstat, mkdtemp, readFile, readlink, realpath, rmdir } from 'fs/promises';
|
|
19
|
+
import { basename, dirname, isAbsolute, posix, relative, resolve, sep, win32 } from 'path';
|
|
20
|
+
import { assertConfigDestination, assertNoSymlinkParents, writeConfigAtomic } from './config-file.mjs';
|
|
21
|
+
import { resolveCredentialPolicy, stricterCredentialPolicy, warnCredentialPolicyRelaxation, warnDroppedOverlayPolicy } from './credentials.mjs';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* `platform` lets tests validate Windows path semantics (`C:\org`, UNC
|
|
25
|
+
* `\\server`, root-relative `\org`/`/org`) deterministically on any host; it
|
|
26
|
+
* defaults to the real host platform, so production calls behave exactly as
|
|
27
|
+
* the native `path` module already would.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveConfigLayers(configDirOverride, env = process.env, { platform = process.platform } = {}) {
|
|
30
|
+
if (configDirOverride) return null;
|
|
31
|
+
const raw = env.AIWG_CONFIG_LAYERS;
|
|
32
|
+
if (!raw || !raw.trim()) return null;
|
|
33
|
+
const pathForPlatform = platform === 'win32' ? win32 : posix;
|
|
34
|
+
// A Windows-formatted value uses `;`; splitting a drive-qualified entry
|
|
35
|
+
// (`C:\org`) on the real host's POSIX `:` would wrongly cut it at the drive
|
|
36
|
+
// letter, so the simulated platform's own delimiter is used, not the real
|
|
37
|
+
// host's - matching the native `path` module's behaviour when the real host
|
|
38
|
+
// actually is that platform.
|
|
39
|
+
const entries = raw.split(pathForPlatform.delimiter).map(entry => entry.trim()).filter(Boolean);
|
|
40
|
+
// A bare leading `\` or `/` with no drive letter is current-drive-relative
|
|
41
|
+
// under Windows path semantics: resolving it from C:\work versus D:\work
|
|
42
|
+
// selects different drives, so a layer list could change meaning across
|
|
43
|
+
// hosts. The backslash form is refused on every platform, since it is never
|
|
44
|
+
// a valid POSIX absolute path either. The forward-slash form is refused
|
|
45
|
+
// only when interpreting entries under actual Windows path semantics; on
|
|
46
|
+
// POSIX, a leading `/` is an unambiguous, fully-qualified absolute path and
|
|
47
|
+
// must keep working. Drive-qualified (`C:\`, `C:/`) and UNC (`\\server`,
|
|
48
|
+
// `//server`) forms remain allowed on every platform.
|
|
49
|
+
const driveRelativePattern = platform === 'win32' ? /^[\\/](?![\\/])/ : /^\\(?!\\)/;
|
|
50
|
+
const driveRelativeEntries = entries.filter(entry => driveRelativePattern.test(entry));
|
|
51
|
+
if (driveRelativeEntries.length) {
|
|
52
|
+
throw new Error(`AIWG_CONFIG_LAYERS entries must be absolute paths; refusing Windows current-drive-relative entries: ${driveRelativeEntries.join(', ')}`);
|
|
53
|
+
}
|
|
54
|
+
// A relative entry would resolve against the current working directory, so the
|
|
55
|
+
// same AIWG_CONFIG_LAYERS value would name different layers from different
|
|
56
|
+
// invocation directories. Refuse instead of silently picking a directory.
|
|
57
|
+
const relativeEntries = entries.filter(entry => !pathForPlatform.isAbsolute(entry));
|
|
58
|
+
if (relativeEntries.length) {
|
|
59
|
+
throw new Error(`AIWG_CONFIG_LAYERS entries must be absolute paths; refusing relative entries: ${relativeEntries.join(', ')}`);
|
|
60
|
+
}
|
|
61
|
+
const layers = entries.map(entry => pathForPlatform.resolve(entry));
|
|
62
|
+
return layers.length > 0 ? layers : null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function readLayer(path) {
|
|
66
|
+
try {
|
|
67
|
+
return JSON.parse(await readFile(path, 'utf-8'));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error?.code === 'ENOENT') return null;
|
|
70
|
+
if (error instanceof SyntaxError) throw new Error(`Invalid JSON in MCP configuration layer ${path}`);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** File-format fields every layer file keeps, whichever layer set them. */
|
|
76
|
+
const FORMAT_FIELDS = ['apiVersion', 'kind'];
|
|
77
|
+
|
|
78
|
+
/** Bookkeeping fields that do not make an entry "changed" for layering purposes. */
|
|
79
|
+
const BOOKKEEPING_FIELDS = ['injectedProviders', 'addedAt', 'createdAt', 'updatedAt'];
|
|
80
|
+
|
|
81
|
+
function sortKeys(value) {
|
|
82
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
83
|
+
if (value === null || typeof value !== 'object') return value;
|
|
84
|
+
return Object.fromEntries(Object.keys(value).sort().map(key => [key, sortKeys(value[key])]));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function comparable(entry) {
|
|
88
|
+
const copy = { ...entry };
|
|
89
|
+
for (const field of BOOKKEEPING_FIELDS) delete copy[field];
|
|
90
|
+
return JSON.stringify(sortKeys(copy));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Read `filename` from every layer and merge the `collection` map by entry
|
|
95
|
+
* name. Top-level fields come from the highest layer that sets them, except
|
|
96
|
+
* credentialPolicy: lower (non-write) layers fold together with the
|
|
97
|
+
* strictest value winning - an enforced organisation floor - and the write
|
|
98
|
+
* layer's own declared value (a personal default) is then bounded below by
|
|
99
|
+
* that floor, never copying the floor itself into the write layer's record.
|
|
100
|
+
* `lowerPolicySource` names the config file of the lower layer that set the
|
|
101
|
+
* folded floor's value (the first layer to set it; a later layer repeating
|
|
102
|
+
* the same strictness does not move attribution), for diagnostics.
|
|
103
|
+
*
|
|
104
|
+
* Returns the merged data and a layering record: the names defined in the
|
|
105
|
+
* write layer, and comparable forms of entries and top-level fields in lower layers.
|
|
106
|
+
*/
|
|
107
|
+
export async function loadLayered(layers, filename, collection, defaults) {
|
|
108
|
+
const merged = { ...defaults, [collection]: {} };
|
|
109
|
+
const lower = new Map();
|
|
110
|
+
const own = new Set();
|
|
111
|
+
const lowerFields = new Map();
|
|
112
|
+
const ownFields = new Set();
|
|
113
|
+
let ownPolicy;
|
|
114
|
+
let lowerPolicy;
|
|
115
|
+
let lowerPolicySource;
|
|
116
|
+
const writeLayer = layers.length - 1;
|
|
117
|
+
for (const [index, dir] of layers.entries()) {
|
|
118
|
+
const parsed = await readLayer(resolve(dir, filename));
|
|
119
|
+
if (!parsed) continue;
|
|
120
|
+
const { [collection]: entries, ...rest } = parsed;
|
|
121
|
+
if (index === writeLayer) {
|
|
122
|
+
ownPolicy = rest.credentialPolicy;
|
|
123
|
+
} else if (Object.hasOwn(rest, 'credentialPolicy')) {
|
|
124
|
+
try {
|
|
125
|
+
const folded = stricterCredentialPolicy(lowerPolicy, rest.credentialPolicy);
|
|
126
|
+
if (folded !== lowerPolicy) lowerPolicySource = resolve(dir, filename);
|
|
127
|
+
lowerPolicy = folded;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
throw new Error(`Invalid MCP credential policy in layer ${resolve(dir, filename)}: ${error.message}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
Object.assign(merged, rest);
|
|
133
|
+
// Across several lower layers, credentialPolicy folds by strictness, not
|
|
134
|
+
// by "last layer wins" like every other field: keep the running snapshot
|
|
135
|
+
// in sync with the folded floor so a later lowerFields comparison (used
|
|
136
|
+
// to decide whether to copy an unchanged inherited value) reflects it,
|
|
137
|
+
// not one lower layer's own raw declared value.
|
|
138
|
+
if (index < writeLayer) merged.credentialPolicy = lowerPolicy;
|
|
139
|
+
for (const field of Object.keys(rest)) {
|
|
140
|
+
if (index === writeLayer) ownFields.add(field);
|
|
141
|
+
else lowerFields.set(field, comparable({ value: merged[field] }));
|
|
142
|
+
}
|
|
143
|
+
for (const [name, entry] of Object.entries(entries || {})) {
|
|
144
|
+
merged[collection][name] = entry;
|
|
145
|
+
if (index === writeLayer) own.add(name);
|
|
146
|
+
else lower.set(name, comparable(entry));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// No layer declared a policy anywhere: leave the field absent, exactly as
|
|
150
|
+
// when `defaults` carries no credentialPolicy, rather than materializing
|
|
151
|
+
// the built-in `literal` default as a stored value.
|
|
152
|
+
let effectivePolicy;
|
|
153
|
+
if (ownPolicy !== undefined || lowerPolicy !== undefined) {
|
|
154
|
+
try {
|
|
155
|
+
effectivePolicy = resolveCredentialPolicy({
|
|
156
|
+
registryPolicy: ownPolicy, floorPolicy: lowerPolicy, floorSource: lowerPolicySource, env: {},
|
|
157
|
+
});
|
|
158
|
+
} catch (error) {
|
|
159
|
+
throw new Error(`Invalid MCP credential policy in layer ${resolve(layers[writeLayer], filename)}: ${error.message}`);
|
|
160
|
+
}
|
|
161
|
+
merged.credentialPolicy = effectivePolicy;
|
|
162
|
+
} else {
|
|
163
|
+
delete merged.credentialPolicy;
|
|
164
|
+
}
|
|
165
|
+
return { data: merged, layering: { lower, own, lowerFields, ownFields, ownPolicy, lowerPolicy, lowerPolicySource, effectivePolicy } };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** True when the entry is defined only below the write layer. */
|
|
169
|
+
export function isLowerLayerEntry(layering, name) {
|
|
170
|
+
return layering.lower.has(name) && !layering.own.has(name);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* True when the write layer overrides a lower-layer entry that still carries
|
|
175
|
+
* worker qualification. Removing that override would silently re-expose the
|
|
176
|
+
* lower entry's qualification, so removal must be refused instead.
|
|
177
|
+
*/
|
|
178
|
+
export function lowerEntryQualified(layering, name) {
|
|
179
|
+
if (!layering?.lower?.has(name) || !layering?.own?.has(name)) return false;
|
|
180
|
+
try {
|
|
181
|
+
return JSON.parse(layering.lower.get(name))?.workerQualification !== undefined;
|
|
182
|
+
} catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The data to persist in the write layer: entries defined there, new entries,
|
|
189
|
+
* and lower-layer entries whose content (bookkeeping aside) was changed.
|
|
190
|
+
* Top-level fields follow the same rule, without entry bookkeeping exclusions;
|
|
191
|
+
* apiVersion and kind are always kept so the file stays self-describing.
|
|
192
|
+
*/
|
|
193
|
+
export function writeLayerData(data, collection, layering, explicitPolicy = false) {
|
|
194
|
+
const entries = Object.entries(data[collection] || {}).filter(([name, entry]) =>
|
|
195
|
+
layering.own.has(name) || !layering.lower.has(name) || comparable(entry) !== layering.lower.get(name));
|
|
196
|
+
const fields = Object.entries(data).filter(([field, value]) => field !== collection && (
|
|
197
|
+
FORMAT_FIELDS.includes(field) || layering.ownFields.has(field) || !layering.lowerFields.has(field) ||
|
|
198
|
+
comparable({ value }) !== layering.lowerFields.get(field)));
|
|
199
|
+
const persisted = { ...Object.fromEntries(fields), [collection]: Object.fromEntries(entries) };
|
|
200
|
+
// A setter explicitly writes even when its value equals the merged floor.
|
|
201
|
+
// Other saves retain policy ownership, without copying an inherited floor.
|
|
202
|
+
if (explicitPolicy || data.credentialPolicy !== layering.effectivePolicy) {
|
|
203
|
+
const effective = resolveCredentialPolicy({
|
|
204
|
+
flag: data.credentialPolicy, floorPolicy: layering.lowerPolicy, floorSource: layering.lowerPolicySource, env: {},
|
|
205
|
+
});
|
|
206
|
+
if (effective !== data.credentialPolicy) {
|
|
207
|
+
const location = layering.lowerPolicySource ? ` (set in ${layering.lowerPolicySource})` : '';
|
|
208
|
+
throw new Error(`Cannot relax MCP credential policy floor "${effective}"${location} to "${data.credentialPolicy}".`);
|
|
209
|
+
}
|
|
210
|
+
persisted.credentialPolicy = data.credentialPolicy;
|
|
211
|
+
} else if (layering.ownPolicy !== undefined &&
|
|
212
|
+
resolveCredentialPolicy({ flag: layering.ownPolicy, floorPolicy: layering.lowerPolicy, floorSource: layering.lowerPolicySource, env: {} }) !== layering.ownPolicy) {
|
|
213
|
+
delete persisted.credentialPolicy;
|
|
214
|
+
warnDroppedOverlayPolicy(layering.ownPolicy, layering.lowerPolicy, layering.lowerPolicySource);
|
|
215
|
+
}
|
|
216
|
+
return persisted;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Resolve a target, including a missing suffix, without creating it. */
|
|
220
|
+
async function targetRealpath(path, aliases = []) {
|
|
221
|
+
const absolute = resolve(path);
|
|
222
|
+
if (aliases.includes(absolute)) throw new Error(`MCP configuration target symlink cycle: ${[...aliases, absolute].join(' -> ')}`);
|
|
223
|
+
try {
|
|
224
|
+
return await realpath(path);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
if (error.code !== 'ENOENT') throw error;
|
|
227
|
+
// Resolve dangling aliases too: creating their missing referent would change
|
|
228
|
+
// a lower layer even though realpath currently reports ENOENT.
|
|
229
|
+
if (dirname(absolute) === absolute) throw error;
|
|
230
|
+
const candidate = resolve(await targetRealpath(dirname(absolute), aliases), basename(absolute));
|
|
231
|
+
try {
|
|
232
|
+
if ((await lstat(candidate)).isSymbolicLink()) {
|
|
233
|
+
return targetRealpath(resolve(dirname(candidate), await readlink(candidate)), [...aliases, absolute]);
|
|
234
|
+
}
|
|
235
|
+
} catch (statError) {
|
|
236
|
+
if (statError.code !== 'ENOENT') throw statError;
|
|
237
|
+
}
|
|
238
|
+
return candidate;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Probe the filesystem containing the nearest existing ancestor of a target. */
|
|
243
|
+
export async function isCaseInsensitivePath(path) {
|
|
244
|
+
let ancestor = resolve(path);
|
|
245
|
+
while (true) {
|
|
246
|
+
try {
|
|
247
|
+
await realpath(ancestor);
|
|
248
|
+
break;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error.code !== 'ENOENT' || dirname(ancestor) === ancestor) throw error;
|
|
251
|
+
ancestor = dirname(ancestor);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
let probe;
|
|
255
|
+
try {
|
|
256
|
+
probe = await mkdtemp(resolve(ancestor, '.aiwg-case-probe-a-'));
|
|
257
|
+
const alternate = resolve(dirname(probe), basename(probe).toUpperCase());
|
|
258
|
+
try {
|
|
259
|
+
const [original, folded] = await Promise.all([lstat(probe), lstat(alternate)]);
|
|
260
|
+
return original.dev === folded.dev && original.ino === folded.ino;
|
|
261
|
+
} catch (error) {
|
|
262
|
+
if (error.code === 'ENOENT') return false;
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
} catch (error) {
|
|
266
|
+
// Read-only ancestors cannot be probed: compare conservatively rather than allow overlap.
|
|
267
|
+
if (error.code === 'EACCES' || error.code === 'EPERM' || error.code === 'EROFS') return true;
|
|
268
|
+
throw error;
|
|
269
|
+
} finally {
|
|
270
|
+
if (probe) await rmdir(probe);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function inside(target, parent, caseInsensitive) {
|
|
275
|
+
const rel = relative(caseInsensitive ? parent.toLowerCase() : parent, caseInsensitive ? target.toLowerCase() : target);
|
|
276
|
+
return !rel || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Refuse a write that could modify another configuration layer. */
|
|
280
|
+
export async function assertLayerWriteDestination(layers, filename) {
|
|
281
|
+
const targets = await Promise.all(layers.map(async dir => ({
|
|
282
|
+
dir: await targetRealpath(dir),
|
|
283
|
+
files: await Promise.all(['mcp-servers.json', 'mcp-profiles.json'].map(name => targetRealpath(resolve(dir, name)))),
|
|
284
|
+
})));
|
|
285
|
+
const write = targets[targets.length - 1];
|
|
286
|
+
const caseInsensitive = await isCaseInsensitivePath(write.dir);
|
|
287
|
+
const writeFile = await targetRealpath(resolve(layers[layers.length - 1], filename));
|
|
288
|
+
for (const lower of targets.slice(0, -1)) {
|
|
289
|
+
if (inside(write.dir, lower.dir, caseInsensitive) || inside(writeFile, lower.dir, caseInsensitive) || lower.files.some(file => inside(writeFile, file, caseInsensitive))) {
|
|
290
|
+
throw new Error(`Refusing overlapping MCP configuration layer targets: ${writeFile} overlaps ${lower.dir}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const file = resolve(layers[layers.length - 1], filename);
|
|
294
|
+
await assertNoSymlinkParents(file, layers[layers.length - 1]);
|
|
295
|
+
await assertConfigDestination(file);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Persist atomically, then refresh ownership only after a successful write. */
|
|
299
|
+
export async function saveLayerData(file, data, collection, layers, layering, explicitPolicy = false) {
|
|
300
|
+
if (layers) await assertLayerWriteDestination(layers, basename(file));
|
|
301
|
+
const persisted = layering ? writeLayerData(data, collection, layering, explicitPolicy) : data;
|
|
302
|
+
// The active identity layer file is always 0600: it is the personal write
|
|
303
|
+
// layer of an active AIWG_CONFIG_LAYERS configuration and may carry secrets.
|
|
304
|
+
// Without layering, `file` is whatever single directory the caller
|
|
305
|
+
// configured (which may be a shared, group-readable organisation checkout
|
|
306
|
+
// maintained directly, not a private identity directory): an existing file
|
|
307
|
+
// keeps its mode, while a newly created file starts private at 0600.
|
|
308
|
+
await writeConfigAtomic(file, JSON.stringify(persisted, null, 2) + '\n', layers
|
|
309
|
+
? { userScope: true, rejectSymlinkParents: true }
|
|
310
|
+
: { newFileMode: 0o600, rejectSymlinkParents: true });
|
|
311
|
+
if (layering) {
|
|
312
|
+
layering.own = new Set(Object.keys(persisted[collection] || {}));
|
|
313
|
+
layering.ownFields = new Set(Object.keys(persisted).filter(field => field !== collection));
|
|
314
|
+
layering.ownPolicy = persisted.credentialPolicy;
|
|
315
|
+
layering.effectivePolicy = data.credentialPolicy;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Resolve a profile's `extends` chain. Servers are concatenated base-first
|
|
321
|
+
* without duplicates. Per provider key, toolDeny accumulates across the chain
|
|
322
|
+
* and toolAllow is taken from the most-derived profile that sets it.
|
|
323
|
+
*/
|
|
324
|
+
export function resolveProfileExtends(name, profiles, seen = []) {
|
|
325
|
+
const profile = profiles[name];
|
|
326
|
+
if (!profile) {
|
|
327
|
+
throw new Error(seen.length > 0
|
|
328
|
+
? `Profile "${seen[seen.length - 1]}" extends "${name}", which is not defined in any configuration layer.`
|
|
329
|
+
: `Profile "${name}" not found.`);
|
|
330
|
+
}
|
|
331
|
+
if (seen.includes(name)) throw new Error(`Profile extends cycle: ${[...seen, name].join(' -> ')}`);
|
|
332
|
+
const bases = (profile.extends || []).map(base => resolveProfileExtends(base, profiles, [...seen, name]));
|
|
333
|
+
|
|
334
|
+
const servers = [];
|
|
335
|
+
const providerOverrides = {};
|
|
336
|
+
for (const source of [...bases, profile]) {
|
|
337
|
+
for (const server of source.servers || []) if (!servers.includes(server)) servers.push(server);
|
|
338
|
+
for (const [provider, override] of Object.entries(source.providerOverrides || {})) {
|
|
339
|
+
const previous = providerOverrides[provider] || {};
|
|
340
|
+
providerOverrides[provider] = {
|
|
341
|
+
...previous,
|
|
342
|
+
...(override.toolDeny ? { toolDeny: [...new Set([...(previous.toolDeny || []), ...override.toolDeny])] } : {}),
|
|
343
|
+
...(override.toolAllow ? { toolAllow: [...override.toolAllow] } : {}),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return { ...profile, servers, providerOverrides };
|
|
348
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type McpCredentialPolicy = 'literal' | 'references' | 'none';
|
|
2
|
+
|
|
3
|
+
interface CredentialBearingServer {
|
|
4
|
+
name: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
args?: string[];
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
headerEnv?: Record<string, string>;
|
|
10
|
+
envFrom?: Record<string, string>;
|
|
11
|
+
auth?: { clientSecret?: string; tokenUrl?: string; redirectUri?: string; resource?: string };
|
|
12
|
+
oauth?: { clientSecret?: string; tokenUrl?: string; redirectUri?: string; resource?: string };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ENV_REFERENCE_SYNTAX: Readonly<Record<string, string | null>>;
|
|
16
|
+
export const CREDENTIAL_POLICIES: readonly McpCredentialPolicy[];
|
|
17
|
+
export function urlCarriesUserinfo(url?: string): boolean;
|
|
18
|
+
export function credentialLikeQueryParams(url?: string, options?: { includeReferences?: boolean }): string[];
|
|
19
|
+
export function credentialLikeFragmentParams(url?: string, options?: { includeReferences?: boolean }): string[];
|
|
20
|
+
export function isCredentialReferenceValue(value: unknown): boolean;
|
|
21
|
+
export function credentialLikeArgs(args?: string[], options?: { includeReferences?: boolean }): string[];
|
|
22
|
+
export function redactCredentialArgs(args?: string[]): string[] | undefined;
|
|
23
|
+
export function validateEnvReferenceName(name: string): void;
|
|
24
|
+
export function renderCredentialMaps(
|
|
25
|
+
server: CredentialBearingServer,
|
|
26
|
+
provider: string,
|
|
27
|
+
): { env?: Record<string, string>; headers?: Record<string, string> };
|
|
28
|
+
export function credentialPolicyViolations(server: CredentialBearingServer, policy?: McpCredentialPolicy): string[];
|
|
29
|
+
export function assertCredentialPolicy(servers: CredentialBearingServer[], policy?: McpCredentialPolicy): void;
|
|
30
|
+
export function resolveCredentialPolicy(options?: {
|
|
31
|
+
flag?: string;
|
|
32
|
+
registryPolicy?: string;
|
|
33
|
+
floorPolicy?: string;
|
|
34
|
+
floorSource?: string;
|
|
35
|
+
env?: Record<string, string | undefined>;
|
|
36
|
+
}): McpCredentialPolicy;
|
|
37
|
+
|
|
38
|
+
export function stricterCredentialPolicy(
|
|
39
|
+
a: McpCredentialPolicy | undefined,
|
|
40
|
+
b: McpCredentialPolicy | undefined,
|
|
41
|
+
): McpCredentialPolicy | undefined;
|
|
42
|
+
|
|
43
|
+
export function warnCredentialPolicyRelaxation(candidate: McpCredentialPolicy, floor: McpCredentialPolicy, source?: string): void;
|
|
44
|
+
export function warnDroppedOverlayPolicy(candidate: McpCredentialPolicy, floor: McpCredentialPolicy, source?: string): void;
|
|
45
|
+
export function resetCredentialPolicyWarnings(): void;
|
|
46
|
+
|
|
47
|
+
export const INSTALL_POLICY_EXEMPT_ENV: Readonly<Record<string, readonly string[]>>;
|
|
48
|
+
export function installPolicyCheckedServer(name: string, server: CredentialBearingServer): CredentialBearingServer;
|
|
49
|
+
|
|
50
|
+
export function redactCredentialText(value: string): string;
|
|
51
|
+
export function redactCredentialRecord<T>(value: T): T;
|