@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,132 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as FileSystem from "effect/FileSystem";
|
|
3
|
+
import * as Path from "effect/Path";
|
|
4
|
+
import * as Result from "effect/Result";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import * as semver from "semver";
|
|
7
|
+
import { parseExtensionFqnParts } from "@agentxm/extension-model/unstable/extensions";
|
|
8
|
+
import { computePackManifestContentIdentity } from "./pack-manifest-content-identity.js";
|
|
9
|
+
import { PACK_MANIFEST_FILENAME, PackManifestSchema, } from "@agentxm/extension-model/unstable/packs/manifest-schema";
|
|
10
|
+
import { computePackPathsForLayout } from "./pack-paths.js";
|
|
11
|
+
import { isInlineDesiredExtension, } from "./desired-state-graph.js";
|
|
12
|
+
import { isDesiredExtensionActive } from "./desired-state-enabled.js";
|
|
13
|
+
const normalizedPackIdentity = (identity) => identity.startsWith("workspace:") ? identity.slice("workspace:".length) : identity;
|
|
14
|
+
const isPackProblem = (problem) => problem.type.startsWith("pack-");
|
|
15
|
+
const withoutInvalidPackOrigins = (graph, invalidPacks) => graph.nodes.flatMap((node) => {
|
|
16
|
+
if (isInlineDesiredExtension(node))
|
|
17
|
+
return [node];
|
|
18
|
+
if (node.type === "pack")
|
|
19
|
+
return [node];
|
|
20
|
+
const origins = node.origins.filter((origin) => origin.type !== "pack" || !invalidPacks.has(normalizedPackIdentity(origin.pack)));
|
|
21
|
+
if (origins.length === 0)
|
|
22
|
+
return [];
|
|
23
|
+
const settingsOrigin = origins.find((origin) => origin.type === "settings");
|
|
24
|
+
const packOrigin = origins.find((origin) => origin.type === "pack");
|
|
25
|
+
const constraints = origins.flatMap((origin) => origin.type === "settings" && origin.authority === "inline"
|
|
26
|
+
? []
|
|
27
|
+
: origin.constraint === undefined
|
|
28
|
+
? []
|
|
29
|
+
: [origin.constraint]);
|
|
30
|
+
if (settingsOrigin?.type === "settings" && settingsOrigin.authority === "inline") {
|
|
31
|
+
return [{ ...node, enabled: isDesiredExtensionActive(origins), constraints, origins }];
|
|
32
|
+
}
|
|
33
|
+
return [
|
|
34
|
+
{
|
|
35
|
+
...node,
|
|
36
|
+
source: (settingsOrigin !== undefined && "source" in settingsOrigin
|
|
37
|
+
? settingsOrigin.source
|
|
38
|
+
: undefined) ??
|
|
39
|
+
(packOrigin === undefined
|
|
40
|
+
? node.source
|
|
41
|
+
: `${packOrigin.source}@${packOrigin.constraint}`),
|
|
42
|
+
enabled: isDesiredExtensionActive(origins),
|
|
43
|
+
constraints,
|
|
44
|
+
origins,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
});
|
|
48
|
+
const decodeManifest = Schema.decodeUnknownSync(PackManifestSchema, {
|
|
49
|
+
onExcessProperty: "error",
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Authorize enabled external Pack manifests against their accepted lock row.
|
|
53
|
+
* Workspace-authored Pack manifests are desired authority and need no lock row.
|
|
54
|
+
*/
|
|
55
|
+
export const validateDesiredPackLock = ({ graph, lockfile, layout, }) => Effect.gen(function* () {
|
|
56
|
+
const fs = yield* FileSystem.FileSystem;
|
|
57
|
+
const path = yield* Path.Path;
|
|
58
|
+
const problems = [];
|
|
59
|
+
const invalidPacks = new Set(graph.problems.flatMap((problem) => isPackProblem(problem) ? [normalizedPackIdentity(problem.pack)] : []));
|
|
60
|
+
for (const node of graph.nodes) {
|
|
61
|
+
if (node.type !== "pack" || !node.enabled || node.identity.startsWith("workspace:")) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const identity = parseExtensionFqnParts(node.identity);
|
|
65
|
+
const entry = lockfile.packs?.[node.name];
|
|
66
|
+
const configuredSourceName = node.source.startsWith("@")
|
|
67
|
+
? "agentxm"
|
|
68
|
+
: node.source.slice(0, node.source.indexOf(":"));
|
|
69
|
+
if (identity === undefined ||
|
|
70
|
+
identity.type !== "pack" ||
|
|
71
|
+
entry === undefined ||
|
|
72
|
+
entry.sourceName !== configuredSourceName ||
|
|
73
|
+
entry.owner !== identity.owner ||
|
|
74
|
+
entry.name !== identity.name ||
|
|
75
|
+
!node.constraints.every((constraint) => semver.satisfies(entry.resolvedVersion, constraint))) {
|
|
76
|
+
problems.push({
|
|
77
|
+
type: "pack-resolution-unavailable",
|
|
78
|
+
pack: node.identity,
|
|
79
|
+
detail: "The configured external Pack has no matching accepted resolution.",
|
|
80
|
+
});
|
|
81
|
+
invalidPacks.add(normalizedPackIdentity(node.identity));
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const manifestPath = path.join(computePackPathsForLayout(path.join, layout, entry.sourceName, identity.owner, identity.name).canonicalPath, PACK_MANIFEST_FILENAME);
|
|
85
|
+
const readResult = yield* Effect.result(fs.readFileString(manifestPath));
|
|
86
|
+
if (Result.isFailure(readResult)) {
|
|
87
|
+
problems.push({
|
|
88
|
+
type: "pack-manifest-content-mismatch",
|
|
89
|
+
pack: node.identity,
|
|
90
|
+
path: manifestPath,
|
|
91
|
+
status: "missing",
|
|
92
|
+
acceptedVersion: entry.resolvedVersion,
|
|
93
|
+
acceptedContentIdentity: entry.manifestContentIdentity,
|
|
94
|
+
});
|
|
95
|
+
invalidPacks.add(normalizedPackIdentity(node.identity));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const decoded = Result.try({
|
|
99
|
+
try: () => decodeManifest(JSON.parse(readResult.success)),
|
|
100
|
+
catch: () => undefined,
|
|
101
|
+
});
|
|
102
|
+
const observedManifest = Result.isSuccess(decoded) && decoded.success !== undefined ? decoded.success : undefined;
|
|
103
|
+
const observedContentIdentity = observedManifest === undefined
|
|
104
|
+
? undefined
|
|
105
|
+
: computePackManifestContentIdentity(observedManifest);
|
|
106
|
+
if (observedManifest === undefined ||
|
|
107
|
+
observedContentIdentity !== entry.manifestContentIdentity) {
|
|
108
|
+
problems.push({
|
|
109
|
+
type: "pack-manifest-content-mismatch",
|
|
110
|
+
pack: node.identity,
|
|
111
|
+
path: manifestPath,
|
|
112
|
+
status: "changed",
|
|
113
|
+
acceptedVersion: entry.resolvedVersion,
|
|
114
|
+
acceptedContentIdentity: entry.manifestContentIdentity,
|
|
115
|
+
...(observedManifest === undefined || observedContentIdentity === undefined
|
|
116
|
+
? {}
|
|
117
|
+
: {
|
|
118
|
+
observedVersion: observedManifest.version,
|
|
119
|
+
observedContentIdentity,
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
invalidPacks.add(normalizedPackIdentity(node.identity));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...graph,
|
|
127
|
+
complete: graph.complete && problems.length === 0,
|
|
128
|
+
nodes: withoutInvalidPackOrigins(graph, invalidPacks),
|
|
129
|
+
problems: [...graph.problems, ...problems],
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
//# sourceMappingURL=desired-pack-lock.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared origin-precedence semantics for desired extension nodes.
|
|
3
|
+
*
|
|
4
|
+
* An explicit disabled settings entry is user intent and overrides pack
|
|
5
|
+
* membership. Otherwise any enabled settings origin or pack origin activates
|
|
6
|
+
* the extension.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
export type DesiredStateEnabledOrigin = {
|
|
11
|
+
readonly type: "settings";
|
|
12
|
+
readonly enabled: boolean;
|
|
13
|
+
} | {
|
|
14
|
+
readonly type: "pack";
|
|
15
|
+
readonly enabled: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare const isDesiredExtensionActive: (origins: ReadonlyArray<DesiredStateEnabledOrigin>) => boolean;
|
|
18
|
+
//# sourceMappingURL=desired-state-enabled.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared origin-precedence semantics for desired extension nodes.
|
|
3
|
+
*
|
|
4
|
+
* An explicit disabled settings entry is user intent and overrides pack
|
|
5
|
+
* membership. Otherwise any enabled settings origin or pack origin activates
|
|
6
|
+
* the extension.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
export const isDesiredExtensionActive = (origins) => {
|
|
11
|
+
const settingsOrigin = origins.find((origin) => origin.type === "settings");
|
|
12
|
+
if (settingsOrigin?.enabled === false)
|
|
13
|
+
return false;
|
|
14
|
+
return origins.some((origin) => origin.enabled);
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=desired-state-enabled.js.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as FileSystem from "effect/FileSystem";
|
|
3
|
+
import * as Path from "effect/Path";
|
|
4
|
+
import { type ExtensionType } from "@agentxm/extension-model/unstable/extensions";
|
|
5
|
+
import type { PackRef } from "@agentxm/extension-model/unstable/extensions/refs/pack";
|
|
6
|
+
import type { Settings } from "../settings/index.js";
|
|
7
|
+
import { type WorkspaceLayout } from "./layout.js";
|
|
8
|
+
export type DesiredExtensionOrigin = {
|
|
9
|
+
readonly type: "settings";
|
|
10
|
+
readonly authority?: "sourced";
|
|
11
|
+
readonly source: string;
|
|
12
|
+
readonly enabled: boolean;
|
|
13
|
+
readonly constraint?: string;
|
|
14
|
+
} | {
|
|
15
|
+
readonly type: "settings";
|
|
16
|
+
readonly authority: "inline";
|
|
17
|
+
readonly source?: undefined;
|
|
18
|
+
readonly constraint?: undefined;
|
|
19
|
+
readonly enabled: boolean;
|
|
20
|
+
} | {
|
|
21
|
+
readonly type: "pack";
|
|
22
|
+
readonly pack: string;
|
|
23
|
+
readonly manifestPath: string;
|
|
24
|
+
readonly source: string;
|
|
25
|
+
readonly constraint: string;
|
|
26
|
+
readonly enabled: boolean;
|
|
27
|
+
};
|
|
28
|
+
interface DesiredExtensionNodeCommon {
|
|
29
|
+
readonly type: ExtensionType;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly identity: string;
|
|
32
|
+
readonly enabled: boolean;
|
|
33
|
+
readonly constraints: ReadonlyArray<string>;
|
|
34
|
+
readonly origins: ReadonlyArray<DesiredExtensionOrigin>;
|
|
35
|
+
}
|
|
36
|
+
export type DesiredExtensionNode = DesiredExtensionNodeCommon & ({
|
|
37
|
+
readonly authority?: "sourced";
|
|
38
|
+
readonly source: string;
|
|
39
|
+
} | {
|
|
40
|
+
readonly type: "mcp-server";
|
|
41
|
+
readonly authority: "inline";
|
|
42
|
+
readonly source?: undefined;
|
|
43
|
+
});
|
|
44
|
+
export declare const isInlineDesiredExtension: (node: DesiredExtensionNode) => node is DesiredExtensionNode & {
|
|
45
|
+
readonly authority: "inline";
|
|
46
|
+
};
|
|
47
|
+
export declare const isSourcedDesiredExtension: (node: DesiredExtensionNode) => node is DesiredExtensionNode & {
|
|
48
|
+
readonly source: string;
|
|
49
|
+
};
|
|
50
|
+
export interface DesiredConstraintContributor {
|
|
51
|
+
readonly source: "settings" | "pack";
|
|
52
|
+
readonly range: string;
|
|
53
|
+
readonly location: string;
|
|
54
|
+
readonly dependingPack?: string;
|
|
55
|
+
}
|
|
56
|
+
export type DesiredStateProblem = {
|
|
57
|
+
readonly type: "workspace-owner-missing";
|
|
58
|
+
readonly extensionType: ExtensionType;
|
|
59
|
+
readonly name: string;
|
|
60
|
+
} | {
|
|
61
|
+
readonly type: "pack-manifest-unavailable";
|
|
62
|
+
readonly pack: string;
|
|
63
|
+
readonly path: string;
|
|
64
|
+
} | {
|
|
65
|
+
readonly type: "pack-manifest-invalid";
|
|
66
|
+
readonly pack: string;
|
|
67
|
+
readonly path: string;
|
|
68
|
+
} | {
|
|
69
|
+
readonly type: "pack-identity-mismatch";
|
|
70
|
+
readonly pack: string;
|
|
71
|
+
readonly path: string;
|
|
72
|
+
readonly detail: string;
|
|
73
|
+
} | {
|
|
74
|
+
readonly type: "pack-resolution-unavailable";
|
|
75
|
+
readonly pack: string;
|
|
76
|
+
readonly detail: string;
|
|
77
|
+
} | {
|
|
78
|
+
readonly type: "pack-manifest-content-mismatch";
|
|
79
|
+
readonly pack: string;
|
|
80
|
+
readonly path?: string;
|
|
81
|
+
readonly status: string;
|
|
82
|
+
readonly acceptedVersion: string;
|
|
83
|
+
readonly acceptedContentIdentity: string;
|
|
84
|
+
readonly observedVersion?: string;
|
|
85
|
+
readonly observedContentIdentity?: string;
|
|
86
|
+
} | {
|
|
87
|
+
readonly type: "projection-collision";
|
|
88
|
+
readonly extensionType: ExtensionType;
|
|
89
|
+
readonly name: string;
|
|
90
|
+
readonly identities: ReadonlyArray<string>;
|
|
91
|
+
} | {
|
|
92
|
+
readonly type: "constraint-conflict";
|
|
93
|
+
readonly extensionType: ExtensionType;
|
|
94
|
+
readonly name: string;
|
|
95
|
+
readonly constraints: ReadonlyArray<string>;
|
|
96
|
+
readonly contributors: ReadonlyArray<DesiredConstraintContributor>;
|
|
97
|
+
};
|
|
98
|
+
export interface DesiredStateGraph {
|
|
99
|
+
readonly complete: boolean;
|
|
100
|
+
readonly nodes: ReadonlyArray<DesiredExtensionNode>;
|
|
101
|
+
readonly problems: ReadonlyArray<DesiredStateProblem>;
|
|
102
|
+
}
|
|
103
|
+
export type ProspectivePackRef = Pick<PackRef, "owner" | "pack" | "version">;
|
|
104
|
+
interface DesiredStateGraphArgs {
|
|
105
|
+
readonly baseDir: string;
|
|
106
|
+
readonly settings: Settings;
|
|
107
|
+
readonly layout?: WorkspaceLayout;
|
|
108
|
+
/** Resolved Pack roots whose manifests supersede the currently materialized copy. */
|
|
109
|
+
readonly prospectivePacks?: ReadonlyArray<ProspectivePackRef>;
|
|
110
|
+
}
|
|
111
|
+
export declare const collectDesiredConstraintContributors: (_path: Path.Path, origins: ReadonlyArray<DesiredExtensionOrigin>) => ReadonlyArray<DesiredConstraintContributor>;
|
|
112
|
+
export declare const buildDesiredStateGraph: ({ baseDir, settings, layout, prospectivePacks, }: DesiredStateGraphArgs) => Effect.Effect<DesiredStateGraph, never, FileSystem.FileSystem | Path.Path>;
|
|
113
|
+
export {};
|
|
114
|
+
//# sourceMappingURL=desired-state-graph.d.ts.map
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as FileSystem from "effect/FileSystem";
|
|
3
|
+
import * as Path from "effect/Path";
|
|
4
|
+
import * as Result from "effect/Result";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import * as semver from "semver";
|
|
7
|
+
import { extensionTypes, parseExtensionFqnParts, parseRegistrySourceRef, toExtensionTypePlural, } from "@agentxm/extension-model/unstable/extensions";
|
|
8
|
+
import { PACK_MANIFEST_FILENAME, PackManifestSchema, } from "@agentxm/extension-model/unstable/packs/manifest-schema";
|
|
9
|
+
import { computePackPathsForLayout } from "./pack-paths.js";
|
|
10
|
+
import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
|
|
11
|
+
import { isDesiredExtensionActive } from "./desired-state-enabled.js";
|
|
12
|
+
import { configuredAuthoredDirectory } from "./layout.js";
|
|
13
|
+
import { SETTINGS_FILENAME } from "@agentxm/extension-model/unstable/workspace-files";
|
|
14
|
+
import { ACQUIRED_EXTENSIONS_DIR } from "./constants.js";
|
|
15
|
+
import { intersectVersionConstraints } from "@agentxm/extension-model/unstable/version-constraints";
|
|
16
|
+
export const isInlineDesiredExtension = (node) => node.authority === "inline";
|
|
17
|
+
export const isSourcedDesiredExtension = (node) => node.authority !== "inline";
|
|
18
|
+
const nodeKey = (type, name) => `${type}:${name}`;
|
|
19
|
+
const packageIdentity = (identity) => identity.startsWith("workspace:") ? identity.slice("workspace:".length) : identity;
|
|
20
|
+
const registryLocator = (source) => {
|
|
21
|
+
if (source.startsWith("@"))
|
|
22
|
+
return { sourceName: "agentxm", ref: source };
|
|
23
|
+
const separator = source.indexOf(":");
|
|
24
|
+
if (separator <= 0)
|
|
25
|
+
return undefined;
|
|
26
|
+
const ref = source.slice(separator + 1);
|
|
27
|
+
return ref.startsWith("@") ? { sourceName: source.slice(0, separator), ref } : undefined;
|
|
28
|
+
};
|
|
29
|
+
const sourceIdentity = (type, name, source, settings) => {
|
|
30
|
+
if (isWorkspaceSourceLocator(source)) {
|
|
31
|
+
return settings.owner === undefined
|
|
32
|
+
? { identity: source }
|
|
33
|
+
: { identity: `workspace:${settings.owner}/${toExtensionTypePlural(type)}/${name}` };
|
|
34
|
+
}
|
|
35
|
+
const locator = registryLocator(source);
|
|
36
|
+
const parsed = locator === undefined ? undefined : parseRegistrySourceRef(locator.ref);
|
|
37
|
+
if (parsed !== undefined && parsed.type === toExtensionTypePlural(type)) {
|
|
38
|
+
return {
|
|
39
|
+
identity: `${parsed.owner}/${parsed.type}/${parsed.name}`,
|
|
40
|
+
...(parsed.versionRange === undefined ? {} : { constraint: parsed.versionRange }),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return { identity: source };
|
|
44
|
+
};
|
|
45
|
+
const packIdentity = (settingsName, source, settings) => {
|
|
46
|
+
if (isWorkspaceSourceLocator(source)) {
|
|
47
|
+
if (settings.owner === undefined)
|
|
48
|
+
return undefined;
|
|
49
|
+
return {
|
|
50
|
+
owner: settings.owner,
|
|
51
|
+
name: settingsName,
|
|
52
|
+
fqn: `${settings.owner}/packs/${settingsName}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const locator = registryLocator(source);
|
|
56
|
+
const parsed = locator === undefined ? undefined : parseRegistrySourceRef(locator.ref);
|
|
57
|
+
if (parsed !== undefined && parsed.type === "packs") {
|
|
58
|
+
return {
|
|
59
|
+
owner: parsed.owner,
|
|
60
|
+
name: parsed.name,
|
|
61
|
+
fqn: `${parsed.owner}/packs/${parsed.name}`,
|
|
62
|
+
...(parsed.versionRange === undefined ? {} : { constraint: parsed.versionRange }),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (source === "registry" && settings.owner !== undefined) {
|
|
66
|
+
return {
|
|
67
|
+
owner: settings.owner,
|
|
68
|
+
name: settingsName,
|
|
69
|
+
fqn: `${settings.owner}/packs/${settingsName}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
};
|
|
74
|
+
export const collectDesiredConstraintContributors = (_path, origins) => origins
|
|
75
|
+
.flatMap((origin) => {
|
|
76
|
+
if (origin.type === "settings" && origin.authority === "inline")
|
|
77
|
+
return [];
|
|
78
|
+
if (origin.constraint === undefined)
|
|
79
|
+
return [];
|
|
80
|
+
if (origin.type === "settings") {
|
|
81
|
+
return [
|
|
82
|
+
{
|
|
83
|
+
source: "settings",
|
|
84
|
+
range: origin.constraint,
|
|
85
|
+
location: SETTINGS_FILENAME,
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
return [
|
|
90
|
+
{
|
|
91
|
+
source: "pack",
|
|
92
|
+
dependingPack: origin.pack.replace(/^workspace:/, ""),
|
|
93
|
+
range: origin.constraint,
|
|
94
|
+
location: origin.manifestPath,
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
})
|
|
98
|
+
.sort((left, right) => {
|
|
99
|
+
const byPack = (left.dependingPack ?? "").localeCompare(right.dependingPack ?? "");
|
|
100
|
+
if (byPack !== 0)
|
|
101
|
+
return byPack;
|
|
102
|
+
const byRange = left.range.localeCompare(right.range);
|
|
103
|
+
return byRange === 0 ? left.location.localeCompare(right.location) : byRange;
|
|
104
|
+
});
|
|
105
|
+
const parsePackManifest = (raw) => {
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
const decoded = Schema.decodeUnknownResult(PackManifestSchema)(parsed);
|
|
114
|
+
return Result.isSuccess(decoded) ? decoded.success : undefined;
|
|
115
|
+
};
|
|
116
|
+
export const buildDesiredStateGraph = ({ baseDir, settings, layout, prospectivePacks = [], }) => Effect.gen(function* () {
|
|
117
|
+
const fs = yield* FileSystem.FileSystem;
|
|
118
|
+
const path = yield* Path.Path;
|
|
119
|
+
const candidates = [];
|
|
120
|
+
const problems = [];
|
|
121
|
+
const prospectivePacksByIdentity = new Map(prospectivePacks.map((ref) => [`${ref.owner}/packs/${ref.pack.name}`, ref]));
|
|
122
|
+
const addSettingsEntries = (type, entries) => {
|
|
123
|
+
for (const [name, entry] of Object.entries(entries ?? {})) {
|
|
124
|
+
const bundled = type === "skill" && entry.origin === "bundled";
|
|
125
|
+
const identity = bundled
|
|
126
|
+
? { identity: `bundled:@agentxm/skills/${name}` }
|
|
127
|
+
: sourceIdentity(type, name, entry.source, settings);
|
|
128
|
+
if (!bundled && isWorkspaceSourceLocator(entry.source) && settings.owner === undefined) {
|
|
129
|
+
problems.push({ type: "workspace-owner-missing", extensionType: type, name });
|
|
130
|
+
}
|
|
131
|
+
candidates.push({
|
|
132
|
+
type,
|
|
133
|
+
name,
|
|
134
|
+
identity: identity.identity,
|
|
135
|
+
authority: "sourced",
|
|
136
|
+
source: entry.source,
|
|
137
|
+
enabled: entry.enabled,
|
|
138
|
+
...(identity.constraint === undefined ? {} : { constraint: identity.constraint }),
|
|
139
|
+
origin: {
|
|
140
|
+
type: "settings",
|
|
141
|
+
authority: "sourced",
|
|
142
|
+
source: entry.source,
|
|
143
|
+
enabled: entry.enabled,
|
|
144
|
+
...(identity.constraint === undefined ? {} : { constraint: identity.constraint }),
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
addSettingsEntries("skill", settings.skills);
|
|
150
|
+
for (const [name, entry] of Object.entries(settings.mcpServers ?? {})) {
|
|
151
|
+
if (entry.kind === "inline") {
|
|
152
|
+
candidates.push({
|
|
153
|
+
type: "mcp-server",
|
|
154
|
+
name,
|
|
155
|
+
identity: `@workspace/mcps/${name}`,
|
|
156
|
+
authority: "inline",
|
|
157
|
+
enabled: entry.enabled,
|
|
158
|
+
origin: { type: "settings", authority: "inline", enabled: entry.enabled },
|
|
159
|
+
});
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const identity = sourceIdentity("mcp-server", name, entry.source, settings);
|
|
163
|
+
if (isWorkspaceSourceLocator(entry.source) && settings.owner === undefined) {
|
|
164
|
+
problems.push({ type: "workspace-owner-missing", extensionType: "mcp-server", name });
|
|
165
|
+
}
|
|
166
|
+
candidates.push({
|
|
167
|
+
type: "mcp-server",
|
|
168
|
+
name,
|
|
169
|
+
identity: identity.identity,
|
|
170
|
+
authority: "sourced",
|
|
171
|
+
source: entry.source,
|
|
172
|
+
enabled: entry.enabled,
|
|
173
|
+
...(identity.constraint === undefined ? {} : { constraint: identity.constraint }),
|
|
174
|
+
origin: {
|
|
175
|
+
type: "settings",
|
|
176
|
+
authority: "sourced",
|
|
177
|
+
source: entry.source,
|
|
178
|
+
enabled: entry.enabled,
|
|
179
|
+
...(identity.constraint === undefined ? {} : { constraint: identity.constraint }),
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
addSettingsEntries("subagent", settings.subagents);
|
|
184
|
+
addSettingsEntries("rule", settings.rules);
|
|
185
|
+
addSettingsEntries("hook", settings.hooks);
|
|
186
|
+
addSettingsEntries("knowledge", settings.knowledge);
|
|
187
|
+
for (const [settingsName, entry] of Object.entries(settings.packs ?? {})) {
|
|
188
|
+
const identity = packIdentity(settingsName, entry.source, settings);
|
|
189
|
+
if (identity === undefined) {
|
|
190
|
+
problems.push({
|
|
191
|
+
type: "pack-identity-mismatch",
|
|
192
|
+
pack: entry.source,
|
|
193
|
+
path: "",
|
|
194
|
+
detail: "The configured pack source does not identify a Registry or workspace pack.",
|
|
195
|
+
});
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
candidates.push({
|
|
199
|
+
type: "pack",
|
|
200
|
+
name: identity.name,
|
|
201
|
+
identity: isWorkspaceSourceLocator(entry.source)
|
|
202
|
+
? `workspace:${identity.fqn}`
|
|
203
|
+
: identity.fqn,
|
|
204
|
+
authority: "sourced",
|
|
205
|
+
source: entry.source,
|
|
206
|
+
enabled: entry.enabled !== false,
|
|
207
|
+
...(identity.constraint === undefined ? {} : { constraint: identity.constraint }),
|
|
208
|
+
origin: {
|
|
209
|
+
type: "settings",
|
|
210
|
+
authority: "sourced",
|
|
211
|
+
source: entry.source,
|
|
212
|
+
enabled: entry.enabled !== false,
|
|
213
|
+
...(identity.constraint === undefined ? {} : { constraint: identity.constraint }),
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
const workspacePack = isWorkspaceSourceLocator(entry.source);
|
|
217
|
+
const configuredRegistrySource = registryLocator(entry.source)?.sourceName ?? "agentxm";
|
|
218
|
+
const manifestPath = path.join(layout === undefined
|
|
219
|
+
? path.join(baseDir, workspacePack
|
|
220
|
+
? configuredAuthoredDirectory(settings, "pack")
|
|
221
|
+
: path.join(ACQUIRED_EXTENSIONS_DIR, configuredRegistrySource, identity.owner, "packs"), identity.name)
|
|
222
|
+
: computePackPathsForLayout(path.join, layout, workspacePack ? "workspace" : configuredRegistrySource, identity.owner, identity.name).canonicalPath, PACK_MANIFEST_FILENAME);
|
|
223
|
+
const prospective = prospectivePacksByIdentity.get(identity.fqn);
|
|
224
|
+
const manifest = yield* prospective === undefined
|
|
225
|
+
? Effect.gen(function* () {
|
|
226
|
+
const readResult = yield* Effect.result(fs.readFileString(manifestPath));
|
|
227
|
+
if (Result.isFailure(readResult)) {
|
|
228
|
+
problems.push({
|
|
229
|
+
type: "pack-manifest-unavailable",
|
|
230
|
+
pack: identity.fqn,
|
|
231
|
+
path: manifestPath,
|
|
232
|
+
});
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
const decoded = parsePackManifest(readResult.success);
|
|
236
|
+
if (decoded === undefined) {
|
|
237
|
+
problems.push({
|
|
238
|
+
type: "pack-manifest-invalid",
|
|
239
|
+
pack: identity.fqn,
|
|
240
|
+
path: manifestPath,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return decoded;
|
|
244
|
+
})
|
|
245
|
+
: Effect.succeed({
|
|
246
|
+
owner: prospective.owner,
|
|
247
|
+
type: "pack",
|
|
248
|
+
name: prospective.pack.name,
|
|
249
|
+
version: prospective.version,
|
|
250
|
+
dependencies: prospective.pack.dependencies,
|
|
251
|
+
});
|
|
252
|
+
if (manifest === undefined)
|
|
253
|
+
continue;
|
|
254
|
+
if (manifest.owner !== identity.owner ||
|
|
255
|
+
manifest.name !== identity.name ||
|
|
256
|
+
(identity.constraint !== undefined &&
|
|
257
|
+
!semver.satisfies(manifest.version, identity.constraint))) {
|
|
258
|
+
problems.push({
|
|
259
|
+
type: "pack-identity-mismatch",
|
|
260
|
+
pack: identity.fqn,
|
|
261
|
+
path: manifestPath,
|
|
262
|
+
detail: `Expected ${identity.fqn}${identity.constraint === undefined ? "" : `@${identity.constraint}`}, found ${manifest.owner}/packs/${manifest.name}@${manifest.version}.`,
|
|
263
|
+
});
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
for (const [fqn, constraint] of Object.entries(manifest.dependencies)) {
|
|
267
|
+
const parsed = parseExtensionFqnParts(fqn);
|
|
268
|
+
if (parsed === undefined || parsed.type === "pack")
|
|
269
|
+
continue;
|
|
270
|
+
candidates.push({
|
|
271
|
+
type: parsed.type,
|
|
272
|
+
name: parsed.name,
|
|
273
|
+
identity: `${parsed.owner}/${toExtensionTypePlural(parsed.type)}/${parsed.name}`,
|
|
274
|
+
authority: "sourced",
|
|
275
|
+
source: `${fqn}@${constraint}`,
|
|
276
|
+
enabled: entry.enabled !== false,
|
|
277
|
+
constraint,
|
|
278
|
+
origin: {
|
|
279
|
+
type: "pack",
|
|
280
|
+
pack: workspacePack ? `workspace:${identity.fqn}` : identity.fqn,
|
|
281
|
+
manifestPath: path.relative(baseDir, manifestPath),
|
|
282
|
+
source: fqn,
|
|
283
|
+
constraint,
|
|
284
|
+
enabled: entry.enabled !== false,
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const nodes = new Map();
|
|
290
|
+
for (const candidate of candidates) {
|
|
291
|
+
const key = nodeKey(candidate.type, candidate.name);
|
|
292
|
+
const existing = nodes.get(key);
|
|
293
|
+
if (existing === undefined) {
|
|
294
|
+
nodes.set(key, candidate.authority === "sourced"
|
|
295
|
+
? {
|
|
296
|
+
type: candidate.type,
|
|
297
|
+
name: candidate.name,
|
|
298
|
+
identity: candidate.identity,
|
|
299
|
+
authority: "sourced",
|
|
300
|
+
source: candidate.source,
|
|
301
|
+
enabled: candidate.enabled,
|
|
302
|
+
constraints: candidate.constraint === undefined ? [] : [candidate.constraint],
|
|
303
|
+
origins: [candidate.origin],
|
|
304
|
+
}
|
|
305
|
+
: {
|
|
306
|
+
type: "mcp-server",
|
|
307
|
+
name: candidate.name,
|
|
308
|
+
identity: candidate.identity,
|
|
309
|
+
authority: "inline",
|
|
310
|
+
enabled: candidate.enabled,
|
|
311
|
+
constraints: [],
|
|
312
|
+
origins: [candidate.origin],
|
|
313
|
+
});
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (packageIdentity(existing.identity) !== packageIdentity(candidate.identity)) {
|
|
317
|
+
problems.push({
|
|
318
|
+
type: "projection-collision",
|
|
319
|
+
extensionType: candidate.type,
|
|
320
|
+
name: candidate.name,
|
|
321
|
+
identities: [existing.identity, candidate.identity],
|
|
322
|
+
});
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (isInlineDesiredExtension(existing) || candidate.authority === "inline") {
|
|
326
|
+
problems.push({
|
|
327
|
+
type: "projection-collision",
|
|
328
|
+
extensionType: candidate.type,
|
|
329
|
+
name: candidate.name,
|
|
330
|
+
identities: [existing.identity, candidate.identity],
|
|
331
|
+
});
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
const origins = [...existing.origins, candidate.origin];
|
|
335
|
+
nodes.set(key, {
|
|
336
|
+
...existing,
|
|
337
|
+
source: existing.origins.some((origin) => origin.type === "settings")
|
|
338
|
+
? existing.source
|
|
339
|
+
: candidate.source,
|
|
340
|
+
enabled: isDesiredExtensionActive(origins),
|
|
341
|
+
constraints: candidate.constraint === undefined || existing.constraints.includes(candidate.constraint)
|
|
342
|
+
? existing.constraints
|
|
343
|
+
: [...existing.constraints, candidate.constraint],
|
|
344
|
+
origins,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
for (const node of nodes.values()) {
|
|
348
|
+
if (intersectVersionConstraints(node.constraints) === undefined) {
|
|
349
|
+
problems.push({
|
|
350
|
+
type: "constraint-conflict",
|
|
351
|
+
extensionType: node.type,
|
|
352
|
+
name: node.name,
|
|
353
|
+
constraints: node.constraints,
|
|
354
|
+
contributors: collectDesiredConstraintContributors(path, node.origins),
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const typeOrder = new Map(extensionTypes.map((type, index) => [type, index]));
|
|
359
|
+
const orderedNodes = [...nodes.values()]
|
|
360
|
+
.map((node) => {
|
|
361
|
+
if (isInlineDesiredExtension(node))
|
|
362
|
+
return node;
|
|
363
|
+
const constraint = intersectVersionConstraints(node.constraints);
|
|
364
|
+
return {
|
|
365
|
+
...node,
|
|
366
|
+
source: node.identity.startsWith("@") && node.constraints.length > 0 && constraint !== undefined
|
|
367
|
+
? `${node.identity}@${constraint}`
|
|
368
|
+
: node.source,
|
|
369
|
+
};
|
|
370
|
+
})
|
|
371
|
+
.sort((left, right) => {
|
|
372
|
+
const leftOrder = typeOrder.get(left.type) ?? Number.MAX_SAFE_INTEGER;
|
|
373
|
+
const rightOrder = typeOrder.get(right.type) ?? Number.MAX_SAFE_INTEGER;
|
|
374
|
+
return leftOrder === rightOrder
|
|
375
|
+
? left.name.localeCompare(right.name)
|
|
376
|
+
: leftOrder - rightOrder;
|
|
377
|
+
});
|
|
378
|
+
return {
|
|
379
|
+
complete: problems.length === 0,
|
|
380
|
+
nodes: orderedNodes,
|
|
381
|
+
problems,
|
|
382
|
+
};
|
|
383
|
+
});
|
|
384
|
+
//# sourceMappingURL=desired-state-graph.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DesiredStateProblem } from "./desired-state-graph.js";
|
|
2
|
+
/** Sanitized terminal text for one desired-state problem. */
|
|
3
|
+
export declare const desiredStateProblemText: (problem: DesiredStateProblem) => string;
|
|
4
|
+
/** Stable, sanitized terminal text for a desired-state problem set. */
|
|
5
|
+
export declare const desiredStateProblemsText: (problems: ReadonlyArray<DesiredStateProblem>) => string;
|
|
6
|
+
//# sourceMappingURL=desired-state-problem-text.d.ts.map
|