@agentxm/workspace-sync 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/dist/src/errors.d.ts +29 -0
- package/dist/src/errors.js +25 -0
- package/dist/src/failure-adapter.d.ts +18 -0
- package/dist/src/failure-adapter.js +11 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.js +14 -0
- package/dist/src/materialize.d.ts +125 -0
- package/dist/src/materialize.js +547 -0
- package/dist/src/plan.d.ts +100 -0
- package/dist/src/plan.js +456 -0
- package/dist/src/rendered-file-cleanup.d.ts +45 -0
- package/dist/src/rendered-file-cleanup.js +381 -0
- package/package.json +55 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Destructive sweep of AXM-managed rendered files across agent surfaces:
|
|
3
|
+
* stale skill and subagent projections, managed MCP server entries, and
|
|
4
|
+
* managed hook groups. Read-only discovery primitives live in
|
|
5
|
+
* `extension-workspace/managed-file-discovery.ts`.
|
|
6
|
+
*
|
|
7
|
+
* @experimental This API is unstable and may change without notice.
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import * as FileSystem from "effect/FileSystem";
|
|
12
|
+
import * as Path from "effect/Path";
|
|
13
|
+
import { WorkspaceSyncFailed } from "./errors.js";
|
|
14
|
+
import { CodingAgentRepository, pruneManagedMcpServersForAgent, extensionNameFromFilename, hasAxmManagedMarker, safeReadDirectory, safeReadFileString, readAmbiguousHookCommands, stripManagedHooksFromJson, } from "@agentxm/extension-workspace";
|
|
15
|
+
import { AGENTS as CAPABILITY_AGENTS } from "@agentxm/extension-model/unstable/agent-capabilities";
|
|
16
|
+
import { PER_AGENT_EXTENSION_TYPES, } from "@agentxm/extension-model/unstable/extensions/common";
|
|
17
|
+
import { ACQUIRED_EXTENSIONS_DIR } from "@agentxm/workspace-state";
|
|
18
|
+
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
19
|
+
import { protectWorkspacePath } from "@agentxm/workspace-state";
|
|
20
|
+
import { recordFootprint } from "@agentxm/workspace-state";
|
|
21
|
+
const isWithin = (path, parent, child) => {
|
|
22
|
+
const relative = path.relative(path.resolve(parent), path.resolve(child));
|
|
23
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
24
|
+
};
|
|
25
|
+
const removePath = (fs, filePath, dryRun) => dryRun
|
|
26
|
+
? Effect.void
|
|
27
|
+
: protectWorkspacePath(filePath).pipe(Effect.andThen(fs.remove(filePath, { recursive: true })), Effect.andThen(recordFootprint({ path: filePath, change: "removed" })), Effect.mapError((error) => new WorkspaceSyncFailed({
|
|
28
|
+
category: "internal",
|
|
29
|
+
detail: `Failed to remove managed agent artifact: ${filePath}`,
|
|
30
|
+
cause: error,
|
|
31
|
+
})));
|
|
32
|
+
const hasManagedSkillCopyMarker = (fs, path, artifactPath) => safeReadFileString(fs, path.join(artifactPath, "SKILL.md")).pipe(Effect.map(hasAxmManagedMarker));
|
|
33
|
+
const cleanupSkillArtifactsInDir = (args) => Effect.gen(function* () {
|
|
34
|
+
const removedPaths = [];
|
|
35
|
+
const preservedPaths = [];
|
|
36
|
+
const entries = yield* safeReadDirectory(args.fs, args.skillsDir);
|
|
37
|
+
const configuredRoots = args.ownershipRoots ?? [
|
|
38
|
+
args.path.join(args.baseDir, ACQUIRED_EXTENSIONS_DIR),
|
|
39
|
+
];
|
|
40
|
+
const ownershipRoots = yield* Effect.forEach(configuredRoots, (root) => args.fs.realPath(root).pipe(Effect.orElseSucceed(() => root)));
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
if (args.expectedNames?.has(entry) === true)
|
|
43
|
+
continue;
|
|
44
|
+
const artifactPath = args.path.join(args.skillsDir, entry);
|
|
45
|
+
const linkTarget = yield* args.fs.readLink(artifactPath).pipe(Effect.option);
|
|
46
|
+
if (linkTarget._tag === "Some") {
|
|
47
|
+
const resolvedTarget = args.path.resolve(args.skillsDir, linkTarget.value);
|
|
48
|
+
const canonicalTarget = yield* args.fs.realPath(resolvedTarget).pipe(Effect.option);
|
|
49
|
+
const ownershipTarget = canonicalTarget._tag === "Some" ? canonicalTarget.value : resolvedTarget;
|
|
50
|
+
if (!ownershipRoots.some((root) => isWithin(args.path, root, ownershipTarget))) {
|
|
51
|
+
preservedPaths.push(artifactPath);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
yield* removePath(args.fs, artifactPath, args.dryRun);
|
|
55
|
+
removedPaths.push(artifactPath);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const stat = yield* args.fs.stat(artifactPath).pipe(Effect.option);
|
|
59
|
+
if (stat._tag === "None")
|
|
60
|
+
continue;
|
|
61
|
+
if (stat.value.type !== "Directory") {
|
|
62
|
+
preservedPaths.push(artifactPath);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const managedCopy = yield* hasManagedSkillCopyMarker(args.fs, args.path, artifactPath);
|
|
66
|
+
if (!managedCopy) {
|
|
67
|
+
preservedPaths.push(artifactPath);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
yield* removePath(args.fs, artifactPath, args.dryRun);
|
|
71
|
+
removedPaths.push(artifactPath);
|
|
72
|
+
}
|
|
73
|
+
return { removedPaths, preservedPaths };
|
|
74
|
+
});
|
|
75
|
+
/** Remove AXM-owned skill projections whose package is no longer desired. */
|
|
76
|
+
export const cleanupStaleManagedSkillDirectories = (args) => Effect.gen(function* () {
|
|
77
|
+
const fs = yield* FileSystem.FileSystem;
|
|
78
|
+
const path = yield* Path.Path;
|
|
79
|
+
const ws = yield* WorkspaceMutations;
|
|
80
|
+
const agentRepo = yield* CodingAgentRepository;
|
|
81
|
+
const configuredAgentIds = new Set(yield* ws.getConfiguredAgents());
|
|
82
|
+
const agents = yield* agentRepo.all;
|
|
83
|
+
const removedPaths = [];
|
|
84
|
+
const ownershipRoots = ws.layout.scope === "project"
|
|
85
|
+
? [ws.layout.acquiredRoot, ws.layout.authoredRoot("skill")]
|
|
86
|
+
: [ws.layout.acquiredRoot];
|
|
87
|
+
for (const agent of agents) {
|
|
88
|
+
if (!configuredAgentIds.has(agent.id))
|
|
89
|
+
continue;
|
|
90
|
+
const resolved = yield* agent.resolveEffectiveSkillsDir({ workspaceRoot: ws.baseDir });
|
|
91
|
+
if (resolved._tag !== "supported")
|
|
92
|
+
continue;
|
|
93
|
+
const result = yield* cleanupSkillArtifactsInDir({
|
|
94
|
+
fs,
|
|
95
|
+
path,
|
|
96
|
+
baseDir: ws.baseDir,
|
|
97
|
+
skillsDir: resolved.dir,
|
|
98
|
+
dryRun: args.dryRun === true,
|
|
99
|
+
ownershipRoots,
|
|
100
|
+
expectedNames: args.expectedSkillNames,
|
|
101
|
+
});
|
|
102
|
+
removedPaths.push(...result.removedPaths);
|
|
103
|
+
}
|
|
104
|
+
return { removedPaths: [...new Set(removedPaths)] };
|
|
105
|
+
});
|
|
106
|
+
const cleanupSubagentArtifactsInDir = (args) => Effect.gen(function* () {
|
|
107
|
+
const removedPaths = [];
|
|
108
|
+
const preservedPaths = [];
|
|
109
|
+
const entries = yield* safeReadDirectory(args.fs, args.subagentsDir);
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
const filePath = args.path.join(args.subagentsDir, entry);
|
|
112
|
+
const stat = yield* args.fs.stat(filePath).pipe(Effect.option);
|
|
113
|
+
if (stat._tag === "None" || stat.value.type !== "File")
|
|
114
|
+
continue;
|
|
115
|
+
const content = yield* safeReadFileString(args.fs, filePath);
|
|
116
|
+
if (!hasAxmManagedMarker(content)) {
|
|
117
|
+
preservedPaths.push(filePath);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
yield* removePath(args.fs, filePath, args.dryRun);
|
|
121
|
+
removedPaths.push(filePath);
|
|
122
|
+
}
|
|
123
|
+
return { removedPaths, preservedPaths };
|
|
124
|
+
});
|
|
125
|
+
const NO_PATHS = { removedPaths: [], preservedPaths: [] };
|
|
126
|
+
const cleanupAgentSkills = (context) => Effect.gen(function* () {
|
|
127
|
+
const skillsDir = yield* context.agent.resolveEffectiveSkillsDir({
|
|
128
|
+
workspaceRoot: context.workspaceRoot,
|
|
129
|
+
});
|
|
130
|
+
if (skillsDir._tag !== "supported")
|
|
131
|
+
return NO_PATHS;
|
|
132
|
+
return yield* cleanupSkillArtifactsInDir({
|
|
133
|
+
fs: context.fs,
|
|
134
|
+
path: context.path,
|
|
135
|
+
baseDir: context.workspaceRoot,
|
|
136
|
+
skillsDir: skillsDir.dir,
|
|
137
|
+
dryRun: context.dryRun,
|
|
138
|
+
ownershipRoots: context.skillOwnershipRoots,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
const cleanupAgentSubagents = (context) => Effect.gen(function* () {
|
|
142
|
+
const subagentsDir = yield* context.agent.resolveEffectiveSubagentsDir({
|
|
143
|
+
workspaceRoot: context.workspaceRoot,
|
|
144
|
+
scope: context.scope,
|
|
145
|
+
});
|
|
146
|
+
if (subagentsDir._tag !== "supported")
|
|
147
|
+
return NO_PATHS;
|
|
148
|
+
return yield* cleanupSubagentArtifactsInDir({
|
|
149
|
+
fs: context.fs,
|
|
150
|
+
path: context.path,
|
|
151
|
+
subagentsDir: subagentsDir.dir,
|
|
152
|
+
dryRun: context.dryRun,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
/**
|
|
156
|
+
* Drop every `x-axm`-tagged server from the agent's MCP config. An empty
|
|
157
|
+
* declared set means "nothing should remain", so only managed entries go and
|
|
158
|
+
* user-authored servers stay.
|
|
159
|
+
*/
|
|
160
|
+
const cleanupAgentMcpServers = (context) => Effect.gen(function* () {
|
|
161
|
+
const outcome = yield* pruneManagedMcpServersForAgent(context.agent.id, {
|
|
162
|
+
workspaceRoot: context.workspaceRoot,
|
|
163
|
+
declaredServerNames: new Set(),
|
|
164
|
+
scope: context.scope,
|
|
165
|
+
dryRun: context.dryRun,
|
|
166
|
+
});
|
|
167
|
+
if (outcome._tag !== "success")
|
|
168
|
+
return NO_PATHS;
|
|
169
|
+
return {
|
|
170
|
+
removedPaths: (outcome.targets ?? []).map((target) => target.path),
|
|
171
|
+
preservedPaths: [],
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
/**
|
|
175
|
+
* Strip AXM-rendered hook groups from the agent's settings files. Edits go
|
|
176
|
+
* through jsonc-parser so user-authored groups, comments, and formatting in
|
|
177
|
+
* these user-owned files survive.
|
|
178
|
+
*/
|
|
179
|
+
const cleanupAgentHooks = (context) => Effect.gen(function* () {
|
|
180
|
+
const capabilityAgent = CAPABILITY_AGENTS.find((candidate) => candidate.id === context.agent.id);
|
|
181
|
+
const writer = capabilityAgent?.capabilities.hook.axm.writer;
|
|
182
|
+
if (writer === undefined || writer === null)
|
|
183
|
+
return NO_PATHS;
|
|
184
|
+
const removedPaths = [];
|
|
185
|
+
const configFiles = writer.configFiles.filter((file) => file.scope === "project" && file.format === "json");
|
|
186
|
+
for (const file of configFiles) {
|
|
187
|
+
const configPath = context.path.resolve(context.workspaceRoot, file.path);
|
|
188
|
+
const exists = yield* context.fs
|
|
189
|
+
.exists(configPath)
|
|
190
|
+
.pipe(Effect.catch(() => Effect.succeed(false)));
|
|
191
|
+
if (!exists)
|
|
192
|
+
continue;
|
|
193
|
+
const raw = yield* safeReadFileString(context.fs, configPath);
|
|
194
|
+
const next = yield* stripManagedHooksFromJson(configPath, writer.settingsKey, raw);
|
|
195
|
+
if (next === raw)
|
|
196
|
+
continue;
|
|
197
|
+
if (!context.dryRun) {
|
|
198
|
+
yield* protectWorkspacePath(configPath);
|
|
199
|
+
yield* context.fs.writeFileString(configPath, next).pipe(Effect.mapError((error) => new WorkspaceSyncFailed({
|
|
200
|
+
category: "internal",
|
|
201
|
+
detail: `Failed to strip managed hooks from: ${configPath}`,
|
|
202
|
+
cause: error,
|
|
203
|
+
})));
|
|
204
|
+
}
|
|
205
|
+
removedPaths.push(configPath);
|
|
206
|
+
}
|
|
207
|
+
return { removedPaths, preservedPaths: [] };
|
|
208
|
+
});
|
|
209
|
+
/**
|
|
210
|
+
* Cleanup keyed on the placement axis: every extension type that renders into a
|
|
211
|
+
* directory the agent owns needs removal behavior here, and adding a per-agent
|
|
212
|
+
* type fails to compile until that behavior is decided.
|
|
213
|
+
*
|
|
214
|
+
* Workspace-placed types are deliberately absent rather than mapped to a no-op.
|
|
215
|
+
* Workspace-placed extensions live in shared workspace content and are not
|
|
216
|
+
* keyed to a single agent, so removing one agent must not delete them.
|
|
217
|
+
*/
|
|
218
|
+
const cleanupByExtensionType = {
|
|
219
|
+
skill: cleanupAgentSkills,
|
|
220
|
+
subagent: cleanupAgentSubagents,
|
|
221
|
+
"mcp-server": cleanupAgentMcpServers,
|
|
222
|
+
hook: cleanupAgentHooks,
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Remove AXM-managed artifacts for agents that are no longer configured for a
|
|
226
|
+
* workspace: rendered skill and subagent files, plus the agent's
|
|
227
|
+
* managed MCP server entries and hook groups. Only content carrying an
|
|
228
|
+
* AXM-managed signal is removed; user-authored files and entries are left
|
|
229
|
+
* untouched.
|
|
230
|
+
*/
|
|
231
|
+
export const cleanupManagedArtifactsForRemovedAgents = (args) => Effect.gen(function* () {
|
|
232
|
+
const fs = yield* FileSystem.FileSystem;
|
|
233
|
+
const path = yield* Path.Path;
|
|
234
|
+
const ws = yield* WorkspaceMutations;
|
|
235
|
+
const agentRepo = yield* CodingAgentRepository;
|
|
236
|
+
const agents = yield* agentRepo.all;
|
|
237
|
+
const removedPaths = [];
|
|
238
|
+
const preservedPaths = [];
|
|
239
|
+
for (const agent of agents) {
|
|
240
|
+
if (!args.removedAgentIds.has(agent.id))
|
|
241
|
+
continue;
|
|
242
|
+
const context = {
|
|
243
|
+
fs,
|
|
244
|
+
path,
|
|
245
|
+
agent,
|
|
246
|
+
workspaceRoot: ws.baseDir,
|
|
247
|
+
scope: ws.scope,
|
|
248
|
+
skillOwnershipRoots: ws.layout.scope === "project"
|
|
249
|
+
? [ws.layout.acquiredRoot, ws.layout.authoredRoot("skill")]
|
|
250
|
+
: [ws.layout.acquiredRoot],
|
|
251
|
+
dryRun: args.dryRun === true,
|
|
252
|
+
};
|
|
253
|
+
for (const type of PER_AGENT_EXTENSION_TYPES) {
|
|
254
|
+
const result = yield* cleanupByExtensionType[type](context);
|
|
255
|
+
removedPaths.push(...result.removedPaths);
|
|
256
|
+
preservedPaths.push(...result.preservedPaths);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
removedPaths: [...new Set(removedPaths)],
|
|
261
|
+
preservedPaths: [...new Set(preservedPaths)],
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
/** Inspect ownership proofs without mutating any agent-native artifact. */
|
|
265
|
+
export const inspectWorkspaceOwnership = () => Effect.gen(function* () {
|
|
266
|
+
const fs = yield* FileSystem.FileSystem;
|
|
267
|
+
const path = yield* Path.Path;
|
|
268
|
+
const ws = yield* WorkspaceMutations;
|
|
269
|
+
const agentRepo = yield* CodingAgentRepository;
|
|
270
|
+
const configured = new Set(yield* ws.getConfiguredAgents());
|
|
271
|
+
const agents = yield* agentRepo.all;
|
|
272
|
+
const issues = [];
|
|
273
|
+
for (const agent of agents) {
|
|
274
|
+
if (!configured.has(agent.id))
|
|
275
|
+
continue;
|
|
276
|
+
const skillsDir = yield* agent.resolveEffectiveSkillsDir({ workspaceRoot: ws.baseDir });
|
|
277
|
+
if (skillsDir._tag === "supported") {
|
|
278
|
+
const result = yield* cleanupSkillArtifactsInDir({
|
|
279
|
+
fs,
|
|
280
|
+
path,
|
|
281
|
+
baseDir: ws.baseDir,
|
|
282
|
+
skillsDir: skillsDir.dir,
|
|
283
|
+
dryRun: true,
|
|
284
|
+
ownershipRoots: ws.layout.scope === "project"
|
|
285
|
+
? [ws.layout.acquiredRoot, ws.layout.authoredRoot("skill")]
|
|
286
|
+
: [ws.layout.acquiredRoot],
|
|
287
|
+
});
|
|
288
|
+
issues.push(...result.preservedPaths.map((artifactPath) => ({
|
|
289
|
+
kind: "managed-file-unowned",
|
|
290
|
+
path: artifactPath,
|
|
291
|
+
detail: "Agent skill artifact has no AXM symlink or structured file ownership proof.",
|
|
292
|
+
})));
|
|
293
|
+
}
|
|
294
|
+
const subagentsDir = yield* agent.resolveEffectiveSubagentsDir({
|
|
295
|
+
workspaceRoot: ws.baseDir,
|
|
296
|
+
scope: ws.scope,
|
|
297
|
+
});
|
|
298
|
+
if (subagentsDir._tag === "supported") {
|
|
299
|
+
const result = yield* cleanupSubagentArtifactsInDir({
|
|
300
|
+
fs,
|
|
301
|
+
path,
|
|
302
|
+
subagentsDir: subagentsDir.dir,
|
|
303
|
+
dryRun: true,
|
|
304
|
+
});
|
|
305
|
+
issues.push(...result.preservedPaths.map((artifactPath) => ({
|
|
306
|
+
kind: "managed-file-unowned",
|
|
307
|
+
path: artifactPath,
|
|
308
|
+
detail: "Agent subagent artifact has no structured file ownership proof.",
|
|
309
|
+
})));
|
|
310
|
+
}
|
|
311
|
+
const capabilityAgent = CAPABILITY_AGENTS.find((candidate) => candidate.id === agent.id);
|
|
312
|
+
const writer = capabilityAgent?.capabilities.hook.axm.writer;
|
|
313
|
+
if (writer === undefined || writer === null)
|
|
314
|
+
continue;
|
|
315
|
+
for (const file of writer.configFiles.filter((candidate) => candidate.scope === ws.scope && candidate.format === "json")) {
|
|
316
|
+
const configPath = path.resolve(ws.baseDir, file.path);
|
|
317
|
+
if (!(yield* fs.exists(configPath).pipe(Effect.catch(() => Effect.succeed(false)))))
|
|
318
|
+
continue;
|
|
319
|
+
const raw = yield* safeReadFileString(fs, configPath);
|
|
320
|
+
const commands = yield* readAmbiguousHookCommands(configPath, writer.settingsKey, raw);
|
|
321
|
+
issues.push(...commands.map((command) => ({
|
|
322
|
+
kind: "hook-ownership-ambiguous",
|
|
323
|
+
path: configPath,
|
|
324
|
+
detail: `Hook command targets an AXM canonical extension path without x-axm ownership metadata: ${command}`,
|
|
325
|
+
})));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return issues.filter((issue, index) => issues.findIndex((candidate) => candidate.kind === issue.kind &&
|
|
329
|
+
candidate.path === issue.path &&
|
|
330
|
+
candidate.detail === issue.detail) === index);
|
|
331
|
+
});
|
|
332
|
+
export const cleanupStaleManagedSubagentFiles = (args) => Effect.gen(function* () {
|
|
333
|
+
const fs = yield* FileSystem.FileSystem;
|
|
334
|
+
const path = yield* Path.Path;
|
|
335
|
+
const ws = yield* WorkspaceMutations;
|
|
336
|
+
const agentRepo = yield* CodingAgentRepository;
|
|
337
|
+
const configuredAgentIds = new Set(yield* ws.getConfiguredAgents());
|
|
338
|
+
const agents = yield* agentRepo.all;
|
|
339
|
+
const removedPaths = [];
|
|
340
|
+
for (const agent of agents) {
|
|
341
|
+
const resolved = yield* agent.resolveEffectiveSubagentsDir({
|
|
342
|
+
workspaceRoot: ws.baseDir,
|
|
343
|
+
scope: ws.scope,
|
|
344
|
+
});
|
|
345
|
+
if (resolved._tag !== "supported")
|
|
346
|
+
continue;
|
|
347
|
+
const exists = yield* fs.exists(resolved.dir).pipe(Effect.catch(() => Effect.succeed(false)));
|
|
348
|
+
if (!exists)
|
|
349
|
+
continue;
|
|
350
|
+
const entries = yield* fs
|
|
351
|
+
.readDirectory(resolved.dir)
|
|
352
|
+
.pipe(Effect.catch(() => Effect.succeed([])));
|
|
353
|
+
for (const entry of entries) {
|
|
354
|
+
const filePath = path.join(resolved.dir, entry);
|
|
355
|
+
const stat = yield* fs.stat(filePath).pipe(Effect.option);
|
|
356
|
+
if (stat._tag === "None" || stat.value.type !== "File")
|
|
357
|
+
continue;
|
|
358
|
+
const content = yield* fs
|
|
359
|
+
.readFileString(filePath)
|
|
360
|
+
.pipe(Effect.catch(() => Effect.succeed("")));
|
|
361
|
+
if (!hasAxmManagedMarker(content))
|
|
362
|
+
continue;
|
|
363
|
+
const expected = configuredAgentIds.has(agent.id) &&
|
|
364
|
+
args.expectedSubagentNames.has(extensionNameFromFilename(entry));
|
|
365
|
+
if (expected)
|
|
366
|
+
continue;
|
|
367
|
+
if (args.dryRun !== true) {
|
|
368
|
+
yield* protectWorkspacePath(filePath);
|
|
369
|
+
yield* fs.remove(filePath).pipe(Effect.mapError((error) => new WorkspaceSyncFailed({
|
|
370
|
+
category: "internal",
|
|
371
|
+
detail: `Failed to remove stale managed subagent file: ${filePath}`,
|
|
372
|
+
cause: error,
|
|
373
|
+
})));
|
|
374
|
+
yield* recordFootprint({ path: filePath, change: "removed" });
|
|
375
|
+
}
|
|
376
|
+
removedPaths.push(filePath);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return { removedPaths };
|
|
380
|
+
});
|
|
381
|
+
//# sourceMappingURL=rendered-file-cleanup.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentxm/workspace-sync",
|
|
3
|
+
"version": "0.28.4-bootstrap.0",
|
|
4
|
+
"description": "AXM workspace-sync feature: desired-state reconciliation planning, projection realization, and reconciliation outcomes for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "FSL-1.1-MIT",
|
|
7
|
+
"homepage": "https://axm.sh",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/agentxm/axm/issues"
|
|
10
|
+
},
|
|
11
|
+
"author": "AgentXM <hello@agentxm.ai> (https://agentxm.ai)",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/agentxm/axm.git",
|
|
15
|
+
"directory": "packages/workspace-sync"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/src/index.d.ts",
|
|
21
|
+
"default": "./dist/src/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist/src/",
|
|
26
|
+
"!**/*.map"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=22.19.0"
|
|
33
|
+
},
|
|
34
|
+
"nx": {
|
|
35
|
+
"includedScripts": []
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"effect": "4.0.0-rc.112",
|
|
39
|
+
"semver": "^7.8.5",
|
|
40
|
+
"@agentxm/extension-model": "^0.28.4-bootstrap.0",
|
|
41
|
+
"@agentxm/extension-workspace": "^0.28.4-bootstrap.0",
|
|
42
|
+
"@agentxm/registry-protocol": "^0.28.4-bootstrap.0",
|
|
43
|
+
"@agentxm/workspace-state": "^0.28.4-bootstrap.0",
|
|
44
|
+
"@agentxm/workspace-operations": "^0.28.4-bootstrap.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@effect/platform-node": "4.0.0-rc.112",
|
|
48
|
+
"@effect/vitest": "4.0.0-rc.112",
|
|
49
|
+
"@types/bun": "^1.3.14",
|
|
50
|
+
"@types/semver": "^7.5.8",
|
|
51
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
52
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
53
|
+
"vitest": "^4.1.10"
|
|
54
|
+
}
|
|
55
|
+
}
|