@flowstack-ui/agent-tools 0.1.0-bootstrap.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 (239) hide show
  1. package/.codex-plugin/plugin.json +37 -0
  2. package/CHANGELOG.md +21 -0
  3. package/LICENSE +21 -0
  4. package/README.md +125 -0
  5. package/docs/architecture.md +77 -0
  6. package/docs/releasing.md +26 -0
  7. package/docs/testing.md +32 -0
  8. package/package.json +63 -0
  9. package/public/index.json +2073 -0
  10. package/public/llms.txt +19 -0
  11. package/public/packages/atom/0.24.0/components/accordion.txt +131 -0
  12. package/public/packages/atom/0.24.0/components/alert-dialog.txt +112 -0
  13. package/public/packages/atom/0.24.0/components/app-bar.txt +96 -0
  14. package/public/packages/atom/0.24.0/components/aspect-ratio.txt +111 -0
  15. package/public/packages/atom/0.24.0/components/avatar.txt +119 -0
  16. package/public/packages/atom/0.24.0/components/badge.txt +123 -0
  17. package/public/packages/atom/0.24.0/components/bottom-navigation.txt +96 -0
  18. package/public/packages/atom/0.24.0/components/breadcrumb.txt +96 -0
  19. package/public/packages/atom/0.24.0/components/button.txt +98 -0
  20. package/public/packages/atom/0.24.0/components/carousel.txt +128 -0
  21. package/public/packages/atom/0.24.0/components/checkbox-group.txt +118 -0
  22. package/public/packages/atom/0.24.0/components/checkbox.txt +100 -0
  23. package/public/packages/atom/0.24.0/components/clipboard.txt +112 -0
  24. package/public/packages/atom/0.24.0/components/collapsible.txt +112 -0
  25. package/public/packages/atom/0.24.0/components/color-picker.txt +117 -0
  26. package/public/packages/atom/0.24.0/components/combobox.txt +126 -0
  27. package/public/packages/atom/0.24.0/components/context-menu.txt +114 -0
  28. package/public/packages/atom/0.24.0/components/data-grid.txt +136 -0
  29. package/public/packages/atom/0.24.0/components/dialog.txt +116 -0
  30. package/public/packages/atom/0.24.0/components/direction.txt +132 -0
  31. package/public/packages/atom/0.24.0/components/divider.txt +94 -0
  32. package/public/packages/atom/0.24.0/components/drag-drop.txt +141 -0
  33. package/public/packages/atom/0.24.0/components/drawer.txt +96 -0
  34. package/public/packages/atom/0.24.0/components/dropdown-menu.txt +112 -0
  35. package/public/packages/atom/0.24.0/components/feed.txt +132 -0
  36. package/public/packages/atom/0.24.0/components/field.txt +108 -0
  37. package/public/packages/atom/0.24.0/components/fieldset.txt +96 -0
  38. package/public/packages/atom/0.24.0/components/file-upload.txt +120 -0
  39. package/public/packages/atom/0.24.0/components/form.txt +98 -0
  40. package/public/packages/atom/0.24.0/components/hover-card.txt +114 -0
  41. package/public/packages/atom/0.24.0/components/image.txt +94 -0
  42. package/public/packages/atom/0.24.0/components/input.txt +96 -0
  43. package/public/packages/atom/0.24.0/components/label.txt +121 -0
  44. package/public/packages/atom/0.24.0/components/link.txt +100 -0
  45. package/public/packages/atom/0.24.0/components/list.txt +131 -0
  46. package/public/packages/atom/0.24.0/components/listbox.txt +120 -0
  47. package/public/packages/atom/0.24.0/components/menu.txt +126 -0
  48. package/public/packages/atom/0.24.0/components/menubar.txt +120 -0
  49. package/public/packages/atom/0.24.0/components/modal.txt +118 -0
  50. package/public/packages/atom/0.24.0/components/multi-select.txt +120 -0
  51. package/public/packages/atom/0.24.0/components/nav-list.txt +104 -0
  52. package/public/packages/atom/0.24.0/components/navigation-menu.txt +104 -0
  53. package/public/packages/atom/0.24.0/components/number-input.txt +124 -0
  54. package/public/packages/atom/0.24.0/components/otp-field.txt +122 -0
  55. package/public/packages/atom/0.24.0/components/pagination.txt +111 -0
  56. package/public/packages/atom/0.24.0/components/password-toggle-field.txt +116 -0
  57. package/public/packages/atom/0.24.0/components/popover.txt +122 -0
  58. package/public/packages/atom/0.24.0/components/pressable.txt +94 -0
  59. package/public/packages/atom/0.24.0/components/progress.txt +130 -0
  60. package/public/packages/atom/0.24.0/components/radio-group.txt +118 -0
  61. package/public/packages/atom/0.24.0/components/rating.txt +122 -0
  62. package/public/packages/atom/0.24.0/components/reorder.txt +141 -0
  63. package/public/packages/atom/0.24.0/components/scroll-area.txt +96 -0
  64. package/public/packages/atom/0.24.0/components/select.txt +126 -0
  65. package/public/packages/atom/0.24.0/components/sidebar.txt +96 -0
  66. package/public/packages/atom/0.24.0/components/skip-link.txt +96 -0
  67. package/public/packages/atom/0.24.0/components/slider.txt +124 -0
  68. package/public/packages/atom/0.24.0/components/swipeable-item.txt +118 -0
  69. package/public/packages/atom/0.24.0/components/switch.txt +116 -0
  70. package/public/packages/atom/0.24.0/components/table.txt +128 -0
  71. package/public/packages/atom/0.24.0/components/tabs.txt +96 -0
  72. package/public/packages/atom/0.24.0/components/textarea.txt +96 -0
  73. package/public/packages/atom/0.24.0/components/toast.txt +124 -0
  74. package/public/packages/atom/0.24.0/components/toggle-group.txt +118 -0
  75. package/public/packages/atom/0.24.0/components/toggle.txt +110 -0
  76. package/public/packages/atom/0.24.0/components/toolbar.txt +98 -0
  77. package/public/packages/atom/0.24.0/components/tooltip.txt +112 -0
  78. package/public/packages/atom/0.24.0/components/tree-grid.txt +138 -0
  79. package/public/packages/atom/0.24.0/components/tree.txt +138 -0
  80. package/public/packages/atom/0.24.0/components/visually-hidden.txt +119 -0
  81. package/public/packages/atom/0.24.0/docs/guides/agent-knowledge.txt +55 -0
  82. package/public/packages/atom/0.24.0/docs/guides/getting-started.txt +65 -0
  83. package/public/packages/atom/0.24.0/docs/guides/imports.txt +26 -0
  84. package/public/packages/atom/0.24.0/docs/guides/public-api.txt +100 -0
  85. package/public/packages/atom/0.24.0/guides/behavior-composition.txt +277 -0
  86. package/public/packages/atom/0.24.0/guides/layer-selection.txt +807 -0
  87. package/public/packages/atom/0.24.0/index.txt +89 -0
  88. package/public/packages/brick/0.1.11/components/accordion.txt +158 -0
  89. package/public/packages/brick/0.1.11/components/alert-dialog.txt +175 -0
  90. package/public/packages/brick/0.1.11/components/app-bar.txt +134 -0
  91. package/public/packages/brick/0.1.11/components/appearance.txt +143 -0
  92. package/public/packages/brick/0.1.11/components/aspect-ratio.txt +136 -0
  93. package/public/packages/brick/0.1.11/components/avatar.txt +152 -0
  94. package/public/packages/brick/0.1.11/components/badge.txt +139 -0
  95. package/public/packages/brick/0.1.11/components/bleed.txt +104 -0
  96. package/public/packages/brick/0.1.11/components/bottom-navigation.txt +106 -0
  97. package/public/packages/brick/0.1.11/components/breadcrumb.txt +96 -0
  98. package/public/packages/brick/0.1.11/components/button.txt +103 -0
  99. package/public/packages/brick/0.1.11/components/card.txt +132 -0
  100. package/public/packages/brick/0.1.11/components/carousel.txt +206 -0
  101. package/public/packages/brick/0.1.11/components/checkbox-group.txt +175 -0
  102. package/public/packages/brick/0.1.11/components/checkbox.txt +103 -0
  103. package/public/packages/brick/0.1.11/components/chip.txt +128 -0
  104. package/public/packages/brick/0.1.11/components/code-block.txt +134 -0
  105. package/public/packages/brick/0.1.11/components/code.txt +120 -0
  106. package/public/packages/brick/0.1.11/components/collapsible.txt +179 -0
  107. package/public/packages/brick/0.1.11/components/color-picker.txt +135 -0
  108. package/public/packages/brick/0.1.11/components/color-swatch.txt +98 -0
  109. package/public/packages/brick/0.1.11/components/combobox.txt +157 -0
  110. package/public/packages/brick/0.1.11/components/container.txt +112 -0
  111. package/public/packages/brick/0.1.11/components/context-menu.txt +174 -0
  112. package/public/packages/brick/0.1.11/components/data-grid.txt +199 -0
  113. package/public/packages/brick/0.1.11/components/data-list.txt +115 -0
  114. package/public/packages/brick/0.1.11/components/dialog.txt +176 -0
  115. package/public/packages/brick/0.1.11/components/divider.txt +104 -0
  116. package/public/packages/brick/0.1.11/components/drawer.txt +146 -0
  117. package/public/packages/brick/0.1.11/components/dropdown-menu.txt +179 -0
  118. package/public/packages/brick/0.1.11/components/feed.txt +143 -0
  119. package/public/packages/brick/0.1.11/components/field.txt +115 -0
  120. package/public/packages/brick/0.1.11/components/fieldset.txt +103 -0
  121. package/public/packages/brick/0.1.11/components/file-upload.txt +154 -0
  122. package/public/packages/brick/0.1.11/components/form.txt +108 -0
  123. package/public/packages/brick/0.1.11/components/frame.txt +132 -0
  124. package/public/packages/brick/0.1.11/components/grid.txt +141 -0
  125. package/public/packages/brick/0.1.11/components/group.txt +136 -0
  126. package/public/packages/brick/0.1.11/components/hide.txt +121 -0
  127. package/public/packages/brick/0.1.11/components/hover-card.txt +156 -0
  128. package/public/packages/brick/0.1.11/components/icon-button.txt +119 -0
  129. package/public/packages/brick/0.1.11/components/icon.txt +160 -0
  130. package/public/packages/brick/0.1.11/components/image.txt +163 -0
  131. package/public/packages/brick/0.1.11/components/input.txt +101 -0
  132. package/public/packages/brick/0.1.11/components/link-box.txt +161 -0
  133. package/public/packages/brick/0.1.11/components/link.txt +133 -0
  134. package/public/packages/brick/0.1.11/components/list.txt +139 -0
  135. package/public/packages/brick/0.1.11/components/menubar.txt +174 -0
  136. package/public/packages/brick/0.1.11/components/multi-select.txt +153 -0
  137. package/public/packages/brick/0.1.11/components/nav-list.txt +130 -0
  138. package/public/packages/brick/0.1.11/components/navigation-menu.txt +150 -0
  139. package/public/packages/brick/0.1.11/components/notification-badge.txt +148 -0
  140. package/public/packages/brick/0.1.11/components/number-input.txt +150 -0
  141. package/public/packages/brick/0.1.11/components/otp-field.txt +146 -0
  142. package/public/packages/brick/0.1.11/components/pagination.txt +124 -0
  143. package/public/packages/brick/0.1.11/components/password-toggle-field.txt +146 -0
  144. package/public/packages/brick/0.1.11/components/popover.txt +181 -0
  145. package/public/packages/brick/0.1.11/components/progress-circle.txt +142 -0
  146. package/public/packages/brick/0.1.11/components/progress.txt +150 -0
  147. package/public/packages/brick/0.1.11/components/radio-group.txt +152 -0
  148. package/public/packages/brick/0.1.11/components/rating.txt +151 -0
  149. package/public/packages/brick/0.1.11/components/reorderable-list.txt +130 -0
  150. package/public/packages/brick/0.1.11/components/scroll-area.txt +110 -0
  151. package/public/packages/brick/0.1.11/components/section.txt +118 -0
  152. package/public/packages/brick/0.1.11/components/segment-group.txt +116 -0
  153. package/public/packages/brick/0.1.11/components/select.txt +157 -0
  154. package/public/packages/brick/0.1.11/components/show.txt +121 -0
  155. package/public/packages/brick/0.1.11/components/sidebar.txt +126 -0
  156. package/public/packages/brick/0.1.11/components/skeleton.txt +127 -0
  157. package/public/packages/brick/0.1.11/components/skip-link.txt +102 -0
  158. package/public/packages/brick/0.1.11/components/slider.txt +147 -0
  159. package/public/packages/brick/0.1.11/components/stack.txt +155 -0
  160. package/public/packages/brick/0.1.11/components/status.txt +110 -0
  161. package/public/packages/brick/0.1.11/components/surface.txt +194 -0
  162. package/public/packages/brick/0.1.11/components/swipeable-item.txt +154 -0
  163. package/public/packages/brick/0.1.11/components/switch.txt +152 -0
  164. package/public/packages/brick/0.1.11/components/table.txt +183 -0
  165. package/public/packages/brick/0.1.11/components/tabs.txt +136 -0
  166. package/public/packages/brick/0.1.11/components/text.txt +148 -0
  167. package/public/packages/brick/0.1.11/components/textarea.txt +101 -0
  168. package/public/packages/brick/0.1.11/components/toast.txt +150 -0
  169. package/public/packages/brick/0.1.11/components/toggle-group.txt +149 -0
  170. package/public/packages/brick/0.1.11/components/toggle.txt +140 -0
  171. package/public/packages/brick/0.1.11/components/toolbar.txt +118 -0
  172. package/public/packages/brick/0.1.11/components/tooltip.txt +156 -0
  173. package/public/packages/brick/0.1.11/components/tree-grid.txt +160 -0
  174. package/public/packages/brick/0.1.11/components/tree.txt +156 -0
  175. package/public/packages/brick/0.1.11/components/visually-hidden.txt +123 -0
  176. package/public/packages/brick/0.1.11/components/z-stack.txt +143 -0
  177. package/public/packages/brick/0.1.11/docs/guides/agent-knowledge.txt +67 -0
  178. package/public/packages/brick/0.1.11/docs/guides/appearance-and-tokens.txt +179 -0
  179. package/public/packages/brick/0.1.11/docs/guides/browser-support.txt +25 -0
  180. package/public/packages/brick/0.1.11/docs/guides/control-sizing.txt +59 -0
  181. package/public/packages/brick/0.1.11/docs/guides/installation.txt +79 -0
  182. package/public/packages/brick/0.1.11/docs/guides/theme-contract.txt +90 -0
  183. package/public/packages/brick/0.1.11/guides/interface-composition.txt +665 -0
  184. package/public/packages/brick/0.1.11/guides/layer-selection.txt +1437 -0
  185. package/public/packages/brick/0.1.11/index.txt +110 -0
  186. package/public/packages/colors/0.1.1/docs/agent-knowledge.txt +63 -0
  187. package/public/packages/colors/0.1.1/docs/architecture.txt +74 -0
  188. package/public/packages/colors/0.1.1/docs/color-foundations.txt +128 -0
  189. package/public/packages/colors/0.1.1/docs/compatibility.txt +75 -0
  190. package/public/packages/colors/0.1.1/docs/dependency-qualification.txt +117 -0
  191. package/public/packages/colors/0.1.1/docs/installation.txt +48 -0
  192. package/public/packages/colors/0.1.1/docs/palette-generation.txt +151 -0
  193. package/public/packages/colors/0.1.1/docs/releasing.txt +34 -0
  194. package/public/packages/colors/0.1.1/docs/testing.txt +51 -0
  195. package/public/packages/colors/0.1.1/guides/colors-system.txt +282 -0
  196. package/public/packages/colors/0.1.1/index.txt +29 -0
  197. package/public/packages/colors/0.1.1/operations/color-conversion.txt +14 -0
  198. package/public/packages/colors/0.1.1/operations/color-inspection.txt +23 -0
  199. package/public/packages/colors/0.1.1/operations/color-measurement.txt +18 -0
  200. package/public/packages/colors/0.1.1/operations/color-provenance.txt +14 -0
  201. package/public/packages/colors/0.1.1/operations/named-palette-reference.txt +15 -0
  202. package/public/packages/colors/0.1.1/operations/palette-candidate.txt +37 -0
  203. package/public/packages/theme/0.1.1/docs/agent-knowledge.txt +44 -0
  204. package/public/packages/theme/0.1.1/docs/appearances-and-portals.txt +41 -0
  205. package/public/packages/theme/0.1.1/docs/architecture.txt +121 -0
  206. package/public/packages/theme/0.1.1/docs/authoring.txt +141 -0
  207. package/public/packages/theme/0.1.1/docs/colors-interchange.txt +82 -0
  208. package/public/packages/theme/0.1.1/docs/fonts.txt +40 -0
  209. package/public/packages/theme/0.1.1/docs/installation.txt +45 -0
  210. package/public/packages/theme/0.1.1/docs/migration.txt +40 -0
  211. package/public/packages/theme/0.1.1/docs/testing.txt +64 -0
  212. package/public/packages/theme/0.1.1/docs/troubleshooting.txt +53 -0
  213. package/public/packages/theme/0.1.1/guides/theme-system.txt +340 -0
  214. package/public/packages/theme/0.1.1/index.txt +31 -0
  215. package/public/packages/theme/0.1.1/operations/brick-contract-compatibility.txt +35 -0
  216. package/public/packages/theme/0.1.1/operations/colors-interchange.txt +35 -0
  217. package/public/packages/theme/0.1.1/operations/theme-artifacts.txt +19 -0
  218. package/public/packages/theme/0.1.1/operations/theme-cli.txt +10 -0
  219. package/public/packages/theme/0.1.1/operations/theme-compilation.txt +23 -0
  220. package/public/packages/theme/0.1.1/operations/theme-definition.txt +36 -0
  221. package/public/packages/theme/0.1.1/operations/theme-validation.txt +19 -0
  222. package/public/tasks/data.txt +39 -0
  223. package/public/tasks/forms.txt +65 -0
  224. package/public/tasks/layout.txt +37 -0
  225. package/public/tasks/navigation.txt +51 -0
  226. package/public/tasks/overlays.txt +39 -0
  227. package/public/tasks/theming.txt +37 -0
  228. package/skills/flowstack-ui-builder/SKILL.md +35 -0
  229. package/skills/flowstack-ui-builder/agents/openai.yaml +4 -0
  230. package/skills/flowstack-ui-builder/scripts/resolve-agent-knowledge.mjs +399 -0
  231. package/skills/flowstack-ui-compose/SKILL.md +32 -0
  232. package/skills/flowstack-ui-compose/agents/openai.yaml +4 -0
  233. package/skills/flowstack-ui-compose/scripts/resolve-agent-knowledge.mjs +399 -0
  234. package/skills/flowstack-ui-maintainer/SKILL.md +40 -0
  235. package/skills/flowstack-ui-maintainer/agents/openai.yaml +4 -0
  236. package/skills/flowstack-ui-maintainer/scripts/resolve-agent-knowledge.mjs +399 -0
  237. package/skills/flowstack-ui-review/SKILL.md +29 -0
  238. package/skills/flowstack-ui-review/agents/openai.yaml +4 -0
  239. package/skills/flowstack-ui-review/scripts/resolve-agent-knowledge.mjs +399 -0
@@ -0,0 +1,399 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createHash } from "node:crypto";
4
+ import { access, readFile, realpath, stat } from "node:fs/promises";
5
+ import { createRequire } from "node:module";
6
+ import { dirname, join, relative, resolve, sep } from "node:path";
7
+
8
+ const allowedFlags = new Set(["agent-tools", "archive-sha256", "id", "kind", "package", "project", "version"]);
9
+ const values = new Map();
10
+ for (let index = 2; index < process.argv.length; index += 1) {
11
+ const flag = process.argv[index];
12
+ if (!flag?.startsWith("--")) fail(`invalid argument: ${flag ?? "end of command"}`);
13
+ const key = flag.slice(2);
14
+ if (!allowedFlags.has(key)) fail(`unknown flag: ${flag}`);
15
+ if (values.has(key)) fail(`duplicate flag: ${flag}`);
16
+ const value = process.argv[index + 1];
17
+ if (!value || value.startsWith("--")) fail(`missing value for ${flag}`);
18
+ values.set(key, value);
19
+ index += 1;
20
+ }
21
+
22
+ const project = resolve(values.get("project") ?? process.cwd());
23
+ const packageName = values.get("package");
24
+ const requestedVersion = values.get("version");
25
+ const requestedArchiveSha256 = values.get("archive-sha256");
26
+ const kind = values.get("kind");
27
+ const id = values.get("id");
28
+ if (!packageName) fail("--package is required");
29
+ if (!["@flowstack-ui/atom", "@flowstack-ui/brick", "@flowstack-ui/colors", "@flowstack-ui/theme"].includes(packageName)) fail(`unsupported public Agent Tools package: ${packageName}`);
30
+ if (requestedVersion && !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u.test(requestedVersion)) fail("--version must be one exact package version");
31
+ if (requestedArchiveSha256 && !/^[a-f0-9]{64}$/u.test(requestedArchiveSha256)) fail("--archive-sha256 must be one lowercase SHA-256 digest");
32
+ if ((kind && !id) || (!kind && id)) fail("--kind and --id must be supplied together");
33
+ if (kind && !["guide", "component", "operation"].includes(kind)) fail(`unsupported owner kind: ${kind}`);
34
+
35
+ const projectRequire = createRequire(join(project, "package.json"));
36
+ let installedPackagePath;
37
+ let manifestPath;
38
+ try {
39
+ manifestPath = projectRequire.resolve(`${packageName}/agents/manifest.json`);
40
+ } catch {}
41
+ try {
42
+ installedPackagePath = projectRequire.resolve(`${packageName}/package.json`);
43
+ } catch {}
44
+ if (!installedPackagePath && manifestPath) installedPackagePath = await findPackageJson(manifestPath);
45
+ if (!installedPackagePath) {
46
+ try {
47
+ installedPackagePath = await findPackageJson(projectRequire.resolve(packageName));
48
+ } catch {}
49
+ }
50
+
51
+ let installedPackage = null;
52
+ if (installedPackagePath) {
53
+ installedPackage = await readJson(installedPackagePath);
54
+ if (installedPackage.name !== packageName) fail(`installed package identity does not match ${packageName}`);
55
+ if (!requestedArchiveSha256 && requestedVersion && requestedVersion !== installedPackage.version) {
56
+ fail(`installed ${packageName}@${installedPackage.version} does not match requested ${requestedVersion}`);
57
+ }
58
+ if (manifestPath && !requestedArchiveSha256) {
59
+ const result = await resolveInstalled(installedPackage, installedPackagePath, manifestPath);
60
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
61
+ process.exit(0);
62
+ }
63
+ }
64
+
65
+ if (!installedPackage && !requestedVersion) {
66
+ fail(`--version is required when ${packageName} is not exactly installed`);
67
+ }
68
+
69
+ const toolsIndexPath = await findAgentToolsIndex();
70
+ if (toolsIndexPath) {
71
+ const result = await resolveDelivery(toolsIndexPath, installedPackage);
72
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
73
+ process.exit(0);
74
+ }
75
+
76
+ const exactVersion = requestedVersion ?? installedPackage?.version;
77
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: no exact installed Agent Knowledge or Agent Tools route for ${packageName}@${exactVersion}`);
78
+
79
+ async function resolveInstalled(packageJson, packageJsonPath, unresolvedManifestPath) {
80
+ const packageRoot = dirname(await realpath(packageJsonPath));
81
+ const manifestPath = await containedFile(packageRoot, unresolvedManifestPath, "installed manifest");
82
+ const manifest = await readJson(manifestPath);
83
+ if (manifest.schema !== "flowstack.agent-manifest.v1") fail(`unsupported Agent Knowledge manifest schema in ${manifestPath}`);
84
+ assertIdentity(manifest, packageJson.name, packageJson.version, "manifest");
85
+ if (typeof manifest.coverage !== "string" || !manifest.coverage) fail("manifest coverage link is missing");
86
+ const coveragePath = await existingArtifact(manifestPath, manifest.coverage, "coverage");
87
+ const coverage = await readJson(coveragePath);
88
+ if (coverage.schema !== "flowstack.agent-coverage.v1") fail(`unsupported Agent Knowledge coverage schema in ${coveragePath}`);
89
+ assertIdentity(coverage, packageJson.name, packageJson.version, "coverage");
90
+ validateInstalledClosure(manifest, coverage);
91
+
92
+ const packageGuides = [];
93
+ for (const entry of manifest.guides) packageGuides.push(await installedGuide(manifest, manifestPath, entry));
94
+
95
+ return {
96
+ schema: "flowstack.agent-skill-resolution.v1",
97
+ source: "installed-package",
98
+ sourceIdentity: { kind: "installed-package", packageJsonPath, archiveSha256: null },
99
+ package: packageJson.name,
100
+ version: packageJson.version,
101
+ manifestPath,
102
+ coveragePath,
103
+ packageGuides,
104
+ selected: kind ? await installedSelection(manifest, coverage, manifestPath, packageGuides) : null,
105
+ };
106
+ }
107
+
108
+ function validateInstalledClosure(manifest, coverage) {
109
+ const summary = coverage.summary;
110
+ if (!summary || typeof summary !== "object") fail("coverage summary is missing");
111
+ requireEqualCount(summary, "publicSurfaces", "classifiedPublicSurfaces");
112
+ for (const key of ["unclassified", "invalidExclusions", "unresolvedSelections"]) requireZero(summary, key);
113
+ for (const [key, value] of Object.entries(summary)) {
114
+ if (/^(?:unclassified|invalid|unresolved)/u.test(key) && value !== 0) fail(`coverage counter ${key} must be zero`);
115
+ }
116
+ if (!Array.isArray(coverage.failures) || coverage.failures.length !== 0) fail(`coverage is not closed for ${coverage.package}@${coverage.packageVersion}`);
117
+
118
+ const guides = exactEntries(manifest.guides, "manifest guides", { nonempty: true });
119
+ const coveredGuides = coveredEntries(coverage.guides, "coverage guides");
120
+ sameIds(guides, coveredGuides, "guide");
121
+ requireCount(summary, "packageGuides", guides.length);
122
+ for (const guide of guides) {
123
+ const covered = coveredGuides.find((entry) => entry.id === guide.id);
124
+ const json = covered.manifestPaths?.json ?? covered.json;
125
+ const markdown = covered.manifestPaths?.markdown ?? covered.markdown;
126
+ if (json !== guide.json || markdown !== guide.markdown) fail(`guide ${guide.id} manifest and coverage artifacts do not match`);
127
+ }
128
+
129
+ const components = exactEntries(manifest.components ?? [], "manifest components");
130
+ const coveredComponents = coveredEntries(coverage.components, "coverage components");
131
+ sameIds(components, coveredComponents, "component");
132
+ requireEqualCount(summary, "componentOwners", "guidedComponentOwners");
133
+ requireCount(summary, "componentOwners", components.length);
134
+ const operations = exactEntries(manifest.operations ?? [], "manifest operations");
135
+ const coveredOperations = coveredEntries(coverage.operations ?? [], "coverage operations");
136
+ sameIds(operations, coveredOperations, "operation");
137
+ const items = exactEntries(manifest.registryItems ?? [], "manifest registry items");
138
+ const coveredItems = coveredEntries(coverage.registryItems ?? [], "coverage registry items");
139
+ sameIds(items, coveredItems, "registry item");
140
+ const owners = coveredEntries(coverage.owners ?? [], "coverage owners");
141
+
142
+ const profile = coverage.profile?.kind ?? ((coverage.layer === "atom" || coverage.layer === "brick") ? "component-package" : null);
143
+ if (profile === "component-package") {
144
+ if (coverage.profile && coverage.profile.ownerUnit !== "component") fail("component-package ownerUnit must be component");
145
+ if (operations.length || items.length || owners.length) fail("component package has non-component owners");
146
+ return;
147
+ }
148
+
149
+ for (const key of ["invalidRegistryItems", "unresolvedDependencies"]) requireZero(summary, key);
150
+ requireEqualCount(summary, "ownerUnits", "guidedOwnerUnits");
151
+ requireCount(summary, "ownerUnits", owners.length);
152
+
153
+ if (profile === "operation-package") {
154
+ if (coverage.profile?.ownerUnit !== "operation") fail("operation-package ownerUnit must be operation");
155
+ if (operations.length === 0) fail("manifest operations must be a nonempty array");
156
+ if (items.length) fail("operation package has registry owners");
157
+ sameIds(operations, owners, "operation owner");
158
+ requireEqualCount(summary, "operationOwners", "guidedOperationOwners");
159
+ requireCount(summary, "operationOwners", operations.length);
160
+ requireCount(summary, "registryItems", 0);
161
+ requireCount(summary, "guidedRegistryItems", 0);
162
+ for (const operation of operations) {
163
+ if (!guides.some((guide) => guide.json === operation.guide)) fail(`operation ${operation.id} has an unresolved guide`);
164
+ }
165
+ return;
166
+ }
167
+
168
+ fail(`unsupported coverage profile: ${profile ?? "missing"}`);
169
+ }
170
+
171
+ async function installedGuide(manifest, manifestPath, entry) {
172
+ const jsonPath = await existingArtifact(manifestPath, entry.json, `guide ${entry.id} JSON`);
173
+ const markdownPath = await existingArtifact(manifestPath, entry.markdown, `guide ${entry.id} Markdown`);
174
+ const machine = await readJson(jsonPath);
175
+ assertMachineArtifact(machine, { schema: "flowstack.agent-guide.v1", id: entry.id, packageName: manifest.package, kind: "guide" });
176
+ return { id: entry.id, json: jsonPath, markdown: markdownPath };
177
+ }
178
+
179
+ async function installedSelection(manifest, coverage, manifestPath, packageGuides) {
180
+ const collection = kind === "guide" ? manifest.guides : kind === "component" ? manifest.components : kind === "operation" ? manifest.operations : manifest.registryItems;
181
+ const matches = (collection ?? []).filter((candidate) => candidate.id === id);
182
+ if (matches.length !== 1) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: ${manifest.package}@${manifest.packageVersion} has no unique ${kind} ${id}`);
183
+ const entry = matches[0];
184
+ if (kind === "guide") {
185
+ const guide = packageGuides.find((candidate) => candidate.id === id);
186
+ return { package: manifest.package, kind, ...guide };
187
+ }
188
+ if (kind === "operation") {
189
+ const guideEntry = manifest.guides.find((candidate) => candidate.json === entry.guide);
190
+ if (!guideEntry) fail(`operation ${id} has an unresolved guide`);
191
+ const guide = packageGuides.find((candidate) => candidate.id === guideEntry.id);
192
+ return { package: manifest.package, kind, id, guideId: guide.id, json: guide.json, markdown: guide.markdown };
193
+ }
194
+ const jsonReference = entry.json ?? entry.agentJson;
195
+ const markdownReference = entry.markdown ?? entry.agentMarkdown;
196
+ const jsonPath = await existingArtifact(manifestPath, jsonReference, `${kind} ${id} JSON`);
197
+ const markdownPath = await existingArtifact(manifestPath, markdownReference, `${kind} ${id} Markdown`);
198
+ const machine = await readJson(jsonPath);
199
+ if (kind === "component") {
200
+ assertMachineArtifact(machine, { schema: "flowstack.agent-component.v1", id, packageName: manifest.package, kind });
201
+ } else if (machine.$schema !== "flowstack.block-agent.v1" || machine.id !== id) {
202
+ fail(`selected block artifact identity does not match ${manifest.package} ${id}`);
203
+ }
204
+ return { package: manifest.package, kind, id, json: jsonPath, markdown: markdownPath };
205
+ }
206
+
207
+ async function resolveDelivery(unresolvedIndexPath, installedPackage) {
208
+ const indexPath = await containedFile(dirname(unresolvedIndexPath), unresolvedIndexPath, "Agent Tools index");
209
+ const index = await readJson(indexPath);
210
+ if (index.schema !== "flowstack.agent-delivery-index.v1") fail(`unsupported Agent Tools index schema in ${indexPath}`);
211
+ const exactVersion = requestedVersion ?? installedPackage?.version;
212
+ if (!exactVersion) fail(`--version is required when ${packageName} is not exactly installed`);
213
+ const records = index.packages.filter((entry) => entry.name === packageName && entry.version === exactVersion);
214
+ if (records.length !== 1) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools has no unique exact route for ${packageName}@${exactVersion}`);
215
+ const record = records[0];
216
+ validateDeliveryRecord(record);
217
+
218
+ const routes = index.routes.filter((route) => route.package === record.id && route.version === record.version);
219
+ const keys = new Set();
220
+ const paths = new Set();
221
+ for (const route of routes) {
222
+ const key = `${route.kind}:${route.id}`;
223
+ if (keys.has(key) || paths.has(route.path)) fail(`Agent Tools has duplicate routes for ${packageName}@${record.version}`);
224
+ keys.add(key);
225
+ paths.add(route.path);
226
+ }
227
+ const expectedCounts = { guide: record.counts.guides, component: record.counts.components, operation: record.counts.operations, package: 1 };
228
+ for (const [routeKind, count] of Object.entries(expectedCounts)) {
229
+ if (routes.filter((route) => route.kind === routeKind).length !== count) fail(`Agent Tools ${routeKind} route count does not match ${packageName}@${record.version}`);
230
+ }
231
+
232
+ const publicRoot = dirname(indexPath);
233
+ const packageRoute = routes.find((route) => route.kind === "package" && route.path === record.route);
234
+ if (!packageRoute) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools package route is missing for ${packageName}@${record.version}`);
235
+ const guideRoutes = routes.filter((route) => route.kind === "guide");
236
+ if (guideRoutes.length === 0) fail(`Agent Tools has no mandatory package guides for ${packageName}@${record.version}`);
237
+ const packageGuides = [];
238
+ for (const route of guideRoutes) packageGuides.push(await deliveryArtifact(publicRoot, route, record));
239
+
240
+ let selected = null;
241
+ if (kind) {
242
+ const matches = routes.filter((candidate) => candidate.kind === kind && candidate.id === id);
243
+ if (matches.length !== 1) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools has no unique ${kind} ${id} for ${packageName}@${record.version}`);
244
+ selected = await deliveryArtifact(publicRoot, matches[0], record);
245
+ }
246
+ return {
247
+ schema: "flowstack.agent-skill-resolution.v1",
248
+ source: "agent-tools-route",
249
+ sourceIdentity: { kind: "locked-archive", archiveSha256: record.archiveSha256 },
250
+ package: packageName,
251
+ version: record.version,
252
+ indexPath,
253
+ packageRoute: await deliveryArtifact(publicRoot, packageRoute, record, { identity: false }),
254
+ packageGuides,
255
+ selected,
256
+ };
257
+ }
258
+
259
+ function validateDeliveryRecord(record) {
260
+ if (!/^[a-f0-9]{64}$/u.test(record.archiveSha256 ?? "")) fail(`Agent Tools archive digest is invalid for ${packageName}@${record.version}`);
261
+ if (requestedArchiveSha256 && record.archiveSha256 !== requestedArchiveSha256) {
262
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: archive digest does not match ${packageName}@${record.version}`);
263
+ }
264
+ const coverage = record.coverage;
265
+ if (!coverage || coverage.failures !== 0 || coverage.publicSurfaces !== coverage.classifiedPublicSurfaces) {
266
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools coverage is not closed for ${packageName}@${record.version}`);
267
+ }
268
+ if (!record.counts || !Number.isInteger(record.counts.guides) || record.counts.guides <= 0) fail(`Agent Tools guide count is invalid for ${packageName}@${record.version}`);
269
+ for (const key of ["components", "operations"]) if (!Number.isInteger(record.counts[key]) || record.counts[key] < 0) fail(`Agent Tools ${key} count is invalid`);
270
+ const profile = record.profile;
271
+ if (profile?.kind === "component-package" && profile.ownerUnit === "component") {
272
+ if (record.counts.components <= 0 || record.counts.operations !== 0) fail("Agent Tools component profile counts are inconsistent");
273
+ } else if (profile?.kind === "operation-package" && profile.ownerUnit === "operation") {
274
+ if (record.counts.operations <= 0 || record.counts.components !== 0) fail("Agent Tools operation profile counts are inconsistent");
275
+ } else {
276
+ fail(`unsupported Agent Tools coverage profile for ${packageName}@${record.version}`);
277
+ }
278
+ }
279
+
280
+ async function deliveryArtifact(publicRoot, route, record, { identity = true } = {}) {
281
+ const lexicalPath = resolve(publicRoot, route.path.replace(/^\//u, ""));
282
+ const path = await containedFile(publicRoot, lexicalPath, `Agent Tools route ${route.path}`);
283
+ const content = await readFile(path);
284
+ const digest = createHash("sha256").update(content).digest("hex");
285
+ if (!Number.isInteger(route.bytes) || content.length !== route.bytes || !/^[a-f0-9]{64}$/u.test(route.sha256) || digest !== route.sha256) {
286
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools route integrity failed for ${route.path}`);
287
+ }
288
+ if (identity) {
289
+ const text = content.toString("utf8");
290
+ if (!text.includes(`\nSource: ${record.name}@${record.version}\n`) || !text.includes(`\nKind: ${route.kind}\n`) || !text.includes(`\nID: ${route.id}\n`)) {
291
+ fail(`Agent Tools route identity does not match ${record.name} ${route.kind} ${route.id}`);
292
+ }
293
+ }
294
+ return { package: record.name, kind: route.kind, id: route.id, route: route.path, path };
295
+ }
296
+
297
+ async function findAgentToolsIndex() {
298
+ const supplied = values.get("agent-tools");
299
+ if (supplied) {
300
+ const target = resolve(supplied);
301
+ const info = await stat(target).catch(() => null);
302
+ if (!info) return null;
303
+ if (!info.isDirectory()) return target;
304
+ for (const candidate of [join(target, "public", "index.json"), join(target, "index.json")]) {
305
+ if (await access(candidate).then(() => true).catch(() => false)) return candidate;
306
+ }
307
+ return null;
308
+ }
309
+ try {
310
+ return projectRequire.resolve("@flowstack-ui/agent-tools/index.json");
311
+ } catch {
312
+ return null;
313
+ }
314
+ }
315
+
316
+ async function existingArtifact(manifestPath, artifact, label) {
317
+ if (typeof artifact !== "string" || !artifact) fail(`${label} path is missing`);
318
+ const base = dirname(manifestPath);
319
+ const path = resolve(base, artifact);
320
+ const relativePath = relative(base, path);
321
+ if (relativePath === ".." || relativePath.startsWith(`..${sep}`)) fail(`escaping manifest artifact: ${artifact}`);
322
+ return containedFile(base, path, label);
323
+ }
324
+
325
+ async function containedFile(root, path, label) {
326
+ const rootPath = await realpath(root);
327
+ const filePath = await realpath(path).catch(() => null);
328
+ if (!filePath) fail(`${label} is missing`);
329
+ const relativePath = relative(rootPath, filePath);
330
+ if (relativePath === ".." || relativePath.startsWith(`..${sep}`)) fail(`${label} escapes its authority root`);
331
+ const info = await stat(filePath);
332
+ if (!info.isFile()) fail(`${label} is not a file`);
333
+ return filePath;
334
+ }
335
+
336
+ function assertMachineArtifact(machine, expected) {
337
+ if (machine.schema !== expected.schema || machine.id !== expected.id || machine.package !== expected.packageName || machine.kind !== expected.kind) {
338
+ fail(`selected artifact identity does not match ${expected.packageName} ${expected.kind} ${expected.id}`);
339
+ }
340
+ }
341
+
342
+ function assertIdentity(value, name, version, label) {
343
+ if (value.package !== name || value.packageVersion !== version) fail(`${label} identity does not match installed ${name}@${version}`);
344
+ }
345
+
346
+ function exactEntries(entries, label, { nonempty = false } = {}) {
347
+ if (!Array.isArray(entries) || (nonempty && entries.length === 0)) fail(`${label} must be ${nonempty ? "a nonempty" : "an"} array`);
348
+ const ids = new Set();
349
+ for (const entry of entries) {
350
+ if (!entry || typeof entry.id !== "string" || !entry.id || ids.has(entry.id)) fail(`${label} has a missing or duplicate id`);
351
+ ids.add(entry.id);
352
+ }
353
+ return entries;
354
+ }
355
+
356
+ function coveredEntries(entries, label) {
357
+ const result = exactEntries(entries, label);
358
+ if (result.some((entry) => entry.status !== "covered")) fail(`${label} contains an uncovered owner`);
359
+ return result;
360
+ }
361
+
362
+ function sameIds(left, right, label) {
363
+ const leftIds = left.map(({ id }) => id).sort();
364
+ const rightIds = right.map(({ id }) => id).sort();
365
+ if (JSON.stringify(leftIds) !== JSON.stringify(rightIds)) fail(`${label} manifest and coverage ids do not match`);
366
+ }
367
+
368
+ function requireCount(summary, key, expected) {
369
+ if (!Number.isInteger(summary[key]) || summary[key] !== expected) fail(`coverage counter ${key} must equal ${expected}`);
370
+ }
371
+
372
+ function requireEqualCount(summary, left, right) {
373
+ if (!Number.isInteger(summary[left]) || !Number.isInteger(summary[right]) || summary[left] !== summary[right]) fail(`coverage counters ${left} and ${right} must match`);
374
+ }
375
+
376
+ function requireZero(summary, key) {
377
+ requireCount(summary, key, 0);
378
+ }
379
+
380
+ async function readJson(path) {
381
+ return JSON.parse(await readFile(path, "utf8"));
382
+ }
383
+
384
+ async function findPackageJson(start) {
385
+ let directory = dirname(start);
386
+ while (true) {
387
+ const candidate = join(directory, "package.json");
388
+ const json = await readJson(candidate).catch(() => null);
389
+ if (json?.name === packageName) return candidate;
390
+ const parent = dirname(directory);
391
+ if (parent === directory) return null;
392
+ directory = parent;
393
+ }
394
+ }
395
+
396
+ function fail(message) {
397
+ process.stderr.write(`${message}\n`);
398
+ process.exit(1);
399
+ }