aontu 0.65.0 → 0.66.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.
- package/dist/aontu.d.ts +1 -1
- package/dist/aontu.js +1 -1
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +220 -2
- package/dist/cli.js.map +1 -1
- package/dist/helpdoc.js +1 -1
- package/dist/helpdoc.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/grammar/aontu.gbnf +8 -18
- package/grammar/aontu.lark +6 -14
- package/grammar/aontu.tmLanguage.json +4 -6
- package/package.json +3 -2
- package/skill/tasks.md +12 -7
- package/src/aontu.ts +1 -1
- package/src/cli.ts +243 -3
- package/src/helpdoc.ts +1 -1
package/dist/aontu.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { loadProfile } from './profile';
|
|
|
23
23
|
import { desugarTemplate, resugarTemplate, markerFor } from './template';
|
|
24
24
|
import { format, unifiedDiff } from './format';
|
|
25
25
|
export type { LintFinding, FormatReport, FormatOptions } from './format';
|
|
26
|
-
declare const VERSION = "0.
|
|
26
|
+
declare const VERSION = "0.66.0";
|
|
27
27
|
declare class Aontu {
|
|
28
28
|
opts: AontuOptions;
|
|
29
29
|
lang: Lang;
|
package/dist/aontu.js
CHANGED
|
@@ -58,7 +58,7 @@ Object.defineProperty(exports, "markerFor", { enumerable: true, get: function ()
|
|
|
58
58
|
const format_1 = require("./format");
|
|
59
59
|
Object.defineProperty(exports, "format", { enumerable: true, get: function () { return format_1.format; } });
|
|
60
60
|
Object.defineProperty(exports, "unifiedDiff", { enumerable: true, get: function () { return format_1.unifiedDiff; } });
|
|
61
|
-
const VERSION = '0.
|
|
61
|
+
const VERSION = '0.66.0';
|
|
62
62
|
exports.VERSION = VERSION;
|
|
63
63
|
function genQuiet(val, aontu) {
|
|
64
64
|
return val.gen(aontu.ctx({ collect: true }));
|
package/dist/cli.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ declare function runPackageVerb(verb: string, argv: string[], servers: Servers):
|
|
|
49
49
|
declare function runModel(argv: string[]): number;
|
|
50
50
|
declare function runRelations(argv: string[]): number;
|
|
51
51
|
declare function runTrace(argv: string[]): number;
|
|
52
|
+
declare function runRender(argv: string[]): Promise<number>;
|
|
52
53
|
declare function runReaches(argv: string[]): number;
|
|
53
54
|
declare function runView(argv: string[]): number;
|
|
54
55
|
declare function runJsonSchema(argv: string[]): number;
|
|
@@ -80,4 +81,4 @@ declare const KNOWN_VERBS: string[];
|
|
|
80
81
|
declare function looksLikeVerb(arg: string): boolean;
|
|
81
82
|
declare function nearestVerb(word: string, verbs: string[]): string;
|
|
82
83
|
declare function main(argv: string[], servers?: Servers): void;
|
|
83
|
-
export { evalSource, main, runVet, runSubsume, runBreaking, runTrim, runRelations, runReaches, runView, runJsonSchema, runTemplate, runTrace, runPkg, runModel, runPackageVerb, pkgToolOptions, serveUntilInterrupted, runHash, runGet, runHelp, runExplain, runInit, nearestVerb, looksLikeVerb, KNOWN_VERBS, runWhy, renderWhyText, runSet, runAllow, runAgentsMd, runFmt, watchChange, watchSignature, vetWaiter, deprecatedAt, };
|
|
84
|
+
export { evalSource, main, runVet, runSubsume, runBreaking, runTrim, runRelations, runReaches, runView, runJsonSchema, runTemplate, runTrace, runRender, runPkg, runModel, runPackageVerb, pkgToolOptions, serveUntilInterrupted, runHash, runGet, runHelp, runExplain, runInit, nearestVerb, looksLikeVerb, KNOWN_VERBS, runWhy, renderWhyText, runSet, runAllow, runAgentsMd, runFmt, watchChange, watchSignature, vetWaiter, deprecatedAt, };
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.runView = runView;
|
|
|
15
15
|
exports.runJsonSchema = runJsonSchema;
|
|
16
16
|
exports.runTemplate = runTemplate;
|
|
17
17
|
exports.runTrace = runTrace;
|
|
18
|
+
exports.runRender = runRender;
|
|
18
19
|
exports.runPkg = runPkg;
|
|
19
20
|
exports.runModel = runModel;
|
|
20
21
|
exports.runPackageVerb = runPackageVerb;
|
|
@@ -76,6 +77,9 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
76
77
|
[--profile <file>] <file>
|
|
77
78
|
aontu trace [--at <path>] [--format json] [--marker <token>]
|
|
78
79
|
[--profile <file>] <file>
|
|
80
|
+
aontu render [--check] [--at <path>] [--format json]
|
|
81
|
+
[--marker <token>] [--profile <file>]
|
|
82
|
+
<file|folder> <path>
|
|
79
83
|
aontu hash [options] <file>
|
|
80
84
|
aontu sync [--frozen] [options] [dir]
|
|
81
85
|
aontu add <pkg>[@<version>] [options] [dir]
|
|
@@ -390,6 +394,31 @@ every other line is a line of output.
|
|
|
390
394
|
|
|
391
395
|
Template exit codes: 0 written, 1 --check drift, 2 usage or I/O.
|
|
392
396
|
|
|
397
|
+
Render options:
|
|
398
|
+
--check Compare what the generator writes with what <path>
|
|
399
|
+
holds, write nothing, and exit 1 on drift
|
|
400
|
+
--at <path> Where the component tree lives in the document
|
|
401
|
+
(default $.out)
|
|
402
|
+
--format json Print the files written, or the drift, as JSON
|
|
403
|
+
--marker <t> The file is a generator, and this is its marker
|
|
404
|
+
(default //-, and #- --- /*- <!--- by extension)
|
|
405
|
+
--profile <f> A profile file, whose template.ext names the
|
|
406
|
+
extensions it marks and template.marker the marker
|
|
407
|
+
|
|
408
|
+
The render verb writes the component tree a generator answers. The
|
|
409
|
+
tree is handed to jostraca, the generator runtime, which writes the
|
|
410
|
+
files: a tree that is one file is written to <path> itself, unless
|
|
411
|
+
<path> is a directory, and any other tree is written below <path>.
|
|
412
|
+
With --check nothing is written and <path> is compared with what the
|
|
413
|
+
generator writes, one "kind: file" line per difference.
|
|
414
|
+
A folder as the generator is a set: every regular file directly in
|
|
415
|
+
it, dotfiles aside, in name order, and their trees are written below
|
|
416
|
+
<path> as one run, so a path two of them claim is refused. A file with
|
|
417
|
+
no marker line in it is refused by name.
|
|
418
|
+
|
|
419
|
+
Render exit codes: 0 written or clean, 1 --check drift, 2 usage or
|
|
420
|
+
I/O, 4 the document does not stand up, or --at names nothing.
|
|
421
|
+
|
|
393
422
|
Model set options:
|
|
394
423
|
--entry <file> The document the change is checked against
|
|
395
424
|
--overlay <file> The file the change is appended to (created if
|
|
@@ -2446,6 +2475,192 @@ function runTrace(argv) {
|
|
|
2446
2475
|
}
|
|
2447
2476
|
return 0;
|
|
2448
2477
|
}
|
|
2478
|
+
// ---------------------------------------------------------------------
|
|
2479
|
+
// The writer (ADR-040). A generator answers a component tree; this verb
|
|
2480
|
+
// hands it to jostraca, which writes the files below a path or holds
|
|
2481
|
+
// them to it.
|
|
2482
|
+
const RENDER_HELP = 'aontu render [--check] [--at <path>] [--format json] ' +
|
|
2483
|
+
'[--marker <token>] [--profile <file>] <file|folder> <path> (try --help)';
|
|
2484
|
+
// Loaded at the call, so every other verb starts without it.
|
|
2485
|
+
function generatorRuntime() {
|
|
2486
|
+
return require('jostraca');
|
|
2487
|
+
}
|
|
2488
|
+
function isDirectory(path) {
|
|
2489
|
+
return true === (0, node_fs_1.statSync)(path, { throwIfNoEntry: false })?.isDirectory();
|
|
2490
|
+
}
|
|
2491
|
+
async function runRender(argv) {
|
|
2492
|
+
const trusted = takeTrust(argv);
|
|
2493
|
+
if (null == trusted) {
|
|
2494
|
+
return 2;
|
|
2495
|
+
}
|
|
2496
|
+
argv = trusted.argv;
|
|
2497
|
+
const trust = trusted.trust;
|
|
2498
|
+
const rest = [];
|
|
2499
|
+
const profileFiles = [];
|
|
2500
|
+
let format = 'text';
|
|
2501
|
+
let at = undefined;
|
|
2502
|
+
let marker = undefined;
|
|
2503
|
+
let check = false;
|
|
2504
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2505
|
+
const arg = argv[i];
|
|
2506
|
+
if ('-h' === arg || '--help' === arg) {
|
|
2507
|
+
process.stdout.write(HELP);
|
|
2508
|
+
return 0;
|
|
2509
|
+
}
|
|
2510
|
+
if ('--check' === arg) {
|
|
2511
|
+
check = true;
|
|
2512
|
+
}
|
|
2513
|
+
else if ('--format' === arg) {
|
|
2514
|
+
const f = argv[++i];
|
|
2515
|
+
if ('text' !== f && 'json' !== f) {
|
|
2516
|
+
process.stderr.write('aontu: --format needs text or json\n');
|
|
2517
|
+
return 2;
|
|
2518
|
+
}
|
|
2519
|
+
format = f;
|
|
2520
|
+
}
|
|
2521
|
+
else if ('--at' === arg) {
|
|
2522
|
+
at = argv[++i];
|
|
2523
|
+
if (null == at || '' === at) {
|
|
2524
|
+
process.stderr.write('aontu: --at needs a path\n');
|
|
2525
|
+
return 2;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
else if ('--marker' === arg) {
|
|
2529
|
+
marker = argv[++i];
|
|
2530
|
+
if (null == marker || '' === marker) {
|
|
2531
|
+
process.stderr.write('aontu: --marker needs a token\n');
|
|
2532
|
+
return 2;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
else if ('--profile' === arg) {
|
|
2536
|
+
const pf = argv[++i];
|
|
2537
|
+
if (null == pf || '' === pf) {
|
|
2538
|
+
process.stderr.write('aontu: --profile needs a file\n');
|
|
2539
|
+
return 2;
|
|
2540
|
+
}
|
|
2541
|
+
profileFiles.push(pf);
|
|
2542
|
+
}
|
|
2543
|
+
else if (arg.startsWith('-')) {
|
|
2544
|
+
process.stderr.write(`aontu: unknown render option ${arg} (try --help)\n`);
|
|
2545
|
+
return 2;
|
|
2546
|
+
}
|
|
2547
|
+
else {
|
|
2548
|
+
rest.push(arg);
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
if (2 !== rest.length) {
|
|
2552
|
+
process.stderr.write(`aontu: render needs a file and a path\n${RENDER_HELP}\n`);
|
|
2553
|
+
return 2;
|
|
2554
|
+
}
|
|
2555
|
+
const [file, dest] = rest;
|
|
2556
|
+
const declared = loadProfiles(profileFiles, trust);
|
|
2557
|
+
if ('number' === typeof declared) {
|
|
2558
|
+
return declared;
|
|
2559
|
+
}
|
|
2560
|
+
// A FOLDER IS A SET OF GENERATORS: every regular file directly in it,
|
|
2561
|
+
// dotfiles aside, in code-point order, written as one tree.
|
|
2562
|
+
let entries;
|
|
2563
|
+
try {
|
|
2564
|
+
entries = (0, node_fs_1.readdirSync)(file, { withFileTypes: true });
|
|
2565
|
+
}
|
|
2566
|
+
catch (err) {
|
|
2567
|
+
entries = undefined;
|
|
2568
|
+
}
|
|
2569
|
+
const set = undefined !== entries;
|
|
2570
|
+
const files = undefined === entries ? [file] :
|
|
2571
|
+
entries.filter((e) => e.isFile() && !e.name.startsWith('.'))
|
|
2572
|
+
.map((e) => e.name).sort(keyorder_1.cmpCodePoint).map((n) => (0, node_path_1.join)(file, n));
|
|
2573
|
+
if (0 === files.length) {
|
|
2574
|
+
process.stderr.write(`aontu: ${file} holds no generator\n`);
|
|
2575
|
+
return 2;
|
|
2576
|
+
}
|
|
2577
|
+
const trees = [];
|
|
2578
|
+
for (const f of files) {
|
|
2579
|
+
let src;
|
|
2580
|
+
try {
|
|
2581
|
+
src = (0, node_fs_1.readFileSync)(f, 'utf8');
|
|
2582
|
+
}
|
|
2583
|
+
catch (err) {
|
|
2584
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2585
|
+
return 2;
|
|
2586
|
+
}
|
|
2587
|
+
if (!/[.](aon|aontu)$/.test(f)) {
|
|
2588
|
+
const mark = marker ?? (0, template_1.markerFromProfiles)(declared, f) ?? (0, template_1.markerFor)(f);
|
|
2589
|
+
if (!(0, template_1.templateOutputs)(src, mark).some((out) => !out)) {
|
|
2590
|
+
process.stderr.write(`aontu: ${f} carries no ${mark} marker line, ` +
|
|
2591
|
+
'so there is no aontu in it to render\n');
|
|
2592
|
+
return 2;
|
|
2593
|
+
}
|
|
2594
|
+
src = (0, template_1.desugarTemplate)(src, mark);
|
|
2595
|
+
}
|
|
2596
|
+
const report = (0, aontu_1.get)(src, at ?? '$.out', {
|
|
2597
|
+
view: 'json', path: f, ...verbOpts(trust, entryRootOf(f)),
|
|
2598
|
+
});
|
|
2599
|
+
if (!report.ok) {
|
|
2600
|
+
process.stderr.write(report.findings.map(renderFinding).join('\n') + '\n');
|
|
2601
|
+
return 4;
|
|
2602
|
+
}
|
|
2603
|
+
const tree = JSON.parse(report.out);
|
|
2604
|
+
// A `File` without a name is refused: the runtime ports disagree
|
|
2605
|
+
// about it.
|
|
2606
|
+
if ('File' === tree?.cmp && 'string' !== typeof tree.props?.name) {
|
|
2607
|
+
process.stderr.write(`aontu: ${f}: the file at ${at ?? '$.out'} has no name\n`);
|
|
2608
|
+
return 4;
|
|
2609
|
+
}
|
|
2610
|
+
trees.push(tree);
|
|
2611
|
+
}
|
|
2612
|
+
// ONE FILE GOES TO THE PATH ITSELF, unless the path is a directory; a
|
|
2613
|
+
// set is written below the path whatever its trees are.
|
|
2614
|
+
let folder = dest;
|
|
2615
|
+
const tree = set ? trees.flatMap((t) => Array.isArray(t) ? t : [t]) : trees[0];
|
|
2616
|
+
if (!set && 'File' === tree?.cmp && !isDirectory(dest)) {
|
|
2617
|
+
tree.props.name = (0, node_path_1.basename)(dest);
|
|
2618
|
+
folder = (0, node_path_1.dirname)(dest);
|
|
2619
|
+
}
|
|
2620
|
+
const { cmpTree, Jostraca } = generatorRuntime();
|
|
2621
|
+
let root;
|
|
2622
|
+
try {
|
|
2623
|
+
root = cmpTree(tree, { raw: true });
|
|
2624
|
+
}
|
|
2625
|
+
catch (err) {
|
|
2626
|
+
process.stderr.write(`aontu: ${file}: ${err.message}\n`);
|
|
2627
|
+
return 4;
|
|
2628
|
+
}
|
|
2629
|
+
const runtime = Jostraca();
|
|
2630
|
+
try {
|
|
2631
|
+
if (check) {
|
|
2632
|
+
const res = await runtime.check({ folder }, root);
|
|
2633
|
+
const drift = res.drift.map((d) => ({ kind: d.kind, path: d.path }));
|
|
2634
|
+
if ('json' === format) {
|
|
2635
|
+
process.stdout.write((0, aontu_1.exactJSON)({
|
|
2636
|
+
aontu: { version: version(), verb: 'render' },
|
|
2637
|
+
verdict: 0 === drift.length ? 'ok' : 'drift',
|
|
2638
|
+
checked: res.checked,
|
|
2639
|
+
drift,
|
|
2640
|
+
}, 2) + '\n');
|
|
2641
|
+
}
|
|
2642
|
+
else {
|
|
2643
|
+
for (const d of drift) {
|
|
2644
|
+
process.stdout.write(`${d.kind}: ${d.path}\n`);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
return 0 === drift.length ? 0 : 1;
|
|
2648
|
+
}
|
|
2649
|
+
const res = await runtime.generate({ folder }, root);
|
|
2650
|
+
if ('json' === format) {
|
|
2651
|
+
process.stdout.write((0, aontu_1.exactJSON)({
|
|
2652
|
+
aontu: { version: version(), verb: 'render' },
|
|
2653
|
+
verdict: 'ok',
|
|
2654
|
+
files: res.files,
|
|
2655
|
+
}, 2) + '\n');
|
|
2656
|
+
}
|
|
2657
|
+
return 0;
|
|
2658
|
+
}
|
|
2659
|
+
catch (err) {
|
|
2660
|
+
process.stderr.write(`aontu: ${err.message}\n`);
|
|
2661
|
+
return 2;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2449
2664
|
function runReaches(argv) {
|
|
2450
2665
|
const trusted = takeTrust(argv);
|
|
2451
2666
|
if (null == trusted) {
|
|
@@ -4191,8 +4406,8 @@ function runInit(argv) {
|
|
|
4191
4406
|
const KNOWN_VERBS = [
|
|
4192
4407
|
'add', 'agentsmd', 'allow', 'breaking', 'explain', 'fmt', 'get', 'hash',
|
|
4193
4408
|
'help', 'init', 'jsonschema', 'lsp', 'mcp', 'model', 'pkg', 'publish',
|
|
4194
|
-
'reaches', 'relations', 'remove', '
|
|
4195
|
-
'trim', 'vet', 'view', 'why',
|
|
4409
|
+
'reaches', 'relations', 'remove', 'render', 'subsume', 'sync', 'template',
|
|
4410
|
+
'trace', 'trim', 'vet', 'view', 'why',
|
|
4196
4411
|
];
|
|
4197
4412
|
exports.KNOWN_VERBS = KNOWN_VERBS;
|
|
4198
4413
|
// looksLikeVerb reports whether an unreadable argument was meant as a
|
|
@@ -4316,6 +4531,9 @@ function main(argv, servers = SERVERS) {
|
|
|
4316
4531
|
if ('trace' === argv[2]) {
|
|
4317
4532
|
return finish(runTrace(argv.slice(3)));
|
|
4318
4533
|
}
|
|
4534
|
+
if ('render' === argv[2]) {
|
|
4535
|
+
return void runRender(argv.slice(3)).then(finish);
|
|
4536
|
+
}
|
|
4319
4537
|
if ('reaches' === argv[2]) {
|
|
4320
4538
|
return finish(runReaches(argv.slice(3)));
|
|
4321
4539
|
}
|