@deepagents/text2sql 0.3.1 → 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.
- package/README.md +167 -0
- package/dist/finetune/convert-to-gguf.d.ts +18 -0
- package/dist/finetune/convert-to-gguf.d.ts.map +1 -0
- package/dist/finetune/run-finetune.d.ts +23 -0
- package/dist/finetune/run-finetune.d.ts.map +1 -0
- package/dist/finetune/run-mlx.d.ts +22 -0
- package/dist/finetune/run-mlx.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1793 -279
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/adapter.d.ts +3 -3
- package/dist/lib/adapters/adapter.d.ts.map +1 -1
- package/dist/lib/adapters/{grounding.ticket.d.ts → groundings/abstract.grounding.d.ts} +2 -2
- package/dist/lib/adapters/groundings/abstract.grounding.d.ts.map +1 -0
- package/dist/lib/adapters/groundings/column-stats.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/column-stats.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/column-values.grounding.d.ts +76 -0
- package/dist/lib/adapters/groundings/column-values.grounding.d.ts.map +1 -0
- package/dist/lib/adapters/groundings/constraint.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/constraint.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/context.d.ts +1 -1
- package/dist/lib/adapters/groundings/context.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/{grounding.d.ts → index.d.ts} +8 -5
- package/dist/lib/adapters/groundings/index.d.ts.map +1 -0
- package/dist/lib/adapters/groundings/{grounding.js → index.js} +411 -206
- package/dist/lib/adapters/groundings/index.js.map +7 -0
- package/dist/lib/adapters/groundings/indexes.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/indexes.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/info.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/info.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/report.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/report.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/row-count.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/row-count.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/table.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/table.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/view.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/view.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/column-stats.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts +17 -0
- package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts.map +1 -0
- package/dist/lib/adapters/postgres/index.d.ts +4 -4
- package/dist/lib/adapters/postgres/index.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/index.js +233 -33
- package/dist/lib/adapters/postgres/index.js.map +4 -4
- package/dist/lib/adapters/sqlite/column-values.sqlite.grounding.d.ts +17 -0
- package/dist/lib/adapters/sqlite/column-values.sqlite.grounding.d.ts.map +1 -0
- package/dist/lib/adapters/sqlite/constraint.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/index.d.ts +4 -4
- package/dist/lib/adapters/sqlite/index.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/index.js +214 -46
- package/dist/lib/adapters/sqlite/index.js.map +4 -4
- package/dist/lib/adapters/sqlserver/column-values.sqlserver.grounding.d.ts +17 -0
- package/dist/lib/adapters/sqlserver/column-values.sqlserver.grounding.d.ts.map +1 -0
- package/dist/lib/adapters/sqlserver/index.d.ts +4 -4
- package/dist/lib/adapters/sqlserver/index.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/index.js +179 -32
- package/dist/lib/adapters/sqlserver/index.js.map +4 -4
- package/dist/lib/agents/chat1.agent.d.ts +50 -0
- package/dist/lib/agents/chat1.agent.d.ts.map +1 -0
- package/dist/lib/agents/chat2.agent.d.ts +68 -0
- package/dist/lib/agents/chat2.agent.d.ts.map +1 -0
- package/dist/lib/agents/chat3.agent.d.ts +80 -0
- package/dist/lib/agents/chat3.agent.d.ts.map +1 -0
- package/dist/lib/agents/chat4.agent.d.ts +88 -0
- package/dist/lib/agents/chat4.agent.d.ts.map +1 -0
- package/dist/lib/agents/question.agent.d.ts +23 -0
- package/dist/lib/agents/question.agent.d.ts.map +1 -0
- package/dist/lib/agents/sql.agent.d.ts +62 -0
- package/dist/lib/agents/sql.agent.d.ts.map +1 -0
- package/dist/lib/agents/teachables.agent.d.ts +8 -9
- package/dist/lib/agents/teachables.agent.d.ts.map +1 -1
- package/dist/lib/agents/text2sql.agent.d.ts +0 -1
- package/dist/lib/agents/text2sql.agent.d.ts.map +1 -1
- package/dist/lib/checkpoint.d.ts +99 -0
- package/dist/lib/checkpoint.d.ts.map +1 -0
- package/dist/lib/instructions.js +50 -21
- package/dist/lib/instructions.js.map +2 -2
- package/dist/lib/sql.d.ts +83 -3
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/syntheize.d.ts +2 -0
- package/dist/lib/syntheize.d.ts.map +1 -0
- package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts +26 -0
- package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts.map +1 -0
- package/dist/lib/synthesis/decorators/filtered-producer.d.ts +26 -0
- package/dist/lib/synthesis/decorators/filtered-producer.d.ts.map +1 -0
- package/dist/lib/synthesis/decorators/index.d.ts +7 -0
- package/dist/lib/synthesis/decorators/index.d.ts.map +1 -0
- package/dist/lib/synthesis/decorators/validated-producer.d.ts +33 -0
- package/dist/lib/synthesis/decorators/validated-producer.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts +76 -0
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/full-context-extractor.d.ts +25 -0
- package/dist/lib/synthesis/extractors/full-context-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/index.d.ts +8 -0
- package/dist/lib/synthesis/extractors/index.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/last-query-extractor.d.ts +30 -0
- package/dist/lib/synthesis/extractors/last-query-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/message-extractor.d.ts +27 -0
- package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/segmented-context-extractor.d.ts +48 -0
- package/dist/lib/synthesis/extractors/segmented-context-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/sql-extractor.d.ts +27 -0
- package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/extractors/windowed-context-extractor.d.ts +30 -0
- package/dist/lib/synthesis/extractors/windowed-context-extractor.d.ts.map +1 -0
- package/dist/lib/synthesis/index.d.ts +6 -0
- package/dist/lib/synthesis/index.d.ts.map +1 -0
- package/dist/lib/synthesis/index.js +2069 -0
- package/dist/lib/synthesis/index.js.map +7 -0
- package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts +34 -0
- package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -0
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts +41 -0
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -0
- package/dist/lib/synthesis/synthesizers/index.d.ts +7 -0
- package/dist/lib/synthesis/synthesizers/index.d.ts.map +1 -0
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts +34 -0
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts.map +1 -0
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +39 -0
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -0
- package/dist/lib/synthesis/synthesizers/styles.d.ts +8 -0
- package/dist/lib/synthesis/synthesizers/styles.d.ts.map +1 -0
- package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts +32 -0
- package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts.map +1 -0
- package/dist/lib/synthesis/types.d.ts +26 -0
- package/dist/lib/synthesis/types.d.ts.map +1 -0
- package/dist/lib/teach/teachables.d.ts +18 -3
- package/dist/lib/teach/teachables.d.ts.map +1 -1
- package/dist/lib/teach/teachings.d.ts +9 -2
- package/dist/lib/teach/teachings.d.ts.map +1 -1
- package/package.json +32 -15
- package/dist/lib/adapters/grounding.ticket.d.ts.map +0 -1
- package/dist/lib/adapters/groundings/grounding.d.ts.map +0 -1
- package/dist/lib/adapters/groundings/grounding.js.map +0 -7
- package/dist/lib/adapters/groundings/low-cardinality.grounding.d.ts +0 -35
- package/dist/lib/adapters/groundings/low-cardinality.grounding.d.ts.map +0 -1
- package/dist/lib/adapters/postgres/low-cardinality.postgres.grounding.d.ts +0 -14
- package/dist/lib/adapters/postgres/low-cardinality.postgres.grounding.d.ts.map +0 -1
- package/dist/lib/adapters/sqlite/low-cardinality.sqlite.grounding.d.ts +0 -14
- package/dist/lib/adapters/sqlite/low-cardinality.sqlite.grounding.d.ts.map +0 -1
- package/dist/lib/adapters/sqlserver/low-cardinality.sqlserver.grounding.d.ts +0 -14
- 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/
|
|
12
|
-
|
|
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.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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(
|
|
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 === "
|
|
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=
|
|
712
|
+
//# sourceMappingURL=index.js.map
|