@deepagents/text2sql 0.10.1 → 0.11.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 +32 -41
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2338 -2395
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/adapter.d.ts +13 -1
- package/dist/lib/adapters/adapter.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/abstract.grounding.d.ts +19 -3
- package/dist/lib/adapters/groundings/abstract.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/column-stats.grounding.d.ts +1 -2
- package/dist/lib/adapters/groundings/column-stats.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/column-values.grounding.d.ts +1 -2
- package/dist/lib/adapters/groundings/column-values.grounding.d.ts.map +1 -1
- 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/index.js +15 -222
- package/dist/lib/adapters/groundings/index.js.map +3 -3
- 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 +3 -3
- 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/mysql/index.js +343 -315
- package/dist/lib/adapters/mysql/index.js.map +4 -4
- package/dist/lib/adapters/postgres/index.js +385 -357
- package/dist/lib/adapters/postgres/index.js.map +4 -4
- package/dist/lib/adapters/spreadsheet/index.js +290 -223
- package/dist/lib/adapters/spreadsheet/index.js.map +4 -4
- package/dist/lib/adapters/sqlite/index.js +307 -279
- package/dist/lib/adapters/sqlite/index.js.map +4 -4
- package/dist/lib/adapters/sqlserver/index.js +383 -355
- package/dist/lib/adapters/sqlserver/index.js.map +4 -4
- package/dist/lib/agents/developer.agent.d.ts +33 -23
- package/dist/lib/agents/developer.agent.d.ts.map +1 -1
- package/dist/lib/agents/sql.agent.d.ts +4 -4
- package/dist/lib/agents/sql.agent.d.ts.map +1 -1
- package/dist/lib/agents/teachables.agent.d.ts +2 -2
- package/dist/lib/agents/teachables.agent.d.ts.map +1 -1
- package/dist/lib/agents/text2sql.agent.d.ts +18 -71
- package/dist/lib/agents/text2sql.agent.d.ts.map +1 -1
- package/dist/lib/fragments/schema.d.ts +214 -0
- package/dist/lib/fragments/schema.d.ts.map +1 -0
- package/dist/lib/instructions.d.ts +29 -2
- package/dist/lib/instructions.d.ts.map +1 -1
- package/dist/lib/instructions.js +336 -319
- package/dist/lib/instructions.js.map +4 -4
- package/dist/lib/sql.d.ts +13 -103
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts +2 -2
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/message-extractor.d.ts +1 -2
- package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +1794 -572
- package/dist/lib/synthesis/index.js.map +4 -4
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts +7 -17
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +2 -2
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts +8 -20
- package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts.map +1 -1
- package/dist/lib/teach/teachings.d.ts +2 -2
- package/dist/lib/teach/teachings.d.ts.map +1 -1
- package/package.json +4 -3
- package/dist/lib/agents/chat1.agent.d.ts +0 -50
- package/dist/lib/agents/chat1.agent.d.ts.map +0 -1
- package/dist/lib/agents/chat2.agent.d.ts +0 -68
- package/dist/lib/agents/chat2.agent.d.ts.map +0 -1
- package/dist/lib/agents/chat3.agent.d.ts +0 -80
- package/dist/lib/agents/chat3.agent.d.ts.map +0 -1
- package/dist/lib/agents/chat4.agent.d.ts +0 -88
- package/dist/lib/agents/chat4.agent.d.ts.map +0 -1
- package/dist/lib/history/history.d.ts +0 -41
- package/dist/lib/history/history.d.ts.map +0 -1
- package/dist/lib/history/memory.history.d.ts +0 -5
- package/dist/lib/history/memory.history.d.ts.map +0 -1
- package/dist/lib/history/sqlite.history.d.ts +0 -15
- package/dist/lib/history/sqlite.history.d.ts.map +0 -1
- package/dist/lib/memory/memory.prompt.d.ts +0 -3
- package/dist/lib/memory/memory.prompt.d.ts.map +0 -1
- package/dist/lib/memory/memory.store.d.ts +0 -5
- package/dist/lib/memory/memory.store.d.ts.map +0 -1
- package/dist/lib/memory/sqlite.store.d.ts +0 -14
- package/dist/lib/memory/sqlite.store.d.ts.map +0 -1
- package/dist/lib/memory/store.d.ts +0 -40
- package/dist/lib/memory/store.d.ts.map +0 -1
- package/dist/lib/teach/teachables.d.ts +0 -648
- package/dist/lib/teach/teachables.d.ts.map +0 -1
- package/dist/lib/teach/xml.d.ts +0 -6
- package/dist/lib/teach/xml.d.ts.map +0 -1
|
@@ -1,3 +1,94 @@
|
|
|
1
|
+
// packages/text2sql/src/lib/fragments/schema.ts
|
|
2
|
+
function dialectInfo(input) {
|
|
3
|
+
return {
|
|
4
|
+
name: "dialectInfo",
|
|
5
|
+
data: {
|
|
6
|
+
dialect: input.dialect,
|
|
7
|
+
...input.version && { version: input.version },
|
|
8
|
+
...input.database && { database: input.database }
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function table(input) {
|
|
13
|
+
return {
|
|
14
|
+
name: "table",
|
|
15
|
+
data: {
|
|
16
|
+
name: input.name,
|
|
17
|
+
...input.schema && { schema: input.schema },
|
|
18
|
+
...input.rowCount != null && { rowCount: input.rowCount },
|
|
19
|
+
...input.sizeHint && { sizeHint: input.sizeHint },
|
|
20
|
+
columns: input.columns,
|
|
21
|
+
...input.indexes?.length && { indexes: input.indexes },
|
|
22
|
+
...input.constraints?.length && { constraints: input.constraints }
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function column(input) {
|
|
27
|
+
return {
|
|
28
|
+
name: "column",
|
|
29
|
+
data: {
|
|
30
|
+
name: input.name,
|
|
31
|
+
type: input.type,
|
|
32
|
+
...input.pk && { pk: true },
|
|
33
|
+
...input.fk && { fk: input.fk },
|
|
34
|
+
...input.unique && { unique: true },
|
|
35
|
+
...input.notNull && { notNull: true },
|
|
36
|
+
...input.default && { default: input.default },
|
|
37
|
+
...input.indexed && { indexed: true },
|
|
38
|
+
...input.values?.length && { values: input.values },
|
|
39
|
+
...input.stats && { stats: input.stats }
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function index(input) {
|
|
44
|
+
return {
|
|
45
|
+
name: "index",
|
|
46
|
+
data: {
|
|
47
|
+
name: input.name,
|
|
48
|
+
columns: input.columns,
|
|
49
|
+
...input.unique && { unique: true },
|
|
50
|
+
...input.type && { type: input.type }
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function constraint(input) {
|
|
55
|
+
return {
|
|
56
|
+
name: "constraint",
|
|
57
|
+
data: {
|
|
58
|
+
name: input.name,
|
|
59
|
+
type: input.type,
|
|
60
|
+
...input.columns?.length && { columns: input.columns },
|
|
61
|
+
...input.definition && { definition: input.definition },
|
|
62
|
+
...input.defaultValue && { defaultValue: input.defaultValue },
|
|
63
|
+
...input.referencedTable && { referencedTable: input.referencedTable },
|
|
64
|
+
...input.referencedColumns?.length && {
|
|
65
|
+
referencedColumns: input.referencedColumns
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function view(input) {
|
|
71
|
+
return {
|
|
72
|
+
name: "view",
|
|
73
|
+
data: {
|
|
74
|
+
name: input.name,
|
|
75
|
+
...input.schema && { schema: input.schema },
|
|
76
|
+
columns: input.columns,
|
|
77
|
+
...input.definition && { definition: input.definition }
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function relationship(input) {
|
|
82
|
+
return {
|
|
83
|
+
name: "relationship",
|
|
84
|
+
data: {
|
|
85
|
+
from: input.from,
|
|
86
|
+
to: input.to,
|
|
87
|
+
...input.cardinality && { cardinality: input.cardinality }
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
1
92
|
// packages/text2sql/src/lib/adapters/groundings/context.ts
|
|
2
93
|
function createGroundingContext() {
|
|
3
94
|
return {
|
|
@@ -10,24 +101,169 @@ function createGroundingContext() {
|
|
|
10
101
|
|
|
11
102
|
// packages/text2sql/src/lib/adapters/adapter.ts
|
|
12
103
|
var Adapter = class {
|
|
104
|
+
/**
|
|
105
|
+
* Introspect the database schema and return context fragments.
|
|
106
|
+
*
|
|
107
|
+
* Executes all configured groundings to populate the context, then
|
|
108
|
+
* generates fragments from the complete context data.
|
|
109
|
+
*
|
|
110
|
+
* @param ctx - Optional grounding context for sharing state between groundings
|
|
111
|
+
* @returns Array of context fragments representing the database schema
|
|
112
|
+
*/
|
|
13
113
|
async introspect(ctx = createGroundingContext()) {
|
|
14
|
-
const lines = [];
|
|
15
114
|
for (const fn of this.grounding) {
|
|
16
115
|
const grounding = fn(this);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
116
|
+
await grounding.execute(ctx);
|
|
117
|
+
}
|
|
118
|
+
return this.#toSchemaFragments(ctx);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Convert complete grounding context to schema fragments.
|
|
122
|
+
* Called after all groundings have populated ctx with data.
|
|
123
|
+
*/
|
|
124
|
+
#toSchemaFragments(ctx) {
|
|
125
|
+
const fragments = [];
|
|
126
|
+
if (ctx.info) {
|
|
127
|
+
fragments.push(
|
|
128
|
+
dialectInfo({
|
|
129
|
+
dialect: ctx.info.dialect,
|
|
130
|
+
version: ctx.info.version,
|
|
131
|
+
database: ctx.info.database
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
for (const t of ctx.tables) {
|
|
136
|
+
fragments.push(this.#tableToFragment(t));
|
|
21
137
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
138
|
+
for (const v of ctx.views) {
|
|
139
|
+
fragments.push(this.#viewToFragment(v));
|
|
140
|
+
}
|
|
141
|
+
const tableMap = new Map(ctx.tables.map((t) => [t.name, t]));
|
|
142
|
+
for (const rel of ctx.relationships) {
|
|
143
|
+
const sourceTable = tableMap.get(rel.table);
|
|
144
|
+
const targetTable = tableMap.get(rel.referenced_table);
|
|
145
|
+
fragments.push(
|
|
146
|
+
this.#relationshipToFragment(rel, sourceTable, targetTable)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
if (ctx.report) {
|
|
150
|
+
fragments.push({ name: "businessContext", data: ctx.report });
|
|
151
|
+
}
|
|
152
|
+
return fragments;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Convert a Table to a table fragment with nested column, index, and constraint fragments.
|
|
156
|
+
*/
|
|
157
|
+
#tableToFragment(t) {
|
|
158
|
+
const pkConstraint = t.constraints?.find((c) => c.type === "PRIMARY_KEY");
|
|
159
|
+
const pkColumns = new Set(pkConstraint?.columns ?? []);
|
|
160
|
+
const notNullColumns = new Set(
|
|
161
|
+
t.constraints?.filter((c) => c.type === "NOT_NULL").flatMap((c) => c.columns ?? []) ?? []
|
|
162
|
+
);
|
|
163
|
+
const defaultByColumn = /* @__PURE__ */ new Map();
|
|
164
|
+
for (const c of t.constraints?.filter((c2) => c2.type === "DEFAULT") ?? []) {
|
|
165
|
+
for (const col of c.columns ?? []) {
|
|
166
|
+
if (c.defaultValue != null) {
|
|
167
|
+
defaultByColumn.set(col, c.defaultValue);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const uniqueColumns = new Set(
|
|
172
|
+
t.constraints?.filter((c) => c.type === "UNIQUE" && c.columns?.length === 1).flatMap((c) => c.columns ?? []) ?? []
|
|
173
|
+
);
|
|
174
|
+
const fkByColumn = /* @__PURE__ */ new Map();
|
|
175
|
+
for (const c of t.constraints?.filter((c2) => c2.type === "FOREIGN_KEY") ?? []) {
|
|
176
|
+
const cols = c.columns ?? [];
|
|
177
|
+
const refCols = c.referencedColumns ?? [];
|
|
178
|
+
for (let i = 0; i < cols.length; i++) {
|
|
179
|
+
const refCol = refCols[i] ?? refCols[0] ?? cols[i];
|
|
180
|
+
fkByColumn.set(cols[i], `${c.referencedTable}.${refCol}`);
|
|
26
181
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
182
|
+
}
|
|
183
|
+
const columnFragments = t.columns.map(
|
|
184
|
+
(col) => column({
|
|
185
|
+
name: col.name,
|
|
186
|
+
type: col.type,
|
|
187
|
+
pk: pkColumns.has(col.name) || void 0,
|
|
188
|
+
fk: fkByColumn.get(col.name),
|
|
189
|
+
unique: uniqueColumns.has(col.name) || void 0,
|
|
190
|
+
notNull: notNullColumns.has(col.name) || void 0,
|
|
191
|
+
default: defaultByColumn.get(col.name),
|
|
192
|
+
indexed: col.isIndexed || void 0,
|
|
193
|
+
values: col.values,
|
|
194
|
+
stats: col.stats
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
const indexFragments = (t.indexes ?? []).map(
|
|
198
|
+
(idx) => index({
|
|
199
|
+
name: idx.name,
|
|
200
|
+
columns: idx.columns,
|
|
201
|
+
unique: idx.unique,
|
|
202
|
+
type: idx.type
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
const constraintFragments = (t.constraints ?? []).filter(
|
|
206
|
+
(c) => c.type === "CHECK" || c.type === "UNIQUE" && (c.columns?.length ?? 0) > 1
|
|
207
|
+
).map(
|
|
208
|
+
(c) => constraint({
|
|
209
|
+
name: c.name,
|
|
210
|
+
type: c.type,
|
|
211
|
+
columns: c.columns,
|
|
212
|
+
definition: c.definition
|
|
213
|
+
})
|
|
214
|
+
);
|
|
215
|
+
return table({
|
|
216
|
+
name: t.name,
|
|
217
|
+
schema: t.schema,
|
|
218
|
+
rowCount: t.rowCount,
|
|
219
|
+
sizeHint: t.sizeHint,
|
|
220
|
+
columns: columnFragments,
|
|
221
|
+
indexes: indexFragments.length > 0 ? indexFragments : void 0,
|
|
222
|
+
constraints: constraintFragments.length > 0 ? constraintFragments : void 0
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Convert a View to a view fragment with nested column fragments.
|
|
227
|
+
*/
|
|
228
|
+
#viewToFragment(v) {
|
|
229
|
+
const columnFragments = v.columns.map(
|
|
230
|
+
(col) => column({
|
|
231
|
+
name: col.name,
|
|
232
|
+
type: col.type,
|
|
233
|
+
values: col.values,
|
|
234
|
+
stats: col.stats
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
return view({
|
|
238
|
+
name: v.name,
|
|
239
|
+
schema: v.schema,
|
|
240
|
+
columns: columnFragments,
|
|
241
|
+
definition: v.definition
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Convert a Relationship to a relationship fragment.
|
|
246
|
+
* Infers cardinality from row counts if available.
|
|
247
|
+
*/
|
|
248
|
+
#relationshipToFragment(rel, sourceTable, targetTable) {
|
|
249
|
+
const sourceCount = sourceTable?.rowCount;
|
|
250
|
+
const targetCount = targetTable?.rowCount;
|
|
251
|
+
let cardinality;
|
|
252
|
+
if (sourceCount != null && targetCount != null && targetCount > 0) {
|
|
253
|
+
const ratio = sourceCount / targetCount;
|
|
254
|
+
if (ratio > 5) {
|
|
255
|
+
cardinality = "many-to-one";
|
|
256
|
+
} else if (ratio < 1.2 && ratio > 0.8) {
|
|
257
|
+
cardinality = "one-to-one";
|
|
258
|
+
} else if (ratio < 0.2) {
|
|
259
|
+
cardinality = "one-to-many";
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return relationship({
|
|
263
|
+
from: { table: rel.table, columns: rel.from },
|
|
264
|
+
to: { table: rel.referenced_table, columns: rel.to },
|
|
265
|
+
cardinality
|
|
266
|
+
});
|
|
31
267
|
}
|
|
32
268
|
/**
|
|
33
269
|
* Convert unknown database value to number.
|
|
@@ -83,16 +319,19 @@ ${description}
|
|
|
83
319
|
|
|
84
320
|
// packages/text2sql/src/lib/adapters/groundings/abstract.grounding.ts
|
|
85
321
|
var AbstractGrounding = class {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
322
|
+
/**
|
|
323
|
+
* Grounding identifier for debugging/logging.
|
|
324
|
+
*/
|
|
325
|
+
name;
|
|
326
|
+
constructor(name) {
|
|
327
|
+
this.name = name;
|
|
89
328
|
}
|
|
90
329
|
};
|
|
91
330
|
|
|
92
331
|
// packages/text2sql/src/lib/adapters/groundings/column-stats.grounding.ts
|
|
93
332
|
var ColumnStatsGrounding = class extends AbstractGrounding {
|
|
94
333
|
constructor(config = {}) {
|
|
95
|
-
super("
|
|
334
|
+
super("columnStats");
|
|
96
335
|
}
|
|
97
336
|
/**
|
|
98
337
|
* Execute the grounding process.
|
|
@@ -101,33 +340,29 @@ var ColumnStatsGrounding = class extends AbstractGrounding {
|
|
|
101
340
|
async execute(ctx) {
|
|
102
341
|
const allContainers = [...ctx.tables, ...ctx.views];
|
|
103
342
|
for (const container of allContainers) {
|
|
104
|
-
for (const
|
|
343
|
+
for (const column2 of container.columns) {
|
|
105
344
|
try {
|
|
106
|
-
const stats = await this.collectStats(container.name,
|
|
345
|
+
const stats = await this.collectStats(container.name, column2);
|
|
107
346
|
if (stats) {
|
|
108
|
-
|
|
347
|
+
column2.stats = stats;
|
|
109
348
|
}
|
|
110
349
|
} catch (error) {
|
|
111
350
|
console.warn(
|
|
112
351
|
"Error collecting stats for",
|
|
113
352
|
container.name,
|
|
114
|
-
|
|
353
|
+
column2.name,
|
|
115
354
|
error
|
|
116
355
|
);
|
|
117
356
|
}
|
|
118
357
|
}
|
|
119
358
|
}
|
|
120
|
-
return () => this.#describe();
|
|
121
|
-
}
|
|
122
|
-
#describe() {
|
|
123
|
-
return null;
|
|
124
359
|
}
|
|
125
360
|
};
|
|
126
361
|
|
|
127
362
|
// packages/text2sql/src/lib/adapters/groundings/info.grounding.ts
|
|
128
363
|
var InfoGrounding = class extends AbstractGrounding {
|
|
129
364
|
constructor(config = {}) {
|
|
130
|
-
super("
|
|
365
|
+
super("dialectInfo");
|
|
131
366
|
}
|
|
132
367
|
/**
|
|
133
368
|
* Execute the grounding process.
|
|
@@ -135,17 +370,6 @@ var InfoGrounding = class extends AbstractGrounding {
|
|
|
135
370
|
*/
|
|
136
371
|
async execute(ctx) {
|
|
137
372
|
ctx.info = await this.collectInfo();
|
|
138
|
-
const lines = [`Dialect: ${ctx.info.dialect ?? "unknown"}`];
|
|
139
|
-
if (ctx.info.version) {
|
|
140
|
-
lines.push(`Version: ${ctx.info.version}`);
|
|
141
|
-
}
|
|
142
|
-
if (ctx.info.database) {
|
|
143
|
-
lines.push(`Database: ${ctx.info.database}`);
|
|
144
|
-
}
|
|
145
|
-
if (ctx.info.details && Object.keys(ctx.info.details).length) {
|
|
146
|
-
lines.push(`Details: ${JSON.stringify(ctx.info.details)}`);
|
|
147
|
-
}
|
|
148
|
-
return () => lines.join("\n");
|
|
149
373
|
}
|
|
150
374
|
};
|
|
151
375
|
|
|
@@ -153,7 +377,7 @@ var InfoGrounding = class extends AbstractGrounding {
|
|
|
153
377
|
var ColumnValuesGrounding = class extends AbstractGrounding {
|
|
154
378
|
lowCardinalityLimit;
|
|
155
379
|
constructor(config = {}) {
|
|
156
|
-
super("
|
|
380
|
+
super("columnValues");
|
|
157
381
|
this.lowCardinalityLimit = config.lowCardinalityLimit ?? 20;
|
|
158
382
|
}
|
|
159
383
|
/**
|
|
@@ -171,14 +395,14 @@ var ColumnValuesGrounding = class extends AbstractGrounding {
|
|
|
171
395
|
* - CHECK ((status)::text = ANY (ARRAY['a'::text, 'b'::text]))
|
|
172
396
|
* - CHECK (status = 'active' OR status = 'inactive')
|
|
173
397
|
*/
|
|
174
|
-
parseCheckConstraint(
|
|
175
|
-
if (
|
|
398
|
+
parseCheckConstraint(constraint2, columnName) {
|
|
399
|
+
if (constraint2.type !== "CHECK" || !constraint2.definition) {
|
|
176
400
|
return void 0;
|
|
177
401
|
}
|
|
178
|
-
if (
|
|
402
|
+
if (constraint2.columns && !constraint2.columns.includes(columnName)) {
|
|
179
403
|
return void 0;
|
|
180
404
|
}
|
|
181
|
-
const def =
|
|
405
|
+
const def = constraint2.definition;
|
|
182
406
|
const escapedCol = this.escapeRegex(columnName);
|
|
183
407
|
const colPattern = `(?:\\(?\\(?${escapedCol}\\)?(?:::(?:text|varchar|character varying))?\\)?)`;
|
|
184
408
|
const inMatch = def.match(
|
|
@@ -236,55 +460,51 @@ var ColumnValuesGrounding = class extends AbstractGrounding {
|
|
|
236
460
|
async execute(ctx) {
|
|
237
461
|
const allContainers = [...ctx.tables, ...ctx.views];
|
|
238
462
|
for (const container of allContainers) {
|
|
239
|
-
const
|
|
240
|
-
for (const
|
|
463
|
+
const table2 = this.getTable(ctx, container.name);
|
|
464
|
+
for (const column2 of container.columns) {
|
|
241
465
|
try {
|
|
242
466
|
const result = await this.resolveColumnValues(
|
|
243
467
|
container.name,
|
|
244
|
-
|
|
245
|
-
|
|
468
|
+
column2,
|
|
469
|
+
table2?.constraints
|
|
246
470
|
);
|
|
247
471
|
if (result) {
|
|
248
|
-
|
|
249
|
-
|
|
472
|
+
column2.kind = result.kind;
|
|
473
|
+
column2.values = result.values;
|
|
250
474
|
}
|
|
251
475
|
} catch (error) {
|
|
252
476
|
console.warn(
|
|
253
477
|
"Error collecting column values for",
|
|
254
478
|
container.name,
|
|
255
|
-
|
|
479
|
+
column2.name,
|
|
256
480
|
error
|
|
257
481
|
);
|
|
258
482
|
}
|
|
259
483
|
}
|
|
260
484
|
}
|
|
261
|
-
return () => this.#describe();
|
|
262
485
|
}
|
|
263
486
|
/**
|
|
264
487
|
* Resolve column values from all sources in priority order.
|
|
265
488
|
*/
|
|
266
|
-
async resolveColumnValues(tableName,
|
|
267
|
-
const enumValues = await this.collectEnumValues(tableName,
|
|
489
|
+
async resolveColumnValues(tableName, column2, constraints) {
|
|
490
|
+
const enumValues = await this.collectEnumValues(tableName, column2);
|
|
268
491
|
if (enumValues?.length) {
|
|
269
492
|
return { kind: "Enum", values: enumValues };
|
|
270
493
|
}
|
|
271
494
|
if (constraints) {
|
|
272
|
-
for (const
|
|
273
|
-
const checkValues = this.parseCheckConstraint(
|
|
495
|
+
for (const constraint2 of constraints) {
|
|
496
|
+
const checkValues = this.parseCheckConstraint(constraint2, column2.name);
|
|
274
497
|
if (checkValues?.length) {
|
|
275
498
|
return { kind: "Enum", values: checkValues };
|
|
276
499
|
}
|
|
277
500
|
}
|
|
278
501
|
}
|
|
279
|
-
const lowCardValues = await this.collectLowCardinality(tableName,
|
|
502
|
+
const lowCardValues = await this.collectLowCardinality(tableName, column2);
|
|
280
503
|
if (lowCardValues?.length) {
|
|
281
504
|
return { kind: "LowCardinality", values: lowCardValues };
|
|
282
505
|
}
|
|
283
506
|
return void 0;
|
|
284
507
|
}
|
|
285
|
-
#describe() {
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
508
|
};
|
|
289
509
|
|
|
290
510
|
// packages/text2sql/src/lib/adapters/groundings/report.grounding.ts
|
|
@@ -343,21 +563,20 @@ var reportAgent = agent({
|
|
|
343
563
|
// packages/text2sql/src/lib/adapters/groundings/row-count.grounding.ts
|
|
344
564
|
var RowCountGrounding = class extends AbstractGrounding {
|
|
345
565
|
constructor(config = {}) {
|
|
346
|
-
super("
|
|
566
|
+
super("rowCount");
|
|
347
567
|
}
|
|
348
568
|
/**
|
|
349
569
|
* Execute the grounding process.
|
|
350
570
|
* Annotates tables in ctx.tables with row counts and size hints.
|
|
351
571
|
*/
|
|
352
572
|
async execute(ctx) {
|
|
353
|
-
for (const
|
|
354
|
-
const count = await this.getRowCount(
|
|
573
|
+
for (const table2 of ctx.tables) {
|
|
574
|
+
const count = await this.getRowCount(table2.name);
|
|
355
575
|
if (count != null) {
|
|
356
|
-
|
|
357
|
-
|
|
576
|
+
table2.rowCount = count;
|
|
577
|
+
table2.sizeHint = this.#classifyRowCount(count);
|
|
358
578
|
}
|
|
359
579
|
}
|
|
360
|
-
return () => null;
|
|
361
580
|
}
|
|
362
581
|
/**
|
|
363
582
|
* Classify row count into a size hint category.
|
|
@@ -372,13 +591,12 @@ var RowCountGrounding = class extends AbstractGrounding {
|
|
|
372
591
|
};
|
|
373
592
|
|
|
374
593
|
// packages/text2sql/src/lib/adapters/groundings/table.grounding.ts
|
|
375
|
-
import pluralize from "pluralize";
|
|
376
594
|
var TableGrounding = class extends AbstractGrounding {
|
|
377
595
|
#filter;
|
|
378
596
|
#forward;
|
|
379
597
|
#backward;
|
|
380
598
|
constructor(config = {}) {
|
|
381
|
-
super("
|
|
599
|
+
super("table");
|
|
382
600
|
this.#filter = config.filter;
|
|
383
601
|
this.#forward = config.forward;
|
|
384
602
|
this.#backward = config.backward;
|
|
@@ -396,7 +614,7 @@ var TableGrounding = class extends AbstractGrounding {
|
|
|
396
614
|
seedTables.map((name) => this.getTable(name))
|
|
397
615
|
);
|
|
398
616
|
ctx.tables.push(...tables3);
|
|
399
|
-
return
|
|
617
|
+
return;
|
|
400
618
|
}
|
|
401
619
|
const tables2 = {};
|
|
402
620
|
const allRelationships = [];
|
|
@@ -452,7 +670,6 @@ var TableGrounding = class extends AbstractGrounding {
|
|
|
452
670
|
const tablesList = Object.values(tables2);
|
|
453
671
|
ctx.tables.push(...tablesList);
|
|
454
672
|
ctx.relationships.push(...allRelationships);
|
|
455
|
-
return () => this.#describeTables(tablesList);
|
|
456
673
|
}
|
|
457
674
|
/**
|
|
458
675
|
* Apply the filter to get seed table names.
|
|
@@ -482,156 +699,6 @@ var TableGrounding = class extends AbstractGrounding {
|
|
|
482
699
|
all.push(rel);
|
|
483
700
|
}
|
|
484
701
|
}
|
|
485
|
-
#describeTables(tables2) {
|
|
486
|
-
if (!tables2.length) {
|
|
487
|
-
return "Schema unavailable.";
|
|
488
|
-
}
|
|
489
|
-
return tables2.map((table) => {
|
|
490
|
-
const rowCountInfo = table.rowCount != null ? ` [rows: ${table.rowCount}${table.sizeHint ? `, size: ${table.sizeHint}` : ""}]` : "";
|
|
491
|
-
const pkConstraint = table.constraints?.find(
|
|
492
|
-
(c) => c.type === "PRIMARY_KEY"
|
|
493
|
-
);
|
|
494
|
-
const pkColumns = new Set(pkConstraint?.columns ?? []);
|
|
495
|
-
const notNullColumns = new Set(
|
|
496
|
-
table.constraints?.filter((c) => c.type === "NOT_NULL").flatMap((c) => c.columns ?? []) ?? []
|
|
497
|
-
);
|
|
498
|
-
const defaultByColumn = /* @__PURE__ */ new Map();
|
|
499
|
-
for (const c of table.constraints?.filter(
|
|
500
|
-
(c2) => c2.type === "DEFAULT"
|
|
501
|
-
) ?? []) {
|
|
502
|
-
for (const col of c.columns ?? []) {
|
|
503
|
-
if (c.defaultValue != null) {
|
|
504
|
-
defaultByColumn.set(col, c.defaultValue);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
const uniqueColumns = new Set(
|
|
509
|
-
table.constraints?.filter((c) => c.type === "UNIQUE" && c.columns?.length === 1).flatMap((c) => c.columns ?? []) ?? []
|
|
510
|
-
);
|
|
511
|
-
const fkByColumn = /* @__PURE__ */ new Map();
|
|
512
|
-
for (const c of table.constraints?.filter(
|
|
513
|
-
(c2) => c2.type === "FOREIGN_KEY"
|
|
514
|
-
) ?? []) {
|
|
515
|
-
const cols = c.columns ?? [];
|
|
516
|
-
const refCols = c.referencedColumns ?? [];
|
|
517
|
-
for (let i = 0; i < cols.length; i++) {
|
|
518
|
-
const refCol = refCols[i] ?? refCols[0] ?? cols[i];
|
|
519
|
-
fkByColumn.set(cols[i], `${c.referencedTable}.${refCol}`);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
const columns = table.columns.map((column) => {
|
|
523
|
-
const annotations = [];
|
|
524
|
-
const isPrimaryKey = pkColumns.has(column.name);
|
|
525
|
-
if (isPrimaryKey) {
|
|
526
|
-
annotations.push("PK");
|
|
527
|
-
}
|
|
528
|
-
if (fkByColumn.has(column.name)) {
|
|
529
|
-
annotations.push(`FK -> ${fkByColumn.get(column.name)}`);
|
|
530
|
-
}
|
|
531
|
-
if (uniqueColumns.has(column.name)) {
|
|
532
|
-
annotations.push("UNIQUE");
|
|
533
|
-
}
|
|
534
|
-
if (notNullColumns.has(column.name)) {
|
|
535
|
-
annotations.push("NOT NULL");
|
|
536
|
-
}
|
|
537
|
-
if (defaultByColumn.has(column.name)) {
|
|
538
|
-
annotations.push(`DEFAULT: ${defaultByColumn.get(column.name)}`);
|
|
539
|
-
}
|
|
540
|
-
if (column.isIndexed && !isPrimaryKey) {
|
|
541
|
-
annotations.push("Indexed");
|
|
542
|
-
}
|
|
543
|
-
if (column.kind === "Enum" && column.values?.length) {
|
|
544
|
-
annotations.push(`Enum: ${column.values.join(", ")}`);
|
|
545
|
-
} else if (column.kind === "LowCardinality" && column.values?.length) {
|
|
546
|
-
annotations.push(`LowCardinality: ${column.values.join(", ")}`);
|
|
547
|
-
}
|
|
548
|
-
if (column.stats) {
|
|
549
|
-
const statParts = [];
|
|
550
|
-
if (column.stats.min != null || column.stats.max != null) {
|
|
551
|
-
const minText = column.stats.min ?? "n/a";
|
|
552
|
-
const maxText = column.stats.max ?? "n/a";
|
|
553
|
-
statParts.push(`range ${minText} \u2192 ${maxText}`);
|
|
554
|
-
}
|
|
555
|
-
if (column.stats.nullFraction != null && Number.isFinite(column.stats.nullFraction)) {
|
|
556
|
-
const percent = Math.round(column.stats.nullFraction * 1e3) / 10;
|
|
557
|
-
statParts.push(`null\u2248${percent}%`);
|
|
558
|
-
}
|
|
559
|
-
if (statParts.length) {
|
|
560
|
-
annotations.push(statParts.join(", "));
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
const annotationText = annotations.length ? ` [${annotations.join(", ")}]` : "";
|
|
564
|
-
return ` - ${column.name} (${column.type})${annotationText}`;
|
|
565
|
-
}).join("\n");
|
|
566
|
-
const indexes = table.indexes?.length ? `
|
|
567
|
-
Indexes:
|
|
568
|
-
${table.indexes.map((index) => {
|
|
569
|
-
const props = [];
|
|
570
|
-
if (index.unique) {
|
|
571
|
-
props.push("UNIQUE");
|
|
572
|
-
}
|
|
573
|
-
if (index.type) {
|
|
574
|
-
props.push(index.type);
|
|
575
|
-
}
|
|
576
|
-
const propsText = props.length ? ` (${props.join(", ")})` : "";
|
|
577
|
-
const columnsText = index.columns?.length ? index.columns.join(", ") : "expression";
|
|
578
|
-
return ` - ${index.name}${propsText}: ${columnsText}`;
|
|
579
|
-
}).join("\n")}` : "";
|
|
580
|
-
const multiColumnUniques = table.constraints?.filter(
|
|
581
|
-
(c) => c.type === "UNIQUE" && (c.columns?.length ?? 0) > 1
|
|
582
|
-
) ?? [];
|
|
583
|
-
const uniqueConstraints = multiColumnUniques.length ? `
|
|
584
|
-
Unique Constraints:
|
|
585
|
-
${multiColumnUniques.map((c) => ` - ${c.name}: (${c.columns?.join(", ")})`).join("\n")}` : "";
|
|
586
|
-
const checkConstraints = table.constraints?.filter((c) => c.type === "CHECK") ?? [];
|
|
587
|
-
const checks = checkConstraints.length ? `
|
|
588
|
-
Check Constraints:
|
|
589
|
-
${checkConstraints.map((c) => ` - ${c.name}: ${c.definition}`).join("\n")}` : "";
|
|
590
|
-
return `- Table: ${table.name}${rowCountInfo}
|
|
591
|
-
Columns:
|
|
592
|
-
${columns}${indexes}${uniqueConstraints}${checks}`;
|
|
593
|
-
}).join("\n\n");
|
|
594
|
-
}
|
|
595
|
-
#formatTableLabel = (tableName) => {
|
|
596
|
-
const base = tableName.split(".").pop() ?? tableName;
|
|
597
|
-
return base.replace(/_/g, " ");
|
|
598
|
-
};
|
|
599
|
-
#describeRelationships = (tables2, relationships) => {
|
|
600
|
-
if (!relationships.length) {
|
|
601
|
-
return "None detected";
|
|
602
|
-
}
|
|
603
|
-
const tableMap = new Map(tables2.map((table) => [table.name, table]));
|
|
604
|
-
return relationships.map((relationship) => {
|
|
605
|
-
const sourceLabel = this.#formatTableLabel(relationship.table);
|
|
606
|
-
const targetLabel = this.#formatTableLabel(
|
|
607
|
-
relationship.referenced_table
|
|
608
|
-
);
|
|
609
|
-
const singularSource = pluralize.singular(sourceLabel);
|
|
610
|
-
const pluralSource = pluralize.plural(sourceLabel);
|
|
611
|
-
const singularTarget = pluralize.singular(targetLabel);
|
|
612
|
-
const pluralTarget = pluralize.plural(targetLabel);
|
|
613
|
-
const sourceTable = tableMap.get(relationship.table);
|
|
614
|
-
const targetTable = tableMap.get(relationship.referenced_table);
|
|
615
|
-
const sourceCount = sourceTable?.rowCount;
|
|
616
|
-
const targetCount = targetTable?.rowCount;
|
|
617
|
-
const ratio = sourceCount != null && targetCount != null && targetCount > 0 ? sourceCount / targetCount : null;
|
|
618
|
-
let cardinality = "each";
|
|
619
|
-
if (ratio != null) {
|
|
620
|
-
if (ratio > 5) {
|
|
621
|
-
cardinality = `many-to-one (\u2248${sourceCount} vs ${targetCount})`;
|
|
622
|
-
} else if (ratio < 1.2 && ratio > 0.8) {
|
|
623
|
-
cardinality = `roughly 1:1 (${sourceCount} vs ${targetCount})`;
|
|
624
|
-
} else if (ratio < 0.2) {
|
|
625
|
-
cardinality = `one-to-many (${sourceCount} vs ${targetCount})`;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
const mappings = relationship.from.map((fromCol, idx) => {
|
|
629
|
-
const targetCol = relationship.to[idx] ?? relationship.to[0] ?? fromCol;
|
|
630
|
-
return `${relationship.table}.${fromCol} -> ${relationship.referenced_table}.${targetCol}`;
|
|
631
|
-
}).join(", ");
|
|
632
|
-
return `- ${relationship.table} (${relationship.from.join(", ")}) -> ${relationship.referenced_table} (${relationship.to.join(", ")}) [${cardinality}]`;
|
|
633
|
-
}).join("\n");
|
|
634
|
-
};
|
|
635
702
|
};
|
|
636
703
|
|
|
637
704
|
// packages/text2sql/src/lib/adapters/sqlite/column-stats.sqlite.grounding.ts
|
|
@@ -641,12 +708,12 @@ var SqliteColumnStatsGrounding = class extends ColumnStatsGrounding {
|
|
|
641
708
|
super(config);
|
|
642
709
|
this.#adapter = adapter;
|
|
643
710
|
}
|
|
644
|
-
async collectStats(tableName,
|
|
645
|
-
if (!this.#shouldCollectStats(
|
|
711
|
+
async collectStats(tableName, column2) {
|
|
712
|
+
if (!this.#shouldCollectStats(column2.type)) {
|
|
646
713
|
return void 0;
|
|
647
714
|
}
|
|
648
715
|
const tableIdentifier = this.#adapter.quoteIdentifier(tableName);
|
|
649
|
-
const columnIdentifier = this.#adapter.quoteIdentifier(
|
|
716
|
+
const columnIdentifier = this.#adapter.quoteIdentifier(column2.name);
|
|
650
717
|
const sql = `
|
|
651
718
|
SELECT
|
|
652
719
|
MIN(${columnIdentifier}) AS min_value,
|
|
@@ -730,9 +797,9 @@ var SqliteColumnValuesGrounding = class extends ColumnValuesGrounding {
|
|
|
730
797
|
super(config);
|
|
731
798
|
this.#adapter = adapter;
|
|
732
799
|
}
|
|
733
|
-
async collectLowCardinality(tableName,
|
|
800
|
+
async collectLowCardinality(tableName, column2) {
|
|
734
801
|
const tableIdentifier = this.#adapter.quoteIdentifier(tableName);
|
|
735
|
-
const columnIdentifier = this.#adapter.quoteIdentifier(
|
|
802
|
+
const columnIdentifier = this.#adapter.quoteIdentifier(column2.name);
|
|
736
803
|
const limit = this.lowCardinalityLimit + 1;
|
|
737
804
|
const sql = `
|
|
738
805
|
SELECT DISTINCT ${columnIdentifier} AS value
|