@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
@@ -0,0 +1,455 @@
1
+ /**
2
+ * Semantic preprocessor for skill Markdown.
3
+ *
4
+ * Markdown gives syntax but no semantics: in "Use `execute_parallel_work_streams` with
5
+ * `customer_orders`", nothing distinguishes the tool from the sample data. Rather than guess,
6
+ * this preprocessor recognises exactly four explicit constructs and leaves every other byte of
7
+ * prose untouched:
8
+ *
9
+ * - `{@tool search_documents}` → renders as `` `search_documents` ``
10
+ * - `{@skill workstreams}` → renders as `` `learn_workstreams` ``
11
+ * - `{@param search_documents.query}` → renders as `` `query` ``, checked against the schema
12
+ * - ```` ```json tool=batch_execute ```` → validated against that tool, tag stripped on render
13
+ *
14
+ * What that buys is *fail-closed validation and consistent rendering*, not centralised naming —
15
+ * the name is still spelled out at each site, so a rename still touches every reference. The
16
+ * `{@skill}` form earns the most: it takes the `learn_` prefix convention out of the author's
17
+ * hands, and that convention is exactly what drifts.
18
+ *
19
+ * Deliberately pure. It reads no files, imports no registry, and never inspects Git; it is a
20
+ * function of (markdown, catalog) alone, so a build, a test, and CI cannot disagree — and a
21
+ * tarball or shallow checkout builds identically. Schema knowledge stays with the caller via
22
+ * `validateExample`, which keeps AJV and the dispatch model out of build-tools entirely.
23
+ */
24
+ /** The runtime convention: a skill named `x` is offered to the model as the tool `learn_x`. */
25
+ export const DEFAULT_SKILL_TOOL_PREFIX = 'learn_';
26
+ /** Snake_case, with hyphens tolerated because some remote skill names use them. */
27
+ const NAME = /^[a-z][a-z0-9_-]*$/;
28
+ /**
29
+ * `{@word …}`. The keyword is matched loosely so `{@tolo x}` is a reported typo, not prose.
30
+ *
31
+ * Two things keep the cost linear, neither of which costs any expressiveness — a construct's
32
+ * arguments are names and separators:
33
+ *
34
+ * - The argument group is anchored on a character the keyword cannot take, so the two cannot
35
+ * divide the same text. With both able to match `x`, `{@Axxxxxx…` with no closing brace gave
36
+ * the engine quadratically many ways to fail at a single position.
37
+ * - Neither argument class can cross a `{`. Otherwise the *scan* is quadratic rather than any
38
+ * one match: on `{@A/{@A/{@A/…` every opener sweeps to the end of the line before failing, so
39
+ * 240 KB took 5.2s. Stopping at the next `{` bounds each attempt by the distance to the next
40
+ * candidate start.
41
+ *
42
+ * The empty alternative keeps the group a string, and keeps `{@tool}` matching — and so being
43
+ * reported as naming nothing — rather than falling through as prose.
44
+ */
45
+ const CONSTRUCT = /\{@([A-Za-z][A-Za-z0-9_]*)([^A-Za-z0-9_{}][^{}]*|)\}/g;
46
+ /**
47
+ * The same construct, restricted to the real keywords, for use inside fenced blocks. The loose
48
+ * form would flag template syntax that fenced examples legitimately contain — Handlebars
49
+ * `{{@index}}`, for one — which the renderer only ever sees in prose.
50
+ *
51
+ * `[^{}]` for the same reason as above, and it keeps this guard reporting exactly what the
52
+ * renderer would have rendered: neither form matches a construct with a `{` in its arguments.
53
+ */
54
+ const FENCED_CONSTRUCT = /\{@(?:subagent_tool|tool|skill|param)\b[^{}]*\}/g;
55
+ /**
56
+ * A code fence line: up to 3 spaces of indent, a run of markers, then the info string.
57
+ *
58
+ * The info string is spelled `[^\r\n]*` rather than `.*` because lines are split on `\n` alone, so
59
+ * a CRLF file leaves a trailing `\r` that `.` — which excludes line terminators — cannot cross. The
60
+ * earlier spelling matched no fence at all in such a file: tags went unstripped and unvalidated,
61
+ * and the in-fence construct guard never ran, all without a single error.
62
+ */
63
+ // The info string is anchored on a non-blank first character so it cannot overlap the run of
64
+ // spaces before it. With both able to match a tab, a line of tabs gave the engine quadratically
65
+ // many ways to split the same text — harmless on skill sources, but this is a published library
66
+ // and its input is whatever a consumer passes. The empty alternative keeps group 3 a string.
67
+ const FENCE = /^([ \t]{0,3})(`{3,}|~{3,})[ \t]*([^ \t\r\n][^\r\n]*|)\r?$/;
68
+ /**
69
+ * Inline code spans, masked so `` `{@tool x}` `` can document the syntax without invoking it.
70
+ *
71
+ * Scanned rather than matched: the regex form needs a backreference and a body that can match a
72
+ * backtick two ways, which costs quadratic time on a run of them.
73
+ *
74
+ * The scan tokenises the backtick runs once and indexes them by suffix maximum, because the
75
+ * obvious scan is quadratic too: an opener with no closer would rescan the whole remainder, so
76
+ * descending run lengths (```` ```…``` ```` then ```` ``…`` ```` then …) make every opener fail
77
+ * after a full sweep. `suffixMax` answers "is any later run long enough?" in constant time, which
78
+ * leaves only openers that do close — and those consume everything they scanned past.
79
+ */
80
+ function maskInlineCode(source, masked) {
81
+ // Maximal runs of backticks: `start[i]` is where run i begins, `len[i]` how long it is.
82
+ const start = [];
83
+ const len = [];
84
+ for (let at = 0; at < source.length;) {
85
+ const open = source.indexOf('`', at);
86
+ if (open < 0) {
87
+ break;
88
+ }
89
+ let end = open + 1;
90
+ while (end < source.length && source[end] === '`') {
91
+ end++;
92
+ }
93
+ start.push(open);
94
+ len.push(end - open);
95
+ at = end;
96
+ }
97
+ if (start.length === 0) {
98
+ return source;
99
+ }
100
+ // suffixMax[i] is the longest run at or after i; suffixMax[start.length] is 0.
101
+ const suffixMax = new Array(start.length + 1).fill(0);
102
+ for (let i = start.length - 1; i >= 0; i--) {
103
+ suffixMax[i] = Math.max(len[i], suffixMax[i + 1]);
104
+ }
105
+ let out = '';
106
+ let at = 0;
107
+ let i = 0;
108
+ while (i < start.length) {
109
+ // Skip runs already consumed by an earlier span; `at` can also sit inside run i when a
110
+ // longer run closed a shorter opener and left backticks over.
111
+ if (start[i] + len[i] <= at) {
112
+ i++;
113
+ continue;
114
+ }
115
+ const open = Math.max(start[i], at);
116
+ const width = start[i] + len[i] - open;
117
+ const after = start[i] + len[i];
118
+ if (suffixMax[i + 1] < width) {
119
+ // No closing run: the backticks are literal text, and the search resumes after them so
120
+ // a later span in the same line is still masked.
121
+ out += source.slice(at, after);
122
+ at = after;
123
+ i++;
124
+ continue;
125
+ }
126
+ let close = i + 1;
127
+ while (len[close] < width) {
128
+ close++;
129
+ }
130
+ const end = start[close] + width;
131
+ masked.push(source.slice(open, end));
132
+ out += `${source.slice(at, open)}${MASK_OPEN}${masked.length - 1}${MASK_CLOSE}`;
133
+ at = end;
134
+ i = close;
135
+ }
136
+ return out + source.slice(at);
137
+ }
138
+ /** NUL cannot occur in these sources, so masking round-trips even through numeric prose. */
139
+ const MASK_OPEN = '\u0000';
140
+ const MASK_CLOSE = '\u0001';
141
+ /**
142
+ * An ATX heading: up to 3 spaces of indent, 1-6 `#`, then its text.
143
+ *
144
+ * The optional closing `#` run is trimmed in code rather than in the pattern. Expressed as
145
+ * `(.*?)[ \t]*#*[ \t]*$` it gave the engine several ways to divide the same trailing whitespace,
146
+ * which is quadratic on a line of tabs.
147
+ */
148
+ // The text group is anchored on a non-blank first character, for the same reason as `FENCE`: with
149
+ // the separator and the text both able to match a tab, a heading followed by a run of them gave
150
+ // the engine quadratically many ways to divide it. The empty alternative keeps group 1 a string.
151
+ const HEADING = /^ {0,3}#{1,6}(?:[ \t]+([^ \t\r\n][^\r\n]*|))?\r?$/;
152
+ /** The heading's text without its optional closing `#` run, trimmed as the pattern used to. */
153
+ function headingText(raw) {
154
+ let end = raw.length;
155
+ while (end > 0 && (raw[end - 1] === ' ' || raw[end - 1] === '\t'))
156
+ end--;
157
+ while (end > 0 && raw[end - 1] === '#')
158
+ end--;
159
+ while (end > 0 && (raw[end - 1] === ' ' || raw[end - 1] === '\t'))
160
+ end--;
161
+ return raw.slice(0, end);
162
+ }
163
+ const TAG_PREFIX = 'tool=';
164
+ /**
165
+ * The tool a heading names, when it names exactly one — `## batch_execute`, `` ## `batch_execute` ``
166
+ * or `## {@tool batch_execute}`.
167
+ *
168
+ * A section titled after a tool is the author stating, in prose, which tool the examples below
169
+ * belong to. That is independent evidence about the tag, and the only kind available: field overlap
170
+ * cannot tell two tools apart when both declare `id`.
171
+ */
172
+ function toolNamedByHeading(line, tools) {
173
+ const heading = HEADING.exec(line);
174
+ if (!heading) {
175
+ return undefined;
176
+ }
177
+ // The unwrapped name allows `-` because `NAME` does: some remote skill and tool names use it,
178
+ // and a narrower pattern here would silently skip the heading agreement check for them.
179
+ const named = headingText(heading[1] ?? '')
180
+ .replace(/^\{@tool[ \t]+([A-Za-z][A-Za-z0-9_-]*)\}$/, '$1')
181
+ .replace(/^`([A-Za-z][A-Za-z0-9_-]*)`$/, '$1');
182
+ return tools.has(named) ? named : undefined;
183
+ }
184
+ const DEFAULT_EXAMPLE_LANGUAGES = new Set(['json']);
185
+ /**
186
+ * `{@param tool.field}`: a tool name, then a dotted/`[]` path into its params schema.
187
+ *
188
+ * The path uses the same spelling as a `dispatch` descriptor — `inputs[].input` — so one path
189
+ * syntax covers both, and renders as the path alone: the tool is usually named in the same
190
+ * sentence, and repeating it reads worse than the prose the construct replaces.
191
+ */
192
+ const PARAM = /^([a-z][a-z0-9_-]*)\.([A-Za-z_][A-Za-z0-9_]*(?:\[\])*(?:\.[A-Za-z_][A-Za-z0-9_]*(?:\[\])*)*)$/;
193
+ function renderParam(whole, args, line, options, references, errors) {
194
+ const match = args.length === 1 ? PARAM.exec(args[0]) : null;
195
+ if (!match) {
196
+ errors.push(`line ${line}: '${whole}' must be written {@param tool.field}, with one dotted path`);
197
+ return whole;
198
+ }
199
+ const [, name, path] = match;
200
+ const rendered = `\`${path}\``;
201
+ const ambiguous = options.ambiguousTools?.has(name) ?? false;
202
+ let resolved = false;
203
+ if (ambiguous) {
204
+ errors.push(`line ${line}: '${whole}' is ambiguous — more than one provider defines the tool ` +
205
+ `'${name}'. Resolve the collision at the source before referencing it.`);
206
+ }
207
+ else if (!options.tools.has(name)) {
208
+ errors.push(`line ${line}: '${whole}' refers to a tool no provider registers`);
209
+ }
210
+ else if (!options.validateField) {
211
+ // The construct exists only to be checked. A catalog that supplies no field validator
212
+ // would turn every `{@param …}` in the tree into decoration, and nothing would say so.
213
+ errors.push(`line ${line}: '${whole}' cannot be checked: this build's catalog supplies no ` +
214
+ 'validateField. Add one (createSchemaFieldValidator), or write the field as prose.');
215
+ }
216
+ else {
217
+ let problems;
218
+ try {
219
+ problems = options.validateField({ tool: name, path });
220
+ }
221
+ catch (err) {
222
+ // Same contract as validateExample: a broken validator is a finding, not an exception
223
+ // thrown from an unrelated frame.
224
+ problems = [`could not be checked: ${err.message}`];
225
+ }
226
+ errors.push(...problems.map((problem) => `line ${line}: '${whole}' ${problem}`));
227
+ resolved = problems.length === 0;
228
+ }
229
+ references.push({ kind: 'param', name, path, rendered, line, resolved });
230
+ return rendered;
231
+ }
232
+ /**
233
+ * `{@subagent_tool launcher tool}` — a tool the sub-agent launched by `launcher` will call.
234
+ *
235
+ * Renders as the tool name alone, since that is what the reader needs: the sentence around it
236
+ * already says whose action it is. Both names are resolved here; whether `launcher` really
237
+ * launches an interaction configured with `tool` is checked by `check:skills`, which is the only
238
+ * place that can see interaction definitions.
239
+ */
240
+ function renderSubagentTool(whole, args, line, options, references, errors) {
241
+ if (args.length !== 2 || !NAME.test(args[0]) || !NAME.test(args[1])) {
242
+ errors.push(`line ${line}: '${whole}' must be written {@subagent_tool launcher tool}, naming two tools`);
243
+ return whole;
244
+ }
245
+ const [launcher, name] = args;
246
+ const rendered = `\`${name}\``;
247
+ let resolved = true;
248
+ for (const candidate of [launcher, name]) {
249
+ if (options.ambiguousTools?.has(candidate)) {
250
+ errors.push(`line ${line}: '${whole}' is ambiguous — more than one provider defines the tool ` +
251
+ `'${candidate}'. Resolve the collision at the source before referencing it.`);
252
+ resolved = false;
253
+ }
254
+ else if (!options.tools.has(candidate)) {
255
+ errors.push(`line ${line}: '${whole}' refers to a tool no provider registers: '${candidate}'`);
256
+ resolved = false;
257
+ }
258
+ }
259
+ references.push({ kind: 'subagent_tool', name, rendered, line, resolved });
260
+ return rendered;
261
+ }
262
+ /** Substitute constructs on a single line, leaving inline code spans verbatim. */
263
+ function renderLine(source, line, options, references, errors) {
264
+ if (!source.includes('{@')) {
265
+ return source;
266
+ }
267
+ const prefix = options.skillToolPrefix ?? DEFAULT_SKILL_TOOL_PREFIX;
268
+ const masked = [];
269
+ const text = maskInlineCode(source, masked);
270
+ // Every `{@` must be consumed by a well-formed construct. An unterminated one would
271
+ // otherwise sail through as prose and reach the model as raw template syntax.
272
+ const consumed = new Set();
273
+ const rendered = text.replace(CONSTRUCT, (whole, keyword, rest, offset) => {
274
+ consumed.add(offset);
275
+ const args = rest.trim().split(/\s+/).filter(Boolean);
276
+ if (keyword !== 'tool' && keyword !== 'skill' && keyword !== 'param' && keyword !== 'subagent_tool') {
277
+ errors.push(`line ${line}: unknown construct '{@${keyword} …}' (expected {@tool …}, {@skill …}, ` +
278
+ '{@param …} or {@subagent_tool …})');
279
+ return whole;
280
+ }
281
+ if (keyword === 'param') {
282
+ return renderParam(whole, args, line, options, references, errors);
283
+ }
284
+ if (keyword === 'subagent_tool') {
285
+ return renderSubagentTool(whole, args, line, options, references, errors);
286
+ }
287
+ if (args.length !== 1 || !NAME.test(args[0])) {
288
+ errors.push(`line ${line}: '${whole}' must name exactly one ${keyword}`);
289
+ return whole;
290
+ }
291
+ const name = args[0];
292
+ const kind = keyword;
293
+ const known = kind === 'tool' ? options.tools : options.skills;
294
+ const ambiguous = (kind === 'tool' ? options.ambiguousTools : options.ambiguousSkills)?.has(name) ?? false;
295
+ const resolved = known.has(name) && !ambiguous;
296
+ const target = kind === 'skill' ? `${prefix}${name}` : name;
297
+ if (ambiguous) {
298
+ errors.push(`line ${line}: '${whole}' is ambiguous — more than one provider defines the ${kind} ` +
299
+ `'${name}'. Resolve the collision at the source before referencing it.`);
300
+ }
301
+ else if (!known.has(name)) {
302
+ errors.push(`line ${line}: '${whole}' refers to a ${kind} no provider registers`);
303
+ }
304
+ references.push({ kind, name, rendered: `\`${target}\``, line, resolved });
305
+ return `\`${target}\``;
306
+ });
307
+ for (const opener of text.matchAll(/\{@/g)) {
308
+ if (!consumed.has(opener.index)) {
309
+ errors.push(`line ${line}: malformed construct at '${text.slice(opener.index, opener.index + 24)}…'`);
310
+ }
311
+ }
312
+ return rendered.replace(new RegExp(`${MASK_OPEN}(\\d+)${MASK_CLOSE}`, 'g'), (_, index) => masked[Number(index)]);
313
+ }
314
+ function isClosingFence(line, marker) {
315
+ const match = FENCE.exec(line);
316
+ return !!match && match[2][0] === marker[0] && match[2].length >= marker.length && match[3].trim() === '';
317
+ }
318
+ /**
319
+ * Render explicit constructs and validate tagged examples.
320
+ *
321
+ * Never throws and never reads the environment: a caller wanting a hard failure inspects
322
+ * `errors`, or uses `assertSkillMarkdown`.
323
+ */
324
+ export function preprocessSkillMarkdown(markdown, options) {
325
+ const lines = markdown.split('\n');
326
+ const out = [];
327
+ const references = [];
328
+ const examples = [];
329
+ const errors = [];
330
+ // The tool named by the most recent heading, if it named one. Any other heading clears it, so a
331
+ // later unrelated section never inherits the claim.
332
+ let headingTool;
333
+ let headingLine = 0;
334
+ for (let i = 0; i < lines.length;) {
335
+ const fence = FENCE.exec(lines[i]);
336
+ if (!fence) {
337
+ if (HEADING.test(lines[i])) {
338
+ headingTool = toolNamedByHeading(lines[i], options.tools);
339
+ headingLine = i + 1;
340
+ }
341
+ out.push(renderLine(lines[i], i + 1, options, references, errors));
342
+ i++;
343
+ continue;
344
+ }
345
+ // Fenced block: emitted verbatim apart from the `tool=` tag, which is build metadata.
346
+ const [, indent, marker, info] = fence;
347
+ const openLine = i + 1;
348
+ const parts = info.trim().split(/\s+/).filter(Boolean);
349
+ const lang = parts[0] ?? '';
350
+ const tagIndexes = parts.flatMap((p, index) => (index > 0 && p.startsWith(TAG_PREFIX) ? [index] : []));
351
+ const tagIndex = tagIndexes[0] ?? -1;
352
+ const tag = tagIndex === -1 ? undefined : parts[tagIndex].slice(TAG_PREFIX.length);
353
+ if (tagIndexes.length > 1) {
354
+ // Silently honouring the first would validate against a tool the author did not mean.
355
+ errors.push(`line ${openLine}: fence carries ${tagIndexes.length} ${TAG_PREFIX} tags ` +
356
+ `(${tagIndexes.map((index) => parts[index]).join(', ')}); exactly one is allowed`);
357
+ }
358
+ const body = [];
359
+ let j = i + 1;
360
+ for (; j < lines.length && !isClosingFence(lines[j], marker); j++) {
361
+ body.push(lines[j]);
362
+ }
363
+ const closed = j < lines.length;
364
+ if (!closed && tag !== undefined) {
365
+ // An unterminated tagged fence swallows the rest of the document into its "payload",
366
+ // so the tag validates nonsense and the prose below it is never rendered.
367
+ errors.push(`line ${openLine}: fence tagged '${TAG_PREFIX}${tag}' is never closed`);
368
+ }
369
+ // Fence bodies are passed through untouched, so a construct written inside one is never
370
+ // rendered and reaches the model verbatim — and, because it is not a reference either, no
371
+ // other check sees it. Silence is the whole danger, so report it here.
372
+ for (const [offset, line] of body.entries()) {
373
+ for (const found of line.matchAll(FENCED_CONSTRUCT)) {
374
+ errors.push(`line ${openLine + 1 + offset}: '${found[0]}' is inside a code fence, where it ` +
375
+ 'is passed through unrendered; move it into prose or write the rendered form');
376
+ }
377
+ }
378
+ // Rewrite the opening line only when there is a tag to remove, so untagged fences keep
379
+ // their exact spelling — a preprocessor that reformats untouched prose is a liability.
380
+ // The line's own terminator is carried over for the same reason: rewriting one CRLF line
381
+ // as LF would leave the file mixed.
382
+ const cr = lines[i].endsWith('\r') ? '\r' : '';
383
+ const open = tagIndex === -1
384
+ ? lines[i]
385
+ : `${indent}${marker}${parts.filter((_, index) => index !== tagIndex).join(' ')}${cr}`;
386
+ out.push(open, ...body);
387
+ if (closed) {
388
+ out.push(lines[j]);
389
+ }
390
+ i = closed ? j + 1 : j;
391
+ if (tag !== undefined) {
392
+ if (headingTool !== undefined && tag !== headingTool) {
393
+ // Both were written deliberately, so one of them is wrong and only the author knows
394
+ // which. Schema validation cannot arbitrate: it would have accepted either.
395
+ errors.push(`line ${openLine}: fence is tagged '${TAG_PREFIX}${tag}' under the heading for ` +
396
+ `'${headingTool}' (line ${headingLine}); the tag and the heading name ` +
397
+ 'different tools');
398
+ }
399
+ examples.push(validateFenceExample(tag, lang, body.join('\n'), openLine, options, errors));
400
+ }
401
+ }
402
+ return { markdown: out.join('\n'), references, examples, errors };
403
+ }
404
+ function validateFenceExample(tag, lang, body, line, options, errors) {
405
+ const example = { tool: tag, lang, source: body, line, errors: [] };
406
+ const languages = options.exampleLanguages ?? DEFAULT_EXAMPLE_LANGUAGES;
407
+ if (!NAME.test(tag)) {
408
+ example.errors.push(`'${TAG_PREFIX}${tag}' is not a valid tool name`);
409
+ }
410
+ else if (!languages.has(lang)) {
411
+ // A tag on a shell or Python fence can never be validated, so it is a false assurance:
412
+ // the fence looks gated in review while nothing checks it.
413
+ example.errors.push(`is tagged '${TAG_PREFIX}${tag}' on a '${lang || '(none)'}' fence; only ` +
414
+ `${[...languages].join(', ')} fences can be validated`);
415
+ }
416
+ else if (!options.tools.has(tag)) {
417
+ example.errors.push(`is tagged for '${tag}', which no provider registers`);
418
+ }
419
+ else if (options.ambiguousTools?.has(tag)) {
420
+ example.errors.push(`is tagged for '${tag}', which more than one provider defines`);
421
+ }
422
+ else if (options.unvalidatableTools?.has(tag)) {
423
+ example.errors.push(`is tagged for '${tag}', whose schema this build cannot see, so the payload cannot be ` +
424
+ 'verified. Remove the tag, or make the schema available to the catalog.');
425
+ }
426
+ else {
427
+ try {
428
+ example.value = JSON.parse(body);
429
+ }
430
+ catch (err) {
431
+ example.errors.push(`is tagged for validation but is not strict JSON: ${err.message}`);
432
+ }
433
+ if (example.value !== undefined && options.validateExample) {
434
+ try {
435
+ example.errors.push(...options.validateExample({ tool: tag, value: example.value }));
436
+ }
437
+ catch (err) {
438
+ // The no-throw contract is the caller's guarantee; a broken validator must be
439
+ // reported as a finding, not turned into an exception from an unrelated frame.
440
+ example.errors.push(`could not be validated: ${err.message}`);
441
+ }
442
+ }
443
+ }
444
+ errors.push(...example.errors.map((message) => `line ${line}: example ${message}`));
445
+ return example;
446
+ }
447
+ /** Convenience for build callers: preprocess, or throw once with every problem listed. */
448
+ export function assertSkillMarkdown(markdown, options, source) {
449
+ const result = preprocessSkillMarkdown(markdown, options);
450
+ if (result.errors.length > 0) {
451
+ throw new Error(`Skill markdown errors in ${source}:\n${result.errors.map((e) => ` - ${e}`).join('\n')}`);
452
+ }
453
+ return result;
454
+ }
455
+ //# sourceMappingURL=preprocess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preprocess.js","sourceRoot":"","sources":["../../../src/core/skill-markdown/preprocess.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * A ready-made `validateExample` for `preprocessSkillMarkdown`.
3
+ *
4
+ * The preprocessor deliberately knows nothing about schemas — it hands each `tool=`-tagged
5
+ * payload to a callback. This module is the callback most consumers want: JSON Schema validation
6
+ * plus the one thing JSON Schema structurally cannot do.
7
+ *
8
+ * That gap is dispatchers. A tool like `batch_execute` declares `tool_name: { type: 'string' }`
9
+ * and an opaque `input` object, so AJV accepts `{"tool_name": "web_search", "input": {...}}` even
10
+ * when `web_search` does not exist and the input belongs to a different tool's schema. A
11
+ * `dispatch` descriptor names the field carrying the tool name and the field carrying its
12
+ * payload, which is enough to resolve one against the registry and validate the other against the
13
+ * *dispatched* tool.
14
+ *
15
+ * Input is plain data — names, JSON Schemas, descriptors — so this stays independent of any
16
+ * particular tool registry.
17
+ */
18
+ export interface ToolDispatchDescriptor {
19
+ /** Path to the field holding a dispatched tool name. Dots nest, `[]` walks an array. */
20
+ field: string;
21
+ /** Path to the payload forwarded to that tool, if any. */
22
+ inputField?: string;
23
+ /** Tool names the dispatcher refuses at runtime. */
24
+ deny?: readonly string[];
25
+ /**
26
+ * True when the runtime strips a leading `+` or `-` before resolving the name — the selection
27
+ * prefixes that add to, or remove from, the default toolset. Without this the documented
28
+ * `+learn_web_search` form reads as an unregistered tool.
29
+ */
30
+ stripsSelectionPrefix?: boolean;
31
+ }
32
+ export interface ToolSchemaEntry {
33
+ name: string;
34
+ /** JSON Schema for the tool's parameters. Absent when the provider exposes no schema. */
35
+ params?: unknown;
36
+ dispatch?: ToolDispatchDescriptor;
37
+ }
38
+ /**
39
+ * Walk a dotted/`[]` path, returning every value found.
40
+ *
41
+ * `inputs[].input` over `{inputs: [{input: A}, {input: B}]}` yields `[A, B]`. Missing segments
42
+ * yield nothing rather than `undefined`, so callers cannot mistake absence for a null payload.
43
+ */
44
+ export declare function nodesAtPath(value: unknown, path: string): unknown[];
45
+ /** Path values narrowed to strings — used for fields that carry a tool name. */
46
+ export declare function toolNamesAtPath(value: unknown, path: string): string[];
47
+ /** Walk the same dotted/`[]` path through a JSON Schema rather than through a value. */
48
+ export declare function schemaNodeAtPath(schema: unknown, path: string): Record<string, unknown> | undefined;
49
+ /**
50
+ * Build a `validateField` callback over a set of tools.
51
+ *
52
+ * A skill that says a tool "takes `query` as an object" is making a claim about that tool's
53
+ * schema, and it is exactly the claim that rots when a parameter is renamed. `{@param …}` states
54
+ * the claim so this can check it.
55
+ *
56
+ * Every path that cannot be judged is reported rather than passed: a tool absent from these
57
+ * entries, a tool with no visible schema, a reference that does not resolve. A construct that
58
+ * looks checked while checking nothing is the failure mode a `tool=` tag on an unvalidatable tool
59
+ * is already rejected for, and it is worse here — `{@param …}` exists only to be checked.
60
+ */
61
+ export declare function createSchemaFieldValidator(tools: readonly ToolSchemaEntry[]): (ref: {
62
+ tool: string;
63
+ path: string;
64
+ }) => string[];
65
+ /**
66
+ * Is the descriptor coherent with the tool's own schema?
67
+ *
68
+ * Returns the problems, empty when sound. Callers treat a problem as an error rather than
69
+ * skipping the check: a descriptor pointing at a renamed field would otherwise disable dispatcher
70
+ * validation for that tool silently, which is the worst possible failure for a safety net.
71
+ */
72
+ export declare function checkDispatchDescriptor(tool: ToolSchemaEntry): string[];
73
+ /** One dispatched name found in a payload, already judged against the registry. */
74
+ export interface DispatchResolution {
75
+ name: string;
76
+ /** Set when the name resolves to a usable tool. */
77
+ tool?: ToolSchemaEntry;
78
+ /** Set when it does not: the reason, ready to report. */
79
+ problem?: string;
80
+ }
81
+ /**
82
+ * Resolve every dispatched name a payload carries, honouring the descriptor's deny list.
83
+ *
84
+ * Shared so the build gate and the repository audit apply one rule. They differ only in how they
85
+ * report: one throws a build error, the other builds a `Finding` with a file and a subject.
86
+ */
87
+ export declare function resolveDispatchedNames(tool: ToolSchemaEntry, value: unknown, lookup: (name: string) => ToolSchemaEntry | undefined): DispatchResolution[];
88
+ /**
89
+ * Pair each forwarded payload with the tool that will receive it.
90
+ *
91
+ * One dispatched name applies to every input; otherwise pair positionally. Any other shape is
92
+ * ambiguous and yields no pairing — guessing there would manufacture exactly the false positives
93
+ * this whole mechanism exists to avoid.
94
+ */
95
+ export declare function pairDispatchedInputs(tool: ToolSchemaEntry, value: unknown, dispatched: readonly ToolSchemaEntry[]): Array<{
96
+ target: ToolSchemaEntry;
97
+ input: Record<string, unknown>;
98
+ }>;
99
+ /**
100
+ * Build a `validateExample` callback over a set of tools.
101
+ *
102
+ * Returns human-readable problems; an empty array means the example is valid. Tools without a
103
+ * schema are skipped rather than guessed at.
104
+ */
105
+ export declare function createSchemaExampleValidator(tools: readonly ToolSchemaEntry[]): (example: {
106
+ tool: string;
107
+ value: unknown;
108
+ }) => string[];
109
+ //# sourceMappingURL=schema-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-validator.d.ts","sourceRoot":"","sources":["../../../src/core/skill-markdown/schema-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,WAAW,sBAAsB;IACnC,wFAAwF;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACrC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAyBnE;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtE;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAenG;AA4HD;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACtC,KAAK,EAAE,SAAS,eAAe,EAAE,GAClC,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,EAAE,CAwCnD;AAcD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,EAAE,CAkBvE;AAED,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAClC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,GAAG,SAAS,GACtD,kBAAkB,EAAE,CAmBtB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,SAAS,eAAe,EAAE,GACvC,KAAK,CAAC;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAmBpE;AAmDD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CACxC,KAAK,EAAE,SAAS,eAAe,EAAE,GAClC,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,KAAK,MAAM,EAAE,CAwEzD"}