@skillctl/core 0.4.0 → 0.5.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.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 xFurti, Gabry848
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xFurti, Gabry848
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAmBA,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAsB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc9E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWvF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ3E;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrF;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBtE;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9H"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAoBA,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAsB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlE;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAI/D;AAMD;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc9E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWvF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ3E;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrF;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBtE;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9H"}
package/dist/cache.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { cp, mkdir, stat, readdir, rm } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
+ import { createHash } from 'node:crypto';
4
5
  import { getDirStatSignature } from './fs.js';
5
6
  /**
6
7
  * Content-addressable cache for performance (PR12).
@@ -26,8 +27,13 @@ export async function ensureCacheDir(sub) {
26
27
  return d;
27
28
  }
28
29
  export function cacheKeyFromIntegrity(integrity) {
29
- // e.g. 'sha256:abc123...' -> 'abc123...'
30
- return integrity.replace(/^sha256:/i, '').toLowerCase();
30
+ const match = /^sha256:([0-9a-f]{64})$/i.exec(integrity);
31
+ if (!match)
32
+ throw new Error(`Invalid cache integrity key: ${integrity}`);
33
+ return match[1].toLowerCase();
34
+ }
35
+ function safeDownloadKey(key) {
36
+ return createHash('sha256').update(key).digest('hex');
31
37
  }
32
38
  /**
33
39
  * Return path to cached extracted skill dir for this integrity, or null.
@@ -73,7 +79,7 @@ export async function putCachedSkill(integrity, srcDir) {
73
79
  */
74
80
  export async function getCachedDownload(key) {
75
81
  await ensureCacheDir('downloads');
76
- const p = join(DOWNLOAD_CACHE, key);
82
+ const p = join(DOWNLOAD_CACHE, safeDownloadKey(key));
77
83
  try {
78
84
  const st = await stat(p);
79
85
  if (st.isFile())
@@ -84,7 +90,7 @@ export async function getCachedDownload(key) {
84
90
  }
85
91
  export async function putCachedDownload(key, srcFile) {
86
92
  await ensureCacheDir('downloads');
87
- const dest = join(DOWNLOAD_CACHE, key);
93
+ const dest = join(DOWNLOAD_CACHE, safeDownloadKey(key));
88
94
  await cp(srcFile, dest, { force: true });
89
95
  return dest;
90
96
  }
package/dist/cache.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAsBjD,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAiB7E;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3F;AAED,wBAAgB,gBAAgB,IAAI,cAAc,CAEjD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAsBjD,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAoB7E;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM3F;AAED,wBAAgB,gBAAgB,IAAI,cAAc,CAEjD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
package/dist/config.js CHANGED
@@ -1,9 +1,9 @@
1
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
- import { join } from 'node:path';
1
+ import { readFile, mkdir } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
+ import { writeFileAtomic } from './fs.js';
4
5
  const DEFAULT_STORE = join(homedir(), '.skillctl', 'skills');
5
- const CONFIG_DIR = join(homedir(), '.skillctl');
6
- const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
6
+ const CONFIG_PATH = join(homedir(), '.skillctl', 'config.json');
7
7
  const DEFAULT_CONFIG = {
8
8
  version: 1,
9
9
  store: DEFAULT_STORE,
@@ -24,31 +24,71 @@ export async function loadConfig(customPath) {
24
24
  try {
25
25
  const raw = await readFile(path, 'utf8');
26
26
  const parsed = JSON.parse(raw);
27
+ validateConfig(parsed);
27
28
  // merge with defaults for forward compat / missing keys
28
- return {
29
+ const config = {
29
30
  ...DEFAULT_CONFIG,
30
31
  ...parsed,
31
32
  agents: { ...DEFAULT_CONFIG.agents, ...parsed.agents },
32
33
  trustedSources: parsed.trustedSources ?? DEFAULT_CONFIG.trustedSources,
33
34
  registries: parsed.registries ?? DEFAULT_CONFIG.registries,
34
35
  };
36
+ if (process.env.SKILLCTL_STORE)
37
+ config.store = process.env.SKILLCTL_STORE;
38
+ return config;
35
39
  }
36
- catch {
37
- // missing or invalid -> return defaults (do not auto-write unless save called)
38
- return { ...DEFAULT_CONFIG };
40
+ catch (err) {
41
+ if (err.code === 'ENOENT')
42
+ return cloneDefaultConfig();
43
+ throw new Error(`Unable to load skillctl config at ${path}: ${err.message}`, { cause: err });
39
44
  }
40
45
  }
41
46
  export async function saveConfig(config, customPath) {
42
47
  const path = customPath || CONFIG_PATH;
43
- await mkdir(CONFIG_DIR, { recursive: true });
44
- // simple write; PR2 would have atomic + proper-lockfile
48
+ validateConfig(config);
49
+ await mkdir(dirname(path), { recursive: true });
45
50
  const data = JSON.stringify(config, null, 2);
46
- await writeFile(path, data + '\n', 'utf8');
51
+ await writeFileAtomic(path, data + '\n');
47
52
  }
48
53
  export function getDefaultConfig() {
49
- return { ...DEFAULT_CONFIG };
54
+ return cloneDefaultConfig();
50
55
  }
51
56
  export function getConfigPath() {
52
57
  return CONFIG_PATH;
53
58
  }
59
+ function cloneDefaultConfig() {
60
+ const config = {
61
+ ...DEFAULT_CONFIG,
62
+ agents: { ...DEFAULT_CONFIG.agents },
63
+ registries: [...(DEFAULT_CONFIG.registries || [])],
64
+ trustedSources: [...(DEFAULT_CONFIG.trustedSources || [])],
65
+ };
66
+ if (process.env.SKILLCTL_STORE)
67
+ config.store = process.env.SKILLCTL_STORE;
68
+ return config;
69
+ }
70
+ function validateConfig(config) {
71
+ if (!config || typeof config !== 'object')
72
+ throw new Error('config must be an object');
73
+ if (config.version !== undefined && config.version !== 1)
74
+ throw new Error('unsupported config version');
75
+ if (config.store !== undefined && typeof config.store !== 'string')
76
+ throw new Error('store must be a string');
77
+ if (config.defaultMode !== undefined &&
78
+ !['symlink', 'copy', 'junction'].includes(config.defaultMode)) {
79
+ throw new Error('defaultMode must be symlink, copy, or junction');
80
+ }
81
+ if (config.agents !== undefined &&
82
+ (typeof config.agents !== 'object' || Object.values(config.agents).some((v) => typeof v !== 'boolean'))) {
83
+ throw new Error('agents must map agent ids to booleans');
84
+ }
85
+ if (config.registries !== undefined &&
86
+ (!Array.isArray(config.registries) || config.registries.some((v) => typeof v !== 'string'))) {
87
+ throw new Error('registries must be an array');
88
+ }
89
+ if (config.trustedSources !== undefined &&
90
+ (!Array.isArray(config.trustedSources) || config.trustedSources.some((v) => typeof v !== 'string'))) {
91
+ throw new Error('trustedSources must be an array');
92
+ }
93
+ }
54
94
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAChD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD,MAAM,cAAc,GAAmB;IACrC,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,aAAa;IACpB,WAAW,EAAE,SAAS;IACtB,MAAM,EAAE;QACN,aAAa,EAAE,IAAI;QACnB,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,IAAI;KACX;IACD,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,CAAC,sBAAsB,EAAE,aAAa,EAAE,0BAA0B,CAAC;CACpF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,MAAM,IAAI,GAAG,UAAU,IAAI,WAAW,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAC1D,wDAAwD;QACxD,OAAO;YACL,GAAG,cAAc;YACjB,GAAG,MAAM;YACT,MAAM,EAAE,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE;YACtD,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,cAAc,CAAC,cAAc;YACtE,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,cAAc,CAAC,UAAU;SACzC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;QAC/E,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAsB,EAAE,UAAmB;IAC1E,MAAM,IAAI,GAAG,UAAU,IAAI,WAAW,CAAC;IACvC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,wDAAwD;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/fs.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;GAGG;AAEH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5F;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBtE;AAeD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU9G;AAkBD,wBAAgB,kBAAkB,IAAI,QAAQ,CAE7C"}
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;GAGG;AAEH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5F;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBtE;AAeD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU9G;AAkBD,wBAAgB,kBAAkB,IAAI,QAAQ,CAE7C"}
package/dist/fs.js CHANGED
@@ -1,4 +1,4 @@
1
- import { readFile, writeFile, mkdir, rename, stat, readdir } from 'node:fs/promises';
1
+ import { readFile, writeFile, mkdir, rename, stat, readdir, lstat, readlink, rm } from 'node:fs/promises';
2
2
  import { join, dirname } from 'node:path';
3
3
  import { createHash } from 'node:crypto';
4
4
  /**
@@ -14,8 +14,13 @@ export async function ensureDir(dir) {
14
14
  export async function writeFileAtomic(filePath, data) {
15
15
  await ensureDir(dirname(filePath));
16
16
  const tmp = `${filePath}.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`;
17
- await writeFile(tmp, data);
18
- await rename(tmp, filePath);
17
+ try {
18
+ await writeFile(tmp, data);
19
+ await rename(tmp, filePath);
20
+ }
21
+ finally {
22
+ await rm(tmp, { force: true }).catch(() => { });
23
+ }
19
24
  }
20
25
  /**
21
26
  * Compute sha256 of a file (for single files).
@@ -38,16 +43,19 @@ export async function computeDirIntegrity(dir) {
38
43
  files.sort(); // deterministic
39
44
  const hash = createHash('sha256');
40
45
  for (const f of files) {
41
- try {
46
+ const fileStat = await lstat(f);
47
+ hash.update(f.slice(dir.length)); // relative
48
+ hash.update('\0');
49
+ if (fileStat.isSymbolicLink()) {
50
+ hash.update('symlink\0');
51
+ hash.update(await readlink(f));
52
+ }
53
+ else {
42
54
  const buf = await readFile(f);
43
- hash.update(f.slice(dir.length)); // relative
44
- hash.update('\0');
55
+ hash.update('file\0');
45
56
  hash.update(buf);
46
- hash.update('\0');
47
- }
48
- catch {
49
- // ignore unreadable
50
57
  }
58
+ hash.update('\0');
51
59
  }
52
60
  return `sha256:${hash.digest('hex')}`;
53
61
  }
@@ -60,7 +68,7 @@ async function walk(dir, out) {
60
68
  if (e.isDirectory()) {
61
69
  await walk(p, out);
62
70
  }
63
- else if (e.isFile()) {
71
+ else if (e.isFile() || e.isSymbolicLink()) {
64
72
  out.push(p);
65
73
  }
66
74
  }
package/dist/fs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIpD"}
package/dist/names.js CHANGED
@@ -1,5 +1,8 @@
1
1
  /** Canonical skill name: lowercase, hyphen normalized (per design). */
2
2
  export function canonicalizeName(raw) {
3
- return raw.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
3
+ const canonical = raw.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
4
+ if (!canonical)
5
+ throw new Error(`Invalid skill name: ${raw}`);
6
+ return canonical;
4
7
  }
5
8
  //# sourceMappingURL=names.js.map
package/dist/names.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"names.js","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC"}
1
+ {"version":3,"file":"names.js","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACxF,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAC;IAC9D,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/dist/paths.d.ts CHANGED
@@ -6,4 +6,6 @@ export declare function expandTilde(path: string): string;
6
6
  export declare function formatCanonicalPathForLock(skillName: string): string;
7
7
  /** Resolve lock canonicalPath (tilde, legacy absolute, or store-relative) to a filesystem path. */
8
8
  export declare function resolveCanonicalPath(canonicalPath: string, store?: string): string;
9
+ /** Resolve an untrusted relative path and require it to remain inside root. */
10
+ export declare function resolvePathInside(root: string, candidate: string, label?: string): string;
9
11
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAIA,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAgB,GAAG,MAAM,CAGrG;AAED,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhD;AAID,+DAA+D;AAC/D,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,mGAAmG;AACnG,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAclF"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAIA,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAgB,GAAG,MAAM,CAGrG;AAED,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhD;AAID,+DAA+D;AAC/D,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,mGAAmG;AACnG,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAclF;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,SAAS,GAAG,MAAM,CAWzF"}
package/dist/paths.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { homedir } from 'node:os';
2
- import { isAbsolute, join, normalize as pathNormalize } from 'node:path';
2
+ import { isAbsolute, join, normalize as pathNormalize, relative, resolve } from 'node:path';
3
3
  import { canonicalizeName } from './names.js';
4
4
  /** Resolve adapter target base + skill name (project-relative or absolute global). */
5
5
  export function resolveAdapterTarget(basePath, skillName, cwd = process.cwd()) {
@@ -33,4 +33,17 @@ export function resolveCanonicalPath(canonicalPath, store) {
33
33
  }
34
34
  return join(storeRoot, canonicalPath);
35
35
  }
36
+ /** Resolve an untrusted relative path and require it to remain inside root. */
37
+ export function resolvePathInside(root, candidate, label = 'path') {
38
+ if (!candidate || isAbsolute(candidate)) {
39
+ throw new Error(`Unsafe ${label}: absolute or empty paths are not allowed`);
40
+ }
41
+ const rootAbs = resolve(root);
42
+ const result = resolve(rootAbs, candidate);
43
+ const rel = relative(rootAbs, result);
44
+ if (rel.startsWith('..') || isAbsolute(rel)) {
45
+ throw new Error(`Unsafe ${label}: path escapes its root (${candidate})`);
46
+ }
47
+ return result;
48
+ }
36
49
  //# sourceMappingURL=paths.js.map
package/dist/paths.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,SAAiB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3F,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC/E,OAAO,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,OAAO,EAAE,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAEpD,+DAA+D;AAC/D,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IAC1D,OAAO,GAAG,qBAAqB,GAAG,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,oBAAoB,CAAC,aAAqB,EAAE,KAAc;IACxE,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAElE,IAAI,aAAa,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,IAAI,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,SAAiB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3F,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC/E,OAAO,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,OAAO,EAAE,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAEpD,+DAA+D;AAC/D,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IAC1D,OAAO,GAAG,qBAAqB,GAAG,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,oBAAoB,CAAC,aAAqB,EAAE,KAAc;IACxE,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAElE,IAAI,aAAa,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACxC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,SAAiB,EAAE,KAAK,GAAG,MAAM;IAC/E,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,2CAA2C,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,4BAA4B,SAAS,GAAG,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -3,4 +3,6 @@ export declare function isPortableCanonicalPath(path: string): boolean;
3
3
  export declare function isPortableSpecifier(spec: string): boolean;
4
4
  /** Detect machine-local paths in manifest/lock that should be rewritten for git portability. */
5
5
  export declare function findPortablePathWarnings(lock: SkillLockfile, manifest?: SkillManifest | null): string[];
6
+ /** Detect legacy lock entries that cannot be restored deterministically on a new machine. */
7
+ export declare function findLockReproducibilityWarnings(lock: SkillLockfile): string[];
6
8
  //# sourceMappingURL=portable-lock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"portable-lock.d.ts","sourceRoot":"","sources":["../src/portable-lock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI9E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKzD;AAcD,gGAAgG;AAChG,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,aAAa,EACnB,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,GAC9B,MAAM,EAAE,CAiBV"}
1
+ {"version":3,"file":"portable-lock.d.ts","sourceRoot":"","sources":["../src/portable-lock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI9E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKzD;AAcD,gGAAgG;AAChG,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,aAAa,EACnB,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,GAC9B,MAAM,EAAE,CAoBV;AAKD,6FAA6F;AAC7F,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAoB7E"}
@@ -30,7 +30,10 @@ export function findPortablePathWarnings(lock, manifest) {
30
30
  checkEntry(name, 'resolved', entry.resolved, warnings);
31
31
  checkEntry(name, 'canonicalPath', entry.canonicalPath, warnings);
32
32
  }
33
- const deps = manifest?.agentSkills?.dependencies || {};
33
+ const deps = {
34
+ ...(manifest?.agentSkills?.dependencies || {}),
35
+ ...(manifest?.agentSkills?.devDependencies || {}),
36
+ };
34
37
  for (const [name, spec] of Object.entries(deps)) {
35
38
  if (!isPortableSpecifier(spec)) {
36
39
  warnings.push(`${name}: manifest specifier is not portable (${spec}) — run skillctl add/install to rewrite`);
@@ -38,4 +41,28 @@ export function findPortablePathWarnings(lock, manifest) {
38
41
  }
39
42
  return warnings;
40
43
  }
44
+ const FULL_COMMIT = /^[0-9a-f]{40}$/i;
45
+ const EXACT_NPM_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
46
+ /** Detect legacy lock entries that cannot be restored deterministically on a new machine. */
47
+ export function findLockReproducibilityWarnings(lock) {
48
+ const warnings = [];
49
+ for (const [name, entry] of Object.entries(lock.skills)) {
50
+ if (entry.provenance.type === 'github' || entry.provenance.type === 'skills.sh') {
51
+ const immutableResolved = /@[0-9a-f]{40}(?:#|\/|$)/i.test(entry.resolved);
52
+ if (!FULL_COMMIT.test(entry.provenance.commit || '') || !immutableResolved) {
53
+ warnings.push(`mutable-resolution: ${name} is not pinned to a full Git commit — run skillctl update ${name}`);
54
+ }
55
+ }
56
+ if (entry.provenance.type === 'npm') {
57
+ const version = entry.provenance.version || '';
58
+ if (!EXACT_NPM_VERSION.test(version) || !entry.provenance.tarballHash) {
59
+ warnings.push(`mutable-resolution: ${name} is missing an exact npm version or tarball integrity — run skillctl update ${name}`);
60
+ }
61
+ }
62
+ if (entry.specifier.startsWith('local:imported/')) {
63
+ warnings.push(`non-reproducible-local: ${name} requires its existing canonical imported copy`);
64
+ }
65
+ }
66
+ return warnings;
67
+ }
41
68
  //# sourceMappingURL=portable-lock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portable-lock.js","sourceRoot":"","sources":["../src/portable-lock.ts"],"names":[],"mappings":"AAEA,MAAM,yBAAyB,GAAG,qBAAqB,CAAC;AAExD,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,IAAI,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,KAAa,EAAE,KAAa,EAAE,QAAkB;IAChF,IAAI,KAAK,KAAK,eAAe,EAAE,CAAC;QAC9B,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,UAAU,KAAK,qBAAqB,KAAK,qCAAqC,CAAC,CAAC;QACvG,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,UAAU,KAAK,qBAAqB,KAAK,qCAAqC,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,wBAAwB,CACtC,IAAmB,EACnB,QAA+B;IAE/B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACzD,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvD,UAAU,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,EAAE,WAAW,EAAE,YAAY,IAAI,EAAE,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,yCAAyC,IAAI,yCAAyC,CAAC,CAAC;QAC/G,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"portable-lock.js","sourceRoot":"","sources":["../src/portable-lock.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -19,7 +19,10 @@ export interface ResolvedSkill {
19
19
  export interface Provenance {
20
20
  type: 'github' | 'npm' | 'local' | 'skills.sh' | 'other';
21
21
  commit?: string;
22
+ requestedRef?: string;
23
+ version?: string;
22
24
  tarballHash?: string;
25
+ tarballUrl?: string;
23
26
  subpath?: string;
24
27
  migratedFrom?: 'npx' | 'python-skillctl' | 'project-scan';
25
28
  originalHash?: string;
@@ -36,8 +39,10 @@ export interface AgentAdapter {
36
39
  detect(): Promise<boolean>;
37
40
  ensureTarget(skillName: string, targetPath: string, canonical: string, mode?: 'symlink' | 'copy' | 'junction', options?: {
38
41
  relative?: boolean;
42
+ dryRun?: boolean;
43
+ force?: boolean;
39
44
  }): Promise<void>;
40
- removeTarget(skillName: string, targetPath: string): Promise<void>;
45
+ removeTarget(skillName: string, targetPath: string, canonical?: string): Promise<void>;
41
46
  }
42
47
  export interface RegistrySource {
43
48
  readonly id: string;
@@ -60,6 +65,7 @@ export interface ResolvedSource {
60
65
  tarballHash?: string;
61
66
  gitUrl?: string;
62
67
  ref?: string;
68
+ requestedRef?: string;
63
69
  subpath?: string;
64
70
  localPath?: string;
65
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAuHH,4EAA4E;AAC5E,mFAAmF;AACnF,wEAAwE"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AA2HH,4EAA4E;AAC5E,mFAAmF;AACnF,wEAAwE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillctl/core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Core types, config, and FS utilities for skillctl",
5
5
  "license": "MIT",
6
6
  "author": "xFurti & Gabry848",
@@ -8,7 +8,8 @@
8
8
  "main": "./dist/index.js",
9
9
  "types": "./dist/index.d.ts",
10
10
  "files": [
11
- "dist"
11
+ "dist",
12
+ "!dist/test"
12
13
  ],
13
14
  "devDependencies": {
14
15
  "@types/node": "^20.14.0",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=normalize-specifier.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"normalize-specifier.test.d.ts","sourceRoot":"","sources":["../../src/test/normalize-specifier.test.ts"],"names":[],"mappings":""}
@@ -1,64 +0,0 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { mkdtemp, rm, mkdir, writeFile } from 'node:fs/promises';
4
- import { join } from 'node:path';
5
- import { tmpdir } from 'node:os';
6
- import { normalizeLocalSpecifier, portableSpecifierForResolved, formatCanonicalPathForLock, expandTilde, } from '../index.js';
7
- test('normalizeLocalSpecifier keeps file:./ in project', async () => {
8
- const root = await mkdtemp(join(tmpdir(), 'norm-spec-'));
9
- try {
10
- const skillDir = join(root, 'some-skill');
11
- await mkdir(skillDir, { recursive: true });
12
- await writeFile(join(skillDir, 'SKILL.md'), '---\nname: some-skill\n---\n');
13
- const rel = normalizeLocalSpecifier('file:./some-skill', root);
14
- assert.equal(rel.portable, 'file:./some-skill');
15
- assert.equal(rel.outsideProject, false);
16
- assert.ok(rel.absPath.endsWith('some-skill'));
17
- }
18
- finally {
19
- await rm(root, { recursive: true, force: true });
20
- }
21
- });
22
- test('normalizeLocalSpecifier rewrites abs-in-project to file:./', async () => {
23
- const root = await mkdtemp(join(tmpdir(), 'norm-spec-'));
24
- try {
25
- const skillDir = join(root, 'some-skill');
26
- await mkdir(skillDir, { recursive: true });
27
- await writeFile(join(skillDir, 'SKILL.md'), '---\nname: some-skill\n---\n');
28
- const absInProject = normalizeLocalSpecifier(`file:${skillDir}`, root);
29
- assert.equal(absInProject.portable, 'file:./some-skill');
30
- assert.equal(absInProject.outsideProject, false);
31
- }
32
- finally {
33
- await rm(root, { recursive: true, force: true });
34
- }
35
- });
36
- test('normalizeLocalSpecifier maps outside-project to local:imported', async () => {
37
- const root = await mkdtemp(join(tmpdir(), 'norm-spec-'));
38
- const outsideParent = await mkdtemp(join(tmpdir(), 'outside-parent-'));
39
- const outside = join(outsideParent, 'outside');
40
- try {
41
- await mkdir(outside, { recursive: true });
42
- await writeFile(join(outside, 'SKILL.md'), '---\nname: outside\n---\n');
43
- const out = normalizeLocalSpecifier(`file:${outside}`, root);
44
- assert.equal(out.portable, 'local:imported/outside');
45
- assert.equal(out.outsideProject, true);
46
- }
47
- finally {
48
- await rm(root, { recursive: true, force: true });
49
- await rm(outsideParent, { recursive: true, force: true });
50
- }
51
- });
52
- test('normalizeLocalSpecifier preserves local:imported', () => {
53
- const imported = normalizeLocalSpecifier('local:imported/my-skill', '/tmp');
54
- assert.equal(imported.portable, 'local:imported/my-skill');
55
- });
56
- test('portableSpecifierForResolved adds github: prefix', () => {
57
- const remote = portableSpecifierForResolved('acme/demo', { sourceType: 'github', resolved: 'github:acme/demo@HEAD' }, '/tmp');
58
- assert.equal(remote, 'github:acme/demo');
59
- });
60
- test('formatCanonicalPathForLock and expandTilde', () => {
61
- assert.equal(formatCanonicalPathForLock('My Skill'), '~/.skillctl/skills/my-skill');
62
- assert.ok(expandTilde('~/.skillctl/skills/foo').includes('.skillctl'));
63
- });
64
- //# sourceMappingURL=normalize-specifier.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"normalize-specifier.test.js","sourceRoot":"","sources":["../../src/test/normalize-specifier.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,EAC1B,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,IAAI,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;IAClE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC1C,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,8BAA8B,CAAC,CAAC;QAE5E,MAAM,GAAG,GAAG,uBAAuB,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;IAChD,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC5E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAC1C,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,8BAA8B,CAAC,CAAC;QAE5E,MAAM,YAAY,GAAG,uBAAuB,CAAC,QAAQ,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IAChF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,uBAAuB,CAAC,QAAQ,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAC5D,MAAM,QAAQ,GAAG,uBAAuB,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAAC;IAC5E,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAC5D,MAAM,MAAM,GAAG,4BAA4B,CACzC,WAAW,EACX,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,uBAAuB,EAAE,EAC3D,MAAM,CACP,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4CAA4C,EAAE,GAAG,EAAE;IACtD,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,UAAU,CAAC,EAAE,6BAA6B,CAAC,CAAC;IACpF,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;AACzE,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=operations.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"operations.test.d.ts","sourceRoot":"","sources":["../../src/test/operations.test.ts"],"names":[],"mappings":""}
@@ -1,72 +0,0 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
4
- import { join } from 'node:path';
5
- import { homedir } from 'node:os';
6
- import { tmpdir } from 'node:os';
7
- import { resolveCanonicalPath, formatCanonicalPathForLock, needsInstall, lockToSkillTargets, resolveEntryCanonicalPath, computeDirIntegrity, } from '../index.js';
8
- function makeEntry(overrides) {
9
- return {
10
- specifier: 'file:./skill',
11
- resolved: 'file:./skill',
12
- integrity: 'sha256:placeholder',
13
- canonicalPath: formatCanonicalPathForLock(overrides.name),
14
- fetchedAt: new Date().toISOString(),
15
- provenance: { type: 'local' },
16
- ...overrides,
17
- };
18
- }
19
- test('resolveCanonicalPath expands portable tilde store paths', () => {
20
- const customStore = join(homedir(), 'custom-skill-store');
21
- const portable = formatCanonicalPathForLock('demo-skill');
22
- const resolved = resolveCanonicalPath(portable, customStore);
23
- assert.equal(resolved, join(customStore, 'demo-skill'));
24
- });
25
- test('resolveCanonicalPath keeps legacy absolute paths', () => {
26
- const legacy = join(homedir(), '.skillctl', 'skills', 'legacy-skill');
27
- assert.equal(resolveCanonicalPath(legacy), legacy);
28
- });
29
- test('resolveEntryCanonicalPath falls back to store/name for legacy absolute lock paths', async () => {
30
- const store = await mkdtemp(join(tmpdir(), 'skillctl-store-'));
31
- const skillName = 'legacy-fallback';
32
- const skillDir = join(store, skillName);
33
- try {
34
- await mkdir(skillDir, { recursive: true });
35
- await writeFile(join(skillDir, 'SKILL.md'), '---\nname: legacy-fallback\n---\n');
36
- const otherMachinePath = join(homedir(), 'other-machine', '.skillctl', 'skills', skillName);
37
- const entry = makeEntry({
38
- name: skillName,
39
- canonicalPath: otherMachinePath,
40
- integrity: await computeDirIntegrity(skillDir),
41
- });
42
- const resolved = await resolveEntryCanonicalPath(entry, { store });
43
- assert.equal(resolved, skillDir);
44
- assert.equal(await needsInstall(entry, { store }), false);
45
- }
46
- finally {
47
- await rm(store, { recursive: true, force: true });
48
- }
49
- });
50
- test('lockToSkillTargets returns filesystem paths from portable lock entries', async () => {
51
- const store = await mkdtemp(join(tmpdir(), 'skillctl-store-'));
52
- const skillName = 'sync-target';
53
- const skillDir = join(store, skillName);
54
- try {
55
- await mkdir(skillDir, { recursive: true });
56
- await writeFile(join(skillDir, 'SKILL.md'), '---\nname: sync-target\n---\n');
57
- const integrity = await computeDirIntegrity(skillDir);
58
- const lock = {
59
- lockfileVersion: '1.0',
60
- skills: {
61
- [skillName]: makeEntry({ name: skillName, integrity }),
62
- },
63
- };
64
- const targets = await lockToSkillTargets(lock, { store });
65
- assert.equal(targets.length, 1);
66
- assert.equal(targets[0].canonicalPath, skillDir);
67
- }
68
- finally {
69
- await rm(store, { recursive: true, force: true });
70
- }
71
- });
72
- //# sourceMappingURL=operations.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"operations.test.js","sourceRoot":"","sources":["../../src/test/operations.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=portable-lock.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"portable-lock.test.d.ts","sourceRoot":"","sources":["../../src/test/portable-lock.test.ts"],"names":[],"mappings":""}
@@ -1,32 +0,0 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { isPortableSpecifier, isPortableCanonicalPath, findPortablePathWarnings, formatCanonicalPathForLock, } from '../index.js';
4
- test('isPortableSpecifier accepts remote and project-relative forms', () => {
5
- assert.equal(isPortableSpecifier('github:foo/bar'), true);
6
- assert.equal(isPortableSpecifier('file:./skills/foo'), true);
7
- assert.equal(isPortableSpecifier('local:imported/my-skill'), true);
8
- assert.equal(isPortableSpecifier('file:/Users/me/skill'), false);
9
- assert.equal(isPortableSpecifier('local:/Users/me/skill'), false);
10
- });
11
- test('isPortableCanonicalPath accepts tilde store paths only', () => {
12
- assert.equal(isPortableCanonicalPath(formatCanonicalPathForLock('demo')), true);
13
- assert.equal(isPortableCanonicalPath('/Users/me/.skillctl/skills/demo'), false);
14
- });
15
- test('findPortablePathWarnings flags legacy lock entries', () => {
16
- const warnings = findPortablePathWarnings({
17
- lockfileVersion: '1.0',
18
- skills: {
19
- demo: {
20
- specifier: 'file:/Users/me/project/skill',
21
- resolved: 'local:/Users/me/project/skill',
22
- integrity: 'sha256:abc',
23
- name: 'demo',
24
- canonicalPath: '/Users/me/.skillctl/skills/demo',
25
- fetchedAt: '2026-01-01T00:00:00.000Z',
26
- provenance: { type: 'local' },
27
- },
28
- },
29
- });
30
- assert.equal(warnings.length, 3);
31
- });
32
- //# sourceMappingURL=portable-lock.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"portable-lock.test.js","sourceRoot":"","sources":["../../src/test/portable-lock.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAErB,IAAI,CAAC,+DAA+D,EAAE,GAAG,EAAE;IACzE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7D,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,yBAAyB,CAAC,EAAE,IAAI,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,sBAAsB,CAAC,EAAE,KAAK,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,EAAE,KAAK,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wDAAwD,EAAE,GAAG,EAAE;IAClE,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAChF,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,iCAAiC,CAAC,EAAE,KAAK,CAAC,CAAC;AAClF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAC9D,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QACxC,eAAe,EAAE,KAAK;QACtB,MAAM,EAAE;YACN,IAAI,EAAE;gBACJ,SAAS,EAAE,8BAA8B;gBACzC,QAAQ,EAAE,+BAA+B;gBACzC,SAAS,EAAE,YAAY;gBACvB,IAAI,EAAE,MAAM;gBACZ,aAAa,EAAE,iCAAiC;gBAChD,SAAS,EAAE,0BAA0B;gBACrC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;aAC9B;SACF;KACF,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC"}