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,427 @@
1
+ import fastify from 'fastify';
2
+ import fastifyStatic from '@fastify/static';
3
+ import { execFile, execFileSync } from 'node:child_process';
4
+ import { createHash } from 'node:crypto';
5
+ import { existsSync } from 'node:fs';
6
+ import os from 'node:os';
7
+ import path from 'node:path';
8
+ import { promisify } from 'node:util';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { errorCode, errorMessage, SkillsManagerError } from '../../shared/errors.js';
11
+ import { createRuntimeServices } from '../../infra/runtime.js';
12
+ import { NodeFileSystem } from '../../infra/fs-skill-home.js';
13
+ import { previewFileEntries, previewSkillDir, readSkillFile } from './skill-file.js';
14
+ const execFileAsync = promisify(execFile);
15
+ const dirname = path.dirname(fileURLToPath(import.meta.url));
16
+ function hasDashboardIndex(candidate) {
17
+ return existsSync(path.join(candidate, 'index.html'));
18
+ }
19
+ function buildDashboardWeb(projectRoot) {
20
+ if (!projectRoot)
21
+ return;
22
+ const sourceRoot = path.resolve(projectRoot, 'dashboard-web');
23
+ const viteBin = path.resolve(projectRoot, 'node_modules', 'vite', 'bin', 'vite.js');
24
+ if (!existsSync(path.join(sourceRoot, 'vite.config.ts')) || !existsSync(viteBin))
25
+ return;
26
+ console.log('Dashboard build output not found. Building dashboard web assets...');
27
+ execFileSync(process.execPath, [viteBin, 'build', '--config', path.join(sourceRoot, 'vite.config.ts')], { cwd: projectRoot, stdio: 'inherit' });
28
+ }
29
+ function staticRoot(projectRoot) {
30
+ const candidates = [
31
+ path.resolve(dirname, '..', '..', 'dashboard-web'),
32
+ projectRoot ? path.resolve(projectRoot, 'dist', 'dashboard-web') : '',
33
+ path.resolve(process.cwd(), 'dist', 'dashboard-web'),
34
+ ].filter(Boolean);
35
+ let found = candidates.find((candidate) => hasDashboardIndex(candidate));
36
+ if (!found) {
37
+ buildDashboardWeb(projectRoot);
38
+ found = candidates.find((candidate) => hasDashboardIndex(candidate));
39
+ }
40
+ if (!found)
41
+ throw new Error('Dashboard build output not found. Run pnpm run build first.');
42
+ return found;
43
+ }
44
+ const sourceBody = {
45
+ type: 'object',
46
+ required: ['source'],
47
+ additionalProperties: false,
48
+ properties: { source: { type: 'string', minLength: 1 } },
49
+ };
50
+ const initBody = {
51
+ type: 'object',
52
+ additionalProperties: false,
53
+ properties: {
54
+ resolve: { type: 'object', additionalProperties: { type: 'string' } },
55
+ },
56
+ };
57
+ const installBody = {
58
+ type: 'object',
59
+ required: ['source', 'subpaths'],
60
+ additionalProperties: false,
61
+ properties: {
62
+ source: { type: 'string', minLength: 1 },
63
+ subpaths: { type: 'array', items: { type: 'string' } },
64
+ consumers: { type: 'array', items: { type: 'string' } },
65
+ overwrite: { type: 'boolean' },
66
+ },
67
+ };
68
+ const skillsBody = {
69
+ type: 'object',
70
+ required: ['skills'],
71
+ additionalProperties: false,
72
+ properties: { skills: { type: 'array', items: { type: 'string' } } },
73
+ };
74
+ const distributeBody = {
75
+ type: 'object',
76
+ required: ['to', 'skills'],
77
+ additionalProperties: false,
78
+ properties: {
79
+ to: { type: 'string', enum: ['user', 'project'] },
80
+ projectRoot: { type: 'string' },
81
+ skills: { type: 'array', items: { type: 'string' } },
82
+ agents: { type: 'array', items: { type: 'string' } },
83
+ mode: { type: 'string', enum: ['symlink', 'copy'] },
84
+ force: { type: 'boolean' },
85
+ },
86
+ };
87
+ const undistributeBody = {
88
+ type: 'object',
89
+ required: ['to', 'skills'],
90
+ additionalProperties: false,
91
+ properties: {
92
+ to: { type: 'string', enum: ['user', 'project'] },
93
+ projectRoot: { type: 'string' },
94
+ skills: { type: 'array', items: { type: 'string' } },
95
+ agents: { type: 'array', items: { type: 'string' } },
96
+ },
97
+ };
98
+ export function createDashboardApp(options) {
99
+ const app = fastify({ logger: false });
100
+ app.setErrorHandler((error, _request, reply) => {
101
+ const code = errorCode(error);
102
+ const status = error.statusCode && error.statusCode >= 400
103
+ ? error.statusCode
104
+ : code === 'distribute_foreign_exists'
105
+ ? 409
106
+ : 500;
107
+ reply.status(status).send({
108
+ ok: false,
109
+ error: { code, message: errorMessage(error), details: error.details },
110
+ });
111
+ });
112
+ const getServices = () => createRuntimeServices(options, options.projectRoot || process.cwd());
113
+ const data = (value) => ({ ok: true, data: value });
114
+ // Update detection for the single page: hasUpdate is a real diff, not plan
115
+ // membership — local sources compare content trees, remote sources compare
116
+ // the registry's upstream commit against the tracked ref's remote head.
117
+ // Membership alone would mark every sourced skill updatable forever.
118
+ const contentFs = new NodeFileSystem();
119
+ const REMOTE_HEAD_TTL_MS = 5 * 60 * 1000;
120
+ const remoteHeads = new Map();
121
+ async function remoteHeadSha(url, ref) {
122
+ const key = `${url}|${ref || ''}`;
123
+ const cached = remoteHeads.get(key);
124
+ if (cached && Date.now() - cached.fetchedAt < REMOTE_HEAD_TTL_MS)
125
+ return cached.sha;
126
+ let sha = null;
127
+ try {
128
+ const args = ref ? ['ls-remote', url, ref] : ['ls-remote', url, 'HEAD'];
129
+ const { stdout } = await execFileAsync('git', args, { timeout: 15000 });
130
+ sha = stdout.trim().split('\t')[0] || null;
131
+ }
132
+ catch {
133
+ sha = null; // offline or unreachable: stay quiet rather than crying wolf
134
+ }
135
+ remoteHeads.set(key, { sha, fetchedAt: Date.now() });
136
+ return sha;
137
+ }
138
+ /** Mirrors DistributeService.fingerprint's tree hashing so equal trees compare equal.
139
+ * Drift is caught behaviourally: dashboard-state tests require hasUpdate=false
140
+ * on a fresh install, which only holds while both algorithms agree. */
141
+ function hashTree(root) {
142
+ if (contentFs.kind(root) !== 'directory')
143
+ return null;
144
+ const hash = createHash('sha256');
145
+ const walk = (prefix) => {
146
+ const dir = prefix ? path.join(root, prefix) : root;
147
+ for (const entry of contentFs.readDirectory(dir).sort((a, b) => a.name.localeCompare(b.name))) {
148
+ const relative = prefix ? path.join(prefix, entry.name) : entry.name;
149
+ const full = path.join(root, relative);
150
+ const kind = contentFs.kind(full);
151
+ hash.update(relative);
152
+ hash.update('\0');
153
+ hash.update(kind);
154
+ hash.update('\0');
155
+ if (kind === 'file')
156
+ hash.update(contentFs.readText(full));
157
+ else if (kind === 'symlink')
158
+ hash.update(contentFs.readlink(full));
159
+ if (entry.kind === 'directory')
160
+ walk(relative);
161
+ }
162
+ };
163
+ walk('');
164
+ return `sha256:${hash.digest('hex')}`;
165
+ }
166
+ async function detectUpdates(services, skills) {
167
+ const candidates = new Set(services.update.plan().candidates.map((candidate) => candidate.skill));
168
+ const updatable = new Map();
169
+ await Promise.all(skills.map(async (skill) => {
170
+ const source = skill.source;
171
+ if (!candidates.has(skill.name) || !source.url || !source.subpath)
172
+ return;
173
+ if (source.type === 'local') {
174
+ const sourceHash = hashTree(path.resolve(source.url, source.subpath));
175
+ if (sourceHash === null)
176
+ return;
177
+ updatable.set(skill.name, sourceHash !== services.distribute.fingerprint(skill.name));
178
+ return;
179
+ }
180
+ const remote = await remoteHeadSha(source.url, source.ref);
181
+ if (remote === null || !source.upstream_commit)
182
+ return;
183
+ updatable.set(skill.name, remote !== source.upstream_commit);
184
+ }));
185
+ return updatable;
186
+ }
187
+ // Single-page state (ADR-0005): one row per skill, recent operations, and the
188
+ // update count. distributedAgents is the logical layer of the hub
189
+ // distribution index — observed agent ids, never registry consumers tags
190
+ // (desired defaults; see ADR-0004).
191
+ const state = async () => {
192
+ const services = getServices();
193
+ const listed = services.registry.listSkills({ includeArchived: false });
194
+ const updatable = await detectUpdates(services, listed);
195
+ const index = services.distribute.listIndex();
196
+ const brokenPaths = new Set(services.doctor.check().brokenLinks);
197
+ const skills = listed.map((skill) => {
198
+ const agents = new Set();
199
+ let warning = null;
200
+ let hubFingerprint = null;
201
+ for (const record of index) {
202
+ for (const entry of record.entries) {
203
+ if (entry.skill !== skill.name)
204
+ continue;
205
+ entry.agents.forEach((id) => agents.add(id));
206
+ if (!warning && brokenPaths.has(entry.runtimePath))
207
+ warning = 'broken-link';
208
+ if (!warning && entry.mode === 'copy') {
209
+ hubFingerprint ??= services.distribute.fingerprint(skill.name);
210
+ if (entry.fingerprint !== hubFingerprint)
211
+ warning = 'outdated-copy';
212
+ }
213
+ }
214
+ }
215
+ return {
216
+ name: skill.name,
217
+ category: skill.category,
218
+ description: skill.description,
219
+ sourceType: skill.source.type || 'local',
220
+ hasUpdate: updatable.get(skill.name) ?? false,
221
+ warning,
222
+ distributedAgents: [...agents].sort(),
223
+ };
224
+ });
225
+ return {
226
+ skills,
227
+ activity: services.activity.list({ limit: 25 }),
228
+ updateCount: skills.filter((skill) => skill.hasUpdate).length,
229
+ // Read-only derivation of the hub index: the project targets the operator
230
+ // has actually distributed to, most recent first — the picker's datalist.
231
+ knownProjects: index
232
+ .filter((record) => record.kind === 'project')
233
+ .sort((a, b) => (a.updatedAt < b.updatedAt ? 1 : a.updatedAt > b.updatedAt ? -1 : 0))
234
+ .map((record) => record.targetRoot),
235
+ };
236
+ };
237
+ app.get('/api/state', async () => data(await state()));
238
+ // Skill preview (read-only): one file of one skill, rendered server-side.
239
+ app.get('/api/skill/file', async (request) => {
240
+ const query = request.query;
241
+ const { resolution } = getServices();
242
+ return data(await readSkillFile(resolution.root, query.name ?? '', query.path ?? ''));
243
+ });
244
+ // Skill preview (read-only): the skill's full file list for the tree.
245
+ // listSkillFiles' first consumer (spec §API 契约).
246
+ app.get('/api/skill/files', async (request) => {
247
+ const query = request.query;
248
+ const name = query.name ?? '';
249
+ const { resolution, registry } = getServices();
250
+ const skillDir = previewSkillDir(resolution.root, name);
251
+ return data({ files: previewFileEntries(skillDir, registry.listSkillFiles(name)) });
252
+ });
253
+ // Directory browsing for project path picker: list entries in a directory
254
+ // with parent-link semantics. Prevents traversal attacks by restricting to
255
+ // user home and cwd.
256
+ app.get('/api/fs/browse', async (request) => {
257
+ const query = request.query;
258
+ const userHome = options.userHome || process.env.HOME || os.homedir();
259
+ const cwd = process.cwd();
260
+ let targetPath = query.path ? path.resolve(query.path) : userHome;
261
+ // Security: restrict to user home or cwd to prevent traversal outside allowed bounds
262
+ const normalized = path.normalize(targetPath);
263
+ const normalizedHome = path.normalize(userHome);
264
+ const normalizedCwd = path.normalize(cwd);
265
+ const isInHome = normalized === normalizedHome || normalized.startsWith(normalizedHome + path.sep);
266
+ const isInCwd = normalized === normalizedCwd || normalized.startsWith(normalizedCwd + path.sep);
267
+ if (!isInHome && !isInCwd) {
268
+ throw Object.assign(new SkillsManagerError('browse_forbidden', `Access denied to ${targetPath}`), { statusCode: 403 });
269
+ }
270
+ const fs = new NodeFileSystem();
271
+ if (fs.kind(targetPath) !== 'directory') {
272
+ throw Object.assign(new SkillsManagerError('browse_not_directory', `${targetPath} is not a directory`), { statusCode: 400 });
273
+ }
274
+ const entries = fs.readDirectory(targetPath)
275
+ .filter((entry) => entry.kind === 'directory')
276
+ .sort((a, b) => a.name.localeCompare(b.name));
277
+ const parent = targetPath !== userHome && targetPath !== '/'
278
+ ? path.dirname(targetPath)
279
+ : null;
280
+ return data({
281
+ path: targetPath,
282
+ parent,
283
+ entries: entries.map((entry) => ({
284
+ name: entry.name,
285
+ path: path.join(targetPath, entry.name),
286
+ })),
287
+ });
288
+ });
289
+ // Picker data endpoint: the full catalog filtered for a scope, with detected
290
+ // flags, family keys for shared-path grouping, and invalid reasons.
291
+ app.get('/api/catalog/agents', async (request) => {
292
+ const query = request.query;
293
+ const scope = query.scope === 'project' ? 'project' : 'user';
294
+ const services = getServices();
295
+ const snapshot = services.catalog.load();
296
+ const detected = new Set(services.catalog.detected());
297
+ // Project families depend on the named project — same project-required
298
+ // semantics as the distribute service; no silent server-cwd fallback.
299
+ if (scope === 'project' && !query.projectRoot) {
300
+ throw Object.assign(new SkillsManagerError('catalog_project_root_required', 'Project scope requires an explicit projectRoot'), { statusCode: 400 });
301
+ }
302
+ const projectRoot = path.resolve(query.projectRoot ?? '');
303
+ const agents = snapshot.agents.map((agent) => {
304
+ if (scope === 'user') {
305
+ if (!agent.globalSkillsDir) {
306
+ return { id: agent.id, label: agent.label, detected: detected.has(agent.id), familyKey: null, invalidReason: 'Project-only agent: the catalog has no global runtime path for it. Switch to project scope to use it.' };
307
+ }
308
+ const familyKey = services.catalog.resolveGlobalDir(agent.id);
309
+ return { id: agent.id, label: agent.label, detected: detected.has(agent.id), familyKey, invalidReason: familyKey === null ? 'Global runtime dir cannot be resolved on this machine.' : null };
310
+ }
311
+ return { id: agent.id, label: agent.label, detected: detected.has(agent.id), familyKey: path.join(projectRoot, agent.skillsDir), invalidReason: null };
312
+ });
313
+ return data({ scope, agents });
314
+ });
315
+ app.post('/api/discover', { schema: { body: sourceBody } }, async (request) => {
316
+ const body = request.body;
317
+ const services = getServices();
318
+ const source = services.source.checkout(body.source);
319
+ return data({ sourceInfo: source, discovered: services.source.discover(source), existing: services.registry.listCanonicalSkills() });
320
+ });
321
+ // Reverse import (ADR-0006): the dashboard's conflict decisions arrive as the
322
+ // same resolve map the CLI's --resolve flags produce.
323
+ app.post('/api/init/preview', async () => {
324
+ const services = getServices();
325
+ return data(services.init.run({ dryRun: true }));
326
+ });
327
+ app.post('/api/init/apply', { schema: { body: initBody } }, async (request) => {
328
+ const body = request.body;
329
+ const services = getServices();
330
+ const result = services.init.run({ resolve: body.resolve });
331
+ services.activity.record({ action: 'init', summary: `Imported ${result.imported.join(', ') || 'nothing'} from runtime dirs`, details: { imported: result.imported, conflicts: result.conflicts.map((conflict) => conflict.skill), failed: result.failed } });
332
+ return data(result);
333
+ });
334
+ app.post('/api/install', { schema: { body: installBody } }, async (request) => {
335
+ const body = request.body;
336
+ const services = getServices();
337
+ const result = services.install.installFromSourceSelection({ source: body.source, selectors: body.subpaths, consumers: body.consumers, overwrite: body.overwrite ?? false });
338
+ services.activity.record({ action: 'install', summary: `Installed ${result.installed.join(', ')}`, details: { source: body.source, installed: result.installed } });
339
+ return data(result);
340
+ });
341
+ app.post('/api/update/skills', { schema: { body: skillsBody } }, async (request) => {
342
+ const body = request.body;
343
+ const services = getServices();
344
+ const result = services.update.updateSkills(body.skills);
345
+ services.activity.record({ action: 'update-skills', summary: `Updated ${result.updated.join(', ')}`, details: result });
346
+ return data(result);
347
+ });
348
+ app.post('/api/distribute', { schema: { body: distributeBody } }, async (request) => {
349
+ const body = request.body;
350
+ const services = getServices();
351
+ const result = services.distribute.apply(body);
352
+ services.activity.record({ action: 'distribute', summary: `Distributed ${body.skills.length} skill(s) to ${body.to}`, details: body });
353
+ return data(result);
354
+ });
355
+ app.post('/api/undistribute', { schema: { body: undistributeBody } }, async (request) => {
356
+ const body = request.body;
357
+ const services = getServices();
358
+ const result = services.distribute.undistribute(body);
359
+ services.activity.record({ action: 'undistribute', summary: `Undistributed ${body.skills.length} skill(s) from ${body.to}`, details: body });
360
+ return data(result);
361
+ });
362
+ app.post('/api/skills/archive', { schema: { body: skillsBody } }, async (request) => {
363
+ const body = request.body;
364
+ const services = getServices();
365
+ const result = services.archive.archiveSkills(body.skills);
366
+ services.activity.record({ action: 'archive', summary: `Archived ${result.archived.join(', ')}`, details: result });
367
+ return data(result);
368
+ });
369
+ // One-step remove (ADR-0005): per skill, undistribute from every known
370
+ // target, then archive. Per-skill results; a failure is reported and never
371
+ // rolls back other skills' successes (same semantics as archive/undistribute).
372
+ app.post('/api/skills/remove', { schema: { body: skillsBody } }, async (request) => {
373
+ const body = request.body;
374
+ const services = getServices();
375
+ const results = [];
376
+ for (const skill of body.skills) {
377
+ try {
378
+ let removed = 0;
379
+ for (const record of services.distribute.listIndex()) {
380
+ const entries = record.entries.filter((entry) => entry.skill === skill);
381
+ if (entries.length === 0)
382
+ continue;
383
+ const out = services.distribute.undistribute({
384
+ to: record.kind,
385
+ projectRoot: record.kind === 'project' ? record.targetRoot : undefined,
386
+ skills: [skill],
387
+ agents: [...new Set(entries.flatMap((entry) => entry.agents))],
388
+ });
389
+ removed += out.removed.length;
390
+ }
391
+ services.archive.archiveSkills([skill]);
392
+ results.push({ skill, ok: true, removed });
393
+ }
394
+ catch (error) {
395
+ results.push({ skill, ok: false, error: { code: errorCode(error), message: errorMessage(error) } });
396
+ }
397
+ }
398
+ const done = results.filter((result) => result.ok);
399
+ const failed = results.filter((result) => !result.ok);
400
+ services.activity.record({
401
+ action: 'remove',
402
+ summary: [
403
+ done.length > 0 ? `Removed ${done.map((result) => result.skill).join(', ')}` : null,
404
+ failed.length > 0 ? `failed: ${failed.map((result) => `${result.skill} (${result.error.code})`).join(', ')}` : null,
405
+ ].filter(Boolean).join('; '),
406
+ details: { results },
407
+ });
408
+ return data({ results });
409
+ });
410
+ return app;
411
+ }
412
+ export async function startDashboardServer(options) {
413
+ const app = createDashboardApp(options);
414
+ await app.register(fastifyStatic, { root: staticRoot(options.projectRoot), prefix: '/' });
415
+ app.setNotFoundHandler((_request, reply) => reply.sendFile('index.html'));
416
+ await app.listen({ port: options.port, host: options.host });
417
+ const url = `http://${options.host === '0.0.0.0' ? 'localhost' : options.host}:${options.port}`;
418
+ console.log(`Skills Manager dashboard: ${url}`);
419
+ if (options.open)
420
+ openBrowser(url);
421
+ }
422
+ function openBrowser(url) {
423
+ const command = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';
424
+ const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
425
+ execFile(command, args, () => { });
426
+ }
427
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/dashboard/server/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import MarkdownIt from 'markdown-it';
2
+ import DOMPurify from 'isomorphic-dompurify';
3
+ import { createHighlighter } from 'shiki';
4
+ // Server-side render pipeline (spec §Rendering Pipeline): markdown-it renders
5
+ // with inline HTML allowed, Shiki highlights fenced code, DOMPurify sanitizes
6
+ // the output — skill bodies are untrusted third-party input, so nothing
7
+ // reaches the html field unsanitized.
8
+ /** Language whitelist (spec): fence aliases in, shiki grammar ids out. */
9
+ const HIGHLIGHT_LANGS = [
10
+ 'markdown', 'javascript', 'typescript', 'python', 'vue', 'shellscript',
11
+ 'json', 'yaml', 'toml', 'html', 'css', 'xml', 'sql',
12
+ ];
13
+ const FENCE_ALIASES = {
14
+ js: 'javascript', ts: 'typescript', py: 'python', md: 'markdown',
15
+ sh: 'shellscript', bash: 'shellscript', shell: 'shellscript', zsh: 'shellscript',
16
+ yml: 'yaml', 'c++': 'cpp',
17
+ };
18
+ function resolveLang(fence) {
19
+ const normalized = fence.trim().toLowerCase();
20
+ const candidate = FENCE_ALIASES[normalized] ?? normalized;
21
+ return HIGHLIGHT_LANGS.includes(candidate) ? candidate : null;
22
+ }
23
+ let highlighterPromise = null;
24
+ function getHighlighter() {
25
+ highlighterPromise ??= createHighlighter({
26
+ themes: ['github-light', 'github-dark'],
27
+ langs: [...HIGHLIGHT_LANGS],
28
+ });
29
+ return highlighterPromise;
30
+ }
31
+ // markdown-it's highlight callback is synchronous, so the highlighter is
32
+ // awaited in renderMarkdown and handed over through a module-local slot.
33
+ let activeHighlighter = null;
34
+ const md = new MarkdownIt({
35
+ html: true,
36
+ highlight(code, fence) {
37
+ const lang = resolveLang(fence);
38
+ if (!activeHighlighter || lang === null)
39
+ return ''; // markdown-it default escape
40
+ // defaultColor false: one DOM, both palettes as CSS variables — the client
41
+ // switches themes purely via CSS, no re-render, no second request.
42
+ return activeHighlighter.codeToHtml(code, {
43
+ lang,
44
+ themes: { light: 'github-light', dark: 'github-dark' },
45
+ defaultColor: false,
46
+ });
47
+ },
48
+ });
49
+ // Same leading YAML block shape parseSkillMarkdownMetadata recognizes
50
+ // (src/shared/validation.ts); the preview renders the body after it.
51
+ const FRONTMATTER = /^---\s*\n[\s\S]*?\n---\s*\n?/;
52
+ /** Drop the leading `---` YAML block — the rendered view starts at the body. */
53
+ export function stripFrontmatter(text) {
54
+ return text.replace(FRONTMATTER, '');
55
+ }
56
+ export async function renderMarkdown(body) {
57
+ activeHighlighter = await getHighlighter();
58
+ try {
59
+ return DOMPurify.sanitize(md.render(body));
60
+ }
61
+ finally {
62
+ activeHighlighter = null;
63
+ }
64
+ }
65
+ /** Standalone source file highlight (preview `source` kind): same dual-theme
66
+ * CSS-variable output, sanitized like everything entering an html field. */
67
+ export async function highlightSource(code, lang) {
68
+ const highlighter = await getHighlighter();
69
+ return DOMPurify.sanitize(highlighter.codeToHtml(code, {
70
+ lang,
71
+ themes: { light: 'github-light', dark: 'github-dark' },
72
+ defaultColor: false,
73
+ }));
74
+ }
75
+ //# sourceMappingURL=render-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-markdown.js","sourceRoot":"","sources":["../../../src/dashboard/server/render-markdown.ts"],"names":[],"mappings":"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"}