@aid-framework/cli 0.1.62 → 0.1.64

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `aid cost` — a cost and latency report read from the local trace sink.
2
+ * `aid cost` — a cost and latency report read from the local trace sink.
3
3
  *
4
4
  * The numbers already exist. `runtimes/{python,typescript}` write one JSONL span per line
5
5
  * whenever `AID_TRACE_DIR` is set, and those spans carry the GenAI token attributes and
@@ -1 +1 @@
1
- {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAyDD,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,GAAG,cAAc,CA4I9E"}
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AA0CD,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,GAAG,cAAc,CAuF9E"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `aid cost` — a cost and latency report read from the local trace sink.
2
+ * `aid cost` — a cost and latency report read from the local trace sink.
3
3
  *
4
4
  * The numbers already exist. `runtimes/{python,typescript}` write one JSONL span per line
5
5
  * whenever `AID_TRACE_DIR` is set, and those spans carry the GenAI token attributes and
@@ -18,28 +18,11 @@
18
18
  * - `0` otherwise, including for an empty directory: a report of zero spans is true, and
19
19
  * the warning on stderr says why it is zero.
20
20
  */
21
- import { readdirSync, readFileSync, statSync } from 'node:fs';
22
- import { isAbsolute, join, relative, resolve, sep } from 'node:path';
23
21
  import { CLI_DIAGNOSTIC_CODES, cliError, cliWarning } from '../diagnostics.js';
24
22
  import { EXIT_FAILURE, EXIT_OK, EXIT_USAGE } from '../exit.js';
25
- import { outcome } from '../output.js';
26
- import { parseSince, parseTraceLines, summariseSpans } from '../trace.js';
27
- /** The variable the runtimes read. Named here, not imported, because it is a runtime knob. */
28
- const TRACE_DIR_ENV = 'AID_TRACE_DIR';
29
- function displayPath(cwd, absolute) {
30
- const path = relative(cwd, absolute);
31
- if (path === '')
32
- return '.';
33
- if (path.startsWith('..') || isAbsolute(path))
34
- return absolute;
35
- return path.split(sep).join('/');
36
- }
37
- function group(value) {
38
- return String(Math.trunc(value)).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
39
- }
40
- function usd(value) {
41
- return `$${value.toFixed(6)}`;
42
- }
23
+ import { group, outcome, usd } from '../output.js';
24
+ import { parseSince, summariseSpans } from '../trace.js';
25
+ import { confirmTraceDir, locateTraceDir, readTraceDir, TRACE_DIR_ENV } from '../trace-dir.js';
43
26
  function modelLines(models) {
44
27
  if (models.length === 0)
45
28
  return [];
@@ -52,7 +35,7 @@ function modelLines(models) {
52
35
  `${String(model.calls).padStart(4)} calls`,
53
36
  `${group(model.inputTokens).padStart(9)} in`,
54
37
  `${group(model.outputTokens).padStart(9)} out`,
55
- usd(model.costUsd).padStart(14),
38
+ usd(model.costUsd, 6).padStart(14),
56
39
  unpriced,
57
40
  ].join(' '));
58
41
  }
@@ -64,8 +47,8 @@ function reportLines(summary, dir, since) {
64
47
  `dir: ${dir}`,
65
48
  `spans: ${group(summary.spans)} in ${group(summary.traces)} trace(s)${scope}`,
66
49
  summary.unpricedSpans === 0
67
- ? `cost: ${usd(summary.costUsd)}`
68
- : `cost: ${usd(summary.costUsd)} (${summary.unpricedSpans} unpriced span(s) not included)`,
50
+ ? `cost: ${usd(summary.costUsd, 6)}`
51
+ : `cost: ${usd(summary.costUsd, 6)} (${summary.unpricedSpans} unpriced span(s) not included)`,
69
52
  `tokens: ${group(summary.inputTokens)} input, ${group(summary.outputTokens)} output`,
70
53
  ];
71
54
  if (summary.latency !== undefined) {
@@ -78,21 +61,10 @@ function reportLines(summary, dir, since) {
78
61
  }
79
62
  export function cost(context, options) {
80
63
  const command = 'cost';
81
- const configured = options.dir ?? context.env[TRACE_DIR_ENV]?.trim();
82
- if (configured === undefined || configured === '') {
83
- return outcome({
84
- command,
85
- exitCode: EXIT_USAGE,
86
- diagnostics: [
87
- cliError({
88
- code: CLI_DIAGNOSTIC_CODES.traceDirMissing,
89
- message: `no trace directory: \`aid cost\` needs one to read.`,
90
- hint: `Pass it as \`aid ${command} <dir>\`, or set ${TRACE_DIR_ENV} to the directory the runtime writes to.`,
91
- }),
92
- ],
93
- text: `aid: no trace directory. Pass one, or set ${TRACE_DIR_ENV}.\n`,
94
- });
95
- }
64
+ const located = locateTraceDir(context, options.dir, command);
65
+ if (located.kind === 'refused')
66
+ return located.outcome;
67
+ const shown = located.shown;
96
68
  let since;
97
69
  if (options.since !== undefined) {
98
70
  since = parseSince(options.since);
@@ -111,51 +83,11 @@ export function cost(context, options) {
111
83
  });
112
84
  }
113
85
  }
114
- const absolute = resolve(context.cwd, configured);
115
- const shown = displayPath(context.cwd, absolute);
86
+ const confirmed = confirmTraceDir(located, command);
87
+ if (confirmed.kind === 'refused')
88
+ return confirmed.outcome;
116
89
  const diagnostics = [];
117
- let isDirectory = false;
118
- try {
119
- isDirectory = statSync(absolute).isDirectory();
120
- }
121
- catch {
122
- isDirectory = false;
123
- }
124
- if (!isDirectory) {
125
- return outcome({
126
- command,
127
- exitCode: EXIT_USAGE,
128
- diagnostics: [
129
- cliError({
130
- code: CLI_DIAGNOSTIC_CODES.traceDirNotFound,
131
- message: `"${shown}" is not a directory.`,
132
- hint: `Point \`aid ${command}\` at the directory ${TRACE_DIR_ENV} names, or unset it to be told which is missing.`,
133
- }),
134
- ],
135
- text: `aid: "${shown}" is not a directory.\n`,
136
- });
137
- }
138
- const names = readdirSync(absolute, { withFileTypes: true })
139
- .filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl'))
140
- .map((entry) => entry.name)
141
- .sort();
142
- let skipped = 0;
143
- const all = [];
144
- let unreadable = 0;
145
- for (const name of names) {
146
- let text;
147
- try {
148
- text = readFileSync(join(absolute, name), 'utf8');
149
- }
150
- catch {
151
- // Counted, not thrown: one unreadable file should not hide the spans in the rest.
152
- unreadable += 1;
153
- continue;
154
- }
155
- const parsed = parseTraceLines(text);
156
- all.push(...parsed.spans);
157
- skipped += parsed.skipped;
158
- }
90
+ const { files: names, spans: all, skipped, unreadable } = readTraceDir(confirmed.absolute);
159
91
  if (unreadable > 0) {
160
92
  diagnostics.push(cliError({
161
93
  code: CLI_DIAGNOSTIC_CODES.traceUnreadable,
@@ -1 +1 @@
1
- {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/commands/cost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `aid migrate` — emit the SQL the declared stores need, for an operator to apply once.
3
+ *
4
+ * Both runtimes create their own schema on first connect (`CREATE ... IF NOT EXISTS`), so
5
+ * this command is not how the application works; it is how the application is allowed to
6
+ * *stop* creating schema. A production role that only needs `INSERT`/`SELECT` should not
7
+ * hold `CREATE TABLE` because the first request happened to arrive before the table did.
8
+ * Emitting the same schema as a reviewable file moves that one-time act to the operator
9
+ * and leaves the application's `IF NOT EXISTS` as a no-op.
10
+ *
11
+ * Four decisions worth stating:
12
+ *
13
+ * - **Bootstrap only.** Every statement is idempotent, so re-applying is harmless. The file
14
+ * creates and never alters: once `aid_chunks` exists, `IF NOT EXISTS` skips the table,
15
+ * so an edited vector dimension would report success while the column kept its old type.
16
+ * A changed dimension is a *new* migration, and the header says so where the person
17
+ * editing the file will read it.
18
+ * - **No target flag.** The SQL is identical for both runtimes -- they declare the same
19
+ * table, the same columns and the same operators -- so a `--target` option would imply a
20
+ * per-target difference that does not exist.
21
+ * - **One file, whatever the store count.** The runtimes use a single shared `aid_chunks`
22
+ * table and do not key rows by store id, so a second `pgvector` store is not a second
23
+ * table. Emitting one file per store would print the same DDL twice and invite a reader
24
+ * to believe the stores are isolated.
25
+ * - **The file is identified by its own header.** `migrations/` is a directory people keep
26
+ * their own migrations in. `aid migrate` only rewrites or deletes a file that carries the
27
+ * header it writes, so a hand-written `aid-schema.sql` is refused rather than replaced.
28
+ *
29
+ * The table DDL is restated here because neither runtime publishes it as a value the CLI
30
+ * can import -- Python holds it in a module constant, TypeScript in another. That is a
31
+ * third copy, so `migrate.test.ts` reads both runtimes' sources and fails when either one
32
+ * stops agreeing with {@link AID_CHUNKS_TABLE}: the duplication is guarded rather than
33
+ * hoped for.
34
+ */
35
+ import type { CliContext } from '../context.js';
36
+ import type { CommandOutcome } from '../output.js';
37
+ export interface MigrateOptions {
38
+ readonly spec: string | undefined;
39
+ /** Directory for the migration file, repo-relative; defaults to `migrations`. */
40
+ readonly out: string | undefined;
41
+ /** Fail when the committed file does not match the spec; writes nothing. */
42
+ readonly check: boolean;
43
+ readonly dryRun: boolean;
44
+ }
45
+ /** The header that marks a file as this command's to rewrite. */
46
+ export declare const MIGRATION_MARKER = "-- Generated by aid migrate. Do not edit.";
47
+ /**
48
+ * The table both runtimes declare, verbatim apart from the embedding type.
49
+ *
50
+ * `{embedding}` is replaced with `vector(N)` when the spec pins one dimension and with
51
+ * `vector` when it does not. The column list, its types and its `NOT NULL`s are what the
52
+ * runtimes' insert and select statements assume; a driver that added or renamed a column
53
+ * would fail at runtime, not here.
54
+ */
55
+ export declare const AID_CHUNKS_TABLE = "CREATE TABLE IF NOT EXISTS aid_chunks (\n chunk_id text PRIMARY KEY,\n doc_id text NOT NULL,\n uri text NOT NULL,\n chunk_index integer NOT NULL,\n start_offset integer NOT NULL,\n end_offset integer NOT NULL,\n body text NOT NULL,\n metadata jsonb NOT NULL DEFAULT '{}'::jsonb,\n embedding {embedding} NOT NULL\n);";
56
+ export declare function migrate(context: CliContext, options: MigrateOptions): CommandOutcome;
57
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAQH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAKnD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iFAAiF;IACjF,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,8CAA8C,CAAC;AAK5E;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,2VAU1B,CAAC;AAuLJ,wBAAgB,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,GAAG,cAAc,CA+GpF"}
@@ -0,0 +1,305 @@
1
+ /**
2
+ * `aid migrate` — emit the SQL the declared stores need, for an operator to apply once.
3
+ *
4
+ * Both runtimes create their own schema on first connect (`CREATE ... IF NOT EXISTS`), so
5
+ * this command is not how the application works; it is how the application is allowed to
6
+ * *stop* creating schema. A production role that only needs `INSERT`/`SELECT` should not
7
+ * hold `CREATE TABLE` because the first request happened to arrive before the table did.
8
+ * Emitting the same schema as a reviewable file moves that one-time act to the operator
9
+ * and leaves the application's `IF NOT EXISTS` as a no-op.
10
+ *
11
+ * Four decisions worth stating:
12
+ *
13
+ * - **Bootstrap only.** Every statement is idempotent, so re-applying is harmless. The file
14
+ * creates and never alters: once `aid_chunks` exists, `IF NOT EXISTS` skips the table,
15
+ * so an edited vector dimension would report success while the column kept its old type.
16
+ * A changed dimension is a *new* migration, and the header says so where the person
17
+ * editing the file will read it.
18
+ * - **No target flag.** The SQL is identical for both runtimes -- they declare the same
19
+ * table, the same columns and the same operators -- so a `--target` option would imply a
20
+ * per-target difference that does not exist.
21
+ * - **One file, whatever the store count.** The runtimes use a single shared `aid_chunks`
22
+ * table and do not key rows by store id, so a second `pgvector` store is not a second
23
+ * table. Emitting one file per store would print the same DDL twice and invite a reader
24
+ * to believe the stores are isolated.
25
+ * - **The file is identified by its own header.** `migrations/` is a directory people keep
26
+ * their own migrations in. `aid migrate` only rewrites or deletes a file that carries the
27
+ * header it writes, so a hand-written `aid-schema.sql` is refused rather than replaced.
28
+ *
29
+ * The table DDL is restated here because neither runtime publishes it as a value the CLI
30
+ * can import -- Python holds it in a module constant, TypeScript in another. That is a
31
+ * third copy, so `migrate.test.ts` reads both runtimes' sources and fails when either one
32
+ * stops agreeing with {@link AID_CHUNKS_TABLE}: the duplication is guarded rather than
33
+ * hoped for.
34
+ */
35
+ import { resolve, sep } from 'node:path';
36
+ import { createNodeSink } from '@aid-framework/generator-sdk';
37
+ import { hasErrors } from '@aid-framework/spec';
38
+ import { CLI_DIAGNOSTIC_CODES, cliError, cliWarning } from '../diagnostics.js';
39
+ import { EXIT_FAILURE, EXIT_OK, EXIT_USAGE } from '../exit.js';
40
+ import { outcome } from '../output.js';
41
+ import { lowerSpec, readSpec } from '../pipeline.js';
42
+ import { DEFAULT_SPEC_PATH } from '../targets.js';
43
+ /** The header that marks a file as this command's to rewrite. */
44
+ export const MIGRATION_MARKER = '-- Generated by aid migrate. Do not edit.';
45
+ const DEFAULT_OUT_DIR = 'migrations';
46
+ const FILE_NAME = 'aid-schema.sql';
47
+ /**
48
+ * The table both runtimes declare, verbatim apart from the embedding type.
49
+ *
50
+ * `{embedding}` is replaced with `vector(N)` when the spec pins one dimension and with
51
+ * `vector` when it does not. The column list, its types and its `NOT NULL`s are what the
52
+ * runtimes' insert and select statements assume; a driver that added or renamed a column
53
+ * would fail at runtime, not here.
54
+ */
55
+ export const AID_CHUNKS_TABLE = `CREATE TABLE IF NOT EXISTS aid_chunks (
56
+ chunk_id text PRIMARY KEY,
57
+ doc_id text NOT NULL,
58
+ uri text NOT NULL,
59
+ chunk_index integer NOT NULL,
60
+ start_offset integer NOT NULL,
61
+ end_offset integer NOT NULL,
62
+ body text NOT NULL,
63
+ metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
64
+ embedding {embedding} NOT NULL
65
+ );`;
66
+ const EXTENSION = 'CREATE EXTENSION IF NOT EXISTS vector;';
67
+ /** pgvector's operator classes, one per metric the IR models. */
68
+ const OPERATOR_CLASS = {
69
+ cosine: 'vector_cosine_ops',
70
+ dot: 'vector_ip_ops',
71
+ l2: 'vector_l2_ops',
72
+ };
73
+ /** Shared by both runtimes as the order in which a distance is written in a query. */
74
+ const METRIC_ORDER = ['cosine', 'dot', 'l2'];
75
+ function skipReason(store) {
76
+ switch (store.kind) {
77
+ case 'memory':
78
+ return 'in-process, so there is nothing to provision';
79
+ case 'custom':
80
+ return 'the runtime supplies it, so `aid migrate` cannot know its schema';
81
+ default:
82
+ return 'a managed service that owns its own schema';
83
+ }
84
+ }
85
+ /**
86
+ * The dimension to pin, or `undefined` to leave the column dimensionless.
87
+ *
88
+ * Pinning is strictly better when it is possible: the database then rejects a record of
89
+ * the wrong width at insert time, instead of storing two incompatible vectors in one
90
+ * table. It is not possible when two stores disagree, because they share the table --
91
+ * so that case warns instead of silently picking one.
92
+ */
93
+ function dimensionOf(stores, specPath) {
94
+ const declared = [...new Set(stores.map((store) => store.dimensions))].filter((value) => value !== undefined);
95
+ if (declared.length === 0)
96
+ return { value: undefined, warnings: [] };
97
+ if (declared.length === 1)
98
+ return { value: declared[0], warnings: [] };
99
+ return {
100
+ value: undefined,
101
+ warnings: [
102
+ cliWarning({
103
+ code: CLI_DIAGNOSTIC_CODES.migrateDimensionAmbiguous,
104
+ message: `The declared pgvector stores pin different dimensions (${declared.join(', ')}), so the shared \`aid_chunks\` table is left dimensionless.`,
105
+ path: [specPath],
106
+ hint: 'One table cannot hold two widths; declare one dimension, or give the stores separate tables by hand.',
107
+ }),
108
+ ],
109
+ };
110
+ }
111
+ /**
112
+ * One HNSW index per metric a `pgvector`-backed retriever searches with.
113
+ *
114
+ * The runtimes never create an index -- a scan over `aid_chunks` is exact, which is fine
115
+ * for a fixture corpus and quadratic for a real one -- so this is the one part of the file
116
+ * that is a performance decision rather than a correctness one. HNSW is chosen because it
117
+ * is the index pgvector ships that needs no training step; `ivfflat` would need data
118
+ * before it could be built, which is the wrong shape for a first migration.
119
+ */
120
+ function indexesFor(ir) {
121
+ const pgvectorIds = new Set(ir.stores.filter((store) => store.kind === 'pgvector').map((store) => store.id));
122
+ const metrics = new Set();
123
+ for (const retriever of ir.retrievers) {
124
+ if (pgvectorIds.has(retriever.store))
125
+ metrics.add(retriever.index.metric);
126
+ }
127
+ return METRIC_ORDER.filter((metric) => metrics.has(metric)).map((metric) => ({
128
+ name: `aid_chunks_embedding_${metric}_idx`,
129
+ metric,
130
+ }));
131
+ }
132
+ function renderSql(dimension, indexes) {
133
+ const table = AID_CHUNKS_TABLE.replace('{embedding}', dimension === undefined ? 'vector' : `vector(${dimension})`);
134
+ const statements = [EXTENSION, table];
135
+ for (const index of indexes) {
136
+ statements.push(`CREATE INDEX IF NOT EXISTS ${index.name}\n ON aid_chunks USING hnsw (embedding ${OPERATOR_CLASS[index.metric]});`);
137
+ }
138
+ const header = [
139
+ MIGRATION_MARKER,
140
+ '--',
141
+ '-- The schema the declared vector stores need. Apply it once, with DDL rights; the',
142
+ '-- application itself only needs DML. Every statement is idempotent, so applying this',
143
+ '-- file again is a no-op.',
144
+ '--',
145
+ '-- This file creates, and never alters. Changing a vector dimension or a distance',
146
+ '-- metric is a new migration, not an edit to this one: the table already exists, so',
147
+ '-- `IF NOT EXISTS` would skip the statement and report success over the old column.',
148
+ ];
149
+ return `${[...header, '', ...statements].join('\n')}\n`;
150
+ }
151
+ function plan(ir, specPath) {
152
+ const pgvector = ir.stores.filter((store) => store.kind === 'pgvector');
153
+ const skipped = ir.stores
154
+ .filter((store) => store.kind !== 'pgvector')
155
+ .map((store) => ({ id: store.id, kind: store.kind, reason: skipReason(store) }));
156
+ const dimension = dimensionOf(pgvector, specPath);
157
+ const indexes = indexesFor(ir);
158
+ return {
159
+ pgvector,
160
+ skipped,
161
+ dimension: dimension.value,
162
+ indexes,
163
+ sql: pgvector.length === 0 ? undefined : renderSql(dimension.value, indexes),
164
+ warnings: dimension.warnings,
165
+ };
166
+ }
167
+ /** Strip trailing path separators, falling back to the default when nothing is left. */
168
+ function stripTrailingSeparators(directory) {
169
+ let end = directory.length;
170
+ while (end > 0 && (directory[end - 1] === '/' || directory[end - 1] === '\\'))
171
+ end -= 1;
172
+ return end === 0 ? DEFAULT_OUT_DIR : directory.slice(0, end);
173
+ }
174
+ /** Whether `relative`, resolved against `cwd`, lands outside the project. */
175
+ function escapes(cwd, relative) {
176
+ const root = resolve(cwd);
177
+ const target = resolve(root, relative);
178
+ return target !== root && !target.startsWith(root.endsWith(sep) ? root : `${root}${sep}`);
179
+ }
180
+ function describe(plan) {
181
+ const text = [`stores: ${plan.pgvector.length + plan.skipped.length} declared`];
182
+ for (const store of plan.pgvector)
183
+ text.push(` ${store.id} (pgvector)`);
184
+ for (const store of plan.skipped) {
185
+ text.push(` ${store.id} (${store.kind}) -- ${store.reason}`);
186
+ }
187
+ if (plan.sql === undefined) {
188
+ text.push('no pgvector store is declared, so there is no SQL to emit');
189
+ }
190
+ else {
191
+ text.push(`dimension: ${plan.dimension === undefined ? 'not pinned' : `${plan.dimension} (pinned)`}`);
192
+ if (plan.indexes.length > 0) {
193
+ text.push(`indexes: ${plan.indexes.map((index) => `${index.name} (${index.metric})`).join(', ')}`);
194
+ }
195
+ else {
196
+ text.push('indexes: none -- no pgvector-backed retriever declares a distance');
197
+ }
198
+ }
199
+ return text;
200
+ }
201
+ export function migrate(context, options) {
202
+ const command = 'migrate';
203
+ const specPath = options.spec ?? DEFAULT_SPEC_PATH;
204
+ const outDir = stripTrailingSeparators(options.out ?? DEFAULT_OUT_DIR);
205
+ const path = `${outDir}/${FILE_NAME}`;
206
+ const fields = { spec: specPath, path, check: options.check, dryRun: options.dryRun };
207
+ // The sink refuses an escaping path by throwing, which reads as an internal error. A
208
+ // caller who typed an absolute path gets the same refusal, but as an invocation error
209
+ // that names the flag.
210
+ if (escapes(context.cwd, path)) {
211
+ return outcome({
212
+ command,
213
+ exitCode: EXIT_USAGE,
214
+ fields,
215
+ diagnostics: [
216
+ cliError({
217
+ code: CLI_DIAGNOSTIC_CODES.migrateOutEscapes,
218
+ message: `\`--out\` resolves to "${path}", which is outside the project.`,
219
+ hint: 'Give a directory inside the project, such as `migrations`.',
220
+ }),
221
+ ],
222
+ });
223
+ }
224
+ const read = readSpec(context, specPath);
225
+ if (!read.ok) {
226
+ return outcome({ command, exitCode: EXIT_FAILURE, fields, diagnostics: read.diagnostics });
227
+ }
228
+ const lowered = lowerSpec(read.text, specPath);
229
+ if (!lowered.ok) {
230
+ return outcome({ command, exitCode: EXIT_FAILURE, fields, diagnostics: lowered.diagnostics });
231
+ }
232
+ const sink = createNodeSink(context.cwd);
233
+ const planned = plan(lowered.ir, specPath);
234
+ const existing = sink.read(path);
235
+ const owned = existing?.startsWith(MIGRATION_MARKER) === true;
236
+ const diagnostics = [...planned.warnings];
237
+ let action;
238
+ if (planned.sql === undefined) {
239
+ action = owned ? 'removed' : 'none';
240
+ }
241
+ else if (existing === undefined) {
242
+ action = 'created';
243
+ }
244
+ else if (owned) {
245
+ action = existing === planned.sql ? 'unchanged' : 'updated';
246
+ }
247
+ else {
248
+ // Someone else's file. Refusing is the whole safety property of this command: the
249
+ // point of a migrations directory is that its contents are reviewed once and applied
250
+ // in order, so silently replacing an entry would rewrite history a database already
251
+ // recorded.
252
+ diagnostics.push(cliError({
253
+ code: CLI_DIAGNOSTIC_CODES.refusingToOverwrite,
254
+ message: `"${path}" exists and was not written by \`aid migrate\`.`,
255
+ path: [path],
256
+ hint: 'Move it aside, or pass `--out` to write the generated schema somewhere else.',
257
+ }));
258
+ action = 'none';
259
+ }
260
+ const pending = action === 'created' || action === 'updated' || action === 'removed';
261
+ const failed = hasErrors(diagnostics);
262
+ if (pending && !options.check && !options.dryRun) {
263
+ // `remove` and `write` are the sink's, so the path-escape guard and the atomic rename
264
+ // are the ones every generated file already goes through.
265
+ if (planned.sql === undefined)
266
+ sink.remove(path);
267
+ else
268
+ sink.write(path, planned.sql);
269
+ }
270
+ const text = describe(planned);
271
+ text.push(`${path}: ${action}`);
272
+ if (options.check && pending) {
273
+ text.push('the migration does not match the spec; run `aid migrate` and commit the result:');
274
+ text.push(` ${path}`);
275
+ }
276
+ const verb = action === 'unchanged' || action === 'none'
277
+ ? 'migrate: ok'
278
+ : options.check || options.dryRun
279
+ ? `migrate: would be ${action}`
280
+ : `migrate: ${action}`;
281
+ text.push(verb);
282
+ return outcome({
283
+ command,
284
+ exitCode: failed || (options.check && pending) ? EXIT_FAILURE : EXIT_OK,
285
+ diagnostics,
286
+ text: text.join('\n'),
287
+ fields: {
288
+ ...fields,
289
+ action,
290
+ written: pending && !options.check && !options.dryRun,
291
+ dimension: planned.dimension ?? null,
292
+ indexes: planned.indexes,
293
+ stores: [
294
+ ...planned.pgvector.map((store) => ({ id: store.id, kind: store.kind, status: 'emitted' })),
295
+ ...planned.skipped.map((store) => ({
296
+ id: store.id,
297
+ kind: store.kind,
298
+ status: 'skipped',
299
+ reason: store.reason,
300
+ })),
301
+ ],
302
+ },
303
+ });
304
+ }
305
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAIhD,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAWlD,iEAAiE;AACjE,MAAM,CAAC,MAAM,gBAAgB,GAAG,2CAA2C,CAAC;AAE5E,MAAM,eAAe,GAAG,YAAY,CAAC;AACrC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;GAU7B,CAAC;AAEJ,MAAM,SAAS,GAAG,wCAAwC,CAAC;AAE3D,iEAAiE;AACjE,MAAM,cAAc,GAAgC;IAClD,MAAM,EAAE,mBAAmB;IAC3B,GAAG,EAAE,eAAe;IACpB,EAAE,EAAE,eAAe;CACpB,CAAC;AAEF,sFAAsF;AACtF,MAAM,YAAY,GAA2B,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAsBrE,SAAS,UAAU,CAAC,KAAuB;IACzC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,8CAA8C,CAAC;QACxD,KAAK,QAAQ;YACX,OAAO,kEAAkE,CAAC;QAC5E;YACE,OAAO,4CAA4C,CAAC;IACxD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAClB,MAAmC,EACnC,QAAgB;IAEhB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAC3E,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,KAAK,SAAS,CAChD,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACrE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAEvE,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE;YACR,UAAU,CAAC;gBACT,IAAI,EAAE,oBAAoB,CAAC,yBAAyB;gBACpD,OAAO,EAAE,0DAA0D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,8DAA8D;gBACpJ,IAAI,EAAE,CAAC,QAAQ,CAAC;gBAChB,IAAI,EAAE,sGAAsG;aAC7G,CAAC;SACH;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,EAAM;IACxB,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAChF,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IACvC,KAAK,MAAM,SAAS,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;QACtC,IAAI,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC3E,IAAI,EAAE,wBAAwB,MAAM,MAAM;QAC1C,MAAM;KACP,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,SAAS,CAAC,SAA6B,EAAE,OAA+B;IAC/E,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CACpC,aAAa,EACb,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,SAAS,GAAG,CAC5D,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,UAAU,CAAC,IAAI,CACb,8BAA8B,KAAK,CAAC,IAAI,6CAA6C,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CACtH,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG;QACb,gBAAgB;QAChB,IAAI;QACJ,oFAAoF;QACpF,uFAAuF;QACvF,2BAA2B;QAC3B,IAAI;QACJ,mFAAmF;QACnF,qFAAqF;QACrF,qFAAqF;KACtF,CAAC;IAEF,OAAO,GAAG,CAAC,GAAG,MAAM,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1D,CAAC;AAED,SAAS,IAAI,CAAC,EAAM,EAAE,QAAgB;IACpC,MAAM,QAAQ,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM;SACtB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;SAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAE/B,OAAO;QACL,QAAQ;QACR,OAAO;QACP,SAAS,EAAE,SAAS,CAAC,KAAK;QAC1B,OAAO;QACP,GAAG,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC;QAC5E,QAAQ,EAAE,SAAS,CAAC,QAAQ;KAC7B,CAAC;AACJ,CAAC;AAID,wFAAwF;AACxF,SAAS,uBAAuB,CAAC,SAAiB;IAChD,IAAI,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC;IAC3B,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC;QAAE,GAAG,IAAI,CAAC,CAAC;IACxF,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,6EAA6E;AAC7E,SAAS,OAAO,CAAC,GAAW,EAAE,QAAgB;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvC,OAAO,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,QAAQ,CAAC,IAAU;IAC1B,MAAM,IAAI,GAAG,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,WAAW,CAAC,CAAC;IAChF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,aAAa,CAAC,CAAC;IACzE,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,CACP,cAAc,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,WAAW,EAAE,CAC3F,CAAC;QACF,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CACP,YAAY,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAmB,EAAE,OAAuB;IAClE,MAAM,OAAO,GAAG,SAAS,CAAC;IAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,iBAAiB,CAAC;IACnD,MAAM,MAAM,GAAG,uBAAuB,CAAC,OAAO,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,SAAS,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IAEtF,qFAAqF;IACrF,sFAAsF;IACtF,uBAAuB;IACvB,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC;YACb,OAAO;YACP,QAAQ,EAAE,UAAU;YACpB,MAAM;YACN,WAAW,EAAE;gBACX,QAAQ,CAAC;oBACP,IAAI,EAAE,oBAAoB,CAAC,iBAAiB;oBAC5C,OAAO,EAAE,0BAA0B,IAAI,kCAAkC;oBACzE,IAAI,EAAE,4DAA4D;iBACnE,CAAC;aACH;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,QAAQ,EAAE,UAAU,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC9D,MAAM,WAAW,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE1C,IAAI,MAAc,CAAC;IACnB,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IACtC,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC;SAAM,IAAI,KAAK,EAAE,CAAC;QACjB,MAAM,GAAG,QAAQ,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,kFAAkF;QAClF,qFAAqF;QACrF,oFAAoF;QACpF,YAAY;QACZ,WAAW,CAAC,IAAI,CACd,QAAQ,CAAC;YACP,IAAI,EAAE,oBAAoB,CAAC,mBAAmB;YAC9C,OAAO,EAAE,IAAI,IAAI,kDAAkD;YACnE,IAAI,EAAE,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,8EAA8E;SACrF,CAAC,CACH,CAAC;QACF,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,CAAC;IACrF,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IAEtC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACjD,sFAAsF;QACtF,0DAA0D;QAC1D,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;YAC5C,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;IAChC,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAC;QAC7F,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,IAAI,GACR,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,MAAM;QACzC,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM;YAC/B,CAAC,CAAC,qBAAqB,MAAM,EAAE;YAC/B,CAAC,CAAC,YAAY,MAAM,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhB,OAAO,OAAO,CAAC;QACb,OAAO;QACP,QAAQ,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;QACvE,WAAW;QACX,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACrB,MAAM,EAAE;YACN,GAAG,MAAM;YACT,MAAM;YACN,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM;YACrD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YACpC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE;gBACN,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC3F,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACjC,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,MAAM,EAAE,SAAS;oBACjB,MAAM,EAAE,KAAK,CAAC,MAAM;iBACrB,CAAC,CAAC;aACJ;SACF;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `aid trace` — read a traced run back out of the local trace sink.
3
+ *
4
+ * The sink records *what happened*, not *what was said*: spans carry timing, kind, model,
5
+ * token counts and priced cost, but no prompts and no completions. So this command
6
+ * **inspects** a run; it does not replay one. A replay needs the request payloads, and
7
+ * inventing them -- asking the model again -- would answer a different question than "what
8
+ * happened here", while looking like an answer to it. Replay stays unimplemented until the
9
+ * sink records payloads, and the help text says so rather than letting a reader assume.
10
+ *
11
+ * Exit codes:
12
+ *
13
+ * - `2` when the invocation is wrong: no directory, a selector that matches no run or more
14
+ * than one, or `--run` together with `--all`.
15
+ * - `1` only when a trace file exists and could not be read. The tree still prints: what
16
+ * was readable is worth seeing.
17
+ * - `0` otherwise, including a directory with no runs yet -- "nothing ran" is a true
18
+ * answer, and the warning on stderr says why it is empty.
19
+ */
20
+ import type { CliContext } from '../context.js';
21
+ import type { CommandOutcome } from '../output.js';
22
+ export interface TraceOptions {
23
+ /** The directory to read; defaults to `$AID_TRACE_DIR`. */
24
+ readonly dir: string | undefined;
25
+ /** A full trace id, or an unambiguous prefix of one. */
26
+ readonly run: string | undefined;
27
+ /** Print every run's tree instead of the run list. */
28
+ readonly all: boolean;
29
+ }
30
+ export declare function trace(context: CliContext, options: TraceOptions): CommandOutcome;
31
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/commands/trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,sDAAsD;IACtD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;CACvB;AAgJD,wBAAgB,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,cAAc,CA6GhF"}