@aid-framework/cli 0.0.0-stage → 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +45 -2
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/args.d.ts +37 -0
  5. package/dist/args.d.ts.map +1 -0
  6. package/dist/args.js +74 -0
  7. package/dist/args.js.map +1 -0
  8. package/dist/cli.d.ts +17 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +26 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/eval.d.ts +44 -0
  13. package/dist/commands/eval.d.ts.map +1 -0
  14. package/dist/commands/eval.js +257 -0
  15. package/dist/commands/eval.js.map +1 -0
  16. package/dist/commands/gen.d.ts +42 -0
  17. package/dist/commands/gen.d.ts.map +1 -0
  18. package/dist/commands/gen.js +138 -0
  19. package/dist/commands/gen.js.map +1 -0
  20. package/dist/commands/ingest.d.ts +44 -0
  21. package/dist/commands/ingest.d.ts.map +1 -0
  22. package/dist/commands/ingest.js +238 -0
  23. package/dist/commands/ingest.js.map +1 -0
  24. package/dist/commands/init.d.ts +38 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +203 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/validate.d.ts +22 -0
  29. package/dist/commands/validate.d.ts.map +1 -0
  30. package/dist/commands/validate.js +53 -0
  31. package/dist/commands/validate.js.map +1 -0
  32. package/dist/context.d.ts +37 -0
  33. package/dist/context.d.ts.map +1 -0
  34. package/dist/context.js +36 -0
  35. package/dist/context.js.map +1 -0
  36. package/dist/diagnostics.d.ts +42 -0
  37. package/dist/diagnostics.d.ts.map +1 -0
  38. package/dist/diagnostics.js +47 -0
  39. package/dist/diagnostics.js.map +1 -0
  40. package/dist/exit.d.ts +16 -0
  41. package/dist/exit.d.ts.map +1 -0
  42. package/dist/exit.js +15 -0
  43. package/dist/exit.js.map +1 -0
  44. package/dist/index.d.ts +42 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +29 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/main.d.ts +25 -0
  49. package/dist/main.d.ts.map +1 -0
  50. package/dist/main.js +155 -0
  51. package/dist/main.js.map +1 -0
  52. package/dist/output.d.ts +48 -0
  53. package/dist/output.d.ts.map +1 -0
  54. package/dist/output.js +50 -0
  55. package/dist/output.js.map +1 -0
  56. package/dist/paths.d.ts +21 -0
  57. package/dist/paths.d.ts.map +1 -0
  58. package/dist/paths.js +31 -0
  59. package/dist/paths.js.map +1 -0
  60. package/dist/pipeline.d.ts +74 -0
  61. package/dist/pipeline.d.ts.map +1 -0
  62. package/dist/pipeline.js +113 -0
  63. package/dist/pipeline.js.map +1 -0
  64. package/dist/python.d.ts +30 -0
  65. package/dist/python.d.ts.map +1 -0
  66. package/dist/python.js +57 -0
  67. package/dist/python.js.map +1 -0
  68. package/dist/targets.d.ts +75 -0
  69. package/dist/targets.d.ts.map +1 -0
  70. package/dist/targets.js +136 -0
  71. package/dist/targets.js.map +1 -0
  72. package/dist/usage.d.ts +20 -0
  73. package/dist/usage.d.ts.map +1 -0
  74. package/dist/usage.js +49 -0
  75. package/dist/usage.js.map +1 -0
  76. package/package.json +46 -3
package/dist/main.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The dispatcher: argv in, exit code out.
3
+ *
4
+ * It is a pure function of the argv and a `CliContext`, so the whole CLI can be driven in
5
+ * a test by calling `run([...], context)` against a temporary directory and asserting on
6
+ * the captured streams -- no subprocess, no `process.exit`, no spawning the built binary
7
+ * to find out what a flag does.
8
+ *
9
+ * `run` decides only what is genuinely global: which command, whether the invocation was
10
+ * well formed, whether help was asked for, and how an unforeseen exception maps onto an
11
+ * exit code. Everything else belongs to the command, which is why each entry in the table
12
+ * below is a two-line adapter and not a flag handler.
13
+ */
14
+ import type { ParsedArguments } from './args.js';
15
+ import type { CliContext } from './context.js';
16
+ import type { ExitCode } from './exit.js';
17
+ import type { CommandOutcome } from './output.js';
18
+ import type { CommandSpec } from './usage.js';
19
+ interface Command extends CommandSpec {
20
+ readonly run: (context: CliContext, args: ParsedArguments) => CommandOutcome;
21
+ }
22
+ export declare const COMMANDS: readonly Command[];
23
+ export declare function run(argv: readonly string[], context: CliContext): ExitCode;
24
+ export {};
25
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAOjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,UAAU,OAAQ,SAAQ,WAAW;IACnC,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,KAAK,cAAc,CAAC;CAC9E;AAQD,eAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,EAoFtC,CAAC;AA0BF,wBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,CAuC1E"}
package/dist/main.js ADDED
@@ -0,0 +1,155 @@
1
+ /**
2
+ * The dispatcher: argv in, exit code out.
3
+ *
4
+ * It is a pure function of the argv and a `CliContext`, so the whole CLI can be driven in
5
+ * a test by calling `run([...], context)` against a temporary directory and asserting on
6
+ * the captured streams -- no subprocess, no `process.exit`, no spawning the built binary
7
+ * to find out what a flag does.
8
+ *
9
+ * `run` decides only what is genuinely global: which command, whether the invocation was
10
+ * well formed, whether help was asked for, and how an unforeseen exception maps onto an
11
+ * exit code. Everything else belongs to the command, which is why each entry in the table
12
+ * below is a two-line adapter and not a flag handler.
13
+ */
14
+ import { booleanFlag, JSON_FLAG, parseArguments, valueFlag } from './args.js';
15
+ import { evaluate } from './commands/eval.js';
16
+ import { generate } from './commands/gen.js';
17
+ import { ingest } from './commands/ingest.js';
18
+ import { init } from './commands/init.js';
19
+ import { validate } from './commands/validate.js';
20
+ import { EXIT_OK, EXIT_USAGE } from './exit.js';
21
+ import { emit } from './output.js';
22
+ import { targetNames } from './targets.js';
23
+ import { commandUsage, globalUsage } from './usage.js';
24
+ const TARGET_FLAG = valueFlag('target', 'name', `generator target; one of ${targetNames().join(', ')}`);
25
+ export const COMMANDS = [
26
+ {
27
+ name: 'init',
28
+ summary: 'scaffold a project: a starter spec and a README',
29
+ usage: 'init [dir] [--from <spec>] [--target <name>] [--force] [--gen]',
30
+ flags: [
31
+ valueFlag('from', 'spec', 'import an existing spec instead of writing the starter'),
32
+ TARGET_FLAG,
33
+ booleanFlag('force', 'replace a spec or README that is already there'),
34
+ booleanFlag('gen', 'generate immediately after scaffolding'),
35
+ JSON_FLAG,
36
+ ],
37
+ run: (context, args) => init(context, {
38
+ dir: args.positionals[0],
39
+ from: args.values.get('from'),
40
+ target: args.values.get('target'),
41
+ force: args.booleans.has('force'),
42
+ gen: args.booleans.has('gen'),
43
+ }),
44
+ },
45
+ {
46
+ name: 'validate',
47
+ summary: 'parse the spec, build the IR, and run every build-time gate',
48
+ usage: 'validate [spec]',
49
+ flags: [JSON_FLAG],
50
+ run: (context, args) => validate(context, { spec: args.positionals[0] }),
51
+ },
52
+ {
53
+ name: 'gen',
54
+ summary: 'compile the spec and reconcile the tree with it',
55
+ usage: 'gen [spec] [--target <name>] [--dry-run] [--force]',
56
+ flags: [
57
+ TARGET_FLAG,
58
+ booleanFlag('dry-run', 'report what would change, and write nothing'),
59
+ booleanFlag('force', 'overwrite generated files that were edited by hand'),
60
+ JSON_FLAG,
61
+ ],
62
+ run: (context, args) => generate(context, {
63
+ spec: args.positionals[0],
64
+ target: args.values.get('target'),
65
+ dryRun: args.booleans.has('dry-run'),
66
+ force: args.booleans.has('force'),
67
+ }),
68
+ },
69
+ {
70
+ name: 'ingest',
71
+ summary: 'index a retriever corpus into the store the spec declares',
72
+ usage: 'ingest [spec] [--target <name>] [--retriever <id> | --all] [--dry-run]',
73
+ flags: [
74
+ valueFlag('retriever', 'id', 'ingest one declared retriever, by the id the spec used'),
75
+ booleanFlag('all', 'ingest every retriever the spec declares'),
76
+ booleanFlag('dry-run', 'report what a run would write, and write nothing'),
77
+ TARGET_FLAG,
78
+ JSON_FLAG,
79
+ ],
80
+ run: (context, args) => ingest(context, {
81
+ spec: args.positionals[0],
82
+ target: args.values.get('target'),
83
+ retriever: args.values.get('retriever'),
84
+ all: args.booleans.has('all'),
85
+ dryRun: args.booleans.has('dry-run'),
86
+ }),
87
+ },
88
+ {
89
+ name: 'eval',
90
+ summary: 'run the eval gate, or record the baseline it measures against',
91
+ usage: 'eval [spec] [--target <name>] [--suite <id>] [--baseline]',
92
+ flags: [
93
+ valueFlag('suite', 'id', 'run one eval instead of all of them'),
94
+ TARGET_FLAG,
95
+ booleanFlag('baseline', 'record a fresh baseline instead of gating'),
96
+ JSON_FLAG,
97
+ ],
98
+ run: (context, args) => evaluate(context, {
99
+ spec: args.positionals[0],
100
+ target: args.values.get('target'),
101
+ suite: args.values.get('suite'),
102
+ baseline: args.booleans.has('baseline'),
103
+ }),
104
+ },
105
+ ];
106
+ function usageError(context, message, usage) {
107
+ context.stderr(`aid: ${message}\n\n${usage ?? globalUsage(COMMANDS)}`);
108
+ return EXIT_USAGE;
109
+ }
110
+ /**
111
+ * Map an unexpected throw onto exit 2. A command that crashed has not judged the project,
112
+ * so it must not report `1` -- that code means "the project is wrong", and a crash
113
+ * claiming it would send a reader looking for a spec problem that does not exist.
114
+ */
115
+ function internalError(context, json, command, error) {
116
+ const message = error instanceof Error ? error.message : String(error);
117
+ context.stderr(`aid: internal error in \`${command}\`: ${message}\n`);
118
+ if (json) {
119
+ context.stdout(`${JSON.stringify({ command, ok: false, diagnostics: [] }, null, 2)}\n`);
120
+ }
121
+ return EXIT_USAGE;
122
+ }
123
+ export function run(argv, context) {
124
+ const [name, ...rest] = argv;
125
+ if (name === undefined || name === '--help' || name === '-h' || name === 'help') {
126
+ context.stdout(globalUsage(COMMANDS));
127
+ // No command at all is a usage error; explicitly asking for help is not.
128
+ return name === undefined ? EXIT_USAGE : EXIT_OK;
129
+ }
130
+ const command = COMMANDS.find((candidate) => candidate.name === name);
131
+ if (command === undefined) {
132
+ return usageError(context, `unknown command \`${name}\``);
133
+ }
134
+ const parsed = parseArguments(rest, command.flags);
135
+ if (!parsed.ok) {
136
+ return usageError(context, parsed.message, commandUsage(command));
137
+ }
138
+ if (parsed.args.help) {
139
+ context.stdout(commandUsage(command));
140
+ return EXIT_OK;
141
+ }
142
+ // Every command takes at most one positional (a spec, or the directory to scaffold
143
+ // into), so the arity rule lives here rather than four times in four commands.
144
+ if (parsed.args.positionals.length > 1) {
145
+ return usageError(context, `\`aid ${command.name}\` takes at most one path, got ${parsed.args.positionals.length}`, commandUsage(command));
146
+ }
147
+ const json = parsed.args.booleans.has('json');
148
+ try {
149
+ return emit(context, json, command.run(context, parsed.args));
150
+ }
151
+ catch (error) {
152
+ return internalError(context, json, command.name, error);
153
+ }
154
+ }
155
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The command's whole result: what to print, what to embed in `--json`, and what to
3
+ * exit with.
4
+ *
5
+ * Commands return this instead of printing and exiting themselves, so that a command
6
+ * can be asserted on directly and so that `init --gen` can run the generation pipeline
7
+ * and fold its outcome into its own. `ok` is derived from the exit code rather than
8
+ * passed alongside it, because two fields that can disagree eventually will.
9
+ */
10
+ import type { CliContext } from './context.js';
11
+ import type { CliDiagnostic } from './diagnostics.js';
12
+ import type { ExitCode } from './exit.js';
13
+ export interface CommandOutcome {
14
+ readonly exitCode: ExitCode;
15
+ /** The `--json` document. */
16
+ readonly report: Record<string, unknown>;
17
+ readonly diagnostics: readonly CliDiagnostic[];
18
+ /** The human rendering on stdout. Empty when there is nothing to say. */
19
+ readonly text: string;
20
+ /**
21
+ * Text a subprocess wrote to its own stderr, carried through to the CLI's stderr.
22
+ *
23
+ * `aid eval` is the only user. It cannot be folded into {@link text}: `--json` swaps
24
+ * stdout for a single JSON document, and an eval that explains on stderr why it could
25
+ * not measure something would have that explanation dropped by the one mode a machine
26
+ * reads.
27
+ */
28
+ readonly stderr?: string;
29
+ }
30
+ export interface OutcomeInit {
31
+ readonly command: string;
32
+ readonly exitCode: ExitCode;
33
+ readonly fields?: Record<string, unknown>;
34
+ readonly diagnostics?: readonly CliDiagnostic[];
35
+ readonly text?: string;
36
+ readonly stderr?: string;
37
+ }
38
+ export declare function outcome(init: OutcomeInit): CommandOutcome;
39
+ /**
40
+ * Print an outcome and hand back its exit code.
41
+ *
42
+ * Diagnostics go to stderr in both modes. In `--json` mode stdout carries exactly one
43
+ * JSON document and nothing else, so that `aid ... --json | jq` is always well formed;
44
+ * the diagnostics are in that document *and* on stderr, which is what a caller piping
45
+ * stdout wants and what a human watching a terminal wants.
46
+ */
47
+ export declare function emit(context: CliContext, json: boolean, command: CommandOutcome): ExitCode;
48
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/C,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,cAAc,CAczD;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,QAAQ,CAa1F"}
package/dist/output.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The command's whole result: what to print, what to embed in `--json`, and what to
3
+ * exit with.
4
+ *
5
+ * Commands return this instead of printing and exiting themselves, so that a command
6
+ * can be asserted on directly and so that `init --gen` can run the generation pipeline
7
+ * and fold its outcome into its own. `ok` is derived from the exit code rather than
8
+ * passed alongside it, because two fields that can disagree eventually will.
9
+ */
10
+ import { formatDiagnostics } from '@aid-framework/spec';
11
+ import { EXIT_OK } from './exit.js';
12
+ export function outcome(init) {
13
+ const diagnostics = init.diagnostics ?? [];
14
+ return {
15
+ exitCode: init.exitCode,
16
+ diagnostics,
17
+ text: init.text ?? '',
18
+ ...(init.stderr === undefined ? {} : { stderr: init.stderr }),
19
+ report: {
20
+ command: init.command,
21
+ ok: init.exitCode === EXIT_OK,
22
+ ...init.fields,
23
+ diagnostics,
24
+ },
25
+ };
26
+ }
27
+ /**
28
+ * Print an outcome and hand back its exit code.
29
+ *
30
+ * Diagnostics go to stderr in both modes. In `--json` mode stdout carries exactly one
31
+ * JSON document and nothing else, so that `aid ... --json | jq` is always well formed;
32
+ * the diagnostics are in that document *and* on stderr, which is what a caller piping
33
+ * stdout wants and what a human watching a terminal wants.
34
+ */
35
+ export function emit(context, json, command) {
36
+ if (json) {
37
+ context.stdout(`${JSON.stringify(command.report, null, 2)}\n`);
38
+ }
39
+ else if (command.text !== '') {
40
+ context.stdout(command.text.endsWith('\n') ? command.text : `${command.text}\n`);
41
+ }
42
+ if (command.stderr !== undefined && command.stderr !== '') {
43
+ context.stderr(command.stderr.endsWith('\n') ? command.stderr : `${command.stderr}\n`);
44
+ }
45
+ if (command.diagnostics.length > 0) {
46
+ context.stderr(formatDiagnostics(command.diagnostics));
47
+ }
48
+ return command.exitCode;
49
+ }
50
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAIxD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BpC,MAAM,UAAU,OAAO,CAAC,IAAiB;IACvC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;IAC3C,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW;QACX,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;QACrB,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,MAAM,EAAE;YACN,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,EAAE,EAAE,IAAI,CAAC,QAAQ,KAAK,OAAO;YAC7B,GAAG,IAAI,CAAC,MAAM;YACd,WAAW;SACZ;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAAC,OAAmB,EAAE,IAAa,EAAE,OAAuB;IAC9E,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1D,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The repository-relative POSIX paths every package in this repository speaks, and the
3
+ * one place they become operating-system paths.
4
+ *
5
+ * A plan's paths, a manifest's records and a generator's path helpers are all
6
+ * `app/generated/...`, joined with `/`. They are converted at the filesystem boundary
7
+ * and nowhere else, so no comparison in the CLI can be defeated by a separator.
8
+ */
9
+ /**
10
+ * The absolute path `posixPath` names under `root`.
11
+ *
12
+ * An absolute path is taken as it is. `aid init --from C:\specs\app.spec.yaml` and
13
+ * `aid validate /srv/app/app.spec.yaml` are ordinary invocations, and joining an absolute
14
+ * path onto the working directory does not fail loudly -- it produces a well-formed path
15
+ * to a file that cannot exist, so the caller reads a "no such file" for a file that is
16
+ * right there.
17
+ */
18
+ export declare function absolutePath(root: string, posixPath: string): string;
19
+ /** The parent of a repository-relative POSIX path, or `''` for a top-level one. */
20
+ export declare function parentPath(posixPath: string): string;
21
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGpD"}
package/dist/paths.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The repository-relative POSIX paths every package in this repository speaks, and the
3
+ * one place they become operating-system paths.
4
+ *
5
+ * A plan's paths, a manifest's records and a generator's path helpers are all
6
+ * `app/generated/...`, joined with `/`. They are converted at the filesystem boundary
7
+ * and nowhere else, so no comparison in the CLI can be defeated by a separator.
8
+ */
9
+ import { isAbsolute, join, resolve } from 'node:path';
10
+ /**
11
+ * The absolute path `posixPath` names under `root`.
12
+ *
13
+ * An absolute path is taken as it is. `aid init --from C:\specs\app.spec.yaml` and
14
+ * `aid validate /srv/app/app.spec.yaml` are ordinary invocations, and joining an absolute
15
+ * path onto the working directory does not fail loudly -- it produces a well-formed path
16
+ * to a file that cannot exist, so the caller reads a "no such file" for a file that is
17
+ * right there.
18
+ */
19
+ export function absolutePath(root, posixPath) {
20
+ if (posixPath === '')
21
+ return root;
22
+ if (isAbsolute(posixPath))
23
+ return resolve(posixPath);
24
+ return join(root, ...posixPath.split('/'));
25
+ }
26
+ /** The parent of a repository-relative POSIX path, or `''` for a top-level one. */
27
+ export function parentPath(posixPath) {
28
+ const index = posixPath.lastIndexOf('/');
29
+ return index === -1 ? '' : posixPath.slice(0, index);
30
+ }
31
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,SAAiB;IAC1D,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The compile pipeline: read the spec, lower it to the IR, run every build-time gate,
3
+ * then ask the target to compile it.
4
+ *
5
+ * This is the sequence `packages/generators/py-fastapi/scripts/generate-example.mjs`
6
+ * already performs for the example app, and it is deliberately the *same* sequence
7
+ * rather than a parallel one: every step is a call into `@aid-framework/spec`, `@aid-framework/ir`,
8
+ * `@aid-framework/generator-sdk` or `@aid-framework/generator-py-fastapi`. The CLI introduces no gate, no
9
+ * hash, no drift rule and no manifest reader of its own -- a second implementation of a
10
+ * gate is a defect, because the two can disagree and only one of them will be right.
11
+ *
12
+ * Two behaviours worth stating because they are choices, not accidents:
13
+ *
14
+ * - Stages stop at the first error. Lowering a spec whose own schema did not validate
15
+ * would report a cascade of consequences of the first mistake, which buries it.
16
+ * Warnings produced before the stop are kept, because the design emits some
17
+ * deliberately -- the eval-coverage gate warns rather than fails.
18
+ * - The target's compiler runs *before* its planner. `checkPlan` reports every problem
19
+ * at once; `plan` throws. Asking first is what lets `aid gen` print the target's own
20
+ * codes and paths instead of a stack trace with an exception dressed up as a
21
+ * diagnostic.
22
+ */
23
+ import { type AidManifest, type AidManifestProvenance, type Plan, type RegenerationSink } from '@aid-framework/generator-sdk';
24
+ import type { IR } from '@aid-framework/ir';
25
+ import type { CliContext } from './context.js';
26
+ import type { CliDiagnostic } from './diagnostics.js';
27
+ import type { Target } from './targets.js';
28
+ /** A stage that judged the project and said no. */
29
+ export interface Failed {
30
+ readonly ok: false;
31
+ readonly diagnostics: readonly CliDiagnostic[];
32
+ }
33
+ export interface ReadSpec {
34
+ readonly ok: true;
35
+ readonly text: string;
36
+ }
37
+ /** A spec that reduced to an IR the gates accepted. `diagnostics` holds its warnings. */
38
+ export interface Lowered {
39
+ readonly ok: true;
40
+ readonly ir: IR;
41
+ readonly diagnostics: readonly CliDiagnostic[];
42
+ }
43
+ export type LowerOutcome = Lowered | Failed;
44
+ /** A spec the target accepted, with the plan it produced. */
45
+ export interface Compiled {
46
+ readonly ok: true;
47
+ readonly ir: IR;
48
+ readonly plan: Plan;
49
+ readonly diagnostics: readonly CliDiagnostic[];
50
+ }
51
+ export type CompileOutcome = Compiled | Failed;
52
+ /** A manifest read back from the tree, or the diagnostics explaining why it was not. */
53
+ export interface ReadManifest {
54
+ readonly ok: true;
55
+ readonly manifest: AidManifest | undefined;
56
+ }
57
+ export type ManifestOutcome = ReadManifest | Failed;
58
+ export declare function readSpec(context: CliContext, specPath: string): ReadSpec | Failed;
59
+ export declare function lowerSpec(text: string, file: string): LowerOutcome;
60
+ export declare function compile(text: string, file: string, target: Target): CompileOutcome;
61
+ /**
62
+ * The manifest the tree currently holds, read through the sink so that the path-escape
63
+ * guard and the "missing file is `undefined`" contract are the SDK's rather than this
64
+ * layer's. A manifest with an error in it is a failure, not a warning: generation
65
+ * cannot tell a hand edit from its own output without it.
66
+ */
67
+ export declare function readManifest(sink: RegenerationSink, target: Target): ManifestOutcome;
68
+ /**
69
+ * What the next manifest records about the run that wrote it, read off the target's own
70
+ * manifest so that the generator identity in the manifest and the generator that ran
71
+ * cannot disagree.
72
+ */
73
+ export declare function provenanceFor(target: Target, ir: IR): AidManifestProvenance;
74
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,IAAI,EAET,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAI5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,mDAAmD;AACnD,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,yFAAyF;AACzF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAC;AAE5C,6DAA6D;AAC7D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE/C,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,CAAC;CAC5C;AAED,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,MAAM,CAAC;AAMpD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAgBjF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAwBlE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CASlF;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CAYpF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,qBAAqB,CAM3E"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The compile pipeline: read the spec, lower it to the IR, run every build-time gate,
3
+ * then ask the target to compile it.
4
+ *
5
+ * This is the sequence `packages/generators/py-fastapi/scripts/generate-example.mjs`
6
+ * already performs for the example app, and it is deliberately the *same* sequence
7
+ * rather than a parallel one: every step is a call into `@aid-framework/spec`, `@aid-framework/ir`,
8
+ * `@aid-framework/generator-sdk` or `@aid-framework/generator-py-fastapi`. The CLI introduces no gate, no
9
+ * hash, no drift rule and no manifest reader of its own -- a second implementation of a
10
+ * gate is a defect, because the two can disagree and only one of them will be right.
11
+ *
12
+ * Two behaviours worth stating because they are choices, not accidents:
13
+ *
14
+ * - Stages stop at the first error. Lowering a spec whose own schema did not validate
15
+ * would report a cascade of consequences of the first mistake, which buries it.
16
+ * Warnings produced before the stop are kept, because the design emits some
17
+ * deliberately -- the eval-coverage gate warns rather than fails.
18
+ * - The target's compiler runs *before* its planner. `checkPlan` reports every problem
19
+ * at once; `plan` throws. Asking first is what lets `aid gen` print the target's own
20
+ * codes and paths instead of a stack trace with an exception dressed up as a
21
+ * diagnostic.
22
+ */
23
+ import { readFileSync } from 'node:fs';
24
+ import { parseAidManifestJson, } from '@aid-framework/generator-sdk';
25
+ import { buildIR, runGates } from '@aid-framework/ir';
26
+ import { checkSpecText, hasErrors, sortDiagnostics } from '@aid-framework/spec';
27
+ import { CLI_DIAGNOSTIC_CODES, cliError } from './diagnostics.js';
28
+ import { absolutePath } from './paths.js';
29
+ import { targetCapabilities } from './targets.js';
30
+ function describeError(error) {
31
+ return error instanceof Error ? error.message : String(error);
32
+ }
33
+ export function readSpec(context, specPath) {
34
+ try {
35
+ return { ok: true, text: readFileSync(absolutePath(context.cwd, specPath), 'utf8') };
36
+ }
37
+ catch (error) {
38
+ return {
39
+ ok: false,
40
+ diagnostics: [
41
+ cliError({
42
+ code: CLI_DIAGNOSTIC_CODES.specUnreadable,
43
+ message: `Cannot read the spec at "${specPath}": ${describeError(error)}`,
44
+ path: [specPath],
45
+ hint: 'Run `aid init` to scaffold a project, or pass the path to an existing spec.',
46
+ }),
47
+ ],
48
+ };
49
+ }
50
+ }
51
+ export function lowerSpec(text, file) {
52
+ const diagnostics = [];
53
+ const parsed = checkSpecText(text, { file });
54
+ diagnostics.push(...parsed.diagnostics);
55
+ if (!parsed.ok || parsed.value === undefined) {
56
+ return { ok: false, diagnostics: sortDiagnostics(diagnostics) };
57
+ }
58
+ const built = buildIR(parsed.value, { file });
59
+ diagnostics.push(...built.diagnostics);
60
+ if (hasErrors(built.diagnostics)) {
61
+ return { ok: false, diagnostics: sortDiagnostics(diagnostics) };
62
+ }
63
+ // The gates take the *generators'* capability declarations, not the IR package's
64
+ // placeholder: a gate run against a placeholder passes every spec and is not a gate.
65
+ const gates = runGates(built.ir, { targetCapabilities: targetCapabilities(), file });
66
+ diagnostics.push(...gates.diagnostics);
67
+ if (hasErrors(gates.diagnostics)) {
68
+ return { ok: false, diagnostics: sortDiagnostics(diagnostics) };
69
+ }
70
+ return { ok: true, ir: built.ir, diagnostics: sortDiagnostics(diagnostics) };
71
+ }
72
+ export function compile(text, file, target) {
73
+ const lowered = lowerSpec(text, file);
74
+ if (!lowered.ok)
75
+ return lowered;
76
+ const problems = target.check(lowered.ir);
77
+ const diagnostics = sortDiagnostics([...lowered.diagnostics, ...problems]);
78
+ if (hasErrors(problems))
79
+ return { ok: false, diagnostics };
80
+ return { ok: true, ir: lowered.ir, plan: target.plan(lowered.ir), diagnostics };
81
+ }
82
+ /**
83
+ * The manifest the tree currently holds, read through the sink so that the path-escape
84
+ * guard and the "missing file is `undefined`" contract are the SDK's rather than this
85
+ * layer's. A manifest with an error in it is a failure, not a warning: generation
86
+ * cannot tell a hand edit from its own output without it.
87
+ */
88
+ export function readManifest(sink, target) {
89
+ const text = sink.read(target.manifestPath);
90
+ if (text === undefined)
91
+ return { ok: true, manifest: undefined };
92
+ const parsed = parseAidManifestJson(text, {
93
+ generatedDir: target.generatedDir,
94
+ businessDir: target.businessDir,
95
+ });
96
+ if (parsed.manifest === undefined || hasErrors(parsed.diagnostics)) {
97
+ return { ok: false, diagnostics: sortDiagnostics(parsed.diagnostics) };
98
+ }
99
+ return { ok: true, manifest: parsed.manifest };
100
+ }
101
+ /**
102
+ * What the next manifest records about the run that wrote it, read off the target's own
103
+ * manifest so that the generator identity in the manifest and the generator that ran
104
+ * cannot disagree.
105
+ */
106
+ export function provenanceFor(target, ir) {
107
+ return {
108
+ generator: target.manifest.name,
109
+ generatorVersion: target.manifest.version,
110
+ irVersion: ir.irVersion,
111
+ };
112
+ }
113
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAIL,oBAAoB,GAErB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAIhF,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAwClD,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAmB,EAAE,QAAgB;IAC5D,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;IACvF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,WAAW,EAAE;gBACX,QAAQ,CAAC;oBACP,IAAI,EAAE,oBAAoB,CAAC,cAAc;oBACzC,OAAO,EAAE,4BAA4B,QAAQ,MAAM,aAAa,CAAC,KAAK,CAAC,EAAE;oBACzE,IAAI,EAAE,CAAC,QAAQ,CAAC;oBAChB,IAAI,EAAE,6EAA6E;iBACpF,CAAC;aACH;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IAClD,MAAM,WAAW,GAAoB,EAAE,CAAC;IAExC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;IAClE,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;IAClE,CAAC;IAED,iFAAiF;IACjF,qFAAqF;IACrF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACrF,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;IAClE,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,IAAY,EAAE,MAAc;IAChE,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,OAAO,CAAC;IAEhC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC3E,IAAI,SAAS,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAE3D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;AAClF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAsB,EAAE,MAAc;IACjE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAEjE,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,EAAE;QACxC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACnE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,EAAM;IAClD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;QAC/B,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;QACzC,SAAS,EAAE,EAAE,CAAC,SAAS;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The Python toolchain the commands that run generated code have to find.
3
+ *
4
+ * `aid eval` and `aid ingest` both shell out to a module the generator emitted, so both
5
+ * need the same two answers: which interpreter can actually import the runtime, and how
6
+ * to spawn it. Keeping the discovery here means there is one definition of "a usable
7
+ * interpreter" -- if the two commands each carried their own, an environment could work
8
+ * for one and not the other without anything explaining why.
9
+ *
10
+ * The contract is deliberately narrow: the caller names the module, and this file only
11
+ * decides which program runs it and from where. It knows nothing about evals or ingest.
12
+ */
13
+ import type { CliContext, SpawnResult } from './context.js';
14
+ /**
15
+ * Tried in order. The interpreter already active on this project comes first: it is the
16
+ * one the runtime was installed into. `uv` is last, and is kept because a uv-managed
17
+ * environment that has not been activated is a real setup where none of the others exist.
18
+ */
19
+ export declare const INTERPRETERS: readonly ['python3', 'python', 'uv'];
20
+ /** `uv run python` is a different argv shape from `python`, so it is not a rename. */
21
+ export declare function interpreterCommand(interpreter: string): readonly string[];
22
+ /**
23
+ * Spawn, or `undefined` when the program could not be executed at all. `spawnSync` reports
24
+ * a missing binary as `error` with a `null` status, and collapsing those two into one
25
+ * `undefined` is what lets discovery and the real run share a code path.
26
+ */
27
+ export declare function invoke(context: CliContext, command: readonly string[], stdin?: string): SpawnResult | undefined;
28
+ /** The first interpreter that can import the runtime, or `undefined` when none can. */
29
+ export declare function discoverInterpreter(context: CliContext): string | undefined;
30
+ //# sourceMappingURL=python.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../src/python.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,YAAY,YAAI,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAU,CAAC;AAWjE,sFAAsF;AACtF,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CACpB,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,CAAC,EAAE,MAAM,GACb,WAAW,GAAG,SAAS,CAUzB;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAM3E"}