@vertesia/build-tools 1.5.0-dev.20260725.083715Z → 1.5.0-dev.20260804.124748Z

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 (59) hide show
  1. package/README.md +297 -266
  2. package/lib/bin/build.js +26 -1
  3. package/lib/bin/build.js.map +1 -1
  4. package/lib/bin/config.d.ts +12 -0
  5. package/lib/bin/config.d.ts.map +1 -1
  6. package/lib/bin/config.js +25 -0
  7. package/lib/bin/config.js.map +1 -1
  8. package/lib/core/skill-markdown/load-catalog.d.ts +30 -0
  9. package/lib/core/skill-markdown/load-catalog.d.ts.map +1 -0
  10. package/lib/core/skill-markdown/load-catalog.js +69 -0
  11. package/lib/core/skill-markdown/load-catalog.js.map +1 -0
  12. package/lib/core/skill-markdown/preprocess.d.ts +127 -0
  13. package/lib/core/skill-markdown/preprocess.d.ts.map +1 -0
  14. package/lib/core/skill-markdown/preprocess.js +455 -0
  15. package/lib/core/skill-markdown/preprocess.js.map +1 -0
  16. package/lib/core/skill-markdown/schema-validator.d.ts +109 -0
  17. package/lib/core/skill-markdown/schema-validator.d.ts.map +1 -0
  18. package/lib/core/skill-markdown/schema-validator.js +420 -0
  19. package/lib/core/skill-markdown/schema-validator.js.map +1 -0
  20. package/lib/core/transformers/index.d.ts +1 -1
  21. package/lib/core/transformers/index.d.ts.map +1 -1
  22. package/lib/core/transformers/index.js +1 -1
  23. package/lib/core/transformers/index.js.map +1 -1
  24. package/lib/core/transformers/skill.d.ts +15 -1
  25. package/lib/core/transformers/skill.d.ts.map +1 -1
  26. package/lib/core/transformers/skill.js +82 -60
  27. package/lib/core/transformers/skill.js.map +1 -1
  28. package/lib/import-transform/detector.d.ts +19 -6
  29. package/lib/import-transform/detector.d.ts.map +1 -1
  30. package/lib/import-transform/detector.js +73 -24
  31. package/lib/import-transform/detector.js.map +1 -1
  32. package/lib/import-transform/index.d.ts.map +1 -1
  33. package/lib/import-transform/index.js +10 -1
  34. package/lib/import-transform/index.js.map +1 -1
  35. package/lib/import-transform/patterns.d.ts +7 -8
  36. package/lib/import-transform/patterns.d.ts.map +1 -1
  37. package/lib/import-transform/patterns.js +7 -8
  38. package/lib/import-transform/patterns.js.map +1 -1
  39. package/lib/index.d.ts +7 -3
  40. package/lib/index.d.ts.map +1 -1
  41. package/lib/index.js +9 -3
  42. package/lib/index.js.map +1 -1
  43. package/lib/vite/dev-server.d.ts +10 -0
  44. package/lib/vite/dev-server.d.ts.map +1 -1
  45. package/lib/vite/dev-server.js +36 -4
  46. package/lib/vite/dev-server.js.map +1 -1
  47. package/package.json +9 -12
  48. package/src/bin/build.ts +31 -2
  49. package/src/bin/config.ts +27 -0
  50. package/src/core/skill-markdown/load-catalog.ts +100 -0
  51. package/src/core/skill-markdown/preprocess.ts +632 -0
  52. package/src/core/skill-markdown/schema-validator.ts +517 -0
  53. package/src/core/transformers/index.ts +3 -0
  54. package/src/core/transformers/skill.ts +116 -53
  55. package/src/import-transform/detector.ts +78 -26
  56. package/src/import-transform/index.ts +12 -2
  57. package/src/import-transform/patterns.ts +7 -12
  58. package/src/index.ts +35 -2
  59. package/src/vite/dev-server.ts +52 -4
@@ -31,13 +31,42 @@
31
31
  */
32
32
  import { readFileSync } from 'node:fs';
33
33
  import path from 'node:path';
34
+ import { loadSkillCatalog, readPackageJson, resolveSkillCatalogPath } from '../core/skill-markdown/load-catalog.js';
35
+ import { createSkillTransformer, isSkillTransformer } from '../core/transformers/skill.js';
34
36
  import { BUILTIN_TRANSFORMER_NAMES, resolveTransformerNames } from '../import-transform/builtins.js';
35
37
  export function vertesiaDevServerPlugin(options = {}) {
36
38
  const names = options.transformers ?? BUILTIN_TRANSFORMER_NAMES;
37
39
  const transformers = resolveTransformerNames([...names]);
40
+ // Resolved once, lazily: the catalog module is compiled output, so it may not exist when the
41
+ // config is first evaluated.
42
+ let root = process.cwd();
43
+ let boundPromise;
44
+ /** The catalog-bound skill transformer, or null when this package configures no catalog. */
45
+ const boundSkillTransformer = () => {
46
+ if (!boundPromise) {
47
+ boundPromise = (async () => {
48
+ if (options.skillCatalog === false)
49
+ return null;
50
+ const markdown = typeof options.skillCatalog === 'object'
51
+ ? options.skillCatalog
52
+ : await (async () => {
53
+ const modulePath = typeof options.skillCatalog === 'string'
54
+ ? path.resolve(root, options.skillCatalog)
55
+ : resolveSkillCatalogPath(readPackageJson(root) ?? {}, root);
56
+ return modulePath ? await loadSkillCatalog(modulePath) : null;
57
+ })();
58
+ return markdown ? createSkillTransformer({ markdown }) : null;
59
+ })();
60
+ }
61
+ return boundPromise;
62
+ };
38
63
  return {
39
64
  name: 'vertesia-dev-server',
40
65
  enforce: 'pre',
66
+ configResolved(config) {
67
+ if (config.root)
68
+ root = config.root;
69
+ },
41
70
  /**
42
71
  * Map relative query-style imports to absolute paths so Vite's loader
43
72
  * sees a stable id keyed by the original file location. The query
@@ -72,12 +101,15 @@ export function vertesiaDevServerPlugin(options = {}) {
72
101
  const matched = findMatchingTransformer(id, transformers);
73
102
  if (!matched)
74
103
  return null;
104
+ // Bind the skill transformer to the catalog on first use. Matched by identity rather
105
+ // than by pattern so a consumer's own transformer for the same files is left alone.
106
+ const active = isSkillTransformer(matched) ? ((await boundSkillTransformer()) ?? matched) : matched;
75
107
  const cleanId = stripQuery(id);
76
108
  try {
77
- const content = matched.virtual ? '' : readFileSync(cleanId, 'utf-8');
78
- const result = await matched.transform(content, cleanId);
79
- if (matched.schema) {
80
- const validation = matched.schema.safeParse(result.data);
109
+ const content = active.virtual ? '' : readFileSync(cleanId, 'utf-8');
110
+ const result = await active.transform(content, cleanId);
111
+ if (active.schema) {
112
+ const validation = active.schema.safeParse(result.data);
81
113
  if (!validation.success) {
82
114
  const errors = validation.error.issues
83
115
  .map((err) => ` - ${err.path.join('.')}: ${err.message}`)
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../src/vite/dev-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../src/vite/dev-server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertesia/build-tools",
3
- "version": "1.5.0-dev.20260725.083715Z",
3
+ "version": "1.5.0-dev.20260804.124748Z",
4
4
  "description": "Build tools for Vertesia projects - import transformers (skill / template / prompt / raw), esbuild widget bundler, vertesia-build CLI, and a Vite dev plugin",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -24,7 +24,7 @@
24
24
  }
25
25
  },
26
26
  "devDependencies": {
27
- "@hono/node-server": "^2.0.10",
27
+ "@hono/node-server": "^2.0.11",
28
28
  "@types/js-yaml": "^4.0.9",
29
29
  "@types/node": "^24.13.3",
30
30
  "typescript": "^6.0.3",
@@ -33,20 +33,17 @@
33
33
  "@vertesia/tsconfig": "0.1.0"
34
34
  },
35
35
  "dependencies": {
36
- "@rollup/plugin-commonjs": "^28.0.3",
37
- "@rollup/plugin-json": "^6.1.0",
38
- "@rollup/plugin-node-resolve": "^16.0.1",
39
- "@rollup/plugin-terser": "^0.4.4",
40
- "@rollup/plugin-typescript": "^12.1.2",
36
+ "ajv": "^8.20.0",
37
+ "es-module-lexer": "^1.7.0",
41
38
  "esbuild": "^0.28.1",
42
39
  "js-yaml": "^5.2.1",
43
40
  "zod": "^4.4.3",
44
- "@vertesia/studio-utils": "1.5.0-dev.20260725.083715Z",
45
- "@vertesia/common": "1.5.0-dev.20260725.083715Z",
46
- "@llumiverse/common": "1.5.0-dev.20260725.065646Z"
41
+ "@llumiverse/common": "1.5.0-dev.20260804.122431Z",
42
+ "@vertesia/common": "1.5.0-dev.20260804.124748Z",
43
+ "@vertesia/studio-utils": "1.5.0-dev.20260804.124748Z"
47
44
  },
48
45
  "peerDependencies": {
49
- "@hono/node-server": "^2.0.10",
46
+ "@hono/node-server": "^2.0.11",
50
47
  "vite": "^8.1.4"
51
48
  },
52
49
  "peerDependenciesMeta": {
@@ -78,7 +75,7 @@
78
75
  "zod",
79
76
  "validation"
80
77
  ],
81
- "gitHead": "57bcc2f27dd17b3387f27c18e89329c4c37f98ac",
78
+ "gitHead": "87ac9166db2b38bd1be6e37adf0414ea83e402ee",
82
79
  "scripts": {
83
80
  "lint": "biome lint src",
84
81
  "test": "vitest run",
package/src/bin/build.ts CHANGED
@@ -35,8 +35,11 @@
35
35
 
36
36
  import { readFileSync } from 'node:fs';
37
37
  import path from 'node:path';
38
+ import { loadSkillCatalog } from '../core/skill-markdown/load-catalog.js';
39
+ import { createSkillTransformer, isSkillTransformer } from '../core/transformers/skill.js';
40
+ import type { TransformerRule } from '../core/types.js';
38
41
  import { transformImports } from '../import-transform/index.js';
39
- import { resolveConfig, VertesiaBuildConfigError } from './config.js';
42
+ import { resolveConfig, resolveSkillCatalogPath, VertesiaBuildConfigError } from './config.js';
40
43
 
41
44
  function fail(message: string): never {
42
45
  console.error(`vertesia-build: ${message}`);
@@ -61,15 +64,41 @@ function readPackageJson(cwd: string): Record<string, unknown> {
61
64
  async function main(): Promise<void> {
62
65
  const cwd = process.cwd();
63
66
  const pkg = readPackageJson(cwd);
64
- let options;
67
+ let options: ReturnType<typeof resolveConfig>;
68
+ let catalogPath: string | undefined;
65
69
  try {
66
70
  options = resolveConfig(pkg, cwd);
71
+ catalogPath = resolveSkillCatalogPath(pkg, cwd);
67
72
  } catch (error) {
68
73
  if (error instanceof VertesiaBuildConfigError) {
69
74
  fail(error.message);
70
75
  }
71
76
  throw error;
72
77
  }
78
+
79
+ if (catalogPath) {
80
+ let markdown: Awaited<ReturnType<typeof loadSkillCatalog>>;
81
+ try {
82
+ markdown = await loadSkillCatalog(catalogPath);
83
+ } catch (error) {
84
+ fail((error as Error).message);
85
+ }
86
+ const bound = createSkillTransformer({ markdown });
87
+ // Swap by identity, not by pattern: a consumer's own transformer registered for the same
88
+ // files must not be silently replaced by ours.
89
+ const replaced = options.transformers.filter(isSkillTransformer).length;
90
+ if (replaced === 0) {
91
+ fail('skillCatalog is configured but "skill" is not in vertesia-build.transformers.');
92
+ }
93
+ options = {
94
+ ...options,
95
+ transformers: options.transformers.map((rule: TransformerRule) =>
96
+ isSkillTransformer(rule) ? bound : rule,
97
+ ),
98
+ };
99
+ console.log(`vertesia-build: skill catalog loaded (${markdown.tools.size} tools, ${markdown.skills.size} skills)`);
100
+ }
101
+
73
102
  const result = await transformImports(options);
74
103
  console.log(
75
104
  `vertesia-build: files=${result.filesProcessed} chunks=${result.chunksEmitted} ` +
package/src/bin/config.ts CHANGED
@@ -27,6 +27,33 @@ interface RawConfig {
27
27
  assetsDir?: unknown;
28
28
  widgetsDir?: unknown;
29
29
  widgetConfig?: unknown;
30
+ skillCatalog?: unknown;
31
+ }
32
+
33
+ /**
34
+ * Absolute path of the module the CLI imports to obtain the skill catalog, if configured.
35
+ *
36
+ * A path rather than an inline object because the catalog is derived from compiled code — this
37
+ * package's own tool registry, or a dependency's catalog artifact. Naming the module in
38
+ * package.json keeps the dependency explicit and reviewable instead of having build-tools go
39
+ * looking for a registry it should not know about.
40
+ *
41
+ * Kept separate from `resolveConfig` because loading it is asynchronous I/O, and `resolveConfig`
42
+ * is deliberately pure.
43
+ */
44
+ export function resolveSkillCatalogPath(pkg: Record<string, unknown>, cwd: string): string | undefined {
45
+ const raw = pkg[CONFIG_KEY];
46
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
47
+ return undefined;
48
+ }
49
+ const value = (raw as RawConfig).skillCatalog;
50
+ if (value === undefined) {
51
+ return undefined;
52
+ }
53
+ if (typeof value !== 'string' || value.length === 0) {
54
+ throw new VertesiaBuildConfigError(`"${CONFIG_KEY}.skillCatalog" must be a non-empty path when set.`);
55
+ }
56
+ return path.resolve(cwd, value);
30
57
  }
31
58
 
32
59
  /**
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Loading the skill catalog named by `vertesia-build.skillCatalog`.
3
+ *
4
+ * Shared by the `vertesia-build` CLI and the Vite dev-server plugin so both resolve
5
+ * `{@tool …}` / `{@skill …}` against the same registry. Without this the two paths disagree:
6
+ * a build would validate a skill body that `vite dev` and `vitest` then refuse to transform.
7
+ *
8
+ * The catalog is named as a *module path* rather than inlined, because it is derived from compiled
9
+ * code — a package's own tool registry, or a dependency's catalog artifact. Naming it in
10
+ * package.json keeps that dependency explicit instead of having build-tools go looking for a
11
+ * registry it should not know about.
12
+ */
13
+
14
+ import { readFileSync } from 'node:fs';
15
+ import path from 'node:path';
16
+ import { pathToFileURL } from 'node:url';
17
+ import type { PreprocessSkillMarkdownOptions } from './preprocess.js';
18
+
19
+ export const CONFIG_KEY = 'vertesia-build';
20
+
21
+ /**
22
+ * Shape a `skillCatalog` module may export.
23
+ *
24
+ * The name collections are `Iterable<string>` rather than `ReadonlySet`, so a catalog can export
25
+ * plain arrays — which is what a JSON-derived one naturally produces. They are normalised to sets
26
+ * here, which is why this cannot simply extend `PreprocessSkillMarkdownOptions`.
27
+ */
28
+ interface RawCatalog extends Omit<Partial<PreprocessSkillMarkdownOptions>, keyof RawCatalogNames> {
29
+ tools?: Iterable<string>;
30
+ skills?: Iterable<string>;
31
+ ambiguousTools?: Iterable<string>;
32
+ ambiguousSkills?: Iterable<string>;
33
+ unvalidatableTools?: Iterable<string>;
34
+ exampleLanguages?: Iterable<string>;
35
+ }
36
+
37
+ /** The option keys `RawCatalog` widens to `Iterable`. */
38
+ interface RawCatalogNames {
39
+ tools: unknown;
40
+ skills: unknown;
41
+ ambiguousTools: unknown;
42
+ ambiguousSkills: unknown;
43
+ unvalidatableTools: unknown;
44
+ exampleLanguages: unknown;
45
+ }
46
+
47
+ /**
48
+ * Import a catalog module and normalise it into preprocessor options.
49
+ *
50
+ * @throws when the module does not export both `tools` and `skills`.
51
+ */
52
+ export async function loadSkillCatalog(modulePath: string): Promise<PreprocessSkillMarkdownOptions> {
53
+ const loaded = (await import(pathToFileURL(modulePath).href)) as Record<string, unknown>;
54
+ const source = (loaded.default ?? loaded) as RawCatalog;
55
+
56
+ if (!source.tools || !source.skills) {
57
+ throw new Error(`skillCatalog module ${modulePath} must export { tools, skills }.`);
58
+ }
59
+ return {
60
+ tools: new Set(source.tools),
61
+ skills: new Set(source.skills),
62
+ ambiguousTools: source.ambiguousTools ? new Set(source.ambiguousTools) : undefined,
63
+ ambiguousSkills: source.ambiguousSkills ? new Set(source.ambiguousSkills) : undefined,
64
+ unvalidatableTools: source.unvalidatableTools ? new Set(source.unvalidatableTools) : undefined,
65
+ validateExample: source.validateExample,
66
+ validateField: source.validateField,
67
+ skillToolPrefix: source.skillToolPrefix,
68
+ exampleLanguages: source.exampleLanguages ? new Set(source.exampleLanguages) : undefined,
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Absolute path of the catalog module configured in a package.json, if any.
74
+ *
75
+ * Returns `undefined` when the key is absent — a package that uses no constructs needs no catalog,
76
+ * and the transformer only fails when a body actually uses one.
77
+ */
78
+ export function resolveSkillCatalogPath(pkg: Record<string, unknown>, cwd: string): string | undefined {
79
+ const raw = pkg[CONFIG_KEY];
80
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
81
+ return undefined;
82
+ }
83
+ const value = (raw as { skillCatalog?: unknown }).skillCatalog;
84
+ if (value === undefined) {
85
+ return undefined;
86
+ }
87
+ if (typeof value !== 'string' || value.length === 0) {
88
+ throw new Error(`"${CONFIG_KEY}.skillCatalog" must be a non-empty path when set.`);
89
+ }
90
+ return path.resolve(cwd, value);
91
+ }
92
+
93
+ /** Read `<dir>/package.json`, or `undefined` when it is missing or unparseable. */
94
+ export function readPackageJson(dir: string): Record<string, unknown> | undefined {
95
+ try {
96
+ return JSON.parse(readFileSync(path.join(dir, 'package.json'), 'utf-8')) as Record<string, unknown>;
97
+ } catch {
98
+ return undefined;
99
+ }
100
+ }