@deepagents/text2sql 0.38.1 → 1.0.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.
Files changed (59) hide show
  1. package/README.md +166 -72
  2. package/dist/bin/sql.js +699 -0
  3. package/dist/index.d.ts +2 -3
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1989 -1898
  6. package/dist/index.js.map +4 -4
  7. package/dist/lib/adapter-index.d.ts +35 -0
  8. package/dist/lib/adapter-index.d.ts.map +1 -0
  9. package/dist/lib/adapters/adapter.d.ts +1 -0
  10. package/dist/lib/adapters/adapter.d.ts.map +1 -1
  11. package/dist/lib/adapters/bigquery/index.js +24 -13
  12. package/dist/lib/adapters/bigquery/index.js.map +2 -2
  13. package/dist/lib/adapters/groundings/context.d.ts +2 -2
  14. package/dist/lib/adapters/groundings/context.d.ts.map +1 -1
  15. package/dist/lib/adapters/groundings/index.js +20 -9
  16. package/dist/lib/adapters/groundings/index.js.map +2 -2
  17. package/dist/lib/adapters/mysql/index.js +23 -12
  18. package/dist/lib/adapters/mysql/index.js.map +2 -2
  19. package/dist/lib/adapters/postgres/index.js +31 -18
  20. package/dist/lib/adapters/postgres/index.js.map +3 -3
  21. package/dist/lib/adapters/postgres/postgres.d.ts.map +1 -1
  22. package/dist/lib/adapters/spreadsheet/index.js +20 -9
  23. package/dist/lib/adapters/spreadsheet/index.js.map +2 -2
  24. package/dist/lib/adapters/sqlite/index.js +23 -12
  25. package/dist/lib/adapters/sqlite/index.js.map +2 -2
  26. package/dist/lib/adapters/sqlserver/index.js +31 -18
  27. package/dist/lib/adapters/sqlserver/index.js.map +3 -3
  28. package/dist/lib/adapters/sqlserver/sqlserver.d.ts.map +1 -1
  29. package/dist/lib/agents/question.agent.d.ts.map +1 -1
  30. package/dist/lib/agents/sql-transform-plugins.d.ts +3 -3
  31. package/dist/lib/agents/sql-transform-plugins.d.ts.map +1 -1
  32. package/dist/lib/agents/sql.agent.d.ts.map +1 -1
  33. package/dist/lib/instructions.d.ts +1 -1
  34. package/dist/lib/instructions.d.ts.map +1 -1
  35. package/dist/lib/sql-hooks.d.ts +15 -0
  36. package/dist/lib/sql-hooks.d.ts.map +1 -0
  37. package/dist/lib/sql-meta-hook.d.ts +20 -0
  38. package/dist/lib/sql-meta-hook.d.ts.map +1 -0
  39. package/dist/lib/sql-repair.d.ts +2 -0
  40. package/dist/lib/sql-repair.d.ts.map +1 -0
  41. package/dist/lib/sql-transform.d.ts +2 -0
  42. package/dist/lib/sql-transform.d.ts.map +1 -0
  43. package/dist/lib/sql.d.ts +5 -37
  44. package/dist/lib/sql.d.ts.map +1 -1
  45. package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
  46. package/dist/lib/synthesis/extractors/segmented-context-extractor.d.ts.map +1 -1
  47. package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -1
  48. package/dist/lib/synthesis/index.js +59 -2
  49. package/dist/lib/synthesis/index.js.map +4 -4
  50. package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -1
  51. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
  52. package/dist/lib/synthesis/synthesizers/persona-generator.d.ts.map +1 -1
  53. package/package.json +13 -9
  54. package/dist/lib/agents/sql-command.d.ts +0 -11
  55. package/dist/lib/agents/sql-command.d.ts.map +0 -1
  56. package/dist/lib/demo.d.ts +0 -2
  57. package/dist/lib/demo.d.ts.map +0 -1
  58. package/dist/lib/sandbox.d.ts +0 -21
  59. package/dist/lib/sandbox.d.ts.map +0 -1
@@ -0,0 +1,699 @@
1
+ #!/usr/bin/env node
2
+
3
+ // packages/text2sql/src/bin/sql.ts
4
+ import { cac } from "cac";
5
+
6
+ // packages/text2sql/src/bin/command.ts
7
+ var CommandError = class extends Error {
8
+ command;
9
+ exitCode;
10
+ constructor(command, message, exitCode = 1) {
11
+ super(message);
12
+ this.name = "CommandError";
13
+ this.command = command;
14
+ this.exitCode = exitCode;
15
+ }
16
+ toResult() {
17
+ return {
18
+ stdout: "",
19
+ stderr: `sql ${this.command}: ${this.message}
20
+ `,
21
+ exitCode: this.exitCode
22
+ };
23
+ }
24
+ };
25
+ function errorMessage(error) {
26
+ return error instanceof Error ? error.message : String(error);
27
+ }
28
+ var SqlCommand = class {
29
+ options = [];
30
+ helpDisplay;
31
+ fail(message, exitCode = 1) {
32
+ throw new CommandError(this.name, message, exitCode);
33
+ }
34
+ requireAdapter(adapters, db) {
35
+ const available = Object.keys(adapters).join(", ") || "(none configured)";
36
+ if (!db) {
37
+ this.fail(
38
+ `missing database name. Usage: sql ${this.name} ${this.usage}. Available: ${available}`
39
+ );
40
+ }
41
+ const adapter = adapters[db];
42
+ if (!adapter) {
43
+ this.fail(`unknown database "${db}". Available: ${available}`);
44
+ }
45
+ return adapter;
46
+ }
47
+ };
48
+ var SqlQueryCommand = class extends SqlCommand {
49
+ args = "<db> <...sql>";
50
+ async execute(ctx, args, options) {
51
+ const [db, sqlParts] = args;
52
+ const adapter = this.requireAdapter(ctx.adapters, db);
53
+ const sql = (sqlParts ?? []).join(" ").trim();
54
+ if (!sql) this.fail("no query provided");
55
+ const formatted = await this.formatAndValidate(adapter, sql);
56
+ return this.afterValidation(ctx, adapter, formatted, options);
57
+ }
58
+ async formatAndValidate(adapter, sql) {
59
+ let formatted;
60
+ try {
61
+ formatted = adapter.format(sql);
62
+ } catch (error) {
63
+ this.fail(errorMessage(error));
64
+ }
65
+ try {
66
+ const syntaxError = await adapter.validate(formatted);
67
+ if (syntaxError) this.fail(syntaxError);
68
+ } catch (error) {
69
+ this.fail(errorMessage(error));
70
+ }
71
+ return formatted;
72
+ }
73
+ };
74
+
75
+ // packages/text2sql/src/bin/commands/index.ts
76
+ import { appendFileSync } from "node:fs";
77
+ import { mkdir, writeFile as writeFile2 } from "node:fs/promises";
78
+ import * as path2 from "node:path";
79
+ import { v7 } from "uuid";
80
+
81
+ // packages/text2sql/src/lib/adapter-index.ts
82
+ import { fragment } from "@deepagents/context";
83
+
84
+ // packages/text2sql/src/lib/adapter-name.ts
85
+ var ADAPTER_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
86
+ function isValidAdapterName(name) {
87
+ return name != null && ADAPTER_NAME_PATTERN.test(name);
88
+ }
89
+ function validateAdapterNames(names) {
90
+ for (const name of names) {
91
+ if (!isValidAdapterName(name)) {
92
+ throw new Error(
93
+ `Invalid adapter name "${name}": must match ${ADAPTER_NAME_PATTERN}`
94
+ );
95
+ }
96
+ }
97
+ }
98
+
99
+ // packages/text2sql/src/lib/adapters/adapter.ts
100
+ import { format as formatSql } from "sql-formatter";
101
+
102
+ // packages/text2sql/src/lib/agents/exceptions.ts
103
+ var sqlValidationMarker = Symbol("SQLValidationError");
104
+ var unanswerableSqlMarker = Symbol("UnanswerableSQLError");
105
+ var sqlScopeMarker = Symbol("SQLScopeError");
106
+ var sqlReadOnlyMarker = Symbol("SQLReadOnlyError");
107
+ var SQLValidationError = class _SQLValidationError extends Error {
108
+ [sqlValidationMarker];
109
+ constructor(message) {
110
+ super(message);
111
+ this.name = "SQLValidationError";
112
+ this[sqlValidationMarker] = true;
113
+ }
114
+ static isInstance(error) {
115
+ return error instanceof _SQLValidationError && error[sqlValidationMarker] === true;
116
+ }
117
+ };
118
+ var UnanswerableSQLError = class _UnanswerableSQLError extends Error {
119
+ [unanswerableSqlMarker];
120
+ constructor(message) {
121
+ super(message);
122
+ this.name = "UnanswerableSQLError";
123
+ this[unanswerableSqlMarker] = true;
124
+ }
125
+ static isInstance(error) {
126
+ return error instanceof _UnanswerableSQLError && error[unanswerableSqlMarker] === true;
127
+ }
128
+ };
129
+ var SQLScopeError = class _SQLScopeError extends Error {
130
+ [sqlScopeMarker];
131
+ payload;
132
+ errorType;
133
+ constructor(payload) {
134
+ super(JSON.stringify(payload));
135
+ this.name = "SQLScopeError";
136
+ this.payload = payload;
137
+ this.errorType = payload.error_type;
138
+ this[sqlScopeMarker] = true;
139
+ }
140
+ static isInstance(error) {
141
+ return error instanceof _SQLScopeError && error[sqlScopeMarker] === true;
142
+ }
143
+ };
144
+ var SQLReadOnlyError = class _SQLReadOnlyError extends Error {
145
+ [sqlReadOnlyMarker];
146
+ constructor(message) {
147
+ super(message);
148
+ this.name = "SQLReadOnlyError";
149
+ this[sqlReadOnlyMarker] = true;
150
+ }
151
+ static isInstance(error) {
152
+ return error instanceof _SQLReadOnlyError && error[sqlReadOnlyMarker] === true;
153
+ }
154
+ };
155
+
156
+ // packages/text2sql/src/lib/adapters/groundings/context.ts
157
+ var noopProgress = () => {
158
+ };
159
+ function timestampProgress(onProgress) {
160
+ if (!onProgress) return noopProgress;
161
+ return (progress) => {
162
+ onProgress({
163
+ ...progress,
164
+ timestampMs: progress.timestampMs ?? Date.now()
165
+ });
166
+ };
167
+ }
168
+ function createGroundingContext(options = {}) {
169
+ return {
170
+ tables: [],
171
+ views: [],
172
+ relationships: [],
173
+ info: void 0,
174
+ cache: /* @__PURE__ */ new Map(),
175
+ onProgress: timestampProgress(options.onProgress)
176
+ };
177
+ }
178
+
179
+ // packages/text2sql/src/lib/adapters/runtime-scope.ts
180
+ import nodeSqlParser from "node-sql-parser";
181
+ var { Parser } = nodeSqlParser;
182
+ var parser = new Parser();
183
+
184
+ // packages/text2sql/src/lib/file-cache.ts
185
+ import { createHash } from "node:crypto";
186
+ import { existsSync } from "node:fs";
187
+ import { readFile, writeFile } from "node:fs/promises";
188
+ import { tmpdir } from "node:os";
189
+ import path from "node:path";
190
+ var FileCache = class {
191
+ path;
192
+ constructor(watermark, extension = ".txt") {
193
+ const hash = createHash("md5").update(watermark).digest("hex");
194
+ this.path = path.join(tmpdir(), `text2sql-${hash}${extension}`);
195
+ }
196
+ async get() {
197
+ if (existsSync(this.path)) {
198
+ return readFile(this.path, "utf-8");
199
+ }
200
+ return null;
201
+ }
202
+ set(content) {
203
+ return writeFile(this.path, content, "utf-8");
204
+ }
205
+ };
206
+ var JsonCache = class extends FileCache {
207
+ constructor(watermark) {
208
+ super(watermark, ".json");
209
+ }
210
+ async read() {
211
+ const content = await this.get();
212
+ if (content) {
213
+ return JSON.parse(content);
214
+ }
215
+ return null;
216
+ }
217
+ write(data) {
218
+ return this.set(JSON.stringify(data));
219
+ }
220
+ };
221
+
222
+ // packages/text2sql/src/lib/adapter-index.ts
223
+ var noopProgressHandler = () => {
224
+ };
225
+ function timestampProgressHandler(onProgress) {
226
+ if (!onProgress) return noopProgressHandler;
227
+ return (event) => {
228
+ onProgress({
229
+ ...event,
230
+ timestampMs: event.timestampMs ?? Date.now()
231
+ });
232
+ };
233
+ }
234
+ var AdapterIndexer = class {
235
+ #adapters;
236
+ #version;
237
+ #cacheKey;
238
+ constructor(options) {
239
+ const adapterNames = Object.keys(options.adapters);
240
+ if (adapterNames.length === 0) {
241
+ throw new Error("AdapterIndexer requires at least one adapter");
242
+ }
243
+ validateAdapterNames(adapterNames);
244
+ this.#adapters = options.adapters;
245
+ this.#version = options.version;
246
+ this.#cacheKey = options.cacheKey;
247
+ }
248
+ async index(options = {}) {
249
+ const progress = timestampProgressHandler(options.onProgress);
250
+ const entries = this.#resolveIndexEntries(options.adapterNames);
251
+ progress({
252
+ type: "index:start",
253
+ message: `Indexing ${entries.length} adapter${entries.length === 1 ? "" : "s"}...`,
254
+ current: 0,
255
+ total: entries.length
256
+ });
257
+ const settled = await Promise.allSettled(
258
+ entries.map(async ([name, adapter]) => {
259
+ const schema = await this.#indexAdapter(name, adapter, progress);
260
+ return fragment(name, ...schema);
261
+ })
262
+ );
263
+ const failed = settled.find((result) => result.status === "rejected");
264
+ if (failed) {
265
+ progress({
266
+ type: "index:error",
267
+ message: failed.reason instanceof Error ? failed.reason.message : String(failed.reason)
268
+ });
269
+ throw failed.reason;
270
+ }
271
+ const wrapped = settled.map((result) => {
272
+ if (result.status === "rejected") {
273
+ throw result.reason;
274
+ }
275
+ return result.value;
276
+ });
277
+ progress({
278
+ type: "index:end",
279
+ message: "Finished indexing adapters.",
280
+ current: entries.length,
281
+ total: entries.length
282
+ });
283
+ return wrapped;
284
+ }
285
+ async indexAdapter(name, options = {}) {
286
+ const adapter = this.#adapters[name];
287
+ if (!adapter) {
288
+ const available = Object.keys(this.#adapters).join(", ");
289
+ throw new Error(`unknown adapter "${name}". Available: ${available}`);
290
+ }
291
+ return this.#indexAdapter(
292
+ name,
293
+ adapter,
294
+ timestampProgressHandler(options.onProgress)
295
+ );
296
+ }
297
+ async #indexAdapter(name, adapter, progress) {
298
+ progress({
299
+ type: "adapter:start",
300
+ adapter: name,
301
+ message: `Indexing adapter "${name}"...`
302
+ });
303
+ const cacheKey = this.#adapterCacheKey(name);
304
+ const cache = cacheKey ? new JsonCache(cacheKey) : void 0;
305
+ try {
306
+ const cached = await cache?.read();
307
+ if (cached) {
308
+ progress({
309
+ type: "adapter:cache-hit",
310
+ adapter: name,
311
+ message: `Using cached index for adapter "${name}".`,
312
+ cached: true
313
+ });
314
+ progress({
315
+ type: "adapter:end",
316
+ adapter: name,
317
+ message: `Finished indexing adapter "${name}".`,
318
+ cached: true
319
+ });
320
+ return cached;
321
+ }
322
+ if (cache) {
323
+ progress({
324
+ type: "adapter:cache-miss",
325
+ adapter: name,
326
+ message: `No cached index for adapter "${name}".`,
327
+ cached: false
328
+ });
329
+ }
330
+ const ctx = createGroundingContext({
331
+ onProgress: (event) => progress(adapterProgressEvent(name, event))
332
+ });
333
+ const fragments = await adapter.introspect(ctx);
334
+ await cache?.write(fragments);
335
+ progress({
336
+ type: "adapter:end",
337
+ adapter: name,
338
+ message: `Finished indexing adapter "${name}".`,
339
+ cached: false
340
+ });
341
+ return fragments;
342
+ } catch (error) {
343
+ const reason = errorMessage2(error);
344
+ progress({
345
+ type: "adapter:error",
346
+ adapter: name,
347
+ message: `Failed indexing adapter "${name}": ${reason}`
348
+ });
349
+ throw new Error(`introspecting adapter "${name}": ${reason}`, {
350
+ cause: error
351
+ });
352
+ }
353
+ }
354
+ #resolveIndexEntries(adapterNames) {
355
+ const availableNames = Object.keys(this.#adapters);
356
+ const requestedNames = adapterNames && adapterNames.length > 0 ? [...new Set(adapterNames)] : availableNames;
357
+ const available = availableNames.join(", ");
358
+ return requestedNames.map((name) => {
359
+ const adapter = this.#adapters[name];
360
+ if (!adapter) {
361
+ throw new Error(`unknown adapter "${name}". Available: ${available}`);
362
+ }
363
+ return [name, adapter];
364
+ });
365
+ }
366
+ #adapterCacheKey(name) {
367
+ const configured = this.#cacheKey?.(name);
368
+ if (configured !== void 0) {
369
+ return configured;
370
+ }
371
+ if (this.#version) {
372
+ return `introspection-${this.#version}-${name}`;
373
+ }
374
+ return void 0;
375
+ }
376
+ };
377
+ function adapterProgressEvent(adapter, progress) {
378
+ return {
379
+ type: progress.type,
380
+ adapter,
381
+ phase: progress.phase,
382
+ table: progress.table,
383
+ message: progress.message,
384
+ current: progress.current,
385
+ total: progress.total,
386
+ cached: false,
387
+ timestampMs: progress.timestampMs
388
+ };
389
+ }
390
+ function errorMessage2(error) {
391
+ return error instanceof Error ? error.message : String(error);
392
+ }
393
+
394
+ // packages/text2sql/src/bin/commands/index.ts
395
+ var IndexCommand = class extends SqlCommand {
396
+ name = "index";
397
+ description = "Index adapter schemas and write context artifacts";
398
+ args = "[...adapters]";
399
+ usage = "[--all] [adapter ...]";
400
+ helpDisplay = "[--all] [adapter ...]";
401
+ options = [
402
+ { flag: "--all", description: "Index all adapters (default)" }
403
+ ];
404
+ async execute(ctx, args, options) {
405
+ const adapterNames = args[0] ?? [];
406
+ const requested = options.all ? [] : adapterNames;
407
+ const names = this.resolveNames(ctx.adapters, requested);
408
+ const outputDir = path2.resolve(ctx.cwd, "./sql");
409
+ const id = v7();
410
+ const fragmentsPath = path2.join(outputDir, `index-${id}.json`);
411
+ const eventsPath = path2.join(outputDir, `index-${id}.events.ndjson`);
412
+ try {
413
+ await mkdir(outputDir, { recursive: true });
414
+ await writeFile2(eventsPath, "");
415
+ const indexer = new AdapterIndexer({ adapters: ctx.adapters });
416
+ const fragments = await indexer.index({
417
+ adapterNames: names,
418
+ onProgress: (event) => appendProgressEvent(eventsPath, event)
419
+ });
420
+ await writeFile2(fragmentsPath, JSON.stringify(fragments, null, 2));
421
+ const manifest = {
422
+ fragmentsPath,
423
+ eventsPath,
424
+ adapters: names,
425
+ fragments: countSchemaFragments(fragments)
426
+ };
427
+ return {
428
+ stdout: JSON.stringify(manifest, null, 2) + "\n",
429
+ stderr: "",
430
+ exitCode: 0
431
+ };
432
+ } catch (error) {
433
+ this.fail(errorMessage(error));
434
+ }
435
+ }
436
+ resolveNames(adapters, requested) {
437
+ const availableNames = Object.keys(adapters);
438
+ const available = availableNames.join(", ") || "(none configured)";
439
+ const names = requested.length === 0 ? availableNames : dedupe(requested);
440
+ for (const name of names) {
441
+ if (!adapters[name]) {
442
+ this.fail(`unknown adapter "${name}". Available: ${available}`);
443
+ }
444
+ }
445
+ return names;
446
+ }
447
+ };
448
+ function appendProgressEvent(eventsPath, event) {
449
+ appendFileSync(
450
+ eventsPath,
451
+ JSON.stringify({
452
+ ...event,
453
+ timestampMs: event.timestampMs ?? Date.now()
454
+ }) + "\n"
455
+ );
456
+ }
457
+ function countSchemaFragments(fragments) {
458
+ return fragments.reduce((count, adapterFragment) => {
459
+ if (Array.isArray(adapterFragment.data)) {
460
+ return count + adapterFragment.data.length;
461
+ }
462
+ return count + 1;
463
+ }, 0);
464
+ }
465
+ function dedupe(values) {
466
+ return [...new Set(values)];
467
+ }
468
+
469
+ // packages/text2sql/src/bin/commands/run.ts
470
+ import { mkdir as mkdir2, writeFile as writeFile3 } from "node:fs/promises";
471
+ import * as path3 from "node:path";
472
+ import { v7 as v72 } from "uuid";
473
+ var RunCommand = class extends SqlQueryCommand {
474
+ name = "run";
475
+ description = "Execute query against <db> and store results";
476
+ usage = '<db> "SELECT ..." [--out-dir <path>]';
477
+ helpDisplay = '<db> "SELECT ..."';
478
+ options = [
479
+ {
480
+ flag: "--out-dir <path>",
481
+ description: "Directory for `sql run` result files (default: $TEXT2SQL_OUT_DIR or ./sql)"
482
+ }
483
+ ];
484
+ async afterValidation(ctx, adapter, sql, options) {
485
+ const outputDir = this.resolveOutputDir(ctx, options);
486
+ let rows;
487
+ try {
488
+ rows = await adapter.execute(sql);
489
+ } catch (error) {
490
+ this.fail(errorMessage(error));
491
+ }
492
+ if (!Array.isArray(rows)) {
493
+ this.fail("adapter.execute must return an array of rows");
494
+ }
495
+ const outPath = path3.join(outputDir, `${v72()}.json`);
496
+ try {
497
+ await mkdir2(outputDir, { recursive: true });
498
+ await writeFile3(outPath, JSON.stringify(rows, null, 2));
499
+ } catch (error) {
500
+ this.fail(errorMessage(error));
501
+ }
502
+ const columns = rows.length > 0 ? Object.keys(rows[0]) : [];
503
+ return {
504
+ stdout: [
505
+ `results stored in ${outPath}`,
506
+ `columns: ${columns.join(", ") || "(none)"}`,
507
+ `rows: ${rows.length}`
508
+ ].join("\n") + "\n",
509
+ stderr: "",
510
+ exitCode: 0
511
+ };
512
+ }
513
+ resolveOutputDir(ctx, options) {
514
+ const explicit = typeof options.outDir === "string" ? options.outDir : void 0;
515
+ return path3.resolve(
516
+ ctx.cwd,
517
+ explicit ?? ctx.env.TEXT2SQL_OUT_DIR ?? "./sql"
518
+ );
519
+ }
520
+ };
521
+
522
+ // packages/text2sql/src/bin/commands/validate.ts
523
+ var ValidateCommand = class extends SqlQueryCommand {
524
+ name = "validate";
525
+ description = "Validate query syntax against <db>";
526
+ usage = '<db> "SELECT ..."';
527
+ helpDisplay = '<db> "SELECT ..."';
528
+ async afterValidation() {
529
+ return { stdout: "valid\n", stderr: "", exitCode: 0 };
530
+ }
531
+ };
532
+
533
+ // packages/text2sql/src/bin/commands/registry.ts
534
+ var commands = [
535
+ new RunCommand(),
536
+ new ValidateCommand(),
537
+ new IndexCommand()
538
+ ];
539
+
540
+ // packages/text2sql/src/bin/load-adapters.ts
541
+ import { resolve as resolve3 } from "node:path";
542
+ import { pathToFileURL } from "node:url";
543
+ async function loadAdapters() {
544
+ const target = process.env.TEXT2SQL_ADAPTERS;
545
+ if (!target) {
546
+ throw new Error(
547
+ "TEXT2SQL_ADAPTERS env var is not set. Point it at a module whose default export is Record<string, Adapter>."
548
+ );
549
+ }
550
+ const specifier = target.startsWith(".") || target.startsWith("/") ? pathToFileURL(resolve3(target)).href : target;
551
+ let mod;
552
+ try {
553
+ mod = await import(specifier);
554
+ } catch (cause) {
555
+ throw new Error(
556
+ `TEXT2SQL_ADAPTERS=${target}: failed to import module - ${errorMessage(cause)}`
557
+ );
558
+ }
559
+ const exported = mod.default;
560
+ if (!exported || typeof exported !== "object" || Array.isArray(exported)) {
561
+ throw new Error(
562
+ `TEXT2SQL_ADAPTERS=${target}: default export must be a Record<string, Adapter> (got ${describe(exported)}).`
563
+ );
564
+ }
565
+ const entries = Object.entries(exported);
566
+ if (entries.length === 0) {
567
+ throw new Error(
568
+ `TEXT2SQL_ADAPTERS=${target}: default export is an empty object - declare at least one adapter.`
569
+ );
570
+ }
571
+ for (const [name, value] of entries) {
572
+ if (!isAdapterShape(value)) {
573
+ throw new Error(
574
+ `TEXT2SQL_ADAPTERS=${target}: adapter "${name}" is missing one of the required methods (format, validate, execute).`
575
+ );
576
+ }
577
+ }
578
+ try {
579
+ validateAdapterNames(entries.map(([name]) => name));
580
+ } catch (cause) {
581
+ throw new Error(`TEXT2SQL_ADAPTERS=${target}: ${errorMessage(cause)}`);
582
+ }
583
+ return exported;
584
+ }
585
+ function isAdapterShape(value) {
586
+ if (!value || typeof value !== "object") return false;
587
+ const v = value;
588
+ return typeof v.format === "function" && typeof v.validate === "function" && typeof v.execute === "function";
589
+ }
590
+ function describe(value) {
591
+ if (value === null) return "null";
592
+ if (Array.isArray(value)) return "array";
593
+ return typeof value;
594
+ }
595
+
596
+ // packages/text2sql/src/bin/sql.ts
597
+ var cli = cac("sql");
598
+ cli.usage("<run|validate|index> ...").help(
599
+ (sections) => sections.map(
600
+ (section) => section.title === "Commands" ? { ...section, body: rewriteCommandsHelp(section.body) } : section
601
+ )
602
+ );
603
+ for (const command of commands) {
604
+ registerCommand(cli, command);
605
+ }
606
+ process.exit(await runCli());
607
+ async function runCli() {
608
+ try {
609
+ cli.parse(process.argv, { run: false });
610
+ if (cli.options.help) return 0;
611
+ if (!cli.matchedCommand) {
612
+ try {
613
+ cli.globalCommand.checkUnknownOptions();
614
+ cli.globalCommand.checkOptionValue();
615
+ } catch (error) {
616
+ return writeCliError(error);
617
+ }
618
+ const [subcommand] = cli.args;
619
+ const label = subcommand ? `unknown subcommand "${String(subcommand)}"` : "missing subcommand";
620
+ process.stderr.write(`sql: ${label}
621
+ `);
622
+ cli.outputHelp();
623
+ return 2;
624
+ }
625
+ const result = await cli.runMatchedCommand();
626
+ return typeof result === "number" ? result : 0;
627
+ } catch (error) {
628
+ return writeCliError(error);
629
+ }
630
+ }
631
+ function registerCommand(cli2, command) {
632
+ const cliCommand = cli2.command(`${command.name} ${command.args}`, command.description).usage(command.usage);
633
+ for (const option of command.options) {
634
+ cliCommand.option(option.flag, option.description);
635
+ }
636
+ cliCommand.action(async (...callArgs) => {
637
+ const options = callArgs[callArgs.length - 1] ?? {};
638
+ const positional = callArgs.slice(0, -1);
639
+ return runCommand(command, positional, options);
640
+ });
641
+ }
642
+ async function runCommand(command, positional, options) {
643
+ let ctx;
644
+ try {
645
+ ctx = {
646
+ adapters: await loadAdapters(),
647
+ cwd: process.cwd(),
648
+ env: process.env
649
+ };
650
+ } catch (error) {
651
+ process.stderr.write(`${errorMessage(error)}
652
+ `);
653
+ return 2;
654
+ }
655
+ try {
656
+ const result = await command.execute(ctx, positional, options);
657
+ writeCommandResult(result);
658
+ return result.exitCode;
659
+ } catch (error) {
660
+ if (error instanceof CommandError) {
661
+ writeCommandResult(error.toResult());
662
+ return error.exitCode;
663
+ }
664
+ throw error;
665
+ }
666
+ }
667
+ function rewriteCommandsHelp(body) {
668
+ return commands.reduce((current, command) => {
669
+ if (!command.helpDisplay) return current;
670
+ return current.replace(
671
+ `${command.name} ${command.args}`,
672
+ `${command.name} ${command.helpDisplay}`
673
+ );
674
+ }, body);
675
+ }
676
+ function writeCommandResult(result) {
677
+ if (result.stdout) process.stdout.write(result.stdout);
678
+ if (result.stderr) {
679
+ const out = result.stderr.endsWith("\n") ? result.stderr : result.stderr + "\n";
680
+ process.stderr.write(out);
681
+ }
682
+ }
683
+ function writeCliError(error) {
684
+ if (error instanceof Error && error.name === "CACError") {
685
+ process.stderr.write(`sql: ${error.message}
686
+ `);
687
+ cli.outputHelp();
688
+ return 2;
689
+ }
690
+ if (error instanceof CommandError) {
691
+ writeCommandResult(error.toResult());
692
+ return error.exitCode;
693
+ }
694
+ process.stderr.write(
695
+ `sql: unexpected error: ${error instanceof Error ? error.stack ?? error.message : String(error)}
696
+ `
697
+ );
698
+ return 1;
699
+ }
package/dist/index.d.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  export { isValidAdapterName, validateAdapterNames, } from './lib/adapter-name.ts';
2
2
  export * from './lib/adapters/adapter.ts';
3
3
  export * from './lib/agents/exceptions.ts';
4
- export * from './lib/agents/sql-command.ts';
5
- export * from './lib/agents/sql-transform-plugins.ts';
6
4
  export * from './lib/agents/sql.agent.ts';
7
5
  export * from './lib/agents/suggestions.agents.ts';
6
+ export * from './lib/adapter-index.ts';
8
7
  export * from './lib/checkpoint.ts';
9
8
  export * from './lib/file-cache.ts';
10
9
  export * from './lib/fragments/schema.ts';
11
10
  export * from './lib/fs/index.ts';
12
11
  export * from './lib/instructions.ts';
13
- export * from './lib/sandbox.ts';
12
+ export * from './lib/sql-hooks.ts';
14
13
  export * from './lib/sql.ts';
15
14
  //# sourceMappingURL=index.d.ts.map