skills-manager-cli 2026.8.26-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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -0
  3. package/README.zh-CN.md +103 -0
  4. package/dist/cli/main.js +261 -0
  5. package/dist/cli/main.js.map +1 -0
  6. package/dist/cli.js +3 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/core/catalog/agent-catalog.json +1134 -0
  9. package/dist/core/catalog/evaluate-detection.js +41 -0
  10. package/dist/core/catalog/evaluate-detection.js.map +1 -0
  11. package/dist/core/catalog/extract.js +388 -0
  12. package/dist/core/catalog/extract.js.map +1 -0
  13. package/dist/core/catalog/resolve-path.js +29 -0
  14. package/dist/core/catalog/resolve-path.js.map +1 -0
  15. package/dist/core/catalog/validate-snapshot.js +117 -0
  16. package/dist/core/catalog/validate-snapshot.js.map +1 -0
  17. package/dist/core/index.js +6 -0
  18. package/dist/core/index.js.map +1 -0
  19. package/dist/core/model/catalog.js +7 -0
  20. package/dist/core/model/catalog.js.map +1 -0
  21. package/dist/core/model/index.js +7 -0
  22. package/dist/core/model/index.js.map +1 -0
  23. package/dist/core/ports/filesystem.js +2 -0
  24. package/dist/core/ports/filesystem.js.map +1 -0
  25. package/dist/core/ports/git.js +2 -0
  26. package/dist/core/ports/git.js.map +1 -0
  27. package/dist/core/ports/process-runner.js +2 -0
  28. package/dist/core/ports/process-runner.js.map +1 -0
  29. package/dist/core/services/activity-service.js +36 -0
  30. package/dist/core/services/activity-service.js.map +1 -0
  31. package/dist/core/services/adopt-service.js +7 -0
  32. package/dist/core/services/adopt-service.js.map +1 -0
  33. package/dist/core/services/archive-service.js +35 -0
  34. package/dist/core/services/archive-service.js.map +1 -0
  35. package/dist/core/services/backup-service.js +94 -0
  36. package/dist/core/services/backup-service.js.map +1 -0
  37. package/dist/core/services/catalog-service.js +123 -0
  38. package/dist/core/services/catalog-service.js.map +1 -0
  39. package/dist/core/services/distribute-service.js +474 -0
  40. package/dist/core/services/distribute-service.js.map +1 -0
  41. package/dist/core/services/doctor-service.js +75 -0
  42. package/dist/core/services/doctor-service.js.map +1 -0
  43. package/dist/core/services/index.js +54 -0
  44. package/dist/core/services/index.js.map +1 -0
  45. package/dist/core/services/init-service.js +234 -0
  46. package/dist/core/services/init-service.js.map +1 -0
  47. package/dist/core/services/install-service.js +73 -0
  48. package/dist/core/services/install-service.js.map +1 -0
  49. package/dist/core/services/migration-service.js +102 -0
  50. package/dist/core/services/migration-service.js.map +1 -0
  51. package/dist/core/services/package-service.js +33 -0
  52. package/dist/core/services/package-service.js.map +1 -0
  53. package/dist/core/services/registry-service.js +133 -0
  54. package/dist/core/services/registry-service.js.map +1 -0
  55. package/dist/core/services/skill-home-resolver.js +33 -0
  56. package/dist/core/services/skill-home-resolver.js.map +1 -0
  57. package/dist/core/services/skill-home-service.js +35 -0
  58. package/dist/core/services/skill-home-service.js.map +1 -0
  59. package/dist/core/services/source-service.js +109 -0
  60. package/dist/core/services/source-service.js.map +1 -0
  61. package/dist/core/services/update-service.js +93 -0
  62. package/dist/core/services/update-service.js.map +1 -0
  63. package/dist/core/services/view-service.js +45 -0
  64. package/dist/core/services/view-service.js.map +1 -0
  65. package/dist/dashboard/server/main.js +427 -0
  66. package/dist/dashboard/server/main.js.map +1 -0
  67. package/dist/dashboard/server/render-markdown.js +75 -0
  68. package/dist/dashboard/server/render-markdown.js.map +1 -0
  69. package/dist/dashboard/server/skill-file.js +129 -0
  70. package/dist/dashboard/server/skill-file.js.map +1 -0
  71. package/dist/dashboard-web/assets/index-B43GPIpA.js +13 -0
  72. package/dist/dashboard-web/assets/index-CzbkHV2A.css +1 -0
  73. package/dist/dashboard-web/index.html +13 -0
  74. package/dist/infra/fs-skill-home.js +87 -0
  75. package/dist/infra/fs-skill-home.js.map +1 -0
  76. package/dist/infra/git-cli.js +36 -0
  77. package/dist/infra/git-cli.js.map +1 -0
  78. package/dist/infra/index.js +5 -0
  79. package/dist/infra/index.js.map +1 -0
  80. package/dist/infra/runtime.js +23 -0
  81. package/dist/infra/runtime.js.map +1 -0
  82. package/dist/infra/shell-runner.js +18 -0
  83. package/dist/infra/shell-runner.js.map +1 -0
  84. package/dist/shared/errors.js +17 -0
  85. package/dist/shared/errors.js.map +1 -0
  86. package/dist/shared/result.js +17 -0
  87. package/dist/shared/result.js.map +1 -0
  88. package/dist/shared/validation.js +92 -0
  89. package/dist/shared/validation.js.map +1 -0
  90. package/docs/CLI.md +75 -0
  91. package/package.json +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/services/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,234 @@
1
+ import path from 'node:path';
2
+ import { SkillsManagerError } from '../../shared/errors.js';
3
+ import { assertSafeSkillName, parseSkillMarkdownMetadata } from '../../shared/validation.js';
4
+ /**
5
+ * Reverse of distribute (ADR-0006): fold skills already living in detected
6
+ * agents' global runtime directories into the hub. Content moves into hub
7
+ * `skills/<name>/`; each origin is preserved under hub `.backups/` and becomes
8
+ * a managed symlink back to the hub entity.
9
+ */
10
+ export class InitService {
11
+ fs;
12
+ home;
13
+ skillHome;
14
+ registry;
15
+ distribute;
16
+ catalog;
17
+ backups;
18
+ constructor(fs, home, skillHome, registry, distribute, catalog, backups) {
19
+ this.fs = fs;
20
+ this.home = home;
21
+ this.skillHome = skillHome;
22
+ this.registry = registry;
23
+ this.distribute = distribute;
24
+ this.catalog = catalog;
25
+ this.backups = backups;
26
+ }
27
+ run(request = {}) {
28
+ const agents = this.resolveAgents(request.agents);
29
+ const groups = this.scanGroups(agents);
30
+ const { skills: discovered, invalid } = this.discover(groups);
31
+ // Classification is read-only, so dry-run reports the exact plan untouched.
32
+ const imports = [];
33
+ const skippedManaged = new Set();
34
+ const conflicts = [];
35
+ for (const skill of discovered) {
36
+ const liveLocations = skill.locations.filter((location) => !this.isManagedSymlink(location.path, skill.name));
37
+ if (liveLocations.length < skill.locations.length)
38
+ skippedManaged.add(skill.name);
39
+ if (liveLocations.length === 0)
40
+ continue;
41
+ // Entries linked to each other by symlinks are the same physical copy — merge
42
+ // them before clash detection so one skill laid out across agents isn't a conflict.
43
+ const groups = this.groupByEntity(liveLocations);
44
+ const choice = request.resolve?.[skill.name];
45
+ const hubHas = this.registry.skillExists(skill.name);
46
+ if (!choice && (groups.length > 1 || hubHas)) {
47
+ conflicts.push({
48
+ skill: skill.name,
49
+ kind: groups.length > 1 ? 'multi-runtime' : 'hub-vs-runtime',
50
+ locations: groups.map((group) => group[0]),
51
+ });
52
+ continue;
53
+ }
54
+ imports.push({ skill, groups, choice });
55
+ }
56
+ const result = {
57
+ dryRun: Boolean(request.dryRun),
58
+ scanned: groups.flatMap((group) => group.agents.map((agentId) => ({ agentId, runtimeDir: group.runtimeDir }))),
59
+ discovered,
60
+ imported: [],
61
+ skippedManaged: [...skippedManaged],
62
+ conflicts,
63
+ failed: [...invalid],
64
+ };
65
+ if (request.dryRun)
66
+ return result;
67
+ this.skillHome.ensure();
68
+ for (const item of imports) {
69
+ try {
70
+ this.importResolved(item.skill, item.groups, item.choice);
71
+ result.imported.push(item.skill.name);
72
+ }
73
+ catch (error) {
74
+ result.failed.push({ skill: item.skill.name, reason: error.message });
75
+ }
76
+ }
77
+ this.backups.prune();
78
+ return result;
79
+ }
80
+ /**
81
+ * Import one skill with its conflict decision applied. `choice` is a runtime
82
+ * dir (or any agent id sharing it) whose copy wins, or 'hub' to keep the hub
83
+ * copy and only back-symlink origins.
84
+ */
85
+ importResolved(skill, groups, choice) {
86
+ assertSafeSkillName(skill.name);
87
+ const hubHas = this.registry.skillExists(skill.name);
88
+ const winnerGroup = choice && choice !== 'hub' ? this.groupForChoice(groups, choice, skill.name) : hubHas ? null : groups[0];
89
+ const locations = groups.flat();
90
+ if (winnerGroup) {
91
+ if (hubHas) {
92
+ // The runtime copy wins: preserve the hub entity before it is replaced.
93
+ this.fs.move(this.registry.skillDir(skill.name), this.backupDirFor(skill.name));
94
+ }
95
+ const hubDir = this.registry.skillDir(skill.name);
96
+ // Copy through symlinks: the hub needs the entity's contents, not a link to it.
97
+ this.fs.copyDirectoryContents(this.entityPathOf(winnerGroup[0].path), hubDir);
98
+ this.registry.ensureEntry(skill.name, {
99
+ imported: true,
100
+ imported_at: new Date().toISOString(),
101
+ title: skill.title,
102
+ description: skill.description,
103
+ // Every origin's agents are this skill's desired consumers (catalog ids only).
104
+ consumers: this.agentsForLocations(locations),
105
+ });
106
+ }
107
+ // Real directories are preserved as backups and vacated; symlinked entries are
108
+ // simply removed — distribute lays a managed symlink down in every origin's place.
109
+ for (const location of locations) {
110
+ if (this.fs.kind(location.path) === 'symlink')
111
+ this.fs.removeFileOrSymlink(location.path);
112
+ else
113
+ this.fs.move(location.path, this.backupDirFor(skill.name));
114
+ }
115
+ this.distribute.apply({ to: 'user', skills: [skill.name], agents: this.agentsForLocations(locations), mode: 'symlink' });
116
+ }
117
+ groupForChoice(groups, choice, skill) {
118
+ const found = groups.find((group) => group.some((location) => location.runtimeDir === choice || location.agentIds.includes(choice)));
119
+ if (!found) {
120
+ throw new SkillsManagerError('init_unknown_resolution', `Resolution "${choice}" for skill "${skill}" matches none of the clashing locations. Pick a reported runtime dir (or one of its agent ids) or 'hub'.`);
121
+ }
122
+ return found;
123
+ }
124
+ /** Group locations by the physical directory they resolve to through symlink chains. */
125
+ groupByEntity(locations) {
126
+ return locations.reduce((groups, location) => {
127
+ const entity = this.entityPathOf(location.path);
128
+ const index = groups.findIndex((group) => this.entityPathOf(group[0].path) === entity);
129
+ return index === -1
130
+ ? [...groups, [location]]
131
+ : groups.map((group, i) => (i === index ? [...group, location] : group));
132
+ }, []);
133
+ }
134
+ /** Follow symlink chains (bounded — a loop must not hang import) to the physical path. */
135
+ entityPathOf(locationPath) {
136
+ let current = locationPath;
137
+ for (let hops = 0; this.fs.kind(current) === 'symlink' && hops < 8; hops += 1) {
138
+ current = path.resolve(path.dirname(current), this.fs.readlink(current));
139
+ }
140
+ return current;
141
+ }
142
+ agentsForLocations(live) {
143
+ return [...new Set(live.flatMap((location) => this.agentsForDir(location.runtimeDir)))].sort();
144
+ }
145
+ /** A runtime path already pointing at this hub skill is managed — leave it alone. */
146
+ isManagedSymlink(runtimePath, skill) {
147
+ if (this.fs.kind(runtimePath) !== 'symlink')
148
+ return false;
149
+ return path.resolve(this.fs.readlink(runtimePath)) === path.resolve(this.registry.skillDir(skill));
150
+ }
151
+ backupDirFor(skill) {
152
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
153
+ const base = path.join(this.home.root, '.backups', `${skill}-${timestamp}`);
154
+ let dir = base;
155
+ for (let n = 2; this.fs.exists(dir); n += 1)
156
+ dir = `${base}-${n}`;
157
+ return dir;
158
+ }
159
+ agentsForDir(runtimeDir) {
160
+ const resolved = new Set();
161
+ for (const agent of this.catalog.load().agents) {
162
+ if (!agent.globalSkillsDir)
163
+ continue;
164
+ if (this.catalog.resolveGlobalDir(agent.id) === runtimeDir)
165
+ resolved.add(agent.id);
166
+ }
167
+ return [...resolved].sort();
168
+ }
169
+ resolveAgents(requested) {
170
+ const ids = requested !== undefined ? [...new Set(requested)].sort() : this.catalog.detected();
171
+ if (ids.length === 0) {
172
+ throw new SkillsManagerError('init_no_agents', 'No agents selected and none detected on this machine. Pass --agent <id...>; run `skills-manager catalog info` to see the catalog.');
173
+ }
174
+ const known = new Set(this.catalog.load().agents.map((agent) => agent.id));
175
+ const invalid = ids.filter((id) => !known.has(id));
176
+ if (invalid.length > 0) {
177
+ throw new SkillsManagerError('init_unknown_agent', `Unknown agent id(s): ${invalid.join(', ')}. Run \`skills-manager catalog info\` to list valid catalog ids.`);
178
+ }
179
+ return ids;
180
+ }
181
+ /** Resolve agent ids into deduplicated physical runtime dirs, one scan each. */
182
+ scanGroups(agentIds) {
183
+ const byDir = new Map();
184
+ for (const id of agentIds) {
185
+ const resolved = this.catalog.resolveGlobalDir(id);
186
+ if (resolved === null)
187
+ continue; // project-only agents have nothing global to scan
188
+ const members = byDir.get(resolved) || [];
189
+ byDir.set(resolved, [...members, id]);
190
+ }
191
+ return [...byDir.entries()].map(([runtimeDir, agents]) => ({ runtimeDir, agents: agents.sort() }));
192
+ }
193
+ /** One level under each runtime dir: `<dir>/<name>/SKILL.md` is a skill. */
194
+ discover(groups) {
195
+ const byName = new Map();
196
+ const invalid = [];
197
+ for (const group of groups) {
198
+ if (this.fs.kind(group.runtimeDir) !== 'directory')
199
+ continue;
200
+ for (const entry of this.fs.readDirectory(group.runtimeDir)) {
201
+ // Symlinked entries are still candidates: an origin init already manages
202
+ // is one, and a user-made link may hold a real SKILL.md behind it.
203
+ if ((entry.kind !== 'directory' && entry.kind !== 'symlink') || entry.name.startsWith('.'))
204
+ continue;
205
+ const skillDir = path.join(group.runtimeDir, entry.name);
206
+ const skillFile = path.join(skillDir, 'SKILL.md');
207
+ if (this.fs.kind(skillFile) !== 'file')
208
+ continue;
209
+ let name;
210
+ let title;
211
+ let description;
212
+ try {
213
+ const metadata = parseSkillMarkdownMetadata(this.fs.readText(skillFile));
214
+ name = String(metadata.name || entry.name).trim();
215
+ title = String(metadata.title || name);
216
+ description = String(metadata.description || '');
217
+ }
218
+ catch (error) {
219
+ // An unusable SKILL.md fails this one directory, never the whole scan.
220
+ invalid.push({ skill: entry.name, reason: error.message });
221
+ continue;
222
+ }
223
+ const location = { agentIds: group.agents, runtimeDir: group.runtimeDir, path: skillDir };
224
+ const existing = byName.get(name);
225
+ if (existing)
226
+ byName.set(name, { ...existing, locations: [...existing.locations, location] });
227
+ else
228
+ byName.set(name, { name, title, description, locations: [location] });
229
+ }
230
+ }
231
+ return { skills: [...byName.values()].sort((a, b) => a.name.localeCompare(b.name)), invalid };
232
+ }
233
+ }
234
+ //# sourceMappingURL=init-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-service.js","sourceRoot":"","sources":["../../../src/core/services/init-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { SkillsManagerError } from '../../shared/errors.js';
2
+ import { assertPathInside, parseAgentTags } from '../../shared/validation.js';
3
+ export class InstallService {
4
+ fs;
5
+ home;
6
+ registry;
7
+ source;
8
+ views;
9
+ constructor(fs, home, registry, source, views) {
10
+ this.fs = fs;
11
+ this.home = home;
12
+ this.registry = registry;
13
+ this.source = source;
14
+ this.views = views;
15
+ }
16
+ planInstall(sourceCheckout, discovered, selectors, consumerValues, options = {}) {
17
+ const selected = this.selectDiscovered(discovered, selectors);
18
+ this.source.assertUniqueSkillDestinations(selected);
19
+ // No legacy default: installs stop tagging 'agents'/'claude' (see ADR-0004;
20
+ // registry tags are catalog ids, migrated by `migrate-consumers`).
21
+ const consumers = parseAgentTags(consumerValues, [], { allowEmpty: true });
22
+ const existing = selected.filter((skill) => this.registry.skillExists(skill.name)).map((skill) => skill.name);
23
+ if (existing.length > 0 && !options.overwrite) {
24
+ throw new SkillsManagerError('install_would_overwrite', `Install would overwrite existing skills: ${existing.join(', ')}`, { existing });
25
+ }
26
+ return { source: sourceCheckout, selected, existing, consumers, overwrite: Boolean(options.overwrite) };
27
+ }
28
+ installPlan(plan) {
29
+ for (const skill of plan.selected)
30
+ this.copySkillToCanonical(skill, plan.source, plan.consumers);
31
+ this.views.rebuildCollections();
32
+ return { installed: plan.selected.map((skill) => skill.name), plan };
33
+ }
34
+ installFromSourceSelection(input) {
35
+ const sourceCheckout = this.source.checkout(input.source);
36
+ const discovered = this.source.discover(sourceCheckout);
37
+ const selectors = input.selectors.length > 0 ? input.selectors : discovered.map((skill) => skill.subpath);
38
+ const plan = this.planInstall(sourceCheckout, discovered, selectors, input.consumers, { overwrite: input.overwrite });
39
+ return this.installPlan(plan);
40
+ }
41
+ selectDiscovered(discovered, selectors) {
42
+ if (selectors.length === 0)
43
+ return discovered;
44
+ const requested = new Set(selectors);
45
+ const selected = discovered.filter((skill) => requested.has(skill.subpath) || requested.has(skill.name));
46
+ const missing = [...requested].filter((value) => !selected.some((skill) => skill.subpath === value || skill.name === value));
47
+ if (missing.length > 0)
48
+ throw new SkillsManagerError('skill_not_discovered', `Requested skills were not discovered: ${missing.join(', ')}`, { missing });
49
+ return selected;
50
+ }
51
+ copySkillToCanonical(skill, source, consumers) {
52
+ assertPathInside(skill.absoluteDir, source.repoDir);
53
+ if (this.fs.kind(skill.absoluteDir) !== 'directory')
54
+ throw new SkillsManagerError('source_skill_missing', `Skill source path does not exist: ${skill.absoluteDir}`);
55
+ const destination = this.registry.skillDir(skill.name);
56
+ assertPathInside(destination, this.home.skillsDir);
57
+ this.fs.makeDirectory(destination);
58
+ this.fs.copyDirectoryContents(skill.absoluteDir, destination);
59
+ this.registry.ensureEntry(skill.name, {
60
+ title: skill.title,
61
+ consumers,
62
+ source: {
63
+ type: source.isLocal ? 'local' : 'git',
64
+ url: source.repoUrl,
65
+ subpath: skill.subpath,
66
+ ref: source.ref || null,
67
+ upstream_commit: source.commit,
68
+ },
69
+ description: skill.description,
70
+ });
71
+ }
72
+ }
73
+ //# sourceMappingURL=install-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-service.js","sourceRoot":"","sources":["../../../src/core/services/install-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import path from 'node:path';
2
+ import YAML from 'yaml';
3
+ import { SkillsManagerError } from '../../shared/errors.js';
4
+ import { isLegacyConsumer } from '../../shared/validation.js';
5
+ export class MigrationService {
6
+ fs;
7
+ home;
8
+ distribute;
9
+ catalog;
10
+ constructor(fs, home, distribute, catalog) {
11
+ this.fs = fs;
12
+ this.home = home;
13
+ this.distribute = distribute;
14
+ this.catalog = catalog;
15
+ }
16
+ /** Identity-preserving mapping: claude → claude-code; agents → the ~/.agents/skills global family. */
17
+ agentMapping() {
18
+ const family = this.catalog.load().agents.filter((agent) => agent.globalSkillsDir === '~/.agents/skills').map((agent) => agent.id).sort();
19
+ return { claude: ['claude-code'], agents: family };
20
+ }
21
+ plan() {
22
+ const mapping = this.agentMapping();
23
+ const registryChanges = [];
24
+ for (const [skill, entry] of Object.entries(this.readRawRegistry())) {
25
+ const consumers = (entry.consumers || []);
26
+ const legacy = consumers.filter((value) => isLegacyConsumer(value));
27
+ if (legacy.length === 0)
28
+ continue;
29
+ const to = [...new Set(consumers.flatMap((value) => (isLegacyConsumer(value) ? mapping[value] : [value])))].sort();
30
+ registryChanges.push({ skill, from: consumers, to });
31
+ }
32
+ const records = this.readRawIndex();
33
+ return { agentMapping: mapping, registryChanges, indexEntries: records.reduce((count, record) => count + record.entries.filter((entry) => isLegacyConsumer(entry.consumer)).length, 0) };
34
+ }
35
+ apply() {
36
+ const plan = this.plan();
37
+ const mapping = this.agentMapping();
38
+ const backupDir = path.join(this.home.root, '.skills', 'migrate-consumers-backup', new Date().toISOString().replace(/[:.]/g, '-'));
39
+ this.fs.makeDirectory(backupDir);
40
+ // 1. Registry: expand legacy tags in place (raw read — the loader hard-fails on them by design).
41
+ const rawRegistry = this.readRawRegistry();
42
+ const registrySkills = [];
43
+ for (const change of plan.registryChanges) {
44
+ const entry = rawRegistry[change.skill];
45
+ entry.consumers = change.to;
46
+ registrySkills.push(change.skill);
47
+ }
48
+ this.fs.writeText(path.join(backupDir, 'registry.yaml'), this.fs.readText(this.home.registryFile));
49
+ this.fs.writeText(this.home.registryFile, YAML.stringify({ skills: rawRegistry }, { lineWidth: 0 }));
50
+ // 2. Hub index: v1 consumer entries → v2 dual-layer entries (identical runtimePath).
51
+ const records = this.readRawIndex();
52
+ let indexEntries = 0;
53
+ const migratedRecords = records.map((record) => ({
54
+ ...record,
55
+ entries: record.entries.map((entry) => {
56
+ if (!isLegacyConsumer(entry.consumer)) {
57
+ return entry;
58
+ }
59
+ indexEntries += 1;
60
+ return {
61
+ skill: entry.skill,
62
+ runtimePath: entry.runtimePath,
63
+ mode: entry.mode,
64
+ fingerprint: entry.fingerprint,
65
+ managed: true,
66
+ agents: mapping[entry.consumer],
67
+ appliedAt: record.updatedAt,
68
+ };
69
+ }),
70
+ }));
71
+ this.fs.writeText(path.join(backupDir, 'distributions.jsonl'), this.fs.readText(this.distribute.indexPath()));
72
+ this.fs.writeText(this.distribute.indexPath(), migratedRecords.map((record) => JSON.stringify(record)).join('\n') + (migratedRecords.length ? '\n' : ''));
73
+ return { migrated: { registrySkills, indexEntries }, backupDir };
74
+ }
75
+ rollback() {
76
+ const root = path.join(this.home.root, '.skills', 'migrate-consumers-backup');
77
+ if (this.fs.kind(root) !== 'directory')
78
+ throw new SkillsManagerError('migrate_no_backup', `No migrate-consumers backup found under ${root}`);
79
+ const latest = this.fs.readDirectory(root).filter((entry) => entry.kind === 'directory').map((entry) => entry.name).sort().pop();
80
+ if (!latest)
81
+ throw new SkillsManagerError('migrate_no_backup', `No migrate-consumers backup found under ${root}`);
82
+ const dir = path.join(root, latest);
83
+ this.fs.writeText(this.home.registryFile, this.fs.readText(path.join(dir, 'registry.yaml')));
84
+ this.fs.writeText(this.distribute.indexPath(), this.fs.readText(path.join(dir, 'distributions.jsonl')));
85
+ }
86
+ readRawRegistry() {
87
+ if (!this.fs.exists(this.home.registryFile))
88
+ return {};
89
+ const parsed = YAML.parse(this.fs.readText(this.home.registryFile));
90
+ return parsed?.skills || {};
91
+ }
92
+ readRawIndex() {
93
+ if (this.fs.kind(this.distribute.indexPath()) !== 'file')
94
+ return [];
95
+ return this.fs.readText(this.distribute.indexPath())
96
+ .split('\n')
97
+ .map((line) => line.trim())
98
+ .filter(Boolean)
99
+ .map((line) => JSON.parse(line));
100
+ }
101
+ }
102
+ //# sourceMappingURL=migration-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-service.js","sourceRoot":"","sources":["../../../src/core/services/migration-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import path from 'node:path';
2
+ export class PackageService {
3
+ fs;
4
+ runner;
5
+ projectRoot;
6
+ constructor(fs, runner, projectRoot) {
7
+ this.fs = fs;
8
+ this.runner = runner;
9
+ this.projectRoot = projectRoot;
10
+ }
11
+ readPackageInfo(packageJsonPath = path.join(this.projectRoot, 'package.json')) {
12
+ return JSON.parse(this.fs.readText(packageJsonPath));
13
+ }
14
+ check(packageJsonPath = path.join(this.projectRoot, 'package.json')) {
15
+ const info = this.readPackageInfo(packageJsonPath);
16
+ const warnings = [];
17
+ if (info.name !== 'skills-manager-cli')
18
+ warnings.push(`Package name is ${info.name || '<missing>'}, expected skills-manager-cli`);
19
+ const bin = typeof info.bin === 'string' ? { [info.name || '']: info.bin } : (info.bin || {});
20
+ if (!('skills-manager' in bin))
21
+ warnings.push('Missing skills-manager binary in package.json bin');
22
+ if (info.private)
23
+ warnings.push('Package is marked private');
24
+ if (!info.files?.includes('dist'))
25
+ warnings.push('Package files should include dist');
26
+ return { ok: warnings.length === 0, packageJsonPath, info, warnings };
27
+ }
28
+ packDryRun() {
29
+ const result = this.runner.run('pnpm', ['pack', '--dry-run', '--json'], { cwd: this.projectRoot });
30
+ return { ok: result.status === 0, stdout: result.stdout, stderr: result.stderr };
31
+ }
32
+ }
33
+ //# sourceMappingURL=package-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-service.js","sourceRoot":"","sources":["../../../src/core/services/package-service.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAK7B,MAAM,OAAO,cAAc;IACI,EAAE;IAAmC,MAAM;IAAsC,WAAW;IAAzH,YAA6B,EAAkB,EAAmB,MAAyB,EAAmB,WAAmB;kBAApG,EAAE;sBAAmC,MAAM;2BAAsC,WAAW;IAAW,CAAC;IAErI,eAAe,CAAC,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC;QAC3E,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAgB,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC;QACjE,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB;YAAE,QAAQ,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,IAAI,IAAI,WAAW,+BAA+B,CAAC,CAAC;QAClI,MAAM,GAAG,GAAG,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAC9F,IAAI,CAAC,CAAC,gBAAgB,IAAI,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QACnG,IAAI,IAAI,CAAC,OAAO;YAAE,QAAQ,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACtF,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACxE,CAAC;IAED,UAAU;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACnG,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACnF,CAAC;CACF"}
@@ -0,0 +1,133 @@
1
+ import path from 'node:path';
2
+ import YAML from 'yaml';
3
+ import { SkillsManagerError } from '../../shared/errors.js';
4
+ import { assertPathInside, assertSafeSkillName, isLegacyConsumer, normalizeTags, parseAgentTags, validateRegistrySafePatch } from '../../shared/validation.js';
5
+ export class RegistryService {
6
+ fs;
7
+ home;
8
+ constructor(fs, home) {
9
+ this.fs = fs;
10
+ this.home = home;
11
+ }
12
+ load() {
13
+ if (!this.fs.exists(this.home.registryFile))
14
+ return { skills: {} };
15
+ const parsed = YAML.parse(this.fs.readText(this.home.registryFile));
16
+ const registry = parsed && typeof parsed === 'object' && parsed.skills ? parsed : { skills: {} };
17
+ const legacy = Object.entries(registry.skills || {})
18
+ .filter(([, entry]) => (entry.consumers || []).some((value) => isLegacyConsumer(value)))
19
+ .map(([name]) => name);
20
+ if (legacy.length > 0) {
21
+ throw new SkillsManagerError('legacy_consumer_tags', `registry.yaml still uses legacy consumer tags (agents/claude) on: ${legacy.join(', ')}. Run \`skills-manager migrate-consumers\` to migrate them to catalog agent ids.`);
22
+ }
23
+ return registry;
24
+ }
25
+ save(registry) {
26
+ this.fs.makeDirectory(this.home.root);
27
+ this.fs.writeText(this.home.registryFile, YAML.stringify({ skills: registry.skills || {} }, { lineWidth: 0 }));
28
+ }
29
+ skillDir(skill) {
30
+ assertSafeSkillName(skill);
31
+ const dir = path.resolve(this.home.skillsDir, skill);
32
+ assertPathInside(dir, this.home.skillsDir);
33
+ return dir;
34
+ }
35
+ skillExists(skill) {
36
+ return this.fs.kind(path.join(this.skillDir(skill), 'SKILL.md')) === 'file';
37
+ }
38
+ listCanonicalSkills() {
39
+ if (this.fs.kind(this.home.skillsDir) !== 'directory')
40
+ return [];
41
+ return this.fs.readDirectory(this.home.skillsDir)
42
+ .filter((entry) => entry.kind === 'directory' && !entry.name.startsWith('.') && this.skillExists(entry.name))
43
+ .map((entry) => entry.name)
44
+ .sort();
45
+ }
46
+ listSkills(options = {}) {
47
+ const registry = this.load();
48
+ return Object.entries(registry.skills || {})
49
+ .filter(([name, entry]) => (options.includeArchived || !entry.archived) && this.skillExists(name))
50
+ .map(([name, entry]) => this.toSkill(name, entry))
51
+ .filter((skill) => !options.consumer || skill.consumers.includes(options.consumer))
52
+ .filter((skill) => !options.category || skill.category === options.category)
53
+ .sort((a, b) => a.name.localeCompare(b.name));
54
+ }
55
+ getEntry(skill) {
56
+ return this.load().skills[skill];
57
+ }
58
+ listSkillFiles(skill) {
59
+ const root = this.skillDir(skill);
60
+ const files = [];
61
+ const walk = (dir) => {
62
+ if (this.fs.kind(dir) !== 'directory')
63
+ return;
64
+ for (const entry of this.fs.readDirectory(dir)) {
65
+ const full = path.join(dir, entry.name);
66
+ if (entry.kind === 'directory')
67
+ walk(full);
68
+ else if (entry.kind === 'file' || entry.kind === 'symlink')
69
+ files.push(path.relative(root, full).split(path.sep).join('/'));
70
+ }
71
+ };
72
+ walk(root);
73
+ return files.sort();
74
+ }
75
+ ensureEntry(skill, patch = {}) {
76
+ assertSafeSkillName(skill);
77
+ const registry = this.load();
78
+ registry.skills ||= {};
79
+ registry.skills[skill] = this.defaultEntry(skill, { ...(registry.skills[skill] || {}), ...patch });
80
+ this.save(registry);
81
+ return registry.skills[skill];
82
+ }
83
+ removeEntry(skill) {
84
+ const registry = this.load();
85
+ if (!registry.skills?.[skill])
86
+ return;
87
+ const skills = { ...registry.skills };
88
+ delete skills[skill];
89
+ this.save({ skills });
90
+ }
91
+ editSafeFields(skill, patch) {
92
+ const safePatch = validateRegistrySafePatch(patch);
93
+ const existing = this.getEntry(skill) || this.defaultEntry(skill);
94
+ return this.ensureEntry(skill, {
95
+ ...existing,
96
+ ...safePatch,
97
+ source: safePatch.source ? { ...(existing.source || {}), ...safePatch.source } : existing.source,
98
+ });
99
+ }
100
+ defaultEntry(skill, patch = {}) {
101
+ assertSafeSkillName(skill);
102
+ // No legacy default tags: desired agents are catalog ids (see ADR-0004).
103
+ const consumers = patch.consumers !== undefined ? parseAgentTags(patch.consumers, undefined, { allowEmpty: true }) : [];
104
+ const entry = {
105
+ path: `skills/${skill}`,
106
+ title: skill,
107
+ category: 'experimental',
108
+ tags: [],
109
+ consumers,
110
+ source: { type: 'local', url: null, subpath: null, ref: null, upstream_commit: null },
111
+ update_policy: 'manual',
112
+ description: '',
113
+ ...patch,
114
+ };
115
+ entry.tags = normalizeTags(patch.tags || []);
116
+ entry.consumers = consumers;
117
+ return entry;
118
+ }
119
+ toSkill(name, entry) {
120
+ return {
121
+ name,
122
+ path: entry.path || `skills/${name}`,
123
+ title: entry.title || name,
124
+ category: entry.category || 'experimental',
125
+ tags: normalizeTags(entry.tags || []),
126
+ consumers: entry.consumers !== undefined ? parseAgentTags(entry.consumers, undefined, { allowEmpty: true }) : [],
127
+ description: entry.description || '',
128
+ source: entry.source || {},
129
+ archived: Boolean(entry.archived),
130
+ };
131
+ }
132
+ }
133
+ //# sourceMappingURL=registry-service.js.map