skilld 1.7.3 → 1.7.4

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 (96) hide show
  1. package/dist/_chunks/agent.mjs +693 -599
  2. package/dist/_chunks/agent.mjs.map +1 -1
  3. package/dist/_chunks/assemble.mjs +3 -3
  4. package/dist/_chunks/author.mjs +51 -121
  5. package/dist/_chunks/author.mjs.map +1 -1
  6. package/dist/_chunks/cache.mjs +315 -9
  7. package/dist/_chunks/cache.mjs.map +1 -1
  8. package/dist/_chunks/cache2.mjs +2 -2
  9. package/dist/_chunks/cli-helpers.mjs +3 -3
  10. package/dist/_chunks/core.mjs +7 -4
  11. package/dist/_chunks/detect.mjs +1 -1
  12. package/dist/_chunks/embedding-cache2.mjs +2 -2
  13. package/dist/_chunks/index.d.mts +305 -112
  14. package/dist/_chunks/index.d.mts.map +1 -1
  15. package/dist/_chunks/index2.d.mts +267 -32
  16. package/dist/_chunks/index2.d.mts.map +1 -1
  17. package/dist/_chunks/index3.d.mts +32 -577
  18. package/dist/_chunks/index3.d.mts.map +1 -1
  19. package/dist/_chunks/index4.d.mts +553 -0
  20. package/dist/_chunks/index4.d.mts.map +1 -0
  21. package/dist/_chunks/install.mjs +48 -88
  22. package/dist/_chunks/install.mjs.map +1 -1
  23. package/dist/_chunks/list.mjs +1 -1
  24. package/dist/_chunks/lockfile.mjs +29 -6
  25. package/dist/_chunks/lockfile.mjs.map +1 -1
  26. package/dist/_chunks/monorepo.mjs +71 -0
  27. package/dist/_chunks/monorepo.mjs.map +1 -0
  28. package/dist/_chunks/{shared.mjs → package-registry.mjs} +2 -40
  29. package/dist/_chunks/package-registry.mjs.map +1 -0
  30. package/dist/_chunks/paths.mjs +49 -0
  31. package/dist/_chunks/paths.mjs.map +1 -0
  32. package/dist/_chunks/pool2.mjs +1 -1
  33. package/dist/_chunks/prepare.mjs +1 -1
  34. package/dist/_chunks/prepare2.mjs +5 -5
  35. package/dist/_chunks/prepare2.mjs.map +1 -1
  36. package/dist/_chunks/prompts.mjs +366 -18
  37. package/dist/_chunks/prompts.mjs.map +1 -1
  38. package/dist/_chunks/search-helpers.mjs +5 -6
  39. package/dist/_chunks/search-helpers.mjs.map +1 -1
  40. package/dist/_chunks/search-interactive.mjs +1 -1
  41. package/dist/_chunks/search.mjs +1 -2
  42. package/dist/_chunks/search.mjs.map +1 -1
  43. package/dist/_chunks/semver.mjs +13 -0
  44. package/dist/_chunks/semver.mjs.map +1 -0
  45. package/dist/_chunks/skill-installer.mjs +2 -0
  46. package/dist/_chunks/skill-installer2.mjs +155 -0
  47. package/dist/_chunks/skill-installer2.mjs.map +1 -0
  48. package/dist/_chunks/skills.mjs +10 -9
  49. package/dist/_chunks/skills.mjs.map +1 -1
  50. package/dist/_chunks/sources.mjs +549 -372
  51. package/dist/_chunks/sources.mjs.map +1 -1
  52. package/dist/_chunks/sync-pipeline.mjs +952 -0
  53. package/dist/_chunks/sync-pipeline.mjs.map +1 -0
  54. package/dist/_chunks/sync-registry.mjs +19 -13
  55. package/dist/_chunks/sync-registry.mjs.map +1 -1
  56. package/dist/_chunks/sync.mjs +797 -886
  57. package/dist/_chunks/sync.mjs.map +1 -1
  58. package/dist/_chunks/sync2.mjs +4 -2
  59. package/dist/_chunks/types.d.mts +65 -77
  60. package/dist/_chunks/types.d.mts.map +1 -1
  61. package/dist/_chunks/types2.d.mts +88 -0
  62. package/dist/_chunks/types2.d.mts.map +1 -0
  63. package/dist/_chunks/uninstall.mjs +7 -8
  64. package/dist/_chunks/uninstall.mjs.map +1 -1
  65. package/dist/_chunks/upload.mjs +2 -2
  66. package/dist/_chunks/validate.mjs +1 -1
  67. package/dist/_chunks/version.mjs +3 -13
  68. package/dist/_chunks/version.mjs.map +1 -1
  69. package/dist/_chunks/wizard.mjs +2 -2
  70. package/dist/agent/index.d.mts +2 -346
  71. package/dist/agent/index.mjs +2 -3
  72. package/dist/cache/index.d.mts +2 -2
  73. package/dist/cache/index.mjs +4 -3
  74. package/dist/cli.mjs +12 -13
  75. package/dist/cli.mjs.map +1 -1
  76. package/dist/index.d.mts +5 -4
  77. package/dist/index.mjs +4 -3
  78. package/dist/prepare.mjs +2 -2
  79. package/dist/prepare.mjs.map +1 -1
  80. package/dist/retriv/index.d.mts +2 -2
  81. package/dist/retriv/worker.d.mts +1 -1
  82. package/dist/sources/index.d.mts +3 -2
  83. package/dist/sources/index.mjs +3 -3
  84. package/dist/types.d.mts +3 -3
  85. package/package.json +2 -2
  86. package/dist/_chunks/config.mjs +0 -122
  87. package/dist/_chunks/config.mjs.map +0 -1
  88. package/dist/_chunks/prefix.mjs +0 -108
  89. package/dist/_chunks/prefix.mjs.map +0 -1
  90. package/dist/_chunks/shared.mjs.map +0 -1
  91. package/dist/_chunks/skill.mjs +0 -329
  92. package/dist/_chunks/skill.mjs.map +0 -1
  93. package/dist/_chunks/sync-shared.mjs +0 -2
  94. package/dist/_chunks/sync-shared2.mjs +0 -1020
  95. package/dist/_chunks/sync-shared2.mjs.map +0 -1
  96. package/dist/agent/index.d.mts.map +0 -1
@@ -1,88 +1,76 @@
1
- interface ChunkEntity {
1
+ /**
2
+ * Doc resolver types
3
+ */
4
+ interface NpmPackageInfo {
2
5
  name: string;
3
- type: string;
4
- signature?: string;
5
- isPartial?: boolean;
6
+ version?: string;
7
+ description?: string;
8
+ homepage?: string;
9
+ repository?: string | {
10
+ type: string;
11
+ url: string;
12
+ directory?: string;
13
+ };
14
+ readme?: string;
15
+ dependencies?: Record<string, string>;
16
+ devDependencies?: Record<string, string>;
17
+ peerDependencies?: Record<string, string>;
6
18
  }
7
- interface Document {
8
- id: string;
9
- content: string;
10
- metadata?: Record<string, any>;
19
+ interface ResolvedPackage {
20
+ name: string;
21
+ version?: string;
22
+ /** ISO date string when this version was released */
23
+ releasedAt?: string;
24
+ description?: string;
25
+ /** Production dependencies with version specifiers */
26
+ dependencies?: Record<string, string>;
27
+ /** npm dist-tags with version and release date */
28
+ distTags?: Record<string, {
29
+ version: string;
30
+ releasedAt?: string;
31
+ }>;
32
+ docsUrl?: string;
33
+ llmsUrl?: string;
34
+ readmeUrl?: string;
35
+ repoUrl?: string;
36
+ /** Git docs folder - versioned docs from repo */
37
+ gitDocsUrl?: string;
38
+ /** Git tag/ref used for gitDocsUrl */
39
+ gitRef?: string;
40
+ /** True when gitRef is a branch fallback (no version tag found) */
41
+ gitDocsFallback?: boolean;
42
+ /** URL pattern to crawl for docs */
43
+ crawlUrl?: string;
11
44
  }
12
- interface ChunkingOptions {
13
- chunkSize?: number;
14
- chunkOverlap?: number;
45
+ interface LocalDependency {
46
+ name: string;
47
+ version: string;
15
48
  }
16
- type IndexPhase = 'chunking' | 'embedding' | 'storing';
17
- interface IndexProgress {
18
- phase: IndexPhase;
19
- current: number;
20
- total: number;
49
+ interface LlmsContent {
50
+ raw: string;
51
+ /** Markdown links extracted from llms.txt */
52
+ links: LlmsLink[];
21
53
  }
22
- interface IndexConfig {
23
- dbPath: string;
24
- model?: string;
25
- chunking?: ChunkingOptions;
26
- /** Progress callback forwarded from retriv */
27
- onProgress?: (progress: IndexProgress) => void;
54
+ interface LlmsLink {
55
+ title: string;
56
+ url: string;
28
57
  }
29
- interface SearchResult {
30
- id: string;
58
+ interface FetchedDoc {
59
+ url: string;
60
+ title: string;
31
61
  content: string;
32
- score: number;
33
- metadata: Record<string, any>;
34
- highlights: string[];
35
- /** Line range from chunk [start, end] */
36
- lineRange?: [number, number];
37
- entities?: ChunkEntity[];
38
- scope?: ChunkEntity[];
39
62
  }
40
- type FilterOperator = {
41
- $eq: string | number | boolean;
42
- } | {
43
- $ne: string | number | boolean;
44
- } | {
45
- $gt: number;
46
- } | {
47
- $gte: number;
48
- } | {
49
- $lt: number;
50
- } | {
51
- $lte: number;
52
- } | {
53
- $in: (string | number)[];
54
- } | {
55
- $prefix: string;
56
- } | {
57
- $exists: boolean;
58
- };
59
- type FilterValue = string | number | boolean | FilterOperator;
60
- type SearchFilter = Record<string, FilterValue>;
61
- interface SearchOptions {
62
- /** Max results */
63
- limit?: number;
64
- /** Filter by metadata fields */
65
- filter?: SearchFilter;
63
+ interface ResolveAttempt {
64
+ source: 'npm' | 'crates' | 'github-docs' | 'github-meta' | 'github-search' | 'llms.txt' | 'readme';
65
+ url?: string;
66
+ status: 'success' | 'not-found' | 'error';
67
+ message?: string;
66
68
  }
67
- interface SearchSnippet {
68
- /** Package name and version */
69
- package: string;
70
- /** Source file path */
71
- source: string;
72
- /** Start line number */
73
- lineStart: number;
74
- /** End line number */
75
- lineEnd: number;
76
- /** Snippet content (5 lines around best match) */
77
- content: string;
78
- /** Relevance score */
79
- score: number;
80
- /** Matched query terms, ordered by BM25 score */
81
- highlights: string[];
82
- /** Entities defined in this chunk */
83
- entities?: ChunkEntity[];
84
- /** Containing scope chain */
85
- scope?: ChunkEntity[];
69
+ interface ResolveResult {
70
+ package: ResolvedPackage | null;
71
+ attempts: ResolveAttempt[];
72
+ /** npm registry version, available even when doc resolution fails */
73
+ registryVersion?: string;
86
74
  }
87
- export { IndexProgress as a, SearchResult as c, IndexPhase as i, SearchSnippet as l, Document as n, SearchFilter as o, IndexConfig as r, SearchOptions as s, ChunkEntity as t };
75
+ export { NpmPackageInfo as a, ResolvedPackage as c, LocalDependency as i, LlmsContent as n, ResolveAttempt as o, LlmsLink as r, ResolveResult as s, FetchedDoc as t };
88
76
  //# sourceMappingURL=types.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.mts","names":[],"sources":["../../src/retriv/types.ts"],"mappings":"UAAiB,WAAA;EACf,IAAA;EACA,IAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,UAGe,QAAA;EACf,EAAA;EACA,OAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,eAAA;EACf,SAAA;EACA,YAAA;AAAA;AAAA,KAGU,UAAA;AAAA,UAEK,aAAA;EACf,KAAA,EAAO,UAAA;EACP,OAAA;EACA,KAAA;AAAA;AAAA,UAGe,WAAA;EACf,MAAA;EACA,KAAA;EACA,QAAA,GAAW,eAAA;EAXD;EAaV,UAAA,IAAc,QAAA,EAAU,aAAA;AAAA;AAAA,UAGT,YAAA;EACf,EAAA;EACA,OAAA;EACA,KAAA;EACA,QAAA,EAAU,MAAA;EACV,UAAA;EAlBA;EAoBA,SAAA;EACA,QAAA,GAAW,WAAA;EACX,KAAA,GAAQ,WAAA;AAAA;AAAA,KAGE,cAAA;EACJ,GAAA;AAAA;EACA,GAAA;AAAA;EACA,GAAA;AAAA;EACA,IAAA;AAAA;EACA,GAAA;AAAA;EACA,IAAA;AAAA;EACA,GAAA;AAAA;EACA,OAAA;AAAA;EACA,OAAA;AAAA;AAAA,KAEI,WAAA,+BAA0C,cAAA;AAAA,KAC1C,YAAA,GAAe,MAAA,SAAe,WAAA;AAAA,UAEzB,aAAA;EAzBf;EA2BA,KAAA;EAzBA;EA2BA,MAAA,GAAS,YAAA;AAAA;AAAA,UAGM,aAAA;EA1Bf;EA4BA,OAAA;EA3BW;EA6BX,MAAA;EA5BQ;EA8BR,SAAA;EA9BmB;EAgCnB,OAAA;EA7BwB;EA+BxB,OAAA;EA/BwB;EAiCxB,KAAA;EA/BM;EAiCN,UAAA;EA/BM;EAiCN,QAAA,GAAW,WAAA;EA/BL;EAiCN,KAAA,GAAQ,WAAA;AAAA"}
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../src/sources/types.ts"],"mappings":"AAIA;;;AAAA,UAAiB,cAAA;EACf,IAAA;EACA,OAAA;EACA,WAAA;EACA,QAAA;EACA,UAAA;IACE,IAAA;IACA,GAAA;IACA,SAAA;EAAA;EAEF,MAAA;EACA,YAAA,GAAe,MAAA;EACf,eAAA,GAAkB,MAAA;EAClB,gBAAA,GAAmB,MAAA;AAAA;AAAA,UAGJ,eAAA;EACf,IAAA;EACA,OAAA;EALA;EAOA,UAAA;EACA,WAAA;EARyB;EAUzB,YAAA,GAAe,MAAA;EAPe;EAS9B,QAAA,GAAW,MAAA;IAAiB,OAAA;IAAiB,UAAA;EAAA;EAC7C,OAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EAJA;EAMA,UAAA;EAN4B;EAQ5B,MAAA;EAPA;EASA,eAAA;EAPA;EASA,QAAA;AAAA;AAAA,UAGe,eAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,WAAA;EACf,GAAA;EAN8B;EAQ9B,KAAA,EAAO,QAAA;AAAA;AAAA,UAGQ,QAAA;EACf,KAAA;EACA,GAAA;AAAA;AAAA,UAGe,UAAA;EACf,GAAA;EACA,KAAA;EACA,OAAA;AAAA;AAAA,UAGe,cAAA;EACf,MAAA;EACA,GAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,UAGe,aAAA;EACf,OAAA,EAAS,eAAA;EACT,QAAA,EAAU,cAAA;EAfe;EAiBzB,eAAA;AAAA"}
@@ -0,0 +1,88 @@
1
+ interface ChunkEntity {
2
+ name: string;
3
+ type: string;
4
+ signature?: string;
5
+ isPartial?: boolean;
6
+ }
7
+ interface Document {
8
+ id: string;
9
+ content: string;
10
+ metadata?: Record<string, any>;
11
+ }
12
+ interface ChunkingOptions {
13
+ chunkSize?: number;
14
+ chunkOverlap?: number;
15
+ }
16
+ type IndexPhase = 'chunking' | 'embedding' | 'storing';
17
+ interface IndexProgress {
18
+ phase: IndexPhase;
19
+ current: number;
20
+ total: number;
21
+ }
22
+ interface IndexConfig {
23
+ dbPath: string;
24
+ model?: string;
25
+ chunking?: ChunkingOptions;
26
+ /** Progress callback forwarded from retriv */
27
+ onProgress?: (progress: IndexProgress) => void;
28
+ }
29
+ interface SearchResult {
30
+ id: string;
31
+ content: string;
32
+ score: number;
33
+ metadata: Record<string, any>;
34
+ highlights: string[];
35
+ /** Line range from chunk [start, end] */
36
+ lineRange?: [number, number];
37
+ entities?: ChunkEntity[];
38
+ scope?: ChunkEntity[];
39
+ }
40
+ type FilterOperator = {
41
+ $eq: string | number | boolean;
42
+ } | {
43
+ $ne: string | number | boolean;
44
+ } | {
45
+ $gt: number;
46
+ } | {
47
+ $gte: number;
48
+ } | {
49
+ $lt: number;
50
+ } | {
51
+ $lte: number;
52
+ } | {
53
+ $in: (string | number)[];
54
+ } | {
55
+ $prefix: string;
56
+ } | {
57
+ $exists: boolean;
58
+ };
59
+ type FilterValue = string | number | boolean | FilterOperator;
60
+ type SearchFilter = Record<string, FilterValue>;
61
+ interface SearchOptions {
62
+ /** Max results */
63
+ limit?: number;
64
+ /** Filter by metadata fields */
65
+ filter?: SearchFilter;
66
+ }
67
+ interface SearchSnippet {
68
+ /** Package name and version */
69
+ package: string;
70
+ /** Source file path */
71
+ source: string;
72
+ /** Start line number */
73
+ lineStart: number;
74
+ /** End line number */
75
+ lineEnd: number;
76
+ /** Snippet content (5 lines around best match) */
77
+ content: string;
78
+ /** Relevance score */
79
+ score: number;
80
+ /** Matched query terms, ordered by BM25 score */
81
+ highlights: string[];
82
+ /** Entities defined in this chunk */
83
+ entities?: ChunkEntity[];
84
+ /** Containing scope chain */
85
+ scope?: ChunkEntity[];
86
+ }
87
+ export { IndexProgress as a, SearchResult as c, IndexPhase as i, SearchSnippet as l, Document as n, SearchFilter as o, IndexConfig as r, SearchOptions as s, ChunkEntity as t };
88
+ //# sourceMappingURL=types2.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types2.d.mts","names":[],"sources":["../../src/retriv/types.ts"],"mappings":"UAAiB,WAAA;EACf,IAAA;EACA,IAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,UAGe,QAAA;EACf,EAAA;EACA,OAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,eAAA;EACf,SAAA;EACA,YAAA;AAAA;AAAA,KAGU,UAAA;AAAA,UAEK,aAAA;EACf,KAAA,EAAO,UAAA;EACP,OAAA;EACA,KAAA;AAAA;AAAA,UAGe,WAAA;EACf,MAAA;EACA,KAAA;EACA,QAAA,GAAW,eAAA;EAXD;EAaV,UAAA,IAAc,QAAA,EAAU,aAAA;AAAA;AAAA,UAGT,YAAA;EACf,EAAA;EACA,OAAA;EACA,KAAA;EACA,QAAA,EAAU,MAAA;EACV,UAAA;EAlBA;EAoBA,SAAA;EACA,QAAA,GAAW,WAAA;EACX,KAAA,GAAQ,WAAA;AAAA;AAAA,KAGE,cAAA;EACJ,GAAA;AAAA;EACA,GAAA;AAAA;EACA,GAAA;AAAA;EACA,IAAA;AAAA;EACA,GAAA;AAAA;EACA,IAAA;AAAA;EACA,GAAA;AAAA;EACA,OAAA;AAAA;EACA,OAAA;AAAA;AAAA,KAEI,WAAA,+BAA0C,cAAA;AAAA,KAC1C,YAAA,GAAe,MAAA,SAAe,WAAA;AAAA,UAEzB,aAAA;EAzBf;EA2BA,KAAA;EAzBA;EA2BA,MAAA,GAAS,YAAA;AAAA;AAAA,UAGM,aAAA;EA1Bf;EA4BA,OAAA;EA3BW;EA6BX,MAAA;EA5BQ;EA8BR,SAAA;EA9BmB;EAgCnB,OAAA;EA7BwB;EA+BxB,OAAA;EA/BwB;EAiCxB,KAAA;EA/BM;EAiCN,UAAA;EA/BM;EAiCN,QAAA,GAAW,WAAA;EA/BL;EAiCN,KAAA,GAAQ,WAAA;AAAA"}
@@ -1,15 +1,14 @@
1
- import "./agent.mjs";
2
- import { i as CACHE_DIR } from "./version.mjs";
3
- import "./cache.mjs";
4
- import { r as mapInsert, t as SHARED_SKILLS_DIR } from "./shared.mjs";
1
+ import { c as SHARED_SKILLS_DIR, t as CACHE_DIR } from "./paths.mjs";
2
+ import { I as unregisterProject, j as getRegisteredProjects } from "./cache.mjs";
3
+ import { X as mapInsert } from "./sources.mjs";
5
4
  import { a as targets } from "./detect.mjs";
6
- import { n as getRegisteredProjects, s as unregisterProject } from "./config.mjs";
5
+ import "./agent.mjs";
7
6
  import { p as isInteractive, x as sharedArgs } from "./cli-helpers.mjs";
8
- import { a as readLock } from "./lockfile.mjs";
9
- import { i as SKILLD_MARKER_START, r as SKILLD_MARKER_END } from "./sync-shared2.mjs";
7
+ import { c as readLock } from "./lockfile.mjs";
8
+ import { n as SKILLD_MARKER_START, t as SKILLD_MARKER_END } from "./skill-installer2.mjs";
10
9
  import "./sync.mjs";
11
- import { join } from "pathe";
12
10
  import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
11
+ import { join } from "pathe";
13
12
  import * as p from "@clack/prompts";
14
13
  import { defineCommand } from "citty";
15
14
  function removeAgentInstructions(agent, projectPath) {
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.mjs","names":["agents"],"sources":["../../src/commands/uninstall.ts"],"sourcesContent":["import type { AgentType } from '../agent/index.ts'\nimport { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { agents } from '../agent/index.ts'\nimport { CACHE_DIR } from '../cache/index.ts'\nimport { isInteractive, sharedArgs } from '../cli-helpers.ts'\nimport { getRegisteredProjects, unregisterProject } from '../core/config.ts'\nimport { readLock } from '../core/lockfile.ts'\nimport { mapInsert, SHARED_SKILLS_DIR } from '../core/shared.ts'\nimport { SKILLD_MARKER_END, SKILLD_MARKER_START } from './sync.ts'\n\n/**\n * Remove the skilld marker block from an agent's instruction file.\n * For .mdc files (dedicated skilld files), delete the entire file.\n * Also cleans up legacy .cursorrules markers for backwards compat.\n */\nfunction removeAgentInstructions(agent: AgentType, projectPath: string): boolean {\n const agentConfig = agents[agent]\n if (!agentConfig.instructionFile)\n return false\n\n let removed = false\n\n // Handle current instruction file\n const filePath = join(projectPath, agentConfig.instructionFile)\n if (agentConfig.instructionFile.endsWith('.mdc')) {\n // MDC files are dedicated skilld files - just delete\n if (existsSync(filePath)) {\n rmSync(filePath)\n removed = true\n }\n // Also clean up legacy .cursorrules markers (cursor-specific)\n if (agent === 'cursor')\n removed = removeMarkerBlock(join(projectPath, '.cursorrules')) || removed\n }\n else if (existsSync(filePath)) {\n removed = removeMarkerBlock(filePath)\n }\n\n return removed\n}\n\nfunction removeMarkerBlock(filePath: string): boolean {\n if (!existsSync(filePath))\n return false\n\n const content = readFileSync(filePath, 'utf-8')\n const startIdx = content.indexOf(SKILLD_MARKER_START)\n if (startIdx === -1)\n return false\n\n const endIdx = content.indexOf(SKILLD_MARKER_END, startIdx)\n if (endIdx === -1)\n return false\n\n // Remove marker block plus surrounding blank lines\n const before = content.slice(0, startIdx).replace(/\\n+$/, '')\n const after = content.slice(endIdx + SKILLD_MARKER_END.length).replace(/^\\n+/, '')\n const updated = before + (before && after ? '\\n' : '') + after\n\n if (updated.trim() === '') {\n rmSync(filePath)\n }\n else {\n writeFileSync(filePath, updated.endsWith('\\n') ? updated : `${updated}\\n`)\n }\n return true\n}\n\nexport interface UninstallOptions {\n scope?: 'project' | 'all'\n agent?: AgentType\n yes: boolean\n}\n\n/**\n * Uninstall skilld skills by scope:\n * - project: Remove project skills (cwd)\n * - all: All registered projects + global skills + cache\n */\nexport async function uninstallCommand(opts: UninstallOptions): Promise<void> {\n let scope = opts.scope\n const registeredProjects = getRegisteredProjects()\n\n // Prompt for scope if not provided\n if (!scope) {\n if (!isInteractive()) {\n scope = 'project'\n }\n else {\n const allHint = registeredProjects.length > 0\n ? `${registeredProjects.length} projects + global + cache`\n : 'global skills + cache'\n\n const selected = await p.select({\n message: 'What do you want to uninstall?',\n options: [\n { label: 'This project', value: 'project', hint: 'current project only' },\n { label: 'Everything', value: 'all', hint: allHint },\n ],\n })\n\n if (p.isCancel(selected)) {\n p.cancel('Cancelled')\n return\n }\n scope = selected as 'project' | 'all'\n }\n }\n\n interface RemoveItem { label: string, path: string, version?: string }\n const toRemove: RemoveItem[] = []\n const seenPaths = new Set<string>()\n const projectsToUnregister: string[] = []\n const agentFilter = opts.agent ? [opts.agent] : undefined\n\n const addToRemove = (label: string, path: string, version?: string) => {\n if (seenPaths.has(path))\n return\n seenPaths.add(path)\n toRemove.push({ label, path, version })\n }\n\n // Helper to add skills from a lockfile\n const addSkillsFromLock = (skillsDir: string, label: string): string[] => {\n const trackedNames: string[] = []\n const lock = readLock(skillsDir)\n\n if (lock?.skills) {\n for (const [skillName, info] of Object.entries(lock.skills)) {\n trackedNames.push(skillName)\n const skillDir = join(skillsDir, skillName)\n if (existsSync(skillDir)) {\n const version = info.version ? `${info.version.split('.').slice(0, 2).join('.')}.x` : undefined\n addToRemove(`${label}: ${skillName}`, skillDir, version)\n }\n }\n\n // Also add the lockfile itself\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n if (existsSync(lockPath)) {\n addToRemove(`${label}: skilld-lock.yaml`, lockPath)\n }\n }\n\n return trackedNames\n }\n\n // Helper to find untracked skills in a directory\n const findUntrackedSkills = (skillsDir: string, trackedNames: string[]): string[] => {\n if (!existsSync(skillsDir))\n return []\n const tracked = new Set(trackedNames)\n return readdirSync(skillsDir)\n .filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml' && !tracked.has(f))\n }\n\n // Track untracked skills per directory (dedupe by path)\n const untrackedByDir = new Map<string, { label: string, skills: string[] }>()\n const processedDirs = new Set<string>()\n\n // Helper to process a skills directory (with deduping)\n const processSkillsDir = (skillsDir: string, label: string) => {\n if (processedDirs.has(skillsDir))\n return\n processedDirs.add(skillsDir)\n\n const tracked = addSkillsFromLock(skillsDir, label)\n const untracked = findUntrackedSkills(skillsDir, tracked)\n if (untracked.length > 0) {\n untrackedByDir.set(skillsDir, { label, skills: untracked })\n }\n }\n\n // Project skills\n if (scope === 'project') {\n // Shared dir\n const sharedDir = join(process.cwd(), SHARED_SKILLS_DIR)\n if (existsSync(sharedDir))\n processSkillsDir(sharedDir, 'project (.skills)')\n for (const [name, agent] of Object.entries(agents)) {\n if (agentFilter && !agentFilter.includes(name as AgentType))\n continue\n processSkillsDir(join(process.cwd(), agent.skillsDir), 'project')\n }\n projectsToUnregister.push(process.cwd())\n }\n\n // All registered projects + global\n if (scope === 'all') {\n const projectPaths = registeredProjects.length > 0 ? registeredProjects : [process.cwd()]\n\n // Show which projects will be affected\n if (registeredProjects.length > 0) {\n p.log.info('Projects to uninstall from:')\n for (const proj of projectPaths) {\n p.log.message(` ${proj}`)\n }\n }\n\n // Project skills from lockfiles\n for (const projectPath of projectPaths) {\n if (!existsSync(projectPath))\n continue\n\n const shortPath = projectPath.replace(process.env.HOME || '', '~')\n\n // Shared dir\n const sharedDir = join(projectPath, SHARED_SKILLS_DIR)\n if (existsSync(sharedDir))\n processSkillsDir(sharedDir, `${shortPath} (.skills)`)\n\n for (const [name, agent] of Object.entries(agents)) {\n if (agentFilter && !agentFilter.includes(name as AgentType))\n continue\n processSkillsDir(join(projectPath, agent.skillsDir), shortPath)\n }\n\n projectsToUnregister.push(projectPath)\n }\n\n // Global skills from lockfiles\n for (const [name, agent] of Object.entries(agents)) {\n if (agentFilter && !agentFilter.includes(name as AgentType))\n continue\n if (!agent.globalSkillsDir)\n continue\n processSkillsDir(agent.globalSkillsDir, 'user')\n }\n\n // Cache directory\n if (existsSync(CACHE_DIR)) {\n addToRemove('~/.skilld cache', CACHE_DIR)\n }\n }\n\n // Warn about untracked skills that will remain (grouped by label, deduped)\n if (untrackedByDir.size > 0) {\n const groupedUntracked = new Map<string, Set<string>>()\n for (const [_dir, { label, skills }] of untrackedByDir) {\n const set = mapInsert(groupedUntracked, label, () => new Set())\n for (const s of skills) set.add(s)\n }\n\n const totalUntracked = [...groupedUntracked.values()].reduce((sum, s) => sum + s.size, 0)\n p.log.warn(`${totalUntracked} untracked skill(s) will remain (not managed by skilld):`)\n for (const [label, skills] of groupedUntracked) {\n p.log.message(` ${label}: ${[...skills].join(', ')}`)\n }\n }\n\n if (toRemove.length === 0) {\n p.log.info('Nothing to uninstall')\n return\n }\n\n // Group by prefix for display\n const groups = new Map<string, Array<{ name: string, version?: string }>>()\n for (const item of toRemove) {\n const [prefix, name] = item.label.includes(': ')\n ? item.label.split(': ', 2)\n : ['other', item.label]\n mapInsert(groups, prefix!, () => []).push({ name: name!, version: item.version })\n }\n\n const formatGroup = (items: Array<{ name: string, version?: string }>) =>\n items.map(i => i.version ? `${i.name}@${i.version}` : i.name).join(', ')\n\n p.log.info(`Will remove ${toRemove.length} items:`)\n for (const [prefix, items] of groups) {\n p.log.message(` ${prefix}: ${formatGroup(items)}`)\n }\n\n if (!opts.yes && isInteractive()) {\n const confirmed = await p.confirm({\n message: 'Proceed with uninstall?',\n })\n\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel('Cancelled')\n return\n }\n }\n\n // Remove all items\n for (const item of toRemove) {\n rmSync(item.path, { recursive: true, force: true })\n }\n\n // Show grouped removal summary\n for (const [prefix, items] of groups) {\n p.log.success(`Removed ${prefix}: ${formatGroup(items)}`)\n }\n\n // Remove skilld instructions from agent instruction files\n const agentTypes = agentFilter || (Object.keys(agents) as AgentType[])\n for (const proj of projectsToUnregister) {\n for (const agent of agentTypes) {\n if (removeAgentInstructions(agent, proj)) {\n const file = agents[agent].instructionFile!\n p.log.success(`Cleaned ${file}`)\n }\n }\n }\n\n // Unregister projects from config (skip if cache dir was removed — config is gone)\n if (scope !== 'all') {\n for (const proj of projectsToUnregister) {\n unregisterProject(proj)\n }\n }\n\n p.outro('skilld uninstalled')\n}\n\nexport const uninstallCommandDef = defineCommand({\n meta: { name: 'uninstall', description: 'Remove skilld data' },\n args: {\n ...sharedArgs,\n },\n async run({ args }) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m uninstall`)\n return uninstallCommand({\n scope: args.global ? 'all' : undefined,\n agent: args.agent as AgentType | undefined,\n yes: args.yes,\n })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"uninstall.mjs","names":["agents"],"sources":["../../src/commands/uninstall.ts"],"sourcesContent":["import type { AgentType } from '../agent/index.ts'\nimport { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { agents } from '../agent/index.ts'\nimport { CACHE_DIR } from '../cache/index.ts'\nimport { isInteractive, sharedArgs } from '../cli-helpers.ts'\nimport { getRegisteredProjects, unregisterProject } from '../core/config.ts'\nimport { readLock } from '../core/lockfile.ts'\nimport { mapInsert } from '../core/map.ts'\nimport { SHARED_SKILLS_DIR } from '../core/paths.ts'\nimport { SKILLD_MARKER_END, SKILLD_MARKER_START } from './sync.ts'\n\n/**\n * Remove the skilld marker block from an agent's instruction file.\n * For .mdc files (dedicated skilld files), delete the entire file.\n * Also cleans up legacy .cursorrules markers for backwards compat.\n */\nfunction removeAgentInstructions(agent: AgentType, projectPath: string): boolean {\n const agentConfig = agents[agent]\n if (!agentConfig.instructionFile)\n return false\n\n let removed = false\n\n // Handle current instruction file\n const filePath = join(projectPath, agentConfig.instructionFile)\n if (agentConfig.instructionFile.endsWith('.mdc')) {\n // MDC files are dedicated skilld files - just delete\n if (existsSync(filePath)) {\n rmSync(filePath)\n removed = true\n }\n // Also clean up legacy .cursorrules markers (cursor-specific)\n if (agent === 'cursor')\n removed = removeMarkerBlock(join(projectPath, '.cursorrules')) || removed\n }\n else if (existsSync(filePath)) {\n removed = removeMarkerBlock(filePath)\n }\n\n return removed\n}\n\nfunction removeMarkerBlock(filePath: string): boolean {\n if (!existsSync(filePath))\n return false\n\n const content = readFileSync(filePath, 'utf-8')\n const startIdx = content.indexOf(SKILLD_MARKER_START)\n if (startIdx === -1)\n return false\n\n const endIdx = content.indexOf(SKILLD_MARKER_END, startIdx)\n if (endIdx === -1)\n return false\n\n // Remove marker block plus surrounding blank lines\n const before = content.slice(0, startIdx).replace(/\\n+$/, '')\n const after = content.slice(endIdx + SKILLD_MARKER_END.length).replace(/^\\n+/, '')\n const updated = before + (before && after ? '\\n' : '') + after\n\n if (updated.trim() === '') {\n rmSync(filePath)\n }\n else {\n writeFileSync(filePath, updated.endsWith('\\n') ? updated : `${updated}\\n`)\n }\n return true\n}\n\nexport interface UninstallOptions {\n scope?: 'project' | 'all'\n agent?: AgentType\n yes: boolean\n}\n\n/**\n * Uninstall skilld skills by scope:\n * - project: Remove project skills (cwd)\n * - all: All registered projects + global skills + cache\n */\nexport async function uninstallCommand(opts: UninstallOptions): Promise<void> {\n let scope = opts.scope\n const registeredProjects = getRegisteredProjects()\n\n // Prompt for scope if not provided\n if (!scope) {\n if (!isInteractive()) {\n scope = 'project'\n }\n else {\n const allHint = registeredProjects.length > 0\n ? `${registeredProjects.length} projects + global + cache`\n : 'global skills + cache'\n\n const selected = await p.select({\n message: 'What do you want to uninstall?',\n options: [\n { label: 'This project', value: 'project', hint: 'current project only' },\n { label: 'Everything', value: 'all', hint: allHint },\n ],\n })\n\n if (p.isCancel(selected)) {\n p.cancel('Cancelled')\n return\n }\n scope = selected as 'project' | 'all'\n }\n }\n\n interface RemoveItem { label: string, path: string, version?: string }\n const toRemove: RemoveItem[] = []\n const seenPaths = new Set<string>()\n const projectsToUnregister: string[] = []\n const agentFilter = opts.agent ? [opts.agent] : undefined\n\n const addToRemove = (label: string, path: string, version?: string) => {\n if (seenPaths.has(path))\n return\n seenPaths.add(path)\n toRemove.push({ label, path, version })\n }\n\n // Helper to add skills from a lockfile\n const addSkillsFromLock = (skillsDir: string, label: string): string[] => {\n const trackedNames: string[] = []\n const lock = readLock(skillsDir)\n\n if (lock?.skills) {\n for (const [skillName, info] of Object.entries(lock.skills)) {\n trackedNames.push(skillName)\n const skillDir = join(skillsDir, skillName)\n if (existsSync(skillDir)) {\n const version = info.version ? `${info.version.split('.').slice(0, 2).join('.')}.x` : undefined\n addToRemove(`${label}: ${skillName}`, skillDir, version)\n }\n }\n\n // Also add the lockfile itself\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n if (existsSync(lockPath)) {\n addToRemove(`${label}: skilld-lock.yaml`, lockPath)\n }\n }\n\n return trackedNames\n }\n\n // Helper to find untracked skills in a directory\n const findUntrackedSkills = (skillsDir: string, trackedNames: string[]): string[] => {\n if (!existsSync(skillsDir))\n return []\n const tracked = new Set(trackedNames)\n return readdirSync(skillsDir)\n .filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml' && !tracked.has(f))\n }\n\n // Track untracked skills per directory (dedupe by path)\n const untrackedByDir = new Map<string, { label: string, skills: string[] }>()\n const processedDirs = new Set<string>()\n\n // Helper to process a skills directory (with deduping)\n const processSkillsDir = (skillsDir: string, label: string) => {\n if (processedDirs.has(skillsDir))\n return\n processedDirs.add(skillsDir)\n\n const tracked = addSkillsFromLock(skillsDir, label)\n const untracked = findUntrackedSkills(skillsDir, tracked)\n if (untracked.length > 0) {\n untrackedByDir.set(skillsDir, { label, skills: untracked })\n }\n }\n\n // Project skills\n if (scope === 'project') {\n // Shared dir\n const sharedDir = join(process.cwd(), SHARED_SKILLS_DIR)\n if (existsSync(sharedDir))\n processSkillsDir(sharedDir, 'project (.skills)')\n for (const [name, agent] of Object.entries(agents)) {\n if (agentFilter && !agentFilter.includes(name as AgentType))\n continue\n processSkillsDir(join(process.cwd(), agent.skillsDir), 'project')\n }\n projectsToUnregister.push(process.cwd())\n }\n\n // All registered projects + global\n if (scope === 'all') {\n const projectPaths = registeredProjects.length > 0 ? registeredProjects : [process.cwd()]\n\n // Show which projects will be affected\n if (registeredProjects.length > 0) {\n p.log.info('Projects to uninstall from:')\n for (const proj of projectPaths) {\n p.log.message(` ${proj}`)\n }\n }\n\n // Project skills from lockfiles\n for (const projectPath of projectPaths) {\n if (!existsSync(projectPath))\n continue\n\n const shortPath = projectPath.replace(process.env.HOME || '', '~')\n\n // Shared dir\n const sharedDir = join(projectPath, SHARED_SKILLS_DIR)\n if (existsSync(sharedDir))\n processSkillsDir(sharedDir, `${shortPath} (.skills)`)\n\n for (const [name, agent] of Object.entries(agents)) {\n if (agentFilter && !agentFilter.includes(name as AgentType))\n continue\n processSkillsDir(join(projectPath, agent.skillsDir), shortPath)\n }\n\n projectsToUnregister.push(projectPath)\n }\n\n // Global skills from lockfiles\n for (const [name, agent] of Object.entries(agents)) {\n if (agentFilter && !agentFilter.includes(name as AgentType))\n continue\n if (!agent.globalSkillsDir)\n continue\n processSkillsDir(agent.globalSkillsDir, 'user')\n }\n\n // Cache directory\n if (existsSync(CACHE_DIR)) {\n addToRemove('~/.skilld cache', CACHE_DIR)\n }\n }\n\n // Warn about untracked skills that will remain (grouped by label, deduped)\n if (untrackedByDir.size > 0) {\n const groupedUntracked = new Map<string, Set<string>>()\n for (const [_dir, { label, skills }] of untrackedByDir) {\n const set = mapInsert(groupedUntracked, label, () => new Set())\n for (const s of skills) set.add(s)\n }\n\n const totalUntracked = [...groupedUntracked.values()].reduce((sum, s) => sum + s.size, 0)\n p.log.warn(`${totalUntracked} untracked skill(s) will remain (not managed by skilld):`)\n for (const [label, skills] of groupedUntracked) {\n p.log.message(` ${label}: ${[...skills].join(', ')}`)\n }\n }\n\n if (toRemove.length === 0) {\n p.log.info('Nothing to uninstall')\n return\n }\n\n // Group by prefix for display\n const groups = new Map<string, Array<{ name: string, version?: string }>>()\n for (const item of toRemove) {\n const [prefix, name] = item.label.includes(': ')\n ? item.label.split(': ', 2)\n : ['other', item.label]\n mapInsert(groups, prefix!, () => []).push({ name: name!, version: item.version })\n }\n\n const formatGroup = (items: Array<{ name: string, version?: string }>) =>\n items.map(i => i.version ? `${i.name}@${i.version}` : i.name).join(', ')\n\n p.log.info(`Will remove ${toRemove.length} items:`)\n for (const [prefix, items] of groups) {\n p.log.message(` ${prefix}: ${formatGroup(items)}`)\n }\n\n if (!opts.yes && isInteractive()) {\n const confirmed = await p.confirm({\n message: 'Proceed with uninstall?',\n })\n\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel('Cancelled')\n return\n }\n }\n\n // Remove all items\n for (const item of toRemove) {\n rmSync(item.path, { recursive: true, force: true })\n }\n\n // Show grouped removal summary\n for (const [prefix, items] of groups) {\n p.log.success(`Removed ${prefix}: ${formatGroup(items)}`)\n }\n\n // Remove skilld instructions from agent instruction files\n const agentTypes = agentFilter || (Object.keys(agents) as AgentType[])\n for (const proj of projectsToUnregister) {\n for (const agent of agentTypes) {\n if (removeAgentInstructions(agent, proj)) {\n const file = agents[agent].instructionFile!\n p.log.success(`Cleaned ${file}`)\n }\n }\n }\n\n // Unregister projects from config (skip if cache dir was removed — config is gone)\n if (scope !== 'all') {\n for (const proj of projectsToUnregister) {\n unregisterProject(proj)\n }\n }\n\n p.outro('skilld uninstalled')\n}\n\nexport const uninstallCommandDef = defineCommand({\n meta: { name: 'uninstall', description: 'Remove skilld data' },\n args: {\n ...sharedArgs,\n },\n async run({ args }) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m uninstall`)\n return uninstallCommand({\n scope: args.global ? 'all' : undefined,\n agent: args.agent as AgentType | undefined,\n yes: args.yes,\n })\n },\n})\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { i as parseFrontmatter } from "./markdown.mjs";
2
- import { a as readLock } from "./lockfile.mjs";
2
+ import { c as readLock } from "./lockfile.mjs";
3
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
4
  import { homedir } from "node:os";
4
5
  import { join } from "pathe";
5
- import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
6
6
  import { ofetch } from "ofetch";
7
7
  import { multiselect } from "@clack/prompts";
8
8
  import { defineCommand } from "citty";
@@ -1,4 +1,4 @@
1
- import { o as getSectionValidator } from "./prompts.mjs";
1
+ import { S as getSectionValidator } from "./prompts.mjs";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { defineCommand } from "citty";
4
4
  const SECTION_HEADINGS = {
@@ -1,15 +1,5 @@
1
- import { homedir } from "node:os";
2
- import { join, resolve } from "pathe";
3
- const CACHE_DIR = join(homedir(), ".skilld");
4
- const REFERENCES_DIR = join(CACHE_DIR, "references");
5
- const REPOS_DIR = join(CACHE_DIR, "repos");
6
- function getRepoCacheDir(owner, repo) {
7
- if (owner.includes("..") || repo.includes("..") || owner.includes("/") || repo.includes("/")) throw new Error(`Invalid repo path: ${owner}/${repo}`);
8
- return join(REPOS_DIR, owner, repo);
9
- }
10
- function getPackageDbPath(name, version) {
11
- return join(REFERENCES_DIR, `${name}@${version}`, "search.db");
12
- }
1
+ import { o as REFERENCES_DIR } from "./paths.mjs";
2
+ import { resolve } from "pathe";
13
3
  const VALID_PKG_NAME = /^(?:@[a-z0-9][-a-z0-9._]*\/)?[a-z0-9][-a-z0-9._]*$/;
14
4
  const VALID_VERSION = /^[a-z0-9][-\w.+]*$/i;
15
5
  function getVersionKey(version) {
@@ -25,6 +15,6 @@ function getCacheDir(name, version) {
25
15
  if (!dir.startsWith(REFERENCES_DIR)) throw new Error(`Path traversal detected: ${dir}`);
26
16
  return dir;
27
17
  }
28
- export { REFERENCES_DIR as a, getRepoCacheDir as c, CACHE_DIR as i, getCacheKey as n, REPOS_DIR as o, getVersionKey as r, getPackageDbPath as s, getCacheDir as t };
18
+ export { getCacheKey as n, getVersionKey as r, getCacheDir as t };
29
19
 
30
20
  //# sourceMappingURL=version.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.mjs","names":[],"sources":["../../src/cache/config.ts","../../src/cache/version.ts"],"sourcesContent":["/**\n * Cache configuration\n */\n\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\n\n/** Global cache directory */\nexport const CACHE_DIR = join(homedir(), '.skilld')\n\n/** References subdirectory */\nexport const REFERENCES_DIR = join(CACHE_DIR, 'references')\n\n/** Repo-level cache (issues, discussions, releases shared across monorepo packages) */\nexport const REPOS_DIR = join(CACHE_DIR, 'repos')\n\n/** Get repo cache dir for owner/repo with path traversal validation */\nexport function getRepoCacheDir(owner: string, repo: string): string {\n if (owner.includes('..') || repo.includes('..') || owner.includes('/') || repo.includes('/'))\n throw new Error(`Invalid repo path: ${owner}/${repo}`)\n return join(REPOS_DIR, owner, repo)\n}\n\n/** Get search DB path for a specific package@version */\nexport function getPackageDbPath(name: string, version: string): string {\n return join(REFERENCES_DIR, `${name}@${version}`, 'search.db')\n}\n","/**\n * Version utilities\n */\n\nimport { resolve } from 'pathe'\nimport { REFERENCES_DIR } from './config.ts'\n\n/** Validate npm package name (scoped or unscoped) */\nconst VALID_PKG_NAME = /^(?:@[a-z0-9][-a-z0-9._]*\\/)?[a-z0-9][-a-z0-9._]*$/\n\n/** Validate version string (semver-ish, no path separators) */\nconst VALID_VERSION = /^[a-z0-9][-\\w.+]*$/i\n\n/**\n * Get exact version key for cache keying\n */\nexport function getVersionKey(version: string): string {\n return version\n}\n\n/**\n * Get cache key for a package: name@version\n */\nexport function getCacheKey(name: string, version: string): string {\n return `${name}@${getVersionKey(version)}`\n}\n\n/**\n * Get path to cached package references.\n * Validates name/version to prevent path traversal.\n */\nexport function getCacheDir(name: string, version: string): string {\n if (!VALID_PKG_NAME.test(name))\n throw new Error(`Invalid package name: ${name}`)\n if (!VALID_VERSION.test(version))\n throw new Error(`Invalid version: ${version}`)\n\n const dir = resolve(REFERENCES_DIR, getCacheKey(name, version))\n if (!dir.startsWith(REFERENCES_DIR))\n throw new Error(`Path traversal detected: ${dir}`)\n return dir\n}\n"],"mappings":";;;AAQA,MAAa,iBAAiB,KAAA,WAAW,aAAU;AAGnD,MAAa,YAAA,KAAiB,WAAK,QAAW;AAG9C,SAAa,gBAAiB,OAAA,MAAW;;CAGzC,OAAA,KAAgB,WAAA,OAAgB,KAAe;;;;;;;ACT/C,SAAM,cAAiB,SAAA;;;;;;;;;;CAevB,IAAA,CAAA,IAAgB,WAAY,eAAuC,EAAA,MAAA,IAAA,MAAA,4BAAA,MAAA;CACjE,OAAO"}
1
+ {"version":3,"file":"version.mjs","names":[],"sources":["../../src/cache/version.ts"],"sourcesContent":["/**\n * Version utilities\n */\n\nimport { resolve } from 'pathe'\nimport { REFERENCES_DIR } from '../core/paths.ts'\n\n/** Validate npm package name (scoped or unscoped) */\nconst VALID_PKG_NAME = /^(?:@[a-z0-9][-a-z0-9._]*\\/)?[a-z0-9][-a-z0-9._]*$/\n\n/** Validate version string (semver-ish, no path separators) */\nconst VALID_VERSION = /^[a-z0-9][-\\w.+]*$/i\n\n/**\n * Get exact version key for cache keying\n */\nexport function getVersionKey(version: string): string {\n return version\n}\n\n/**\n * Get cache key for a package: name@version\n */\nexport function getCacheKey(name: string, version: string): string {\n return `${name}@${getVersionKey(version)}`\n}\n\n/**\n * Get path to cached package references.\n * Validates name/version to prevent path traversal.\n */\nexport function getCacheDir(name: string, version: string): string {\n if (!VALID_PKG_NAME.test(name))\n throw new Error(`Invalid package name: ${name}`)\n if (!VALID_VERSION.test(version))\n throw new Error(`Invalid version: ${version}`)\n\n const dir = resolve(REFERENCES_DIR, getCacheKey(name, version))\n if (!dir.startsWith(REFERENCES_DIR))\n throw new Error(`Path traversal detected: ${dir}`)\n return dir\n}\n"],"mappings":";;;AAQA,MAAM,gBAAA;AAGN,SAAM,cAAgB,SAAA;;;AAKtB,SAAgB,YAAA,MAAc,SAAyB;CACrD,OAAO,GAAA,KAAA,GAAA,cAAA,QAAA;;;;CAMT,IAAA,CAAA,cAAgB,KAAY,QAAc,EAAA,MAAyB,IAAA,MAAA,oBAAA,UAAA;CACjE,MAAA,MAAU,QAAQ,gBAAc,YAAQ,MAAA,QAAA,CAAA"}
@@ -1,6 +1,6 @@
1
- import { c as getOAuthProviderList, i as getAvailableModels, l as loginOAuthProvider, o as getModelName } from "./agent.mjs";
1
+ import { L as updateConfig, k as defaultFeatures } from "./cache.mjs";
2
2
  import { a as targets } from "./detect.mjs";
3
- import { c as updateConfig, t as defaultFeatures } from "./config.mjs";
3
+ import { a as getModelName, c as getOAuthProviderList, l as loginOAuthProvider, r as getAvailableModels } from "./agent.mjs";
4
4
  import { g as pickModel, n as NO_MODELS_MESSAGE, p as isInteractive, r as OAUTH_NOTE } from "./cli-helpers.mjs";
5
5
  import { execSync } from "node:child_process";
6
6
  import * as p from "@clack/prompts";