skyl.dev 0.1.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 (139) hide show
  1. package/bundle.json +1 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +4 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +158 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/add.d.ts +10 -0
  11. package/dist/commands/add.d.ts.map +1 -0
  12. package/dist/commands/add.js +38 -0
  13. package/dist/commands/add.js.map +1 -0
  14. package/dist/commands/audit.d.ts +16 -0
  15. package/dist/commands/audit.d.ts.map +1 -0
  16. package/dist/commands/audit.js +91 -0
  17. package/dist/commands/audit.js.map +1 -0
  18. package/dist/commands/context.d.ts +17 -0
  19. package/dist/commands/context.d.ts.map +1 -0
  20. package/dist/commands/context.js +47 -0
  21. package/dist/commands/context.js.map +1 -0
  22. package/dist/commands/diff.d.ts +12 -0
  23. package/dist/commands/diff.d.ts.map +1 -0
  24. package/dist/commands/diff.js +79 -0
  25. package/dist/commands/diff.js.map +1 -0
  26. package/dist/commands/learn.d.ts +18 -0
  27. package/dist/commands/learn.d.ts.map +1 -0
  28. package/dist/commands/learn.js +115 -0
  29. package/dist/commands/learn.js.map +1 -0
  30. package/dist/commands/lint.d.ts +14 -0
  31. package/dist/commands/lint.d.ts.map +1 -0
  32. package/dist/commands/lint.js +109 -0
  33. package/dist/commands/lint.js.map +1 -0
  34. package/dist/commands/list.d.ts +6 -0
  35. package/dist/commands/list.d.ts.map +1 -0
  36. package/dist/commands/list.js +60 -0
  37. package/dist/commands/list.js.map +1 -0
  38. package/dist/commands/remove.d.ts +16 -0
  39. package/dist/commands/remove.d.ts.map +1 -0
  40. package/dist/commands/remove.js +73 -0
  41. package/dist/commands/remove.js.map +1 -0
  42. package/dist/commands/scan.d.ts +10 -0
  43. package/dist/commands/scan.d.ts.map +1 -0
  44. package/dist/commands/scan.js +60 -0
  45. package/dist/commands/scan.js.map +1 -0
  46. package/dist/commands/update.d.ts +11 -0
  47. package/dist/commands/update.d.ts.map +1 -0
  48. package/dist/commands/update.js +135 -0
  49. package/dist/commands/update.js.map +1 -0
  50. package/dist/context.d.ts +44 -0
  51. package/dist/context.d.ts.map +1 -0
  52. package/dist/context.js +179 -0
  53. package/dist/context.js.map +1 -0
  54. package/dist/ignore.d.ts +21 -0
  55. package/dist/ignore.d.ts.map +1 -0
  56. package/dist/ignore.js +79 -0
  57. package/dist/ignore.js.map +1 -0
  58. package/dist/install.d.ts +10 -0
  59. package/dist/install.d.ts.map +1 -0
  60. package/dist/install.js +54 -0
  61. package/dist/install.js.map +1 -0
  62. package/dist/learn.d.ts +45 -0
  63. package/dist/learn.d.ts.map +1 -0
  64. package/dist/learn.js +146 -0
  65. package/dist/learn.js.map +1 -0
  66. package/dist/registry.d.ts +23 -0
  67. package/dist/registry.d.ts.map +1 -0
  68. package/dist/registry.js +38 -0
  69. package/dist/registry.js.map +1 -0
  70. package/dist/scan.d.ts +3 -0
  71. package/dist/scan.d.ts.map +1 -0
  72. package/dist/scan.js +104 -0
  73. package/dist/scan.js.map +1 -0
  74. package/dist/state.d.ts +31 -0
  75. package/dist/state.d.ts.map +1 -0
  76. package/dist/state.js +39 -0
  77. package/dist/state.js.map +1 -0
  78. package/dist/ui.d.ts +17 -0
  79. package/dist/ui.d.ts.map +1 -0
  80. package/dist/ui.js +35 -0
  81. package/dist/ui.js.map +1 -0
  82. package/node_modules/@skyl/core/dist/audit.d.ts +48 -0
  83. package/node_modules/@skyl/core/dist/audit.d.ts.map +1 -0
  84. package/node_modules/@skyl/core/dist/audit.js +99 -0
  85. package/node_modules/@skyl/core/dist/audit.js.map +1 -0
  86. package/node_modules/@skyl/core/dist/detect.d.ts +15 -0
  87. package/node_modules/@skyl/core/dist/detect.d.ts.map +1 -0
  88. package/node_modules/@skyl/core/dist/detect.js +62 -0
  89. package/node_modules/@skyl/core/dist/detect.js.map +1 -0
  90. package/node_modules/@skyl/core/dist/diff.d.ts +32 -0
  91. package/node_modules/@skyl/core/dist/diff.d.ts.map +1 -0
  92. package/node_modules/@skyl/core/dist/diff.js +119 -0
  93. package/node_modules/@skyl/core/dist/diff.js.map +1 -0
  94. package/node_modules/@skyl/core/dist/errors.d.ts +21 -0
  95. package/node_modules/@skyl/core/dist/errors.d.ts.map +1 -0
  96. package/node_modules/@skyl/core/dist/errors.js +25 -0
  97. package/node_modules/@skyl/core/dist/errors.js.map +1 -0
  98. package/node_modules/@skyl/core/dist/index.d.ts +14 -0
  99. package/node_modules/@skyl/core/dist/index.d.ts.map +1 -0
  100. package/node_modules/@skyl/core/dist/index.js +14 -0
  101. package/node_modules/@skyl/core/dist/index.js.map +1 -0
  102. package/node_modules/@skyl/core/dist/lint.d.ts +28 -0
  103. package/node_modules/@skyl/core/dist/lint.d.ts.map +1 -0
  104. package/node_modules/@skyl/core/dist/lint.js +169 -0
  105. package/node_modules/@skyl/core/dist/lint.js.map +1 -0
  106. package/node_modules/@skyl/core/dist/lockfile.d.ts +37 -0
  107. package/node_modules/@skyl/core/dist/lockfile.d.ts.map +1 -0
  108. package/node_modules/@skyl/core/dist/lockfile.js +47 -0
  109. package/node_modules/@skyl/core/dist/lockfile.js.map +1 -0
  110. package/node_modules/@skyl/core/dist/match.d.ts +19 -0
  111. package/node_modules/@skyl/core/dist/match.d.ts.map +1 -0
  112. package/node_modules/@skyl/core/dist/match.js +72 -0
  113. package/node_modules/@skyl/core/dist/match.js.map +1 -0
  114. package/node_modules/@skyl/core/dist/names.d.ts +11 -0
  115. package/node_modules/@skyl/core/dist/names.d.ts.map +1 -0
  116. package/node_modules/@skyl/core/dist/names.js +31 -0
  117. package/node_modules/@skyl/core/dist/names.js.map +1 -0
  118. package/node_modules/@skyl/core/dist/parse.d.ts +22 -0
  119. package/node_modules/@skyl/core/dist/parse.d.ts.map +1 -0
  120. package/node_modules/@skyl/core/dist/parse.js +163 -0
  121. package/node_modules/@skyl/core/dist/parse.js.map +1 -0
  122. package/node_modules/@skyl/core/dist/resolve.d.ts +12 -0
  123. package/node_modules/@skyl/core/dist/resolve.d.ts.map +1 -0
  124. package/node_modules/@skyl/core/dist/resolve.js +40 -0
  125. package/node_modules/@skyl/core/dist/resolve.js.map +1 -0
  126. package/node_modules/@skyl/core/dist/source.d.ts +35 -0
  127. package/node_modules/@skyl/core/dist/source.d.ts.map +1 -0
  128. package/node_modules/@skyl/core/dist/source.js +85 -0
  129. package/node_modules/@skyl/core/dist/source.js.map +1 -0
  130. package/node_modules/@skyl/core/dist/targets.d.ts +20 -0
  131. package/node_modules/@skyl/core/dist/targets.d.ts.map +1 -0
  132. package/node_modules/@skyl/core/dist/targets.js +24 -0
  133. package/node_modules/@skyl/core/dist/targets.js.map +1 -0
  134. package/node_modules/@skyl/core/dist/types.d.ts +51 -0
  135. package/node_modules/@skyl/core/dist/types.d.ts.map +1 -0
  136. package/node_modules/@skyl/core/dist/types.js +2 -0
  137. package/node_modules/@skyl/core/dist/types.js.map +1 -0
  138. package/node_modules/@skyl/core/package.json +20 -0
  139. package/package.json +43 -0
@@ -0,0 +1,47 @@
1
+ import { createHash } from 'node:crypto';
2
+ export const LOCKFILE_NAME = 'skyl.lock';
3
+ export function hashContent(text) {
4
+ return `sha256:${createHash('sha256').update(text, 'utf8').digest('hex')}`;
5
+ }
6
+ export function emptyLockfile(target) {
7
+ return { lockfileVersion: 1, target, skills: {} };
8
+ }
9
+ export function parseLockfile(text) {
10
+ const data = JSON.parse(text);
11
+ if (data.lockfileVersion !== 1) {
12
+ throw new Error(`unsupported lockfile version ${String(data.lockfileVersion)}`);
13
+ }
14
+ return data;
15
+ }
16
+ /** Serialised with sorted keys so a reinstall produces no diff. */
17
+ export function formatLockfile(lock) {
18
+ const skills = {};
19
+ for (const name of Object.keys(lock.skills).sort())
20
+ skills[name] = lock.skills[name];
21
+ const ordered = { lockfileVersion: lock.lockfileVersion, target: lock.target, ...(lock.source ? { source: lock.source } : {}), skills };
22
+ return `${JSON.stringify(ordered, null, 2)}\n`;
23
+ }
24
+ export function entryFor(skill, installed, reason) {
25
+ return { version: skill.version, hash: hashContent(installed), reason };
26
+ }
27
+ /**
28
+ * What happened to an installed skill.
29
+ *
30
+ * `local-edit` and `upstream-change` are told apart because the fix differs: one is the
31
+ * user's work to keep, the other is ours to offer. When both moved, neither can be
32
+ * applied blindly.
33
+ */
34
+ export function drift(entry, onDisk, upstream) {
35
+ if (!entry || onDisk === undefined)
36
+ return 'missing';
37
+ const localChanged = hashContent(onDisk) !== entry.hash;
38
+ const upstreamChanged = upstream !== undefined && upstream.version !== entry.version;
39
+ if (localChanged && upstreamChanged)
40
+ return 'both';
41
+ if (localChanged)
42
+ return 'local-edit';
43
+ if (upstreamChanged)
44
+ return 'upstream-change';
45
+ return 'unchanged';
46
+ }
47
+ //# sourceMappingURL=lockfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAwBzC,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AAEzC,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,UAAU,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC;IAC1C,IAAI,IAAI,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC;IACtF,MAAM,OAAO,GAAG,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACxI,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAY,EAAE,SAAiB,EAAE,MAA2B;IACnF,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;AAC1E,CAAC;AAID;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CACnB,KAA4B,EAC5B,MAA0B,EAC1B,QAA2B;IAE3B,IAAI,CAAC,KAAK,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACrD,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC;IACxD,MAAM,eAAe,GAAG,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC;IACrF,IAAI,YAAY,IAAI,eAAe;QAAE,OAAO,MAAM,CAAC;IACnD,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IACtC,IAAI,eAAe;QAAE,OAAO,iBAAiB,CAAC;IAC9C,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * How a wanted value is compared against a signal, chosen by the shape of the detect key.
3
+ *
4
+ * Substring matching everywhere looked simpler and is wrong in both directions:
5
+ *
6
+ * - `androidx.compose.ui:ui-test-junit4` contains `androidx.compose.ui:ui`, so a
7
+ * project with only Compose test helpers would pull the whole Compose skill.
8
+ * - a file pattern is a glob, and `app/src/main/Main.kt` does not contain the literal
9
+ * text `**` + `/*.kt`, so file detection never fired at all.
10
+ */
11
+ /**
12
+ * A detect key's matching strategy. Unknown keys fall back to exact comparison, which
13
+ * fails closed: a new key matches nothing until it is taught how, rather than matching
14
+ * everything by accident.
15
+ */
16
+ export type Strategy = 'coordinate' | 'glob' | 'exact';
17
+ export declare function strategyFor(key: string): Strategy;
18
+ export declare function matches(key: string, wanted: string, signal: string): boolean;
19
+ //# sourceMappingURL=match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../src/match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAmCH;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC;AAEvD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAIjD;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAS5E"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * How a wanted value is compared against a signal, chosen by the shape of the detect key.
3
+ *
4
+ * Substring matching everywhere looked simpler and is wrong in both directions:
5
+ *
6
+ * - `androidx.compose.ui:ui-test-junit4` contains `androidx.compose.ui:ui`, so a
7
+ * project with only Compose test helpers would pull the whole Compose skill.
8
+ * - a file pattern is a glob, and `app/src/main/Main.kt` does not contain the literal
9
+ * text `**` + `/*.kt`, so file detection never fired at all.
10
+ */
11
+ /** `group:artifact:version` reduced to `group:artifact`, which is the identity. */
12
+ function coordinate(value) {
13
+ const parts = value.split(':');
14
+ return parts.length >= 2 ? `${parts[0]}:${parts[1]}` : value;
15
+ }
16
+ function globToRegExp(glob) {
17
+ let out = '';
18
+ for (let i = 0; i < glob.length; i += 1) {
19
+ const c = glob[i];
20
+ if (c === '*') {
21
+ if (glob[i + 1] === '*') {
22
+ // `**/` spans directories, and also matches nothing so `**/*.kt` hits `a.kt`
23
+ if (glob[i + 2] === '/') {
24
+ out += '(?:.*/)?';
25
+ i += 2;
26
+ }
27
+ else {
28
+ out += '.*';
29
+ i += 1;
30
+ }
31
+ }
32
+ else {
33
+ out += '[^/]*';
34
+ }
35
+ }
36
+ else if (c === '?')
37
+ out += '[^/]';
38
+ else if ('.+^${}()|[]\\'.includes(c))
39
+ out += `\\${c}`;
40
+ else
41
+ out += c;
42
+ }
43
+ return new RegExp(`^${out}$`);
44
+ }
45
+ const globCache = new Map();
46
+ function globMatch(pattern, path) {
47
+ let re = globCache.get(pattern);
48
+ if (!re) {
49
+ re = globToRegExp(pattern);
50
+ globCache.set(pattern, re);
51
+ }
52
+ const normalised = path.replace(/^\.\//, '').replace(/\\/g, '/');
53
+ return re.test(normalised) || re.test(`./${normalised}`.slice(2));
54
+ }
55
+ export function strategyFor(key) {
56
+ if (key.endsWith('dependency') || key.endsWith('dependencies'))
57
+ return 'coordinate';
58
+ if (key === 'file' || key.endsWith('_file') || key.endsWith('path'))
59
+ return 'glob';
60
+ return 'exact';
61
+ }
62
+ export function matches(key, wanted, signal) {
63
+ switch (strategyFor(key)) {
64
+ case 'coordinate':
65
+ return coordinate(signal) === coordinate(wanted);
66
+ case 'glob':
67
+ return globMatch(wanted, signal);
68
+ case 'exact':
69
+ return signal === wanted || signal.includes(wanted);
70
+ }
71
+ }
72
+ //# sourceMappingURL=match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match.js","sourceRoot":"","sources":["../src/match.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { SkillMeta } from './types.ts';
2
+ /**
3
+ * Accept `android/kotlin` and bare `kotlin`, because typing the family once is the
4
+ * natural way to ask: `skyl add android/core kotlin compose`.
5
+ *
6
+ * A bare name resolves against the families already named in the same request, then
7
+ * against the whole index. Ambiguity is an error rather than a guess: silently picking
8
+ * one of two families would install the wrong thing and look like it worked.
9
+ */
10
+ export declare function normalise(skills: readonly SkillMeta[], requested: readonly string[]): string[];
11
+ //# sourceMappingURL=names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAuB9F"}
@@ -0,0 +1,31 @@
1
+ import { ResolutionError } from "./errors.js";
2
+ /**
3
+ * Accept `android/kotlin` and bare `kotlin`, because typing the family once is the
4
+ * natural way to ask: `skyl add android/core kotlin compose`.
5
+ *
6
+ * A bare name resolves against the families already named in the same request, then
7
+ * against the whole index. Ambiguity is an error rather than a guess: silently picking
8
+ * one of two families would install the wrong thing and look like it worked.
9
+ */
10
+ export function normalise(skills, requested) {
11
+ const known = new Set(skills.map((s) => s.name));
12
+ const families = new Set(requested.filter((r) => r.includes('/')).map((r) => r.split('/')[0]));
13
+ return requested.map((raw) => {
14
+ const name = raw.trim();
15
+ if (name.includes('/')) {
16
+ if (!known.has(name))
17
+ throw new ResolutionError(`unknown skill \`${name}\``);
18
+ return name;
19
+ }
20
+ const inNamedFamily = skills.filter((s) => families.has(s.family) && s.skill === name);
21
+ if (inNamedFamily.length === 1)
22
+ return inNamedFamily[0].name;
23
+ const anywhere = skills.filter((s) => s.skill === name);
24
+ if (anywhere.length === 1)
25
+ return anywhere[0].name;
26
+ if (anywhere.length === 0)
27
+ throw new ResolutionError(`unknown skill \`${name}\``);
28
+ throw new ResolutionError(`\`${name}\` is ambiguous`, `it exists in ${anywhere.map((s) => s.family).join(', ')}. Name the family.`);
29
+ });
30
+ }
31
+ //# sourceMappingURL=names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"names.js","sourceRoot":"","sources":["../src/names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,MAA4B,EAAE,SAA4B;IAClF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;IAEhG,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,eAAe,CAAC,mBAAmB,IAAI,IAAI,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;QACvF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,aAAa,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC;QAE9D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;QACxD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC;QACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,eAAe,CAAC,mBAAmB,IAAI,IAAI,CAAC,CAAC;QAElF,MAAM,IAAI,eAAe,CACvB,KAAK,IAAI,iBAAiB,EAC1B,gBAAgB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAC7E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type Rule, type Skill } from './types.ts';
2
+ /**
3
+ * The frontmatter shapes this format uses: scalars, inline arrays, and one level of
4
+ * nested map-of-arrays for `detect`. Parsed here rather than with a YAML library so
5
+ * `@skyl/core` stays dependency-free, and because accepting only these shapes means a
6
+ * malformed skill fails loudly instead of parsing into something surprising.
7
+ */
8
+ type Scalar = string;
9
+ type FrontmatterValue = Scalar | string[] | Record<string, string[]>;
10
+ export declare function parseFrontmatter(text: string): Record<string, FrontmatterValue>;
11
+ /** Everything after the frontmatter. */
12
+ export declare function body(text: string): string;
13
+ /**
14
+ * Split a markdown body into its `##` sections, keyed by heading text.
15
+ * Content before the first heading is dropped: the format puts nothing there.
16
+ */
17
+ export declare function sections(markdown: string): Map<string, string>;
18
+ export declare function rules(markdown: string): Rule[];
19
+ /** Parse one SKILL.md into the shape everything else in this package consumes. */
20
+ export declare function parseSkill(text: string): Skill;
21
+ export {};
22
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,KAAK,IAAI,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtF;;;;;GAKG;AACH,KAAK,MAAM,GAAG,MAAM,CAAC;AACrB,KAAK,gBAAgB,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAkBrE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAiD/E;AAED,wCAAwC;AACxC,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAO9D;AAID,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,CAM9C;AAiBD,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CA6D9C"}
@@ -0,0 +1,163 @@
1
+ import { SkillFormatError } from "./errors.js";
2
+ import { AXES } from "./types.js";
3
+ const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
4
+ function stripQuotes(v) {
5
+ const t = v.trim();
6
+ if (t.length >= 2 && ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'")))) {
7
+ return t.slice(1, -1);
8
+ }
9
+ return t;
10
+ }
11
+ function inlineList(v) {
12
+ const inner = v.trim().slice(1, -1).trim();
13
+ if (inner === '')
14
+ return [];
15
+ return inner.split(',').map(stripQuotes).filter((s) => s !== '');
16
+ }
17
+ export function parseFrontmatter(text) {
18
+ const m = FRONTMATTER.exec(text);
19
+ if (!m)
20
+ throw new SkillFormatError('no frontmatter', 'a skill starts with a --- delimited block');
21
+ const out = {};
22
+ const lines = m[1].split('\n');
23
+ let currentKey = null;
24
+ let currentSub = null;
25
+ for (const raw of lines) {
26
+ if (raw.trim() === '' || raw.trimStart().startsWith('#'))
27
+ continue;
28
+ const top = /^([A-Za-z_][\w-]*):\s*(.*)$/.exec(raw);
29
+ if (top && !/^\s/.test(raw)) {
30
+ const [, key, rest] = top;
31
+ currentKey = key;
32
+ currentSub = null;
33
+ const value = rest.trim();
34
+ if (value === '')
35
+ out[key] = {};
36
+ else if (value.startsWith('['))
37
+ out[key] = inlineList(value);
38
+ else
39
+ out[key] = stripQuotes(value);
40
+ continue;
41
+ }
42
+ const nested = /^\s+([A-Za-z_][\w-]*):\s*(.*)$/.exec(raw);
43
+ if (nested && currentKey) {
44
+ const [, sub, rest] = nested;
45
+ const bucket = (out[currentKey] ??= {});
46
+ if (typeof bucket !== 'object' || Array.isArray(bucket)) {
47
+ throw new SkillFormatError(`\`${currentKey}\` has both a value and nested keys`);
48
+ }
49
+ const value = rest.trim();
50
+ bucket[sub] = value.startsWith('[') ? inlineList(value) : value === '' ? [] : [stripQuotes(value)];
51
+ currentSub = sub;
52
+ continue;
53
+ }
54
+ const item = /^\s*-\s+(.*)$/.exec(raw);
55
+ if (item && currentKey) {
56
+ const value = stripQuotes(item[1]);
57
+ const bucket = out[currentKey];
58
+ if (Array.isArray(bucket))
59
+ bucket.push(value);
60
+ else if (currentSub && bucket && typeof bucket === 'object') {
61
+ (bucket[currentSub] ??= []).push(value);
62
+ }
63
+ else
64
+ out[currentKey] = [value];
65
+ continue;
66
+ }
67
+ }
68
+ return out;
69
+ }
70
+ /** Everything after the frontmatter. */
71
+ export function body(text) {
72
+ const m = FRONTMATTER.exec(text);
73
+ return m ? text.slice(m[0].length) : text;
74
+ }
75
+ /**
76
+ * Split a markdown body into its `##` sections, keyed by heading text.
77
+ * Content before the first heading is dropped: the format puts nothing there.
78
+ */
79
+ export function sections(markdown) {
80
+ const out = new Map();
81
+ const parts = markdown.split(/^## (.+)$/m);
82
+ for (let i = 1; i < parts.length; i += 2) {
83
+ out.set(parts[i].trim(), (parts[i + 1] ?? '').trim());
84
+ }
85
+ return out;
86
+ }
87
+ const RULE = /^- \*\*([A-Z0-9]+-\d+)\*\*\s+`(must|should)`/gm;
88
+ export function rules(markdown) {
89
+ const out = [];
90
+ for (const m of markdown.matchAll(RULE)) {
91
+ out.push({ id: m[1], priority: m[2] });
92
+ }
93
+ return out;
94
+ }
95
+ function requireString(fm, key) {
96
+ const v = fm[key];
97
+ if (typeof v !== 'string' || v === '') {
98
+ throw new SkillFormatError(`frontmatter is missing \`${key}\``);
99
+ }
100
+ return v;
101
+ }
102
+ function list(fm, key) {
103
+ const v = fm[key];
104
+ if (v === undefined)
105
+ return [];
106
+ if (Array.isArray(v))
107
+ return v;
108
+ throw new SkillFormatError(`\`${key}\` must be a list`);
109
+ }
110
+ /** Parse one SKILL.md into the shape everything else in this package consumes. */
111
+ export function parseSkill(text) {
112
+ const fm = parseFrontmatter(text);
113
+ const md = body(text);
114
+ const name = requireString(fm, 'name');
115
+ const slash = name.indexOf('/');
116
+ if (slash <= 0 || slash === name.length - 1) {
117
+ throw new SkillFormatError(`name \`${name}\` is not \`family/skill\``);
118
+ }
119
+ const axis = requireString(fm, 'axis');
120
+ if (!AXES.includes(axis)) {
121
+ throw new SkillFormatError(`axis \`${axis}\` is not one of ${AXES.join(', ')}`);
122
+ }
123
+ const version = requireString(fm, 'version');
124
+ if (!/^\d+\.\d+\.\d+$/.test(version)) {
125
+ throw new SkillFormatError(`version \`${version}\` is not semver`);
126
+ }
127
+ const agentSections = list(fm, 'agent_sections');
128
+ if (agentSections.length === 0) {
129
+ throw new SkillFormatError('frontmatter is missing `agent_sections`', 'nothing would be installed');
130
+ }
131
+ const detectRaw = fm['detect'];
132
+ const detect = detectRaw && typeof detectRaw === 'object' && !Array.isArray(detectRaw)
133
+ ? detectRaw
134
+ : {};
135
+ const all = sections(md);
136
+ const installable = agentSections
137
+ .map((s) => {
138
+ const heading = s.charAt(0).toUpperCase() + s.slice(1);
139
+ const found = all.get(heading) ?? all.get(s);
140
+ if (found === undefined) {
141
+ throw new SkillFormatError(`\`agent_sections\` names \`${s}\` but the file has no \`## ${heading}\``);
142
+ }
143
+ return `## ${heading}\n\n${found}`;
144
+ })
145
+ .join('\n\n');
146
+ return {
147
+ name,
148
+ family: name.slice(0, slash),
149
+ skill: name.slice(slash + 1),
150
+ axis: axis,
151
+ version,
152
+ requires: list(fm, 'requires'),
153
+ agentSections,
154
+ retired: list(fm, 'retired'),
155
+ detect,
156
+ authors: list(fm, 'authors'),
157
+ rules: rules(md),
158
+ installable,
159
+ installableWords: installable.split(/\s+/).filter(Boolean).length,
160
+ raw: text,
161
+ };
162
+ }
163
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SkillMeta } from './types.ts';
2
+ /**
3
+ * Expand a requested set to include everything it requires, and order it so a skill
4
+ * always appears after what it depends on.
5
+ *
6
+ * Install order matters: `agent_sections` are concatenated in the order written, and a
7
+ * layer that refers to its core reads wrong if it lands first.
8
+ */
9
+ export declare function resolve<T extends SkillMeta>(skills: readonly T[], requested: readonly string[]): T[];
10
+ /** What `resolve` added that the caller did not ask for, so a prompt can say so. */
11
+ export declare function implied<T extends SkillMeta>(resolved: readonly T[], requested: readonly string[]): T[];
12
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,EAAE,CAkCpG;AAED,oFAAoF;AACpF,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,EAAE,CAGtG"}
@@ -0,0 +1,40 @@
1
+ import { ResolutionError } from "./errors.js";
2
+ /**
3
+ * Expand a requested set to include everything it requires, and order it so a skill
4
+ * always appears after what it depends on.
5
+ *
6
+ * Install order matters: `agent_sections` are concatenated in the order written, and a
7
+ * layer that refers to its core reads wrong if it lands first.
8
+ */
9
+ export function resolve(skills, requested) {
10
+ const byName = new Map(skills.map((s) => [s.name, s]));
11
+ const ordered = [];
12
+ const done = new Set();
13
+ const path = [];
14
+ const visit = (name, from) => {
15
+ if (done.has(name))
16
+ return;
17
+ if (path.includes(name)) {
18
+ throw new ResolutionError('skills require each other in a cycle', [...path.slice(path.indexOf(name)), name].join(' -> '));
19
+ }
20
+ const skill = byName.get(name);
21
+ if (!skill) {
22
+ throw new ResolutionError(`unknown skill \`${name}\``, from ? `required by \`${from}\`` : 'not in the index');
23
+ }
24
+ path.push(name);
25
+ for (const dep of skill.requires)
26
+ visit(dep, name);
27
+ path.pop();
28
+ done.add(name);
29
+ ordered.push(skill);
30
+ };
31
+ for (const name of requested)
32
+ visit(name);
33
+ return ordered;
34
+ }
35
+ /** What `resolve` added that the caller did not ask for, so a prompt can say so. */
36
+ export function implied(resolved, requested) {
37
+ const asked = new Set(requested);
38
+ return resolved.filter((s) => !asked.has(s.name));
39
+ }
40
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAsB,MAAoB,EAAE,SAA4B;IAC7F,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,OAAO,GAAQ,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,IAAa,EAAQ,EAAE;QAClD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAE3B,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,eAAe,CACvB,sCAAsC,EACtC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CACvD,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,eAAe,CACvB,mBAAmB,IAAI,IAAI,EAC3B,IAAI,CAAC,CAAC,CAAC,iBAAiB,IAAI,IAAI,CAAC,CAAC,CAAC,kBAAkB,CACtD,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ;YAAE,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,EAAE,CAAC;QAEX,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,OAAO,CAAsB,QAAsB,EAAE,SAA4B;IAC/F,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { Skill } from './types.ts';
2
+ /**
3
+ * Where skill content comes from.
4
+ *
5
+ * Three routes, tried in order, because each fails in a different way: a bundle shipped
6
+ * inside the package always works and goes stale, a fetched artifact is current and needs
7
+ * a network, and a local directory is what a contributor is editing. Resolution order is
8
+ * configuration rather than something baked into the CLI.
9
+ */
10
+ export interface Source {
11
+ readonly name: string;
12
+ /** Every skill this source can supply. */
13
+ load(): Promise<Skill[]>;
14
+ }
15
+ /** A directory laid out as `<root>/<family>/<skill>/SKILL.md`. */
16
+ export declare function directorySource(root: string, label?: string): Source;
17
+ /** A JSON bundle: `{ "skills": { "android/core": "<raw SKILL.md>" } }`. */
18
+ export interface Bundle {
19
+ readonly version?: string;
20
+ readonly skills: Record<string, string>;
21
+ }
22
+ export declare function bundleSource(load: () => Promise<Bundle>, label: string): Source;
23
+ export declare function httpBundleSource(url: string, label?: string): Source;
24
+ /**
25
+ * Try sources in order and take the first that yields anything.
26
+ *
27
+ * Failures are collected rather than thrown as they happen: falling back from a network
28
+ * source to a bundled one is the normal path, not an error, and a caller only needs to
29
+ * hear about it when every route failed.
30
+ */
31
+ export declare function firstAvailable(sources: readonly Source[]): Promise<{
32
+ skills: Skill[];
33
+ from: Source;
34
+ }>;
35
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;CAC1B;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAc,GAAG,MAAM,CAiCzE;AAED,2EAA2E;AAC3E,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAc/E;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,MAAM,CAMtE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAY3G"}
@@ -0,0 +1,85 @@
1
+ import { SourceError } from "./errors.js";
2
+ import { parseSkill } from "./parse.js";
3
+ /** A directory laid out as `<root>/<family>/<skill>/SKILL.md`. */
4
+ export function directorySource(root, label = 'directory') {
5
+ return {
6
+ name: `${label} (${root})`,
7
+ async load() {
8
+ const { readdir, readFile } = await import('node:fs/promises');
9
+ const { join } = await import('node:path');
10
+ const out = [];
11
+ let families;
12
+ try {
13
+ families = (await readdir(root, { withFileTypes: true }))
14
+ .filter((e) => e.isDirectory())
15
+ .map((e) => e.name);
16
+ }
17
+ catch (cause) {
18
+ throw new SourceError(`cannot read ${root}`, String(cause));
19
+ }
20
+ for (const family of families) {
21
+ const dir = join(root, family);
22
+ const entries = (await readdir(dir, { withFileTypes: true })).filter((e) => e.isDirectory());
23
+ for (const entry of entries) {
24
+ const file = join(dir, entry.name, 'SKILL.md');
25
+ try {
26
+ out.push(parseSkill(await readFile(file, 'utf8')));
27
+ }
28
+ catch (cause) {
29
+ if (cause.code === 'ENOENT')
30
+ continue;
31
+ throw new SourceError(`cannot parse ${file}`, cause.message);
32
+ }
33
+ }
34
+ }
35
+ return out;
36
+ },
37
+ };
38
+ }
39
+ export function bundleSource(load, label) {
40
+ return {
41
+ name: label,
42
+ async load() {
43
+ const bundle = await load();
44
+ return Object.entries(bundle.skills).map(([name, raw]) => {
45
+ try {
46
+ return parseSkill(raw);
47
+ }
48
+ catch (cause) {
49
+ throw new SourceError(`cannot parse \`${name}\` from ${label}`, cause.message);
50
+ }
51
+ });
52
+ },
53
+ };
54
+ }
55
+ export function httpBundleSource(url, label = 'remote') {
56
+ return bundleSource(async () => {
57
+ const res = await fetch(url, { headers: { accept: 'application/json' } });
58
+ if (!res.ok)
59
+ throw new SourceError(`${label} returned ${res.status}`, url);
60
+ return (await res.json());
61
+ }, `${label} (${url})`);
62
+ }
63
+ /**
64
+ * Try sources in order and take the first that yields anything.
65
+ *
66
+ * Failures are collected rather than thrown as they happen: falling back from a network
67
+ * source to a bundled one is the normal path, not an error, and a caller only needs to
68
+ * hear about it when every route failed.
69
+ */
70
+ export async function firstAvailable(sources) {
71
+ const failures = [];
72
+ for (const source of sources) {
73
+ try {
74
+ const skills = await source.load();
75
+ if (skills.length > 0)
76
+ return { skills, from: source };
77
+ failures.push(`${source.name}: empty`);
78
+ }
79
+ catch (cause) {
80
+ failures.push(`${source.name}: ${cause.message}`);
81
+ }
82
+ }
83
+ throw new SourceError('no source could supply the registry', failures.join('\n '));
84
+ }
85
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Where an installer writes, per agent tool.
3
+ *
4
+ * Vendor neutrality is cheap here and expensive to retrofit: the same resolved skill is
5
+ * written to a different directory with a different extension, and nothing above this
6
+ * layer needs to know which tool is in use.
7
+ */
8
+ export interface Target {
9
+ readonly id: string;
10
+ /** Directory, relative to the project root. */
11
+ readonly dir: string;
12
+ /** File name for a skill, given its `family/skill` name. */
13
+ fileFor(name: string): string;
14
+ /** Some tools want their own frontmatter on each file. */
15
+ header?(name: string, version: string): string;
16
+ }
17
+ export declare const TARGETS: readonly Target[];
18
+ export declare const DEFAULT_TARGET = "claude";
19
+ export declare function targetById(id: string): Target | undefined;
20
+ //# sourceMappingURL=targets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../src/targets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAChD;AAID,eAAO,MAAM,OAAO,EAAE,SAAS,MAAM,EAiBpC,CAAC;AAEF,eAAO,MAAM,cAAc,WAAW,CAAC;AAEvC,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEzD"}