@negusdev/dbask 0.0.0-stage → 0.1.8
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/CHANGELOG.md +40 -0
- package/LICENSE +15 -0
- package/README.md +422 -2
- package/dist/ai/factory.d.ts +4 -0
- package/dist/ai/factory.d.ts.map +1 -0
- package/dist/ai/factory.js +55 -0
- package/dist/ai/factory.js.map +1 -0
- package/dist/ai/provider.d.ts +13 -0
- package/dist/ai/provider.d.ts.map +1 -0
- package/dist/ai/provider.js +2 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/ai/sdk-provider.d.ts +13 -0
- package/dist/ai/sdk-provider.d.ts.map +1 -0
- package/dist/ai/sdk-provider.js +36 -0
- package/dist/ai/sdk-provider.js.map +1 -0
- package/dist/cli-args.d.ts +26 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +72 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-observer.d.ts +23 -0
- package/dist/cli-observer.d.ts.map +1 -0
- package/dist/cli-observer.js +224 -0
- package/dist/cli-observer.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +127 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +247 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/validate.d.ts +31 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +205 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config/config.d.ts +42 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +94 -0
- package/dist/config/config.js.map +1 -0
- package/dist/context/db-context.d.ts +12 -0
- package/dist/context/db-context.d.ts.map +1 -0
- package/dist/context/db-context.js +29 -0
- package/dist/context/db-context.js.map +1 -0
- package/dist/core/agent/agent.d.ts +57 -0
- package/dist/core/agent/agent.d.ts.map +1 -0
- package/dist/core/agent/agent.js +518 -0
- package/dist/core/agent/agent.js.map +1 -0
- package/dist/core/agent/index.d.ts +4 -0
- package/dist/core/agent/index.d.ts.map +1 -0
- package/dist/core/agent/index.js +2 -0
- package/dist/core/agent/index.js.map +1 -0
- package/dist/core/agent/observability.d.ts +19 -0
- package/dist/core/agent/observability.d.ts.map +1 -0
- package/dist/core/agent/observability.js +4 -0
- package/dist/core/agent/observability.js.map +1 -0
- package/dist/core/agent/query-plan.d.ts +68 -0
- package/dist/core/agent/query-plan.d.ts.map +1 -0
- package/dist/core/agent/query-plan.js +282 -0
- package/dist/core/agent/query-plan.js.map +1 -0
- package/dist/core/tools/describe-table.d.ts +6 -0
- package/dist/core/tools/describe-table.d.ts.map +1 -0
- package/dist/core/tools/describe-table.js +25 -0
- package/dist/core/tools/describe-table.js.map +1 -0
- package/dist/core/tools/describe-tables.d.ts +6 -0
- package/dist/core/tools/describe-tables.d.ts.map +1 -0
- package/dist/core/tools/describe-tables.js +22 -0
- package/dist/core/tools/describe-tables.js.map +1 -0
- package/dist/core/tools/execute-query.d.ts +6 -0
- package/dist/core/tools/execute-query.d.ts.map +1 -0
- package/dist/core/tools/execute-query.js +31 -0
- package/dist/core/tools/execute-query.js.map +1 -0
- package/dist/core/tools/explain-query.d.ts +10 -0
- package/dist/core/tools/explain-query.d.ts.map +1 -0
- package/dist/core/tools/explain-query.js +34 -0
- package/dist/core/tools/explain-query.js.map +1 -0
- package/dist/core/tools/get-relationships.d.ts +6 -0
- package/dist/core/tools/get-relationships.d.ts.map +1 -0
- package/dist/core/tools/get-relationships.js +23 -0
- package/dist/core/tools/get-relationships.js.map +1 -0
- package/dist/core/tools/index.d.ts +9 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +8 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/list-tables.d.ts +3 -0
- package/dist/core/tools/list-tables.d.ts.map +1 -0
- package/dist/core/tools/list-tables.js +18 -0
- package/dist/core/tools/list-tables.js.map +1 -0
- package/dist/core/tools/registry.d.ts +11 -0
- package/dist/core/tools/registry.d.ts.map +1 -0
- package/dist/core/tools/registry.js +48 -0
- package/dist/core/tools/registry.js.map +1 -0
- package/dist/core/types/index.d.ts +102 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/core/types/index.js +6 -0
- package/dist/core/types/index.js.map +1 -0
- package/dist/database/adapter.d.ts +3 -0
- package/dist/database/adapter.d.ts.map +1 -0
- package/dist/database/adapter.js +2 -0
- package/dist/database/adapter.js.map +1 -0
- package/dist/database/factory.d.ts +16 -0
- package/dist/database/factory.d.ts.map +1 -0
- package/dist/database/factory.js +27 -0
- package/dist/database/factory.js.map +1 -0
- package/dist/database/index.d.ts +8 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +4 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/mysql/adapter.d.ts +26 -0
- package/dist/database/mysql/adapter.d.ts.map +1 -0
- package/dist/database/mysql/adapter.js +131 -0
- package/dist/database/mysql/adapter.js.map +1 -0
- package/dist/database/postgres/adapter.d.ts +60 -0
- package/dist/database/postgres/adapter.d.ts.map +1 -0
- package/dist/database/postgres/adapter.js +307 -0
- package/dist/database/postgres/adapter.js.map +1 -0
- package/dist/database/result-limits.d.ts +17 -0
- package/dist/database/result-limits.d.ts.map +1 -0
- package/dist/database/result-limits.js +26 -0
- package/dist/database/result-limits.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/safety/limits.d.ts +7 -0
- package/dist/safety/limits.d.ts.map +1 -0
- package/dist/safety/limits.js +15 -0
- package/dist/safety/limits.js.map +1 -0
- package/dist/safety/policy.d.ts +8 -0
- package/dist/safety/policy.d.ts.map +1 -0
- package/dist/safety/policy.js +11 -0
- package/dist/safety/policy.js.map +1 -0
- package/dist/safety/sql-tokenizer.d.ts +49 -0
- package/dist/safety/sql-tokenizer.d.ts.map +1 -0
- package/dist/safety/sql-tokenizer.js +240 -0
- package/dist/safety/sql-tokenizer.js.map +1 -0
- package/dist/safety/sql-validator.d.ts +34 -0
- package/dist/safety/sql-validator.d.ts.map +1 -0
- package/dist/safety/sql-validator.js +270 -0
- package/dist/safety/sql-validator.js.map +1 -0
- package/dist/schema/cache.d.ts +24 -0
- package/dist/schema/cache.d.ts.map +1 -0
- package/dist/schema/cache.js +57 -0
- package/dist/schema/cache.js.map +1 -0
- package/dist/ui/markdown.d.ts +8 -0
- package/dist/ui/markdown.d.ts.map +1 -0
- package/dist/ui/markdown.js +205 -0
- package/dist/ui/markdown.js.map +1 -0
- package/dist/ui/spinner.d.ts +32 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +74 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/sql-highlight.d.ts +4 -0
- package/dist/ui/sql-highlight.d.ts.map +1 -0
- package/dist/ui/sql-highlight.js +28 -0
- package/dist/ui/sql-highlight.js.map +1 -0
- package/dist/ui/style.d.ts +38 -0
- package/dist/ui/style.d.ts.map +1 -0
- package/dist/ui/style.js +69 -0
- package/dist/ui/style.js.map +1 -0
- package/package.json +91 -4
- package/sql-ai.example.md +32 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { RelationshipInfo, SqlDialect, TableInfo, TableSchema } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* The plan the model must submit before it may run SQL. Tables and columns are
|
|
5
|
+
* structured so they can be checked against the real schema instead of being
|
|
6
|
+
* free text nobody reads.
|
|
7
|
+
*/
|
|
8
|
+
export declare const queryPlanSchema: z.ZodObject<{
|
|
9
|
+
objective: z.ZodString;
|
|
10
|
+
tables: z.ZodArray<z.ZodString>;
|
|
11
|
+
fields: z.ZodArray<z.ZodObject<{
|
|
12
|
+
table: z.ZodString;
|
|
13
|
+
column: z.ZodString;
|
|
14
|
+
}, z.core.$strip>>;
|
|
15
|
+
filters: z.ZodArray<z.ZodString>;
|
|
16
|
+
joins: z.ZodArray<z.ZodObject<{
|
|
17
|
+
left: z.ZodObject<{
|
|
18
|
+
table: z.ZodString;
|
|
19
|
+
column: z.ZodString;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
right: z.ZodObject<{
|
|
22
|
+
table: z.ZodString;
|
|
23
|
+
column: z.ZodString;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
aggregations: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
27
|
+
sorting: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
/** Named to avoid clashing with the EXPLAIN `QueryPlan` in core/types. */
|
|
30
|
+
export type StructuredQueryPlan = z.infer<typeof queryPlanSchema>;
|
|
31
|
+
export interface SchemaFacts {
|
|
32
|
+
dialect: SqlDialect;
|
|
33
|
+
tables: TableInfo[];
|
|
34
|
+
relationships: RelationshipInfo[];
|
|
35
|
+
describe(table: TableInfo): Promise<TableSchema>;
|
|
36
|
+
}
|
|
37
|
+
export interface PlanValidation {
|
|
38
|
+
valid: boolean;
|
|
39
|
+
errors: string[];
|
|
40
|
+
warnings: string[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Checks a plan against the live schema: every table exists, every column
|
|
44
|
+
* exists, fields and joins only touch planned tables, and the planned tables
|
|
45
|
+
* form one connected join graph (no accidental cross joins). Joins that are not
|
|
46
|
+
* a declared foreign key are allowed but reported as warnings.
|
|
47
|
+
*/
|
|
48
|
+
export declare function validatePlan(plan: StructuredQueryPlan, facts: SchemaFacts): Promise<PlanValidation>;
|
|
49
|
+
export interface TableReferences {
|
|
50
|
+
/** Lower-cased bare table names referenced in FROM / JOIN positions. */
|
|
51
|
+
tables: string[];
|
|
52
|
+
/** Names defined by WITH clauses; these are not real tables. */
|
|
53
|
+
ctes: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extracts the tables a SELECT reads. Handles quoting, schema qualification,
|
|
57
|
+
* comma lists, joins, subqueries and CTE names. Returns an empty result when
|
|
58
|
+
* the SQL cannot be tokenized; the SQL validator reports that failure itself.
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractTableReferences(sql: string, dialect: SqlDialect): TableReferences;
|
|
61
|
+
export interface PlanSqlCheck {
|
|
62
|
+
ok: boolean;
|
|
63
|
+
/** Tables used by the SQL that the plan does not list. */
|
|
64
|
+
unplanned: string[];
|
|
65
|
+
}
|
|
66
|
+
/** The SQL may only read tables that the accepted plan listed. */
|
|
67
|
+
export declare function checkSqlFollowsPlan(sql: string, plan: StructuredQueryPlan, dialect: SqlDialect): PlanSqlCheck;
|
|
68
|
+
//# sourceMappingURL=query-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-plan.d.ts","sourceRoot":"","sources":["../../../src/core/agent/query-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAO3B;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;iBAmB1B,CAAC;AAEH,0EAA0E;AAC1E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAElE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgBD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,mBAAmB,EACzB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,cAAc,CAAC,CA+GzB;AAED,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gEAAgE;IAChE,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAsBD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,eAAe,CAuHxF;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,0DAA0D;IAC1D,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,kEAAkE;AAClE,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,UAAU,GAClB,YAAY,CAad"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { tokenizeSql } from '../../safety/sql-tokenizer.js';
|
|
3
|
+
const columnRef = z.object({
|
|
4
|
+
table: z.string().trim().min(1),
|
|
5
|
+
column: z.string().trim().min(1),
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* The plan the model must submit before it may run SQL. Tables and columns are
|
|
9
|
+
* structured so they can be checked against the real schema instead of being
|
|
10
|
+
* free text nobody reads.
|
|
11
|
+
*/
|
|
12
|
+
export const queryPlanSchema = z.object({
|
|
13
|
+
objective: z.string().trim().min(1).max(500),
|
|
14
|
+
tables: z.array(z.string().trim().min(1)).min(1).max(20),
|
|
15
|
+
fields: z
|
|
16
|
+
.array(columnRef)
|
|
17
|
+
.max(40)
|
|
18
|
+
.describe('Columns the query reads or returns, each as {table, column}.'),
|
|
19
|
+
filters: z.array(z.string().trim().min(1)).max(30),
|
|
20
|
+
joins: z
|
|
21
|
+
.array(z.object({
|
|
22
|
+
left: columnRef,
|
|
23
|
+
right: columnRef,
|
|
24
|
+
}))
|
|
25
|
+
.max(20)
|
|
26
|
+
.describe('One entry per join condition: {left:{table,column}, right:{table,column}}.'),
|
|
27
|
+
aggregations: z.array(z.string().trim().min(1)).max(20).optional(),
|
|
28
|
+
sorting: z.array(z.string().trim().min(1)).max(20).optional(),
|
|
29
|
+
});
|
|
30
|
+
const lower = (value) => value.toLowerCase();
|
|
31
|
+
function qualified(table) {
|
|
32
|
+
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
33
|
+
}
|
|
34
|
+
function findTable(tables, name) {
|
|
35
|
+
const wanted = lower(name);
|
|
36
|
+
const exact = tables.filter((table) => lower(qualified(table)) === wanted || lower(table.name) === wanted);
|
|
37
|
+
return exact[0];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Checks a plan against the live schema: every table exists, every column
|
|
41
|
+
* exists, fields and joins only touch planned tables, and the planned tables
|
|
42
|
+
* form one connected join graph (no accidental cross joins). Joins that are not
|
|
43
|
+
* a declared foreign key are allowed but reported as warnings.
|
|
44
|
+
*/
|
|
45
|
+
export async function validatePlan(plan, facts) {
|
|
46
|
+
const errors = [];
|
|
47
|
+
const warnings = [];
|
|
48
|
+
const resolved = new Map();
|
|
49
|
+
const unknown = [];
|
|
50
|
+
for (const name of plan.tables) {
|
|
51
|
+
const table = findTable(facts.tables, name);
|
|
52
|
+
if (table)
|
|
53
|
+
resolved.set(lower(name), table);
|
|
54
|
+
else
|
|
55
|
+
unknown.push(name);
|
|
56
|
+
}
|
|
57
|
+
if (unknown.length > 0) {
|
|
58
|
+
errors.push(`Unknown table${unknown.length === 1 ? '' : 's'}: ${unknown.join(', ')}. Available tables: ${facts.tables.slice(0, 40).map(qualified).join(', ')}${facts.tables.length > 40 ? ', ...' : ''}.`);
|
|
59
|
+
}
|
|
60
|
+
const columns = new Map();
|
|
61
|
+
for (const [key, table] of resolved) {
|
|
62
|
+
try {
|
|
63
|
+
const schema = await facts.describe(table);
|
|
64
|
+
columns.set(key, new Set(schema.columns.map((column) => lower(column.name))));
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
errors.push(`Could not describe table ${qualified(table)}: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const checkRef = (ref, where) => {
|
|
71
|
+
const key = lower(ref.table);
|
|
72
|
+
if (!resolved.has(key)) {
|
|
73
|
+
if (!unknown.some((name) => lower(name) === key)) {
|
|
74
|
+
errors.push(`${where} refers to ${ref.table}.${ref.column}, but ${ref.table} is not listed in "tables".`);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const known = columns.get(key);
|
|
79
|
+
if (known && !known.has(lower(ref.column))) {
|
|
80
|
+
errors.push(`${where} refers to ${ref.table}.${ref.column}, but ${ref.table} has no column "${ref.column}".`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
plan.fields.forEach((field) => checkRef(field, 'Field'));
|
|
84
|
+
plan.joins.forEach((join) => {
|
|
85
|
+
checkRef(join.left, 'Join');
|
|
86
|
+
checkRef(join.right, 'Join');
|
|
87
|
+
});
|
|
88
|
+
// Connectivity: every planned table must be reachable through the joins.
|
|
89
|
+
const parent = new Map();
|
|
90
|
+
const find = (key) => {
|
|
91
|
+
let root = key;
|
|
92
|
+
while (parent.get(root) !== root)
|
|
93
|
+
root = parent.get(root) ?? root;
|
|
94
|
+
return root;
|
|
95
|
+
};
|
|
96
|
+
for (const key of resolved.keys())
|
|
97
|
+
parent.set(key, key);
|
|
98
|
+
for (const join of plan.joins) {
|
|
99
|
+
const a = lower(join.left.table);
|
|
100
|
+
const b = lower(join.right.table);
|
|
101
|
+
if (parent.has(a) && parent.has(b))
|
|
102
|
+
parent.set(find(a), find(b));
|
|
103
|
+
}
|
|
104
|
+
if (resolved.size > 1) {
|
|
105
|
+
const roots = new Set([...resolved.keys()].map(find));
|
|
106
|
+
if (roots.size > 1) {
|
|
107
|
+
const groups = new Map();
|
|
108
|
+
for (const key of resolved.keys()) {
|
|
109
|
+
const root = find(key);
|
|
110
|
+
groups.set(root, [...(groups.get(root) ?? []), key]);
|
|
111
|
+
}
|
|
112
|
+
errors.push(`The planned tables are not connected by joins (${[...groups.values()].map((g) => g.join('+')).join(' | ')}). Add the join conditions that connect them, or remove tables the query does not need.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Joins that are not a declared foreign key: allowed, but flagged.
|
|
116
|
+
for (const join of plan.joins) {
|
|
117
|
+
const left = resolved.get(lower(join.left.table));
|
|
118
|
+
const right = resolved.get(lower(join.right.table));
|
|
119
|
+
if (!left || !right)
|
|
120
|
+
continue;
|
|
121
|
+
const matches = (a, ac, b, bc) => facts.relationships.some((rel) => lower(rel.table) === lower(a.name) &&
|
|
122
|
+
lower(rel.column) === lower(ac) &&
|
|
123
|
+
lower(rel.referencedTable) === lower(b.name) &&
|
|
124
|
+
lower(rel.referencedColumn) === lower(bc));
|
|
125
|
+
const declared = matches(left, join.left.column, right, join.right.column) ||
|
|
126
|
+
matches(right, join.right.column, left, join.left.column);
|
|
127
|
+
if (!declared && facts.relationships.length > 0) {
|
|
128
|
+
warnings.push(`${join.left.table}.${join.left.column} = ${join.right.table}.${join.right.column} is not a declared foreign key.`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
132
|
+
}
|
|
133
|
+
const FROM_END = new Set([
|
|
134
|
+
'WHERE', 'GROUP', 'ORDER', 'HAVING', 'LIMIT', 'UNION', 'INTERSECT', 'EXCEPT',
|
|
135
|
+
'ON', 'USING', 'WINDOW', 'OFFSET', 'FETCH', 'FOR', 'JOIN', 'INNER', 'LEFT',
|
|
136
|
+
'RIGHT', 'FULL', 'CROSS', 'NATURAL',
|
|
137
|
+
]);
|
|
138
|
+
const FROM_FUNCTIONS = new Set(['EXTRACT', 'SUBSTRING', 'TRIM', 'OVERLAY', 'POSITION']);
|
|
139
|
+
function isName(token) {
|
|
140
|
+
return !!token && (token.type === 'word' || token.type === 'quoted-identifier');
|
|
141
|
+
}
|
|
142
|
+
function bare(token) {
|
|
143
|
+
const value = token.value;
|
|
144
|
+
if (token.type === 'quoted-identifier') {
|
|
145
|
+
return lower(value.slice(1, -1).replace(/""|``/g, (m) => m[0]));
|
|
146
|
+
}
|
|
147
|
+
return lower(value);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Extracts the tables a SELECT reads. Handles quoting, schema qualification,
|
|
151
|
+
* comma lists, joins, subqueries and CTE names. Returns an empty result when
|
|
152
|
+
* the SQL cannot be tokenized; the SQL validator reports that failure itself.
|
|
153
|
+
*/
|
|
154
|
+
export function extractTableReferences(sql, dialect) {
|
|
155
|
+
const { tokens, error } = tokenizeSql(sql, dialect);
|
|
156
|
+
const empty = { tables: [], ctes: [] };
|
|
157
|
+
if (error)
|
|
158
|
+
return empty;
|
|
159
|
+
const tables = new Set();
|
|
160
|
+
const ctes = new Set();
|
|
161
|
+
// Per paren depth: is a FROM list currently open, and is this a function paren.
|
|
162
|
+
const fromOpen = [false];
|
|
163
|
+
const functionParen = [false];
|
|
164
|
+
let depth = 0;
|
|
165
|
+
const readTableName = (index) => {
|
|
166
|
+
// Returns the index after the (possibly qualified) name, recording it.
|
|
167
|
+
const first = tokens[index];
|
|
168
|
+
if (!isName(first))
|
|
169
|
+
return index;
|
|
170
|
+
let last = first;
|
|
171
|
+
let next = index + 1;
|
|
172
|
+
while (tokens[next]?.value === '.' && isName(tokens[next + 1])) {
|
|
173
|
+
last = tokens[next + 1];
|
|
174
|
+
next += 2;
|
|
175
|
+
}
|
|
176
|
+
tables.add(bare(last));
|
|
177
|
+
return next;
|
|
178
|
+
};
|
|
179
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
180
|
+
const token = tokens[i];
|
|
181
|
+
if (token.type === 'punct') {
|
|
182
|
+
if (token.value === '(') {
|
|
183
|
+
const before = tokens[i - 1];
|
|
184
|
+
depth++;
|
|
185
|
+
fromOpen[depth] = false;
|
|
186
|
+
functionParen[depth] = before?.type === 'word' && FROM_FUNCTIONS.has(before.value);
|
|
187
|
+
}
|
|
188
|
+
else if (token.value === ')') {
|
|
189
|
+
fromOpen[depth] = false;
|
|
190
|
+
depth = Math.max(0, depth - 1);
|
|
191
|
+
}
|
|
192
|
+
else if (token.value === ',' && fromOpen[depth] && !functionParen[depth]) {
|
|
193
|
+
i = readTableName(i + 1) - 1;
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (token.type !== 'word')
|
|
198
|
+
continue;
|
|
199
|
+
if (token.value === 'WITH') {
|
|
200
|
+
// WITH [RECURSIVE] name [(cols)] AS ( ... ) [, name AS ( ... )]
|
|
201
|
+
let j = i + 1;
|
|
202
|
+
if (tokens[j]?.value === 'RECURSIVE')
|
|
203
|
+
j++;
|
|
204
|
+
while (isName(tokens[j])) {
|
|
205
|
+
ctes.add(bare(tokens[j]));
|
|
206
|
+
j++;
|
|
207
|
+
if (tokens[j]?.value === '(') {
|
|
208
|
+
// optional column list, skip to matching paren
|
|
209
|
+
let level = 0;
|
|
210
|
+
for (; j < tokens.length; j++) {
|
|
211
|
+
if (tokens[j].value === '(')
|
|
212
|
+
level++;
|
|
213
|
+
if (tokens[j].value === ')' && --level === 0) {
|
|
214
|
+
j++;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (tokens[j]?.value !== 'AS')
|
|
220
|
+
break;
|
|
221
|
+
j++;
|
|
222
|
+
if (tokens[j]?.value === 'NOT' || tokens[j]?.value === 'MATERIALIZED')
|
|
223
|
+
j++;
|
|
224
|
+
if (tokens[j]?.value === 'MATERIALIZED')
|
|
225
|
+
j++;
|
|
226
|
+
if (tokens[j]?.value !== '(')
|
|
227
|
+
break;
|
|
228
|
+
let level = 0;
|
|
229
|
+
for (; j < tokens.length; j++) {
|
|
230
|
+
if (tokens[j].value === '(')
|
|
231
|
+
level++;
|
|
232
|
+
if (tokens[j].value === ')' && --level === 0) {
|
|
233
|
+
j++;
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (tokens[j]?.value === ',')
|
|
238
|
+
j++;
|
|
239
|
+
else
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (token.value === 'FROM' || token.value === 'JOIN') {
|
|
245
|
+
const previous = tokens[i - 1];
|
|
246
|
+
const isFunctionFrom = functionParen[depth] === true;
|
|
247
|
+
const isDistinctFrom = previous?.type === 'word' && previous.value === 'DISTINCT';
|
|
248
|
+
if (isFunctionFrom || isDistinctFrom)
|
|
249
|
+
continue;
|
|
250
|
+
if (token.value === 'FROM')
|
|
251
|
+
fromOpen[depth] = true;
|
|
252
|
+
// LATERAL and ONLY are modifiers, not names.
|
|
253
|
+
let next = i + 1;
|
|
254
|
+
if (tokens[next]?.type === 'word' && (tokens[next].value === 'LATERAL' || tokens[next].value === 'ONLY')) {
|
|
255
|
+
next++;
|
|
256
|
+
}
|
|
257
|
+
if (tokens[next]?.value === '(')
|
|
258
|
+
continue; // subquery: handled when its own FROM appears
|
|
259
|
+
i = readTableName(next) - 1;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (fromOpen[depth] && FROM_END.has(token.value)) {
|
|
263
|
+
fromOpen[depth] = false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
tables: [...tables].filter((name) => !ctes.has(name)),
|
|
268
|
+
ctes: [...ctes],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/** The SQL may only read tables that the accepted plan listed. */
|
|
272
|
+
export function checkSqlFollowsPlan(sql, plan, dialect) {
|
|
273
|
+
const planned = new Set(plan.tables.flatMap((table) => {
|
|
274
|
+
const name = lower(table);
|
|
275
|
+
const dot = name.lastIndexOf('.');
|
|
276
|
+
return dot === -1 ? [name] : [name, name.slice(dot + 1)];
|
|
277
|
+
}));
|
|
278
|
+
const { tables } = extractTableReferences(sql, dialect);
|
|
279
|
+
const unplanned = tables.filter((name) => !planned.has(name));
|
|
280
|
+
return { ok: unplanned.length === 0, unplanned };
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=query-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-plan.js","sourceRoot":"","sources":["../../../src/core/agent/query-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SqlToolResult, ToolContext } from '../types/index.js';
|
|
2
|
+
export interface DescribeTableInput {
|
|
3
|
+
table: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function describeTable(input: DescribeTableInput, context: ToolContext): Promise<SqlToolResult>;
|
|
6
|
+
//# sourceMappingURL=describe-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-table.d.ts","sourceRoot":"","sources":["../../../src/core/tools/describe-table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAyBxB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export async function describeTable(input, context) {
|
|
2
|
+
const table = input.table.trim();
|
|
3
|
+
if (!table) {
|
|
4
|
+
return {
|
|
5
|
+
success: false,
|
|
6
|
+
error: 'Table name is required.',
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
const schema = context.schemaCache
|
|
11
|
+
? await context.schemaCache.describeTable(context.database, table)
|
|
12
|
+
: await context.database.describeTable(table);
|
|
13
|
+
return {
|
|
14
|
+
success: true,
|
|
15
|
+
data: schema,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
return {
|
|
20
|
+
success: false,
|
|
21
|
+
error: error instanceof Error ? error.message : `Failed to describe table "${table}".`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=describe-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-table.js","sourceRoot":"","sources":["../../../src/core/tools/describe-table.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAyB,EACzB,OAAoB;IAEpB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAEjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,yBAAyB;SACjC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW;YAChC,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC;YAClE,CAAC,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAEhD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,KAAK,IAAI;SACvF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SqlToolResult, ToolContext } from '../types/index.js';
|
|
2
|
+
export interface DescribeTablesInput {
|
|
3
|
+
tables: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare function describeTables(input: DescribeTablesInput, context: ToolContext): Promise<SqlToolResult>;
|
|
6
|
+
//# sourceMappingURL=describe-tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-tables.d.ts","sourceRoot":"","sources":["../../../src/core/tools/describe-tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAuBxB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export async function describeTables(input, context) {
|
|
2
|
+
const tables = [...new Set((input.tables ?? []).map((table) => table.trim()).filter(Boolean))];
|
|
3
|
+
if (tables.length === 0) {
|
|
4
|
+
return { success: false, error: 'At least one table name is required.' };
|
|
5
|
+
}
|
|
6
|
+
if (tables.length > 10) {
|
|
7
|
+
return { success: false, error: 'A maximum of 10 tables can be described at once.' };
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
const schemas = context.schemaCache
|
|
11
|
+
? await context.schemaCache.describeTables(context.database, tables)
|
|
12
|
+
: await Promise.all(tables.map((table) => context.database.describeTable(table)));
|
|
13
|
+
return { success: true, data: schemas };
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return {
|
|
17
|
+
success: false,
|
|
18
|
+
error: error instanceof Error ? error.message : 'Failed to describe tables.',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=describe-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-tables.js","sourceRoot":"","sources":["../../../src/core/tools/describe-tables.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAA0B,EAC1B,OAAoB;IAEpB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAE/F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC;IAC3E,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,kDAAkD,EAAE,CAAC;IACvF,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW;YACjC,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;YACpE,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,4BAA4B;SAC7E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SqlToolResult, ToolContext } from '../types/index.js';
|
|
2
|
+
export interface ExecuteQueryInput {
|
|
3
|
+
sql: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function executeQuery(input: ExecuteQueryInput, context: ToolContext): Promise<SqlToolResult>;
|
|
6
|
+
//# sourceMappingURL=execute-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-query.d.ts","sourceRoot":"","sources":["../../../src/core/tools/execute-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGpE,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CA8BxB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { validateSql } from '../../safety/sql-validator.js';
|
|
2
|
+
export async function executeQuery(input, context) {
|
|
3
|
+
const validation = validateSql(input.sql, context.safety, context.database.dialect);
|
|
4
|
+
if (!validation.valid || !validation.sql) {
|
|
5
|
+
return {
|
|
6
|
+
success: false,
|
|
7
|
+
executionAttempted: false,
|
|
8
|
+
error: validation.reason ?? 'SQL query failed validation.',
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const result = await context.database.executeQuery(validation.sql, {
|
|
13
|
+
maxRows: context.safety.maxRows,
|
|
14
|
+
timeoutMs: context.safety.queryTimeoutMs,
|
|
15
|
+
maxResultBytes: context.safety.maxResultBytes,
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
success: true,
|
|
19
|
+
executionAttempted: true,
|
|
20
|
+
data: result,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
executionAttempted: true,
|
|
27
|
+
error: error instanceof Error ? error.message : 'Failed to execute query.',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=execute-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-query.js","sourceRoot":"","sources":["../../../src/core/tools/execute-query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAM5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAwB,EACxB,OAAoB;IAEpB,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEpF,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QACzC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,kBAAkB,EAAE,KAAK;YACzB,KAAK,EAAE,UAAU,CAAC,MAAM,IAAI,8BAA8B;SAC3D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,EAAE;YACjE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO;YAC/B,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc;YACxC,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc;SAC9C,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,IAAI;YACb,kBAAkB,EAAE,IAAI;YACxB,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,kBAAkB,EAAE,IAAI;YACxB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B;SAC3E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SqlToolResult, ToolContext } from '../types/index.js';
|
|
2
|
+
export interface ExplainQueryInput {
|
|
3
|
+
sql: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Produces a database query plan after passing the SQL through the harness
|
|
7
|
+
* safety boundary.
|
|
8
|
+
*/
|
|
9
|
+
export declare function explainQuery(input: ExplainQueryInput, context: ToolContext): Promise<SqlToolResult>;
|
|
10
|
+
//# sourceMappingURL=explain-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain-query.d.ts","sourceRoot":"","sources":["../../../src/core/tools/explain-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGpE,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CA8BxB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { validateSql } from '../../safety/sql-validator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Produces a database query plan after passing the SQL through the harness
|
|
4
|
+
* safety boundary.
|
|
5
|
+
*/
|
|
6
|
+
export async function explainQuery(input, context) {
|
|
7
|
+
const validation = validateSql(input.sql, context.safety, context.database.dialect);
|
|
8
|
+
if (!validation.valid || !validation.sql) {
|
|
9
|
+
return {
|
|
10
|
+
success: false,
|
|
11
|
+
error: validation.reason ?? 'SQL query failed validation.',
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (!/^(SELECT|WITH)\b/i.test(validation.sql)) {
|
|
15
|
+
return {
|
|
16
|
+
success: false,
|
|
17
|
+
error: 'Only SELECT or WITH queries can be explained by this tool.',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = await context.database.explainQuery(validation.sql);
|
|
22
|
+
return {
|
|
23
|
+
success: true,
|
|
24
|
+
data: result,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
error: error instanceof Error ? error.message : 'Failed to explain query.',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=explain-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain-query.js","sourceRoot":"","sources":["../../../src/core/tools/explain-query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAM5D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAwB,EACxB,OAAoB;IAEpB,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEpF,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QACzC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,UAAU,CAAC,MAAM,IAAI,8BAA8B;SAC3D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,4DAA4D;SACpE,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAEnE,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B;SAC3E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SqlToolResult, ToolContext } from '../types/index.js';
|
|
2
|
+
export interface GetRelationshipsInput {
|
|
3
|
+
table?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function getRelationships(input: GetRelationshipsInput | undefined, context: ToolContext): Promise<SqlToolResult>;
|
|
6
|
+
//# sourceMappingURL=get-relationships.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-relationships.d.ts","sourceRoot":"","sources":["../../../src/core/tools/get-relationships.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,YAAK,EACjC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,CAAC,CAsBxB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export async function getRelationships(input = {}, context) {
|
|
2
|
+
const table = input.table?.trim() || undefined;
|
|
3
|
+
try {
|
|
4
|
+
const relationships = table
|
|
5
|
+
? await context.database.getRelationships(table)
|
|
6
|
+
: context.schemaCache
|
|
7
|
+
? await context.schemaCache.getRelationships(context.database)
|
|
8
|
+
: await context.database.getRelationships();
|
|
9
|
+
return {
|
|
10
|
+
success: true,
|
|
11
|
+
data: relationships,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return {
|
|
16
|
+
success: false,
|
|
17
|
+
error: error instanceof Error
|
|
18
|
+
? error.message
|
|
19
|
+
: 'Failed to retrieve database relationships.',
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=get-relationships.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-relationships.js","sourceRoot":"","sources":["../../../src/core/tools/get-relationships.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAK,GAA0B,EAAE,EACjC,OAAoB;IAEpB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAE/C,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,KAAK;YACzB,CAAC,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAChD,CAAC,CAAC,OAAO,CAAC,WAAW;gBACnB,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC9D,CAAC,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAEhD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,aAAa;SACpB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK;gBAC3B,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,4CAA4C;SACjD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { listTables } from './list-tables.js';
|
|
2
|
+
export { describeTable } from './describe-table.js';
|
|
3
|
+
export { describeTables } from './describe-tables.js';
|
|
4
|
+
export { getRelationships } from './get-relationships.js';
|
|
5
|
+
export { executeQuery } from './execute-query.js';
|
|
6
|
+
export { explainQuery } from './explain-query.js';
|
|
7
|
+
export { getTool, getTools, executeTool } from './registry.js';
|
|
8
|
+
export type { ToolName, RegisteredTool } from './registry.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { listTables } from './list-tables.js';
|
|
2
|
+
export { describeTable } from './describe-table.js';
|
|
3
|
+
export { describeTables } from './describe-tables.js';
|
|
4
|
+
export { getRelationships } from './get-relationships.js';
|
|
5
|
+
export { executeQuery } from './execute-query.js';
|
|
6
|
+
export { explainQuery } from './explain-query.js';
|
|
7
|
+
export { getTool, getTools, executeTool } from './registry.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|