@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.
- package/README.md +297 -266
- package/lib/bin/build.js +26 -1
- package/lib/bin/build.js.map +1 -1
- package/lib/bin/config.d.ts +12 -0
- package/lib/bin/config.d.ts.map +1 -1
- package/lib/bin/config.js +25 -0
- package/lib/bin/config.js.map +1 -1
- package/lib/core/skill-markdown/load-catalog.d.ts +30 -0
- package/lib/core/skill-markdown/load-catalog.d.ts.map +1 -0
- package/lib/core/skill-markdown/load-catalog.js +69 -0
- package/lib/core/skill-markdown/load-catalog.js.map +1 -0
- package/lib/core/skill-markdown/preprocess.d.ts +127 -0
- package/lib/core/skill-markdown/preprocess.d.ts.map +1 -0
- package/lib/core/skill-markdown/preprocess.js +455 -0
- package/lib/core/skill-markdown/preprocess.js.map +1 -0
- package/lib/core/skill-markdown/schema-validator.d.ts +109 -0
- package/lib/core/skill-markdown/schema-validator.d.ts.map +1 -0
- package/lib/core/skill-markdown/schema-validator.js +420 -0
- package/lib/core/skill-markdown/schema-validator.js.map +1 -0
- package/lib/core/transformers/index.d.ts +1 -1
- package/lib/core/transformers/index.d.ts.map +1 -1
- package/lib/core/transformers/index.js +1 -1
- package/lib/core/transformers/index.js.map +1 -1
- package/lib/core/transformers/skill.d.ts +15 -1
- package/lib/core/transformers/skill.d.ts.map +1 -1
- package/lib/core/transformers/skill.js +82 -60
- package/lib/core/transformers/skill.js.map +1 -1
- package/lib/import-transform/detector.d.ts +19 -6
- package/lib/import-transform/detector.d.ts.map +1 -1
- package/lib/import-transform/detector.js +73 -24
- package/lib/import-transform/detector.js.map +1 -1
- package/lib/import-transform/index.d.ts.map +1 -1
- package/lib/import-transform/index.js +10 -1
- package/lib/import-transform/index.js.map +1 -1
- package/lib/import-transform/patterns.d.ts +7 -8
- package/lib/import-transform/patterns.d.ts.map +1 -1
- package/lib/import-transform/patterns.js +7 -8
- package/lib/import-transform/patterns.js.map +1 -1
- package/lib/index.d.ts +7 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -3
- package/lib/index.js.map +1 -1
- package/lib/vite/dev-server.d.ts +10 -0
- package/lib/vite/dev-server.d.ts.map +1 -1
- package/lib/vite/dev-server.js +36 -4
- package/lib/vite/dev-server.js.map +1 -1
- package/package.json +9 -12
- package/src/bin/build.ts +31 -2
- package/src/bin/config.ts +27 -0
- package/src/core/skill-markdown/load-catalog.ts +100 -0
- package/src/core/skill-markdown/preprocess.ts +632 -0
- package/src/core/skill-markdown/schema-validator.ts +517 -0
- package/src/core/transformers/index.ts +3 -0
- package/src/core/transformers/skill.ts +116 -53
- package/src/import-transform/detector.ts +78 -26
- package/src/import-transform/index.ts +12 -2
- package/src/import-transform/patterns.ts +7 -12
- package/src/index.ts +35 -2
- 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"}
|