@agentxm/extension-materialization 0.29.2 → 0.30.1
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/dist/src/hooks/manager.d.ts +0 -5
- package/dist/src/hooks/manager.js +73 -36
- package/dist/src/index.d.ts +1 -6
- package/dist/src/index.js +0 -9
- package/dist/src/knowledge/manager.d.ts +0 -1
- package/dist/src/knowledge/manager.js +36 -29
- package/dist/src/manager-contract.d.ts +16 -18
- package/dist/src/manager-registry.d.ts +2 -3
- package/dist/src/managers.d.ts +22 -3
- package/dist/src/managers.js +0 -13
- package/dist/src/mcps/manager.js +84 -44
- package/dist/src/packs/manager.js +21 -18
- package/dist/src/rules/manager.d.ts +0 -5
- package/dist/src/rules/manager.js +22 -32
- package/dist/src/skills/errors.d.ts +2 -1
- package/dist/src/skills/manager.js +45 -53
- package/dist/src/skills/materialization.d.ts +2 -2
- package/dist/src/skills/skill-artifact.d.ts +5 -1
- package/dist/src/subagents/manager.js +31 -52
- package/dist/src/testing.d.ts +0 -66
- package/dist/src/testing.js +1 -89
- package/package.json +19 -22
- package/dist/src/desired-state/errors.d.ts +0 -22
- package/dist/src/desired-state/errors.js +0 -22
- package/dist/src/desired-state/retained-materialization.d.ts +0 -58
- package/dist/src/desired-state/retained-materialization.js +0 -119
- package/dist/src/extensions/operations.d.ts +0 -252
- package/dist/src/extensions/operations.js +0 -631
- package/dist/src/mcps/authored-materialization.d.ts +0 -28
- package/dist/src/mcps/authored-materialization.js +0 -34
- package/dist/src/mcps/install-operation.d.ts +0 -92
- package/dist/src/mcps/install-operation.js +0 -557
|
@@ -1,631 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared extension closure recipes — install, materialize, uninstall, and the
|
|
3
|
-
* authored-package transition.
|
|
4
|
-
*
|
|
5
|
-
* A recipe composes one manager's contract into one plan step. Requirements
|
|
6
|
-
* stay explicit: the step declares the manager's `R` plus the transaction
|
|
7
|
-
* scope its closure runs in, and the command boundary composes them once. The
|
|
8
|
-
* facts a materialization observed travel from `materializeInstall` to the
|
|
9
|
-
* settings and lockfile writes and to the step's artifact as values.
|
|
10
|
-
*
|
|
11
|
-
* @experimental This API is unstable and may change without notice.
|
|
12
|
-
* @packageDocumentation
|
|
13
|
-
*/
|
|
14
|
-
import * as Effect from "effect/Effect";
|
|
15
|
-
import * as Option from "effect/Option";
|
|
16
|
-
import { LifecyclePostconditionViolated, ScaffoldedExtensionUnresolved } from "./errors.js";
|
|
17
|
-
import { SourceAuthorityBlocked } from "@agentxm/extension-resolution";
|
|
18
|
-
import { applyProjectionPlans, projectionPlanExclusionWarnings, } from "@agentxm/workspace-projection";
|
|
19
|
-
import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
|
|
20
|
-
import { evaluateSourceAuthority } from "@agentxm/extension-resolution";
|
|
21
|
-
import { formatDeprecationWarning } from "@agentxm/registry-client";
|
|
22
|
-
import { runWorkspaceTransaction } from "@agentxm/workspace-transactions";
|
|
23
|
-
import { toExtensionTypePlural } from "@agentxm/extension-model/unstable/extensions/common";
|
|
24
|
-
// -----------------------------------------------------------------------------
|
|
25
|
-
// Target Helpers
|
|
26
|
-
// -----------------------------------------------------------------------------
|
|
27
|
-
/**
|
|
28
|
-
* Derive an ExtensionTarget from an ExtensionRef.
|
|
29
|
-
*
|
|
30
|
-
* Pack targets include owner; leaf-extension targets are name-only.
|
|
31
|
-
*/
|
|
32
|
-
export const targetFromRef = (ref) => {
|
|
33
|
-
switch (ref.type) {
|
|
34
|
-
case "skill":
|
|
35
|
-
return { type: "skill", name: ref.skill.name };
|
|
36
|
-
case "pack":
|
|
37
|
-
return { type: "pack", name: ref.pack.name, owner: ref.owner };
|
|
38
|
-
case "mcp-server":
|
|
39
|
-
return { type: "mcp-server", name: ref.server.name };
|
|
40
|
-
case "subagent":
|
|
41
|
-
return { type: "subagent", name: ref.subagent.name };
|
|
42
|
-
case "rule":
|
|
43
|
-
return { type: "rule", name: ref.rule.name };
|
|
44
|
-
case "hook":
|
|
45
|
-
return { type: "hook", name: ref.hook.name };
|
|
46
|
-
case "knowledge":
|
|
47
|
-
return { type: "knowledge", name: ref.knowledge.name };
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
export const extensionRefLifecycleWarnings = (ref) => ref.refType === "registry"
|
|
51
|
-
? [
|
|
52
|
-
...(ref.deprecation === undefined
|
|
53
|
-
? []
|
|
54
|
-
: [
|
|
55
|
-
formatDeprecationWarning(`${ref.owner}/${toExtensionTypePlural(ref.type)}/${ref.name}`, ref.deprecation),
|
|
56
|
-
]),
|
|
57
|
-
...(ref.lifecycleWarnings ?? []),
|
|
58
|
-
]
|
|
59
|
-
: [];
|
|
60
|
-
export const extensionRefRegistryLifecycle = (ref) => ref.refType !== "registry" || ref.deprecation === undefined
|
|
61
|
-
? undefined
|
|
62
|
-
: { deprecation: ref.deprecation };
|
|
63
|
-
/**
|
|
64
|
-
* Produce a display label from an ExtensionTarget.
|
|
65
|
-
*
|
|
66
|
-
* Pack targets render as `owner/name`; others render as `name`.
|
|
67
|
-
*/
|
|
68
|
-
export const toLabel = (target) => target.type === "pack" ? `${target.owner}/${target.name}` : target.name;
|
|
69
|
-
/**
|
|
70
|
-
* Produce a stable step identity key from an ExtensionTarget.
|
|
71
|
-
*
|
|
72
|
-
* This is internal plan identity, not display text.
|
|
73
|
-
*/
|
|
74
|
-
export const toStepKey = (target) => target.type === "pack"
|
|
75
|
-
? `${target.type}:${target.owner}/${target.name}`
|
|
76
|
-
: `${target.type}:${target.name}`;
|
|
77
|
-
/**
|
|
78
|
-
* Format a single PackageUrlParts as a compact display string.
|
|
79
|
-
*
|
|
80
|
-
* Examples: `pkg:npm/react`, `pkg:npm/@angular/core@18.0.0`
|
|
81
|
-
*/
|
|
82
|
-
export const formatPackageUrlParts = (parts) => {
|
|
83
|
-
const ns = parts.namespace !== undefined ? `${parts.namespace}/` : "";
|
|
84
|
-
const ver = parts.version !== undefined ? `@${parts.version}` : "";
|
|
85
|
-
return `pkg:${parts.type}/${ns}${parts.name}${ver}`;
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Build a display label with optional packages suffix.
|
|
89
|
-
*
|
|
90
|
-
* When packages is non-empty, appends them parenthesized:
|
|
91
|
-
* `code-review (pkg:npm/react, pkg:npm/typescript)`
|
|
92
|
-
*/
|
|
93
|
-
export const toLabelWithCompanions = (target, packages) => {
|
|
94
|
-
const base = toLabel(target);
|
|
95
|
-
if (packages.length === 0)
|
|
96
|
-
return base;
|
|
97
|
-
const purls = packages.map(formatPackageUrlParts).join(", ");
|
|
98
|
-
return `${base} (${purls})`;
|
|
99
|
-
};
|
|
100
|
-
const NO_PROJECTION_WARNINGS = [];
|
|
101
|
-
/**
|
|
102
|
-
* Render the manager's shared aggregate units and return the operator-facing
|
|
103
|
-
* report for every desired contributor those units could not render. The
|
|
104
|
-
* report travels with the step that performed the render.
|
|
105
|
-
*/
|
|
106
|
-
const applyManagerProjectionPlans = (manager) => manager.projectionPlans === undefined
|
|
107
|
-
? Effect.succeed(NO_PROJECTION_WARNINGS)
|
|
108
|
-
: manager
|
|
109
|
-
.projectionPlans()
|
|
110
|
-
.pipe(Effect.flatMap((plans) => applyProjectionPlans(plans).pipe(Effect.as(projectionPlanExclusionWarnings(plans)))));
|
|
111
|
-
const isConfigured = (manager, target) => {
|
|
112
|
-
if (manager.isConfigured !== undefined)
|
|
113
|
-
return manager.isConfigured({ target });
|
|
114
|
-
if (manager.getConfiguredSource === undefined)
|
|
115
|
-
return Effect.succeed(false);
|
|
116
|
-
return manager.getConfiguredSource({ target }).pipe(Effect.map(Option.isSome));
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Execute the canonical install sequence.
|
|
120
|
-
*
|
|
121
|
-
* Root installs materialize and commit desired state plus any accepted external
|
|
122
|
-
* resolution before validating the observable postcondition. Pack-derived
|
|
123
|
-
* installs omit the root settings declaration while retaining that resolution.
|
|
124
|
-
*/
|
|
125
|
-
const runInstallOperation = (manager, args) => Effect.gen(function* () {
|
|
126
|
-
const target = targetFromRef(args.ref);
|
|
127
|
-
const configuredSource = manager.getConfiguredSource === undefined
|
|
128
|
-
? Option.none()
|
|
129
|
-
: yield* manager.getConfiguredSource({ target });
|
|
130
|
-
const authority = evaluateSourceAuthority({
|
|
131
|
-
target: { ...target, identity: toStepKey(target) },
|
|
132
|
-
relationship: { kind: "root" },
|
|
133
|
-
requested: {
|
|
134
|
-
identity: `${args.ref.refType}:${toStepKey(target)}`,
|
|
135
|
-
workspace: args.ref.refType === "workspace",
|
|
136
|
-
},
|
|
137
|
-
...(Option.isNone(configuredSource)
|
|
138
|
-
? {}
|
|
139
|
-
: {
|
|
140
|
-
configured: {
|
|
141
|
-
identity: configuredSource.value,
|
|
142
|
-
workspace: isWorkspaceSourceLocator(configuredSource.value),
|
|
143
|
-
},
|
|
144
|
-
}),
|
|
145
|
-
...(args.allowWorkspaceReplacement === undefined
|
|
146
|
-
? {}
|
|
147
|
-
: { allowWorkspaceReplacement: args.allowWorkspaceReplacement }),
|
|
148
|
-
});
|
|
149
|
-
if (authority.kind === "blocked") {
|
|
150
|
-
return yield* new SourceAuthorityBlocked({
|
|
151
|
-
detail: authority.fact.detail,
|
|
152
|
-
recovery: authority.fact.recovery,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
const installedBefore = args.installedBefore === undefined ? false : yield* args.installedBefore;
|
|
156
|
-
const transaction = yield* runWorkspaceTransaction({
|
|
157
|
-
transition: Effect.gen(function* () {
|
|
158
|
-
const cleanupSupersededCanonical = manager.prepareSourceTransition === undefined
|
|
159
|
-
? Effect.void
|
|
160
|
-
: yield* manager.prepareSourceTransition({ ref: args.ref });
|
|
161
|
-
const materialization = yield* manager.materializeInstall({
|
|
162
|
-
ref: args.ref,
|
|
163
|
-
...(args.force === undefined ? {} : { force: args.force }),
|
|
164
|
-
});
|
|
165
|
-
if (!args.skipSettings) {
|
|
166
|
-
yield* manager.upsertSettingsEntry({
|
|
167
|
-
ref: args.ref,
|
|
168
|
-
versionRange: args.versionRange,
|
|
169
|
-
materialization: Option.some(materialization),
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
yield* manager.upsertLockfileEntry({
|
|
173
|
-
ref: args.ref,
|
|
174
|
-
materialization: Option.some(materialization),
|
|
175
|
-
});
|
|
176
|
-
yield* cleanupSupersededCanonical;
|
|
177
|
-
// Desired state and canonical content are committed; render every
|
|
178
|
-
// shared aggregate unit once from the complete contributor set.
|
|
179
|
-
const projectionWarnings = args.skipProjections !== true
|
|
180
|
-
? yield* applyManagerProjectionPlans(manager)
|
|
181
|
-
: NO_PROJECTION_WARNINGS;
|
|
182
|
-
return { installedBefore, materialization, projectionWarnings };
|
|
183
|
-
}),
|
|
184
|
-
validate: () => Effect.gen(function* () {
|
|
185
|
-
if (args.deferObservableValidation !== true) {
|
|
186
|
-
const installed = yield* manager.isInstalled({ target });
|
|
187
|
-
if (!installed) {
|
|
188
|
-
return yield* new LifecyclePostconditionViolated({
|
|
189
|
-
postcondition: "install-observable",
|
|
190
|
-
targetType: target.type,
|
|
191
|
-
targetName: target.name,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (args.skipSettings !== true &&
|
|
196
|
-
(manager.isConfigured !== undefined || manager.getConfiguredSource !== undefined)) {
|
|
197
|
-
const configured = yield* isConfigured(manager, target);
|
|
198
|
-
if (!configured) {
|
|
199
|
-
return yield* new LifecyclePostconditionViolated({
|
|
200
|
-
postcondition: "install-declared",
|
|
201
|
-
targetType: target.type,
|
|
202
|
-
targetName: target.name,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}),
|
|
207
|
-
});
|
|
208
|
-
const artifact = args.buildArtifact === undefined
|
|
209
|
-
? undefined
|
|
210
|
-
: yield* args.buildArtifact({
|
|
211
|
-
installedBefore,
|
|
212
|
-
materialization: Option.some(transaction.materialization),
|
|
213
|
-
});
|
|
214
|
-
const artifactWithLifecycle = artifact === undefined ||
|
|
215
|
-
args.ref.refType !== "registry" ||
|
|
216
|
-
args.ref.deprecation === undefined
|
|
217
|
-
? artifact
|
|
218
|
-
: { ...artifact, registryLifecycle: { deprecation: args.ref.deprecation } };
|
|
219
|
-
return {
|
|
220
|
-
result: "success",
|
|
221
|
-
message: args.message ?? "Applied install operation",
|
|
222
|
-
...(artifactWithLifecycle === undefined ? {} : { artifact: artifactWithLifecycle }),
|
|
223
|
-
...(transaction.projectionWarnings.length === 0
|
|
224
|
-
? {}
|
|
225
|
-
: { warnings: transaction.projectionWarnings }),
|
|
226
|
-
};
|
|
227
|
-
}).pipe(Effect.mapError(args.toStepFailure));
|
|
228
|
-
/**
|
|
229
|
-
* Build a PlannedJobStep for an install operation.
|
|
230
|
-
*
|
|
231
|
-
* The step keeps the manager's requirements and the transaction scope in its
|
|
232
|
-
* `run` effect; the command boundary composes them once.
|
|
233
|
-
*/
|
|
234
|
-
export const buildInstallOperation = (manager, args) => {
|
|
235
|
-
const target = targetFromRef(args.ref);
|
|
236
|
-
const companionPkgs = args.ref.refType === "registry" ? args.ref.packages : [];
|
|
237
|
-
const lifecycleWarnings = extensionRefLifecycleWarnings(args.ref);
|
|
238
|
-
const registryLifecycle = extensionRefRegistryLifecycle(args.ref);
|
|
239
|
-
// The proposed Registry identity travels with the step as structured data,
|
|
240
|
-
// so trust classification compares bindings rather than reading warnings.
|
|
241
|
-
const registryBinding = args.ref.refType === "registry"
|
|
242
|
-
? {
|
|
243
|
-
extensionType: args.ref.type,
|
|
244
|
-
target: target.name,
|
|
245
|
-
owner: args.ref.owner,
|
|
246
|
-
packageName: args.ref.name,
|
|
247
|
-
version: args.ref.version,
|
|
248
|
-
publisherBindingId: args.ref.publisherBindingId,
|
|
249
|
-
}
|
|
250
|
-
: undefined;
|
|
251
|
-
const base = {
|
|
252
|
-
key: toStepKey(target),
|
|
253
|
-
label: toLabelWithCompanions(target, companionPkgs),
|
|
254
|
-
run: runInstallOperation(manager, args),
|
|
255
|
-
...(registryLifecycle === undefined ? {} : { registryLifecycle }),
|
|
256
|
-
...(registryBinding === undefined ? {} : { registryBinding }),
|
|
257
|
-
};
|
|
258
|
-
return lifecycleWarnings.length === 0
|
|
259
|
-
? { ...base, readiness: "ready" }
|
|
260
|
-
: {
|
|
261
|
-
...base,
|
|
262
|
-
readiness: "warn",
|
|
263
|
-
warnMessage: lifecycleWarnings.join("; "),
|
|
264
|
-
};
|
|
265
|
-
};
|
|
266
|
-
/**
|
|
267
|
-
* Build a PlannedJobStep for `new` commands.
|
|
268
|
-
*
|
|
269
|
-
* A read-only preflight runs first. The transaction then snapshots the source
|
|
270
|
-
* path, scaffolds it, seeds desired state, resolves the canonical package, and
|
|
271
|
-
* materializes projections before validating the authored postcondition.
|
|
272
|
-
*/
|
|
273
|
-
export const buildAuthoredExtensionStep = (manager, args) => {
|
|
274
|
-
const target = args.target;
|
|
275
|
-
return {
|
|
276
|
-
key: toStepKey(target),
|
|
277
|
-
label: args.label ?? toLabel(target),
|
|
278
|
-
readiness: "ready",
|
|
279
|
-
...(args.plannedArtifact === undefined ? {} : { artifact: args.plannedArtifact }),
|
|
280
|
-
run: (args.allowConfiguredSourceTransition === true
|
|
281
|
-
? Effect.void
|
|
282
|
-
: manager.listMaterializable()).pipe(Effect.andThen(runWorkspaceTransaction({
|
|
283
|
-
targets: Array.from(new Set([args.location, ...(args.transactionTargets ?? [])])).sort(),
|
|
284
|
-
transition: Effect.gen(function* () {
|
|
285
|
-
if (args.preflight !== undefined)
|
|
286
|
-
yield* args.preflight;
|
|
287
|
-
yield* args.scaffold;
|
|
288
|
-
yield* args.markAuthored;
|
|
289
|
-
const materializable = yield* manager.listMaterializable();
|
|
290
|
-
const ref = materializable.find((candidate) => toStepKey(targetFromRef(candidate)) === toStepKey(target));
|
|
291
|
-
if (ref === undefined) {
|
|
292
|
-
return yield* new ScaffoldedExtensionUnresolved({
|
|
293
|
-
targetType: target.type,
|
|
294
|
-
targetName: target.name,
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
const installedBefore = args.installedBefore === undefined ? false : yield* args.installedBefore;
|
|
298
|
-
let materialization = Option.none();
|
|
299
|
-
if (args.enabled !== false || args.materializeWhenDisabled === true) {
|
|
300
|
-
materialization =
|
|
301
|
-
args.materializeInstall === undefined
|
|
302
|
-
? Option.some(yield* manager.materializeInstall({ ref }))
|
|
303
|
-
: yield* args.materializeInstall(ref);
|
|
304
|
-
}
|
|
305
|
-
yield* manager.upsertSettingsEntry({
|
|
306
|
-
ref,
|
|
307
|
-
versionRange: args.versionRange,
|
|
308
|
-
materialization,
|
|
309
|
-
});
|
|
310
|
-
if (args.finalizeAuthored !== undefined) {
|
|
311
|
-
yield* args.finalizeAuthored;
|
|
312
|
-
}
|
|
313
|
-
if (args.enabled === false && args.materializeWhenDisabled === true) {
|
|
314
|
-
yield* manager.materializeDeactivate({ target });
|
|
315
|
-
}
|
|
316
|
-
else if (args.enabled !== false) {
|
|
317
|
-
// Desired state is committed; render shared aggregate units once
|
|
318
|
-
// from the complete contributor set.
|
|
319
|
-
return {
|
|
320
|
-
ref,
|
|
321
|
-
installedBefore,
|
|
322
|
-
materialization,
|
|
323
|
-
projectionWarnings: yield* applyManagerProjectionPlans(manager),
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
return {
|
|
327
|
-
ref,
|
|
328
|
-
installedBefore,
|
|
329
|
-
materialization,
|
|
330
|
-
projectionWarnings: NO_PROJECTION_WARNINGS,
|
|
331
|
-
};
|
|
332
|
-
}),
|
|
333
|
-
validate: () => Effect.gen(function* () {
|
|
334
|
-
const installed = yield* manager.isInstalled({ target });
|
|
335
|
-
if (args.enabled !== false && !installed) {
|
|
336
|
-
return yield* new LifecyclePostconditionViolated({
|
|
337
|
-
postcondition: "new-observable",
|
|
338
|
-
targetType: target.type,
|
|
339
|
-
targetName: target.name,
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
if (manager.getConfiguredSource !== undefined) {
|
|
343
|
-
const configured = yield* manager.getConfiguredSource({ target });
|
|
344
|
-
if (Option.isNone(configured)) {
|
|
345
|
-
return yield* new LifecyclePostconditionViolated({
|
|
346
|
-
postcondition: "new-declared",
|
|
347
|
-
targetType: target.type,
|
|
348
|
-
targetName: target.name,
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}),
|
|
353
|
-
})), Effect.flatMap(({ installedBefore, materialization }) => Effect.gen(function* () {
|
|
354
|
-
const artifact = args.buildArtifact === undefined
|
|
355
|
-
? undefined
|
|
356
|
-
: yield* args.buildArtifact({ installedBefore, materialization });
|
|
357
|
-
return {
|
|
358
|
-
result: "success",
|
|
359
|
-
message: args.message,
|
|
360
|
-
...(artifact === undefined ? {} : { artifact }),
|
|
361
|
-
};
|
|
362
|
-
})), Effect.mapError(args.toStepFailure)),
|
|
363
|
-
};
|
|
364
|
-
};
|
|
365
|
-
/**
|
|
366
|
-
* Build a PlannedJobStep for existing `new` commands.
|
|
367
|
-
*
|
|
368
|
-
* New commands remain enabled by default while sharing the authored-package
|
|
369
|
-
* transaction used by fork and native import.
|
|
370
|
-
*/
|
|
371
|
-
export const buildNewExtensionStep = (manager, args) => {
|
|
372
|
-
if (args.ref.refType !== "workspace") {
|
|
373
|
-
return {
|
|
374
|
-
key: toStepKey(args.target),
|
|
375
|
-
label: args.label ?? toLabel(args.target),
|
|
376
|
-
readiness: "error",
|
|
377
|
-
errorMessage: "New authored extensions require a workspace source",
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
return buildAuthoredExtensionStep(manager, {
|
|
381
|
-
...args,
|
|
382
|
-
location: args.ref.location,
|
|
383
|
-
enabled: true,
|
|
384
|
-
});
|
|
385
|
-
};
|
|
386
|
-
const runMaterializeOperation = (manager, args) => Effect.gen(function* () {
|
|
387
|
-
const target = targetFromRef(args.ref);
|
|
388
|
-
const materialization = yield* runWorkspaceTransaction({
|
|
389
|
-
transition: Effect.gen(function* () {
|
|
390
|
-
const observed = yield* manager.materializeInstall({
|
|
391
|
-
ref: args.ref,
|
|
392
|
-
...(args.force === undefined ? {} : { force: args.force }),
|
|
393
|
-
});
|
|
394
|
-
if (args.validateMaterialized !== undefined) {
|
|
395
|
-
yield* args.validateMaterialized({ materialization: observed });
|
|
396
|
-
}
|
|
397
|
-
yield* manager.upsertLockfileEntry({
|
|
398
|
-
ref: args.ref,
|
|
399
|
-
materialization: Option.some(observed),
|
|
400
|
-
});
|
|
401
|
-
return observed;
|
|
402
|
-
}),
|
|
403
|
-
validate: () => manager.isInstalled({ target }).pipe(Effect.flatMap((installed) => installed
|
|
404
|
-
? Effect.void
|
|
405
|
-
: new LifecyclePostconditionViolated({
|
|
406
|
-
postcondition: "materialize-observable",
|
|
407
|
-
targetType: target.type,
|
|
408
|
-
targetName: target.name,
|
|
409
|
-
}))),
|
|
410
|
-
});
|
|
411
|
-
const artifact = args.buildArtifact === undefined ? undefined : yield* args.buildArtifact({ materialization });
|
|
412
|
-
return {
|
|
413
|
-
result: "success",
|
|
414
|
-
message: args.message ?? "Synced agent artifacts",
|
|
415
|
-
...(artifact === undefined ? {} : { artifact }),
|
|
416
|
-
};
|
|
417
|
-
}).pipe(Effect.mapError(args.toStepFailure));
|
|
418
|
-
export const buildMaterializeOperation = (manager, args) => {
|
|
419
|
-
const target = targetFromRef(args.ref);
|
|
420
|
-
const companionPkgs = args.ref.refType === "registry" ? args.ref.packages : [];
|
|
421
|
-
return {
|
|
422
|
-
key: toStepKey(target),
|
|
423
|
-
label: args.label ?? toLabelWithCompanions(target, companionPkgs),
|
|
424
|
-
readiness: "ready",
|
|
425
|
-
run: runMaterializeOperation(manager, args),
|
|
426
|
-
};
|
|
427
|
-
};
|
|
428
|
-
const uninstallSettlementMessage = (target, settlement) => {
|
|
429
|
-
const label = toLabel(target);
|
|
430
|
-
if (settlement.declaration === "absent" && settlement.canonical === "absent") {
|
|
431
|
-
return `${label} is already absent`;
|
|
432
|
-
}
|
|
433
|
-
switch (settlement.canonical) {
|
|
434
|
-
case "absent":
|
|
435
|
-
return `Unconfigured ${label}; no canonical package was present`;
|
|
436
|
-
case "removed":
|
|
437
|
-
return `Removed ${label}`;
|
|
438
|
-
case "retained-by-pack":
|
|
439
|
-
return `Unconfigured ${label}; retained its package because an installed pack still requires it`;
|
|
440
|
-
case "preserved-authored":
|
|
441
|
-
return `Unconfigured ${label}; preserved its workspace-authored source`;
|
|
442
|
-
case "preserved-unowned":
|
|
443
|
-
return `Unconfigured ${label}; preserved canonical content without an accepted source owner`;
|
|
444
|
-
case "preserved-unreadable":
|
|
445
|
-
return `Unconfigured ${label}; preserved its package because its manifest could not be read`;
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
/**
|
|
449
|
-
* Plain-language account of a registration-only removal: what was retired, why
|
|
450
|
-
* its content could not be verified, what was left in place, and what the
|
|
451
|
-
* operator can do about the remainder.
|
|
452
|
-
*/
|
|
453
|
-
const unreadablePackageWarning = (target, retirement) => `${toLabel(target)}: its package manifest ${retirement.reason === "missing" ? "is missing" : "cannot be read"} at ${retirement.manifestPath}, so AXM removed its configuration entry and accepted resolution and left its package content in place. Delete that content yourself once you no longer need it.`;
|
|
454
|
-
/**
|
|
455
|
-
* Execute the uninstall sequence with retention check.
|
|
456
|
-
*
|
|
457
|
-
* If the target is still required by an installed pack:
|
|
458
|
-
* 1. Remove settings entry
|
|
459
|
-
*
|
|
460
|
-
* If not required:
|
|
461
|
-
* 1. Unmaterialize from disk
|
|
462
|
-
* 2. Remove lockfile entry
|
|
463
|
-
* 3. Remove settings entry
|
|
464
|
-
*/
|
|
465
|
-
const runUninstallOperation = (manager, retentionPolicy, args) => Effect.gen(function* () {
|
|
466
|
-
const configuredSource = manager.getConfiguredSource === undefined
|
|
467
|
-
? Option.none()
|
|
468
|
-
: yield* manager.getConfiguredSource({ target: args.target });
|
|
469
|
-
const configured = yield* isConfigured(manager, args.target);
|
|
470
|
-
const transition = Effect.gen(function* () {
|
|
471
|
-
const applyProjections = () => args.skipProjections !== true
|
|
472
|
-
? applyManagerProjectionPlans(manager)
|
|
473
|
-
: Effect.succeed(NO_PROJECTION_WARNINGS);
|
|
474
|
-
if (args.retirement !== undefined) {
|
|
475
|
-
// Nothing about the package can be verified, so only the registration
|
|
476
|
-
// AXM itself wrote is removable. Canonical content stays untouched.
|
|
477
|
-
yield* manager.removeSettingsEntry({
|
|
478
|
-
target: args.target,
|
|
479
|
-
materialization: Option.none(),
|
|
480
|
-
});
|
|
481
|
-
yield* manager.removeLockfileEntry({
|
|
482
|
-
target: args.target,
|
|
483
|
-
materialization: Option.none(),
|
|
484
|
-
});
|
|
485
|
-
return {
|
|
486
|
-
settlement: {
|
|
487
|
-
declaration: "removed",
|
|
488
|
-
canonical: "preserved-unreadable",
|
|
489
|
-
},
|
|
490
|
-
unmaterialization: Option.none(),
|
|
491
|
-
expectedInstalled: undefined,
|
|
492
|
-
projectionWarnings: yield* applyProjections(),
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
const isInstalled = yield* manager.isInstalled({ target: args.target });
|
|
496
|
-
if (!isInstalled) {
|
|
497
|
-
if (configured) {
|
|
498
|
-
// Configured extensions may still own native agent projections even
|
|
499
|
-
// when they have no canonical managed package on disk.
|
|
500
|
-
const withdrawn = yield* manager.materializeUninstall({ target: args.target });
|
|
501
|
-
const unmaterialization = Option.some(withdrawn);
|
|
502
|
-
yield* manager.removeSettingsEntry({
|
|
503
|
-
target: args.target,
|
|
504
|
-
materialization: unmaterialization,
|
|
505
|
-
});
|
|
506
|
-
yield* manager.removeLockfileEntry({
|
|
507
|
-
target: args.target,
|
|
508
|
-
materialization: unmaterialization,
|
|
509
|
-
});
|
|
510
|
-
return {
|
|
511
|
-
settlement: {
|
|
512
|
-
declaration: "removed",
|
|
513
|
-
canonical: "absent",
|
|
514
|
-
},
|
|
515
|
-
unmaterialization,
|
|
516
|
-
expectedInstalled: false,
|
|
517
|
-
projectionWarnings: yield* applyProjections(),
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
return {
|
|
521
|
-
settlement: {
|
|
522
|
-
declaration: "absent",
|
|
523
|
-
canonical: "absent",
|
|
524
|
-
},
|
|
525
|
-
unmaterialization: Option.none(),
|
|
526
|
-
expectedInstalled: false,
|
|
527
|
-
projectionWarnings: NO_PROJECTION_WARNINGS,
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
const stillRequiredByPack = yield* retentionPolicy.isRequiredByInstalledPack({
|
|
531
|
-
target: args.target,
|
|
532
|
-
});
|
|
533
|
-
if (stillRequiredByPack) {
|
|
534
|
-
yield* manager.removeSettingsEntry({ target: args.target, materialization: Option.none() });
|
|
535
|
-
return {
|
|
536
|
-
settlement: {
|
|
537
|
-
declaration: "removed",
|
|
538
|
-
canonical: "retained-by-pack",
|
|
539
|
-
},
|
|
540
|
-
unmaterialization: Option.none(),
|
|
541
|
-
expectedInstalled: true,
|
|
542
|
-
projectionWarnings: yield* applyProjections(),
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
const unmaterialization = Option.some(yield* manager.materializeUninstall({ target: args.target }));
|
|
546
|
-
yield* manager.removeSettingsEntry({
|
|
547
|
-
target: args.target,
|
|
548
|
-
materialization: unmaterialization,
|
|
549
|
-
});
|
|
550
|
-
yield* manager.removeLockfileEntry({
|
|
551
|
-
target: args.target,
|
|
552
|
-
materialization: unmaterialization,
|
|
553
|
-
});
|
|
554
|
-
// The target has left the desired-state graph; re-render every shared
|
|
555
|
-
// aggregate unit once so only reachable contributors remain.
|
|
556
|
-
const projectionWarnings = yield* applyProjections();
|
|
557
|
-
return {
|
|
558
|
-
projectionWarnings,
|
|
559
|
-
unmaterialization,
|
|
560
|
-
settlement: {
|
|
561
|
-
declaration: "removed",
|
|
562
|
-
canonical: Option.match(configuredSource, {
|
|
563
|
-
onNone: () => "preserved-unowned",
|
|
564
|
-
onSome: (source) => isWorkspaceSourceLocator(source)
|
|
565
|
-
? "preserved-authored"
|
|
566
|
-
: "removed",
|
|
567
|
-
}),
|
|
568
|
-
},
|
|
569
|
-
expectedInstalled: Option.match(configuredSource, {
|
|
570
|
-
onNone: () => undefined,
|
|
571
|
-
onSome: (source) => (isWorkspaceSourceLocator(source) ? undefined : false),
|
|
572
|
-
}),
|
|
573
|
-
};
|
|
574
|
-
});
|
|
575
|
-
const result = yield* runWorkspaceTransaction({
|
|
576
|
-
transition,
|
|
577
|
-
validate: (outcome) => Effect.gen(function* () {
|
|
578
|
-
if (manager.isConfigured !== undefined || manager.getConfiguredSource !== undefined) {
|
|
579
|
-
const remainsConfigured = yield* isConfigured(manager, args.target);
|
|
580
|
-
if (remainsConfigured) {
|
|
581
|
-
return yield* new LifecyclePostconditionViolated({
|
|
582
|
-
postcondition: "uninstall-remains-declared",
|
|
583
|
-
targetType: args.target.type,
|
|
584
|
-
targetName: args.target.name,
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
const installed = yield* manager.isInstalled({ target: args.target });
|
|
589
|
-
if (outcome.expectedInstalled !== undefined && installed !== outcome.expectedInstalled) {
|
|
590
|
-
return yield* new LifecyclePostconditionViolated({
|
|
591
|
-
postcondition: "uninstall-observed-state",
|
|
592
|
-
targetType: args.target.type,
|
|
593
|
-
targetName: args.target.name,
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
}),
|
|
597
|
-
});
|
|
598
|
-
const warnings = [
|
|
599
|
-
...(args.retirement === undefined
|
|
600
|
-
? []
|
|
601
|
-
: [unreadablePackageWarning(args.target, args.retirement)]),
|
|
602
|
-
...result.projectionWarnings,
|
|
603
|
-
];
|
|
604
|
-
const artifact = args.buildArtifact === undefined
|
|
605
|
-
? undefined
|
|
606
|
-
: yield* args.buildArtifact({
|
|
607
|
-
settlement: result.settlement,
|
|
608
|
-
unmaterialization: result.unmaterialization,
|
|
609
|
-
});
|
|
610
|
-
return {
|
|
611
|
-
result: "success",
|
|
612
|
-
message: uninstallSettlementMessage(args.target, result.settlement),
|
|
613
|
-
...(result.settlement.declaration === "absent" ? { disposition: "unchanged" } : {}),
|
|
614
|
-
...(artifact === undefined ? {} : { artifact }),
|
|
615
|
-
...(warnings.length === 0 ? {} : { warnings }),
|
|
616
|
-
};
|
|
617
|
-
}).pipe(Effect.mapError(args.toStepFailure));
|
|
618
|
-
/**
|
|
619
|
-
* Build a PlannedJobStep for an uninstall operation.
|
|
620
|
-
*
|
|
621
|
-
* The step keeps the manager's requirements and the transaction scope in its
|
|
622
|
-
* `run` effect; the command boundary composes them once.
|
|
623
|
-
*/
|
|
624
|
-
export const buildUninstallOperation = (manager, retentionPolicy, args) => {
|
|
625
|
-
return {
|
|
626
|
-
label: toLabel(args.target),
|
|
627
|
-
readiness: "ready",
|
|
628
|
-
run: runUninstallOperation(manager, retentionPolicy, args),
|
|
629
|
-
};
|
|
630
|
-
};
|
|
631
|
-
//# sourceMappingURL=operations.js.map
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Materializing an authored MCP server package during create, fork, adopt, and
|
|
3
|
-
* native import.
|
|
4
|
-
*
|
|
5
|
-
* The authored closure recipe accepts a type-specific materialization because
|
|
6
|
-
* an MCP server's canonical content is realized by the install operation
|
|
7
|
-
* rather than by its manager. Both live in this capability, so every authoring
|
|
8
|
-
* route reaches the same realization without importing a peer feature.
|
|
9
|
-
*
|
|
10
|
-
* @experimental This API is unstable and may change without notice.
|
|
11
|
-
*/
|
|
12
|
-
import * as Effect from "effect/Effect";
|
|
13
|
-
import * as Option from "effect/Option";
|
|
14
|
-
import type { McpServerExtensionRef } from "@agentxm/extension-model/unstable/extensions/refs/mcp-server";
|
|
15
|
-
import type { McpServerMaterializationFacts } from "../managers.js";
|
|
16
|
-
import type { ExtensionManagerFailure } from "../errors.js";
|
|
17
|
-
import { type McpServerInstallRequirements } from "./install-operation.js";
|
|
18
|
-
/**
|
|
19
|
-
* Realize the authored package's canonical content and native projections
|
|
20
|
-
* without touching workspace state: the authored closure commits desired state
|
|
21
|
-
* itself. Reports no acquisition facts — an authored package has no accepted
|
|
22
|
-
* registry resolution for the entry writers to record.
|
|
23
|
-
*/
|
|
24
|
-
export declare const materializeAuthoredMcpServer: (args: {
|
|
25
|
-
readonly ref: McpServerExtensionRef;
|
|
26
|
-
readonly nonInteractive: boolean;
|
|
27
|
-
}) => Effect.Effect<Option.Option<McpServerMaterializationFacts>, ExtensionManagerFailure, McpServerInstallRequirements>;
|
|
28
|
-
//# sourceMappingURL=authored-materialization.d.ts.map
|