@agentxm/workspace-state 0.28.4-bootstrap.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -0
- package/README.md +11 -0
- package/dist/src/index.d.ts +72 -0
- package/dist/src/index.js +88 -0
- package/dist/src/knowledge/discovery-config.d.ts +12 -0
- package/dist/src/knowledge/discovery-config.js +9 -0
- package/dist/src/lockfile/accepted-registry-version.d.ts +12 -0
- package/dist/src/lockfile/accepted-registry-version.js +13 -0
- package/dist/src/lockfile/entry-fields.d.ts +189 -0
- package/dist/src/lockfile/entry-fields.js +89 -0
- package/dist/src/lockfile/errors.d.ts +48 -0
- package/dist/src/lockfile/errors.js +27 -0
- package/dist/src/lockfile/index.d.ts +18 -0
- package/dist/src/lockfile/index.js +16 -0
- package/dist/src/lockfile/lockfile.d.ts +2255 -0
- package/dist/src/lockfile/lockfile.js +235 -0
- package/dist/src/lockfile/resolved-version.d.ts +4 -0
- package/dist/src/lockfile/resolved-version.js +7 -0
- package/dist/src/lockfile/schema.d.ts +3062 -0
- package/dist/src/lockfile/schema.js +406 -0
- package/dist/src/schema/index.d.ts +3 -0
- package/dist/src/schema/index.js +2 -0
- package/dist/src/schema/read-and-validate-json-file.d.ts +20 -0
- package/dist/src/schema/read-and-validate-json-file.js +85 -0
- package/dist/src/schema/types.d.ts +26 -0
- package/dist/src/schema/types.js +2 -0
- package/dist/src/settings/errors.d.ts +22 -0
- package/dist/src/settings/errors.js +15 -0
- package/dist/src/settings/format-preserving-json.d.ts +40 -0
- package/dist/src/settings/format-preserving-json.js +80 -0
- package/dist/src/settings/index.d.ts +15 -0
- package/dist/src/settings/index.js +14 -0
- package/dist/src/settings/schema.d.ts +687 -0
- package/dist/src/settings/schema.js +977 -0
- package/dist/src/settings/settings.d.ts +38 -0
- package/dist/src/settings/settings.js +213 -0
- package/dist/src/testing.d.ts +17 -0
- package/dist/src/testing.js +17 -0
- package/dist/src/utils/atomic-write.d.ts +67 -0
- package/dist/src/utils/atomic-write.js +71 -0
- package/dist/src/utils/environment.d.ts +16 -0
- package/dist/src/utils/environment.js +19 -0
- package/dist/src/utils/path-safety.d.ts +25 -0
- package/dist/src/utils/path-safety.js +34 -0
- package/dist/src/utils/resolve-parent-symlinks.d.ts +16 -0
- package/dist/src/utils/resolve-parent-symlinks.js +36 -0
- package/dist/src/workspace/accepted-canonical-ref.d.ts +58 -0
- package/dist/src/workspace/accepted-canonical-ref.js +229 -0
- package/dist/src/workspace/artifact-change.d.ts +14 -0
- package/dist/src/workspace/artifact-change.js +18 -0
- package/dist/src/workspace/canonical-observation.d.ts +39 -0
- package/dist/src/workspace/canonical-observation.js +307 -0
- package/dist/src/workspace/configured-agent-outcome.d.ts +22 -0
- package/dist/src/workspace/configured-agent-outcome.js +33 -0
- package/dist/src/workspace/configured-agent-outcomes-provider.d.ts +50 -0
- package/dist/src/workspace/configured-agent-outcomes-provider.js +26 -0
- package/dist/src/workspace/configured-agent-outcomes.d.ts +48 -0
- package/dist/src/workspace/configured-agent-outcomes.js +113 -0
- package/dist/src/workspace/configured-entry-resolution/types.d.ts +32 -0
- package/dist/src/workspace/configured-entry-resolution/types.js +2 -0
- package/dist/src/workspace/configured-entry-resolution/workspace-ref.d.ts +32 -0
- package/dist/src/workspace/configured-entry-resolution/workspace-ref.js +176 -0
- package/dist/src/workspace/constants.d.ts +6 -0
- package/dist/src/workspace/constants.js +6 -0
- package/dist/src/workspace/create-symlink.d.ts +26 -0
- package/dist/src/workspace/create-symlink.js +87 -0
- package/dist/src/workspace/desired-pack-lock.d.ts +18 -0
- package/dist/src/workspace/desired-pack-lock.js +132 -0
- package/dist/src/workspace/desired-state-enabled.d.ts +18 -0
- package/dist/src/workspace/desired-state-enabled.js +16 -0
- package/dist/src/workspace/desired-state-graph.d.ts +114 -0
- package/dist/src/workspace/desired-state-graph.js +384 -0
- package/dist/src/workspace/desired-state-problem-text.d.ts +6 -0
- package/dist/src/workspace/desired-state-problem-text.js +27 -0
- package/dist/src/workspace/errors.d.ts +184 -0
- package/dist/src/workspace/errors.js +79 -0
- package/dist/src/workspace/extension-name.d.ts +28 -0
- package/dist/src/workspace/extension-name.js +66 -0
- package/dist/src/workspace/extension-paths.d.ts +82 -0
- package/dist/src/workspace/extension-paths.js +172 -0
- package/dist/src/workspace/footprint-recorder.d.ts +30 -0
- package/dist/src/workspace/footprint-recorder.js +32 -0
- package/dist/src/workspace/layout.d.ts +43 -0
- package/dist/src/workspace/layout.js +164 -0
- package/dist/src/workspace/lock-entry-to-ref.d.ts +40 -0
- package/dist/src/workspace/lock-entry-to-ref.js +433 -0
- package/dist/src/workspace/lock-entry-to-source-params.d.ts +26 -0
- package/dist/src/workspace/lock-entry-to-source-params.js +81 -0
- package/dist/src/workspace/locked-entries.d.ts +30 -0
- package/dist/src/workspace/locked-entries.js +34 -0
- package/dist/src/workspace/materialized-file-target.d.ts +14 -0
- package/dist/src/workspace/materialized-file-target.js +14 -0
- package/dist/src/workspace/materialized-tree.d.ts +23 -0
- package/dist/src/workspace/materialized-tree.js +90 -0
- package/dist/src/workspace/mcp-entry-semantics.d.ts +31 -0
- package/dist/src/workspace/mcp-entry-semantics.js +60 -0
- package/dist/src/workspace/observed-installed.d.ts +9 -0
- package/dist/src/workspace/observed-installed.js +9 -0
- package/dist/src/workspace/pack-manifest-content-identity.d.ts +12 -0
- package/dist/src/workspace/pack-manifest-content-identity.js +20 -0
- package/dist/src/workspace/pack-paths.d.ts +24 -0
- package/dist/src/workspace/pack-paths.js +16 -0
- package/dist/src/workspace/package-hash.d.ts +25 -0
- package/dist/src/workspace/package-hash.js +45 -0
- package/dist/src/workspace/paths.d.ts +24 -0
- package/dist/src/workspace/paths.js +52 -0
- package/dist/src/workspace/read-model/__fixtures__/builder.d.ts +199 -0
- package/dist/src/workspace/read-model/__fixtures__/builder.js +588 -0
- package/dist/src/workspace/read-model/__fixtures__/decoders.d.ts +15 -0
- package/dist/src/workspace/read-model/__fixtures__/decoders.js +15 -0
- package/dist/src/workspace/read-model/__fixtures__/occurrences.d.ts +72 -0
- package/dist/src/workspace/read-model/__fixtures__/occurrences.js +134 -0
- package/dist/src/workspace/read-model/__fixtures__/scenario-harness.d.ts +99 -0
- package/dist/src/workspace/read-model/__fixtures__/scenario-harness.js +142 -0
- package/dist/src/workspace/read-model/__fixtures__/test-layer.d.ts +60 -0
- package/dist/src/workspace/read-model/__fixtures__/test-layer.js +57 -0
- package/dist/src/workspace/read-model/agent-presence.d.ts +32 -0
- package/dist/src/workspace/read-model/agent-presence.js +21 -0
- package/dist/src/workspace/read-model/agent-root-resolver.d.ts +38 -0
- package/dist/src/workspace/read-model/agent-root-resolver.js +35 -0
- package/dist/src/workspace/read-model/agents/index.d.ts +38 -0
- package/dist/src/workspace/read-model/agents/index.js +45 -0
- package/dist/src/workspace/read-model/agents/shared.d.ts +27 -0
- package/dist/src/workspace/read-model/agents/shared.js +63 -0
- package/dist/src/workspace/read-model/agents/types.d.ts +133 -0
- package/dist/src/workspace/read-model/agents/types.js +51 -0
- package/dist/src/workspace/read-model/diagnostics.d.ts +18 -0
- package/dist/src/workspace/read-model/diagnostics.js +14 -0
- package/dist/src/workspace/read-model/discovery/index.d.ts +5 -0
- package/dist/src/workspace/read-model/discovery/index.js +5 -0
- package/dist/src/workspace/read-model/discovery/plugin-manifests.d.ts +16 -0
- package/dist/src/workspace/read-model/discovery/plugin-manifests.js +168 -0
- package/dist/src/workspace/read-model/discovery/skills.d.ts +58 -0
- package/dist/src/workspace/read-model/discovery/skills.js +263 -0
- package/dist/src/workspace/read-model/discovery/subagents.d.ts +37 -0
- package/dist/src/workspace/read-model/discovery/subagents.js +48 -0
- package/dist/src/workspace/read-model/errors.d.ts +93 -0
- package/dist/src/workspace/read-model/errors.js +30 -0
- package/dist/src/workspace/read-model/extensions/actual-helpers.d.ts +4 -0
- package/dist/src/workspace/read-model/extensions/actual-helpers.js +4 -0
- package/dist/src/workspace/read-model/extensions/hook.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/hook.js +119 -0
- package/dist/src/workspace/read-model/extensions/index.d.ts +19 -0
- package/dist/src/workspace/read-model/extensions/index.js +43 -0
- package/dist/src/workspace/read-model/extensions/indexByName.d.ts +31 -0
- package/dist/src/workspace/read-model/extensions/indexByName.js +30 -0
- package/dist/src/workspace/read-model/extensions/inventory.d.ts +99 -0
- package/dist/src/workspace/read-model/extensions/inventory.js +111 -0
- package/dist/src/workspace/read-model/extensions/knowledge.d.ts +101 -0
- package/dist/src/workspace/read-model/extensions/knowledge.js +121 -0
- package/dist/src/workspace/read-model/extensions/mcp-server.d.ts +106 -0
- package/dist/src/workspace/read-model/extensions/mcp-server.js +122 -0
- package/dist/src/workspace/read-model/extensions/pack.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/pack.js +123 -0
- package/dist/src/workspace/read-model/extensions/package-root.d.ts +39 -0
- package/dist/src/workspace/read-model/extensions/package-root.js +48 -0
- package/dist/src/workspace/read-model/extensions/projection.d.ts +137 -0
- package/dist/src/workspace/read-model/extensions/projection.js +180 -0
- package/dist/src/workspace/read-model/extensions/rule.d.ts +104 -0
- package/dist/src/workspace/read-model/extensions/rule.js +113 -0
- package/dist/src/workspace/read-model/extensions/skill.d.ts +170 -0
- package/dist/src/workspace/read-model/extensions/skill.js +148 -0
- package/dist/src/workspace/read-model/extensions/subagent.d.ts +97 -0
- package/dist/src/workspace/read-model/extensions/subagent.js +120 -0
- package/dist/src/workspace/read-model/scanners/agent-dir.d.ts +49 -0
- package/dist/src/workspace/read-model/scanners/agent-dir.js +180 -0
- package/dist/src/workspace/read-model/scanners/agent-root.d.ts +73 -0
- package/dist/src/workspace/read-model/scanners/agent-root.js +148 -0
- package/dist/src/workspace/read-model/scanners/agent-settings.d.ts +43 -0
- package/dist/src/workspace/read-model/scanners/agent-settings.js +54 -0
- package/dist/src/workspace/read-model/scanners/canonical-extensions.d.ts +48 -0
- package/dist/src/workspace/read-model/scanners/canonical-extensions.js +237 -0
- package/dist/src/workspace/read-model/scanners/fs-helpers.d.ts +63 -0
- package/dist/src/workspace/read-model/scanners/fs-helpers.js +106 -0
- package/dist/src/workspace/read-model/scanners/index.d.ts +15 -0
- package/dist/src/workspace/read-model/scanners/index.js +34 -0
- package/dist/src/workspace/read-model/scanners/mcp-config.d.ts +47 -0
- package/dist/src/workspace/read-model/scanners/mcp-config.js +212 -0
- package/dist/src/workspace/read-model/scanners/types.d.ts +170 -0
- package/dist/src/workspace/read-model/scanners/types.js +86 -0
- package/dist/src/workspace/read-model/service.d.ts +103 -0
- package/dist/src/workspace/read-model/service.js +391 -0
- package/dist/src/workspace/read-model/state.d.ts +35 -0
- package/dist/src/workspace/read-model/state.js +97 -0
- package/dist/src/workspace/read-model/types.d.ts +75 -0
- package/dist/src/workspace/read-model/types.js +26 -0
- package/dist/src/workspace/read-model-record-readers.d.ts +34 -0
- package/dist/src/workspace/read-model-record-readers.js +467 -0
- package/dist/src/workspace/read-model-record-rows.d.ts +45 -0
- package/dist/src/workspace/read-model-record-rows.js +33 -0
- package/dist/src/workspace/read-model-record-types.d.ts +45 -0
- package/dist/src/workspace/read-model-record-types.js +13 -0
- package/dist/src/workspace/remove-if-exists.d.ts +13 -0
- package/dist/src/workspace/remove-if-exists.js +26 -0
- package/dist/src/workspace/rendered-files.d.ts +53 -0
- package/dist/src/workspace/rendered-files.js +50 -0
- package/dist/src/workspace/scope-refusal.d.ts +26 -0
- package/dist/src/workspace/scope-refusal.js +29 -0
- package/dist/src/workspace/service-interface.d.ts +479 -0
- package/dist/src/workspace/service-interface.js +27 -0
- package/dist/src/workspace/service.d.ts +1665 -0
- package/dist/src/workspace/service.js +1263 -0
- package/dist/src/workspace/setup-scope-support.d.ts +27 -0
- package/dist/src/workspace/setup-scope-support.js +299 -0
- package/dist/src/workspace/skill-paths.d.ts +33 -0
- package/dist/src/workspace/skill-paths.js +14 -0
- package/dist/src/workspace/source-metadata.d.ts +7 -0
- package/dist/src/workspace/source-metadata.js +10 -0
- package/dist/src/workspace/source-to-lock-entry.d.ts +32 -0
- package/dist/src/workspace/source-to-lock-entry.js +68 -0
- package/dist/src/workspace/test-stubs.d.ts +144 -0
- package/dist/src/workspace/test-stubs.js +412 -0
- package/dist/src/workspace/transaction.d.ts +218 -0
- package/dist/src/workspace/transaction.js +177 -0
- package/package.json +57 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP-config scanner: plans physical targets from the capability catalog,
|
|
3
|
+
* reads each physical file once, and emits one occurrence per declared server.
|
|
4
|
+
* Shared targets remain shared observations; agent-native targets retain the
|
|
5
|
+
* exact agent id whose private surface supplied the observation.
|
|
6
|
+
*
|
|
7
|
+
* Per-file partial failures (unreadable config, bad JSON, schema-incompatible
|
|
8
|
+
* payload) become diagnostic warnings rather than errors. The error channel
|
|
9
|
+
* stays empty.
|
|
10
|
+
*
|
|
11
|
+
* MCP config layout:
|
|
12
|
+
*
|
|
13
|
+
* ```json
|
|
14
|
+
* {
|
|
15
|
+
* "mcpServers": {
|
|
16
|
+
* "<server-name>": { ... }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* The scanner emits one occurrence per `<server-name>` and captures each
|
|
22
|
+
* record-shaped server payload for import/adoption flows.
|
|
23
|
+
*/
|
|
24
|
+
import * as Effect from "effect/Effect";
|
|
25
|
+
import * as Option from "effect/Option";
|
|
26
|
+
import * as Schema from "effect/Schema";
|
|
27
|
+
import { parse } from "jsonc-parser";
|
|
28
|
+
import { getHome } from "../../../utils/environment.js";
|
|
29
|
+
import { AGENTS } from "@agentxm/extension-model/unstable/agents/registry";
|
|
30
|
+
import { CONFIGURABLE_AGENTS_BY_ID, } from "@agentxm/extension-model/unstable/agent-capabilities";
|
|
31
|
+
import { ExtensionNameSchema, } from "@agentxm/extension-model/unstable/extensions/common";
|
|
32
|
+
import { makeAbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
33
|
+
import { isPathSafe } from "../../../utils/path-safety.js";
|
|
34
|
+
const SCANNER_NAME = "mcp-config";
|
|
35
|
+
/**
|
|
36
|
+
* Closure helper: returns the dependency-closed scanner effect.
|
|
37
|
+
*/
|
|
38
|
+
export const makeMcpConfigScanner = (deps) => scanMcpConfig(deps);
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Helpers: read + parse + extract server names
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* Minimum shape the scanner needs from an MCP config file: a top-level
|
|
44
|
+
* object that may contain an agent-configured server record. Per-server payloads stay
|
|
45
|
+
* opaque (`Schema.Unknown`) — Phase 7's MCP server subject module decodes
|
|
46
|
+
* them through its own schema. The scanner only emits one occurrence per
|
|
47
|
+
* server name.
|
|
48
|
+
*/
|
|
49
|
+
const McpConfigShapeSchema = Schema.Record(Schema.String, Schema.Unknown);
|
|
50
|
+
const decodeMcpConfigShape = Schema.decodeUnknownEffect(McpConfigShapeSchema);
|
|
51
|
+
// MCP configs can contain arbitrary, user-authored server names. Only names that
|
|
52
|
+
// are valid AXM extension names can be managed; skip the rest instead of letting
|
|
53
|
+
// a non-conforming name (e.g. uppercase or underscore) crash the whole scan.
|
|
54
|
+
const decodeExtensionNameOption = Schema.decodeUnknownOption(ExtensionNameSchema);
|
|
55
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56
|
+
const extractServers = (decoded, serversKey) => !isRecord(decoded[serversKey])
|
|
57
|
+
? []
|
|
58
|
+
: Object.entries(decoded[serversKey]).flatMap(([name, config]) => {
|
|
59
|
+
if (!isRecord(config))
|
|
60
|
+
return [];
|
|
61
|
+
const decodedName = decodeExtensionNameOption(name);
|
|
62
|
+
return Option.isNone(decodedName) ? [] : [{ name: decodedName.value, config }];
|
|
63
|
+
});
|
|
64
|
+
const readMcpConfig = (fs, diagnostics, filePath) => Effect.gen(function* () {
|
|
65
|
+
const exists = yield* Effect.result(fs.exists(filePath));
|
|
66
|
+
if (exists._tag === "Failure") {
|
|
67
|
+
yield* diagnostics.append({
|
|
68
|
+
source: "scanner",
|
|
69
|
+
message: `${SCANNER_NAME}: cannot stat ${filePath}`,
|
|
70
|
+
path: filePath,
|
|
71
|
+
code: "scanner-io",
|
|
72
|
+
});
|
|
73
|
+
return Option.none();
|
|
74
|
+
}
|
|
75
|
+
if (!exists.success)
|
|
76
|
+
return Option.none();
|
|
77
|
+
const read = yield* Effect.result(fs.readFileString(filePath));
|
|
78
|
+
if (read._tag === "Failure") {
|
|
79
|
+
yield* diagnostics.append({
|
|
80
|
+
source: "scanner",
|
|
81
|
+
message: `${SCANNER_NAME}: cannot read ${filePath}`,
|
|
82
|
+
path: filePath,
|
|
83
|
+
code: "scanner-io",
|
|
84
|
+
});
|
|
85
|
+
return Option.none();
|
|
86
|
+
}
|
|
87
|
+
const parsed = yield* Effect.result(Effect.try({
|
|
88
|
+
try: () => {
|
|
89
|
+
const errors = [];
|
|
90
|
+
const value = parse(read.success, errors, { allowTrailingComma: true });
|
|
91
|
+
if (errors.length > 0)
|
|
92
|
+
throw errors;
|
|
93
|
+
return value;
|
|
94
|
+
},
|
|
95
|
+
catch: (cause) => ({ cause }),
|
|
96
|
+
}));
|
|
97
|
+
if (parsed._tag === "Failure") {
|
|
98
|
+
yield* diagnostics.append({
|
|
99
|
+
source: "scanner",
|
|
100
|
+
message: `${SCANNER_NAME}: cannot parse JSON at ${filePath}`,
|
|
101
|
+
path: filePath,
|
|
102
|
+
code: "scanner-parse",
|
|
103
|
+
});
|
|
104
|
+
return Option.none();
|
|
105
|
+
}
|
|
106
|
+
const decoded = yield* Effect.result(decodeMcpConfigShape(parsed.success));
|
|
107
|
+
if (decoded._tag === "Failure") {
|
|
108
|
+
yield* diagnostics.append({
|
|
109
|
+
source: "scanner",
|
|
110
|
+
message: `${SCANNER_NAME}: invalid MCP config shape at ${filePath}: ${decoded.failure.message}`,
|
|
111
|
+
path: filePath,
|
|
112
|
+
code: "scanner-parse",
|
|
113
|
+
});
|
|
114
|
+
return Option.none();
|
|
115
|
+
}
|
|
116
|
+
return Option.some(decoded.success);
|
|
117
|
+
});
|
|
118
|
+
const readMcpConfigCached = (cache, fs, diagnostics, filePath) => {
|
|
119
|
+
const existing = cache.get(filePath);
|
|
120
|
+
if (existing !== undefined)
|
|
121
|
+
return Effect.succeed(existing);
|
|
122
|
+
return readMcpConfig(fs, diagnostics, filePath).pipe(Effect.tap((decoded) => Effect.sync(() => {
|
|
123
|
+
cache.set(filePath, decoded);
|
|
124
|
+
})));
|
|
125
|
+
};
|
|
126
|
+
const hasMcpConfig = (capability) => capability.axm.writer !== null;
|
|
127
|
+
const isCapabilityAgentId = (id) => id in CONFIGURABLE_AGENTS_BY_ID;
|
|
128
|
+
const capabilityFor = (descriptor) => {
|
|
129
|
+
if (!isCapabilityAgentId(descriptor.id))
|
|
130
|
+
return undefined;
|
|
131
|
+
const agent = CONFIGURABLE_AGENTS_BY_ID[descriptor.id];
|
|
132
|
+
const capability = agent.capabilities["mcp-server"];
|
|
133
|
+
return hasMcpConfig(capability) ? capability : undefined;
|
|
134
|
+
};
|
|
135
|
+
const surfacePlanKey = (plan) => plan.surface._tag === "shared"
|
|
136
|
+
? `shared:${plan.target.scope}:${plan.target.path}`
|
|
137
|
+
: `agent:${plan.surface.agentId}:${plan.target.scope}:${plan.target.path}`;
|
|
138
|
+
const planMcpSurfaces = (scope, registry) => {
|
|
139
|
+
const plans = new Map();
|
|
140
|
+
for (const descriptor of Object.values(registry)) {
|
|
141
|
+
const capability = capabilityFor(descriptor);
|
|
142
|
+
if (capability === undefined)
|
|
143
|
+
continue;
|
|
144
|
+
for (const target of capability.axm.writer.config.targets) {
|
|
145
|
+
if (target.scope !== scope)
|
|
146
|
+
continue;
|
|
147
|
+
const surface = target.attribution === "shared"
|
|
148
|
+
? { _tag: "shared" }
|
|
149
|
+
: { _tag: "agent", agentId: descriptor.id };
|
|
150
|
+
const plan = {
|
|
151
|
+
surface,
|
|
152
|
+
target,
|
|
153
|
+
serversKey: capability.axm.writer.config.serversKey,
|
|
154
|
+
};
|
|
155
|
+
const key = surfacePlanKey(plan);
|
|
156
|
+
if (!plans.has(key))
|
|
157
|
+
plans.set(key, plan);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return [...plans.values()];
|
|
161
|
+
};
|
|
162
|
+
const resolveMcpConfigTargetPath = (deps, target) => Effect.gen(function* () {
|
|
163
|
+
const { path, workspaceRoot, diagnostics } = deps;
|
|
164
|
+
const home = yield* getHome;
|
|
165
|
+
const configPath = target.scope === "user"
|
|
166
|
+
? target.path.startsWith("~/")
|
|
167
|
+
? path.join(home, target.path.slice(2))
|
|
168
|
+
: path.resolve(home, target.path)
|
|
169
|
+
: path.resolve(workspaceRoot, target.path);
|
|
170
|
+
if (target.scope === "project" && !isPathSafe(path, workspaceRoot, configPath)) {
|
|
171
|
+
yield* diagnostics.append({
|
|
172
|
+
source: "scanner",
|
|
173
|
+
message: `${SCANNER_NAME}: MCP config target escapes workspace root: ${target.path}`,
|
|
174
|
+
path: configPath,
|
|
175
|
+
code: "scanner-config",
|
|
176
|
+
});
|
|
177
|
+
return Option.none();
|
|
178
|
+
}
|
|
179
|
+
return Option.some(configPath);
|
|
180
|
+
});
|
|
181
|
+
const scanMcpSurface = (deps, plan, cache) => Effect.gen(function* () {
|
|
182
|
+
const { fs, path, scope, diagnostics } = deps;
|
|
183
|
+
const filePathOpt = yield* resolveMcpConfigTargetPath(deps, plan.target);
|
|
184
|
+
if (Option.isNone(filePathOpt))
|
|
185
|
+
return [];
|
|
186
|
+
const decoded = yield* readMcpConfigCached(cache, fs, diagnostics, filePathOpt.value);
|
|
187
|
+
if (Option.isNone(decoded))
|
|
188
|
+
return [];
|
|
189
|
+
const servers = extractServers(decoded.value, plan.serversKey);
|
|
190
|
+
const contentLocation = makeAbsolutePath(path, filePathOpt.value);
|
|
191
|
+
return servers.map((server) => ({
|
|
192
|
+
_tag: "mcp-config",
|
|
193
|
+
scope,
|
|
194
|
+
surface: plan.surface,
|
|
195
|
+
name: server.name,
|
|
196
|
+
contentLocation,
|
|
197
|
+
config: server.config,
|
|
198
|
+
}));
|
|
199
|
+
});
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// Scanner body
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
const scanMcpConfig = Effect.fn("workspace.read-model.scanner.mcp-config")(function* (deps) {
|
|
204
|
+
const registry = deps.agentRegistry ?? AGENTS;
|
|
205
|
+
const cache = new Map();
|
|
206
|
+
const plans = planMcpSurfaces(deps.scope, registry);
|
|
207
|
+
const occurrences = yield* Effect.forEach(plans, (plan) => scanMcpSurface(deps, plan, cache), {
|
|
208
|
+
concurrency: 1,
|
|
209
|
+
});
|
|
210
|
+
return occurrences.flat();
|
|
211
|
+
});
|
|
212
|
+
//# sourceMappingURL=mcp-config.js.map
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared scanner types: occurrence shape, common per-occurrence fields, and
|
|
3
|
+
* scanner-tier origin discriminators.
|
|
4
|
+
*
|
|
5
|
+
* Per Decision 5 of the workspace read-model design, scanner output is
|
|
6
|
+
* occurrence-shaped (`ReadonlyArray<Occurrence>`) — one entry per observable
|
|
7
|
+
* physical materialization. There is no central `DetectionOrigin` union; each
|
|
8
|
+
* scanner exports the discriminator it observes, and per-subject modules in
|
|
9
|
+
* Phase 7 map these scanner-tier discriminators into subject-specific origin
|
|
10
|
+
* unions.
|
|
11
|
+
*
|
|
12
|
+
* Identity of an actual entry is `(scope, type | agentId, origin, contentLocation)`.
|
|
13
|
+
* Two scanner paths observing the same physical occurrence collapse to one
|
|
14
|
+
* entry; two distinct physical paths under the same name produce two entries
|
|
15
|
+
* with different identities.
|
|
16
|
+
*/
|
|
17
|
+
import * as Option from "effect/Option";
|
|
18
|
+
import type { ExtensionName, ExtensionType } from "@agentxm/extension-model/unstable/extensions/common";
|
|
19
|
+
import type { Handle } from "@agentxm/extension-model/unstable/extensions/handle";
|
|
20
|
+
import type { AgentId } from "@agentxm/extension-model/unstable/agents/types";
|
|
21
|
+
import type { AbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
22
|
+
import type { Scope } from "../types.js";
|
|
23
|
+
/**
|
|
24
|
+
* Origin tag for an occurrence emitted by the canonical-extensions scanner.
|
|
25
|
+
* `canonical-axm` covers authored or owner-qualified packages;
|
|
26
|
+
* `external-axm` covers user-scope external-layout packages.
|
|
27
|
+
*/
|
|
28
|
+
export type CanonicalExtensionOriginKind = "canonical-axm" | "external-axm";
|
|
29
|
+
/**
|
|
30
|
+
* One canonical package materialization observed in an authored root,
|
|
31
|
+
* `agent_extensions/`, or the user-scope `agent_extensions/` root.
|
|
32
|
+
*
|
|
33
|
+
* Fields:
|
|
34
|
+
*
|
|
35
|
+
* - `scope` — the scoping tier this occurrence belongs to (project | user).
|
|
36
|
+
* - `type` — the subject extension type.
|
|
37
|
+
* - `origin` — scanner-tier origin (canonical-axm | external-axm).
|
|
38
|
+
* - `name` — the subject's directory name (last segment under owner/type).
|
|
39
|
+
* - `owner` — the registry-owner prefix for canonical AXM, `null` for external.
|
|
40
|
+
* - `contentLocation` — absolute path on the synthesized FS to the subject's
|
|
41
|
+
* content root (the directory itself, not a file inside it).
|
|
42
|
+
* - `pathSegments` — `contentLocation` split via the `Path` service. Subject
|
|
43
|
+
* modules reach for this when they need to derive parent paths
|
|
44
|
+
* (`packageRoot`, etc.) without re-parsing the string. Cross-platform safe.
|
|
45
|
+
* - `subjectFile` — `Some(path)` when the subject type has a canonical
|
|
46
|
+
* primary content file (e.g., `<dir>/SKILL.md` for skills). `None` for
|
|
47
|
+
* subject types that do not use a fixed primary file (mcp-server, file,
|
|
48
|
+
* rule, pack).
|
|
49
|
+
* - `subjectFileExists` — `true` if the scanner probed `subjectFile` and found
|
|
50
|
+
* it present. Always `false` when `subjectFile` is `None`. Subject modules
|
|
51
|
+
* consume this rather than hardcoding presence.
|
|
52
|
+
*/
|
|
53
|
+
export interface CanonicalExtensionOccurrence {
|
|
54
|
+
readonly _tag: "canonical-extension";
|
|
55
|
+
readonly scope: Scope;
|
|
56
|
+
readonly type: ExtensionType;
|
|
57
|
+
readonly origin: CanonicalExtensionOriginKind;
|
|
58
|
+
readonly name: ExtensionName;
|
|
59
|
+
readonly owner: Handle | null;
|
|
60
|
+
readonly contentLocation: AbsolutePath;
|
|
61
|
+
readonly pathSegments: ReadonlyArray<string>;
|
|
62
|
+
readonly subjectFile: Option.Option<AbsolutePath>;
|
|
63
|
+
readonly subjectFileExists: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Subject types renderable into per-agent directories. Only the subjects
|
|
67
|
+
* actually observed by the v1 scanner are listed; rules render through
|
|
68
|
+
* subject-specific dirs that the agent registry does not currently encode and
|
|
69
|
+
* are therefore out of scope for the agent-dir scanner.
|
|
70
|
+
*/
|
|
71
|
+
export type AgentDirSubjectType = "skill" | "subagent";
|
|
72
|
+
/**
|
|
73
|
+
* One materialization observed under a per-agent rendered directory
|
|
74
|
+
* (`.claude/skills/`, `.codex/agents/`, `.roomodes`,
|
|
75
|
+
* etc.). The origin discriminator carries the agent id so per-subject modules
|
|
76
|
+
* can map cleanly into agent-specific origins.
|
|
77
|
+
*
|
|
78
|
+
* Structural fields mirror `CanonicalExtensionOccurrence`:
|
|
79
|
+
*
|
|
80
|
+
* - `pathSegments` — `contentLocation` split via the `Path` service.
|
|
81
|
+
* - `subjectFile` — `Some(path)` when the subject type has a canonical
|
|
82
|
+
* primary file (skill → `<dir>/SKILL.md`, command → `<dir>/${name}.md`,
|
|
83
|
+
* subagent dir → `<dir>/${name}.md`). For single-file subagent surfaces
|
|
84
|
+
* (e.g., `.roomodes`) the `subjectFile` is the `contentLocation` itself.
|
|
85
|
+
* - `subjectFileExists` — `true` if the scanner probed `subjectFile` and
|
|
86
|
+
* found it present. Always `false` when `subjectFile` is `None`. For
|
|
87
|
+
* single-file subagents this is always `true` because presence of the file
|
|
88
|
+
* is what produced the occurrence.
|
|
89
|
+
*/
|
|
90
|
+
export interface AgentDirOccurrence {
|
|
91
|
+
readonly _tag: "agent-dir";
|
|
92
|
+
readonly scope: Scope;
|
|
93
|
+
readonly type: AgentDirSubjectType;
|
|
94
|
+
readonly agentId: AgentId;
|
|
95
|
+
/** Primary write path or the catalog status of an additional read-only path. */
|
|
96
|
+
readonly readPathStatus?: "primary" | "canonical" | "compat" | "deprecated";
|
|
97
|
+
readonly name: string;
|
|
98
|
+
readonly contentLocation: AbsolutePath;
|
|
99
|
+
readonly pathSegments: ReadonlyArray<string>;
|
|
100
|
+
readonly subjectFile: Option.Option<AbsolutePath>;
|
|
101
|
+
readonly subjectFileExists: boolean;
|
|
102
|
+
}
|
|
103
|
+
/** Physical MCP configuration surface that supplied an observation. */
|
|
104
|
+
export type McpConfigSurface = {
|
|
105
|
+
readonly _tag: "shared";
|
|
106
|
+
} | {
|
|
107
|
+
readonly _tag: "agent";
|
|
108
|
+
readonly agentId: AgentId;
|
|
109
|
+
};
|
|
110
|
+
/** One MCP server entry observed on one physical configuration surface. */
|
|
111
|
+
export interface McpConfigOccurrence {
|
|
112
|
+
readonly _tag: "mcp-config";
|
|
113
|
+
readonly scope: Scope;
|
|
114
|
+
readonly surface: McpConfigSurface;
|
|
115
|
+
readonly name: ExtensionName;
|
|
116
|
+
readonly contentLocation: AbsolutePath;
|
|
117
|
+
readonly config: Readonly<Record<string, unknown>>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* One agent-native settings file observed on disk (e.g.,
|
|
121
|
+
* `.claude/settings.json`).
|
|
122
|
+
*
|
|
123
|
+
* `contentLocation` is the absolute path to the settings file. There is no
|
|
124
|
+
* "name" in the subject sense — the file itself is the materialization, keyed
|
|
125
|
+
* by `agentId`.
|
|
126
|
+
*/
|
|
127
|
+
export interface AgentSettingsOccurrence {
|
|
128
|
+
readonly _tag: "agent-settings";
|
|
129
|
+
readonly scope: Scope;
|
|
130
|
+
readonly agentId: AgentId;
|
|
131
|
+
readonly contentLocation: AbsolutePath;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Stable occurrence identity tuple. The four-part shape mirrors the spec's
|
|
135
|
+
* "Actual entries carry stable occurrence identity" requirement:
|
|
136
|
+
* `(scope, type | agentId, origin, contentLocation)`. `subjectKey` is the
|
|
137
|
+
* subject discriminator — extension type for extension occurrences, agent id
|
|
138
|
+
* for agent occurrences.
|
|
139
|
+
*/
|
|
140
|
+
export interface OccurrenceIdentity {
|
|
141
|
+
readonly scope: Scope;
|
|
142
|
+
readonly subjectKey: string;
|
|
143
|
+
readonly origin: string;
|
|
144
|
+
readonly contentLocation: string;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* All occurrence shapes scanners emit. The discriminator on `_tag` lets
|
|
148
|
+
* downstream subject modules narrow without a centralized origin union.
|
|
149
|
+
*/
|
|
150
|
+
export type ScannerOccurrence = CanonicalExtensionOccurrence | AgentDirOccurrence | McpConfigOccurrence | AgentSettingsOccurrence;
|
|
151
|
+
/**
|
|
152
|
+
* Compute the identity tuple for one occurrence. Two scanner paths observing
|
|
153
|
+
* the same physical occurrence produce equal identities; distinct physical
|
|
154
|
+
* paths under the same name produce different identities.
|
|
155
|
+
*/
|
|
156
|
+
export declare const occurrenceIdentity: (occurrence: ScannerOccurrence) => OccurrenceIdentity;
|
|
157
|
+
/**
|
|
158
|
+
* Serialize an `OccurrenceIdentity` to a stable string key. Two occurrences
|
|
159
|
+
* with identical identity tuples produce equal strings; differences in any
|
|
160
|
+
* tuple field produce different strings. The encoding uses a delimiter that
|
|
161
|
+
* cannot appear in a relative path or origin tag.
|
|
162
|
+
*/
|
|
163
|
+
export declare const occurrenceIdentityKey: (id: OccurrenceIdentity) => string;
|
|
164
|
+
/**
|
|
165
|
+
* Convenience: collapse an occurrence array to one entry per identity. The
|
|
166
|
+
* first occurrence with a given identity wins; subsequent observations are
|
|
167
|
+
* dropped. Stable ordering: input order is preserved for first-seen entries.
|
|
168
|
+
*/
|
|
169
|
+
export declare const dedupeByIdentity: <T extends ScannerOccurrence>(occurrences: ReadonlyArray<T>) => ReadonlyArray<T>;
|
|
170
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared scanner types: occurrence shape, common per-occurrence fields, and
|
|
3
|
+
* scanner-tier origin discriminators.
|
|
4
|
+
*
|
|
5
|
+
* Per Decision 5 of the workspace read-model design, scanner output is
|
|
6
|
+
* occurrence-shaped (`ReadonlyArray<Occurrence>`) — one entry per observable
|
|
7
|
+
* physical materialization. There is no central `DetectionOrigin` union; each
|
|
8
|
+
* scanner exports the discriminator it observes, and per-subject modules in
|
|
9
|
+
* Phase 7 map these scanner-tier discriminators into subject-specific origin
|
|
10
|
+
* unions.
|
|
11
|
+
*
|
|
12
|
+
* Identity of an actual entry is `(scope, type | agentId, origin, contentLocation)`.
|
|
13
|
+
* Two scanner paths observing the same physical occurrence collapse to one
|
|
14
|
+
* entry; two distinct physical paths under the same name produce two entries
|
|
15
|
+
* with different identities.
|
|
16
|
+
*/
|
|
17
|
+
import * as Option from "effect/Option";
|
|
18
|
+
/**
|
|
19
|
+
* Compute the identity tuple for one occurrence. Two scanner paths observing
|
|
20
|
+
* the same physical occurrence produce equal identities; distinct physical
|
|
21
|
+
* paths under the same name produce different identities.
|
|
22
|
+
*/
|
|
23
|
+
export const occurrenceIdentity = (occurrence) => {
|
|
24
|
+
switch (occurrence._tag) {
|
|
25
|
+
case "canonical-extension":
|
|
26
|
+
return {
|
|
27
|
+
scope: occurrence.scope,
|
|
28
|
+
subjectKey: occurrence.type,
|
|
29
|
+
origin: occurrence.origin,
|
|
30
|
+
contentLocation: occurrence.contentLocation,
|
|
31
|
+
};
|
|
32
|
+
case "agent-dir":
|
|
33
|
+
return {
|
|
34
|
+
scope: occurrence.scope,
|
|
35
|
+
subjectKey: `${occurrence.type}:${occurrence.agentId}`,
|
|
36
|
+
origin: `agent-dir:${occurrence.agentId}`,
|
|
37
|
+
contentLocation: occurrence.contentLocation,
|
|
38
|
+
};
|
|
39
|
+
case "mcp-config":
|
|
40
|
+
return occurrence.surface._tag === "shared"
|
|
41
|
+
? {
|
|
42
|
+
scope: occurrence.scope,
|
|
43
|
+
subjectKey: "mcp-server",
|
|
44
|
+
origin: "shared-mcp-config",
|
|
45
|
+
contentLocation: `${occurrence.contentLocation}#${occurrence.name}`,
|
|
46
|
+
}
|
|
47
|
+
: {
|
|
48
|
+
scope: occurrence.scope,
|
|
49
|
+
subjectKey: `mcp-server:${occurrence.surface.agentId}`,
|
|
50
|
+
origin: `agent-mcp-config:${occurrence.surface.agentId}`,
|
|
51
|
+
contentLocation: `${occurrence.contentLocation}#${occurrence.name}`,
|
|
52
|
+
};
|
|
53
|
+
case "agent-settings":
|
|
54
|
+
return {
|
|
55
|
+
scope: occurrence.scope,
|
|
56
|
+
subjectKey: `agent-settings:${occurrence.agentId}`,
|
|
57
|
+
origin: `agent-settings:${occurrence.agentId}`,
|
|
58
|
+
contentLocation: occurrence.contentLocation,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Serialize an `OccurrenceIdentity` to a stable string key. Two occurrences
|
|
64
|
+
* with identical identity tuples produce equal strings; differences in any
|
|
65
|
+
* tuple field produce different strings. The encoding uses a delimiter that
|
|
66
|
+
* cannot appear in a relative path or origin tag.
|
|
67
|
+
*/
|
|
68
|
+
export const occurrenceIdentityKey = (id) => `${id.scope}\u0000${id.subjectKey}\u0000${id.origin}\u0000${id.contentLocation}`;
|
|
69
|
+
/**
|
|
70
|
+
* Convenience: collapse an occurrence array to one entry per identity. The
|
|
71
|
+
* first occurrence with a given identity wins; subsequent observations are
|
|
72
|
+
* dropped. Stable ordering: input order is preserved for first-seen entries.
|
|
73
|
+
*/
|
|
74
|
+
export const dedupeByIdentity = (occurrences) => {
|
|
75
|
+
const seen = new Set();
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const occ of occurrences) {
|
|
78
|
+
const key = occurrenceIdentityKey(occurrenceIdentity(occ));
|
|
79
|
+
if (seen.has(key))
|
|
80
|
+
continue;
|
|
81
|
+
seen.add(key);
|
|
82
|
+
out.push(occ);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Per-scope read-only workspace model factory and configuration. */
|
|
2
|
+
import * as Brand from "effect/Brand";
|
|
3
|
+
import * as ServiceMap from "effect/Context";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as FileSystem from "effect/FileSystem";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Path from "effect/Path";
|
|
8
|
+
import { type Handle } from "@agentxm/extension-model/unstable/extensions/handle";
|
|
9
|
+
import type { SourceHostConfig } from "../../settings/schema.js";
|
|
10
|
+
import { type AbsolutePath } from "@agentxm/extension-model/unstable/path-types";
|
|
11
|
+
import { AgentRootResolver } from "./agent-root-resolver.js";
|
|
12
|
+
import { type ScopedAgentsApi } from "./agents/index.js";
|
|
13
|
+
import { type Warning } from "./diagnostics.js";
|
|
14
|
+
import { WorkspaceRootEscape, type LockfileIoError, type SettingsIoError, type SettingsReadError } from "./errors.js";
|
|
15
|
+
import { type HookExtensionsApi, type KnowledgeExtensionsApi, type McpServerExtensionsApi, type PackExtensionsApi, type RuleExtensionsApi, type SkillExtensionsApi, type SubagentExtensionsApi } from "./extensions/index.js";
|
|
16
|
+
import { type CanonicalExtensionOccurrence } from "./scanners/index.js";
|
|
17
|
+
import { type RawSourceBytes, type ScopedStateLoaders } from "./state.js";
|
|
18
|
+
import type { Scope } from "./types.js";
|
|
19
|
+
export type { RawSourceBytes } from "./state.js";
|
|
20
|
+
/** Scoped state cells; `raw(source)` reads cached bytes (absent → `Option.none`). */
|
|
21
|
+
export interface ScopedStateApi {
|
|
22
|
+
readonly settings: ScopedStateLoaders["settings"];
|
|
23
|
+
readonly lockfile: ScopedStateLoaders["lockfile"];
|
|
24
|
+
readonly raw: (source: "settings" | "lockfile") => Effect.Effect<Option.Option<RawSourceBytes>, SettingsIoError | LockfileIoError>;
|
|
25
|
+
}
|
|
26
|
+
/** Scoped source-host views over the cached settings loader. */
|
|
27
|
+
export interface ScopedSourceHostsApi {
|
|
28
|
+
readonly declared: Effect.Effect<ReadonlyArray<SourceHostConfig>, SettingsReadError>;
|
|
29
|
+
readonly effective: Effect.Effect<ReadonlyArray<SourceHostConfig>, SettingsReadError>;
|
|
30
|
+
readonly registryHosts: Effect.Effect<ReadonlyArray<Extract<SourceHostConfig, {
|
|
31
|
+
type: "registry";
|
|
32
|
+
}>>, SettingsReadError>;
|
|
33
|
+
readonly byName: (name: string) => Effect.Effect<Option.Option<SourceHostConfig>, SettingsReadError>;
|
|
34
|
+
}
|
|
35
|
+
/** Scoped owner view over the cached settings loader (declared owner; no fallback). */
|
|
36
|
+
export type ScopedOwnerApi = Effect.Effect<Option.Option<Handle>, SettingsReadError>;
|
|
37
|
+
/**
|
|
38
|
+
* Workspace read model for a single scope (project or user).
|
|
39
|
+
*
|
|
40
|
+
* Returned by {@link makeWorkspaceReadModel}. Each invocation builds its own
|
|
41
|
+
* scoped cells; cells cache for the lifetime of the returned value.
|
|
42
|
+
*/
|
|
43
|
+
export interface WorkspaceReadModel {
|
|
44
|
+
readonly scope: Scope;
|
|
45
|
+
readonly skills: SkillExtensionsApi;
|
|
46
|
+
readonly mcpServers: McpServerExtensionsApi;
|
|
47
|
+
readonly subagents: SubagentExtensionsApi;
|
|
48
|
+
readonly rules: RuleExtensionsApi;
|
|
49
|
+
readonly hooks: HookExtensionsApi;
|
|
50
|
+
readonly knowledge: KnowledgeExtensionsApi;
|
|
51
|
+
readonly packs: PackExtensionsApi;
|
|
52
|
+
readonly agents: ScopedAgentsApi;
|
|
53
|
+
readonly state: ScopedStateApi;
|
|
54
|
+
readonly sourceHosts: ScopedSourceHostsApi;
|
|
55
|
+
readonly owner: ScopedOwnerApi;
|
|
56
|
+
readonly diagnostics: Effect.Effect<ReadonlyArray<Warning>>;
|
|
57
|
+
readonly canonicalExtensions: Effect.Effect<ReadonlyArray<CanonicalExtensionOccurrence>>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The read-model family that carries each catalog extension type, or `null`
|
|
61
|
+
* where no family exists yet.
|
|
62
|
+
*
|
|
63
|
+
* Total by construction: a new extension type fails compile here until its
|
|
64
|
+
* read-model coverage is decided. The parity conformance suite reads this map
|
|
65
|
+
* to check the read-model obligation, and every `null` must be matched by a
|
|
66
|
+
* ledger row.
|
|
67
|
+
*
|
|
68
|
+
* @experimental This API is unstable and may change without notice.
|
|
69
|
+
*/
|
|
70
|
+
export declare const READ_MODEL_EXTENSION_FAMILY_BY_TYPE: {
|
|
71
|
+
readonly skill: "skills";
|
|
72
|
+
readonly "mcp-server": "mcpServers";
|
|
73
|
+
readonly subagent: "subagents";
|
|
74
|
+
readonly rule: "rules";
|
|
75
|
+
readonly hook: "hooks";
|
|
76
|
+
readonly knowledge: "knowledge";
|
|
77
|
+
};
|
|
78
|
+
/** Configuration the factory requires beyond `FileSystem` and `Path`. */
|
|
79
|
+
export interface WorkspaceReadModelConfigService {
|
|
80
|
+
readonly projectRoot: AbsolutePath;
|
|
81
|
+
readonly userHome: AbsolutePath;
|
|
82
|
+
readonly allowedRoot: AbsolutePath;
|
|
83
|
+
}
|
|
84
|
+
declare const WorkspaceReadModelConfig_base: ServiceMap.ServiceClass<WorkspaceReadModelConfig, "@agentxm/workspace-state/workspace/read-model/service/WorkspaceReadModelConfig", WorkspaceReadModelConfigService>;
|
|
85
|
+
/** Service tag for the {@link WorkspaceReadModelConfigService} the factory requires. */
|
|
86
|
+
export declare class WorkspaceReadModelConfig extends WorkspaceReadModelConfig_base {
|
|
87
|
+
}
|
|
88
|
+
/** Workspace root that has been validated against `allowedRoot`. */
|
|
89
|
+
export type ResolvedWorkspaceRoot = string & Brand.Brand<"ResolvedWorkspaceRoot">;
|
|
90
|
+
/**
|
|
91
|
+
* Build a {@link WorkspaceReadModel} for the requested scope.
|
|
92
|
+
*
|
|
93
|
+
* Each invocation produces a fresh instance with its own cached cells; call
|
|
94
|
+
* once at the command boundary and pass the value inward. Callers that need
|
|
95
|
+
* both scopes invoke the factory twice.
|
|
96
|
+
*
|
|
97
|
+
* Cross-scope state (the agent-root resolver and its collision warnings) is
|
|
98
|
+
* supplied by {@link AgentRootResolver}, which must be provided in the
|
|
99
|
+
* environment so the same warnings flow into every scope built against the
|
|
100
|
+
* same layer.
|
|
101
|
+
*/
|
|
102
|
+
export declare const makeWorkspaceReadModel: (scope: Scope) => Effect.Effect<WorkspaceReadModel, WorkspaceRootEscape, FileSystem.FileSystem | Path.Path | WorkspaceReadModelConfig | AgentRootResolver>;
|
|
103
|
+
//# sourceMappingURL=service.d.ts.map
|