skilld 1.7.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/_chunks/add.mjs +66 -0
  2. package/dist/_chunks/add.mjs.map +1 -0
  3. package/dist/_chunks/agent-prompt.mjs +88 -0
  4. package/dist/_chunks/agent-prompt.mjs.map +1 -0
  5. package/dist/_chunks/agent.mjs +737 -619
  6. package/dist/_chunks/agent.mjs.map +1 -1
  7. package/dist/_chunks/args.mjs +42 -0
  8. package/dist/_chunks/args.mjs.map +1 -0
  9. package/dist/_chunks/assemble.mjs +11 -8
  10. package/dist/_chunks/assemble.mjs.map +1 -1
  11. package/dist/_chunks/author.mjs +77 -131
  12. package/dist/_chunks/author.mjs.map +1 -1
  13. package/dist/_chunks/cache.mjs +320 -54
  14. package/dist/_chunks/cache.mjs.map +1 -1
  15. package/dist/_chunks/cache2.mjs +7 -6
  16. package/dist/_chunks/cache2.mjs.map +1 -1
  17. package/dist/_chunks/client.mjs +117 -0
  18. package/dist/_chunks/client.mjs.map +1 -0
  19. package/dist/_chunks/core.mjs +7 -4
  20. package/dist/_chunks/detect.mjs +54 -44
  21. package/dist/_chunks/detect.mjs.map +1 -1
  22. package/dist/_chunks/eject.mjs +69 -0
  23. package/dist/_chunks/eject.mjs.map +1 -0
  24. package/dist/_chunks/embedding-cache2.mjs +2 -2
  25. package/dist/_chunks/env.mjs +19 -0
  26. package/dist/_chunks/env.mjs.map +1 -0
  27. package/dist/_chunks/install-many.mjs +376 -0
  28. package/dist/_chunks/install-many.mjs.map +1 -0
  29. package/dist/_chunks/install.mjs +86 -371
  30. package/dist/_chunks/install.mjs.map +1 -1
  31. package/dist/_chunks/intro.mjs +63 -0
  32. package/dist/_chunks/intro.mjs.map +1 -0
  33. package/dist/_chunks/list.mjs +2 -2
  34. package/dist/_chunks/list.mjs.map +1 -1
  35. package/dist/_chunks/lockfile.mjs +31 -7
  36. package/dist/_chunks/lockfile.mjs.map +1 -1
  37. package/dist/_chunks/login.mjs +233 -0
  38. package/dist/_chunks/login.mjs.map +1 -0
  39. package/dist/_chunks/logout.mjs +27 -0
  40. package/dist/_chunks/logout.mjs.map +1 -0
  41. package/dist/_chunks/map.mjs +11 -0
  42. package/dist/_chunks/map.mjs.map +1 -0
  43. package/dist/_chunks/markdown.mjs +79 -54
  44. package/dist/_chunks/markdown.mjs.map +1 -1
  45. package/dist/_chunks/menu.mjs +33 -0
  46. package/dist/_chunks/menu.mjs.map +1 -0
  47. package/dist/_chunks/model-picker.mjs +61 -0
  48. package/dist/_chunks/model-picker.mjs.map +1 -0
  49. package/dist/_chunks/monorepo.mjs +73 -0
  50. package/dist/_chunks/monorepo.mjs.map +1 -0
  51. package/dist/_chunks/package-json.mjs.map +1 -1
  52. package/dist/_chunks/paths.mjs +47 -0
  53. package/dist/_chunks/paths.mjs.map +1 -0
  54. package/dist/_chunks/pipeline.mjs +985 -0
  55. package/dist/_chunks/pipeline.mjs.map +1 -0
  56. package/dist/_chunks/pool2.mjs +2 -2
  57. package/dist/_chunks/portable.mjs +151 -0
  58. package/dist/_chunks/portable.mjs.map +1 -0
  59. package/dist/_chunks/prepare-hook.mjs +2 -0
  60. package/dist/_chunks/prepare-hook2.mjs +61 -0
  61. package/dist/_chunks/prepare-hook2.mjs.map +1 -0
  62. package/dist/_chunks/prepare.mjs +47 -3
  63. package/dist/_chunks/prepare.mjs.map +1 -1
  64. package/dist/_chunks/prepare2.mjs +9 -8
  65. package/dist/_chunks/prepare2.mjs.map +1 -1
  66. package/dist/_chunks/prompts.mjs +784 -26
  67. package/dist/_chunks/prompts.mjs.map +1 -1
  68. package/dist/_chunks/pull.mjs +219 -0
  69. package/dist/_chunks/pull.mjs.map +1 -0
  70. package/dist/_chunks/regex.mjs +19 -0
  71. package/dist/_chunks/regex.mjs.map +1 -0
  72. package/dist/_chunks/retriv.mjs +2 -171
  73. package/dist/_chunks/retriv2.mjs +159 -0
  74. package/dist/_chunks/retriv2.mjs.map +1 -0
  75. package/dist/_chunks/sanitize.mjs +12 -9
  76. package/dist/_chunks/sanitize.mjs.map +1 -1
  77. package/dist/_chunks/search-helpers.mjs +9 -8
  78. package/dist/_chunks/search-helpers.mjs.map +1 -1
  79. package/dist/_chunks/search-interactive.mjs +23 -20
  80. package/dist/_chunks/search-interactive.mjs.map +1 -1
  81. package/dist/_chunks/search.mjs +3 -4
  82. package/dist/_chunks/search.mjs.map +1 -1
  83. package/dist/_chunks/{sources.mjs → semver.mjs} +1128 -838
  84. package/dist/_chunks/semver.mjs.map +1 -0
  85. package/dist/_chunks/skill-installer.mjs +2 -0
  86. package/dist/_chunks/skill-installer2.mjs +154 -0
  87. package/dist/_chunks/skill-installer2.mjs.map +1 -0
  88. package/dist/_chunks/skills.mjs +12 -12
  89. package/dist/_chunks/skills.mjs.map +1 -1
  90. package/dist/_chunks/store.mjs +107 -0
  91. package/dist/_chunks/store.mjs.map +1 -0
  92. package/dist/_chunks/sync.mjs +761 -1349
  93. package/dist/_chunks/sync.mjs.map +1 -1
  94. package/dist/_chunks/sync2.mjs +2 -3
  95. package/dist/_chunks/telemetry.mjs +26 -0
  96. package/dist/_chunks/telemetry.mjs.map +1 -0
  97. package/dist/_chunks/uninstall.mjs +15 -13
  98. package/dist/_chunks/uninstall.mjs.map +1 -1
  99. package/dist/_chunks/update.mjs +171 -0
  100. package/dist/_chunks/update.mjs.map +1 -0
  101. package/dist/_chunks/upload.mjs +4 -4
  102. package/dist/_chunks/validate.mjs +1 -1
  103. package/dist/_chunks/version.mjs +16 -27
  104. package/dist/_chunks/version.mjs.map +1 -1
  105. package/dist/_chunks/whoami.mjs +21 -0
  106. package/dist/_chunks/whoami.mjs.map +1 -0
  107. package/dist/_chunks/wizard.mjs +2 -190
  108. package/dist/_chunks/wizard2.mjs +200 -0
  109. package/dist/_chunks/wizard2.mjs.map +1 -0
  110. package/dist/cli.mjs +77 -59
  111. package/dist/cli.mjs.map +1 -1
  112. package/dist/prepare.mjs +5 -4
  113. package/dist/prepare.mjs.map +1 -1
  114. package/dist/retriv/worker.d.mts +5 -1
  115. package/dist/retriv/worker.d.mts.map +1 -1
  116. package/dist/retriv/worker.mjs +1 -1
  117. package/package.json +20 -29
  118. package/dist/_chunks/author-group.mjs +0 -17
  119. package/dist/_chunks/author-group.mjs.map +0 -1
  120. package/dist/_chunks/cli-helpers.mjs +0 -335
  121. package/dist/_chunks/cli-helpers.mjs.map +0 -1
  122. package/dist/_chunks/cli-helpers2.mjs +0 -2
  123. package/dist/_chunks/config.mjs +0 -122
  124. package/dist/_chunks/config.mjs.map +0 -1
  125. package/dist/_chunks/index.d.mts +0 -151
  126. package/dist/_chunks/index.d.mts.map +0 -1
  127. package/dist/_chunks/index2.d.mts +0 -44
  128. package/dist/_chunks/index2.d.mts.map +0 -1
  129. package/dist/_chunks/index3.d.mts +0 -589
  130. package/dist/_chunks/index3.d.mts.map +0 -1
  131. package/dist/_chunks/prefix.mjs +0 -108
  132. package/dist/_chunks/prefix.mjs.map +0 -1
  133. package/dist/_chunks/retriv.mjs.map +0 -1
  134. package/dist/_chunks/setup.mjs +0 -17
  135. package/dist/_chunks/setup.mjs.map +0 -1
  136. package/dist/_chunks/shared.mjs +0 -503
  137. package/dist/_chunks/shared.mjs.map +0 -1
  138. package/dist/_chunks/skill.mjs +0 -329
  139. package/dist/_chunks/skill.mjs.map +0 -1
  140. package/dist/_chunks/sources.mjs.map +0 -1
  141. package/dist/_chunks/sync-registry.mjs +0 -59
  142. package/dist/_chunks/sync-registry.mjs.map +0 -1
  143. package/dist/_chunks/sync-shared.mjs +0 -2
  144. package/dist/_chunks/sync-shared2.mjs +0 -1020
  145. package/dist/_chunks/sync-shared2.mjs.map +0 -1
  146. package/dist/_chunks/types.d.mts +0 -88
  147. package/dist/_chunks/types.d.mts.map +0 -1
  148. package/dist/_chunks/wizard.mjs.map +0 -1
  149. package/dist/agent/index.d.mts +0 -346
  150. package/dist/agent/index.d.mts.map +0 -1
  151. package/dist/agent/index.mjs +0 -5
  152. package/dist/cache/index.d.mts +0 -2
  153. package/dist/cache/index.mjs +0 -4
  154. package/dist/index.d.mts +0 -5
  155. package/dist/index.mjs +0 -5
  156. package/dist/retriv/index.d.mts +0 -3
  157. package/dist/retriv/index.mjs +0 -2
  158. package/dist/sources/index.d.mts +0 -2
  159. package/dist/sources/index.mjs +0 -3
  160. package/dist/types.d.mts +0 -4
  161. package/dist/types.mjs +0 -1
@@ -1,9 +1,150 @@
1
- import { a as REFERENCES_DIR, c as getRepoCacheDir, o as REPOS_DIR, t as getCacheDir } from "./version.mjs";
2
- import { i as readPackageJsonSafe } from "./package-json.mjs";
3
- import { r as resolvePkgDir } from "./prepare.mjs";
1
+ import { c as REPOS_DIR, d as getRepoCacheDir, m as skillInternalDir, n as CACHE_DIR, r as CONFIG_PATH, s as REFERENCES_DIR, u as getPackageDbPath } from "./paths.mjs";
4
2
  import { n as sanitizeMarkdown } from "./sanitize.mjs";
5
- import { basename, join, resolve } from "pathe";
6
- import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import { n as yamlParseKV, r as yamlUnescape, t as yamlEscape } from "./yaml.mjs";
4
+ import { a as resolvePkgDir, c as getVersionKey, r as hasShippedDocs, s as getCacheDir, t as getPkgKeyFiles } from "./prepare.mjs";
5
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
6
+ import { dirname, join, resolve } from "pathe";
7
+ const STATIC_REGEX_1$1 = /^ {2}(\w+):\s*(.+)/;
8
+ const defaultFeatures = {
9
+ search: true,
10
+ issues: true,
11
+ discussions: true,
12
+ releases: true
13
+ };
14
+ function getActiveFeatures(overrides) {
15
+ const fromConfig = readConfig().features;
16
+ const merged = {
17
+ ...defaultFeatures,
18
+ ...fromConfig ?? {}
19
+ };
20
+ return overrides ? {
21
+ ...merged,
22
+ ...overrides
23
+ } : merged;
24
+ }
25
+ let configCache;
26
+ function hasConfig() {
27
+ return existsSync(CONFIG_PATH);
28
+ }
29
+ function hasCompletedWizard() {
30
+ if (!existsSync(CONFIG_PATH)) return false;
31
+ const config = readConfig();
32
+ return config.features !== void 0 || config.model !== void 0 || config.skipLlm !== void 0;
33
+ }
34
+ function readConfig() {
35
+ if (configCache) return {
36
+ ...configCache,
37
+ features: configCache.features ? { ...configCache.features } : void 0,
38
+ projects: configCache.projects ? [...configCache.projects] : void 0
39
+ };
40
+ if (!existsSync(CONFIG_PATH)) return {};
41
+ const content = readFileSync(CONFIG_PATH, "utf-8");
42
+ const config = {};
43
+ let inBlock = null;
44
+ const projects = [];
45
+ const features = {};
46
+ for (const line of content.split("\n")) {
47
+ if (line.startsWith("projects:")) {
48
+ inBlock = "projects";
49
+ continue;
50
+ }
51
+ if (line.startsWith("features:")) {
52
+ inBlock = "features";
53
+ continue;
54
+ }
55
+ if (inBlock === "projects") {
56
+ if (line.startsWith(" - ")) {
57
+ projects.push(yamlUnescape(line.slice(4)));
58
+ continue;
59
+ }
60
+ inBlock = null;
61
+ }
62
+ if (inBlock === "features") {
63
+ const m = line.match(STATIC_REGEX_1$1);
64
+ if (m) {
65
+ const key = m[1];
66
+ if (key in defaultFeatures) features[key] = m[2] === "true";
67
+ continue;
68
+ }
69
+ inBlock = null;
70
+ }
71
+ const kv = yamlParseKV(line);
72
+ if (!kv) continue;
73
+ const [key, value] = kv;
74
+ if (key === "model" && value) config.model = value;
75
+ if (key === "agent" && value) config.agent = value;
76
+ if (key === "skipLlm") config.skipLlm = value === "true";
77
+ }
78
+ if (projects.length > 0) config.projects = projects;
79
+ if (Object.keys(features).length > 0) config.features = {
80
+ ...defaultFeatures,
81
+ ...features
82
+ };
83
+ configCache = config;
84
+ return config;
85
+ }
86
+ function writeConfig(config) {
87
+ mkdirSync(CACHE_DIR, {
88
+ recursive: true,
89
+ mode: 448
90
+ });
91
+ let yaml = "";
92
+ if (config.model) yaml += `model: ${config.model}\n`;
93
+ if (config.agent) yaml += `agent: ${config.agent}\n`;
94
+ if (config.skipLlm) yaml += `skipLlm: true\n`;
95
+ if (config.features) {
96
+ yaml += "features:\n";
97
+ for (const [k, v] of Object.entries(config.features)) yaml += ` ${k}: ${v}\n`;
98
+ }
99
+ if (config.projects?.length) {
100
+ yaml += "projects:\n";
101
+ for (const p of config.projects) yaml += ` - ${yamlEscape(p)}\n`;
102
+ }
103
+ writeFileSync(CONFIG_PATH, yaml, { mode: 384 });
104
+ configCache = void 0;
105
+ }
106
+ function updateConfig(updates) {
107
+ writeConfig({
108
+ ...readConfig(),
109
+ ...updates
110
+ });
111
+ }
112
+ function registerProject(projectPath) {
113
+ const config = readConfig();
114
+ const projects = new Set(config.projects || []);
115
+ projects.add(projectPath);
116
+ writeConfig({
117
+ ...config,
118
+ projects: [...projects]
119
+ });
120
+ }
121
+ function unregisterProject(projectPath) {
122
+ const config = readConfig();
123
+ const projects = (config.projects || []).filter((p) => p !== projectPath);
124
+ writeConfig({
125
+ ...config,
126
+ projects
127
+ });
128
+ }
129
+ function getRegisteredProjects() {
130
+ return readConfig().projects || [];
131
+ }
132
+ const STATIC_REGEX_1 = /^issues\/issue-(\d+)\.md$/;
133
+ const STATIC_REGEX_2 = /^discussions\/discussion-(\d+)\.md$/;
134
+ function classifyCachedDoc(path) {
135
+ const issueMatch = path.match(STATIC_REGEX_1);
136
+ if (issueMatch) return {
137
+ type: "issue",
138
+ number: Number(issueMatch[1])
139
+ };
140
+ const discussionMatch = path.match(STATIC_REGEX_2);
141
+ if (discussionMatch) return {
142
+ type: "discussion",
143
+ number: Number(discussionMatch[1])
144
+ };
145
+ if (path.startsWith("releases/")) return { type: "release" };
146
+ return { type: "doc" };
147
+ }
7
148
  function safeSymlink(target, linkPath) {
8
149
  const resolved = resolve(target);
9
150
  if (!resolved.startsWith(REFERENCES_DIR) && !resolved.startsWith(REPOS_DIR)) throw new Error(`Symlink target outside allowed dirs: ${resolved}`);
@@ -70,7 +211,7 @@ function writeToRepoCache(owner, repo, docs) {
70
211
  }
71
212
  function linkRepoCachedDir(skillDir, owner, repo, subdir) {
72
213
  const repoDir = getRepoCacheDir(owner, repo);
73
- const referencesDir = join(skillDir, ".skilld");
214
+ const referencesDir = skillInternalDir(skillDir);
74
215
  const linkPath = join(referencesDir, subdir);
75
216
  const cachedPath = join(repoDir, subdir);
76
217
  mkdirSync(referencesDir, { recursive: true });
@@ -78,7 +219,7 @@ function linkRepoCachedDir(skillDir, owner, repo, subdir) {
78
219
  }
79
220
  function linkCachedDir(skillDir, name, version, subdir) {
80
221
  const cacheDir = getCacheDir(name, version);
81
- const referencesDir = join(skillDir, ".skilld");
222
+ const referencesDir = skillInternalDir(skillDir);
82
223
  const linkPath = join(referencesDir, subdir);
83
224
  const cachedPath = join(cacheDir, subdir);
84
225
  mkdirSync(referencesDir, { recursive: true });
@@ -87,7 +228,7 @@ function linkCachedDir(skillDir, name, version, subdir) {
87
228
  function linkPkg(skillDir, name, cwd, version) {
88
229
  const pkgPath = resolvePkgDir(name, cwd, version);
89
230
  if (!pkgPath) return;
90
- const referencesDir = join(skillDir, ".skilld");
231
+ const referencesDir = skillInternalDir(skillDir);
91
232
  mkdirSync(referencesDir, { recursive: true });
92
233
  const pkgLinkPath = join(referencesDir, "pkg");
93
234
  try {
@@ -100,7 +241,7 @@ function linkPkgNamed(skillDir, name, cwd, version) {
100
241
  const pkgPath = resolvePkgDir(name, cwd, version);
101
242
  if (!pkgPath) return;
102
243
  const shortName = name.split("/").pop().toLowerCase();
103
- const referencesDir = join(skillDir, ".skilld");
244
+ const referencesDir = skillInternalDir(skillDir);
104
245
  mkdirSync(referencesDir, { recursive: true });
105
246
  const linkPath = join(referencesDir, `pkg-${shortName}`);
106
247
  try {
@@ -109,22 +250,6 @@ function linkPkgNamed(skillDir, name, cwd, version) {
109
250
  } catch {}
110
251
  symlinkSync(pkgPath, linkPath, "junction");
111
252
  }
112
- function getPkgKeyFiles(name, cwd, version) {
113
- const pkgPath = resolvePkgDir(name, cwd, version);
114
- if (!pkgPath) return [];
115
- const files = [];
116
- const pkgJsonResult = readPackageJsonSafe(join(pkgPath, "package.json"));
117
- if (pkgJsonResult) {
118
- const pkg = pkgJsonResult.parsed;
119
- if (pkg.main) files.push(basename(pkg.main));
120
- if (pkg.module && pkg.module !== pkg.main) files.push(basename(pkg.module));
121
- const typesPath = pkg.types || pkg.typings;
122
- if (typesPath && existsSync(join(pkgPath, typesPath))) files.push(typesPath);
123
- }
124
- const entries = readdirSync(pkgPath).filter((f) => /^readme\.md$/i.test(f) || /^changelog\.md$/i.test(f));
125
- files.push(...entries);
126
- return [...new Set(files)];
127
- }
128
253
  function writeSections(name, version, sections) {
129
254
  const sectionsDir = join(getCacheDir(name, version), "sections");
130
255
  mkdirSync(sectionsDir, {
@@ -138,27 +263,6 @@ function readCachedSection(name, version, file) {
138
263
  if (!existsSync(path)) return null;
139
264
  return readFileSync(path, "utf-8");
140
265
  }
141
- function hasShippedDocs(name, cwd, version) {
142
- const pkgPath = resolvePkgDir(name, cwd, version);
143
- if (!pkgPath) return false;
144
- for (const candidate of [
145
- "docs",
146
- "documentation",
147
- "doc"
148
- ]) if (existsSync(join(pkgPath, candidate))) return true;
149
- return false;
150
- }
151
- function listCached() {
152
- if (!existsSync(REFERENCES_DIR)) return [];
153
- return readdirSync(REFERENCES_DIR).filter((name) => name.includes("@")).map((dir) => {
154
- const atIdx = dir.lastIndexOf("@");
155
- return {
156
- name: dir.slice(0, atIdx),
157
- version: dir.slice(atIdx + 1),
158
- dir: join(REFERENCES_DIR, dir)
159
- };
160
- });
161
- }
162
266
  function readCachedDocs(name, version) {
163
267
  const cacheDir = getCacheDir(name, version);
164
268
  if (!existsSync(cacheDir)) return [];
@@ -183,14 +287,8 @@ function clearCache(name, version) {
183
287
  rmSync(cacheDir, { recursive: true });
184
288
  return true;
185
289
  }
186
- function clearAllCache() {
187
- const packages = listCached();
188
- for (const pkg of packages) clearCache(pkg.name, pkg.version);
189
- if (existsSync(REPOS_DIR)) rmSync(REPOS_DIR, { recursive: true });
190
- return packages.length;
191
- }
192
290
  function listReferenceFiles(skillDir, maxDepth = 3) {
193
- const referencesDir = join(skillDir, ".skilld");
291
+ const referencesDir = skillInternalDir(skillDir);
194
292
  if (!existsSync(referencesDir)) return [];
195
293
  const files = [];
196
294
  function walk(dir, depth) {
@@ -213,6 +311,174 @@ function listReferenceFiles(skillDir, maxDepth = 3) {
213
311
  walk(referencesDir, 0);
214
312
  return files;
215
313
  }
216
- export { writeSections as _, hasShippedDocs as a, isReadmeOnlyCache as c, linkPkgNamed as d, linkRepoCachedDir as f, readCachedSection as g, readCachedDocs as h, getPkgKeyFiles as i, linkCachedDir as l, listReferenceFiles as m, clearCache as n, inferDocsTypeFromCache as o, listCached as p, ensureCacheDir as r, isCached as s, clearAllCache as t, linkPkg as u, writeToCache as v, writeToRepoCache as y };
314
+ function getSkillReferenceDirs(skillDir) {
315
+ const refsDir = skillInternalDir(skillDir);
316
+ if (!existsSync(refsDir)) return [];
317
+ const resolved = readdirSync(refsDir).map((entry) => join(refsDir, entry)).filter((p) => lstatSync(p).isSymbolicLink() && existsSync(p)).map((p) => realpathSync(p));
318
+ const parents = /* @__PURE__ */ new Set();
319
+ for (const p of resolved) {
320
+ const parent = dirname(p);
321
+ if (!resolved.includes(parent)) parents.add(parent);
322
+ }
323
+ return [...resolved, ...parents];
324
+ }
325
+ function clearSkillInternalDir(skillDir) {
326
+ const refsDir = skillInternalDir(skillDir);
327
+ if (existsSync(refsDir)) rmSync(refsDir, {
328
+ recursive: true,
329
+ force: true
330
+ });
331
+ }
332
+ function forceClearCache(packageName, version, repoInfo) {
333
+ clearCache(packageName, version);
334
+ const forcedDbPath = getPackageDbPath(packageName, version);
335
+ if (existsSync(forcedDbPath)) rmSync(forcedDbPath, {
336
+ recursive: true,
337
+ force: true
338
+ });
339
+ if (repoInfo) {
340
+ const repoDir = getRepoCacheDir(repoInfo.owner, repoInfo.repo);
341
+ if (existsSync(repoDir)) rmSync(repoDir, {
342
+ recursive: true,
343
+ force: true
344
+ });
345
+ }
346
+ }
347
+ function linkAllReferences(skillDir, packageName, cwd, version, docsType, extraPackages, features, repoInfo) {
348
+ const f = features ?? readConfig().features ?? defaultFeatures;
349
+ try {
350
+ linkPkg(skillDir, packageName, cwd, version);
351
+ linkPkgNamed(skillDir, packageName, cwd, version);
352
+ if (!hasShippedDocs(packageName, cwd, version) && docsType !== "readme") linkCachedDir(skillDir, packageName, version, "docs");
353
+ if (f.issues) if (repoInfo) linkRepoCachedDir(skillDir, repoInfo.owner, repoInfo.repo, "issues");
354
+ else linkCachedDir(skillDir, packageName, version, "issues");
355
+ if (f.discussions) if (repoInfo) linkRepoCachedDir(skillDir, repoInfo.owner, repoInfo.repo, "discussions");
356
+ else linkCachedDir(skillDir, packageName, version, "discussions");
357
+ if (f.releases) if (repoInfo) linkRepoCachedDir(skillDir, repoInfo.owner, repoInfo.repo, "releases");
358
+ else linkCachedDir(skillDir, packageName, version, "releases");
359
+ linkCachedDir(skillDir, packageName, version, "sections");
360
+ if (extraPackages) {
361
+ for (const pkg of extraPackages) if (pkg.name !== packageName) linkPkgNamed(skillDir, pkg.name, cwd, pkg.version);
362
+ }
363
+ } catch {}
364
+ }
365
+ function detectDocsType(packageName, version, repoUrl, llmsUrl) {
366
+ const cacheDir = getCacheDir(packageName, version);
367
+ if (existsSync(join(cacheDir, "docs", "index.md")) || existsSync(join(cacheDir, "docs", "guide"))) return {
368
+ docsType: "docs",
369
+ docSource: repoUrl ? `${repoUrl}/tree/v${version}/docs` : "git"
370
+ };
371
+ if (existsSync(join(cacheDir, "llms.txt"))) return {
372
+ docsType: "llms.txt",
373
+ docSource: llmsUrl || "llms.txt"
374
+ };
375
+ if (existsSync(join(cacheDir, "docs", "README.md"))) return { docsType: "readme" };
376
+ return { docsType: "readme" };
377
+ }
378
+ function ejectReferences(skillDir, packageName, cwd, version, docsType, features, repoInfo) {
379
+ const f = features ?? readConfig().features ?? defaultFeatures;
380
+ const cacheDir = getCacheDir(packageName, version);
381
+ const refsDir = join(skillDir, "references");
382
+ const repoDir = repoInfo ? getRepoCacheDir(repoInfo.owner, repoInfo.repo) : cacheDir;
383
+ if (!hasShippedDocs(packageName, cwd, version) && docsType !== "readme") copyCachedSubdir(cacheDir, refsDir, "docs");
384
+ if (f.issues) copyCachedSubdir(repoDir, refsDir, "issues");
385
+ if (f.discussions) copyCachedSubdir(repoDir, refsDir, "discussions");
386
+ if (f.releases) copyCachedSubdir(repoDir, refsDir, "releases");
387
+ }
388
+ function copyCachedSubdir(cacheDir, refsDir, subdir) {
389
+ const srcDir = join(cacheDir, subdir);
390
+ if (!existsSync(srcDir)) return;
391
+ const destDir = join(refsDir, subdir);
392
+ mkdirSync(destDir, { recursive: true });
393
+ function walk(dir, rel) {
394
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
395
+ const srcPath = join(dir, entry.name);
396
+ const destPath = join(destDir, rel ? `${rel}/${entry.name}` : entry.name);
397
+ if (entry.isDirectory()) {
398
+ mkdirSync(destPath, { recursive: true });
399
+ walk(srcPath, rel ? `${rel}/${entry.name}` : entry.name);
400
+ } else copyFileSync(srcPath, destPath);
401
+ }
402
+ }
403
+ walk(srcDir, "");
404
+ }
405
+ function loadCachedReferences(opts) {
406
+ const { packageName, version, repoUrl, llmsUrl, readmeUrl, onProgress, generateDocsIndex } = opts;
407
+ onProgress("Loading cached docs");
408
+ const detected = detectDocsType(packageName, version, repoUrl, llmsUrl);
409
+ const docsType = detected.docsType;
410
+ const docSource = detected.docSource ?? readmeUrl ?? "readme";
411
+ const docsToIndex = [];
412
+ if (!existsSync(getPackageDbPath(packageName, version))) {
413
+ onProgress("Reading cached docs for indexing");
414
+ const cached = readCachedDocs(packageName, version);
415
+ for (const doc of cached) docsToIndex.push({
416
+ id: doc.path,
417
+ content: doc.content,
418
+ metadata: {
419
+ package: packageName,
420
+ source: doc.path,
421
+ ...classifyCachedDoc(doc.path)
422
+ }
423
+ });
424
+ }
425
+ let backfillIndex;
426
+ if (docsType !== "readme" && !existsSync(join(getCacheDir(packageName, version), "docs", "_INDEX.md"))) {
427
+ onProgress("Generating docs index");
428
+ const cached = readCachedDocs(packageName, version);
429
+ if (cached.filter((d) => d.path.startsWith("docs/") && d.path.endsWith(".md")).length > 1) {
430
+ const docsIndex = generateDocsIndex(cached);
431
+ if (docsIndex) backfillIndex = {
432
+ path: "docs/_INDEX.md",
433
+ content: docsIndex
434
+ };
435
+ }
436
+ }
437
+ return {
438
+ docsToIndex,
439
+ docSource,
440
+ docsType,
441
+ backfillIndex
442
+ };
443
+ }
444
+ function createReferenceCache(packageName, version) {
445
+ const requireVersion = (op) => {
446
+ if (!version) throw new Error(`ReferenceCache.${op} requires a version (package: ${packageName})`);
447
+ return version;
448
+ };
449
+ return {
450
+ packageName,
451
+ version,
452
+ get versionKey() {
453
+ return getVersionKey(requireVersion("versionKey"));
454
+ },
455
+ get dir() {
456
+ return getCacheDir(packageName, requireVersion("dir"));
457
+ },
458
+ ensure: () => ensureCacheDir(),
459
+ has: () => !!version && isCached(packageName, version),
460
+ isReadmeOnly: () => isReadmeOnlyCache(getCacheDir(packageName, requireVersion("isReadmeOnly"))),
461
+ inferDocsType: (source) => inferDocsTypeFromCache(getCacheDir(packageName, requireVersion("inferDocsType")), source),
462
+ write: (docs) => void writeToCache(packageName, requireVersion("write"), docs),
463
+ writeSections: (sections) => writeSections(packageName, requireVersion("writeSections"), sections),
464
+ readSection: (file) => readCachedSection(packageName, requireVersion("readSection"), file),
465
+ readDocs: () => readCachedDocs(packageName, requireVersion("readDocs")),
466
+ detectDocs: (repoUrl, llmsUrl) => detectDocsType(packageName, requireVersion("detectDocs"), repoUrl, llmsUrl),
467
+ load: (opts) => loadCachedReferences({
468
+ ...opts,
469
+ packageName,
470
+ version: requireVersion("load")
471
+ }),
472
+ linkInto: (skillDir, cwd, docsType, opts) => linkAllReferences(skillDir, packageName, cwd, requireVersion("linkInto"), docsType, opts?.extraPackages, opts?.features, opts?.repoInfo),
473
+ linkPkgNamed: (skillDir, cwd) => linkPkgNamed(skillDir, packageName, cwd, version),
474
+ eject: (skillDir, cwd, docsType, opts) => ejectReferences(skillDir, packageName, cwd, requireVersion("eject"), docsType, opts?.features, opts?.repoInfo),
475
+ clearForce: (repoInfo) => forceClearCache(packageName, requireVersion("clearForce"), repoInfo),
476
+ clearSkillInternal: (skillDir) => clearSkillInternalDir(skillDir),
477
+ pkgDir: (cwd) => resolvePkgDir(packageName, cwd, version),
478
+ hasShipped: (cwd) => hasShippedDocs(packageName, cwd, version),
479
+ keyFiles: (cwd) => getPkgKeyFiles(packageName, cwd, version)
480
+ };
481
+ }
482
+ export { writeToRepoCache as a, getRegisteredProjects as c, readConfig as d, registerProject as f, listReferenceFiles as i, hasCompletedWizard as l, updateConfig as m, getSkillReferenceDirs as n, defaultFeatures as o, unregisterProject as p, ensureCacheDir as r, getActiveFeatures as s, createReferenceCache as t, hasConfig as u };
217
483
 
218
484
  //# sourceMappingURL=cache.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache.mjs","names":[],"sources":["../../src/cache/storage.ts"],"sourcesContent":["/**\n * Cache storage operations\n */\n\nimport type { CachedDoc, CachedPackage } from './types.ts'\nimport { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { basename, join, resolve } from 'pathe'\nimport { readPackageJsonSafe } from '../core/package-json.ts'\nimport { resolvePkgDir } from '../core/prepare.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getRepoCacheDir, REFERENCES_DIR, REPOS_DIR } from './config.ts'\nimport { getCacheDir } from './version.ts'\n\n/** Safely create a symlink, validating target is under REFERENCES_DIR or REPOS_DIR */\nfunction safeSymlink(target: string, linkPath: string): void {\n const resolved = resolve(target)\n if (!resolved.startsWith(REFERENCES_DIR) && !resolved.startsWith(REPOS_DIR))\n throw new Error(`Symlink target outside allowed dirs: ${resolved}`)\n // Remove pre-existing symlink (check with lstat to detect symlinks)\n try {\n const stat = lstatSync(linkPath)\n if (stat.isSymbolicLink() || stat.isFile())\n unlinkSync(linkPath)\n }\n catch {}\n symlinkSync(target, linkPath, 'junction')\n}\n\n/**\n * Check if package is cached at given version\n */\nexport function isCached(name: string, version: string): boolean {\n return existsSync(getCacheDir(name, version))\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nexport function isReadmeOnlyCache(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\nexport function inferDocsTypeFromCache(cacheDir: string, source?: string): 'llms.txt' | 'readme' | 'docs' {\n if (source?.includes('llms.txt') || existsSync(join(cacheDir, 'docs', 'llms.txt')))\n return 'llms.txt'\n return isReadmeOnlyCache(cacheDir) ? 'readme' : 'docs'\n}\n\n/**\n * Ensure cache directories exist\n */\nexport function ensureCacheDir(): void {\n mkdirSync(REFERENCES_DIR, { recursive: true, mode: 0o700 })\n mkdirSync(REPOS_DIR, { recursive: true, mode: 0o700 })\n}\n\n/**\n * Write docs to cache\n */\nexport function writeToCache(\n name: string,\n version: string,\n docs: CachedDoc[],\n): string {\n const cacheDir = getCacheDir(name, version)\n mkdirSync(cacheDir, { recursive: true, mode: 0o700 })\n\n for (const doc of docs) {\n const filePath = join(cacheDir, doc.path)\n mkdirSync(join(filePath, '..'), { recursive: true, mode: 0o700 })\n writeFileSync(filePath, sanitizeMarkdown(doc.content), { mode: 0o600 })\n }\n\n return cacheDir\n}\n\n/**\n * Write docs to repo-level cache (~/.skilld/repos/<owner>/<repo>/)\n */\nexport function writeToRepoCache(\n owner: string,\n repo: string,\n docs: CachedDoc[],\n): string {\n const repoDir = getRepoCacheDir(owner, repo)\n mkdirSync(repoDir, { recursive: true, mode: 0o700 })\n\n for (const doc of docs) {\n const filePath = join(repoDir, doc.path)\n mkdirSync(join(filePath, '..'), { recursive: true, mode: 0o700 })\n writeFileSync(filePath, sanitizeMarkdown(doc.content), { mode: 0o600 })\n }\n\n return repoDir\n}\n\n/**\n * Create symlink from .skilld dir to a repo-level cached subdirectory.\n * .claude/skills/<skill>/.skilld/<subdir> -> ~/.skilld/repos/<owner>/<repo>/<subdir>\n */\nexport function linkRepoCachedDir(skillDir: string, owner: string, repo: string, subdir: string): void {\n const repoDir = getRepoCacheDir(owner, repo)\n const referencesDir = join(skillDir, '.skilld')\n const linkPath = join(referencesDir, subdir)\n const cachedPath = join(repoDir, subdir)\n\n mkdirSync(referencesDir, { recursive: true })\n\n if (existsSync(cachedPath)) {\n safeSymlink(cachedPath, linkPath)\n }\n}\n\n/**\n * Create symlink from .skilld dir to a cached subdirectory.\n * Unified handler for docs, issues, discussions, sections, releases.\n *\n * Structure:\n * .claude/skills/<skill>/.skilld/<subdir> -> ~/.skilld/references/<pkg>@<version>/<subdir>\n *\n * The .skilld/ dirs are gitignored. After clone, `skilld install` recreates from lockfile.\n */\nexport function linkCachedDir(skillDir: string, name: string, version: string, subdir: string): void {\n const cacheDir = getCacheDir(name, version)\n const referencesDir = join(skillDir, '.skilld')\n const linkPath = join(referencesDir, subdir)\n const cachedPath = join(cacheDir, subdir)\n\n mkdirSync(referencesDir, { recursive: true })\n\n if (existsSync(cachedPath)) {\n safeSymlink(cachedPath, linkPath)\n }\n}\n\n/**\n * Resolve the package directory: node_modules first, then cached dist fallback.\n * Returns the path if found, null otherwise.\n */\nexport { resolvePkgDir } from '../core/prepare.ts'\nexport { getShippedSkills, linkShippedSkill } from '../core/prepare.ts'\nexport type { ShippedSkill } from '../core/prepare.ts'\n\n/**\n * Create symlink from .skilld dir to package directory\n *\n * Structure:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> OR ~/.skilld/references/<pkg>@<version>/pkg\n *\n * This gives access to package.json, README.md, dist/, and any shipped docs/\n */\nexport function linkPkg(skillDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const referencesDir = join(skillDir, '.skilld')\n mkdirSync(referencesDir, { recursive: true })\n\n const pkgLinkPath = join(referencesDir, 'pkg')\n try {\n lstatSync(pkgLinkPath)\n unlinkSync(pkgLinkPath)\n }\n catch {}\n symlinkSync(pkgPath, pkgLinkPath, 'junction')\n}\n\n/**\n * Create named symlink from .skilld dir to package directory.\n * Short name = last segment of package name (e.g., @vue/reactivity → pkg-reactivity)\n *\n * Structure:\n * .claude/skills/<skill>/.skilld/pkg-<short> -> node_modules/<pkg>\n */\nexport function linkPkgNamed(skillDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const shortName = name.split('/').pop()!.toLowerCase()\n const referencesDir = join(skillDir, '.skilld')\n mkdirSync(referencesDir, { recursive: true })\n\n const linkPath = join(referencesDir, `pkg-${shortName}`)\n try {\n lstatSync(linkPath)\n unlinkSync(linkPath)\n }\n catch {}\n symlinkSync(pkgPath, linkPath, 'junction')\n}\n\n/**\n * Get key files from a package directory for display\n * Returns entry points + docs files\n */\nexport function getPkgKeyFiles(name: string, cwd: string, version?: string): string[] {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return []\n\n const files: string[] = []\n const pkgJsonPath = join(pkgPath, 'package.json')\n\n const pkgJsonResult = readPackageJsonSafe(pkgJsonPath)\n if (pkgJsonResult) {\n const pkg = pkgJsonResult.parsed as Record<string, any>\n\n // Entry points\n if (pkg.main)\n files.push(basename(pkg.main))\n if (pkg.module && pkg.module !== pkg.main)\n files.push(basename(pkg.module))\n\n // Type definitions (relative path preserved for LLM tool hints)\n const typesPath = pkg.types || pkg.typings\n if (typesPath && existsSync(join(pkgPath, typesPath)))\n files.push(typesPath)\n }\n\n // Check for common doc files (case-insensitive readme match)\n const entries = readdirSync(pkgPath).filter(f =>\n /^readme\\.md$/i.test(f) || /^changelog\\.md$/i.test(f),\n )\n files.push(...entries)\n\n return [...new Set(files)]\n}\n\n/**\n * Write LLM-generated section outputs to global cache for cross-project reuse\n *\n * Structure:\n * ~/.skilld/references/<pkg>@<version>/sections/_BEST_PRACTICES.md\n */\nexport function writeSections(name: string, version: string, sections: Array<{ file: string, content: string }>): void {\n const cacheDir = getCacheDir(name, version)\n const sectionsDir = join(cacheDir, 'sections')\n mkdirSync(sectionsDir, { recursive: true, mode: 0o700 })\n for (const { file, content } of sections) {\n writeFileSync(join(sectionsDir, file), content, { mode: 0o600 })\n }\n}\n\n/**\n * Read a cached section from the global references dir\n */\nexport function readCachedSection(name: string, version: string, file: string): string | null {\n const path = join(getCacheDir(name, version), 'sections', file)\n if (!existsSync(path))\n return null\n return readFileSync(path, 'utf-8')\n}\n\nexport function hasShippedDocs(name: string, cwd: string, version?: string): boolean {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return false\n\n const docsCandidates = ['docs', 'documentation', 'doc']\n for (const candidate of docsCandidates) {\n const docsPath = join(pkgPath, candidate)\n if (existsSync(docsPath))\n return true\n }\n return false\n}\n\n/**\n * List all cached packages\n */\nexport function listCached(): CachedPackage[] {\n if (!existsSync(REFERENCES_DIR))\n return []\n\n return readdirSync(REFERENCES_DIR)\n .filter(name => name.includes('@'))\n .map((dir) => {\n const atIdx = dir.lastIndexOf('@')\n return { name: dir.slice(0, atIdx), version: dir.slice(atIdx + 1), dir: join(REFERENCES_DIR, dir) }\n })\n}\n\n/**\n * Read cached docs for a package\n */\nexport function readCachedDocs(name: string, version: string): CachedDoc[] {\n const cacheDir = getCacheDir(name, version)\n if (!existsSync(cacheDir))\n return []\n\n const docs: CachedDoc[] = []\n\n function walk(dir: string, prefix = '') {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const entryPath = join(dir, entry.name)\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name\n\n if (entry.isDirectory()) {\n walk(entryPath, relativePath)\n }\n else if (entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) {\n docs.push({\n path: relativePath,\n content: readFileSync(entryPath, 'utf-8'),\n })\n }\n }\n }\n\n walk(cacheDir)\n return docs\n}\n\n/**\n * Clear cache for a specific package\n */\nexport function clearCache(name: string, version: string): boolean {\n const cacheDir = getCacheDir(name, version)\n if (!existsSync(cacheDir))\n return false\n\n rmSync(cacheDir, { recursive: true })\n return true\n}\n\n/**\n * Clear all cache\n */\nexport function clearAllCache(): number {\n const packages = listCached()\n for (const pkg of packages) {\n clearCache(pkg.name, pkg.version)\n }\n // Also clear repo-level cache\n if (existsSync(REPOS_DIR))\n rmSync(REPOS_DIR, { recursive: true })\n return packages.length\n}\n\n/**\n * List files in .skilld directory (pkg + docs) as relative paths for prompt context\n * Returns paths like ./.skilld/pkg/README.md, ./.skilld/docs/api.md\n */\nexport function listReferenceFiles(skillDir: string, maxDepth = 3): string[] {\n const referencesDir = join(skillDir, '.skilld')\n if (!existsSync(referencesDir))\n return []\n\n const files: string[] = []\n\n function walk(dir: string, depth: number) {\n if (depth > maxDepth)\n return\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n try {\n const stat = statSync(full)\n if (stat.isDirectory()) {\n walk(full, depth + 1)\n continue\n }\n }\n catch { continue }\n }\n if (entry.name.endsWith('.md')) {\n files.push(full)\n }\n }\n }\n catch {\n // Broken symlink or permission error\n }\n }\n\n walk(referencesDir, 0)\n return files\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cache.mjs","names":["STATIC_REGEX_1"],"sources":["../../src/core/config.ts","../../src/cache/internal/classify.ts","../../src/cache/internal/storage.ts","../../src/cache/internal/references.ts","../../src/cache/reference-cache.ts"],"sourcesContent":["import type { OptimizeModel } from '../agent/index.ts'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { CACHE_DIR, CONFIG_PATH } from './paths.ts'\nimport { yamlEscape, yamlParseKV, yamlUnescape } from './yaml.ts'\n\nconst STATIC_REGEX_1 = /^ {2}(\\w+):\\s*(.+)/\n\nexport interface FeaturesConfig {\n search: boolean\n issues: boolean\n discussions: boolean\n releases: boolean\n}\n\nexport const defaultFeatures: FeaturesConfig = {\n search: true,\n issues: true,\n discussions: true,\n releases: true,\n}\n\n/**\n * Resolve the active feature set: defaults overlaid with user config, then\n * caller-supplied overrides. Single seam so feature gating doesn't drift.\n */\nexport function getActiveFeatures(overrides?: Partial<FeaturesConfig>): FeaturesConfig {\n const fromConfig = readConfig().features\n const merged: FeaturesConfig = { ...defaultFeatures, ...(fromConfig ?? {}) }\n return overrides ? { ...merged, ...overrides } : merged\n}\n\nexport interface SkilldConfig {\n model?: OptimizeModel\n agent?: string\n features?: FeaturesConfig\n projects?: string[]\n skipLlm?: boolean\n}\n\nlet configCache: SkilldConfig | undefined\n\nexport function hasConfig(): boolean {\n return existsSync(CONFIG_PATH)\n}\n\n/** Whether the first-run wizard has been completed (not just agent selection) */\nexport function hasCompletedWizard(): boolean {\n if (!existsSync(CONFIG_PATH))\n return false\n const config = readConfig()\n return config.features !== undefined || config.model !== undefined || config.skipLlm !== undefined\n}\n\nexport function readConfig(): SkilldConfig {\n if (configCache) {\n return {\n ...configCache,\n features: configCache.features ? { ...configCache.features } : undefined,\n projects: configCache.projects ? [...configCache.projects] : undefined,\n }\n }\n if (!existsSync(CONFIG_PATH))\n return {}\n\n const content = readFileSync(CONFIG_PATH, 'utf-8')\n const config: SkilldConfig = {}\n let inBlock: 'projects' | 'features' | null = null\n const projects: string[] = []\n const features: Partial<FeaturesConfig> = {}\n\n for (const line of content.split('\\n')) {\n if (line.startsWith('projects:')) {\n inBlock = 'projects'\n continue\n }\n if (line.startsWith('features:')) {\n inBlock = 'features'\n continue\n }\n if (inBlock === 'projects') {\n if (line.startsWith(' - ')) {\n projects.push(yamlUnescape(line.slice(4)))\n continue\n }\n inBlock = null\n }\n if (inBlock === 'features') {\n const m = line.match(STATIC_REGEX_1)\n if (m) {\n const key = m[1] as keyof FeaturesConfig\n if (key in defaultFeatures)\n features[key] = m[2] === 'true'\n continue\n }\n inBlock = null\n }\n const kv = yamlParseKV(line)\n if (!kv)\n continue\n const [key, value] = kv\n if (key === 'model' && value)\n config.model = value as OptimizeModel\n if (key === 'agent' && value)\n config.agent = value\n if (key === 'skipLlm')\n config.skipLlm = value === 'true'\n }\n\n if (projects.length > 0)\n config.projects = projects\n if (Object.keys(features).length > 0)\n config.features = { ...defaultFeatures, ...features }\n configCache = config\n return config\n}\n\nexport function writeConfig(config: SkilldConfig): void {\n mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 })\n\n let yaml = ''\n if (config.model)\n yaml += `model: ${config.model}\\n`\n if (config.agent)\n yaml += `agent: ${config.agent}\\n`\n if (config.skipLlm)\n yaml += `skipLlm: true\\n`\n if (config.features) {\n yaml += 'features:\\n'\n for (const [k, v] of Object.entries(config.features)) {\n yaml += ` ${k}: ${v}\\n`\n }\n }\n if (config.projects?.length) {\n yaml += 'projects:\\n'\n for (const p of config.projects) {\n yaml += ` - ${yamlEscape(p)}\\n`\n }\n }\n\n writeFileSync(CONFIG_PATH, yaml, { mode: 0o600 })\n configCache = undefined\n}\n\nexport function updateConfig(updates: Partial<SkilldConfig>): void {\n const config = readConfig()\n writeConfig({ ...config, ...updates })\n}\n\nexport function registerProject(projectPath: string): void {\n const config = readConfig()\n const projects = new Set(config.projects || [])\n projects.add(projectPath)\n writeConfig({ ...config, projects: [...projects] })\n}\n\nexport function unregisterProject(projectPath: string): void {\n const config = readConfig()\n const projects = (config.projects || []).filter(p => p !== projectPath)\n writeConfig({ ...config, projects })\n}\n\nexport function getRegisteredProjects(): string[] {\n return readConfig().projects || []\n}\n","const STATIC_REGEX_1 = /^issues\\/issue-(\\d+)\\.md$/\nconst STATIC_REGEX_2 = /^discussions\\/discussion-(\\d+)\\.md$/\n\n/**\n * Classify a cached doc path into the right metadata type.\n * Pure utility — no I/O.\n */\nexport function classifyCachedDoc(path: string): { type: string, number?: number } {\n const issueMatch = path.match(STATIC_REGEX_1)\n if (issueMatch)\n return { type: 'issue', number: Number(issueMatch[1]) }\n const discussionMatch = path.match(STATIC_REGEX_2)\n if (discussionMatch)\n return { type: 'discussion', number: Number(discussionMatch[1]) }\n if (path.startsWith('releases/'))\n return { type: 'release' }\n return { type: 'doc' }\n}\n","/**\n * Cache storage operations\n */\n\nimport type { CachedDoc, CachedPackage } from '../types.ts'\nimport { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'pathe'\nimport { getRepoCacheDir, REFERENCES_DIR, REPOS_DIR, skillInternalDir } from '../../core/paths.ts'\nimport { resolvePkgDir } from '../../core/prepare.ts'\nimport { sanitizeMarkdown } from '../../core/sanitize.ts'\nimport { getCacheDir } from './version.ts'\n\n/** Safely create a symlink, validating target is under REFERENCES_DIR or REPOS_DIR */\nfunction safeSymlink(target: string, linkPath: string): void {\n const resolved = resolve(target)\n if (!resolved.startsWith(REFERENCES_DIR) && !resolved.startsWith(REPOS_DIR))\n throw new Error(`Symlink target outside allowed dirs: ${resolved}`)\n // Remove pre-existing symlink (check with lstat to detect symlinks)\n try {\n const stat = lstatSync(linkPath)\n if (stat.isSymbolicLink() || stat.isFile())\n unlinkSync(linkPath)\n }\n catch {}\n symlinkSync(target, linkPath, 'junction')\n}\n\n/**\n * Check if package is cached at given version\n * @internal\n */\nexport function isCached(name: string, version: string): boolean {\n return existsSync(getCacheDir(name, version))\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nexport function isReadmeOnlyCache(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\nexport function inferDocsTypeFromCache(cacheDir: string, source?: string): 'llms.txt' | 'readme' | 'docs' {\n if (source?.includes('llms.txt') || existsSync(join(cacheDir, 'docs', 'llms.txt')))\n return 'llms.txt'\n return isReadmeOnlyCache(cacheDir) ? 'readme' : 'docs'\n}\n\n/**\n * Ensure cache directories exist\n */\nexport function ensureCacheDir(): void {\n mkdirSync(REFERENCES_DIR, { recursive: true, mode: 0o700 })\n mkdirSync(REPOS_DIR, { recursive: true, mode: 0o700 })\n}\n\n/**\n * Write docs to cache\n * @internal\n */\nexport function writeToCache(\n name: string,\n version: string,\n docs: CachedDoc[],\n): string {\n const cacheDir = getCacheDir(name, version)\n mkdirSync(cacheDir, { recursive: true, mode: 0o700 })\n\n for (const doc of docs) {\n const filePath = join(cacheDir, doc.path)\n mkdirSync(join(filePath, '..'), { recursive: true, mode: 0o700 })\n writeFileSync(filePath, sanitizeMarkdown(doc.content), { mode: 0o600 })\n }\n\n return cacheDir\n}\n\n/**\n * Write docs to repo-level cache (~/.skilld/repos/<owner>/<repo>/)\n */\nexport function writeToRepoCache(\n owner: string,\n repo: string,\n docs: CachedDoc[],\n): string {\n const repoDir = getRepoCacheDir(owner, repo)\n mkdirSync(repoDir, { recursive: true, mode: 0o700 })\n\n for (const doc of docs) {\n const filePath = join(repoDir, doc.path)\n mkdirSync(join(filePath, '..'), { recursive: true, mode: 0o700 })\n writeFileSync(filePath, sanitizeMarkdown(doc.content), { mode: 0o600 })\n }\n\n return repoDir\n}\n\n/**\n * Create symlink from .skilld dir to a repo-level cached subdirectory.\n * .claude/skills/<skill>/.skilld/<subdir> -> ~/.skilld/repos/<owner>/<repo>/<subdir>\n */\nexport function linkRepoCachedDir(skillDir: string, owner: string, repo: string, subdir: string): void {\n const repoDir = getRepoCacheDir(owner, repo)\n const referencesDir = skillInternalDir(skillDir)\n const linkPath = join(referencesDir, subdir)\n const cachedPath = join(repoDir, subdir)\n\n mkdirSync(referencesDir, { recursive: true })\n\n if (existsSync(cachedPath)) {\n safeSymlink(cachedPath, linkPath)\n }\n}\n\n/**\n * Create symlink from .skilld dir to a cached subdirectory.\n * Unified handler for docs, issues, discussions, sections, releases.\n *\n * Structure:\n * .claude/skills/<skill>/.skilld/<subdir> -> ~/.skilld/references/<pkg>@<version>/<subdir>\n *\n * The .skilld/ dirs are gitignored. After clone, `skilld install` recreates from lockfile.\n */\nexport function linkCachedDir(skillDir: string, name: string, version: string, subdir: string): void {\n const cacheDir = getCacheDir(name, version)\n const referencesDir = skillInternalDir(skillDir)\n const linkPath = join(referencesDir, subdir)\n const cachedPath = join(cacheDir, subdir)\n\n mkdirSync(referencesDir, { recursive: true })\n\n if (existsSync(cachedPath)) {\n safeSymlink(cachedPath, linkPath)\n }\n}\n\n/**\n * Create symlink from .skilld dir to package directory\n *\n * Structure:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> OR ~/.skilld/references/<pkg>@<version>/pkg\n *\n * This gives access to package.json, README.md, dist/, and any shipped docs/\n */\nexport function linkPkg(skillDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const referencesDir = skillInternalDir(skillDir)\n mkdirSync(referencesDir, { recursive: true })\n\n const pkgLinkPath = join(referencesDir, 'pkg')\n try {\n lstatSync(pkgLinkPath)\n unlinkSync(pkgLinkPath)\n }\n catch {}\n symlinkSync(pkgPath, pkgLinkPath, 'junction')\n}\n\n/**\n * Create named symlink from .skilld dir to package directory.\n * Short name = last segment of package name (e.g., @vue/reactivity → pkg-reactivity)\n *\n * Structure:\n * .claude/skills/<skill>/.skilld/pkg-<short> -> node_modules/<pkg>\n */\nexport function linkPkgNamed(skillDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const shortName = name.split('/').pop()!.toLowerCase()\n const referencesDir = skillInternalDir(skillDir)\n mkdirSync(referencesDir, { recursive: true })\n\n const linkPath = join(referencesDir, `pkg-${shortName}`)\n try {\n lstatSync(linkPath)\n unlinkSync(linkPath)\n }\n catch {}\n symlinkSync(pkgPath, linkPath, 'junction')\n}\n\n/**\n * Write LLM-generated section outputs to global cache for cross-project reuse\n *\n * Structure:\n * ~/.skilld/references/<pkg>@<version>/sections/_BEST_PRACTICES.md\n */\nexport function writeSections(name: string, version: string, sections: Array<{ file: string, content: string }>): void {\n const cacheDir = getCacheDir(name, version)\n const sectionsDir = join(cacheDir, 'sections')\n mkdirSync(sectionsDir, { recursive: true, mode: 0o700 })\n for (const { file, content } of sections) {\n writeFileSync(join(sectionsDir, file), content, { mode: 0o600 })\n }\n}\n\n/**\n * Read a cached section from the global references dir\n */\nexport function readCachedSection(name: string, version: string, file: string): string | null {\n const path = join(getCacheDir(name, version), 'sections', file)\n if (!existsSync(path))\n return null\n return readFileSync(path, 'utf-8')\n}\n\n/**\n * List all cached packages\n */\nexport function listCached(): CachedPackage[] {\n if (!existsSync(REFERENCES_DIR))\n return []\n\n return readdirSync(REFERENCES_DIR)\n .filter(name => name.includes('@'))\n .map((dir) => {\n const atIdx = dir.lastIndexOf('@')\n return { name: dir.slice(0, atIdx), version: dir.slice(atIdx + 1), dir: join(REFERENCES_DIR, dir) }\n })\n}\n\n/**\n * Read cached docs for a package\n */\nexport function readCachedDocs(name: string, version: string): CachedDoc[] {\n const cacheDir = getCacheDir(name, version)\n if (!existsSync(cacheDir))\n return []\n\n const docs: CachedDoc[] = []\n\n function walk(dir: string, prefix = '') {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const entryPath = join(dir, entry.name)\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name\n\n if (entry.isDirectory()) {\n walk(entryPath, relativePath)\n }\n else if (entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) {\n docs.push({\n path: relativePath,\n content: readFileSync(entryPath, 'utf-8'),\n })\n }\n }\n }\n\n walk(cacheDir)\n return docs\n}\n\n/**\n * Clear cache for a specific package\n */\nexport function clearCache(name: string, version: string): boolean {\n const cacheDir = getCacheDir(name, version)\n if (!existsSync(cacheDir))\n return false\n\n rmSync(cacheDir, { recursive: true })\n return true\n}\n\n/**\n * List files in .skilld directory (pkg + docs) as relative paths for prompt context\n * Returns paths like ./.skilld/pkg/README.md, ./.skilld/docs/api.md\n */\nexport function listReferenceFiles(skillDir: string, maxDepth = 3): string[] {\n const referencesDir = skillInternalDir(skillDir)\n if (!existsSync(referencesDir))\n return []\n\n const files: string[] = []\n\n function walk(dir: string, depth: number) {\n if (depth > maxDepth)\n return\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory() || entry.isSymbolicLink()) {\n try {\n const stat = statSync(full)\n if (stat.isDirectory()) {\n walk(full, depth + 1)\n continue\n }\n }\n catch { continue }\n }\n if (entry.name.endsWith('.md')) {\n files.push(full)\n }\n }\n }\n catch {\n // Broken symlink or permission error\n }\n }\n\n walk(referencesDir, 0)\n return files\n}\n","/**\n * Higher-level reference-cache operations: composition over the cache\n * primitives in `src/cache/index.ts`.\n *\n * Owns:\n * - The on-disk shape of `~/.skilld/references/<pkg>@<version>/`\n * - `.skilld/` symlinks inside agent skill dirs (linkAllReferences)\n * - Loading cached docs back as a `ResolvedContent`-shaped result\n * - Force-clearing and ejecting (portable copy) caches\n *\n * Callers (sync, sync-parallel, sync-git, install, author) should use these\n * helpers instead of touching cache primitives directly.\n */\n\nimport type { FeaturesConfig } from '../../core/config.ts'\nimport type { IndexDoc } from '../../sources/content-resolver.ts'\nimport type { CachedReferencesResult, LoadCachedReferencesOptions } from '../types.ts'\nimport { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, realpathSync, rmSync } from 'node:fs'\nimport { dirname, join } from 'pathe'\nimport { defaultFeatures, readConfig } from '../../core/config.ts'\nimport { getPackageDbPath, getRepoCacheDir, skillInternalDir } from '../../core/paths.ts'\nimport { hasShippedDocs } from '../../core/prepare.ts'\nimport { classifyCachedDoc } from './classify.ts'\nimport {\n clearCache,\n linkCachedDir,\n linkPkg,\n linkPkgNamed,\n linkRepoCachedDir,\n readCachedDocs,\n} from './storage.ts'\nimport { getCacheDir } from './version.ts'\n\n/**\n * Resolve every symlink under `<skillDir>/.skilld/` to its real path, plus\n * the parent dirs CLI sandboxes need (e.g. Gemini). What an LLM CLI passes to\n * `--add-dir` to make references readable.\n */\nexport function getSkillReferenceDirs(skillDir: string): string[] {\n const refsDir = skillInternalDir(skillDir)\n if (!existsSync(refsDir))\n return []\n const resolved = readdirSync(refsDir)\n .map(entry => join(refsDir, entry))\n .filter(p => lstatSync(p).isSymbolicLink() && existsSync(p))\n .map(p => realpathSync(p))\n\n const parents = new Set<string>()\n for (const p of resolved) {\n const parent = dirname(p)\n if (!resolved.includes(parent))\n parents.add(parent)\n }\n\n return [...resolved, ...parents]\n}\n\n/**\n * Remove the transient `<skillDir>/.skilld/` symlink dir. Used after eject to\n * clean up references that have been copied as real files.\n */\nexport function clearSkillInternalDir(skillDir: string): void {\n const refsDir = skillInternalDir(skillDir)\n if (existsSync(refsDir))\n rmSync(refsDir, { recursive: true, force: true })\n}\n\n/** Clear cache + db for --force flag */\nexport function forceClearCache(packageName: string, version: string, repoInfo?: { owner: string, repo: string }): void {\n clearCache(packageName, version)\n const forcedDbPath = getPackageDbPath(packageName, version)\n if (existsSync(forcedDbPath))\n rmSync(forcedDbPath, { recursive: true, force: true })\n // Also clear repo-level cache when force is used\n if (repoInfo) {\n const repoDir = getRepoCacheDir(repoInfo.owner, repoInfo.repo)\n if (existsSync(repoDir))\n rmSync(repoDir, { recursive: true, force: true })\n }\n}\n\n/** Link all reference symlinks (pkg, docs, issues, discussions, releases) */\nexport function linkAllReferences(skillDir: string, packageName: string, cwd: string, version: string, docsType: string, extraPackages?: Array<{ name: string, version?: string }>, features?: FeaturesConfig, repoInfo?: { owner: string, repo: string }): void {\n const f = features ?? readConfig().features ?? defaultFeatures\n try {\n linkPkg(skillDir, packageName, cwd, version)\n linkPkgNamed(skillDir, packageName, cwd, version)\n if (!hasShippedDocs(packageName, cwd, version) && docsType !== 'readme') {\n linkCachedDir(skillDir, packageName, version, 'docs')\n }\n // Issues/discussions/releases: use repo cache when available, else package cache\n if (f.issues) {\n if (repoInfo)\n linkRepoCachedDir(skillDir, repoInfo.owner, repoInfo.repo, 'issues')\n else\n linkCachedDir(skillDir, packageName, version, 'issues')\n }\n if (f.discussions) {\n if (repoInfo)\n linkRepoCachedDir(skillDir, repoInfo.owner, repoInfo.repo, 'discussions')\n else\n linkCachedDir(skillDir, packageName, version, 'discussions')\n }\n if (f.releases) {\n if (repoInfo)\n linkRepoCachedDir(skillDir, repoInfo.owner, repoInfo.repo, 'releases')\n else\n linkCachedDir(skillDir, packageName, version, 'releases')\n }\n linkCachedDir(skillDir, packageName, version, 'sections')\n // Create named symlinks for additional packages in multi-package skills\n if (extraPackages) {\n for (const pkg of extraPackages) {\n if (pkg.name !== packageName)\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n }\n }\n }\n catch {\n // Symlink may fail on some systems\n }\n}\n\n/** Detect docs type from cached directory contents */\nexport function detectDocsType(packageName: string, version: string, repoUrl?: string, llmsUrl?: string): { docsType: 'docs' | 'llms.txt' | 'readme', docSource?: string } {\n const cacheDir = getCacheDir(packageName, version)\n if (existsSync(join(cacheDir, 'docs', 'index.md')) || existsSync(join(cacheDir, 'docs', 'guide'))) {\n return {\n docsType: 'docs',\n docSource: repoUrl ? `${repoUrl}/tree/v${version}/docs` : 'git',\n }\n }\n if (existsSync(join(cacheDir, 'llms.txt'))) {\n return {\n docsType: 'llms.txt',\n docSource: llmsUrl || 'llms.txt',\n }\n }\n if (existsSync(join(cacheDir, 'docs', 'README.md'))) {\n return { docsType: 'readme' }\n }\n return { docsType: 'readme' }\n}\n\n/** Eject (portable copy) of cached references into a skill dir */\nexport function ejectReferences(skillDir: string, packageName: string, cwd: string, version: string, docsType: string, features?: FeaturesConfig, repoInfo?: { owner: string, repo: string }): void {\n const f = features ?? readConfig().features ?? defaultFeatures\n const cacheDir = getCacheDir(packageName, version)\n const refsDir = join(skillDir, 'references')\n // Repo-level data source (falls back to package cache)\n const repoDir = repoInfo ? getRepoCacheDir(repoInfo.owner, repoInfo.repo) : cacheDir\n\n // Copy cached docs (skip pkg — eject is for portable sharing, pkg references node_modules)\n if (!hasShippedDocs(packageName, cwd, version) && docsType !== 'readme')\n copyCachedSubdir(cacheDir, refsDir, 'docs')\n\n if (f.issues)\n copyCachedSubdir(repoDir, refsDir, 'issues')\n if (f.discussions)\n copyCachedSubdir(repoDir, refsDir, 'discussions')\n if (f.releases)\n copyCachedSubdir(repoDir, refsDir, 'releases')\n}\n\n/** Recursively copy a cached subdirectory into the references dir */\nfunction copyCachedSubdir(cacheDir: string, refsDir: string, subdir: string): void {\n const srcDir = join(cacheDir, subdir)\n if (!existsSync(srcDir))\n return\n\n const destDir = join(refsDir, subdir)\n mkdirSync(destDir, { recursive: true })\n\n function walk(dir: string, rel: string) {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const srcPath = join(dir, entry.name)\n const destPath = join(destDir, rel ? `${rel}/${entry.name}` : entry.name)\n if (entry.isDirectory()) {\n mkdirSync(destPath, { recursive: true })\n walk(srcPath, rel ? `${rel}/${entry.name}` : entry.name)\n }\n else {\n copyFileSync(srcPath, destPath)\n }\n }\n }\n\n walk(srcDir, '')\n}\n\n/**\n * Load cached references for a package and produce the index/backfill data\n * needed to continue the sync pipeline without re-fetching.\n */\nexport function loadCachedReferences(opts: LoadCachedReferencesOptions): CachedReferencesResult {\n const { packageName, version, repoUrl, llmsUrl, readmeUrl, onProgress, generateDocsIndex } = opts\n onProgress('Loading cached docs')\n const detected = detectDocsType(packageName, version, repoUrl, llmsUrl)\n const docsType = detected.docsType\n const docSource = detected.docSource ?? readmeUrl ?? 'readme'\n const docsToIndex: IndexDoc[] = []\n\n // Load cached docs for indexing if db doesn't exist yet\n const dbPath = getPackageDbPath(packageName, version)\n if (!existsSync(dbPath)) {\n onProgress('Reading cached docs for indexing')\n const cached = readCachedDocs(packageName, version)\n for (const doc of cached) {\n docsToIndex.push({\n id: doc.path,\n content: doc.content,\n metadata: { package: packageName, source: doc.path, ...classifyCachedDoc(doc.path) },\n })\n }\n }\n\n // Backfill docs index for caches created before this feature\n let backfillIndex: { path: string, content: string } | undefined\n if (docsType !== 'readme' && !existsSync(join(getCacheDir(packageName, version), 'docs', '_INDEX.md'))) {\n onProgress('Generating docs index')\n const cached = readCachedDocs(packageName, version)\n const docFiles = cached.filter(d => d.path.startsWith('docs/') && d.path.endsWith('.md'))\n if (docFiles.length > 1) {\n const docsIndex = generateDocsIndex(cached)\n if (docsIndex)\n backfillIndex = { path: 'docs/_INDEX.md', content: docsIndex }\n }\n }\n\n return { docsToIndex, docSource, docsType, backfillIndex }\n}\n","/**\n * Per-package reference cache facade. Closes over `(packageName, version)` so\n * call sites stop threading those tuples through chained primitives.\n */\n\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { CachedDoc, CachedReferencesResult, LoadCachedReferencesOptions } from './types.ts'\nimport { getPkgKeyFiles, hasShippedDocs, resolvePkgDir } from '../core/prepare.ts'\nimport {\n clearSkillInternalDir,\n detectDocsType,\n ejectReferences,\n forceClearCache,\n linkAllReferences,\n loadCachedReferences,\n} from './internal/references.ts'\nimport {\n ensureCacheDir,\n inferDocsTypeFromCache,\n isCached,\n isReadmeOnlyCache,\n linkPkgNamed,\n readCachedDocs,\n readCachedSection,\n writeSections,\n writeToCache,\n} from './internal/storage.ts'\nimport { getCacheDir, getVersionKey } from './internal/version.ts'\n\nexport interface ReferenceCacheLinkOpts {\n extraPackages?: Array<{ name: string, version?: string }>\n features?: FeaturesConfig\n repoInfo?: { owner: string, repo: string }\n}\n\nexport interface ReferenceCacheEjectOpts {\n features?: FeaturesConfig\n repoInfo?: { owner: string, repo: string }\n}\n\nexport interface ReferenceCache {\n readonly packageName: string\n /** May be undefined when caller only knows the package name (e.g. merge against a lock without a recorded version). Cache-keyed methods/getters throw in that case; pkg/has/keyFiles fall back to node_modules. */\n readonly version: string | undefined\n /** Throws if accessed when version is undefined. */\n readonly versionKey: string\n /** Throws if accessed when version is undefined. */\n readonly dir: string\n ensure: () => void\n has: () => boolean\n isReadmeOnly: () => boolean\n inferDocsType: (source?: string) => 'llms.txt' | 'readme' | 'docs'\n write: (docs: CachedDoc[]) => void\n writeSections: (sections: Array<{ file: string, content: string }>) => void\n readSection: (file: string) => string | null\n readDocs: () => CachedDoc[]\n detectDocs: (\n repoUrl?: string,\n llmsUrl?: string,\n ) => { docsType: 'docs' | 'llms.txt' | 'readme', docSource?: string }\n load: (\n opts: Omit<LoadCachedReferencesOptions, 'packageName' | 'version'>,\n ) => CachedReferencesResult\n linkInto: (\n skillDir: string,\n cwd: string,\n docsType: string,\n opts?: ReferenceCacheLinkOpts,\n ) => void\n linkPkgNamed: (skillDir: string, cwd: string) => void\n eject: (\n skillDir: string,\n cwd: string,\n docsType: string,\n opts?: ReferenceCacheEjectOpts,\n ) => void\n clearForce: (repoInfo?: { owner: string, repo: string }) => void\n clearSkillInternal: (skillDir: string) => void\n pkgDir: (cwd: string) => string | null\n hasShipped: (cwd: string) => boolean\n keyFiles: (cwd: string) => string[]\n}\n\nexport function createReferenceCache(packageName: string, version?: string): ReferenceCache {\n const requireVersion = (op: string): string => {\n if (!version)\n throw new Error(`ReferenceCache.${op} requires a version (package: ${packageName})`)\n return version\n }\n return {\n packageName,\n version,\n get versionKey() { return getVersionKey(requireVersion('versionKey')) },\n get dir() { return getCacheDir(packageName, requireVersion('dir')) },\n ensure: () => ensureCacheDir(),\n has: () => !!version && isCached(packageName, version),\n isReadmeOnly: () => isReadmeOnlyCache(getCacheDir(packageName, requireVersion('isReadmeOnly'))),\n inferDocsType: source => inferDocsTypeFromCache(getCacheDir(packageName, requireVersion('inferDocsType')), source),\n write: docs => void writeToCache(packageName, requireVersion('write'), docs),\n writeSections: sections => writeSections(packageName, requireVersion('writeSections'), sections),\n readSection: file => readCachedSection(packageName, requireVersion('readSection'), file),\n readDocs: () => readCachedDocs(packageName, requireVersion('readDocs')),\n detectDocs: (repoUrl, llmsUrl) =>\n detectDocsType(packageName, requireVersion('detectDocs'), repoUrl, llmsUrl),\n load: opts =>\n loadCachedReferences({ ...opts, packageName, version: requireVersion('load') }),\n linkInto: (skillDir, cwd, docsType, opts) =>\n linkAllReferences(\n skillDir,\n packageName,\n cwd,\n requireVersion('linkInto'),\n docsType,\n opts?.extraPackages,\n opts?.features,\n opts?.repoInfo,\n ),\n linkPkgNamed: (skillDir, cwd) =>\n linkPkgNamed(skillDir, packageName, cwd, version),\n eject: (skillDir, cwd, docsType, opts) =>\n ejectReferences(\n skillDir,\n packageName,\n cwd,\n requireVersion('eject'),\n docsType,\n opts?.features,\n opts?.repoInfo,\n ),\n clearForce: repoInfo => forceClearCache(packageName, requireVersion('clearForce'), repoInfo),\n clearSkillInternal: skillDir => clearSkillInternalDir(skillDir),\n pkgDir: cwd => resolvePkgDir(packageName, cwd, version),\n hasShipped: cwd => hasShippedDocs(packageName, cwd, version),\n keyFiles: cwd => getPkgKeyFiles(packageName, cwd, version),\n }\n}\n"],"mappings":"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"}
@@ -1,10 +1,11 @@
1
- import { a as REFERENCES_DIR, i as CACHE_DIR, o as REPOS_DIR } from "./version.mjs";
1
+ import { c as REPOS_DIR, n as CACHE_DIR, s as REFERENCES_DIR } from "./paths.mjs";
2
2
  import "./cache.mjs";
3
3
  import { n as clearEmbeddingCache } from "./embedding-cache2.mjs";
4
- import { join } from "pathe";
5
4
  import { existsSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
5
+ import { styleText } from "node:util";
6
6
  import * as p from "@clack/prompts";
7
7
  import { defineCommand } from "citty";
8
+ import { join } from "pathe";
8
9
  const LLM_CACHE_DIR = join(CACHE_DIR, "llm-cache");
9
10
  const LLM_CACHE_MAX_AGE = 10080 * 60 * 1e3;
10
11
  function safeRemove(path) {
@@ -85,7 +86,7 @@ function fmtBytes(n) {
85
86
  return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`;
86
87
  }
87
88
  function cacheStatsCommand() {
88
- const dim = (s) => `\x1B[90m${s}\x1B[0m`;
89
+ const dim = (s) => styleText("gray", s);
89
90
  const refs = dirEntries(REFERENCES_DIR);
90
91
  const repos = dirEntries(REPOS_DIR);
91
92
  const llm = dirEntries(LLM_CACHE_DIR);
@@ -132,16 +133,16 @@ const cacheCommandDef = defineCommand({
132
133
  },
133
134
  async run({ args }) {
134
135
  if (args.stats) {
135
- p.intro(`\x1B[1m\x1B[35mskilld\x1B[0m cache stats`);
136
+ p.intro(`${styleText(["bold", "magenta"], "skilld")} cache stats`);
136
137
  cacheStatsCommand();
137
138
  return;
138
139
  }
139
140
  if (args.clean) {
140
- p.intro(`\x1B[1m\x1B[35mskilld\x1B[0m cache clean`);
141
+ p.intro(`${styleText(["bold", "magenta"], "skilld")} cache clean`);
141
142
  await cacheCleanCommand();
142
143
  return;
143
144
  }
144
- p.intro(`\x1B[1m\x1B[35mskilld\x1B[0m cache`);
145
+ p.intro(`${styleText(["bold", "magenta"], "skilld")} cache`);
145
146
  p.log.message("Usage:\n skilld cache --clean Remove expired cache entries\n skilld cache --stats Show cache disk usage");
146
147
  }
147
148
  });
@@ -1 +1 @@
1
- {"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["/**\n * Cache management commands\n */\n\nimport type { Dirent } from 'node:fs'\nimport { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { CACHE_DIR, REFERENCES_DIR, REPOS_DIR } from '../cache/index.ts'\nimport { clearEmbeddingCache } from '../retriv/embedding-cache.ts'\n\nconst LLM_CACHE_DIR = join(CACHE_DIR, 'llm-cache')\nconst LLM_CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000\n\nfunction safeRemove(path: string): number {\n try {\n const size = statSync(path).size\n rmSync(path)\n return size\n }\n catch {\n try {\n rmSync(path)\n }\n catch {}\n return 0\n }\n}\n\nexport async function cacheCleanCommand(): Promise<void> {\n let expiredLlm = 0\n let freedBytes = 0\n\n // Clean expired LLM cache entries\n if (existsSync(LLM_CACHE_DIR)) {\n const now = Date.now()\n for (const entry of readdirSync(LLM_CACHE_DIR)) {\n const path = join(LLM_CACHE_DIR, entry)\n try {\n const { timestamp } = JSON.parse(readFileSync(path, 'utf-8'))\n if (now - timestamp > LLM_CACHE_MAX_AGE) {\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n catch {\n // Corrupt cache entry — remove it\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n }\n\n // Clear embedding cache\n const embeddingDbPath = join(CACHE_DIR, 'embeddings.db')\n let embeddingCleared = false\n if (existsSync(embeddingDbPath)) {\n const size = statSync(embeddingDbPath).size\n clearEmbeddingCache()\n freedBytes += size\n embeddingCleared = true\n }\n\n const freedKB = Math.round(freedBytes / 1024)\n if (expiredLlm > 0 || embeddingCleared) {\n const parts: string[] = []\n if (expiredLlm > 0)\n parts.push(`${expiredLlm} expired enhancement cache entries`)\n if (embeddingCleared)\n parts.push('embedding cache')\n p.log.success(`Removed ${parts.join(' + ')} (${freedKB}KB freed)`)\n }\n else {\n p.log.info('Cache is clean — no expired entries')\n }\n}\n\nfunction dirEntries(dir: string): Dirent[] {\n if (!existsSync(dir))\n return []\n return readdirSync(dir, { withFileTypes: true, recursive: true })\n}\n\nfunction sumFileBytes(entries: Dirent[]): number {\n return entries\n .filter(e => e.isFile())\n .reduce((sum, e) => {\n try {\n return sum + statSync(join(e.parentPath, e.name)).size\n }\n catch { return sum }\n }, 0)\n}\n\nfunction fmtBytes(n: number): string {\n const units = ['B', 'KB', 'MB', 'GB'] as const\n let i = 0\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024\n i++\n }\n return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`\n}\n\nexport function cacheStatsCommand(): void {\n const dim = (s: string) => `\\x1B[90m${s}\\x1B[0m`\n\n const refs = dirEntries(REFERENCES_DIR)\n const repos = dirEntries(REPOS_DIR)\n const llm = dirEntries(LLM_CACHE_DIR)\n const embPath = join(CACHE_DIR, 'embeddings.db')\n const embSize = existsSync(embPath) ? statSync(embPath).size : 0\n\n // Count packages: top-level non-scoped dirs + dirs inside @scope/ dirs\n const packages = refs.filter(e =>\n e.isDirectory()\n && (e.parentPath === REFERENCES_DIR\n ? !e.name.startsWith('@')\n : e.parentPath.startsWith(REFERENCES_DIR)),\n ).length\n\n const llmFiles = llm.filter(e => e.isFile())\n const sizes = { refs: sumFileBytes(refs), repos: sumFileBytes(repos), llm: sumFileBytes(llmFiles), emb: embSize }\n const total = sizes.refs + sizes.repos + sizes.llm + sizes.emb\n\n const lines = [\n `References ${fmtBytes(sizes.refs)} ${dim(`${packages} packages`)}`,\n ...(sizes.repos > 0 ? [`Repos ${fmtBytes(sizes.repos)}`] : []),\n `LLM cache ${fmtBytes(sizes.llm)} ${dim(`${llmFiles.length} entries`)}`,\n ...(sizes.emb > 0 ? [`Embeddings ${fmtBytes(sizes.emb)}`] : []),\n '',\n `Total ${fmtBytes(total)} ${dim(CACHE_DIR)}`,\n ]\n p.log.message(lines.join('\\n'))\n}\n\nexport const cacheCommandDef = defineCommand({\n meta: { name: 'cache', description: 'Cache management', hidden: true },\n args: {\n clean: {\n type: 'boolean',\n alias: 'c',\n description: 'Remove expired enhancement cache entries',\n default: false,\n },\n stats: {\n type: 'boolean',\n alias: 's',\n description: 'Show cache disk usage',\n default: false,\n },\n },\n async run({ args }) {\n if (args.stats) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m cache stats`)\n cacheStatsCommand()\n return\n }\n if (args.clean) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m cache clean`)\n await cacheCleanCommand()\n return\n }\n // No flag: show usage\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m cache`)\n p.log.message('Usage:\\n skilld cache --clean Remove expired cache entries\\n skilld cache --stats Show cache disk usage')\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["/**\n * Cache management commands\n */\n\nimport type { Dirent } from 'node:fs'\nimport { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { CACHE_DIR, REFERENCES_DIR, REPOS_DIR } from '../cache/index.ts'\nimport { clearEmbeddingCache } from '../retriv/embedding-cache.ts'\n\nconst LLM_CACHE_DIR = join(CACHE_DIR, 'llm-cache')\nconst LLM_CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000\n\nfunction safeRemove(path: string): number {\n try {\n const size = statSync(path).size\n rmSync(path)\n return size\n }\n catch {\n try {\n rmSync(path)\n }\n catch {}\n return 0\n }\n}\n\nexport async function cacheCleanCommand(): Promise<void> {\n let expiredLlm = 0\n let freedBytes = 0\n\n // Clean expired LLM cache entries\n if (existsSync(LLM_CACHE_DIR)) {\n const now = Date.now()\n for (const entry of readdirSync(LLM_CACHE_DIR)) {\n const path = join(LLM_CACHE_DIR, entry)\n try {\n const { timestamp } = JSON.parse(readFileSync(path, 'utf-8'))\n if (now - timestamp > LLM_CACHE_MAX_AGE) {\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n catch {\n // Corrupt cache entry — remove it\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n }\n\n // Clear embedding cache\n const embeddingDbPath = join(CACHE_DIR, 'embeddings.db')\n let embeddingCleared = false\n if (existsSync(embeddingDbPath)) {\n const size = statSync(embeddingDbPath).size\n clearEmbeddingCache()\n freedBytes += size\n embeddingCleared = true\n }\n\n const freedKB = Math.round(freedBytes / 1024)\n if (expiredLlm > 0 || embeddingCleared) {\n const parts: string[] = []\n if (expiredLlm > 0)\n parts.push(`${expiredLlm} expired enhancement cache entries`)\n if (embeddingCleared)\n parts.push('embedding cache')\n p.log.success(`Removed ${parts.join(' + ')} (${freedKB}KB freed)`)\n }\n else {\n p.log.info('Cache is clean — no expired entries')\n }\n}\n\nfunction dirEntries(dir: string): Dirent[] {\n if (!existsSync(dir))\n return []\n return readdirSync(dir, { withFileTypes: true, recursive: true })\n}\n\nfunction sumFileBytes(entries: Dirent[]): number {\n return entries\n .filter(e => e.isFile())\n .reduce((sum, e) => {\n try {\n return sum + statSync(join(e.parentPath, e.name)).size\n }\n catch { return sum }\n }, 0)\n}\n\nfunction fmtBytes(n: number): string {\n const units = ['B', 'KB', 'MB', 'GB'] as const\n let i = 0\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024\n i++\n }\n return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`\n}\n\nexport function cacheStatsCommand(): void {\n const dim = (s: string) => styleText('gray', s)\n\n const refs = dirEntries(REFERENCES_DIR)\n const repos = dirEntries(REPOS_DIR)\n const llm = dirEntries(LLM_CACHE_DIR)\n const embPath = join(CACHE_DIR, 'embeddings.db')\n const embSize = existsSync(embPath) ? statSync(embPath).size : 0\n\n // Count packages: top-level non-scoped dirs + dirs inside @scope/ dirs\n const packages = refs.filter(e =>\n e.isDirectory()\n && (e.parentPath === REFERENCES_DIR\n ? !e.name.startsWith('@')\n : e.parentPath.startsWith(REFERENCES_DIR)),\n ).length\n\n const llmFiles = llm.filter(e => e.isFile())\n const sizes = { refs: sumFileBytes(refs), repos: sumFileBytes(repos), llm: sumFileBytes(llmFiles), emb: embSize }\n const total = sizes.refs + sizes.repos + sizes.llm + sizes.emb\n\n const lines = [\n `References ${fmtBytes(sizes.refs)} ${dim(`${packages} packages`)}`,\n ...(sizes.repos > 0 ? [`Repos ${fmtBytes(sizes.repos)}`] : []),\n `LLM cache ${fmtBytes(sizes.llm)} ${dim(`${llmFiles.length} entries`)}`,\n ...(sizes.emb > 0 ? [`Embeddings ${fmtBytes(sizes.emb)}`] : []),\n '',\n `Total ${fmtBytes(total)} ${dim(CACHE_DIR)}`,\n ]\n p.log.message(lines.join('\\n'))\n}\n\nexport const cacheCommandDef = defineCommand({\n meta: { name: 'cache', description: 'Cache management', hidden: true },\n args: {\n clean: {\n type: 'boolean',\n alias: 'c',\n description: 'Remove expired enhancement cache entries',\n default: false,\n },\n stats: {\n type: 'boolean',\n alias: 's',\n description: 'Show cache disk usage',\n default: false,\n },\n },\n async run({ args }) {\n if (args.stats) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache stats`)\n cacheStatsCommand()\n return\n }\n if (args.clean) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache clean`)\n await cacheCleanCommand()\n return\n }\n // No flag: show usage\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache`)\n p.log.message('Usage:\\n skilld cache --clean Remove expired cache entries\\n skilld cache --stats Show cache disk usage')\n },\n})\n"],"mappings":"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"}