@agentxm/extension-lifecycle 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/activation/set-activation.d.ts +22 -40
- package/dist/src/activation/set-activation.js +199 -331
- package/dist/src/demote/demote-to-external-source.d.ts +1 -1
- package/dist/src/demote/demote-to-external-source.js +53 -24
- package/dist/src/hooks/configured-agent-outcomes-provider.d.ts +4 -4
- package/dist/src/hooks/configured-agent-outcomes-provider.js +23 -17
- package/dist/src/hooks/install/plan.js +6 -3
- package/dist/src/hooks/uninstall/plan.js +4 -3
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.js +1 -2
- package/dist/src/install/root-intent.d.ts +2 -2
- package/dist/src/install/vocabulary.d.ts +5 -4
- package/dist/src/knowledge/install/plan.js +2 -1
- package/dist/src/knowledge/uninstall/plan.js +4 -3
- package/dist/src/live.d.ts +1 -1
- package/dist/src/live.js +1 -1
- package/dist/src/mcps/install/plan.js +2 -3
- package/dist/src/mcps/operations/disable.js +1 -1
- package/dist/src/mcps/operations/enable.js +20 -35
- package/dist/src/mcps/operations/uninstall.js +2 -1
- package/dist/src/mcps/uninstall/plan.js +13 -4
- package/dist/src/packs/graph-transition.d.ts +0 -25
- package/dist/src/packs/graph-transition.js +0 -101
- package/dist/src/packs/install/plan.d.ts +0 -13
- package/dist/src/packs/install/plan.js +12 -9
- package/dist/src/packs/member-install-step.js +8 -21
- package/dist/src/packs/promote-authored-pack.js +6 -3
- package/dist/src/packs/uninstall/plan.js +52 -20
- package/dist/src/rules/install/plan.js +6 -3
- package/dist/src/rules/uninstall/plan.js +4 -3
- package/dist/src/skills/install/bundled.js +4 -4
- package/dist/src/skills/install/plan.js +3 -2
- package/dist/src/skills/operations/install.d.ts +0 -1
- package/dist/src/skills/operations/install.js +9 -18
- package/dist/src/skills/uninstall/plan.js +4 -3
- package/dist/src/subagents/install/plan.js +3 -2
- package/dist/src/subagents/operations/enable.js +1 -3
- package/dist/src/subagents/uninstall/plan.js +4 -3
- package/dist/src/testing.d.ts +1 -1
- package/dist/src/testing.js +2 -1
- package/dist/src/uninstall/root-intent.d.ts +1 -1
- package/dist/src/uninstall/uninstall-extensions.d.ts +1 -1
- package/dist/src/uninstall/uninstall-extensions.js +77 -1
- package/dist/src/update/root-request.d.ts +2 -2
- package/dist/src/update/selective/skills.d.ts +1 -1
- package/dist/src/update/selective/skills.js +0 -1
- package/dist/src/update/selective/subagents.d.ts +1 -1
- package/dist/src/update/selective/subagents.js +3 -2
- package/dist/src/update/selective/use-case.d.ts +2 -2
- package/dist/src/update/targeted-plan.js +4 -2
- package/dist/src/workspace-paths.d.ts +0 -6
- package/dist/src/workspace-paths.js +0 -10
- package/package.json +22 -24
- package/dist/src/uninstall/retention-policy.d.ts +0 -21
- package/dist/src/uninstall/retention-policy.js +0 -28
|
@@ -11,109 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import * as Effect from "effect/Effect";
|
|
13
13
|
import { WorkspaceMutations, desiredStateProblemsText, } from "@agentxm/workspace-state";
|
|
14
|
-
import { runWorkspaceTransaction } from "@agentxm/workspace-transactions";
|
|
15
|
-
import { StepFailure, } from "@agentxm/workspace-operations";
|
|
16
|
-
import { lifecycleStepFailure } from "../step-failure.js";
|
|
17
14
|
import { installRefused } from "../install/vocabulary.js";
|
|
18
15
|
const normalizedIdentity = (identity) => identity.startsWith("workspace:") ? identity.slice("workspace:".length) : identity;
|
|
19
|
-
const failedStep = (label, result) => result.result === "error"
|
|
20
|
-
? Effect.fail(result.error ??
|
|
21
|
-
lifecycleStepFailure(installRefused({
|
|
22
|
-
category: "internal",
|
|
23
|
-
detail: `${label} failed: ${result.message}`,
|
|
24
|
-
})))
|
|
25
|
-
: Effect.succeed(result);
|
|
26
|
-
const aggregatePackCoverage = (results, scope) => Effect.gen(function* () {
|
|
27
|
-
const applicableArtifacts = results.flatMap(({ result, coverage }) => coverage === "eligible" &&
|
|
28
|
-
result.result === "success" &&
|
|
29
|
-
result.artifact?.agents !== undefined
|
|
30
|
-
? [result.artifact]
|
|
31
|
-
: []);
|
|
32
|
-
const agents = [];
|
|
33
|
-
for (const artifact of applicableArtifacts) {
|
|
34
|
-
if (artifact.scope !== scope) {
|
|
35
|
-
return yield* installRefused({
|
|
36
|
-
category: "internal",
|
|
37
|
-
detail: `Pack coverage spans ${scope} and ${artifact.scope} scopes`,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
const artifactAgents = new Set(artifact.agents);
|
|
41
|
-
for (const target of artifact.targets ?? []) {
|
|
42
|
-
for (const agent of target.agentIds ?? []) {
|
|
43
|
-
if (!artifactAgents.has(agent)) {
|
|
44
|
-
return yield* installRefused({
|
|
45
|
-
category: "internal",
|
|
46
|
-
detail: `Pack child target agent ${agent} is absent from its artifact agents`,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
for (const agent of artifact.agents ?? []) {
|
|
52
|
-
if (agent !== "universal" && !agents.includes(agent))
|
|
53
|
-
agents.push(agent);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return { applicable: applicableArtifacts.length > 0, agents };
|
|
57
|
-
});
|
|
58
|
-
/** Wrap a pack transition's children in one workspace transaction. */
|
|
59
|
-
export const buildAtomicPackGraphStep = (args) => Effect.sync(() => {
|
|
60
|
-
const readinessErrors = args.children.flatMap(({ step }) => step.readiness === "error" ? [step.errorMessage] : []);
|
|
61
|
-
if (readinessErrors.length > 0) {
|
|
62
|
-
const blockingConditionIds = args.children.flatMap(({ step }) => step.readiness === "error" ? (step.blockingConditionIds ?? []) : []);
|
|
63
|
-
return {
|
|
64
|
-
readiness: "error",
|
|
65
|
-
label: args.label,
|
|
66
|
-
errorMessage: readinessErrors.join("; "),
|
|
67
|
-
artifact: args.artifact,
|
|
68
|
-
...(blockingConditionIds.length === 0 ? {} : { blockingConditionIds }),
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
const readinessWarnings = args.children.flatMap(({ step }) => step.readiness === "warn" ? [step.warnMessage] : []);
|
|
72
|
-
const runnableChildren = args.children.filter((child) => child.step.readiness !== "error");
|
|
73
|
-
let validatedCoverage = { applicable: false, agents: [] };
|
|
74
|
-
const run = runWorkspaceTransaction({
|
|
75
|
-
transition: Effect.gen(function* () {
|
|
76
|
-
if (args.preTransition !== undefined) {
|
|
77
|
-
yield* args.preTransition.pipe(Effect.mapError(lifecycleStepFailure));
|
|
78
|
-
}
|
|
79
|
-
return yield* Effect.forEach(runnableChildren, ({ step, coverage }) => step.run.pipe(Effect.flatMap((result) => failedStep(step.label, result)), Effect.map((result) => ({ result, coverage }))), { concurrency: 1 });
|
|
80
|
-
}),
|
|
81
|
-
validate: (results) => Effect.gen(function* () {
|
|
82
|
-
yield* args.validate;
|
|
83
|
-
validatedCoverage = yield* aggregatePackCoverage(results, args.artifact.scope);
|
|
84
|
-
}).pipe(Effect.mapError(lifecycleStepFailure)),
|
|
85
|
-
}).pipe(Effect.mapError(lifecycleStepFailure), Effect.map((results) => {
|
|
86
|
-
const warnings = results.flatMap(({ result }) => result.result === "success" ? (result.warnings ?? []) : []);
|
|
87
|
-
const allChildrenUnchanged = args.reportUnchangedWhenChildrenUnchanged === true &&
|
|
88
|
-
results.length > 0 &&
|
|
89
|
-
results.every(({ result }) => result.result === "success" && result.artifact?.change === "unchanged");
|
|
90
|
-
const artifact = allChildrenUnchanged
|
|
91
|
-
? { ...args.artifact, change: "unchanged" }
|
|
92
|
-
: args.artifact;
|
|
93
|
-
return {
|
|
94
|
-
result: "success",
|
|
95
|
-
message: args.message,
|
|
96
|
-
artifact: !validatedCoverage.applicable
|
|
97
|
-
? artifact
|
|
98
|
-
: { ...artifact, agents: validatedCoverage.agents },
|
|
99
|
-
...(warnings.length === 0 ? {} : { warnings }),
|
|
100
|
-
};
|
|
101
|
-
}));
|
|
102
|
-
return readinessWarnings.length === 0
|
|
103
|
-
? {
|
|
104
|
-
readiness: "ready",
|
|
105
|
-
label: args.label,
|
|
106
|
-
artifact: args.artifact,
|
|
107
|
-
run,
|
|
108
|
-
}
|
|
109
|
-
: {
|
|
110
|
-
readiness: "warn",
|
|
111
|
-
label: args.label,
|
|
112
|
-
warnMessage: readinessWarnings.join("; "),
|
|
113
|
-
artifact: args.artifact,
|
|
114
|
-
run,
|
|
115
|
-
};
|
|
116
|
-
});
|
|
117
16
|
/** The desired-graph predicate a completed pack transition must satisfy. */
|
|
118
17
|
export const validatePackGraphPostcondition = (args) => Effect.gen(function* () {
|
|
119
18
|
const ws = yield* WorkspaceMutations;
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Installing a pack.
|
|
3
|
-
*
|
|
4
|
-
* A pack install is a graph transition, not a package copy: the pack's own
|
|
5
|
-
* package, every member its manifest resolves to, and every member the
|
|
6
|
-
* previous graph owned and this one drops all change together. Workspace
|
|
7
|
-
* source authority decides whether a locally-authored package may stand in
|
|
8
|
-
* for a declared member, the minimum-release-age policy decides whether a
|
|
9
|
-
* held-back release preserves the current graph or blocks, and the transition
|
|
10
|
-
* is refused if the authority it was planned against changed underneath it.
|
|
11
|
-
*
|
|
12
|
-
* @experimental This API is unstable and may change without notice.
|
|
13
|
-
*/
|
|
14
1
|
import * as Effect from "effect/Effect";
|
|
15
2
|
import * as Option from "effect/Option";
|
|
16
3
|
import * as Path from "effect/Path";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildReconciliationClosure } from "@agentxm/workspace-reconciliation";
|
|
1
2
|
/**
|
|
2
3
|
* Installing a pack.
|
|
3
4
|
*
|
|
@@ -16,7 +17,8 @@ import * as Effect from "effect/Effect";
|
|
|
16
17
|
import * as Option from "effect/Option";
|
|
17
18
|
import * as Path from "effect/Path";
|
|
18
19
|
import * as Result from "effect/Result";
|
|
19
|
-
import { HookManager, KnowledgeManager, McpServerManager, PackManager, RuleManager, SkillManager, SubagentManager,
|
|
20
|
+
import { HookManager, KnowledgeManager, McpServerManager, PackManager, RuleManager, SkillManager, SubagentManager, } from "@agentxm/extension-materialization";
|
|
21
|
+
import { buildInstallOperation, buildUninstallOperation, targetFromRef, toLabel, } from "@agentxm/workspace-reconciliation";
|
|
20
22
|
import { parseExtensionFqnParts, toExtensionTypePlural, } from "@agentxm/extension-model/unstable/extensions";
|
|
21
23
|
import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
|
|
22
24
|
import { versionSatisfiesRange, } from "@agentxm/extension-model/unstable/version-constraints";
|
|
@@ -31,10 +33,10 @@ import { registryLoginSuggestions } from "../../install/registry-login-suggestio
|
|
|
31
33
|
import { formatRegistryProbe, sourceFailureDetail, } from "../../install/registry-source-resolution.js";
|
|
32
34
|
import { installRefused, } from "../../install/vocabulary.js";
|
|
33
35
|
import { expandPackInstallRefs, expandPackInstallRefsWithReleaseAge } from "../expansion.js";
|
|
34
|
-
import {
|
|
36
|
+
import { validatePackGraphPostcondition } from "../graph-transition.js";
|
|
35
37
|
import { buildPackMemberInstallStep } from "../member-install-step.js";
|
|
36
38
|
import { registrySourceArtifact, registrySourcePath } from "../artifact.js";
|
|
37
|
-
import { makeWorkspaceRetentionPolicy } from "
|
|
39
|
+
import { makeWorkspaceRetentionPolicy } from "@agentxm/workspace-reconciliation";
|
|
38
40
|
const isRemoteReadNotImplemented = (error) => {
|
|
39
41
|
const detail = sourceFailureDetail(error);
|
|
40
42
|
return detail.includes("not implemented") || detail.includes("not yet supported");
|
|
@@ -661,12 +663,12 @@ export const planPackInstall = Effect.fn("InstallExtensions.planPack")(function*
|
|
|
661
663
|
// cleanup by suppressing dropped-member removal until the pre-install graph
|
|
662
664
|
// is complete.
|
|
663
665
|
const existingPack = graph.complete ? currentPackNode : undefined;
|
|
664
|
-
const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
|
|
666
|
+
const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
|
|
665
667
|
const installSteps = yield* Effect.forEach(refs, (ref) => ref.type === "pack"
|
|
666
668
|
? Effect.succeed(buildInstallOperation(packManager, {
|
|
667
669
|
toStepFailure: lifecycleStepFailure,
|
|
668
670
|
ref,
|
|
669
|
-
versionRange: intent.versionRange,
|
|
671
|
+
declaration: { name: ref.pack.name, versionRange: intent.versionRange },
|
|
670
672
|
...(intent.forceCanonical === true ? { force: true } : {}),
|
|
671
673
|
installedBefore: graph.complete
|
|
672
674
|
? packManager.isInstalled({
|
|
@@ -724,19 +726,19 @@ export const planPackInstall = Effect.fn("InstallExtensions.planPack")(function*
|
|
|
724
726
|
return buildUninstallOperation(ruleManager, retentionPolicy, {
|
|
725
727
|
toStepFailure: lifecycleStepFailure,
|
|
726
728
|
target,
|
|
727
|
-
|
|
729
|
+
enclosingClosure: { projections: [target.type] },
|
|
728
730
|
});
|
|
729
731
|
case "hook":
|
|
730
732
|
return buildUninstallOperation(hookManager, retentionPolicy, {
|
|
731
733
|
toStepFailure: lifecycleStepFailure,
|
|
732
734
|
target,
|
|
733
|
-
|
|
735
|
+
enclosingClosure: { projections: [target.type] },
|
|
734
736
|
});
|
|
735
737
|
case "knowledge":
|
|
736
738
|
return buildUninstallOperation(knowledgeManager, retentionPolicy, {
|
|
737
739
|
toStepFailure: lifecycleStepFailure,
|
|
738
740
|
target,
|
|
739
|
-
|
|
741
|
+
enclosingClosure: { projections: [target.type] },
|
|
740
742
|
});
|
|
741
743
|
}
|
|
742
744
|
});
|
|
@@ -777,7 +779,8 @@ export const planPackInstall = Effect.fn("InstallExtensions.planPack")(function*
|
|
|
777
779
|
...droppedTargets.map(({ target }) => target.type),
|
|
778
780
|
]),
|
|
779
781
|
});
|
|
780
|
-
const graphStep = yield*
|
|
782
|
+
const graphStep = yield* buildReconciliationClosure({
|
|
783
|
+
toStepFailure: lifecycleStepFailure,
|
|
781
784
|
label: packIdentity,
|
|
782
785
|
message: `Installed ${packIdentity} and ${refs.length - 1} pack member${refs.length === 2 ? "" : "s"}`,
|
|
783
786
|
artifact: {
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import * as Effect from "effect/Effect";
|
|
12
12
|
import * as Option from "effect/Option";
|
|
13
|
-
import { HookManager, KnowledgeManager, NO_MATERIALIZATION_OBSERVATION, RuleManager, SkillManager, SubagentManager,
|
|
13
|
+
import { HookManager, KnowledgeManager, NO_MATERIALIZATION_OBSERVATION, RuleManager, SkillManager, SubagentManager, } from "@agentxm/extension-materialization";
|
|
14
|
+
import { installMcpServer } from "@agentxm/workspace-reconciliation";
|
|
15
|
+
import { buildInstallOperation, extensionRefLifecycleWarnings, extensionRefRegistryLifecycle, toLabelWithCompanions, } from "@agentxm/workspace-reconciliation";
|
|
14
16
|
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
15
17
|
import { lifecycleStepFailure } from "../step-failure.js";
|
|
16
18
|
import { registrySourceArtifact } from "./artifact.js";
|
|
@@ -28,9 +30,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
|
|
|
28
30
|
return buildInstallOperation(skillManager, {
|
|
29
31
|
toStepFailure: lifecycleStepFailure,
|
|
30
32
|
ref,
|
|
31
|
-
|
|
32
|
-
skipSettings: true,
|
|
33
|
-
deferObservableValidation: true,
|
|
33
|
+
enclosingClosure: { projections: [], postconditions: [ref.type] },
|
|
34
34
|
installedBefore: args.graphComplete
|
|
35
35
|
? skillManager.isInstalled({ target: { type: "skill", name: ref.skill.name } })
|
|
36
36
|
: Effect.succeed(false),
|
|
@@ -55,8 +55,6 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
|
|
|
55
55
|
ref,
|
|
56
56
|
nonInteractive: args.nonInteractive,
|
|
57
57
|
force: false,
|
|
58
|
-
versionRange: Option.none(),
|
|
59
|
-
skipSettings: Option.some(true),
|
|
60
58
|
strictAgentSync: Option.some(true),
|
|
61
59
|
env: Option.none(),
|
|
62
60
|
},
|
|
@@ -82,9 +80,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
|
|
|
82
80
|
return buildInstallOperation(subagentManager, {
|
|
83
81
|
toStepFailure: lifecycleStepFailure,
|
|
84
82
|
ref,
|
|
85
|
-
|
|
86
|
-
skipSettings: true,
|
|
87
|
-
deferObservableValidation: true,
|
|
83
|
+
enclosingClosure: { projections: [], postconditions: [ref.type] },
|
|
88
84
|
installedBefore: args.graphComplete
|
|
89
85
|
? subagentManager.isInstalled({ target: { type: "subagent", name: ref.subagent.name } })
|
|
90
86
|
: Effect.succeed(false),
|
|
@@ -104,10 +100,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
|
|
|
104
100
|
return buildInstallOperation(ruleManager, {
|
|
105
101
|
toStepFailure: lifecycleStepFailure,
|
|
106
102
|
ref,
|
|
107
|
-
|
|
108
|
-
skipSettings: true,
|
|
109
|
-
skipProjections: true,
|
|
110
|
-
deferObservableValidation: true,
|
|
103
|
+
enclosingClosure: { projections: [ref.type], postconditions: [ref.type] },
|
|
111
104
|
installedBefore: args.graphComplete
|
|
112
105
|
? ruleManager.isInstalled({ target: { type: "rule", name: ref.rule.name } })
|
|
113
106
|
: Effect.succeed(false),
|
|
@@ -124,10 +117,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
|
|
|
124
117
|
return buildInstallOperation(hookManager, {
|
|
125
118
|
toStepFailure: lifecycleStepFailure,
|
|
126
119
|
ref,
|
|
127
|
-
|
|
128
|
-
skipSettings: true,
|
|
129
|
-
skipProjections: true,
|
|
130
|
-
deferObservableValidation: true,
|
|
120
|
+
enclosingClosure: { projections: [ref.type], postconditions: [ref.type] },
|
|
131
121
|
installedBefore: args.graphComplete
|
|
132
122
|
? hookManager.isInstalled({ target: { type: "hook", name: ref.hook.name } })
|
|
133
123
|
: Effect.succeed(false),
|
|
@@ -143,10 +133,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
|
|
|
143
133
|
return buildInstallOperation(knowledgeManager, {
|
|
144
134
|
toStepFailure: lifecycleStepFailure,
|
|
145
135
|
ref,
|
|
146
|
-
|
|
147
|
-
skipSettings: true,
|
|
148
|
-
skipProjections: true,
|
|
149
|
-
deferObservableValidation: true,
|
|
136
|
+
enclosingClosure: { projections: [ref.type], postconditions: [ref.type] },
|
|
150
137
|
installedBefore: args.graphComplete
|
|
151
138
|
? knowledgeManager.isInstalled({ target: { type: "knowledge", name: ref.knowledge.name } })
|
|
152
139
|
: Effect.succeed(false),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildReconciliationClosure } from "@agentxm/workspace-reconciliation";
|
|
1
2
|
/**
|
|
2
3
|
* Unpacking a Pack: promoting its members to direct declarations.
|
|
3
4
|
*
|
|
@@ -22,12 +23,13 @@
|
|
|
22
23
|
import * as Effect from "effect/Effect";
|
|
23
24
|
import * as Option from "effect/Option";
|
|
24
25
|
import * as Path from "effect/Path";
|
|
25
|
-
import { PackManager
|
|
26
|
+
import { PackManager } from "@agentxm/extension-materialization";
|
|
27
|
+
import { buildUninstallOperation, } from "@agentxm/workspace-reconciliation";
|
|
26
28
|
import { operationPresentation, prepareExecutionCandidate, resolveExecutionCandidate, } from "@agentxm/workspace-operations";
|
|
27
29
|
import { WorkspaceMutations, usableAcceptedCanonical, } from "@agentxm/workspace-state";
|
|
28
30
|
import { ExtensionLifecycleFailed } from "../errors.js";
|
|
29
31
|
import { lifecycleStepFailure } from "../step-failure.js";
|
|
30
|
-
import {
|
|
32
|
+
import { validatePackGraphPostcondition } from "./graph-transition.js";
|
|
31
33
|
// -----------------------------------------------------------------------------
|
|
32
34
|
// Promotion
|
|
33
35
|
// -----------------------------------------------------------------------------
|
|
@@ -186,7 +188,8 @@ const settleUnpack = Effect.fn("PromoteAuthoredPack.prepare")(function* (request
|
|
|
186
188
|
})),
|
|
187
189
|
{ path: packDisplayPath(path, ws, packNode), change: "removed" },
|
|
188
190
|
];
|
|
189
|
-
const graphStep = yield*
|
|
191
|
+
const graphStep = yield* buildReconciliationClosure({
|
|
192
|
+
toStepFailure: lifecycleStepFailure,
|
|
190
193
|
label: packNode.identity,
|
|
191
194
|
message: `Unpacked ${packNode.identity} into ${promotions.length} direct declaration${promotions.length === 1 ? "" : "s"}`,
|
|
192
195
|
artifact: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildReconciliationClosure } from "@agentxm/workspace-reconciliation";
|
|
1
2
|
/**
|
|
2
3
|
* Uninstalling packs.
|
|
3
4
|
*
|
|
@@ -13,7 +14,8 @@ import * as Effect from "effect/Effect";
|
|
|
13
14
|
import * as FileSystem from "effect/FileSystem";
|
|
14
15
|
import * as Option from "effect/Option";
|
|
15
16
|
import * as Path from "effect/Path";
|
|
16
|
-
import { HookManager, KnowledgeManager, McpServerManager, PackManager, RuleManager, SkillManager, SubagentManager,
|
|
17
|
+
import { HookManager, KnowledgeManager, McpServerManager, PackManager, RuleManager, SkillManager, SubagentManager, } from "@agentxm/extension-materialization";
|
|
18
|
+
import { buildUninstallOperation, prepareUninstallArtifact, collectCleanupStep, proposeDesiredState, } from "@agentxm/workspace-reconciliation";
|
|
17
19
|
import { parseExtensionFqnParts, } from "@agentxm/extension-model/unstable/extensions";
|
|
18
20
|
import { operationPresentation, } from "@agentxm/workspace-operations";
|
|
19
21
|
import { WorkspaceMutations, decodeDesiredExtensionIdentity, } from "@agentxm/workspace-state";
|
|
@@ -21,9 +23,8 @@ import { expandGlob } from "../../glob.js";
|
|
|
21
23
|
import { lifecycleStepFailure } from "../../step-failure.js";
|
|
22
24
|
import { buildAggregateProjectionStep } from "../../install/aggregate-projection-step.js";
|
|
23
25
|
import { installRefused } from "../../install/vocabulary.js";
|
|
24
|
-
import { exclusiveMemberRetentionPolicy, makeWorkspaceRetentionPolicy, } from "
|
|
25
|
-
import {
|
|
26
|
-
import { buildAtomicPackGraphStep, validatePackGraphPostcondition } from "../graph-transition.js";
|
|
26
|
+
import { exclusiveMemberRetentionPolicy, makeWorkspaceRetentionPolicy, } from "@agentxm/workspace-reconciliation";
|
|
27
|
+
import { validatePackGraphPostcondition } from "../graph-transition.js";
|
|
27
28
|
import { PACK_UNINSTALL_GRAPH_BLOCKER_ID, planPackUninstallGraphReadiness, } from "./readiness.js";
|
|
28
29
|
const normalizedPackIdentity = (identity) => identity.startsWith("workspace:") ? identity.slice("workspace:".length) : identity;
|
|
29
30
|
const identityValidationError = (identity) => installRefused({
|
|
@@ -211,7 +212,7 @@ export const planPackUninstall = Effect.fn("UninstallExtensions.planPacks")(func
|
|
|
211
212
|
const retirement = retirementByIdentity.get(normalizedPackIdentity(pack.desiredIdentity));
|
|
212
213
|
return retirement === undefined ? [] : [[pack.name, retirement]];
|
|
213
214
|
}));
|
|
214
|
-
const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
|
|
215
|
+
const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
|
|
215
216
|
const allTargets = new Map();
|
|
216
217
|
for (const pack of intent.packsToUninstall) {
|
|
217
218
|
allTargets.set(`pack:${pack.name}`, pack);
|
|
@@ -234,10 +235,19 @@ export const planPackUninstall = Effect.fn("UninstallExtensions.planPacks")(func
|
|
|
234
235
|
const packTargets = [...allTargets.values()].filter((target) => target.type === "pack");
|
|
235
236
|
const depTargets = [...allTargets.values()].filter((target) => target.type !== "pack");
|
|
236
237
|
const orderedTargets = [...depTargets, ...packTargets];
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
const proposal = yield* proposeDesiredState(intent.packsToUninstall.map((pack) => ({ kind: "remove", type: "pack", name: pack.name }))).pipe(Effect.mapError((cause) => installRefused({
|
|
239
|
+
category: "conflict",
|
|
240
|
+
detail: "Pack retirement intent could not be evaluated",
|
|
241
|
+
cause,
|
|
242
|
+
})));
|
|
243
|
+
const artifacts = yield* Effect.forEach(orderedTargets, (target) => prepareUninstallArtifact(target, proposal)).pipe(Effect.mapError((cause) => installRefused({
|
|
244
|
+
category: "conflict",
|
|
245
|
+
detail: "Pack retirement effects could not be established",
|
|
246
|
+
cause,
|
|
247
|
+
})));
|
|
248
|
+
const artifactTargets = artifacts
|
|
249
|
+
.flatMap((artifact) => artifact.targets ?? [])
|
|
250
|
+
.filter((target, index, all) => all.findIndex((candidate) => candidate.path === target.path && candidate.change === target.change) === index);
|
|
241
251
|
const steps = orderedTargets.map((target) => {
|
|
242
252
|
switch (target.type) {
|
|
243
253
|
case "pack": {
|
|
@@ -276,44 +286,66 @@ export const planPackUninstall = Effect.fn("UninstallExtensions.planPacks")(func
|
|
|
276
286
|
return buildUninstallOperation(ruleManager, exclusiveMemberRetentionPolicy, {
|
|
277
287
|
toStepFailure: lifecycleStepFailure,
|
|
278
288
|
target,
|
|
279
|
-
|
|
289
|
+
enclosingClosure: { projections: [target.type] },
|
|
280
290
|
});
|
|
281
291
|
case "hook":
|
|
282
292
|
return buildUninstallOperation(hookManager, exclusiveMemberRetentionPolicy, {
|
|
283
293
|
toStepFailure: lifecycleStepFailure,
|
|
284
294
|
target,
|
|
285
|
-
|
|
295
|
+
enclosingClosure: { projections: [target.type] },
|
|
286
296
|
});
|
|
287
297
|
case "knowledge":
|
|
288
298
|
return buildUninstallOperation(knowledgeManager, exclusiveMemberRetentionPolicy, {
|
|
289
299
|
toStepFailure: lifecycleStepFailure,
|
|
290
300
|
target,
|
|
291
|
-
|
|
301
|
+
enclosingClosure: { projections: [target.type] },
|
|
292
302
|
});
|
|
293
303
|
}
|
|
294
304
|
});
|
|
305
|
+
const activeNames = (type) => new Set(proposal.after.nodes
|
|
306
|
+
.filter((node) => node.type === type && node.enabled)
|
|
307
|
+
.map((node) => node.name));
|
|
308
|
+
const cleanup = plannedRetirements.length > 0
|
|
309
|
+
? Option.none()
|
|
310
|
+
: yield* collectCleanupStep({
|
|
311
|
+
expectedSkillNames: activeNames("skill"),
|
|
312
|
+
expectedSubagentNames: activeNames("subagent"),
|
|
313
|
+
expectedMcpServerNames: activeNames("mcp-server"),
|
|
314
|
+
expectedHookNames: activeNames("hook"),
|
|
315
|
+
subjects: orderedTargets,
|
|
316
|
+
adapter: {
|
|
317
|
+
toStepFailure: (cause) => lifecycleStepFailure(installRefused({
|
|
318
|
+
category: "conflict",
|
|
319
|
+
detail: ("detail" in cause ? cause.detail : undefined) ?? cause._tag,
|
|
320
|
+
cause,
|
|
321
|
+
})),
|
|
322
|
+
},
|
|
323
|
+
}).pipe(Effect.mapError((cause) => installRefused({
|
|
324
|
+
category: "conflict",
|
|
325
|
+
detail: "Cannot establish owned Pack uninstall outputs",
|
|
326
|
+
cause,
|
|
327
|
+
})));
|
|
295
328
|
const projectionStep = yield* buildAggregateProjectionStep({
|
|
296
329
|
types: new Set(orderedTargets.map((target) => target.type)),
|
|
297
330
|
});
|
|
298
331
|
const registrationOnly = plannedRetirements.length === 0
|
|
299
332
|
? ""
|
|
300
333
|
: ` (${plannedRetirements.length} pack${plannedRetirements.length === 1 ? "" : "s"} unregistered without removing package content)`;
|
|
301
|
-
const graphStep = yield*
|
|
334
|
+
const graphStep = yield* buildReconciliationClosure({
|
|
335
|
+
toStepFailure: lifecycleStepFailure,
|
|
302
336
|
label: `${intent.packsToUninstall.length} pack${intent.packsToUninstall.length === 1 ? "" : "s"}`,
|
|
303
337
|
message: `Uninstalled ${intent.packsToUninstall.length} pack${intent.packsToUninstall.length === 1 ? "" : "s"} and ${depTargets.length} exclusive member${depTargets.length === 1 ? "" : "s"}${registrationOnly}`,
|
|
304
338
|
artifact: {
|
|
305
|
-
path:
|
|
339
|
+
path: artifacts[0]?.path ?? path.relative(ws.baseDir, ws.layout.settingsPath),
|
|
306
340
|
scope: ws.scope,
|
|
307
341
|
change: "removed",
|
|
308
342
|
fileCount: orderedTargets.length,
|
|
309
|
-
targets:
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
// never reported as removed.
|
|
313
|
-
change: target.type === "pack" && retirementByPackName.has(target.name) ? "unchanged" : "removed",
|
|
314
|
-
})),
|
|
343
|
+
targets: artifactTargets,
|
|
344
|
+
references: artifacts.flatMap((artifact) => artifact.references ?? []),
|
|
345
|
+
managedRegions: artifacts.flatMap((artifact) => artifact.managedRegions ?? []),
|
|
315
346
|
},
|
|
316
347
|
children: [
|
|
348
|
+
...Option.toArray(cleanup).map((step) => ({ step, coverage: "ineligible" })),
|
|
317
349
|
...steps.map((step) => ({ step, coverage: "ineligible" })),
|
|
318
350
|
...Option.toArray(projectionStep).map((step) => ({
|
|
319
351
|
step,
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import * as Effect from "effect/Effect";
|
|
11
11
|
import * as Option from "effect/Option";
|
|
12
|
-
import { RuleManager
|
|
12
|
+
import { RuleManager } from "@agentxm/extension-materialization";
|
|
13
|
+
import { buildInstallOperation } from "@agentxm/workspace-reconciliation";
|
|
13
14
|
import { parseSourceQualifiedRegistrySourcePatternParts, } from "@agentxm/extension-model/unstable/extensions";
|
|
14
15
|
import { SourceHostProviders, resolveSource } from "@agentxm/extension-sources";
|
|
15
16
|
import { operationPresentation, } from "@agentxm/workspace-operations";
|
|
@@ -86,8 +87,10 @@ export const planRuleInstall = Effect.fn("InstallExtensions.planRules")(function
|
|
|
86
87
|
const memberSteps = intent.refs.map(({ ref, versionRange }) => buildInstallOperation(ruleManager, {
|
|
87
88
|
toStepFailure: lifecycleStepFailure,
|
|
88
89
|
ref,
|
|
89
|
-
versionRange,
|
|
90
|
-
|
|
90
|
+
declaration: { name: ref.rule.name, versionRange },
|
|
91
|
+
...(deferProjections
|
|
92
|
+
? { enclosingClosure: { projections: [ref.type], postconditions: [] } }
|
|
93
|
+
: {}),
|
|
91
94
|
installedBefore: ruleManager.isInstalled({
|
|
92
95
|
target: { type: "rule", name: ref.rule.name },
|
|
93
96
|
}),
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import * as Effect from "effect/Effect";
|
|
10
10
|
import * as Option from "effect/Option";
|
|
11
|
-
import { RuleManager
|
|
11
|
+
import { RuleManager } from "@agentxm/extension-materialization";
|
|
12
|
+
import { buildUninstallOperation } from "@agentxm/workspace-reconciliation";
|
|
12
13
|
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
13
14
|
import { lifecycleStepFailure } from "../../step-failure.js";
|
|
14
15
|
import { installRefused } from "../../install/vocabulary.js";
|
|
15
|
-
import { makeWorkspaceRetentionPolicy } from "
|
|
16
|
+
import { makeWorkspaceRetentionPolicy } from "@agentxm/workspace-reconciliation";
|
|
16
17
|
/** Settle whether this rule has anything to remove. */
|
|
17
18
|
export const parseRuleUninstallRequest = Effect.fn("UninstallExtensions.parseRuleRequest")(function* (selector) {
|
|
18
19
|
const ruleManager = yield* RuleManager;
|
|
@@ -35,7 +36,7 @@ export const parseRuleUninstallRequest = Effect.fn("UninstallExtensions.parseRul
|
|
|
35
36
|
export const planRuleUninstall = Effect.fn("UninstallExtensions.planRules")(function* (intent) {
|
|
36
37
|
const ws = yield* WorkspaceMutations;
|
|
37
38
|
const ruleManager = yield* RuleManager;
|
|
38
|
-
const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
|
|
39
|
+
const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
|
|
39
40
|
return {
|
|
40
41
|
_tag: "Plan",
|
|
41
42
|
name: "Uninstall rule",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { renderAxmSkillRecovery } from "@agentxm/cli-maintenance/official-skill/adapters/cli";
|
|
1
2
|
/**
|
|
2
3
|
* Installing the official AXM skill that ships inside the CLI.
|
|
3
4
|
*
|
|
@@ -16,7 +17,7 @@ import * as FileSystem from "effect/FileSystem";
|
|
|
16
17
|
import * as Option from "effect/Option";
|
|
17
18
|
import * as Path from "effect/Path";
|
|
18
19
|
import { ensureSkillAgentArtifact, replaceCanonicalDirectory, } from "@agentxm/extension-materialization";
|
|
19
|
-
import { AXM_SKILL_CLI_VERSION_METADATA_KEY, AXM_SKILL_CLI_VERSION_RANGE_METADATA_KEY, AXM_SKILL_FQN, evaluateAxmSkillCompatibility, } from "@agentxm/
|
|
20
|
+
import { AXM_SKILL_CLI_VERSION_METADATA_KEY, AXM_SKILL_CLI_VERSION_RANGE_METADATA_KEY, AXM_SKILL_FQN, evaluateAxmSkillCompatibility, } from "@agentxm/cli-maintenance/official-skill/domain";
|
|
20
21
|
import { operationPresentation, } from "@agentxm/workspace-operations";
|
|
21
22
|
import { CodingAgentRepository } from "@agentxm/workspace-projection";
|
|
22
23
|
import { WorkspaceMutations, sanitizeName } from "@agentxm/workspace-state";
|
|
@@ -173,13 +174,12 @@ export const installBundledAxmSkill = Effect.gen(function* () {
|
|
|
173
174
|
},
|
|
174
175
|
});
|
|
175
176
|
if (compatibility.status === "incompatible") {
|
|
177
|
+
const recovery = renderAxmSkillRecovery(compatibility.recovery);
|
|
176
178
|
return yield* installRefused({
|
|
177
179
|
category: "internal",
|
|
178
180
|
detail: compatibility.detail ??
|
|
179
181
|
"Bundled AXM skill remained incompatible after workspace installation",
|
|
180
|
-
...(
|
|
181
|
-
? {}
|
|
182
|
-
: { cmd: compatibility.recovery.nextAction }),
|
|
182
|
+
...(recovery.nextAction === null ? {} : { cmd: recovery.nextAction }),
|
|
183
183
|
});
|
|
184
184
|
}
|
|
185
185
|
}),
|
|
@@ -17,7 +17,8 @@ import * as Option from "effect/Option";
|
|
|
17
17
|
import * as Path from "effect/Path";
|
|
18
18
|
import * as Result from "effect/Result";
|
|
19
19
|
import * as Schema from "effect/Schema";
|
|
20
|
-
import { SkillManager, artifactAgentIdsFromTargets, artifactTargetAgentIds,
|
|
20
|
+
import { SkillManager, artifactAgentIdsFromTargets, artifactTargetAgentIds, computeSkillSourceHash, groupInstallTargetsByDirectory, } from "@agentxm/extension-materialization";
|
|
21
|
+
import { buildInstallOperation } from "@agentxm/workspace-reconciliation";
|
|
21
22
|
import { matchesReleaseAgeExcludePattern, } from "@agentxm/extension-model/unstable/extensions";
|
|
22
23
|
import { PackageUrlPartsSchema, formatPackageDisplay, } from "@agentxm/extension-model/unstable/packaging";
|
|
23
24
|
import { parseInputPattern, } from "@agentxm/extension-model/unstable/sources/parser";
|
|
@@ -379,7 +380,7 @@ export const planSkillInstall = Effect.fn("InstallExtensions.planSkills")(functi
|
|
|
379
380
|
return withPlanWarning(buildInstallOperation(skillManager, {
|
|
380
381
|
toStepFailure: lifecycleStepFailure,
|
|
381
382
|
ref,
|
|
382
|
-
versionRange: entry.versionRange,
|
|
383
|
+
declaration: { name: ref.skill.name, versionRange: entry.versionRange },
|
|
383
384
|
force: intent.force === true,
|
|
384
385
|
installedBefore: Effect.succeed(installedBefore),
|
|
385
386
|
buildArtifact: ({ installedBefore }) => Effect.gen(function* () {
|
|
@@ -30,7 +30,6 @@ export type InstallSkillOperationArgs = {
|
|
|
30
30
|
/** Version constraint from the original input when available. */
|
|
31
31
|
readonly versionRange: Option.Option<string>;
|
|
32
32
|
/** When true, write to lockfile only (skip settings). Used for pack dependencies. */
|
|
33
|
-
readonly skipSettings: Option.Option<boolean>;
|
|
34
33
|
/** When true, fail on unknown configured agents instead of warning+skip. */
|
|
35
34
|
readonly strictUnknownAgents: Option.Option<boolean>;
|
|
36
35
|
/** Named registry source that provided the ref (written to lockfile for registry skills). */
|
|
@@ -529,25 +529,16 @@ export const installSkill = (op) => Effect.gen(function* () {
|
|
|
529
529
|
}),
|
|
530
530
|
};
|
|
531
531
|
}
|
|
532
|
-
const skipSettings = Option.getOrElse(op.args.skipSettings, () => false);
|
|
533
532
|
const writeEffect = baseLockEntry === undefined
|
|
534
|
-
?
|
|
535
|
-
?
|
|
536
|
-
:
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
lockEntry: baseLockEntry,
|
|
544
|
-
versionRange: materialized.versionRange,
|
|
545
|
-
})
|
|
546
|
-
: ws.setSkill({
|
|
547
|
-
name: ref.skill.name,
|
|
548
|
-
lockEntry: baseLockEntry,
|
|
549
|
-
versionRange: materialized.versionRange,
|
|
550
|
-
});
|
|
533
|
+
? ws.setSkillEntry(ref.skill.name, {
|
|
534
|
+
source: ref.refType === "workspace" ? "workspace" : printSourceParams(ref.source),
|
|
535
|
+
enabled: true,
|
|
536
|
+
})
|
|
537
|
+
: ws.setSkill({
|
|
538
|
+
name: ref.skill.name,
|
|
539
|
+
lockEntry: baseLockEntry,
|
|
540
|
+
versionRange: materialized.versionRange,
|
|
541
|
+
});
|
|
551
542
|
const writeFailure = yield* writeEffect.pipe(Effect.result);
|
|
552
543
|
if (writeFailure._tag === "Failure") {
|
|
553
544
|
const failure = writeFailure.failure;
|
|
@@ -12,14 +12,15 @@ import * as Effect from "effect/Effect";
|
|
|
12
12
|
import * as FileSystem from "effect/FileSystem";
|
|
13
13
|
import * as Option from "effect/Option";
|
|
14
14
|
import * as Path from "effect/Path";
|
|
15
|
-
import { SkillManager,
|
|
15
|
+
import { SkillManager, skillArtifactFromTargets, } from "@agentxm/extension-materialization";
|
|
16
|
+
import { buildUninstallOperation } from "@agentxm/workspace-reconciliation";
|
|
16
17
|
import { resolveInstalledIdentifierNameOrInput } from "@agentxm/extension-sources";
|
|
17
18
|
import { CodingAgentRepository } from "@agentxm/workspace-projection";
|
|
18
19
|
import { WorkspaceMutations, acquiredExtensionDisplayPathFromLockEntry, installedRowsByName, sanitizeName, } from "@agentxm/workspace-state";
|
|
19
20
|
import { expandGlob } from "../../glob.js";
|
|
20
21
|
import { lifecycleStepFailure } from "../../step-failure.js";
|
|
21
22
|
import { installRefused, } from "../../install/vocabulary.js";
|
|
22
|
-
import { makeWorkspaceRetentionPolicy } from "
|
|
23
|
+
import { makeWorkspaceRetentionPolicy } from "@agentxm/workspace-reconciliation";
|
|
23
24
|
import { workspaceAuthoredPath, workspaceCanonicalPath, workspaceCanonicalRoot, workspaceLockfilePath, workspaceSettingsPath, } from "../../workspace-paths.js";
|
|
24
25
|
const skillSourceTarget = (ws, path, configuredSource, lockEntry, sanitizedName) => {
|
|
25
26
|
if (Option.isSome(configuredSource) && configuredSource.value === "workspace") {
|
|
@@ -69,7 +70,7 @@ export const planSkillUninstall = Effect.fn("UninstallExtensions.planSkills")(fu
|
|
|
69
70
|
const skillManager = yield* SkillManager;
|
|
70
71
|
const agentRepo = yield* CodingAgentRepository;
|
|
71
72
|
const path = yield* Path.Path;
|
|
72
|
-
const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
|
|
73
|
+
const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
|
|
73
74
|
const configuredAgents = yield* agentRepo.getMaterializationAgents().pipe(Effect.mapError((cause) => installRefused({
|
|
74
75
|
category: "internal",
|
|
75
76
|
detail: "Configured agents could not be read",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
import * as Array from "effect/Array";
|
|
11
11
|
import * as Effect from "effect/Effect";
|
|
12
12
|
import * as Option from "effect/Option";
|
|
13
|
-
import { NO_MATERIALIZATION_OBSERVATION, SubagentManager,
|
|
13
|
+
import { NO_MATERIALIZATION_OBSERVATION, SubagentManager, } from "@agentxm/extension-materialization";
|
|
14
|
+
import { buildInstallOperation } from "@agentxm/workspace-reconciliation";
|
|
14
15
|
import { parseInputPattern, } from "@agentxm/extension-model/unstable/sources/parser";
|
|
15
16
|
import { SourceHostProviders, sourceResolutionFailureCategory, } from "@agentxm/extension-sources";
|
|
16
17
|
import { operationPresentation, } from "@agentxm/workspace-operations";
|
|
@@ -216,7 +217,7 @@ export const planSubagentInstall = Effect.fn("InstallExtensions.planSubagents")(
|
|
|
216
217
|
return buildInstallOperation(subagentManager, {
|
|
217
218
|
toStepFailure: lifecycleStepFailure,
|
|
218
219
|
ref,
|
|
219
|
-
versionRange: entry.versionRange,
|
|
220
|
+
declaration: { name: ref.subagent.name, versionRange: entry.versionRange },
|
|
220
221
|
installedBefore: subagentManager
|
|
221
222
|
.isInstalled({ target: { type: "subagent", name: ref.subagent.name } })
|
|
222
223
|
.pipe(Effect.catch(() => Effect.succeed(false))),
|