@deepagents/text2sql 0.3.0 → 0.6.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 (149) hide show
  1. package/README.md +167 -0
  2. package/dist/finetune/convert-to-gguf.d.ts +18 -0
  3. package/dist/finetune/convert-to-gguf.d.ts.map +1 -0
  4. package/dist/finetune/run-finetune.d.ts +23 -0
  5. package/dist/finetune/run-finetune.d.ts.map +1 -0
  6. package/dist/finetune/run-mlx.d.ts +22 -0
  7. package/dist/finetune/run-mlx.d.ts.map +1 -0
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1795 -284
  11. package/dist/index.js.map +4 -4
  12. package/dist/lib/adapters/adapter.d.ts +8 -3
  13. package/dist/lib/adapters/adapter.d.ts.map +1 -1
  14. package/dist/lib/adapters/{grounding.ticket.d.ts → groundings/abstract.grounding.d.ts} +2 -2
  15. package/dist/lib/adapters/groundings/abstract.grounding.d.ts.map +1 -0
  16. package/dist/lib/adapters/groundings/column-stats.grounding.d.ts +1 -1
  17. package/dist/lib/adapters/groundings/column-stats.grounding.d.ts.map +1 -1
  18. package/dist/lib/adapters/groundings/column-values.grounding.d.ts +76 -0
  19. package/dist/lib/adapters/groundings/column-values.grounding.d.ts.map +1 -0
  20. package/dist/lib/adapters/groundings/constraint.grounding.d.ts +1 -1
  21. package/dist/lib/adapters/groundings/constraint.grounding.d.ts.map +1 -1
  22. package/dist/lib/adapters/groundings/context.d.ts +1 -1
  23. package/dist/lib/adapters/groundings/context.d.ts.map +1 -1
  24. package/dist/lib/adapters/groundings/{grounding.d.ts → index.d.ts} +8 -5
  25. package/dist/lib/adapters/groundings/index.d.ts.map +1 -0
  26. package/dist/lib/adapters/groundings/{grounding.js → index.js} +411 -206
  27. package/dist/lib/adapters/groundings/index.js.map +7 -0
  28. package/dist/lib/adapters/groundings/indexes.grounding.d.ts +1 -1
  29. package/dist/lib/adapters/groundings/indexes.grounding.d.ts.map +1 -1
  30. package/dist/lib/adapters/groundings/info.grounding.d.ts +1 -1
  31. package/dist/lib/adapters/groundings/info.grounding.d.ts.map +1 -1
  32. package/dist/lib/adapters/groundings/report.grounding.d.ts +1 -1
  33. package/dist/lib/adapters/groundings/report.grounding.d.ts.map +1 -1
  34. package/dist/lib/adapters/groundings/row-count.grounding.d.ts +1 -1
  35. package/dist/lib/adapters/groundings/row-count.grounding.d.ts.map +1 -1
  36. package/dist/lib/adapters/groundings/table.grounding.d.ts +1 -1
  37. package/dist/lib/adapters/groundings/table.grounding.d.ts.map +1 -1
  38. package/dist/lib/adapters/groundings/view.grounding.d.ts +1 -1
  39. package/dist/lib/adapters/groundings/view.grounding.d.ts.map +1 -1
  40. package/dist/lib/adapters/postgres/column-stats.postgres.grounding.d.ts.map +1 -1
  41. package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts +17 -0
  42. package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts.map +1 -0
  43. package/dist/lib/adapters/postgres/index.d.ts +4 -4
  44. package/dist/lib/adapters/postgres/index.d.ts.map +1 -1
  45. package/dist/lib/adapters/postgres/index.js +239 -33
  46. package/dist/lib/adapters/postgres/index.js.map +4 -4
  47. package/dist/lib/adapters/postgres/postgres.d.ts +1 -0
  48. package/dist/lib/adapters/postgres/postgres.d.ts.map +1 -1
  49. package/dist/lib/adapters/sqlite/column-values.sqlite.grounding.d.ts +17 -0
  50. package/dist/lib/adapters/sqlite/column-values.sqlite.grounding.d.ts.map +1 -0
  51. package/dist/lib/adapters/sqlite/constraint.sqlite.grounding.d.ts.map +1 -1
  52. package/dist/lib/adapters/sqlite/index.d.ts +4 -4
  53. package/dist/lib/adapters/sqlite/index.d.ts.map +1 -1
  54. package/dist/lib/adapters/sqlite/index.js +218 -46
  55. package/dist/lib/adapters/sqlite/index.js.map +4 -4
  56. package/dist/lib/adapters/sqlite/sqlite.d.ts +1 -0
  57. package/dist/lib/adapters/sqlite/sqlite.d.ts.map +1 -1
  58. package/dist/lib/adapters/sqlserver/column-values.sqlserver.grounding.d.ts +17 -0
  59. package/dist/lib/adapters/sqlserver/column-values.sqlserver.grounding.d.ts.map +1 -0
  60. package/dist/lib/adapters/sqlserver/index.d.ts +4 -4
  61. package/dist/lib/adapters/sqlserver/index.d.ts.map +1 -1
  62. package/dist/lib/adapters/sqlserver/index.js +185 -32
  63. package/dist/lib/adapters/sqlserver/index.js.map +4 -4
  64. package/dist/lib/adapters/sqlserver/sqlserver.d.ts +1 -0
  65. package/dist/lib/adapters/sqlserver/sqlserver.d.ts.map +1 -1
  66. package/dist/lib/agents/chat1.agent.d.ts +50 -0
  67. package/dist/lib/agents/chat1.agent.d.ts.map +1 -0
  68. package/dist/lib/agents/chat2.agent.d.ts +68 -0
  69. package/dist/lib/agents/chat2.agent.d.ts.map +1 -0
  70. package/dist/lib/agents/chat3.agent.d.ts +80 -0
  71. package/dist/lib/agents/chat3.agent.d.ts.map +1 -0
  72. package/dist/lib/agents/chat4.agent.d.ts +88 -0
  73. package/dist/lib/agents/chat4.agent.d.ts.map +1 -0
  74. package/dist/lib/agents/question.agent.d.ts +23 -0
  75. package/dist/lib/agents/question.agent.d.ts.map +1 -0
  76. package/dist/lib/agents/sql.agent.d.ts +62 -0
  77. package/dist/lib/agents/sql.agent.d.ts.map +1 -0
  78. package/dist/lib/agents/teachables.agent.d.ts +8 -9
  79. package/dist/lib/agents/teachables.agent.d.ts.map +1 -1
  80. package/dist/lib/agents/text2sql.agent.d.ts +0 -1
  81. package/dist/lib/agents/text2sql.agent.d.ts.map +1 -1
  82. package/dist/lib/checkpoint.d.ts +99 -0
  83. package/dist/lib/checkpoint.d.ts.map +1 -0
  84. package/dist/lib/instructions.js +50 -21
  85. package/dist/lib/instructions.js.map +2 -2
  86. package/dist/lib/sql.d.ts +83 -3
  87. package/dist/lib/sql.d.ts.map +1 -1
  88. package/dist/lib/syntheize.d.ts +2 -0
  89. package/dist/lib/syntheize.d.ts.map +1 -0
  90. package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts +26 -0
  91. package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts.map +1 -0
  92. package/dist/lib/synthesis/decorators/filtered-producer.d.ts +26 -0
  93. package/dist/lib/synthesis/decorators/filtered-producer.d.ts.map +1 -0
  94. package/dist/lib/synthesis/decorators/index.d.ts +7 -0
  95. package/dist/lib/synthesis/decorators/index.d.ts.map +1 -0
  96. package/dist/lib/synthesis/decorators/validated-producer.d.ts +33 -0
  97. package/dist/lib/synthesis/decorators/validated-producer.d.ts.map +1 -0
  98. package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts +76 -0
  99. package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -0
  100. package/dist/lib/synthesis/extractors/full-context-extractor.d.ts +25 -0
  101. package/dist/lib/synthesis/extractors/full-context-extractor.d.ts.map +1 -0
  102. package/dist/lib/synthesis/extractors/index.d.ts +8 -0
  103. package/dist/lib/synthesis/extractors/index.d.ts.map +1 -0
  104. package/dist/lib/synthesis/extractors/last-query-extractor.d.ts +30 -0
  105. package/dist/lib/synthesis/extractors/last-query-extractor.d.ts.map +1 -0
  106. package/dist/lib/synthesis/extractors/message-extractor.d.ts +27 -0
  107. package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -0
  108. package/dist/lib/synthesis/extractors/segmented-context-extractor.d.ts +48 -0
  109. package/dist/lib/synthesis/extractors/segmented-context-extractor.d.ts.map +1 -0
  110. package/dist/lib/synthesis/extractors/sql-extractor.d.ts +27 -0
  111. package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -0
  112. package/dist/lib/synthesis/extractors/windowed-context-extractor.d.ts +30 -0
  113. package/dist/lib/synthesis/extractors/windowed-context-extractor.d.ts.map +1 -0
  114. package/dist/lib/synthesis/index.d.ts +6 -0
  115. package/dist/lib/synthesis/index.d.ts.map +1 -0
  116. package/dist/lib/synthesis/index.js +2069 -0
  117. package/dist/lib/synthesis/index.js.map +7 -0
  118. package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts +34 -0
  119. package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -0
  120. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts +41 -0
  121. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -0
  122. package/dist/lib/synthesis/synthesizers/index.d.ts +7 -0
  123. package/dist/lib/synthesis/synthesizers/index.d.ts.map +1 -0
  124. package/dist/lib/synthesis/synthesizers/persona-generator.d.ts +34 -0
  125. package/dist/lib/synthesis/synthesizers/persona-generator.d.ts.map +1 -0
  126. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +39 -0
  127. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -0
  128. package/dist/lib/synthesis/synthesizers/styles.d.ts +8 -0
  129. package/dist/lib/synthesis/synthesizers/styles.d.ts.map +1 -0
  130. package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts +32 -0
  131. package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts.map +1 -0
  132. package/dist/lib/synthesis/types.d.ts +26 -0
  133. package/dist/lib/synthesis/types.d.ts.map +1 -0
  134. package/dist/lib/teach/teachables.d.ts +18 -3
  135. package/dist/lib/teach/teachables.d.ts.map +1 -1
  136. package/dist/lib/teach/teachings.d.ts +9 -2
  137. package/dist/lib/teach/teachings.d.ts.map +1 -1
  138. package/package.json +32 -15
  139. package/dist/lib/adapters/grounding.ticket.d.ts.map +0 -1
  140. package/dist/lib/adapters/groundings/grounding.d.ts.map +0 -1
  141. package/dist/lib/adapters/groundings/grounding.js.map +0 -7
  142. package/dist/lib/adapters/groundings/low-cardinality.grounding.d.ts +0 -35
  143. package/dist/lib/adapters/groundings/low-cardinality.grounding.d.ts.map +0 -1
  144. package/dist/lib/adapters/postgres/low-cardinality.postgres.grounding.d.ts +0 -14
  145. package/dist/lib/adapters/postgres/low-cardinality.postgres.grounding.d.ts.map +0 -1
  146. package/dist/lib/adapters/sqlite/low-cardinality.sqlite.grounding.d.ts +0 -14
  147. package/dist/lib/adapters/sqlite/low-cardinality.sqlite.grounding.d.ts.map +0 -1
  148. package/dist/lib/adapters/sqlserver/low-cardinality.sqlserver.grounding.d.ts +0 -14
  149. package/dist/lib/adapters/sqlserver/low-cardinality.sqlserver.grounding.d.ts.map +0 -1
@@ -1,3 +1,205 @@
1
+ // packages/text2sql/src/lib/adapters/groundings/abstract.grounding.ts
2
+ var AbstractGrounding = class {
3
+ tag;
4
+ constructor(tag) {
5
+ this.tag = tag;
6
+ }
7
+ };
8
+
9
+ // packages/text2sql/src/lib/adapters/groundings/column-stats.grounding.ts
10
+ var ColumnStatsGrounding = class extends AbstractGrounding {
11
+ constructor(config = {}) {
12
+ super("column_stats");
13
+ }
14
+ /**
15
+ * Execute the grounding process.
16
+ * Annotates columns in ctx.tables and ctx.views with statistics.
17
+ */
18
+ async execute(ctx) {
19
+ const allContainers = [...ctx.tables, ...ctx.views];
20
+ for (const container of allContainers) {
21
+ for (const column of container.columns) {
22
+ try {
23
+ const stats = await this.collectStats(container.name, column);
24
+ if (stats) {
25
+ column.stats = stats;
26
+ }
27
+ } catch (error) {
28
+ console.warn(
29
+ "Error collecting stats for",
30
+ container.name,
31
+ column.name,
32
+ error
33
+ );
34
+ }
35
+ }
36
+ }
37
+ return () => this.#describe();
38
+ }
39
+ #describe() {
40
+ return null;
41
+ }
42
+ };
43
+
44
+ // packages/text2sql/src/lib/adapters/groundings/column-values.grounding.ts
45
+ var ColumnValuesGrounding = class extends AbstractGrounding {
46
+ lowCardinalityLimit;
47
+ constructor(config = {}) {
48
+ super("column_values");
49
+ this.lowCardinalityLimit = config.lowCardinalityLimit ?? 20;
50
+ }
51
+ /**
52
+ * Get values for native ENUM type columns.
53
+ * Return undefined if column is not an ENUM type.
54
+ * Default implementation returns undefined (no native ENUM support).
55
+ */
56
+ async collectEnumValues(_tableName, _column) {
57
+ return void 0;
58
+ }
59
+ /**
60
+ * Parse CHECK constraint for enum-like IN clause.
61
+ * Extracts values from patterns like:
62
+ * - CHECK (status IN ('active', 'inactive'))
63
+ * - CHECK ((status)::text = ANY (ARRAY['a'::text, 'b'::text]))
64
+ * - CHECK (status = 'active' OR status = 'inactive')
65
+ */
66
+ parseCheckConstraint(constraint, columnName) {
67
+ if (constraint.type !== "CHECK" || !constraint.definition) {
68
+ return void 0;
69
+ }
70
+ if (constraint.columns && !constraint.columns.includes(columnName)) {
71
+ return void 0;
72
+ }
73
+ const def = constraint.definition;
74
+ const escapedCol = this.escapeRegex(columnName);
75
+ const colPattern = `(?:\\(?\\(?${escapedCol}\\)?(?:::(?:text|varchar|character varying))?\\)?)`;
76
+ const inMatch = def.match(
77
+ new RegExp(`${colPattern}\\s+IN\\s*\\(([^)]+)\\)`, "i")
78
+ );
79
+ if (inMatch) {
80
+ return this.extractStringValues(inMatch[1]);
81
+ }
82
+ const anyMatch = def.match(
83
+ new RegExp(
84
+ `${colPattern}\\s*=\\s*ANY\\s*\\(\\s*(?:ARRAY)?\\s*\\[([^\\]]+)\\]`,
85
+ "i"
86
+ )
87
+ );
88
+ if (anyMatch) {
89
+ return this.extractStringValues(anyMatch[1]);
90
+ }
91
+ const orPattern = new RegExp(
92
+ `\\b${this.escapeRegex(columnName)}\\b\\s*=\\s*'([^']*)'`,
93
+ "gi"
94
+ );
95
+ const orMatches = [...def.matchAll(orPattern)];
96
+ if (orMatches.length >= 2) {
97
+ return orMatches.map((m) => m[1]);
98
+ }
99
+ return void 0;
100
+ }
101
+ /**
102
+ * Extract string values from a comma-separated list.
103
+ */
104
+ extractStringValues(input) {
105
+ const values = [];
106
+ const matches = input.matchAll(/'([^']*)'/g);
107
+ for (const match of matches) {
108
+ values.push(match[1]);
109
+ }
110
+ return values.length > 0 ? values : void 0;
111
+ }
112
+ /**
113
+ * Escape special regex characters in a string.
114
+ */
115
+ escapeRegex(str) {
116
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
117
+ }
118
+ /**
119
+ * Get the table from context by name.
120
+ */
121
+ getTable(ctx, name) {
122
+ return ctx.tables.find((t) => t.name === name);
123
+ }
124
+ /**
125
+ * Execute the grounding process.
126
+ * Annotates columns in ctx.tables and ctx.views with values.
127
+ */
128
+ async execute(ctx) {
129
+ const allContainers = [...ctx.tables, ...ctx.views];
130
+ for (const container of allContainers) {
131
+ const table = this.getTable(ctx, container.name);
132
+ for (const column of container.columns) {
133
+ try {
134
+ const result = await this.resolveColumnValues(
135
+ container.name,
136
+ column,
137
+ table?.constraints
138
+ );
139
+ if (result) {
140
+ column.kind = result.kind;
141
+ column.values = result.values;
142
+ }
143
+ } catch (error) {
144
+ console.warn(
145
+ "Error collecting column values for",
146
+ container.name,
147
+ column.name,
148
+ error
149
+ );
150
+ }
151
+ }
152
+ }
153
+ return () => this.#describe();
154
+ }
155
+ /**
156
+ * Resolve column values from all sources in priority order.
157
+ */
158
+ async resolveColumnValues(tableName, column, constraints) {
159
+ const enumValues = await this.collectEnumValues(tableName, column);
160
+ if (enumValues?.length) {
161
+ return { kind: "Enum", values: enumValues };
162
+ }
163
+ if (constraints) {
164
+ for (const constraint of constraints) {
165
+ const checkValues = this.parseCheckConstraint(constraint, column.name);
166
+ if (checkValues?.length) {
167
+ return { kind: "Enum", values: checkValues };
168
+ }
169
+ }
170
+ }
171
+ const lowCardValues = await this.collectLowCardinality(tableName, column);
172
+ if (lowCardValues?.length) {
173
+ return { kind: "LowCardinality", values: lowCardValues };
174
+ }
175
+ return void 0;
176
+ }
177
+ #describe() {
178
+ return null;
179
+ }
180
+ };
181
+
182
+ // packages/text2sql/src/lib/adapters/groundings/constraint.grounding.ts
183
+ var ConstraintGrounding = class extends AbstractGrounding {
184
+ constructor(config = {}) {
185
+ super("constraints");
186
+ }
187
+ /**
188
+ * Execute the grounding process.
189
+ * Annotates tables in ctx.tables with their constraints.
190
+ */
191
+ async execute(ctx) {
192
+ for (const table of ctx.tables) {
193
+ try {
194
+ table.constraints = await this.getConstraints(table.name);
195
+ } catch (error) {
196
+ console.warn("Error collecting constraints for", table.name, error);
197
+ }
198
+ }
199
+ return () => null;
200
+ }
201
+ };
202
+
1
203
  // packages/text2sql/src/lib/adapters/groundings/context.ts
2
204
  function createGroundingContext() {
3
205
  return {
@@ -8,18 +210,159 @@ function createGroundingContext() {
8
210
  };
9
211
  }
10
212
 
11
- // packages/text2sql/src/lib/adapters/groundings/table.grounding.ts
12
- import pluralize from "pluralize";
213
+ // packages/text2sql/src/lib/adapters/groundings/info.grounding.ts
214
+ var InfoGrounding = class extends AbstractGrounding {
215
+ constructor(config = {}) {
216
+ super("dialect_info");
217
+ }
218
+ /**
219
+ * Execute the grounding process.
220
+ * Writes database info to ctx.info.
221
+ */
222
+ async execute(ctx) {
223
+ ctx.info = await this.collectInfo();
224
+ const lines = [`Dialect: ${ctx.info.dialect ?? "unknown"}`];
225
+ if (ctx.info.version) {
226
+ lines.push(`Version: ${ctx.info.version}`);
227
+ }
228
+ if (ctx.info.database) {
229
+ lines.push(`Database: ${ctx.info.database}`);
230
+ }
231
+ if (ctx.info.details && Object.keys(ctx.info.details).length) {
232
+ lines.push(`Details: ${JSON.stringify(ctx.info.details)}`);
233
+ }
234
+ return () => lines.join("\n");
235
+ }
236
+ };
13
237
 
14
- // packages/text2sql/src/lib/adapters/grounding.ticket.ts
15
- var AbstractGrounding = class {
16
- tag;
17
- constructor(tag) {
18
- this.tag = tag;
238
+ // packages/text2sql/src/lib/adapters/groundings/report.grounding.ts
239
+ import { groq } from "@ai-sdk/groq";
240
+ import { tool } from "ai";
241
+ import dedent from "dedent";
242
+ import z from "zod";
243
+ import {
244
+ agent,
245
+ generate,
246
+ toState,
247
+ user
248
+ } from "@deepagents/agent";
249
+ var ReportGrounding = class extends AbstractGrounding {
250
+ #adapter;
251
+ #model;
252
+ #cache;
253
+ #forceRefresh;
254
+ constructor(adapter, config = {}) {
255
+ super("business_context");
256
+ this.#adapter = adapter;
257
+ this.#model = config.model ?? groq("openai/gpt-oss-20b");
258
+ this.#cache = config.cache;
259
+ this.#forceRefresh = config.forceRefresh ?? false;
260
+ }
261
+ async execute(ctx) {
262
+ if (!this.#forceRefresh && this.#cache) {
263
+ const cached = await this.#cache.get();
264
+ if (cached) {
265
+ ctx.report = cached;
266
+ return () => cached;
267
+ }
268
+ }
269
+ const report = await this.#generateReport();
270
+ ctx.report = report;
271
+ if (this.#cache) {
272
+ await this.#cache.set(report);
273
+ }
274
+ return () => report;
275
+ }
276
+ async #generateReport() {
277
+ const reportAgent = agent({
278
+ name: "db-report-agent",
279
+ model: this.#model,
280
+ prompt: () => dedent`
281
+ <identity>
282
+ You are a database analyst expert. Your job is to understand what
283
+ a database represents and provide business context about it.
284
+ You have READ-ONLY access to the database.
285
+ </identity>
286
+
287
+ <instructions>
288
+ Write a business context that helps another agent answer questions accurately.
289
+
290
+ For EACH table, do queries ONE AT A TIME:
291
+ 1. SELECT COUNT(*) to get row count
292
+ 2. SELECT * LIMIT 3 to see sample data
293
+
294
+ Then write a report with:
295
+ - What business this database is for
296
+ - For each table: purpose, row count, and example of what the data looks like
297
+
298
+ Include concrete examples like "Track prices are $0.99",
299
+ "Customer names like 'Luís Gonçalves'", etc.
300
+
301
+ Keep it 400-600 words, conversational style.
302
+ </instructions>
303
+ `,
304
+ tools: {
305
+ query_database: tool({
306
+ description: "Execute a SELECT query to explore the database and gather insights.",
307
+ inputSchema: z.object({
308
+ sql: z.string().describe("The SELECT query to execute"),
309
+ purpose: z.string().describe(
310
+ "What insight you are trying to gather with this query"
311
+ )
312
+ }),
313
+ execute: ({ sql }, options) => {
314
+ const state = toState(options);
315
+ return state.adapter.execute(sql);
316
+ }
317
+ })
318
+ }
319
+ });
320
+ const { text } = await generate(
321
+ reportAgent,
322
+ [
323
+ user(
324
+ "Please analyze the database and write a contextual report about what this database represents."
325
+ )
326
+ ],
327
+ { adapter: this.#adapter }
328
+ );
329
+ return text;
330
+ }
331
+ };
332
+
333
+ // packages/text2sql/src/lib/adapters/groundings/row-count.grounding.ts
334
+ var RowCountGrounding = class extends AbstractGrounding {
335
+ constructor(config = {}) {
336
+ super("row_counts");
337
+ }
338
+ /**
339
+ * Execute the grounding process.
340
+ * Annotates tables in ctx.tables with row counts and size hints.
341
+ */
342
+ async execute(ctx) {
343
+ for (const table of ctx.tables) {
344
+ const count = await this.getRowCount(table.name);
345
+ if (count != null) {
346
+ table.rowCount = count;
347
+ table.sizeHint = this.#classifyRowCount(count);
348
+ }
349
+ }
350
+ return () => null;
351
+ }
352
+ /**
353
+ * Classify row count into a size hint category.
354
+ */
355
+ #classifyRowCount(count) {
356
+ if (count < 100) return "tiny";
357
+ if (count < 1e3) return "small";
358
+ if (count < 1e4) return "medium";
359
+ if (count < 1e5) return "large";
360
+ return "huge";
19
361
  }
20
362
  };
21
363
 
22
364
  // packages/text2sql/src/lib/adapters/groundings/table.grounding.ts
365
+ import pluralize from "pluralize";
23
366
  var TableGrounding = class extends AbstractGrounding {
24
367
  #filter;
25
368
  #forward;
@@ -135,18 +478,61 @@ var TableGrounding = class extends AbstractGrounding {
135
478
  }
136
479
  return tables.map((table) => {
137
480
  const rowCountInfo = table.rowCount != null ? ` [rows: ${table.rowCount}${table.sizeHint ? `, size: ${table.sizeHint}` : ""}]` : "";
138
- const pkConstraint = table.constraints?.find((c) => c.type === "PRIMARY_KEY");
481
+ const pkConstraint = table.constraints?.find(
482
+ (c) => c.type === "PRIMARY_KEY"
483
+ );
139
484
  const pkColumns = new Set(pkConstraint?.columns ?? []);
485
+ const notNullColumns = new Set(
486
+ table.constraints?.filter((c) => c.type === "NOT_NULL").flatMap((c) => c.columns ?? []) ?? []
487
+ );
488
+ const defaultByColumn = /* @__PURE__ */ new Map();
489
+ for (const c of table.constraints?.filter(
490
+ (c2) => c2.type === "DEFAULT"
491
+ ) ?? []) {
492
+ for (const col of c.columns ?? []) {
493
+ if (c.defaultValue != null) {
494
+ defaultByColumn.set(col, c.defaultValue);
495
+ }
496
+ }
497
+ }
498
+ const uniqueColumns = new Set(
499
+ table.constraints?.filter((c) => c.type === "UNIQUE" && c.columns?.length === 1).flatMap((c) => c.columns ?? []) ?? []
500
+ );
501
+ const fkByColumn = /* @__PURE__ */ new Map();
502
+ for (const c of table.constraints?.filter(
503
+ (c2) => c2.type === "FOREIGN_KEY"
504
+ ) ?? []) {
505
+ const cols = c.columns ?? [];
506
+ const refCols = c.referencedColumns ?? [];
507
+ for (let i = 0; i < cols.length; i++) {
508
+ const refCol = refCols[i] ?? refCols[0] ?? cols[i];
509
+ fkByColumn.set(cols[i], `${c.referencedTable}.${refCol}`);
510
+ }
511
+ }
140
512
  const columns = table.columns.map((column) => {
141
513
  const annotations = [];
142
514
  const isPrimaryKey = pkColumns.has(column.name);
143
515
  if (isPrimaryKey) {
144
516
  annotations.push("PK");
145
517
  }
518
+ if (fkByColumn.has(column.name)) {
519
+ annotations.push(`FK -> ${fkByColumn.get(column.name)}`);
520
+ }
521
+ if (uniqueColumns.has(column.name)) {
522
+ annotations.push("UNIQUE");
523
+ }
524
+ if (notNullColumns.has(column.name)) {
525
+ annotations.push("NOT NULL");
526
+ }
527
+ if (defaultByColumn.has(column.name)) {
528
+ annotations.push(`DEFAULT: ${defaultByColumn.get(column.name)}`);
529
+ }
146
530
  if (column.isIndexed && !isPrimaryKey) {
147
531
  annotations.push("Indexed");
148
532
  }
149
- if (column.kind === "LowCardinality" && column.values?.length) {
533
+ if (column.kind === "Enum" && column.values?.length) {
534
+ annotations.push(`Enum: ${column.values.join(", ")}`);
535
+ } else if (column.kind === "LowCardinality" && column.values?.length) {
150
536
  annotations.push(`LowCardinality: ${column.values.join(", ")}`);
151
537
  }
152
538
  if (column.stats) {
@@ -181,9 +567,19 @@ ${table.indexes.map((index) => {
181
567
  const columnsText = index.columns?.length ? index.columns.join(", ") : "expression";
182
568
  return ` - ${index.name}${propsText}: ${columnsText}`;
183
569
  }).join("\n")}` : "";
570
+ const multiColumnUniques = table.constraints?.filter(
571
+ (c) => c.type === "UNIQUE" && (c.columns?.length ?? 0) > 1
572
+ ) ?? [];
573
+ const uniqueConstraints = multiColumnUniques.length ? `
574
+ Unique Constraints:
575
+ ${multiColumnUniques.map((c) => ` - ${c.name}: (${c.columns?.join(", ")})`).join("\n")}` : "";
576
+ const checkConstraints = table.constraints?.filter((c) => c.type === "CHECK") ?? [];
577
+ const checks = checkConstraints.length ? `
578
+ Check Constraints:
579
+ ${checkConstraints.map((c) => ` - ${c.name}: ${c.definition}`).join("\n")}` : "";
184
580
  return `- Table: ${table.name}${rowCountInfo}
185
581
  Columns:
186
- ${columns}${indexes}`;
582
+ ${columns}${indexes}${uniqueConstraints}${checks}`;
187
583
  }).join("\n\n");
188
584
  }
189
585
  #formatTableLabel = (tableName) => {
@@ -228,105 +624,6 @@ ${columns}${indexes}`;
228
624
  };
229
625
  };
230
626
 
231
- // packages/text2sql/src/lib/adapters/groundings/column-stats.grounding.ts
232
- var ColumnStatsGrounding = class extends AbstractGrounding {
233
- constructor(config = {}) {
234
- super("column_stats");
235
- }
236
- /**
237
- * Execute the grounding process.
238
- * Annotates columns in ctx.tables and ctx.views with statistics.
239
- */
240
- async execute(ctx) {
241
- const allContainers = [...ctx.tables, ...ctx.views];
242
- for (const container of allContainers) {
243
- for (const column of container.columns) {
244
- try {
245
- const stats = await this.collectStats(container.name, column);
246
- if (stats) {
247
- column.stats = stats;
248
- }
249
- } catch (error) {
250
- console.warn(
251
- "Error collecting stats for",
252
- container.name,
253
- column.name,
254
- error
255
- );
256
- }
257
- }
258
- }
259
- return () => this.#describe();
260
- }
261
- #describe() {
262
- return null;
263
- }
264
- };
265
-
266
- // packages/text2sql/src/lib/adapters/groundings/low-cardinality.grounding.ts
267
- var LowCardinalityGrounding = class extends AbstractGrounding {
268
- constructor(config = {}) {
269
- super("low_cardinality");
270
- }
271
- /**
272
- * Execute the grounding process.
273
- * Annotates columns in ctx.tables and ctx.views with low cardinality values.
274
- */
275
- async execute(ctx) {
276
- const allContainers = [...ctx.tables, ...ctx.views];
277
- for (const container of allContainers) {
278
- for (const column of container.columns) {
279
- try {
280
- const lowCard = await this.collectLowCardinality(
281
- container.name,
282
- column
283
- );
284
- if (lowCard) {
285
- column.kind = lowCard.kind;
286
- column.values = lowCard.values;
287
- }
288
- } catch (error) {
289
- console.warn(
290
- "Error collecting low cardinality values for",
291
- container.name,
292
- column.name,
293
- error
294
- );
295
- }
296
- }
297
- }
298
- return () => this.#describe();
299
- }
300
- #describe() {
301
- return null;
302
- }
303
- };
304
-
305
- // packages/text2sql/src/lib/adapters/groundings/info.grounding.ts
306
- var InfoGrounding = class extends AbstractGrounding {
307
- constructor(config = {}) {
308
- super("dialect_info");
309
- }
310
- /**
311
- * Execute the grounding process.
312
- * Writes database info to ctx.info.
313
- */
314
- async execute(ctx) {
315
- ctx.info = await this.collectInfo();
316
- const lines = [`Dialect: ${ctx.info.dialect ?? "unknown"}`];
317
- if (ctx.info.version) {
318
- lines.push(`Version: ${ctx.info.version}`);
319
- }
320
- if (ctx.info.database) {
321
- lines.push(`Database: ${ctx.info.database}`);
322
- }
323
- if (ctx.info.details && Object.keys(ctx.info.details).length) {
324
- lines.push(`Details: ${JSON.stringify(ctx.info.details)}`);
325
- }
326
- return () => lines.join("\n");
327
- }
328
- };
329
-
330
627
  // packages/text2sql/src/lib/adapters/groundings/view.grounding.ts
331
628
  var ViewGrounding = class extends AbstractGrounding {
332
629
  #filter;
@@ -400,108 +697,16 @@ ${columns}`;
400
697
  return names.filter(filter);
401
698
  }
402
699
  };
403
-
404
- // packages/text2sql/src/lib/adapters/groundings/report.grounding.ts
405
- import { groq } from "@ai-sdk/groq";
406
- import { tool } from "ai";
407
- import dedent from "dedent";
408
- import z from "zod";
409
- import {
410
- agent,
411
- generate,
412
- toState,
413
- user
414
- } from "@deepagents/agent";
415
- var ReportGrounding = class extends AbstractGrounding {
416
- #adapter;
417
- #model;
418
- #cache;
419
- #forceRefresh;
420
- constructor(adapter, config = {}) {
421
- super("business_context");
422
- this.#adapter = adapter;
423
- this.#model = config.model ?? groq("openai/gpt-oss-20b");
424
- this.#cache = config.cache;
425
- this.#forceRefresh = config.forceRefresh ?? false;
426
- }
427
- async execute(ctx) {
428
- if (!this.#forceRefresh && this.#cache) {
429
- const cached = await this.#cache.get();
430
- if (cached) {
431
- ctx.report = cached;
432
- return () => cached;
433
- }
434
- }
435
- const report = await this.#generateReport();
436
- ctx.report = report;
437
- if (this.#cache) {
438
- await this.#cache.set(report);
439
- }
440
- return () => report;
441
- }
442
- async #generateReport() {
443
- const reportAgent = agent({
444
- name: "db-report-agent",
445
- model: this.#model,
446
- prompt: () => dedent`
447
- <identity>
448
- You are a database analyst expert. Your job is to understand what
449
- a database represents and provide business context about it.
450
- You have READ-ONLY access to the database.
451
- </identity>
452
-
453
- <instructions>
454
- Write a business context that helps another agent answer questions accurately.
455
-
456
- For EACH table, do queries ONE AT A TIME:
457
- 1. SELECT COUNT(*) to get row count
458
- 2. SELECT * LIMIT 3 to see sample data
459
-
460
- Then write a report with:
461
- - What business this database is for
462
- - For each table: purpose, row count, and example of what the data looks like
463
-
464
- Include concrete examples like "Track prices are $0.99",
465
- "Customer names like 'Luís Gonçalves'", etc.
466
-
467
- Keep it 400-600 words, conversational style.
468
- </instructions>
469
- `,
470
- tools: {
471
- query_database: tool({
472
- description: "Execute a SELECT query to explore the database and gather insights.",
473
- inputSchema: z.object({
474
- sql: z.string().describe("The SELECT query to execute"),
475
- purpose: z.string().describe(
476
- "What insight you are trying to gather with this query"
477
- )
478
- }),
479
- execute: ({ sql }, options) => {
480
- const state = toState(options);
481
- return state.adapter.execute(sql);
482
- }
483
- })
484
- }
485
- });
486
- const { text } = await generate(
487
- reportAgent,
488
- [
489
- user(
490
- "Please analyze the database and write a contextual report about what this database represents."
491
- )
492
- ],
493
- { adapter: this.#adapter }
494
- );
495
- return text;
496
- }
497
- };
498
700
  export {
701
+ AbstractGrounding,
499
702
  ColumnStatsGrounding,
703
+ ColumnValuesGrounding,
704
+ ConstraintGrounding,
500
705
  InfoGrounding,
501
- LowCardinalityGrounding,
502
706
  ReportGrounding,
707
+ RowCountGrounding,
503
708
  TableGrounding,
504
709
  ViewGrounding,
505
710
  createGroundingContext
506
711
  };
507
- //# sourceMappingURL=grounding.js.map
712
+ //# sourceMappingURL=index.js.map