aontu 0.55.0 → 0.57.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/README.md +3 -3
- package/dist/agentsmd.d.ts +1 -0
- package/dist/agentsmd.js +10 -3
- package/dist/agentsmd.js.map +1 -1
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +5 -2
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +10 -3
- package/dist/cli.js +311 -53
- package/dist/cli.js.map +1 -1
- package/dist/diff.d.ts +1 -0
- package/dist/diff.js +3 -2
- package/dist/diff.js.map +1 -1
- package/dist/escape.d.ts +5 -0
- package/dist/escape.js +455 -0
- package/dist/escape.js.map +1 -0
- package/dist/format.d.ts +26 -0
- package/dist/format.js +1489 -0
- package/dist/format.js.map +1 -0
- package/dist/hints.js +39 -1
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.d.ts +1 -0
- package/dist/jsonschema.js +3 -2
- package/dist/jsonschema.js.map +1 -1
- package/dist/lang.js +84 -6
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +2 -1
- package/dist/lsp.js +4 -4
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +2 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +6 -4
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +8 -7
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +6 -6
- package/dist/mod.js.map +1 -1
- package/dist/patch.d.ts +1 -0
- package/dist/patch.js +1 -0
- package/dist/patch.js.map +1 -1
- package/dist/query.d.ts +1 -0
- package/dist/query.js +4 -3
- package/dist/query.js.map +1 -1
- package/dist/reach.d.ts +1 -0
- package/dist/reach.js +3 -2
- package/dist/reach.js.map +1 -1
- package/dist/relation.d.ts +1 -0
- package/dist/relation.js +3 -2
- package/dist/relation.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/std.js +2 -1
- package/dist/std.js.map +1 -1
- package/dist/subsume.d.ts +1 -0
- package/dist/subsume.js +3 -2
- package/dist/subsume.js.map +1 -1
- package/dist/trim.d.ts +1 -0
- package/dist/trim.js +3 -2
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.d.ts +1 -0
- package/dist/type.js.map +1 -1
- package/dist/utility.d.ts +8 -2
- package/dist/utility.js +9 -1
- package/dist/utility.js.map +1 -1
- package/dist/val/EachFuncVal.js +1 -2
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +23 -0
- package/dist/val/EmitFuncVal.js +261 -0
- package/dist/val/EmitFuncVal.js.map +1 -0
- package/dist/val/FilterFuncVal.js +1 -2
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +16 -0
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +1 -2
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PlaceVal.d.ts +3 -1
- package/dist/val/PlaceVal.js +8 -6
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/StrFuncVal.d.ts +32 -0
- package/dist/val/StrFuncVal.js +292 -0
- package/dist/val/StrFuncVal.js.map +1 -0
- package/dist/vet.d.ts +1 -0
- package/dist/vet.js +1 -1
- package/dist/vet.js.map +1 -1
- package/dist/view.d.ts +2 -1
- package/dist/view.js +379 -8
- package/dist/view.js.map +1 -1
- package/grammar/aontu.abnf +156 -0
- package/grammar/aontu.gbnf +4 -3
- package/grammar/aontu.lark +4 -3
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +2 -1
- package/skill/grammar-card.md +5 -2
- package/src/agentsmd.ts +15 -3
- package/src/aontu.ts +8 -1
- package/src/cli.ts +365 -58
- package/src/diff.ts +7 -2
- package/src/escape.ts +371 -0
- package/src/format.ts +1728 -0
- package/src/hints.ts +53 -1
- package/src/jsonschema.ts +7 -1
- package/src/lang.ts +93 -6
- package/src/lsp.ts +8 -6
- package/src/mcp-server.ts +3 -2
- package/src/mcp.ts +6 -4
- package/src/mod-tool.ts +9 -8
- package/src/mod.ts +6 -6
- package/src/patch.ts +7 -0
- package/src/query.ts +8 -4
- package/src/reach.ts +7 -2
- package/src/relation.ts +7 -2
- package/src/sigdecl.ts +1 -1
- package/src/std.ts +2 -1
- package/src/subsume.ts +7 -2
- package/src/trim.ts +7 -2
- package/src/type.ts +8 -0
- package/src/utility.ts +27 -2
- package/src/val/EachFuncVal.ts +1 -3
- package/src/val/EmitFuncVal.ts +401 -0
- package/src/val/FilterFuncVal.ts +1 -3
- package/src/val/FuncBaseVal.ts +18 -0
- package/src/val/PackFuncVal.ts +1 -3
- package/src/val/PlaceVal.ts +8 -6
- package/src/val/StrFuncVal.ts +334 -0
- package/src/vet.ts +9 -3
- package/src/view.ts +442 -9
package/src/cli.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { evalFailure } from './query'
|
|
13
13
|
// __importStar downlevel helper, whose branches no supported Node takes.
|
|
14
14
|
import {
|
|
15
|
-
mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync,
|
|
15
|
+
existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync,
|
|
16
16
|
} from 'node:fs'
|
|
17
17
|
import { basename, dirname, join, resolve } from 'node:path'
|
|
18
18
|
import { tmpdir } from 'node:os'
|
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
get, why, patch, agentsMd,
|
|
26
26
|
} from './aontu'
|
|
27
27
|
import { sarifReport } from './report-sarif'
|
|
28
|
+
import { main as lspMain } from './lsp-server'
|
|
29
|
+
import { main as mcpMain } from './mcp-server'
|
|
28
30
|
import { jsonSchema } from './jsonschema'
|
|
29
31
|
import { modTidy, modVerify, modVendor, modManifest } from './mod-tool'
|
|
30
32
|
import type {
|
|
@@ -48,6 +50,9 @@ import type {
|
|
|
48
50
|
import type { QueryView } from './query'
|
|
49
51
|
import type { WhyRecord } from './provenance'
|
|
50
52
|
import { agentsMdSplice } from './agentsmd'
|
|
53
|
+
import { format, unifiedDiff } from './format'
|
|
54
|
+
import { includeOpts } from './utility'
|
|
55
|
+
import type { IncludeOptions } from './utility'
|
|
51
56
|
|
|
52
57
|
|
|
53
58
|
type Mode = 'json' | 'canon'
|
|
@@ -69,6 +74,9 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
69
74
|
aontu why <path> [options] <file>
|
|
70
75
|
aontu set <path>=<value>... --entry <file> --overlay <file>
|
|
71
76
|
aontu agentsmd [--write <AGENTS.md>] <file>
|
|
77
|
+
aontu fmt [-w|-l|--check|-d|--lint] <file>...
|
|
78
|
+
aontu lsp
|
|
79
|
+
aontu mcp [--root <dir>]
|
|
72
80
|
|
|
73
81
|
Evaluate an Aontu source file and print the result as JSON.
|
|
74
82
|
With no file on an interactive terminal, start a REPL.
|
|
@@ -91,6 +99,10 @@ Options:
|
|
|
91
99
|
Every verb takes it too, and a bare root means the
|
|
92
100
|
document's own directory
|
|
93
101
|
--include-root <dir> Shorthand for --trust root:<dir>
|
|
102
|
+
--text-ext <e> Read these extensions as text too, comma-separated
|
|
103
|
+
and without dots (md,sql). .txt needs no flag; a
|
|
104
|
+
named format keeps its meaning, and .js stays
|
|
105
|
+
refused. Every verb takes it
|
|
94
106
|
|
|
95
107
|
Mod options:
|
|
96
108
|
--format <f> text (default) or json
|
|
@@ -98,10 +110,10 @@ Mod options:
|
|
|
98
110
|
|
|
99
111
|
Mod subcommands:
|
|
100
112
|
tidy Resolve the module closure by minimum version selection and
|
|
101
|
-
rewrite mod-lock.aon in canonical form
|
|
102
|
-
verify Check every locked module still means what
|
|
113
|
+
rewrite aontu_meta/mod-lock.aon in canonical form
|
|
114
|
+
verify Check every locked module still means what the lockfile
|
|
103
115
|
pins, and change nothing (the CI gate; tidy rewrites)
|
|
104
|
-
vendor Materialise the locked closure into
|
|
116
|
+
vendor Materialise the locked closure into aontu_meta/vendor/
|
|
105
117
|
manifest Print the OCI artifact a publish would push, gated on the
|
|
106
118
|
breaking check against --against
|
|
107
119
|
|
|
@@ -182,8 +194,8 @@ Why options:
|
|
|
182
194
|
Why exit codes mirror get's: 0 explained, 1 the path names nothing,
|
|
183
195
|
2 usage, 4 the document does not stand up on its own.
|
|
184
196
|
|
|
185
|
-
View kinds: tree, matrix, graph, layer, sets, layers,
|
|
186
|
-
(the poset takes several files). The figure goes to stdout, the loss
|
|
197
|
+
View kinds: doc, lattice, tree, matrix, graph, layer, sets, layers,
|
|
198
|
+
ladder, poset (the poset takes several files). The figure goes to stdout, the loss
|
|
187
199
|
report to stderr. With --views it draws every figure a document
|
|
188
200
|
declares as data, from one evaluation: each declaration names its own
|
|
189
201
|
kind and out file, nothing is written unless every figure rendered,
|
|
@@ -191,13 +203,13 @@ and --check gates the committed set.
|
|
|
191
203
|
|
|
192
204
|
View options:
|
|
193
205
|
--as <profile> text | mermaid | dot | er | svg, per kind: doc,
|
|
194
|
-
tree, matrix, sets and layers draw text
|
|
195
|
-
or svg; graph draws mermaid (default),
|
|
196
|
-
layer draws text (default), mermaid or
|
|
197
|
-
and poset draw mermaid (default) or dot
|
|
206
|
+
lattice, tree, matrix, sets and layers draw text
|
|
207
|
+
(default) or svg; graph draws mermaid (default),
|
|
208
|
+
dot or er; layer draws text (default), mermaid or
|
|
209
|
+
svg; ladder and poset draw mermaid (default) or dot
|
|
198
210
|
--at <path> Restrict the figure to nodes under this path; the
|
|
199
|
-
subtree doc draws; the
|
|
200
|
-
where the poset compares
|
|
211
|
+
subtree doc draws; the subtree the lattice counts;
|
|
212
|
+
the path the ladder draws; where the poset compares
|
|
201
213
|
--views <path> Draw every figure the document declares at this
|
|
202
214
|
path, one evaluation, all or nothing; each
|
|
203
215
|
declaration names its own kind and out file
|
|
@@ -276,6 +288,32 @@ Agentsmd options:
|
|
|
276
288
|
Agentsmd exit codes: 0 generated, 2 usage, 4 the document does not
|
|
277
289
|
stand up on its own.
|
|
278
290
|
|
|
291
|
+
Fmt options:
|
|
292
|
+
-w, --write Rewrite each file in place, when its form would change
|
|
293
|
+
-l, --list Print the name of each file whose form would change
|
|
294
|
+
--check Like --list, and exit 1 when any would: the CI gate
|
|
295
|
+
-d, --diff Print a unified diff for each file whose form would
|
|
296
|
+
change
|
|
297
|
+
--lint Report the style findings, key case and repeated
|
|
298
|
+
shapes, on standard error, and print nothing else
|
|
299
|
+
--strict With --lint, and exit 1 when there is a finding
|
|
300
|
+
|
|
301
|
+
The fmt verb prints one document in the agreed form; with no file it
|
|
302
|
+
reads standard input. Several files need one of the options above.
|
|
303
|
+
|
|
304
|
+
Fmt exit codes: 0 formatted or clean, 1 a --check file would change or
|
|
305
|
+
a --strict finding, 2 usage, 4 a document does not parse.
|
|
306
|
+
|
|
307
|
+
The lsp verb runs the language server over standard input and output
|
|
308
|
+
(LSP: JSON-RPC with Content-Length framing) until the client exits;
|
|
309
|
+
editors launch it with no arguments. The standalone aontu-lsp binary
|
|
310
|
+
runs the same server.
|
|
311
|
+
|
|
312
|
+
The mcp verb runs the Model Context Protocol server over standard
|
|
313
|
+
input and output (newline-delimited JSON-RPC), confined below --root
|
|
314
|
+
when one is given. It is part of the npm build, as the standalone
|
|
315
|
+
aontu-mcp binary is.
|
|
316
|
+
|
|
279
317
|
REPL commands:
|
|
280
318
|
:help Show REPL help
|
|
281
319
|
:load <file> Evaluate a document and hold it for the commands below
|
|
@@ -333,11 +371,18 @@ function evalSource(
|
|
|
333
371
|
// entry root or goes through package resolution prints a one-line
|
|
334
372
|
// stderr warning naming the flag a future default will require
|
|
335
373
|
// (phase 6, the staged flip).
|
|
336
|
-
type TrustArg =
|
|
374
|
+
type TrustArg = (
|
|
337
375
|
| { kind: 'system-warn' }
|
|
338
376
|
| { kind: 'system' }
|
|
339
377
|
| { kind: 'none' }
|
|
340
378
|
| { kind: 'root', dir?: string }
|
|
379
|
+
// EXTENSIONS READ AS TEXT ride with the capability rather than
|
|
380
|
+
// beside it: both answer "what may an include read", both are
|
|
381
|
+
// stripped by takeTrust before a verb parses its own tail, and a
|
|
382
|
+
// verb that threads one and not the other is the G5 defect again --
|
|
383
|
+
// `aontu vet` running under a flag the bare command honoured and it
|
|
384
|
+
// did not.
|
|
385
|
+
) & { textExt: string[] }
|
|
341
386
|
|
|
342
387
|
|
|
343
388
|
// The one-line warning of the staged default flip. Once per (kind,
|
|
@@ -366,15 +411,16 @@ function makeTrustWarn(): (kind: 'escape' | 'pkg', path: string) => void {
|
|
|
366
411
|
// entryRoot (the entry file's directory, or the working directory for
|
|
367
412
|
// stdin/REPL).
|
|
368
413
|
function trustOpts(trust: TrustArg, entryRoot: string): any {
|
|
414
|
+
const text = 0 === trust.textExt.length ? {} : { textExt: trust.textExt }
|
|
369
415
|
switch (trust.kind) {
|
|
370
416
|
case 'none':
|
|
371
|
-
return { trust: { include: 'none' } }
|
|
417
|
+
return { ...text, trust: { include: 'none' } }
|
|
372
418
|
case 'root':
|
|
373
|
-
return { trust: { include: { root: trust.dir ?? entryRoot } } }
|
|
419
|
+
return { ...text, trust: { include: { root: trust.dir ?? entryRoot } } }
|
|
374
420
|
case 'system':
|
|
375
|
-
return {}
|
|
421
|
+
return { ...text }
|
|
376
422
|
default: // system-warn: today's default plus the warning window
|
|
377
|
-
return { trustWarn: makeTrustWarn(), trustWarnRoot: entryRoot }
|
|
423
|
+
return { ...text, trustWarn: makeTrustWarn(), trustWarnRoot: entryRoot }
|
|
378
424
|
}
|
|
379
425
|
}
|
|
380
426
|
|
|
@@ -392,7 +438,8 @@ function trustOpts(trust: TrustArg, entryRoot: string): any {
|
|
|
392
438
|
function takeTrust(argv: string[]):
|
|
393
439
|
{ argv: string[], trust: TrustArg } | undefined {
|
|
394
440
|
const rest: string[] = []
|
|
395
|
-
let trust: TrustArg = { kind: 'system-warn' }
|
|
441
|
+
let trust: TrustArg = { kind: 'system-warn', textExt: [] }
|
|
442
|
+
let textExt: string[] = []
|
|
396
443
|
for (let i = 0; i < argv.length; i++) {
|
|
397
444
|
const arg = argv[i]
|
|
398
445
|
if ('--trust' === arg) {
|
|
@@ -410,21 +457,47 @@ function takeTrust(argv: string[]):
|
|
|
410
457
|
process.stderr.write('aontu: --include-root needs a directory\n')
|
|
411
458
|
return undefined
|
|
412
459
|
}
|
|
413
|
-
trust = { kind: 'root', dir }
|
|
460
|
+
trust = { kind: 'root', dir, textExt }
|
|
461
|
+
}
|
|
462
|
+
else if ('--text-ext' === arg) {
|
|
463
|
+
const list = null == argv[i + 1] ? undefined : parseTextExt(argv[++i])
|
|
464
|
+
if (null == list) {
|
|
465
|
+
process.stderr.write(
|
|
466
|
+
'aontu: --text-ext needs extensions, without dots' +
|
|
467
|
+
' (--text-ext md,sql)\n')
|
|
468
|
+
return undefined
|
|
469
|
+
}
|
|
470
|
+
textExt = [...textExt, ...list]
|
|
414
471
|
}
|
|
415
472
|
else {
|
|
416
473
|
rest.push(arg)
|
|
417
474
|
}
|
|
418
475
|
}
|
|
419
|
-
return { argv: rest, trust }
|
|
476
|
+
return { argv: rest, trust: { ...trust, textExt } }
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
// `md,sql` or `.md,.sql` -- the dot is accepted and dropped, because a
|
|
481
|
+
// reader who has just written `@"notes.txt"` reaches for one. An empty
|
|
482
|
+
// element, or anything that is not an extension, is a usage error
|
|
483
|
+
// rather than a silently ignored word: a flag that quietly does
|
|
484
|
+
// nothing is how a document ends up refused with no reason visible.
|
|
485
|
+
function parseTextExt(arg: string): string[] | undefined {
|
|
486
|
+
const out: string[] = []
|
|
487
|
+
for (const raw of arg.split(',')) {
|
|
488
|
+
const ext = raw.trim().replace(/^\./, '').toLowerCase()
|
|
489
|
+
if ('' === ext || !/^[a-z0-9]+$/.test(ext)) {
|
|
490
|
+
return undefined
|
|
491
|
+
}
|
|
492
|
+
out.push(ext)
|
|
493
|
+
}
|
|
494
|
+
return out
|
|
420
495
|
}
|
|
421
496
|
|
|
422
497
|
|
|
423
498
|
// The evaluator options a REPL session's capability means.
|
|
424
499
|
function replTrust(state: ReplState, entryRoot: string): any {
|
|
425
|
-
|
|
426
|
-
state.trust ?? { kind: 'system-warn' }, entryRoot)
|
|
427
|
-
return null == capability ? {} : { trust: capability }
|
|
500
|
+
return verbOpts(state.trust ?? { kind: 'system-warn', textExt: [] }, entryRoot)
|
|
428
501
|
}
|
|
429
502
|
|
|
430
503
|
|
|
@@ -444,6 +517,20 @@ function verbTrust(trust: TrustArg, entryRoot: string): any {
|
|
|
444
517
|
}
|
|
445
518
|
|
|
446
519
|
|
|
520
|
+
// THE INCLUDE OPTIONS A VERB RUNS UNDER, spread into its engine call:
|
|
521
|
+
// the capability above, and the extensions `--text-ext` widened. Both
|
|
522
|
+
// are absent when unset rather than present-and-undefined, so a verb's
|
|
523
|
+
// options bag is byte-identical to what it was before either flag
|
|
524
|
+
// existed and no engine sees a key it has to ignore.
|
|
525
|
+
function verbOpts(trust: TrustArg, entryRoot: string): any {
|
|
526
|
+
const include = verbTrust(trust, entryRoot)
|
|
527
|
+
return {
|
|
528
|
+
...(undefined === include ? {} : { trust: include }),
|
|
529
|
+
...(0 === trust.textExt.length ? {} : { textExt: trust.textExt }),
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
447
534
|
// The directory a bare `--trust root` confines to for a verb: the
|
|
448
535
|
// primary document's own, matching the bare command's entry root.
|
|
449
536
|
function entryRootOf(file: string | undefined): string {
|
|
@@ -607,7 +694,7 @@ export function replCommand(
|
|
|
607
694
|
if (':why' === cmd) {
|
|
608
695
|
const report = why(src, path, {
|
|
609
696
|
path: state.name,
|
|
610
|
-
|
|
697
|
+
...verbOpts(state.trust ?? { kind: 'system-warn', textExt: [] },
|
|
611
698
|
entryRootOf(state.name)),
|
|
612
699
|
})
|
|
613
700
|
return report.ok
|
|
@@ -618,7 +705,7 @@ export function replCommand(
|
|
|
618
705
|
? 'keys' : 'canon' === state.mode ? 'canon' : 'json'
|
|
619
706
|
const report = get(src, path, {
|
|
620
707
|
view, path: state.name,
|
|
621
|
-
|
|
708
|
+
...verbOpts(state.trust ?? { kind: 'system-warn', textExt: [] },
|
|
622
709
|
entryRootOf(state.name)),
|
|
623
710
|
})
|
|
624
711
|
return report.ok
|
|
@@ -901,7 +988,7 @@ function vetOnce(args: VetArgs, trust: TrustArg): number {
|
|
|
901
988
|
|
|
902
989
|
for (const source of sources) {
|
|
903
990
|
const report = vet(schemaSrc, source.src, {
|
|
904
|
-
|
|
991
|
+
...verbOpts(trust, entryRootOf(args.schema)),
|
|
905
992
|
at: args.at,
|
|
906
993
|
closed: args.closed,
|
|
907
994
|
partial: args.partial,
|
|
@@ -1193,7 +1280,7 @@ function runSubsume(argv: string[]): number {
|
|
|
1193
1280
|
}
|
|
1194
1281
|
|
|
1195
1282
|
const report = subsume(generalSrc, specificSrc, {
|
|
1196
|
-
|
|
1283
|
+
...verbOpts(trust, entryRootOf(args.general)),
|
|
1197
1284
|
profile: args.profile,
|
|
1198
1285
|
at: args.at,
|
|
1199
1286
|
generalUrl: args.general,
|
|
@@ -1417,15 +1504,18 @@ function oldVersion(spec: string, file: string): OldVersion | undefined {
|
|
|
1417
1504
|
// a disjunction whose default is the declared mode. Undefined when the
|
|
1418
1505
|
// key is absent or does not spell a mode.
|
|
1419
1506
|
function policyCompat(
|
|
1420
|
-
newSrc: string, path: string,
|
|
1507
|
+
newSrc: string, path: string, include: IncludeOptions
|
|
1508
|
+
): BreakingMode | undefined {
|
|
1421
1509
|
const aontu = new Aontu()
|
|
1422
1510
|
const ctx = aontu.ctx({ collect: true })
|
|
1423
1511
|
// The declaration is read by EVALUATING the document, so this leg
|
|
1424
|
-
// runs the include resolver too and has to run it under the
|
|
1425
|
-
//
|
|
1426
|
-
// through an unconfined resolver would confine the
|
|
1427
|
-
// not the question (use-cases/REVIEW.md finding G)
|
|
1428
|
-
|
|
1512
|
+
// runs the include resolver too and has to run it under BOTH of the
|
|
1513
|
+
// verb's include options -- a `breaking --trust none` that read its
|
|
1514
|
+
// own mode through an unconfined resolver would confine the
|
|
1515
|
+
// comparison and not the question (use-cases/REVIEW.md finding G),
|
|
1516
|
+
// and one that took the capability alone read no mode at all when
|
|
1517
|
+
// the declaration arrived through a `--text-ext` include.
|
|
1518
|
+
const v: any = aontu.unify(newSrc, { path, ...includeOpts(include) }, ctx)
|
|
1429
1519
|
if (0 < ctx.err.length || true === v?.isNil) {
|
|
1430
1520
|
return undefined
|
|
1431
1521
|
}
|
|
@@ -1528,7 +1618,8 @@ function runBreaking(argv: string[]): number {
|
|
|
1528
1618
|
// stay valid).
|
|
1529
1619
|
const mode: BreakingMode =
|
|
1530
1620
|
args.mode ??
|
|
1531
|
-
policyCompat(newSrc, args.file,
|
|
1621
|
+
policyCompat(newSrc, args.file,
|
|
1622
|
+
verbOpts(trust, entryRootOf(args.file))) ??
|
|
1532
1623
|
'backward'
|
|
1533
1624
|
|
|
1534
1625
|
if ('none' === mode) {
|
|
@@ -1578,7 +1669,7 @@ function runBreaking(argv: string[]): number {
|
|
|
1578
1669
|
|
|
1579
1670
|
for (const check of checks) {
|
|
1580
1671
|
const report = subsume(check.general[0], check.specific[0], {
|
|
1581
|
-
|
|
1672
|
+
...verbOpts(trust, entryRootOf(args.file)),
|
|
1582
1673
|
at: args.at,
|
|
1583
1674
|
generalUrl: check.general[1],
|
|
1584
1675
|
specificUrl: check.specific[1],
|
|
@@ -1724,7 +1815,7 @@ function runTrim(argv: string[]): number {
|
|
|
1724
1815
|
}
|
|
1725
1816
|
|
|
1726
1817
|
const report = trimCheck(src, {
|
|
1727
|
-
path: files[0],
|
|
1818
|
+
path: files[0], ...verbOpts(trust, entryRootOf(files[0])),
|
|
1728
1819
|
})
|
|
1729
1820
|
const text = 'json' === format
|
|
1730
1821
|
? renderTrimJson(report)
|
|
@@ -1788,8 +1879,8 @@ const VIEW_HELP =
|
|
|
1788
1879
|
'aontu view <kind> [options] <file>... (try --help)'
|
|
1789
1880
|
|
|
1790
1881
|
const VIEW_KINDS: ViewKind[] =
|
|
1791
|
-
['doc', 'tree', 'matrix', 'graph', 'layer', 'sets', 'layers',
|
|
1792
|
-
'poset']
|
|
1882
|
+
['doc', 'lattice', 'tree', 'matrix', 'graph', 'layer', 'sets', 'layers',
|
|
1883
|
+
'ladder', 'poset']
|
|
1793
1884
|
|
|
1794
1885
|
const VIEW_PROFILES: ViewProfile[] = ['text', 'mermaid', 'dot', 'er', 'svg']
|
|
1795
1886
|
|
|
@@ -1920,6 +2011,16 @@ function runMod(argv: string[]): number {
|
|
|
1920
2011
|
return 2
|
|
1921
2012
|
}
|
|
1922
2013
|
|
|
2014
|
+
// THE OLD LAYOUT IS NAMED, NOT READ. The lockfile and the vendored
|
|
2015
|
+
// closure moved under aontu_meta/; a project that still carries them
|
|
2016
|
+
// at its root would otherwise look untouched by any of these verbs,
|
|
2017
|
+
// which is the one silence worth breaking.
|
|
2018
|
+
if (existsSync(join(dir, 'aon_vendor')) || existsSync(join(dir, 'mod-lock.aon'))) {
|
|
2019
|
+
process.stderr.write(
|
|
2020
|
+
'aontu: aon_vendor/ and mod-lock.aon now live under aontu_meta/: ' +
|
|
2021
|
+
'move them, or run aontu mod tidy and aontu mod vendor\n')
|
|
2022
|
+
}
|
|
2023
|
+
|
|
1923
2024
|
// `--against` gates a manifest and means nothing to the other two;
|
|
1924
2025
|
// accepting it there would say it had been honoured.
|
|
1925
2026
|
if (null != against && 'manifest' !== sub) {
|
|
@@ -2110,7 +2211,7 @@ function runRelations(argv: string[]): number {
|
|
|
2110
2211
|
}
|
|
2111
2212
|
|
|
2112
2213
|
const report = relationCheck(src, {
|
|
2113
|
-
path: files[0],
|
|
2214
|
+
path: files[0], ...verbOpts(trust, entryRootOf(files[0])),
|
|
2114
2215
|
})
|
|
2115
2216
|
const text = 'json' === format
|
|
2116
2217
|
? renderRelationsJson(report)
|
|
@@ -2178,7 +2279,7 @@ function runReaches(argv: string[]): number {
|
|
|
2178
2279
|
|
|
2179
2280
|
const report = reachCheck(src, rest[0], rest[1], {
|
|
2180
2281
|
path: rest[2], relation,
|
|
2181
|
-
|
|
2282
|
+
...verbOpts(trust, entryRootOf(rest[2])),
|
|
2182
2283
|
})
|
|
2183
2284
|
const text = 'json' === format
|
|
2184
2285
|
? renderReachesJson(report)
|
|
@@ -2424,7 +2525,7 @@ function runView(argv: string[]): number {
|
|
|
2424
2525
|
kind,
|
|
2425
2526
|
path: files[0],
|
|
2426
2527
|
roots,
|
|
2427
|
-
|
|
2528
|
+
...verbOpts(trust, entryRootOf(files[0])),
|
|
2428
2529
|
docs: files.slice(1).map((path, i) => ({ src: srcs[i + 1], path })),
|
|
2429
2530
|
})
|
|
2430
2531
|
|
|
@@ -2503,7 +2604,7 @@ function runViewSet(
|
|
|
2503
2604
|
}
|
|
2504
2605
|
|
|
2505
2606
|
const report = viewSet(src, {
|
|
2506
|
-
...opts, path: file,
|
|
2607
|
+
...opts, path: file, ...verbOpts(trust, entryRootOf(file)),
|
|
2507
2608
|
})
|
|
2508
2609
|
|
|
2509
2610
|
if ('json' === how.format) {
|
|
@@ -2726,7 +2827,7 @@ function runJsonSchema(argv: string[]): number {
|
|
|
2726
2827
|
}
|
|
2727
2828
|
|
|
2728
2829
|
const report = jsonSchema(src, {
|
|
2729
|
-
at, path: files[0],
|
|
2830
|
+
at, path: files[0], ...verbOpts(trust, entryRootOf(files[0])),
|
|
2730
2831
|
})
|
|
2731
2832
|
|
|
2732
2833
|
if ('json' === format) {
|
|
@@ -2819,9 +2920,7 @@ function runHash(argv: string[]): number {
|
|
|
2819
2920
|
|
|
2820
2921
|
// The file's own directory is the include base, as every verb
|
|
2821
2922
|
// resolves a named file (vet's aontuForPath rule).
|
|
2822
|
-
const
|
|
2823
|
-
const aontu = new Aontu(
|
|
2824
|
-
null == capability ? undefined : { trust: capability })
|
|
2923
|
+
const aontu = new Aontu(verbOpts(trust, entryRootOf(files[0])))
|
|
2825
2924
|
const ctx = aontu.ctx({ collect: true })
|
|
2826
2925
|
const v: any = aontu.unify(src, { path: files[0] }, ctx)
|
|
2827
2926
|
if (0 < ctx.err.length || true === v?.isNil) {
|
|
@@ -2937,7 +3036,7 @@ function runGet(argv: string[]): number {
|
|
|
2937
3036
|
}
|
|
2938
3037
|
|
|
2939
3038
|
const report = get(src, path, {
|
|
2940
|
-
view, depth, path: file,
|
|
3039
|
+
view, depth, path: file, ...verbOpts(trust, entryRootOf(file)),
|
|
2941
3040
|
})
|
|
2942
3041
|
if ('json' === format) {
|
|
2943
3042
|
process.stdout.write(exactJSON({
|
|
@@ -3021,7 +3120,7 @@ function runWhy(argv: string[]): number {
|
|
|
3021
3120
|
}
|
|
3022
3121
|
|
|
3023
3122
|
const report = why(src, path, {
|
|
3024
|
-
path: file,
|
|
3123
|
+
path: file, ...verbOpts(trust, entryRootOf(file)),
|
|
3025
3124
|
})
|
|
3026
3125
|
if ('json' === format) {
|
|
3027
3126
|
process.stdout.write(exactJSON({
|
|
@@ -3156,7 +3255,7 @@ function runSet(argv: string[]): number {
|
|
|
3156
3255
|
}
|
|
3157
3256
|
|
|
3158
3257
|
const report = patch(entrySrc, overlaySrc, assignments, {
|
|
3159
|
-
|
|
3258
|
+
...verbOpts(trust, entryRootOf(entry)),
|
|
3160
3259
|
entryPath: entry,
|
|
3161
3260
|
overlayPath: overlayFile,
|
|
3162
3261
|
inPlace,
|
|
@@ -3291,7 +3390,7 @@ function runAgentsMd(argv: string[]): number {
|
|
|
3291
3390
|
|
|
3292
3391
|
const report = agentsMd(src, {
|
|
3293
3392
|
name: files[0], path: files[0],
|
|
3294
|
-
|
|
3393
|
+
...verbOpts(trust, entryRootOf(files[0])),
|
|
3295
3394
|
})
|
|
3296
3395
|
if (!report.ok) {
|
|
3297
3396
|
process.stderr.write(
|
|
@@ -3343,6 +3442,188 @@ function runAgentsMd(argv: string[]): number {
|
|
|
3343
3442
|
// on the parity-probe discipline in AGENTS.md, which derives expected
|
|
3344
3443
|
// spec values by piping BOTH CLIs and comparing. A truncated pipe there
|
|
3345
3444
|
// reads as a port divergence.
|
|
3445
|
+
// ---------------------------------------------------------------------
|
|
3446
|
+
// The source formatter (docs/design/FMT.0.md): one agreed form, in the
|
|
3447
|
+
// tradition of gofmt. The verb prints, lists, checks, diffs or rewrites;
|
|
3448
|
+
// the form itself is the library's (ts/src/format.ts), and the two
|
|
3449
|
+
// ports agree on it row by row in test/spec/fmt.tsv.
|
|
3450
|
+
|
|
3451
|
+
const FMT_HELP = 'aontu fmt [-w|-l|--check|-d|--lint] <file>... (try --help)'
|
|
3452
|
+
|
|
3453
|
+
type FmtFlags = {
|
|
3454
|
+
write: boolean, list: boolean, check: boolean, diff: boolean, lint: boolean, strict: boolean,
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
function runFmt(argv: string[]): number | Promise<number> {
|
|
3458
|
+
const files: string[] = []
|
|
3459
|
+
const flags: FmtFlags = {
|
|
3460
|
+
write: false, list: false, check: false, diff: false, lint: false, strict: false,
|
|
3461
|
+
}
|
|
3462
|
+
|
|
3463
|
+
for (const arg of argv) {
|
|
3464
|
+
if ('-h' === arg || '--help' === arg) {
|
|
3465
|
+
process.stdout.write(HELP)
|
|
3466
|
+
return 0
|
|
3467
|
+
}
|
|
3468
|
+
if ('-w' === arg || '--write' === arg) {
|
|
3469
|
+
flags.write = true
|
|
3470
|
+
}
|
|
3471
|
+
else if ('-l' === arg || '--list' === arg) {
|
|
3472
|
+
flags.list = true
|
|
3473
|
+
}
|
|
3474
|
+
else if ('--check' === arg) {
|
|
3475
|
+
flags.check = true
|
|
3476
|
+
}
|
|
3477
|
+
else if ('-d' === arg || '--diff' === arg) {
|
|
3478
|
+
flags.diff = true
|
|
3479
|
+
}
|
|
3480
|
+
else if ('--lint' === arg) {
|
|
3481
|
+
flags.lint = true
|
|
3482
|
+
}
|
|
3483
|
+
else if ('--strict' === arg) {
|
|
3484
|
+
flags.lint = true
|
|
3485
|
+
flags.strict = true
|
|
3486
|
+
}
|
|
3487
|
+
else if (arg.startsWith('-')) {
|
|
3488
|
+
process.stderr.write(`aontu: unknown fmt option ${arg} (try --help)\n`)
|
|
3489
|
+
return 2
|
|
3490
|
+
}
|
|
3491
|
+
else {
|
|
3492
|
+
files.push(arg)
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
if (0 === files.length) {
|
|
3497
|
+
// Standard input: formatted onto standard output, or listed,
|
|
3498
|
+
// checked and diffed under the name <stdin>. It cannot be written
|
|
3499
|
+
// back.
|
|
3500
|
+
if (flags.write) {
|
|
3501
|
+
process.stderr.write(`aontu: --write needs a file\n${FMT_HELP}\n`)
|
|
3502
|
+
return 2
|
|
3503
|
+
}
|
|
3504
|
+
return new Promise((resolve) => {
|
|
3505
|
+
let src = ''
|
|
3506
|
+
process.stdin.setEncoding('utf8')
|
|
3507
|
+
process.stdin.on('data', (d) => (src += d))
|
|
3508
|
+
process.stdin.on('end', () => resolve(fmtOne('<stdin>', src, flags)))
|
|
3509
|
+
})
|
|
3510
|
+
}
|
|
3511
|
+
|
|
3512
|
+
// Several files onto standard output would be one stream nobody can
|
|
3513
|
+
// split again (the note's X-6): the verb refuses unless an option
|
|
3514
|
+
// says what to do with each.
|
|
3515
|
+
if (1 < files.length && !fmtQuiet(flags)) {
|
|
3516
|
+
process.stderr.write(
|
|
3517
|
+
`aontu: fmt prints one file; with ${files.length}, say --write, ` +
|
|
3518
|
+
`--list, --check, --diff or --lint\n${FMT_HELP}\n`)
|
|
3519
|
+
return 2
|
|
3520
|
+
}
|
|
3521
|
+
|
|
3522
|
+
let worst = 0
|
|
3523
|
+
for (const file of files) {
|
|
3524
|
+
let src: string
|
|
3525
|
+
try {
|
|
3526
|
+
src = readFileSync(file, 'utf8')
|
|
3527
|
+
}
|
|
3528
|
+
catch (err: any) {
|
|
3529
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`)
|
|
3530
|
+
return 2
|
|
3531
|
+
}
|
|
3532
|
+
worst = Math.max(worst, fmtOne(file, src, flags))
|
|
3533
|
+
}
|
|
3534
|
+
return worst
|
|
3535
|
+
}
|
|
3536
|
+
|
|
3537
|
+
// An option that says what to do with a file, in place of printing
|
|
3538
|
+
// it: what to do when its form would change, or the lint.
|
|
3539
|
+
function fmtQuiet(flags: FmtFlags): boolean {
|
|
3540
|
+
return flags.write || flags.list || flags.check || flags.diff || flags.lint
|
|
3541
|
+
}
|
|
3542
|
+
|
|
3543
|
+
// One document: 0 printed, clean or done; 1 a --check that would
|
|
3544
|
+
// change, or a --strict finding; 2 a file that cannot be written; 4 a
|
|
3545
|
+
// document that does not format, with the finding that says why. The
|
|
3546
|
+
// style findings go to standard error, one line each, in the shape
|
|
3547
|
+
// every linter prints: `file:line:col: rule: message`.
|
|
3548
|
+
function fmtOne(name: string, src: string, flags: FmtFlags): number {
|
|
3549
|
+
const report = format(src, { path: name, lint: flags.lint })
|
|
3550
|
+
if ('error' === report.verdict) {
|
|
3551
|
+
process.stderr.write(`aontu: ${name} was not formatted\n` +
|
|
3552
|
+
report.errors.map(renderFinding).join('\n') + '\n')
|
|
3553
|
+
return 4
|
|
3554
|
+
}
|
|
3555
|
+
for (const f of report.findings) {
|
|
3556
|
+
process.stderr.write(`${name}:${f.line}:${f.col}: ${f.rule}: ${f.message}\n`)
|
|
3557
|
+
}
|
|
3558
|
+
const strict = flags.strict && 0 < report.findings.length ? 1 : 0
|
|
3559
|
+
if (!fmtQuiet(flags)) {
|
|
3560
|
+
process.stdout.write(report.text)
|
|
3561
|
+
return 0
|
|
3562
|
+
}
|
|
3563
|
+
if (!report.changed) {
|
|
3564
|
+
return strict
|
|
3565
|
+
}
|
|
3566
|
+
if (flags.list || flags.check) {
|
|
3567
|
+
process.stdout.write(name + '\n')
|
|
3568
|
+
}
|
|
3569
|
+
if (flags.diff) {
|
|
3570
|
+
process.stdout.write(unifiedDiff(name, src, report.text))
|
|
3571
|
+
}
|
|
3572
|
+
if (flags.write) {
|
|
3573
|
+
try {
|
|
3574
|
+
writeFileSync(name, report.text)
|
|
3575
|
+
}
|
|
3576
|
+
catch (err: any) {
|
|
3577
|
+
process.stderr.write(`aontu: cannot write ${name}: ${err.message}\n`)
|
|
3578
|
+
return 2
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
return flags.check ? 1 : strict
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
|
|
3585
|
+
// ---------------------------------------------------------------------
|
|
3586
|
+
// The servers as verbs: `aontu lsp` runs the language server and
|
|
3587
|
+
// `aontu mcp` the MCP server over the CLI's own streams, so the one
|
|
3588
|
+
// command on PATH is the editor's and the agent's server too, and a
|
|
3589
|
+
// version manager (docs/design/ENV.0.md) has one thing to resolve. The
|
|
3590
|
+
// standalone bins (aontu-lsp, aontu-mcp) run the same functions. Each
|
|
3591
|
+
// server owns its exit; the CLI only dispatches. The pair is a
|
|
3592
|
+
// parameter of main so that a test can see the dispatch without a
|
|
3593
|
+
// server taking the test's own stdin.
|
|
3594
|
+
|
|
3595
|
+
type Servers = {
|
|
3596
|
+
lsp: () => void
|
|
3597
|
+
mcp: (argv: string[]) => void
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3600
|
+
// The real pair takes the process's own stdin and stdout, which no
|
|
3601
|
+
// in-process test can lend it; the executable-entry tests in
|
|
3602
|
+
// cli.test.ts run each through a child process instead, so these two
|
|
3603
|
+
// lines are excluded from the in-process count, as the stdio wiring
|
|
3604
|
+
// of lsp-server.ts is.
|
|
3605
|
+
/* node:coverage ignore next 4 */
|
|
3606
|
+
const SERVERS: Servers = {
|
|
3607
|
+
lsp: () => void lspMain(),
|
|
3608
|
+
mcp: (argv) => void mcpMain(undefined, undefined, undefined, undefined, argv),
|
|
3609
|
+
}
|
|
3610
|
+
|
|
3611
|
+
// undefined: the server took the process; a number: an answer the CLI
|
|
3612
|
+
// gives itself, --help or a usage error.
|
|
3613
|
+
function runLsp(argv: string[], servers: Servers): number | undefined {
|
|
3614
|
+
for (const arg of argv) {
|
|
3615
|
+
if ('-h' === arg || '--help' === arg) {
|
|
3616
|
+
process.stdout.write(HELP)
|
|
3617
|
+
return 0
|
|
3618
|
+
}
|
|
3619
|
+
process.stderr.write(`aontu: lsp takes no arguments (try --help)\n`)
|
|
3620
|
+
return 2
|
|
3621
|
+
}
|
|
3622
|
+
servers.lsp()
|
|
3623
|
+
return undefined
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
|
|
3346
3627
|
function finish(code: number): void {
|
|
3347
3628
|
process.exitCode = code
|
|
3348
3629
|
}
|
|
@@ -3352,22 +3633,22 @@ function finish(code: number): void {
|
|
|
3352
3633
|
// spelling, so the caller owns the usage error.
|
|
3353
3634
|
function parseTrustArg(value: string): TrustArg | undefined {
|
|
3354
3635
|
if ('system' === value) {
|
|
3355
|
-
return { kind: 'system' }
|
|
3636
|
+
return { kind: 'system', textExt: [] }
|
|
3356
3637
|
}
|
|
3357
3638
|
if ('none' === value) {
|
|
3358
|
-
return { kind: 'none' }
|
|
3639
|
+
return { kind: 'none', textExt: [] }
|
|
3359
3640
|
}
|
|
3360
3641
|
if ('root' === value) {
|
|
3361
|
-
return { kind: 'root' }
|
|
3642
|
+
return { kind: 'root', textExt: [] }
|
|
3362
3643
|
}
|
|
3363
3644
|
if (value.startsWith('root:') && 'root:'.length < value.length) {
|
|
3364
|
-
return { kind: 'root', dir: value.slice('root:'.length) }
|
|
3645
|
+
return { kind: 'root', dir: value.slice('root:'.length), textExt: [] }
|
|
3365
3646
|
}
|
|
3366
3647
|
return undefined
|
|
3367
3648
|
}
|
|
3368
3649
|
|
|
3369
3650
|
|
|
3370
|
-
function main(argv: string[]): void {
|
|
3651
|
+
function main(argv: string[], servers: Servers = SERVERS): void {
|
|
3371
3652
|
// COLOUR OFF WHEN THE DESTINATION IS NOT A TERMINAL. Error frames
|
|
3372
3653
|
// hardcoded their ANSI escapes, so a piped report and a `--jsonl`
|
|
3373
3654
|
// answer carried terminal control codes into whatever read them (the
|
|
@@ -3385,7 +3666,8 @@ function main(argv: string[]): void {
|
|
|
3385
3666
|
// overwritten twice. In a tool loop that reads as a passing
|
|
3386
3667
|
// validation. Counting them is what lets the refusal below happen.
|
|
3387
3668
|
const files: string[] = []
|
|
3388
|
-
let trust: TrustArg = { kind: 'system-warn' }
|
|
3669
|
+
let trust: TrustArg = { kind: 'system-warn', textExt: [] }
|
|
3670
|
+
let textExt: string[] = []
|
|
3389
3671
|
// The REPL's SESSION protocol (G7 phase 7): one JSON line per
|
|
3390
3672
|
// answer, so a harness can drive the session. Named --jsonl rather
|
|
3391
3673
|
// than the design's --json, which would read as the `:json` output
|
|
@@ -3413,6 +3695,16 @@ function main(argv: string[]): void {
|
|
|
3413
3695
|
if ('agentsmd' === argv[2]) {
|
|
3414
3696
|
return finish(runAgentsMd(argv.slice(3)))
|
|
3415
3697
|
}
|
|
3698
|
+
if ('fmt' === argv[2]) {
|
|
3699
|
+
return void Promise.resolve(runFmt(argv.slice(3))).then(finish)
|
|
3700
|
+
}
|
|
3701
|
+
if ('lsp' === argv[2]) {
|
|
3702
|
+
const code = runLsp(argv.slice(3), servers)
|
|
3703
|
+
return undefined === code ? undefined : finish(code)
|
|
3704
|
+
}
|
|
3705
|
+
if ('mcp' === argv[2]) {
|
|
3706
|
+
return servers.mcp(argv.slice(3))
|
|
3707
|
+
}
|
|
3416
3708
|
|
|
3417
3709
|
if ('set' === argv[2]) {
|
|
3418
3710
|
return finish(runSet(argv.slice(3)))
|
|
@@ -3492,7 +3784,17 @@ function main(argv: string[]): void {
|
|
|
3492
3784
|
process.stderr.write('aontu: --include-root needs a directory\n')
|
|
3493
3785
|
return finish(2)
|
|
3494
3786
|
}
|
|
3495
|
-
trust = { kind: 'root', dir }
|
|
3787
|
+
trust = { kind: 'root', dir, textExt }
|
|
3788
|
+
}
|
|
3789
|
+
else if ('--text-ext' === arg) {
|
|
3790
|
+
const list = null == args[i + 1] ? undefined : parseTextExt(args[++i])
|
|
3791
|
+
if (null == list) {
|
|
3792
|
+
process.stderr.write(
|
|
3793
|
+
'aontu: --text-ext needs extensions, without dots' +
|
|
3794
|
+
' (--text-ext md,sql)\n')
|
|
3795
|
+
return finish(2)
|
|
3796
|
+
}
|
|
3797
|
+
textExt = [...textExt, ...list]
|
|
3496
3798
|
}
|
|
3497
3799
|
else if (arg.startsWith('-')) {
|
|
3498
3800
|
process.stderr.write(`aontu: unknown option ${arg} (try --help)\n`)
|
|
@@ -3519,6 +3821,11 @@ function main(argv: string[]): void {
|
|
|
3519
3821
|
return finish(2)
|
|
3520
3822
|
}
|
|
3521
3823
|
|
|
3824
|
+
// The extensions ride with the capability from here on, so the three
|
|
3825
|
+
// entry shapes below (file, REPL, stdin) each get them by threading
|
|
3826
|
+
// the one value they already thread.
|
|
3827
|
+
trust = { ...trust, textExt }
|
|
3828
|
+
|
|
3522
3829
|
const file = files[0]
|
|
3523
3830
|
if (null != file) {
|
|
3524
3831
|
finish(runFile(file, mode, trust))
|
|
@@ -3547,6 +3854,6 @@ export {
|
|
|
3547
3854
|
runJsonSchema,
|
|
3548
3855
|
runMod,
|
|
3549
3856
|
runHash, runGet,
|
|
3550
|
-
runWhy, renderWhyText, runSet, runAgentsMd,
|
|
3857
|
+
runWhy, renderWhyText, runSet, runAgentsMd, runFmt,
|
|
3551
3858
|
watchChange, watchSignature, vetWaiter, deprecatedAt,
|
|
3552
3859
|
}
|