@skillsmith/core 0.4.16 → 0.4.17

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 (141) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +57 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/api/client.d.ts +2 -0
  5. package/dist/src/api/client.d.ts.map +1 -1
  6. package/dist/src/api/client.js.map +1 -1
  7. package/dist/src/api/schemas.d.ts +4 -4
  8. package/dist/src/db/schema.d.ts +2 -2
  9. package/dist/src/db/schema.d.ts.map +1 -1
  10. package/dist/src/db/schema.js +8 -2
  11. package/dist/src/db/schema.js.map +1 -1
  12. package/dist/src/embeddings/hnsw-store.d.ts +1 -1
  13. package/dist/src/embeddings/hnsw-store.d.ts.map +1 -1
  14. package/dist/src/embeddings/hnsw-store.js +4 -34
  15. package/dist/src/embeddings/hnsw-store.js.map +1 -1
  16. package/dist/src/embeddings/hnsw-store.types.d.ts +18 -0
  17. package/dist/src/embeddings/hnsw-store.types.d.ts.map +1 -1
  18. package/dist/src/embeddings/hnsw-store.types.js.map +1 -1
  19. package/dist/src/exports/services.d.ts +3 -0
  20. package/dist/src/exports/services.d.ts.map +1 -1
  21. package/dist/src/exports/services.js +6 -0
  22. package/dist/src/exports/services.js.map +1 -1
  23. package/dist/src/index.d.ts +1 -1
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +1 -1
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/learning/PatternStore.d.ts.map +1 -1
  28. package/dist/src/learning/PatternStore.js +2 -9
  29. package/dist/src/learning/PatternStore.js.map +1 -1
  30. package/dist/src/routing/SONARouter.d.ts.map +1 -1
  31. package/dist/src/routing/SONARouter.js +4 -15
  32. package/dist/src/routing/SONARouter.js.map +1 -1
  33. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +5 -0
  34. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  35. package/dist/src/scripts/validation/types.d.ts +2 -2
  36. package/dist/src/security/scanner/SecurityScanner.d.ts +4 -2
  37. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  38. package/dist/src/security/scanner/SecurityScanner.helpers.d.ts +24 -2
  39. package/dist/src/security/scanner/SecurityScanner.helpers.d.ts.map +1 -1
  40. package/dist/src/security/scanner/SecurityScanner.helpers.js +99 -3
  41. package/dist/src/security/scanner/SecurityScanner.helpers.js.map +1 -1
  42. package/dist/src/security/scanner/SecurityScanner.js +29 -90
  43. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  44. package/dist/src/security/scanner/SecurityScanner.ssrf.d.ts +15 -0
  45. package/dist/src/security/scanner/SecurityScanner.ssrf.d.ts.map +1 -0
  46. package/dist/src/security/scanner/SecurityScanner.ssrf.js +76 -0
  47. package/dist/src/security/scanner/SecurityScanner.ssrf.js.map +1 -0
  48. package/dist/src/security/scanner/index.d.ts +1 -1
  49. package/dist/src/security/scanner/index.d.ts.map +1 -1
  50. package/dist/src/security/scanner/index.js +1 -1
  51. package/dist/src/security/scanner/index.js.map +1 -1
  52. package/dist/src/security/scanner/patterns.d.ts +6 -0
  53. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  54. package/dist/src/security/scanner/patterns.js +32 -0
  55. package/dist/src/security/scanner/patterns.js.map +1 -1
  56. package/dist/src/security/scanner/types.d.ts +2 -1
  57. package/dist/src/security/scanner/types.d.ts.map +1 -1
  58. package/dist/src/security/scanner/weights.d.ts.map +1 -1
  59. package/dist/src/security/scanner/weights.js +1 -0
  60. package/dist/src/security/scanner/weights.js.map +1 -1
  61. package/dist/src/services/skill-installation.helpers.d.ts +62 -0
  62. package/dist/src/services/skill-installation.helpers.d.ts.map +1 -0
  63. package/dist/src/services/skill-installation.helpers.js +335 -0
  64. package/dist/src/services/skill-installation.helpers.js.map +1 -0
  65. package/dist/src/services/skill-installation.service.d.ts +45 -0
  66. package/dist/src/services/skill-installation.service.d.ts.map +1 -0
  67. package/dist/src/services/skill-installation.service.js +383 -0
  68. package/dist/src/services/skill-installation.service.js.map +1 -0
  69. package/dist/src/services/skill-installation.types.d.ts +144 -0
  70. package/dist/src/services/skill-installation.types.d.ts.map +1 -0
  71. package/dist/src/services/skill-installation.types.js +38 -0
  72. package/dist/src/services/skill-installation.types.js.map +1 -0
  73. package/dist/src/services/skill-manifest.d.ts +20 -0
  74. package/dist/src/services/skill-manifest.d.ts.map +1 -0
  75. package/dist/src/services/skill-manifest.js +84 -0
  76. package/dist/src/services/skill-manifest.js.map +1 -0
  77. package/dist/src/session/SessionManager.helpers.d.ts +1 -27
  78. package/dist/src/session/SessionManager.helpers.d.ts.map +1 -1
  79. package/dist/src/session/SessionManager.helpers.js +0 -64
  80. package/dist/src/session/SessionManager.helpers.js.map +1 -1
  81. package/dist/src/session/SessionManager.memory.d.ts +12 -11
  82. package/dist/src/session/SessionManager.memory.d.ts.map +1 -1
  83. package/dist/src/session/SessionManager.memory.js +23 -115
  84. package/dist/src/session/SessionManager.memory.js.map +1 -1
  85. package/dist/src/session/SessionManager.types.d.ts +0 -37
  86. package/dist/src/session/SessionManager.types.d.ts.map +1 -1
  87. package/dist/src/session/SessionManager.types.js.map +1 -1
  88. package/dist/src/session/SessionRecovery.js +4 -4
  89. package/dist/src/session/SessionRecovery.js.map +1 -1
  90. package/dist/src/testing/MultiLLMProvider.d.ts.map +1 -1
  91. package/dist/src/testing/MultiLLMProvider.js +5 -19
  92. package/dist/src/testing/MultiLLMProvider.js.map +1 -1
  93. package/dist/tests/billing/StripeClient.test.d.ts +18 -0
  94. package/dist/tests/billing/StripeClient.test.d.ts.map +1 -0
  95. package/dist/tests/billing/StripeClient.test.js +566 -0
  96. package/dist/tests/billing/StripeClient.test.js.map +1 -0
  97. package/dist/tests/billing/StripeWebhookHandler.test.d.ts +16 -0
  98. package/dist/tests/billing/StripeWebhookHandler.test.d.ts.map +1 -0
  99. package/dist/tests/billing/StripeWebhookHandler.test.js +240 -0
  100. package/dist/tests/billing/StripeWebhookHandler.test.js.map +1 -0
  101. package/dist/tests/billing/stripe-helpers.test.d.ts +7 -0
  102. package/dist/tests/billing/stripe-helpers.test.d.ts.map +1 -0
  103. package/dist/tests/billing/stripe-helpers.test.js +91 -0
  104. package/dist/tests/billing/stripe-helpers.test.js.map +1 -0
  105. package/dist/tests/billing/webhook-handlers.test.d.ts +16 -0
  106. package/dist/tests/billing/webhook-handlers.test.d.ts.map +1 -0
  107. package/dist/tests/billing/webhook-handlers.test.js +519 -0
  108. package/dist/tests/billing/webhook-handlers.test.js.map +1 -0
  109. package/dist/tests/db/migration.test.d.ts +11 -0
  110. package/dist/tests/db/migration.test.d.ts.map +1 -0
  111. package/dist/tests/db/migration.test.js +265 -0
  112. package/dist/tests/db/migration.test.js.map +1 -0
  113. package/dist/tests/security/ContinuousSecurity.test.js +2 -2
  114. package/dist/tests/security/ContinuousSecurity.test.js.map +1 -1
  115. package/dist/tests/security.test.js +200 -0
  116. package/dist/tests/security.test.js.map +1 -1
  117. package/dist/tests/session/SessionManager.helpers.test.js +1 -9
  118. package/dist/tests/session/SessionManager.helpers.test.js.map +1 -1
  119. package/dist/tests/session/SessionManager.memory.test.d.ts +3 -4
  120. package/dist/tests/session/SessionManager.memory.test.d.ts.map +1 -1
  121. package/dist/tests/session/SessionManager.memory.test.js +41 -123
  122. package/dist/tests/session/SessionManager.memory.test.js.map +1 -1
  123. package/dist/tests/sync/BackgroundSyncService.test.d.ts +13 -0
  124. package/dist/tests/sync/BackgroundSyncService.test.d.ts.map +1 -0
  125. package/dist/tests/sync/BackgroundSyncService.test.js +259 -0
  126. package/dist/tests/sync/BackgroundSyncService.test.js.map +1 -0
  127. package/dist/tests/testkit.d.ts +14 -0
  128. package/dist/tests/testkit.d.ts.map +1 -0
  129. package/dist/tests/testkit.js +14 -0
  130. package/dist/tests/testkit.js.map +1 -0
  131. package/dist/tests/unit/migrations/v10-dependencies.test.js +3 -3
  132. package/dist/tests/unit/migrations/v10-dependencies.test.js.map +1 -1
  133. package/dist/tests/unit/services/skill-installation.service.test.d.ts +8 -0
  134. package/dist/tests/unit/services/skill-installation.service.test.d.ts.map +1 -0
  135. package/dist/tests/unit/services/skill-installation.service.test.js +732 -0
  136. package/dist/tests/unit/services/skill-installation.service.test.js.map +1 -0
  137. package/package.json +19 -7
  138. package/dist/vitest.config.d.ts +0 -3
  139. package/dist/vitest.config.d.ts.map +0 -1
  140. package/dist/vitest.config.js +0 -13
  141. package/dist/vitest.config.js.map +0 -1
@@ -0,0 +1,383 @@
1
+ /**
2
+ * @fileoverview SkillInstallationService — shared install/uninstall business logic
3
+ * @module @skillsmith/core/services/skill-installation.service
4
+ * @see SMI-3483: Wave 0 — Extract SkillInstallationService into core
5
+ *
6
+ * Both mcp-server and CLI consume this service. The MCP ToolContext coupling is
7
+ * eliminated: callers inject explicit dependencies (db, repositories, paths,
8
+ * registry lookup, progress callback).
9
+ */
10
+ import * as fs from 'fs/promises';
11
+ import * as path from 'path';
12
+ import * as os from 'os';
13
+ import { SecurityScanner } from '../security/index.js';
14
+ import { safeWriteFile } from '../utils/safe-fs.js';
15
+ import { parseRepoUrl } from '../utils/github-url.js';
16
+ import { TRUST_TIER_SCANNER_OPTIONS, } from './skill-installation.types.js';
17
+ import { ManifestManager } from './skill-manifest.js';
18
+ // SMI-3483: Helpers split to companion file to meet 500-line standard
19
+ import { parseSkillIdInternal, hashContent, validateSkillMd, fetchFromGitHub, generateTips, extractDepIntel, persistDependencies, applyOptimization, performUninstall, sanitizeInstallError, } from './skill-installation.helpers.js';
20
+ const DEFAULT_SKILLS_DIR = path.join(os.homedir(), '.claude', 'skills');
21
+ const DEFAULT_SKILLSMITH_DIR = path.join(os.homedir(), '.skillsmith');
22
+ const DEFAULT_MANIFEST_PATH = path.join(DEFAULT_SKILLSMITH_DIR, 'manifest.json');
23
+ export class SkillInstallationService {
24
+ db;
25
+ skillRepo;
26
+ skillDependencyRepo;
27
+ skillsDir;
28
+ manifest;
29
+ onProgress;
30
+ registryLookup;
31
+ coInstallRecorder;
32
+ sessionInstalledSkillIds;
33
+ constructor(params) {
34
+ this.db = params.db;
35
+ this.skillRepo = params.skillRepo;
36
+ this.skillDependencyRepo = params.skillDependencyRepo;
37
+ this.skillsDir = params.skillsDir ?? DEFAULT_SKILLS_DIR;
38
+ this.manifest = new ManifestManager(params.manifestPath ?? DEFAULT_MANIFEST_PATH);
39
+ this.onProgress = params.onProgress ?? (() => { });
40
+ this.registryLookup = params.registryLookup;
41
+ this.coInstallRecorder = params.coInstallRecorder;
42
+ this.sessionInstalledSkillIds = params.sessionInstalledSkillIds ?? [];
43
+ }
44
+ async install(skillId, options = {}) {
45
+ let trustTier = 'unknown';
46
+ try {
47
+ this.onProgress('parse', 'Parsing skill ID');
48
+ const parsed = parseSkillIdInternal(skillId);
49
+ let owner;
50
+ let repo;
51
+ let basePath;
52
+ let skillName;
53
+ let branch = 'main';
54
+ let fromRegistry = false;
55
+ let indexedContentHash;
56
+ if (parsed.isRegistryId) {
57
+ if (!this.registryLookup) {
58
+ return {
59
+ success: false,
60
+ skillId,
61
+ installPath: '',
62
+ error: 'Registry lookup not available. ' +
63
+ 'Use a full GitHub URL: install { skillId: "https://github.com/owner/repo" }',
64
+ };
65
+ }
66
+ this.onProgress('lookup', 'Looking up skill in registry');
67
+ const registrySkill = await this.registryLookup.lookup(skillId);
68
+ if (!registrySkill) {
69
+ return {
70
+ success: false,
71
+ skillId,
72
+ installPath: '',
73
+ error: 'Skill "' +
74
+ skillId +
75
+ '" is indexed for discovery only. ' +
76
+ 'No installation source available (repo_url is missing). ' +
77
+ 'This may be placeholder/seed data or a metadata-only entry.',
78
+ tips: [
79
+ 'Use a full GitHub URL instead: install { skillId: "https://github.com/owner/repo" }',
80
+ 'Search for installable skills using the search tool',
81
+ 'Many indexed skills are metadata-only and cannot be installed directly',
82
+ ],
83
+ };
84
+ }
85
+ if (registrySkill.quarantined) {
86
+ return {
87
+ success: false,
88
+ skillId,
89
+ installPath: '',
90
+ error: 'Skill "' +
91
+ skillId +
92
+ '" has been quarantined due to security concerns. ' +
93
+ 'Installation is blocked to protect your environment.',
94
+ tips: [
95
+ 'Visit https://skillsmith.app/docs/quarantine for details on quarantine policies',
96
+ 'If you believe this is a false positive, contact support via https://skillsmith.app/contact?topic=security',
97
+ 'Contact the skill author or visit the quarantine documentation for more information',
98
+ ],
99
+ };
100
+ }
101
+ const repoInfo = parseRepoUrl(registrySkill.repoUrl);
102
+ owner = repoInfo.owner;
103
+ repo = repoInfo.repo;
104
+ basePath = repoInfo.path ? repoInfo.path + '/' : '';
105
+ branch = repoInfo.branch;
106
+ skillName = registrySkill.name;
107
+ trustTier = registrySkill.trustTier;
108
+ fromRegistry = true;
109
+ indexedContentHash = registrySkill.contentHash;
110
+ }
111
+ else {
112
+ owner = parsed.owner;
113
+ repo = parsed.repo;
114
+ basePath = parsed.path ? parsed.path + '/' : '';
115
+ skillName = parsed.path ? path.basename(parsed.path) : repo;
116
+ }
117
+ const installPath = path.join(this.skillsDir, skillName);
118
+ // Check if already installed
119
+ this.onProgress('manifest', 'Checking manifest');
120
+ const manifest = await this.manifest.load();
121
+ if (manifest.installedSkills[skillName] && !options.force) {
122
+ return {
123
+ success: false,
124
+ skillId,
125
+ installPath,
126
+ error: 'Skill "' + skillName + '" is already installed. Use force=true to reinstall.',
127
+ };
128
+ }
129
+ // Fetch SKILL.md
130
+ this.onProgress('fetch', 'Fetching SKILL.md from GitHub');
131
+ const skillMdPath = basePath + 'SKILL.md';
132
+ let skillMdContent;
133
+ try {
134
+ skillMdContent = await fetchFromGitHub(owner, repo, skillMdPath, branch);
135
+ }
136
+ catch {
137
+ const repoUrl = 'https://github.com/' + owner + '/' + repo;
138
+ return {
139
+ success: false,
140
+ skillId,
141
+ installPath,
142
+ error: fromRegistry
143
+ ? 'This skill is indexed in the Skillsmith registry but its installation source ' +
144
+ 'appears broken (SKILL.md not found at ' +
145
+ (basePath || 'repository root') +
146
+ '). ' +
147
+ 'This is a registry data quality issue. ' +
148
+ 'Please report it at https://skillsmith.app/contact?topic=registry-quality. ' +
149
+ 'Repository: ' +
150
+ repoUrl
151
+ : 'Could not find SKILL.md at ' +
152
+ (basePath || 'repository root') +
153
+ '. ' +
154
+ 'Skills must have a SKILL.md file with YAML frontmatter to be installable. ' +
155
+ 'Repository: ' +
156
+ repoUrl,
157
+ tips: fromRegistry
158
+ ? [
159
+ 'This is a registry data quality issue, not a path format error',
160
+ 'Report the broken entry: https://skillsmith.app/contact?topic=registry-quality',
161
+ ]
162
+ : [
163
+ 'This skill may be browse-only (no SKILL.md at expected location)',
164
+ 'Verify the repository exists: ' + repoUrl,
165
+ ],
166
+ };
167
+ }
168
+ // Validate SKILL.md
169
+ this.onProgress('validate', 'Validating SKILL.md');
170
+ const validation = validateSkillMd(skillMdContent);
171
+ if (!validation.valid) {
172
+ return {
173
+ success: false,
174
+ skillId,
175
+ installPath,
176
+ error: 'Invalid SKILL.md: ' + validation.errors.join(', '),
177
+ tips: [
178
+ 'SKILL.md must have YAML frontmatter with name and description fields',
179
+ 'Content must be at least 100 characters',
180
+ ],
181
+ };
182
+ }
183
+ // SMI-3510: Compare raw content hash against indexed hash (only if indexed hash exists)
184
+ const contentHashMismatch = indexedContentHash != null ? hashContent(skillMdContent) !== indexedContentHash : false;
185
+ // Security scan — GAP-06: Restrict skipScan to trusted tiers only
186
+ if (options.skipScan && (trustTier === 'experimental' || trustTier === 'unknown')) {
187
+ return {
188
+ success: false,
189
+ skillId,
190
+ installPath: '',
191
+ error: 'Cannot skip security scan for ' +
192
+ trustTier +
193
+ ' tier skills. ' +
194
+ 'Only verified, curated, community, and local tier skills may use skipScan.',
195
+ tips: [
196
+ 'Trust tier "' + trustTier + '" requires a security scan before installation',
197
+ 'If you believe this skill is safe, request a trust tier upgrade from the author',
198
+ ],
199
+ };
200
+ }
201
+ let securityReport;
202
+ if (!options.skipScan) {
203
+ this.onProgress('scan', 'Running security scan');
204
+ const scannerOptions = TRUST_TIER_SCANNER_OPTIONS[trustTier];
205
+ const scanner = new SecurityScanner(scannerOptions);
206
+ securityReport = scanner.scan(skillId, skillMdContent);
207
+ if (!securityReport.passed) {
208
+ const criticalFindings = securityReport.findings.filter((f) => f.severity === 'critical' || f.severity === 'high');
209
+ const tierContext = trustTier === 'unknown'
210
+ ? ' (Direct GitHub install - strictest scanning applied)'
211
+ : trustTier === 'experimental'
212
+ ? ' (Experimental skill - aggressive scanning applied)'
213
+ : '';
214
+ return {
215
+ success: false,
216
+ skillId,
217
+ installPath,
218
+ securityReport,
219
+ trustTier,
220
+ error: 'Security scan failed with ' +
221
+ criticalFindings.length +
222
+ ' critical/high findings' +
223
+ tierContext +
224
+ (trustTier === 'experimental' || trustTier === 'unknown'
225
+ ? '. skipScan is not available for ' + trustTier + ' tier skills.'
226
+ : '. Use skipScan=true to override (not recommended).'),
227
+ tips: [
228
+ 'Trust tier: ' + trustTier + ' (threshold: ' + scannerOptions.riskThreshold + ')',
229
+ 'Risk score: ' + securityReport.riskScore,
230
+ ],
231
+ };
232
+ }
233
+ }
234
+ // Optimization
235
+ this.onProgress('optimize', 'Applying optimization');
236
+ const optimizeResult = options.skipOptimize
237
+ ? {
238
+ finalSkillContent: skillMdContent,
239
+ subSkillFiles: [],
240
+ subagentContent: undefined,
241
+ claudeMdSnippet: undefined,
242
+ optimizationInfo: { optimized: false },
243
+ }
244
+ : await applyOptimization(this.db, skillId, skillName, skillMdContent);
245
+ const { finalSkillContent, subSkillFiles, subagentContent, optimizationInfo } = optimizeResult;
246
+ const contentHash = hashContent(finalSkillContent);
247
+ // Write files
248
+ this.onProgress('write', 'Writing skill files');
249
+ const writtenFiles = [];
250
+ try {
251
+ await fs.mkdir(installPath, { recursive: true });
252
+ // Validate directory is not a symlink escape
253
+ const realInstallPath = await fs.realpath(installPath);
254
+ const expectedPrefix = path.resolve(this.skillsDir);
255
+ if (!realInstallPath.startsWith(expectedPrefix + path.sep) &&
256
+ realInstallPath !== expectedPrefix) {
257
+ throw new Error('Install path escapes skills directory: ' + installPath);
258
+ }
259
+ const mainSkillPath = path.join(installPath, 'SKILL.md');
260
+ await safeWriteFile(mainSkillPath, finalSkillContent);
261
+ writtenFiles.push(mainSkillPath);
262
+ // Write sub-skills in parallel
263
+ if (subSkillFiles.length > 0) {
264
+ await Promise.all(subSkillFiles.map(async (subSkill) => {
265
+ const subPath = path.join(installPath, subSkill.filename);
266
+ await safeWriteFile(subPath, subSkill.content);
267
+ writtenFiles.push(subPath);
268
+ }));
269
+ }
270
+ // Write companion subagent if generated
271
+ if (subagentContent) {
272
+ const agentsDir = path.join(os.homedir(), '.claude', 'agents');
273
+ await fs.mkdir(agentsDir, { recursive: true });
274
+ const subagentPath = path.join(agentsDir, skillName + '-specialist.md');
275
+ await safeWriteFile(subagentPath, subagentContent);
276
+ writtenFiles.push(subagentPath);
277
+ optimizationInfo.subagentPath = subagentPath;
278
+ }
279
+ }
280
+ catch (writeError) {
281
+ // Rollback on failure
282
+ for (const filePath of writtenFiles) {
283
+ await fs.unlink(filePath).catch(() => { });
284
+ }
285
+ await fs.rmdir(installPath).catch(() => { });
286
+ throw writeError;
287
+ }
288
+ // Fetch optional files
289
+ const optionalFileScanner = options.skipScan
290
+ ? null
291
+ : new SecurityScanner(TRUST_TIER_SCANNER_OPTIONS[trustTier]);
292
+ const optionalFiles = ['README.md', 'examples.md', 'config.json'];
293
+ for (const file of optionalFiles) {
294
+ try {
295
+ const content = await fetchFromGitHub(owner, repo, basePath + file, branch);
296
+ if (optionalFileScanner) {
297
+ const fileScan = optionalFileScanner.scan(skillId + '/' + file, content);
298
+ if (!fileScan.passed) {
299
+ continue;
300
+ }
301
+ }
302
+ await safeWriteFile(path.join(installPath, file), content);
303
+ }
304
+ catch {
305
+ // Optional files are fine to skip
306
+ }
307
+ }
308
+ // Update manifest
309
+ this.onProgress('manifest', 'Updating manifest');
310
+ await this.manifest.updateSafely((currentManifest) => ({
311
+ ...currentManifest,
312
+ installedSkills: {
313
+ ...currentManifest.installedSkills,
314
+ [skillName]: {
315
+ id: skillId,
316
+ name: skillName,
317
+ version: '1.0.0',
318
+ source: 'github:' + owner + '/' + repo,
319
+ installPath,
320
+ installedAt: new Date().toISOString(),
321
+ lastUpdated: new Date().toISOString(),
322
+ originalContentHash: contentHash, // hash of optimized content (post-applyOptimization)
323
+ },
324
+ },
325
+ }));
326
+ // Record co-install session
327
+ if (this.coInstallRecorder) {
328
+ this.coInstallRecorder.recordSessionCoInstalls([...this.sessionInstalledSkillIds, skillId]);
329
+ this.sessionInstalledSkillIds.push(skillId);
330
+ }
331
+ // Persist dependency intelligence (best-effort)
332
+ const depIntel = extractDepIntel(skillMdContent);
333
+ try {
334
+ persistDependencies(this.skillDependencyRepo, skillId, skillMdContent, depIntel.dep_declared);
335
+ }
336
+ catch {
337
+ // Dependency persistence is best-effort
338
+ }
339
+ this.onProgress('done', 'Installation complete');
340
+ const tips = generateTips(skillName, optimizationInfo);
341
+ // GAP-06: Warn when skipScan was used (allowed tiers only reach here)
342
+ if (options.skipScan) {
343
+ tips.unshift('Security scan was skipped. This skill was not scanned for malicious content.');
344
+ }
345
+ // SMI-3510: Warn when content hash differs from indexed hash
346
+ if (contentHashMismatch) {
347
+ tips.unshift('Content has changed since Skillsmith last indexed this skill. ' +
348
+ 'This may mean the author updated it, or the content was modified. ' +
349
+ "Review recent changes at the skill's repository before using.");
350
+ }
351
+ return {
352
+ success: true,
353
+ skillId,
354
+ installPath,
355
+ securityReport,
356
+ trustTier,
357
+ optimization: optimizationInfo,
358
+ depIntel,
359
+ contentHashMismatch,
360
+ tips,
361
+ };
362
+ }
363
+ catch (error) {
364
+ return {
365
+ success: false,
366
+ skillId,
367
+ installPath: '',
368
+ error: sanitizeInstallError(error),
369
+ };
370
+ }
371
+ }
372
+ async uninstall(skillName, options = {}) {
373
+ return performUninstall({
374
+ skillName,
375
+ force: options.force ?? false,
376
+ skillsDir: this.skillsDir,
377
+ manifest: this.manifest,
378
+ skillDependencyRepo: this.skillDependencyRepo,
379
+ onProgress: this.onProgress,
380
+ });
381
+ }
382
+ }
383
+ //# sourceMappingURL=skill-installation.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.service.js","sourceRoot":"","sources":["../../../src/services/skill-installation.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @fileoverview Types for SkillInstallationService
3
+ * @module @skillsmith/core/services/skill-installation.types
4
+ * @see SMI-3483: Wave 0 — Extract SkillInstallationService into core
5
+ *
6
+ * Shared types consumed by both mcp-server and CLI for install/uninstall operations.
7
+ */
8
+ import type { ScanReport, ScannerOptions } from '../security/index.js';
9
+ import type { TrustTier } from '../types/skill.js';
10
+ import type { DependencyDeclaration } from '../types/dependencies.js';
11
+ /**
12
+ * Callback invoked during install/uninstall to report progress.
13
+ * CLI wires this to an `ora` spinner; mcp-server wires to MCP notifications.
14
+ */
15
+ export type ProgressCallback = (stage: string, detail: string) => void;
16
+ /** Action to take when a conflict is detected during skill update */
17
+ export type ConflictAction = 'overwrite' | 'merge' | 'cancel';
18
+ /** Options for the install operation */
19
+ export interface InstallOptions {
20
+ /** Force reinstall if the skill already exists */
21
+ force?: boolean;
22
+ /** Skip security scan (not recommended) */
23
+ skipScan?: boolean;
24
+ /** Skip Skillsmith optimization (decomposition, subagent generation) */
25
+ skipOptimize?: boolean;
26
+ /** Action to take when local modifications are detected */
27
+ conflictAction?: ConflictAction;
28
+ }
29
+ /** Dependency intelligence result from an install */
30
+ export interface DepIntelResult {
31
+ /** Inferred MCP server names from skill content */
32
+ dep_inferred_servers: string[];
33
+ /** Declared dependency block from frontmatter (if present) */
34
+ dep_declared: DependencyDeclaration | undefined;
35
+ /** Warnings about MCP servers referenced but not configured */
36
+ dep_warnings: string[];
37
+ }
38
+ /** Optimization metadata included in install result */
39
+ export interface OptimizationInfo {
40
+ /** Whether skill was optimized */
41
+ optimized: boolean;
42
+ /** Sub-skills created (filenames) */
43
+ subSkills?: string[];
44
+ /** Whether companion subagent was generated */
45
+ subagentGenerated?: boolean;
46
+ /** Path to generated subagent (if any) */
47
+ subagentPath?: string;
48
+ /** Estimated token reduction percentage */
49
+ tokenReductionPercent?: number;
50
+ /** Original line count */
51
+ originalLines?: number;
52
+ /** Optimized line count */
53
+ optimizedLines?: number;
54
+ }
55
+ /** Result of an install operation */
56
+ export interface InstallResult {
57
+ success: boolean;
58
+ skillId: string;
59
+ installPath: string;
60
+ securityReport?: ScanReport;
61
+ tips?: string[];
62
+ error?: string;
63
+ /** Trust tier used for security scanning */
64
+ trustTier?: TrustTier;
65
+ /** Optimization info (Skillsmith Optimization Layer) */
66
+ optimization?: OptimizationInfo;
67
+ /** Path to backup file created during conflict resolution */
68
+ backupPath?: string;
69
+ /** Dependency intelligence extracted during install */
70
+ depIntel?: DepIntelResult;
71
+ /** Whether fetched content hash differs from indexed content hash */
72
+ contentHashMismatch?: boolean;
73
+ }
74
+ /** Options for the uninstall operation */
75
+ export interface UninstallOptions {
76
+ /** Force removal even if skill has been modified since installation */
77
+ force?: boolean;
78
+ }
79
+ /** Result of an uninstall operation */
80
+ export interface UninstallResult {
81
+ success: boolean;
82
+ skillName: string;
83
+ message: string;
84
+ removedPath?: string;
85
+ warning?: string;
86
+ }
87
+ /** Entry for a single installed skill in the manifest */
88
+ export interface SkillManifestEntry {
89
+ id: string;
90
+ name: string;
91
+ version: string;
92
+ source: string;
93
+ /**
94
+ * Absolute path where the skill is installed.
95
+ * Required by type, but runtime JSON may omit it -- consumers must guard.
96
+ */
97
+ installPath: string;
98
+ installedAt: string;
99
+ lastUpdated: string;
100
+ /** SHA-256 hash of SKILL.md at install time for modification detection */
101
+ originalContentHash?: string;
102
+ /** SHA-256 hash of the content at last update */
103
+ contentHash?: string;
104
+ /** Pinned semver */
105
+ pinnedVersion?: string;
106
+ /** How updates are handled */
107
+ updatePolicy?: 'auto' | 'manual' | 'never';
108
+ }
109
+ /** Manifest tracking all installed skills */
110
+ export interface SkillManifest {
111
+ version: string;
112
+ installedSkills: Record<string, SkillManifestEntry>;
113
+ }
114
+ /** Result from a registry skill lookup */
115
+ export interface RegistrySkillInfo {
116
+ repoUrl: string;
117
+ name: string;
118
+ trustTier: TrustTier;
119
+ /** Whether the skill has been quarantined */
120
+ quarantined?: boolean;
121
+ /** SHA-256 hash of SKILL.md at index time for tamper detection */
122
+ contentHash?: string;
123
+ }
124
+ /**
125
+ * Abstraction for looking up skills in the registry.
126
+ * mcp-server provides the API-first implementation; CLI may provide a simpler one.
127
+ */
128
+ export interface RegistryLookup {
129
+ /**
130
+ * Look up a skill by its ID (e.g. "author/name" or UUID).
131
+ * Returns null if the skill is not found or has no installation source.
132
+ */
133
+ lookup(skillId: string): Promise<RegistrySkillInfo | null>;
134
+ }
135
+ /**
136
+ * Abstraction for recording co-install sessions.
137
+ * mcp-server provides the real implementation; CLI may skip or stub this.
138
+ */
139
+ export interface CoInstallRecorder {
140
+ recordSessionCoInstalls(skillIds: string[]): void;
141
+ }
142
+ /** Security scan configuration per trust tier */
143
+ export declare const TRUST_TIER_SCANNER_OPTIONS: Record<TrustTier, ScannerOptions>;
144
+ //# sourceMappingURL=skill-installation.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.types.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview Types for SkillInstallationService
3
+ * @module @skillsmith/core/services/skill-installation.types
4
+ * @see SMI-3483: Wave 0 — Extract SkillInstallationService into core
5
+ *
6
+ * Shared types consumed by both mcp-server and CLI for install/uninstall operations.
7
+ */
8
+ // ============================================================================
9
+ // Scanner Config
10
+ // ============================================================================
11
+ /** Security scan configuration per trust tier */
12
+ export const TRUST_TIER_SCANNER_OPTIONS = {
13
+ verified: {
14
+ riskThreshold: 70,
15
+ maxContentLength: 2_000_000,
16
+ },
17
+ curated: {
18
+ riskThreshold: 60,
19
+ maxContentLength: 2_000_000,
20
+ },
21
+ community: {
22
+ riskThreshold: 40,
23
+ maxContentLength: 1_000_000,
24
+ },
25
+ local: {
26
+ riskThreshold: 100,
27
+ maxContentLength: 10_000_000,
28
+ },
29
+ experimental: {
30
+ riskThreshold: 25,
31
+ maxContentLength: 500_000,
32
+ },
33
+ unknown: {
34
+ riskThreshold: 20,
35
+ maxContentLength: 250_000,
36
+ },
37
+ };
38
+ //# sourceMappingURL=skill-installation.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installation.types.js","sourceRoot":"","sources":["../../../src/services/skill-installation.types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0KH,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,iDAAiD;AACjD,MAAM,CAAC,MAAM,0BAA0B,GAAsC;IAC3E,QAAQ,EAAE;QACR,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,SAAS;KAC5B;IACD,OAAO,EAAE;QACP,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,SAAS;KAC5B;IACD,SAAS,EAAE;QACT,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,SAAS;KAC5B;IACD,KAAK,EAAE;QACL,aAAa,EAAE,GAAG;QAClB,gBAAgB,EAAE,UAAU;KAC7B;IACD,YAAY,EAAE;QACZ,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,OAAO;KAC1B;IACD,OAAO,EAAE;QACP,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,OAAO;KAC1B;CACF,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @fileoverview Manifest manager for skill installation tracking
3
+ * @module @skillsmith/core/services/skill-manifest
4
+ * @see SMI-3483: Extracted from skill-installation.service.ts to meet 500-line standard
5
+ */
6
+ import type { SkillManifest } from './skill-installation.types.js';
7
+ /**
8
+ * Manages the skill manifest file (~/.skillsmith/manifest.json) with
9
+ * file-level locking for concurrent access safety (CLI + MCP server).
10
+ */
11
+ export declare class ManifestManager {
12
+ private readonly manifestPath;
13
+ constructor(manifestPath: string);
14
+ load(): Promise<SkillManifest>;
15
+ save(manifest: SkillManifest): Promise<void>;
16
+ acquireLock(): Promise<void>;
17
+ releaseLock(): Promise<void>;
18
+ updateSafely(updateFn: (manifest: SkillManifest) => SkillManifest): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=skill-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../src/services/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAKlE;;;GAGG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,MAAM;IAE3C,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;IAS9B,IAAI,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B5B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAUxF"}