@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
package/dist/src/mcp/server.mjs
CHANGED
|
@@ -24,6 +24,7 @@ import { registerCommandRunTool } from './tools/command-run.mjs';
|
|
|
24
24
|
import { registerInteractionTools } from './tools/interaction.mjs';
|
|
25
25
|
import { parseToolsets, registerOptInToolsets, KNOWN_TOOLSETS } from './tools/subsystems.mjs';
|
|
26
26
|
import { AIWG_ROOT, findProjectRoot, resolveProjectAiwgDir } from './helpers.mjs';
|
|
27
|
+
import { pinContainedRoot as pinArtifactRoot, openContainedFile as openArtifact, readContainedFile, listContainedFiles, validateContainedPath } from '../utils/contained-filesystem.mjs';
|
|
27
28
|
|
|
28
29
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
30
|
|
|
@@ -36,7 +37,7 @@ const FRAMEWORKS = {
|
|
|
36
37
|
/**
|
|
37
38
|
* Create and configure the AIWG MCP Server
|
|
38
39
|
*/
|
|
39
|
-
export function createServer() {
|
|
40
|
+
export async function createServer() {
|
|
40
41
|
const server = new McpServer({
|
|
41
42
|
name: 'aiwg',
|
|
42
43
|
version: '1.0.0'
|
|
@@ -51,7 +52,28 @@ export function createServer() {
|
|
|
51
52
|
// discover, skill-list, skill-show, command-list, command-show,
|
|
52
53
|
// rule-list, rule-show, agent-show, template-list, template-show
|
|
53
54
|
// ============================================
|
|
54
|
-
|
|
55
|
+
const corpusStore = await pinArtifactRoot(path.resolve(AIWG_ROOT));
|
|
56
|
+
registerDiscoveryTools(server, { corpusStore });
|
|
57
|
+
async function readCorpus(relative) {
|
|
58
|
+
const content = await readContainedFile(corpusStore, relative);
|
|
59
|
+
if (content === null) throw new Error('Corpus file not found');
|
|
60
|
+
return content;
|
|
61
|
+
}
|
|
62
|
+
function frameworkName(framework) {
|
|
63
|
+
validateContainedPath(framework);
|
|
64
|
+
return Object.hasOwn(FRAMEWORKS, framework) ? framework : 'sdlc-complete';
|
|
65
|
+
}
|
|
66
|
+
async function scanCorpusDirectory(relative, type) {
|
|
67
|
+
const entries = await listContainedFiles(corpusStore, `${relative}/`);
|
|
68
|
+
return entries.filter(entry => entry.path.endsWith('.md')).map(entry => {
|
|
69
|
+
const local = path.relative(relative, entry.path);
|
|
70
|
+
const name = path.basename(local, '.md');
|
|
71
|
+
return {
|
|
72
|
+
name, path: path.join(corpusStore.root, entry.path), uri: `aiwg://${type}/${name}`,
|
|
73
|
+
...(path.dirname(local) !== '.' ? { category: local.split(path.sep)[0] } : {}),
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
55
77
|
registerWriterProfileResources(server);
|
|
56
78
|
|
|
57
79
|
// ============================================
|
|
@@ -70,11 +92,72 @@ export function createServer() {
|
|
|
70
92
|
// Opt-in subsystem toolsets (#1322-#1332)
|
|
71
93
|
//
|
|
72
94
|
// Enabled via AIWG_MCP_TOOLSETS env or `aiwg mcp serve --toolsets=`.
|
|
73
|
-
// Known: flows, missions, memory, kb, research, activity-log, index, ralph, mc, ops, sandbox, all
|
|
95
|
+
// Known: flows, missions, memory, kb, research, activity-log, index, ralph, mc, ops, sandbox, decision, all
|
|
96
|
+
// `workers` (#2892 direct worker run/status/cancel) needs an EXPLICIT name;
|
|
97
|
+
// `all` deliberately does not reach it (src/mcp/tools/subsystems.mjs).
|
|
74
98
|
// Default: none (core only — discovery + command-run)
|
|
75
99
|
// ============================================
|
|
76
100
|
const requested = parseToolsets(process.env.AIWG_MCP_TOOLSETS || '');
|
|
77
|
-
|
|
101
|
+
// #2892 B1: the `workers` toolset's served project root is resolved ONCE,
|
|
102
|
+
// here, at registration time — never lazily from `process.cwd()` inside
|
|
103
|
+
// the tool handler on first request. A project root that cannot be found
|
|
104
|
+
// (not running inside an AIWG project) means `workers` is simply not
|
|
105
|
+
// registered; `registerWorkerInvokeToolset` refuses rather than falling
|
|
106
|
+
// back to an implicit cwd.
|
|
107
|
+
let projectRoot;
|
|
108
|
+
try {
|
|
109
|
+
projectRoot = await findProjectRoot();
|
|
110
|
+
} catch {
|
|
111
|
+
projectRoot = undefined;
|
|
112
|
+
}
|
|
113
|
+
await registerOptInToolsets(server, requested, { projectRoot });
|
|
114
|
+
|
|
115
|
+
// Resolve operator configuration once per trusted project, then pin it.
|
|
116
|
+
// Artifact tools default to the server-start project (the launch directory),
|
|
117
|
+
// not an ancestor discovered by walking up from it: a fresh launch directory
|
|
118
|
+
// inside another marked tree (for example a stray `.aiwg` in the temp dir)
|
|
119
|
+
// must pin its own missing default at startup, never adopt the ancestor's
|
|
120
|
+
// store. Callers select other projects explicitly via `project_dir`.
|
|
121
|
+
const artifactEnv = { ...process.env };
|
|
122
|
+
const trustedProjectRoot = await fs.realpath(process.cwd());
|
|
123
|
+
const trustedArtifactRoot = await resolveProjectAiwgDir(trustedProjectRoot, { env: artifactEnv });
|
|
124
|
+
const startupStore = await pinArtifactRoot(trustedArtifactRoot, trustedProjectRoot);
|
|
125
|
+
const trustedStore = startupStore.root;
|
|
126
|
+
const projects = new Map();
|
|
127
|
+
async function trustProject(requested, store) {
|
|
128
|
+
const canonical = await fs.realpath(requested);
|
|
129
|
+
const identity = await fs.stat(requested);
|
|
130
|
+
if (!identity.isDirectory()) throw new Error('project_dir must be a real directory');
|
|
131
|
+
if (canonical !== trustedProjectRoot) {
|
|
132
|
+
const inStore = path.relative(trustedStore, canonical);
|
|
133
|
+
if (canonical.split(path.sep).includes('.aiwg') || !inStore
|
|
134
|
+
|| (inStore !== '..' && !inStore.startsWith(`..${path.sep}`) && !path.isAbsolute(inStore))) {
|
|
135
|
+
throw new Error('project_dir must not select a project inside an artifact store');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const configured = store ? undefined : await resolveProjectAiwgDir(canonical, { env: { ...process.env } });
|
|
139
|
+
return { canonical, identity, store: store || await pinArtifactRoot(configured, canonical) };
|
|
140
|
+
}
|
|
141
|
+
const startupProject = Promise.resolve(await trustProject(trustedProjectRoot, startupStore));
|
|
142
|
+
projects.set(trustedProjectRoot, startupProject);
|
|
143
|
+
const canonicalProjects = new Map([[trustedProjectRoot, startupProject]]);
|
|
144
|
+
async function artifactRoots(explicit) {
|
|
145
|
+
const requested = explicit ? path.resolve(trustedProjectRoot, explicit) : trustedProjectRoot;
|
|
146
|
+
// Key by the supplied project path, so a replacement cannot acquire fresh trust.
|
|
147
|
+
if (!projects.has(requested)) {
|
|
148
|
+
const canonical = await fs.realpath(requested);
|
|
149
|
+
if (!canonicalProjects.has(canonical)) canonicalProjects.set(canonical, trustProject(requested));
|
|
150
|
+
projects.set(requested, canonicalProjects.get(canonical));
|
|
151
|
+
}
|
|
152
|
+
const pinned = await projects.get(requested);
|
|
153
|
+
const canonical = await fs.realpath(requested);
|
|
154
|
+
const current = await fs.stat(requested);
|
|
155
|
+
if (canonical !== pinned.canonical || !current.isDirectory()
|
|
156
|
+
|| current.dev !== pinned.identity.dev || current.ino !== pinned.identity.ino) {
|
|
157
|
+
throw new Error('Project root changed since it was pinned');
|
|
158
|
+
}
|
|
159
|
+
return pinned.store;
|
|
160
|
+
}
|
|
78
161
|
|
|
79
162
|
// Tool: artifact-read
|
|
80
163
|
server.registerTool('artifact-read', {
|
|
@@ -82,14 +165,21 @@ export function createServer() {
|
|
|
82
165
|
description: 'Read artifact from .aiwg/ directory',
|
|
83
166
|
inputSchema: {
|
|
84
167
|
path: z.string().describe('Path relative to .aiwg/ (e.g., "requirements/UC-001.md")'),
|
|
85
|
-
project_dir: z.string().optional().describe('
|
|
168
|
+
project_dir: z.string().optional().describe('Real project directory outside artifact trees (defaults to server-start project; artifact store pinned on first use)')
|
|
86
169
|
}
|
|
87
170
|
}, async ({ path: artifactPath, project_dir }) => {
|
|
88
171
|
try {
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
172
|
+
const store = await artifactRoots(project_dir);
|
|
173
|
+
const { handle, close } = await openArtifact(store, artifactPath);
|
|
174
|
+
let content;
|
|
175
|
+
let completed = false;
|
|
176
|
+
try {
|
|
177
|
+
content = await handle.readFile('utf-8');
|
|
178
|
+
completed = true;
|
|
179
|
+
} finally {
|
|
180
|
+
const [closed] = await Promise.allSettled([close()]);
|
|
181
|
+
if (completed && closed.status === 'rejected') throw closed.reason;
|
|
182
|
+
}
|
|
93
183
|
return {
|
|
94
184
|
content: [{
|
|
95
185
|
type: 'text',
|
|
@@ -114,20 +204,22 @@ export function createServer() {
|
|
|
114
204
|
inputSchema: {
|
|
115
205
|
path: z.string().describe('Path relative to .aiwg/'),
|
|
116
206
|
content: z.string().describe('Artifact content'),
|
|
117
|
-
project_dir: z.string().optional().describe('
|
|
207
|
+
project_dir: z.string().optional().describe('Real project directory outside artifact trees (defaults to server-start project; artifact store pinned on first use)')
|
|
118
208
|
}
|
|
119
209
|
}, async ({ path: artifactPath, content, project_dir }) => {
|
|
120
210
|
try {
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
211
|
+
const store = await artifactRoots(project_dir);
|
|
212
|
+
const { handle, fullPath, commit, close } = await openArtifact(store, artifactPath, { write: true });
|
|
213
|
+
let completed = false;
|
|
214
|
+
try {
|
|
215
|
+
await handle.writeFile(content, 'utf-8');
|
|
216
|
+
await commit();
|
|
217
|
+
completed = true;
|
|
218
|
+
} finally {
|
|
219
|
+
// Close every owned descriptor; preserve any write/verification error.
|
|
220
|
+
const [closed] = await Promise.allSettled([close()]);
|
|
221
|
+
if (completed && closed.status === 'rejected') throw closed.reason;
|
|
222
|
+
}
|
|
131
223
|
|
|
132
224
|
return {
|
|
133
225
|
content: [{
|
|
@@ -161,12 +253,10 @@ export function createServer() {
|
|
|
161
253
|
}, async ({ template, variables = {} }) => {
|
|
162
254
|
try {
|
|
163
255
|
// Determine framework and template path
|
|
256
|
+
validateContainedPath(template);
|
|
164
257
|
const [framework, ...pathParts] = template.split('/');
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Read template
|
|
169
|
-
let content = await fs.readFile(templatePath, 'utf-8');
|
|
258
|
+
const relative = `agentic/code/frameworks/${frameworkName(framework)}/templates/${pathParts.join('/')}`;
|
|
259
|
+
let content = await readCorpus(relative);
|
|
170
260
|
|
|
171
261
|
// Simple variable substitution
|
|
172
262
|
for (const [key, value] of Object.entries(variables)) {
|
|
@@ -263,8 +353,7 @@ export function createServer() {
|
|
|
263
353
|
mimeType: 'application/json'
|
|
264
354
|
},
|
|
265
355
|
async () => {
|
|
266
|
-
const
|
|
267
|
-
const catalog = await scanDirectory(promptsDir, 'prompts');
|
|
356
|
+
const catalog = await scanCorpusDirectory('agentic/code/addons/aiwg-utils/prompts', 'prompts');
|
|
268
357
|
return {
|
|
269
358
|
contents: [{
|
|
270
359
|
uri: 'aiwg://prompts/catalog',
|
|
@@ -285,10 +374,9 @@ export function createServer() {
|
|
|
285
374
|
},
|
|
286
375
|
async () => {
|
|
287
376
|
const catalogs = {};
|
|
288
|
-
for (const
|
|
289
|
-
const templatesDir = path.join(fwPath, 'templates');
|
|
377
|
+
for (const fw of Object.keys(FRAMEWORKS)) {
|
|
290
378
|
try {
|
|
291
|
-
catalogs[fw] = await
|
|
379
|
+
catalogs[fw] = await scanCorpusDirectory(`agentic/code/frameworks/${fw}/templates`, 'templates');
|
|
292
380
|
} catch {
|
|
293
381
|
catalogs[fw] = [];
|
|
294
382
|
}
|
|
@@ -313,10 +401,9 @@ export function createServer() {
|
|
|
313
401
|
},
|
|
314
402
|
async () => {
|
|
315
403
|
const catalogs = {};
|
|
316
|
-
for (const
|
|
317
|
-
const agentsDir = path.join(fwPath, 'agents');
|
|
404
|
+
for (const fw of Object.keys(FRAMEWORKS)) {
|
|
318
405
|
try {
|
|
319
|
-
catalogs[fw] = await
|
|
406
|
+
catalogs[fw] = await scanCorpusDirectory(`agentic/code/frameworks/${fw}/agents`, 'agents');
|
|
320
407
|
} catch {
|
|
321
408
|
catalogs[fw] = [];
|
|
322
409
|
}
|
|
@@ -339,14 +426,9 @@ export function createServer() {
|
|
|
339
426
|
description: 'Retrieve specific AIWG prompt template'
|
|
340
427
|
},
|
|
341
428
|
async (uri, { category, name }) => {
|
|
342
|
-
const promptPath = path.join(
|
|
343
|
-
AIWG_ROOT,
|
|
344
|
-
'agentic/code/addons/aiwg-utils/prompts',
|
|
345
|
-
category,
|
|
346
|
-
`${name}.md`
|
|
347
|
-
);
|
|
348
429
|
try {
|
|
349
|
-
|
|
430
|
+
validateContainedPath(category); validateContainedPath(name);
|
|
431
|
+
const content = await readCorpus(`agentic/code/addons/aiwg-utils/prompts/${category}/${name}.md`);
|
|
350
432
|
return {
|
|
351
433
|
contents: [{
|
|
352
434
|
uri: uri.href,
|
|
@@ -373,14 +455,9 @@ export function createServer() {
|
|
|
373
455
|
description: 'Retrieve specific AIWG template'
|
|
374
456
|
},
|
|
375
457
|
async (uri, { framework, category, name }) => {
|
|
376
|
-
const templatePath = path.join(
|
|
377
|
-
FRAMEWORKS[framework] || FRAMEWORKS['sdlc-complete'],
|
|
378
|
-
'templates',
|
|
379
|
-
category,
|
|
380
|
-
`${name}.md`
|
|
381
|
-
);
|
|
382
458
|
try {
|
|
383
|
-
|
|
459
|
+
validateContainedPath(category); validateContainedPath(name);
|
|
460
|
+
const content = await readCorpus(`agentic/code/frameworks/${frameworkName(framework)}/templates/${category}/${name}.md`);
|
|
384
461
|
return {
|
|
385
462
|
contents: [{
|
|
386
463
|
uri: uri.href,
|
|
@@ -407,13 +484,9 @@ export function createServer() {
|
|
|
407
484
|
description: 'Retrieve specific AIWG agent definition'
|
|
408
485
|
},
|
|
409
486
|
async (uri, { framework, name }) => {
|
|
410
|
-
const agentPath = path.join(
|
|
411
|
-
FRAMEWORKS[framework] || FRAMEWORKS['sdlc-complete'],
|
|
412
|
-
'agents',
|
|
413
|
-
`${name}.md`
|
|
414
|
-
);
|
|
415
487
|
try {
|
|
416
|
-
|
|
488
|
+
validateContainedPath(name);
|
|
489
|
+
const content = await readCorpus(`agentic/code/frameworks/${frameworkName(framework)}/agents/${name}.md`);
|
|
417
490
|
return {
|
|
418
491
|
contents: [{
|
|
419
492
|
uri: uri.href,
|
|
@@ -579,39 +652,11 @@ If retry fails, prepare structured escalation:
|
|
|
579
652
|
// HELPER FUNCTIONS
|
|
580
653
|
// ============================================
|
|
581
654
|
|
|
582
|
-
/**
|
|
583
|
-
* Scan directory for files
|
|
584
|
-
*/
|
|
585
|
-
async function scanDirectory(dir, type) {
|
|
586
|
-
const results = [];
|
|
587
|
-
try {
|
|
588
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
589
|
-
for (const entry of entries) {
|
|
590
|
-
if (entry.isDirectory()) {
|
|
591
|
-
const subResults = await scanDirectory(path.join(dir, entry.name), type);
|
|
592
|
-
results.push(...subResults.map(r => ({
|
|
593
|
-
...r,
|
|
594
|
-
category: entry.name
|
|
595
|
-
})));
|
|
596
|
-
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
597
|
-
results.push({
|
|
598
|
-
name: entry.name.replace('.md', ''),
|
|
599
|
-
path: path.join(dir, entry.name),
|
|
600
|
-
uri: `aiwg://${type}/${entry.name.replace('.md', '')}`
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
} catch {
|
|
605
|
-
// Directory doesn't exist
|
|
606
|
-
}
|
|
607
|
-
return results;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
655
|
/**
|
|
611
656
|
* Start the MCP server with stdio transport
|
|
612
657
|
*/
|
|
613
658
|
export async function startServer() {
|
|
614
|
-
const server = createServer();
|
|
659
|
+
const server = await createServer();
|
|
615
660
|
const transport = new StdioServerTransport();
|
|
616
661
|
|
|
617
662
|
console.error('[AIWG MCP] Starting server...');
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Tests the server by spawning it and sending JSON-RPC messages via stdio.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { signalChild } from '../process/signal-child.mjs';
|
|
9
10
|
import { spawn } from 'child_process';
|
|
10
11
|
import { fileURLToPath } from 'url';
|
|
11
12
|
import path from 'path';
|
|
@@ -254,7 +255,7 @@ async function main() {
|
|
|
254
255
|
});
|
|
255
256
|
|
|
256
257
|
// Cleanup
|
|
257
|
-
server
|
|
258
|
+
signalChild(server);
|
|
258
259
|
|
|
259
260
|
// Summary
|
|
260
261
|
console.log('');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function tomlString(value: unknown): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Encode a complete TOML basic string using valid Unicode scalar values. */
|
|
2
|
+
export function tomlString(value) {
|
|
3
|
+
if (typeof value !== 'string' || [...value].some(char => {
|
|
4
|
+
const point = char.codePointAt(0);
|
|
5
|
+
return point >= 0xd800 && point <= 0xdfff;
|
|
6
|
+
})) throw new Error('TOML values must be strings containing valid Unicode scalar values');
|
|
7
|
+
// JSON escapes align with TOML basic strings except DEL must also be escaped.
|
|
8
|
+
return JSON.stringify(value).replace(/\u007f/g, '\\u007f');
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function stripMcpServers(text: string): string;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { parseTOML } from 'toml-eslint-parser';
|
|
2
|
+
|
|
3
|
+
/** Remove the root MCP subtree without interpreting strings as TOML structure. */
|
|
4
|
+
export function stripMcpServers(text) {
|
|
5
|
+
const fail = () => { throw new Error('Refusing to copy base Codex config: cannot safely classify TOML (malformed or unterminated structure)'); };
|
|
6
|
+
// Reuse the existing persistent-editor validator (no new dependency). The
|
|
7
|
+
// scanner below owns subtree removal; validation also catches ambiguous
|
|
8
|
+
// scalar syntax and duplicate definitions, beyond balanced delimiters.
|
|
9
|
+
try { parseTOML(text, { tomlVersion: '1.1.0' }); } catch { fail(); }
|
|
10
|
+
// A key path may use bare, literal, or escaped basic quoted components.
|
|
11
|
+
const keyPath = source => {
|
|
12
|
+
const parts = [];
|
|
13
|
+
let rest = source.trim();
|
|
14
|
+
while (rest) {
|
|
15
|
+
const match = /^(?:([A-Za-z0-9_-]+)|'([^'\r\n]*)'|"((?:[^"\\\r\n]|\\(?:[btnfr"\\]|u[\da-fA-F]{4}|U[\da-fA-F]{8}))*)")/.exec(rest);
|
|
16
|
+
if (!match) fail();
|
|
17
|
+
let key = match[1] ?? match[2];
|
|
18
|
+
if (key === undefined) {
|
|
19
|
+
key = match[3].replace(/\\(u[\da-fA-F]{4}|U[\da-fA-F]{8}|[btnfr"\\])/g, (_, escape) => {
|
|
20
|
+
if (escape[0] === 'u' || escape[0] === 'U') {
|
|
21
|
+
const code = Number.parseInt(escape.slice(1), 16);
|
|
22
|
+
if (code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff)) fail();
|
|
23
|
+
return String.fromCodePoint(code);
|
|
24
|
+
}
|
|
25
|
+
return { b: '\b', t: '\t', n: '\n', f: '\f', r: '\r', '"': '"', '\\': '\\' }[escape];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
parts.push(key);
|
|
29
|
+
rest = rest.slice(match[0].length).trim();
|
|
30
|
+
if (!rest) break;
|
|
31
|
+
if (!rest.startsWith('.')) fail();
|
|
32
|
+
rest = rest.slice(1).trim();
|
|
33
|
+
if (!rest) fail();
|
|
34
|
+
}
|
|
35
|
+
if (!parts.length) fail();
|
|
36
|
+
return parts;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let table = [];
|
|
40
|
+
let quote = null;
|
|
41
|
+
let multiline = false;
|
|
42
|
+
const brackets = [];
|
|
43
|
+
let record = '';
|
|
44
|
+
let drop = false;
|
|
45
|
+
const kept = [];
|
|
46
|
+
for (const line of text.split(/(?<=\n)/)) {
|
|
47
|
+
let start = 0;
|
|
48
|
+
if (!record) {
|
|
49
|
+
const trimmed = line.trim();
|
|
50
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
51
|
+
if (table[0] !== 'mcp_servers') kept.push(line);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (trimmed.startsWith('[')) {
|
|
55
|
+
// Header strings are single-line key components; scan their quotes so
|
|
56
|
+
// a bracket or hash inside a quoted name cannot terminate the header.
|
|
57
|
+
let headerQuote = null;
|
|
58
|
+
let end = line.length;
|
|
59
|
+
for (let i = 0; i < line.length; i++) {
|
|
60
|
+
const char = line[i];
|
|
61
|
+
if (headerQuote) {
|
|
62
|
+
if (headerQuote === '"' && char === '\\') { i++; continue; }
|
|
63
|
+
if (char === headerQuote) headerQuote = null;
|
|
64
|
+
} else if (char === '"' || char === "'") headerQuote = char;
|
|
65
|
+
else if (char === '#') { end = i; break; }
|
|
66
|
+
}
|
|
67
|
+
if (headerQuote) fail();
|
|
68
|
+
const header = line.slice(0, end).trim();
|
|
69
|
+
const array = header.startsWith('[[');
|
|
70
|
+
const width = array ? 2 : 1;
|
|
71
|
+
if (!header.endsWith(array ? ']]' : ']')) fail();
|
|
72
|
+
table = keyPath(header.slice(width, -width));
|
|
73
|
+
if (table[0] !== 'mcp_servers') kept.push(line);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
let keyQuote = null;
|
|
77
|
+
let equals = -1;
|
|
78
|
+
for (let i = 0; i < line.length; i++) {
|
|
79
|
+
const char = line[i];
|
|
80
|
+
if (keyQuote) {
|
|
81
|
+
if (keyQuote === '"' && char === '\\') { i++; continue; }
|
|
82
|
+
if (char === keyQuote) keyQuote = null;
|
|
83
|
+
} else if (char === '"' || char === "'") keyQuote = char;
|
|
84
|
+
else if (char === '=') { equals = i; break; }
|
|
85
|
+
else if (char === '#') break;
|
|
86
|
+
}
|
|
87
|
+
if (equals < 0 || keyQuote) fail();
|
|
88
|
+
const key = keyPath(line.slice(0, equals));
|
|
89
|
+
drop = table[0] === 'mcp_servers' || (table.length === 0 && key[0] === 'mcp_servers');
|
|
90
|
+
start = equals + 1;
|
|
91
|
+
if (!line.slice(start).split('#')[0].trim()) fail();
|
|
92
|
+
}
|
|
93
|
+
record += line;
|
|
94
|
+
for (let i = start; i < line.length; i++) {
|
|
95
|
+
const char = line[i];
|
|
96
|
+
if (quote) {
|
|
97
|
+
if (quote === '"' && char === '\\') {
|
|
98
|
+
// A backslash escapes the next character (including a multiline
|
|
99
|
+
// continuation); it cannot conceal a closing delimiter.
|
|
100
|
+
if (i + 1 >= line.length) fail();
|
|
101
|
+
i++;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (char === quote) {
|
|
105
|
+
if (!multiline) quote = null;
|
|
106
|
+
else if (line.slice(i, i + 3) === quote.repeat(3)) {
|
|
107
|
+
let run = 3;
|
|
108
|
+
while (line[i + run] === quote) run++;
|
|
109
|
+
if (run > 5) fail();
|
|
110
|
+
i += run - 1;
|
|
111
|
+
quote = null;
|
|
112
|
+
multiline = false;
|
|
113
|
+
}
|
|
114
|
+
} else if (!multiline && (char === '\n' || char === '\r')) fail();
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (char === '#') break;
|
|
118
|
+
if (char === '"' || char === "'") {
|
|
119
|
+
quote = char;
|
|
120
|
+
multiline = line.slice(i, i + 3) === char.repeat(3);
|
|
121
|
+
if (multiline) i += 2;
|
|
122
|
+
} else if (char === '[' || char === '{') brackets.push(char);
|
|
123
|
+
else if (char === ']' || char === '}') {
|
|
124
|
+
if (brackets.pop() !== (char === ']' ? '[' : '{')) fail();
|
|
125
|
+
} else if (char === '=' && !brackets.includes('{')) fail();
|
|
126
|
+
}
|
|
127
|
+
if (quote && !multiline) fail();
|
|
128
|
+
if (!quote && brackets.length === 0) {
|
|
129
|
+
if (!drop) kept.push(record);
|
|
130
|
+
record = '';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (quote || brackets.length || record) fail();
|
|
134
|
+
return kept.join('');
|
|
135
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ConfigWrite } from './config-file.mjs';
|
|
2
|
+
|
|
3
|
+
export interface ToolFilters {
|
|
4
|
+
deny: string[];
|
|
5
|
+
allow: string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ToolFilterPlan {
|
|
9
|
+
serverFields: Record<string, Record<string, unknown>>;
|
|
10
|
+
tomlLines: Record<string, string[]>;
|
|
11
|
+
topLevel: { tools?: Record<string, boolean> };
|
|
12
|
+
claudePermissions: { deny: string[]; allow: string[] } | null;
|
|
13
|
+
warnings: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function resolveToolFilters(
|
|
17
|
+
profile: { providerOverrides?: Record<string, { toolDeny?: string[]; toolAllow?: string[] }> } | undefined,
|
|
18
|
+
provider: string,
|
|
19
|
+
): ToolFilters;
|
|
20
|
+
export function hasToolFilters(filters: ToolFilters | undefined | null): boolean;
|
|
21
|
+
export function parseToolPattern(pattern: string): { server: string; tool: string } | null;
|
|
22
|
+
export function planToolFilters(provider: string, serverNames: string[], filters: ToolFilters): ToolFilterPlan;
|
|
23
|
+
export function applyJsonToolFilterPlan(
|
|
24
|
+
config: Record<string, unknown>,
|
|
25
|
+
serversKey: string,
|
|
26
|
+
plan: ToolFilterPlan,
|
|
27
|
+
): Record<string, unknown>;
|
|
28
|
+
export function claudeSettingsPath(projectDir?: string, scope?: 'user' | 'project'): string;
|
|
29
|
+
export interface ClaudePermissionOptions {
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
userScope?: boolean;
|
|
32
|
+
projectRoot?: string;
|
|
33
|
+
managedDir?: string;
|
|
34
|
+
sidecar?: boolean;
|
|
35
|
+
mcpPath?: string;
|
|
36
|
+
}
|
|
37
|
+
export function prepareClaudePermissions(
|
|
38
|
+
settingsPath: string,
|
|
39
|
+
permissions: { deny: string[]; allow: string[] },
|
|
40
|
+
options?: ClaudePermissionOptions,
|
|
41
|
+
): Promise<{ merged: Record<string, unknown>; active: boolean; warnings: string[]; writes: ConfigWrite[]; commit(): Promise<void> }>;
|
|
42
|
+
export function mergeClaudePermissions(
|
|
43
|
+
settingsPath: string,
|
|
44
|
+
permissions: { deny: string[]; allow: string[] },
|
|
45
|
+
options?: ClaudePermissionOptions,
|
|
46
|
+
): Promise<Record<string, unknown>>;
|