@agentxm/extension-lifecycle 0.28.4 → 0.28.6
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/configured-entry-resolution.js +6 -3
- package/dist/src/hooks/manager.js +24 -12
- package/dist/src/index.d.ts +1 -3
- package/dist/src/index.js +1 -3
- package/dist/src/knowledge/manager.js +61 -16
- package/dist/src/mcps/manager.js +40 -6
- package/dist/src/mcps/operations/disable.js +6 -42
- package/dist/src/mcps/operations/enable.js +1 -34
- package/dist/src/mcps/operations/install.d.ts +22 -3
- package/dist/src/mcps/operations/install.js +112 -82
- package/dist/src/mcps/operations/uninstall.js +34 -15
- package/dist/src/registry-materialization.js +5 -0
- package/dist/src/rules/manager.js +16 -16
- package/dist/src/subagents/manager.js +48 -3
- package/dist/src/workflows/install-command/workflow.d.ts +1 -2
- package/dist/src/workflows/install-command/workflow.js +6 -6
- package/package.json +10 -8
- package/dist/src/resolution-progress.d.ts +0 -18
- package/dist/src/resolution-progress.js +0 -11
- package/dist/src/skills/operations/uninstall.d.ts +0 -40
- package/dist/src/skills/operations/uninstall.js +0 -157
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
* @experimental This API is unstable and may change without notice.
|
|
8
8
|
*/
|
|
9
9
|
import * as Effect from "effect/Effect";
|
|
10
|
-
import { previewOrApplyPlan } from "@agentxm/workspace-operations";
|
|
11
|
-
import { LifecycleResolutionProgress } from "../../resolution-progress.js";
|
|
10
|
+
import { observeUnit, previewOrApplyPlan, publishPhaseStarted, } from "@agentxm/workspace-operations";
|
|
12
11
|
// -----------------------------------------------------------------------------
|
|
13
12
|
// Install Command Workflow
|
|
14
13
|
// -----------------------------------------------------------------------------
|
|
@@ -20,8 +19,10 @@ import { LifecycleResolutionProgress } from "../../resolution-progress.js";
|
|
|
20
19
|
*/
|
|
21
20
|
export const buildInstallCommandPlan = (args, actions, options) => Effect.gen(function* () {
|
|
22
21
|
const parsed = yield* actions.parseArgs(args);
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// Source resolution is the first lifecycle phase: requested sources become
|
|
23
|
+
// concrete refs, observed as one unit under `resolution`.
|
|
24
|
+
yield* publishPhaseStarted("resolution");
|
|
25
|
+
const refs = yield* observeUnit({ id: "extension-sources", label: "extension sources" }, Effect.flatMap(actions.resolveSourceRequests(parsed), (sourceRequests) => actions.discoverRefs(sourceRequests)));
|
|
25
26
|
const finalizedIntent = yield* actions.finalizeIntent(parsed, refs);
|
|
26
27
|
const intent = options?.transformIntent?.(finalizedIntent) ?? finalizedIntent;
|
|
27
28
|
const plan = yield* actions.buildPlan(intent);
|
|
@@ -34,8 +35,7 @@ export const buildInstallCommandPlan = (args, actions, options) => Effect.gen(fu
|
|
|
34
35
|
* finalizeIntent -> buildPlan -> previewOrApplyPlan.
|
|
35
36
|
*/
|
|
36
37
|
export const runInstallCommandWorkflow = (args, actions, options) => Effect.gen(function* () {
|
|
37
|
-
const
|
|
38
|
-
const plan = yield* progress.withSourceResolution(buildInstallCommandPlan(args, actions, options));
|
|
38
|
+
const plan = yield* buildInstallCommandPlan(args, actions, options);
|
|
39
39
|
return yield* previewOrApplyPlan(plan, { execution: options.execution });
|
|
40
40
|
}).pipe(Effect.scoped, Effect.map((resolution) => resolution));
|
|
41
41
|
//# sourceMappingURL=workflow.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentxm/extension-lifecycle",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.6",
|
|
4
4
|
"description": "AXM extension-lifecycle feature: install, update, uninstall, enable, and disable policy across root and type-specific command forms for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
@@ -18,10 +18,12 @@
|
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
20
|
"types": "./dist/src/index.d.ts",
|
|
21
|
+
"axm-source": "./src/index.ts",
|
|
21
22
|
"default": "./dist/src/index.js"
|
|
22
23
|
},
|
|
23
24
|
"./live": {
|
|
24
25
|
"types": "./dist/src/live.d.ts",
|
|
26
|
+
"axm-source": "./src/live.ts",
|
|
25
27
|
"default": "./dist/src/live.js"
|
|
26
28
|
}
|
|
27
29
|
},
|
|
@@ -41,13 +43,13 @@
|
|
|
41
43
|
"dependencies": {
|
|
42
44
|
"effect": "4.0.0-rc.112",
|
|
43
45
|
"semver": "^7.8.5",
|
|
44
|
-
"@agentxm/extension-
|
|
45
|
-
"@agentxm/extension-
|
|
46
|
-
"@agentxm/
|
|
47
|
-
"@agentxm/
|
|
48
|
-
"@agentxm/workspace-
|
|
49
|
-
"@agentxm/
|
|
50
|
-
"@agentxm/
|
|
46
|
+
"@agentxm/extension-sources": "^0.28.6",
|
|
47
|
+
"@agentxm/extension-model": "^0.28.6",
|
|
48
|
+
"@agentxm/extension-workspace": "^0.28.6",
|
|
49
|
+
"@agentxm/registry-client": "^0.28.6",
|
|
50
|
+
"@agentxm/workspace-operations": "^0.28.6",
|
|
51
|
+
"@agentxm/workspace-state": "^0.28.6",
|
|
52
|
+
"@agentxm/registry-protocol": "^0.28.6"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
55
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Presentation port for the source-resolution phase of lifecycle workflows.
|
|
3
|
-
* The feature marks where progress feedback belongs; the application owns the
|
|
4
|
-
* mechanism and wording (the CLI renders a spinner around the phase).
|
|
5
|
-
*
|
|
6
|
-
* @experimental This API is unstable and may change without notice.
|
|
7
|
-
*/
|
|
8
|
-
import * as ServiceMap from "effect/Context";
|
|
9
|
-
import type * as Effect from "effect/Effect";
|
|
10
|
-
export interface LifecycleResolutionProgressService {
|
|
11
|
-
/** Surround the source-resolution phase with the application's progress feedback. */
|
|
12
|
-
readonly withSourceResolution: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
13
|
-
}
|
|
14
|
-
declare const LifecycleResolutionProgress_base: ServiceMap.ServiceClass<LifecycleResolutionProgress, "@agentxm/extension-lifecycle/resolution-progress/LifecycleResolutionProgress", LifecycleResolutionProgressService>;
|
|
15
|
-
export declare class LifecycleResolutionProgress extends LifecycleResolutionProgress_base {
|
|
16
|
-
}
|
|
17
|
-
export {};
|
|
18
|
-
//# sourceMappingURL=resolution-progress.d.ts.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Presentation port for the source-resolution phase of lifecycle workflows.
|
|
3
|
-
* The feature marks where progress feedback belongs; the application owns the
|
|
4
|
-
* mechanism and wording (the CLI renders a spinner around the phase).
|
|
5
|
-
*
|
|
6
|
-
* @experimental This API is unstable and may change without notice.
|
|
7
|
-
*/
|
|
8
|
-
import * as ServiceMap from "effect/Context";
|
|
9
|
-
export class LifecycleResolutionProgress extends ServiceMap.Service()("@agentxm/extension-lifecycle/resolution-progress/LifecycleResolutionProgress") {
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=resolution-progress.js.map
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Uninstall skill executor — orchestrates per-skill removal pipeline.
|
|
3
|
-
*
|
|
4
|
-
* Pipeline: resolve desired/observed state -> remove agent artifacts
|
|
5
|
-
* concurrently -> remove canonical source -> clear settings and accepted resolution.
|
|
6
|
-
*
|
|
7
|
-
* @experimental This API is unstable and may change without notice.
|
|
8
|
-
*/
|
|
9
|
-
import * as FileSystem from "effect/FileSystem";
|
|
10
|
-
import * as Path from "effect/Path";
|
|
11
|
-
import { LifecycleFailureAdapter } from "../../failure-adapter.js";
|
|
12
|
-
import type { OperationHandler } from "@agentxm/workspace-operations";
|
|
13
|
-
import type { Operation } from "@agentxm/workspace-operations";
|
|
14
|
-
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
15
|
-
/**
|
|
16
|
-
* Args for the uninstall-skill operation.
|
|
17
|
-
*/
|
|
18
|
-
export interface UninstallSkillOperationArgs {
|
|
19
|
-
readonly skillName: string;
|
|
20
|
-
/** Agent filter for partial uninstall. Empty = all agents. */
|
|
21
|
-
readonly agents: ReadonlyArray<string>;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Remove a skill from the workspace.
|
|
25
|
-
*
|
|
26
|
-
* @experimental This API is unstable and may change without notice.
|
|
27
|
-
*/
|
|
28
|
-
export type UninstallSkillOperation = Operation<"uninstall-skill", UninstallSkillOperationArgs>;
|
|
29
|
-
/**
|
|
30
|
-
* Uninstall-skill operation handler.
|
|
31
|
-
*
|
|
32
|
-
* Reads workspace paths from the WorkspaceMutations service, then orchestrates:
|
|
33
|
-
* 1. Sanitize skill name for filesystem
|
|
34
|
-
* 2. Resolve configured and observed state
|
|
35
|
-
* 3. Remove agent symlinks concurrently (skip missing)
|
|
36
|
-
* 4. Remove from all known canonical locations (full uninstall only)
|
|
37
|
-
* 5. Remove or update settings and accepted resolution
|
|
38
|
-
*/
|
|
39
|
-
export declare const uninstallSkill: OperationHandler<UninstallSkillOperation, FileSystem.FileSystem | Path.Path | WorkspaceMutations | LifecycleFailureAdapter>;
|
|
40
|
-
//# sourceMappingURL=uninstall.d.ts.map
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Uninstall skill executor — orchestrates per-skill removal pipeline.
|
|
3
|
-
*
|
|
4
|
-
* Pipeline: resolve desired/observed state -> remove agent artifacts
|
|
5
|
-
* concurrently -> remove canonical source -> clear settings and accepted resolution.
|
|
6
|
-
*
|
|
7
|
-
* @experimental This API is unstable and may change without notice.
|
|
8
|
-
*/
|
|
9
|
-
import * as FileSystem from "effect/FileSystem";
|
|
10
|
-
import * as Path from "effect/Path";
|
|
11
|
-
import * as Effect from "effect/Effect";
|
|
12
|
-
import * as Option from "effect/Option";
|
|
13
|
-
import * as Layer from "effect/Layer";
|
|
14
|
-
import { DefaultCodingAgentRepository } from "@agentxm/extension-workspace";
|
|
15
|
-
import { AGENTS } from "@agentxm/extension-model/unstable/agents/registry";
|
|
16
|
-
import { ExtensionLifecycleFailed } from "../../errors.js";
|
|
17
|
-
import { LifecycleFailureAdapter, withAdaptedStepFailures } from "../../failure-adapter.js";
|
|
18
|
-
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
19
|
-
import { removeIfExists } from "@agentxm/workspace-state";
|
|
20
|
-
import { sanitizeName } from "@agentxm/workspace-state";
|
|
21
|
-
import { acceptedCanonicalObservation, acceptedLockedCanonicalPath, removableAcceptedCanonicalPath, } from "@agentxm/workspace-state";
|
|
22
|
-
// Operation types
|
|
23
|
-
// -----------------------------------------------------------------------------
|
|
24
|
-
const isKnownAgentId = (id) => Object.hasOwn(AGENTS, id);
|
|
25
|
-
// -----------------------------------------------------------------------------
|
|
26
|
-
// Public API
|
|
27
|
-
// -----------------------------------------------------------------------------
|
|
28
|
-
/**
|
|
29
|
-
* Uninstall-skill operation handler.
|
|
30
|
-
*
|
|
31
|
-
* Reads workspace paths from the WorkspaceMutations service, then orchestrates:
|
|
32
|
-
* 1. Sanitize skill name for filesystem
|
|
33
|
-
* 2. Resolve configured and observed state
|
|
34
|
-
* 3. Remove agent symlinks concurrently (skip missing)
|
|
35
|
-
* 4. Remove from all known canonical locations (full uninstall only)
|
|
36
|
-
* 5. Remove or update settings and accepted resolution
|
|
37
|
-
*/
|
|
38
|
-
export const uninstallSkill = (op) => Effect.gen(function* () {
|
|
39
|
-
const fs = yield* FileSystem.FileSystem;
|
|
40
|
-
const path = yield* Path.Path;
|
|
41
|
-
const ws = yield* WorkspaceMutations;
|
|
42
|
-
const base = ws.baseDir;
|
|
43
|
-
const fsPathLayer = Layer.mergeAll(Layer.succeed(FileSystem.FileSystem, fs), Layer.succeed(Path.Path, path));
|
|
44
|
-
const sanitizedName = sanitizeName(op.args.skillName);
|
|
45
|
-
const desired = yield* ws.getDesiredStateGraph();
|
|
46
|
-
if (!desired.complete) {
|
|
47
|
-
return yield* new ExtensionLifecycleFailed({
|
|
48
|
-
category: "conflict",
|
|
49
|
-
detail: "Cannot uninstall the skill while the desired extension graph is incomplete.",
|
|
50
|
-
recover: "Repair or reinstall the configured packs, then retry.",
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
const desiredNode = desired.nodes.find((node) => node.type === "skill" && node.name === op.args.skillName);
|
|
54
|
-
const acceptedCanonical = yield* acceptedCanonicalObservation({
|
|
55
|
-
workspace: ws,
|
|
56
|
-
type: "skill",
|
|
57
|
-
name: op.args.skillName,
|
|
58
|
-
});
|
|
59
|
-
const lockedCanonical = yield* acceptedLockedCanonicalPath({
|
|
60
|
-
workspace: ws,
|
|
61
|
-
type: "skill",
|
|
62
|
-
name: op.args.skillName,
|
|
63
|
-
});
|
|
64
|
-
const removableCanonical = Option.orElse(removableAcceptedCanonicalPath(acceptedCanonical), () => lockedCanonical);
|
|
65
|
-
const installedOnDisk = yield* Option.match(removableCanonical, {
|
|
66
|
-
onNone: () => Effect.succeed(false),
|
|
67
|
-
onSome: (canonicalPath) => fs.exists(canonicalPath).pipe(Effect.catch(() => Effect.succeed(false))),
|
|
68
|
-
});
|
|
69
|
-
if (desiredNode === undefined && !installedOnDisk) {
|
|
70
|
-
return { result: "success", message: "not installed" };
|
|
71
|
-
}
|
|
72
|
-
// Determine which configured agent artifacts to remove. Per-agent state is
|
|
73
|
-
// derived from settings and disk rather than persisted in the lockfile.
|
|
74
|
-
const agentFilter = op.args.agents;
|
|
75
|
-
const isPartialUninstall = agentFilter.length > 0;
|
|
76
|
-
const materializationAgents = yield* DefaultCodingAgentRepository.getMaterializationAgents().pipe(Effect.provideService(WorkspaceMutations, ws));
|
|
77
|
-
const agentsToRemove = isPartialUninstall
|
|
78
|
-
? agentFilter
|
|
79
|
-
: materializationAgents.map((agent) => agent.id);
|
|
80
|
-
const remainingAgents = materializationAgents
|
|
81
|
-
.map((agent) => agent.id)
|
|
82
|
-
.filter((agent) => !agentsToRemove.includes(agent));
|
|
83
|
-
const agentsById = new Map(materializationAgents.map((agent) => [agent.id, agent]));
|
|
84
|
-
const resolveAgentArtifactPath = (agentId) => {
|
|
85
|
-
const configuredAgent = agentsById.get(agentId);
|
|
86
|
-
const agentEffect = configuredAgent !== undefined
|
|
87
|
-
? Effect.succeed(Option.some(configuredAgent))
|
|
88
|
-
: isKnownAgentId(agentId)
|
|
89
|
-
? DefaultCodingAgentRepository.get(agentId).pipe(Effect.map(Option.some))
|
|
90
|
-
: Effect.succeed(Option.none());
|
|
91
|
-
return agentEffect.pipe(Effect.flatMap((agentOption) => {
|
|
92
|
-
if (Option.isNone(agentOption))
|
|
93
|
-
return Effect.succeed(Option.none());
|
|
94
|
-
return agentOption.value
|
|
95
|
-
.resolveEffectiveSkillsDir({ workspaceRoot: base })
|
|
96
|
-
.pipe(Effect.map((outcome) => outcome._tag === "supported"
|
|
97
|
-
? Option.some(path.normalize(path.join(outcome.dir, sanitizedName)))
|
|
98
|
-
: Option.none()));
|
|
99
|
-
}), Effect.provide(fsPathLayer));
|
|
100
|
-
};
|
|
101
|
-
const retainedArtifactOptions = yield* Effect.forEach(remainingAgents, resolveAgentArtifactPath, { concurrency: "unbounded" });
|
|
102
|
-
const retainedArtifactPaths = new Set(retainedArtifactOptions.flatMap((artifactPath) => Option.isSome(artifactPath) ? [artifactPath.value] : []));
|
|
103
|
-
// Remove agent symlinks/copies concurrently using adapter-derived paths.
|
|
104
|
-
yield* Effect.forEach(agentsToRemove, (agentId) => {
|
|
105
|
-
const configuredAgent = agentsById.get(agentId);
|
|
106
|
-
const agentEffect = configuredAgent !== undefined
|
|
107
|
-
? Effect.succeed(Option.some(configuredAgent))
|
|
108
|
-
: isKnownAgentId(agentId)
|
|
109
|
-
? DefaultCodingAgentRepository.get(agentId).pipe(Effect.map(Option.some))
|
|
110
|
-
: Effect.succeed(Option.none());
|
|
111
|
-
return agentEffect.pipe(Effect.flatMap((agentOption) => {
|
|
112
|
-
if (Option.isNone(agentOption)) {
|
|
113
|
-
return Effect.succeed({
|
|
114
|
-
_tag: "unsupported",
|
|
115
|
-
reason: `Unknown coding agent: ${agentId}`,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
return agentOption.value.resolveEffectiveSkillsDir({ workspaceRoot: base });
|
|
119
|
-
}), Effect.provide(fsPathLayer), Effect.flatMap((outcome) => outcome._tag === "supported"
|
|
120
|
-
? (() => {
|
|
121
|
-
const artifactPath = path.normalize(path.join(outcome.dir, sanitizedName));
|
|
122
|
-
return retainedArtifactPaths.has(artifactPath)
|
|
123
|
-
? Effect.void
|
|
124
|
-
: fs
|
|
125
|
-
.remove(artifactPath, { recursive: true })
|
|
126
|
-
.pipe(Effect.catch(() => Effect.void));
|
|
127
|
-
})()
|
|
128
|
-
: Effect.void));
|
|
129
|
-
}, { concurrency: "unbounded" });
|
|
130
|
-
// Handle partial vs full uninstall
|
|
131
|
-
if (isPartialUninstall) {
|
|
132
|
-
const agentList = [...agentsToRemove].join(", ");
|
|
133
|
-
return {
|
|
134
|
-
result: "success",
|
|
135
|
-
message: `Uninstalled ${op.args.skillName} from ${agentList}`,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
const packOwned = desiredNode?.origins.some((origin) => origin.type === "pack") ?? false;
|
|
139
|
-
if (packOwned) {
|
|
140
|
-
// Pack still references this skill — remove from settings only, keep lockfile + disk
|
|
141
|
-
yield* ws.removeSkillFromSettings(op.args.skillName).pipe(Effect.catch(() => Effect.void));
|
|
142
|
-
return {
|
|
143
|
-
result: "success",
|
|
144
|
-
message: `Uninstalled ${op.args.skillName}`,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
// Full uninstall removes only the canonical package proven by accepted authority.
|
|
148
|
-
if (Option.isSome(removableCanonical))
|
|
149
|
-
yield* removeIfExists(fs, removableCanonical.value);
|
|
150
|
-
// Remove from both settings and lockfile (swallow errors on full uninstall)
|
|
151
|
-
yield* ws.removeSkill(op.args.skillName).pipe(Effect.catch(() => Effect.void));
|
|
152
|
-
return {
|
|
153
|
-
result: "success",
|
|
154
|
-
message: `Uninstalled ${op.args.skillName}`,
|
|
155
|
-
};
|
|
156
|
-
}).pipe(withAdaptedStepFailures);
|
|
157
|
-
//# sourceMappingURL=uninstall.js.map
|