@deepagents/text2sql 0.35.0 → 0.37.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 +121 -40
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +404 -727
- package/dist/index.js.map +4 -4
- package/dist/lib/adapter-name.d.ts +4 -0
- package/dist/lib/adapter-name.d.ts.map +1 -0
- package/dist/lib/adapters/adapter.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/index.js +35 -6
- package/dist/lib/adapters/bigquery/index.js.map +2 -2
- package/dist/lib/adapters/mysql/index.js +35 -6
- package/dist/lib/adapters/mysql/index.js.map +2 -2
- package/dist/lib/adapters/postgres/index.js +35 -6
- package/dist/lib/adapters/postgres/index.js.map +2 -2
- package/dist/lib/adapters/spreadsheet/index.js +35 -6
- package/dist/lib/adapters/spreadsheet/index.js.map +2 -2
- package/dist/lib/adapters/sqlite/index.js +35 -6
- package/dist/lib/adapters/sqlite/index.js.map +2 -2
- package/dist/lib/adapters/sqlserver/index.js +35 -6
- package/dist/lib/adapters/sqlserver/index.js.map +2 -2
- package/dist/lib/agents/exceptions.d.ts +9 -0
- package/dist/lib/agents/exceptions.d.ts.map +1 -1
- package/dist/lib/agents/sql-command.d.ts +11 -0
- package/dist/lib/agents/sql-command.d.ts.map +1 -0
- package/dist/lib/agents/sql-transform-plugins.d.ts +4 -1
- package/dist/lib/agents/sql-transform-plugins.d.ts.map +1 -1
- package/dist/lib/demo.d.ts +2 -0
- package/dist/lib/demo.d.ts.map +1 -0
- package/dist/lib/fs/index.d.ts +0 -1
- package/dist/lib/fs/index.d.ts.map +1 -1
- package/dist/lib/instructions.d.ts.map +1 -1
- package/dist/lib/sandbox.d.ts +21 -0
- package/dist/lib/sandbox.d.ts.map +1 -0
- package/dist/lib/sql.d.ts +23 -37
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +12 -0
- package/dist/lib/synthesis/index.js.map +2 -2
- package/package.json +8 -8
- package/dist/lib/agents/explainer.agent.d.ts +0 -7
- package/dist/lib/agents/explainer.agent.d.ts.map +0 -1
- package/dist/lib/agents/result-tools.d.ts +0 -69
- package/dist/lib/agents/result-tools.d.ts.map +0 -1
- package/dist/lib/fs/tracked-fs.d.ts +0 -42
- package/dist/lib/fs/tracked-fs.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
// packages/text2sql/src/lib/adapter-name.ts
|
|
2
|
+
var ADAPTER_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3
|
+
function isValidAdapterName(name) {
|
|
4
|
+
return name != null && ADAPTER_NAME_PATTERN.test(name);
|
|
5
|
+
}
|
|
6
|
+
function validateAdapterNames(names) {
|
|
7
|
+
for (const name of names) {
|
|
8
|
+
if (!isValidAdapterName(name)) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`Invalid adapter name "${name}": must match ${ADAPTER_NAME_PATTERN}`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
1
16
|
// packages/text2sql/src/lib/adapters/adapter.ts
|
|
2
17
|
import { format as formatSql } from "sql-formatter";
|
|
3
18
|
|
|
@@ -5,6 +20,7 @@ import { format as formatSql } from "sql-formatter";
|
|
|
5
20
|
var sqlValidationMarker = Symbol("SQLValidationError");
|
|
6
21
|
var unanswerableSqlMarker = Symbol("UnanswerableSQLError");
|
|
7
22
|
var sqlScopeMarker = Symbol("SQLScopeError");
|
|
23
|
+
var sqlReadOnlyMarker = Symbol("SQLReadOnlyError");
|
|
8
24
|
var SQLValidationError = class _SQLValidationError extends Error {
|
|
9
25
|
[sqlValidationMarker];
|
|
10
26
|
constructor(message) {
|
|
@@ -42,6 +58,17 @@ var SQLScopeError = class _SQLScopeError extends Error {
|
|
|
42
58
|
return error instanceof _SQLScopeError && error[sqlScopeMarker] === true;
|
|
43
59
|
}
|
|
44
60
|
};
|
|
61
|
+
var SQLReadOnlyError = class _SQLReadOnlyError extends Error {
|
|
62
|
+
[sqlReadOnlyMarker];
|
|
63
|
+
constructor(message) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.name = "SQLReadOnlyError";
|
|
66
|
+
this[sqlReadOnlyMarker] = true;
|
|
67
|
+
}
|
|
68
|
+
static isInstance(error) {
|
|
69
|
+
return error instanceof _SQLReadOnlyError && error[sqlReadOnlyMarker] === true;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
45
72
|
|
|
46
73
|
// packages/text2sql/src/lib/fragments/schema.ts
|
|
47
74
|
function dialectInfo(input) {
|
|
@@ -468,12 +495,23 @@ var Adapter = class {
|
|
|
468
495
|
});
|
|
469
496
|
}
|
|
470
497
|
format(sql) {
|
|
498
|
+
const decoded = this.#decodeShellEscapes(sql);
|
|
471
499
|
try {
|
|
472
|
-
return formatSql(
|
|
500
|
+
return formatSql(decoded, { language: this.formatterLanguage });
|
|
473
501
|
} catch {
|
|
474
|
-
return
|
|
502
|
+
return decoded;
|
|
475
503
|
}
|
|
476
504
|
}
|
|
505
|
+
#decodeShellEscapes(sql) {
|
|
506
|
+
return sql.replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\([().*])/g, "$1").replace(/\\(?=$)/gm, "");
|
|
507
|
+
}
|
|
508
|
+
#checkReadOnly(sql) {
|
|
509
|
+
const upper = sql.trimStart().toUpperCase();
|
|
510
|
+
if (!upper.startsWith("SELECT") && !upper.startsWith("WITH")) {
|
|
511
|
+
return "only SELECT or WITH queries allowed";
|
|
512
|
+
}
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
477
515
|
#cachedAllowedEntities = null;
|
|
478
516
|
async #resolveScope() {
|
|
479
517
|
if (this.#cachedAllowedEntities) return this.#cachedAllowedEntities;
|
|
@@ -535,16 +573,22 @@ var Adapter = class {
|
|
|
535
573
|
return buildOutOfScopePayload(sql, outOfScope, allowedEntities);
|
|
536
574
|
}
|
|
537
575
|
async validate(sql) {
|
|
576
|
+
const decoded = this.#decodeShellEscapes(sql);
|
|
577
|
+
const readOnlyError = this.#checkReadOnly(decoded);
|
|
578
|
+
if (readOnlyError) return readOnlyError;
|
|
538
579
|
const allowed = await this.#resolveScope();
|
|
539
|
-
const scopeError = await this.#checkScope(
|
|
580
|
+
const scopeError = await this.#checkScope(decoded, allowed);
|
|
540
581
|
if (scopeError) return JSON.stringify(scopeError);
|
|
541
|
-
return this.validateImpl(
|
|
582
|
+
return this.validateImpl(decoded);
|
|
542
583
|
}
|
|
543
584
|
async execute(sql) {
|
|
585
|
+
const decoded = this.#decodeShellEscapes(sql);
|
|
586
|
+
const readOnlyError = this.#checkReadOnly(decoded);
|
|
587
|
+
if (readOnlyError) throw new SQLReadOnlyError(readOnlyError);
|
|
544
588
|
const allowed = await this.#resolveScope();
|
|
545
|
-
const scopeError = await this.#checkScope(
|
|
589
|
+
const scopeError = await this.#checkScope(decoded, allowed);
|
|
546
590
|
if (scopeError) throw new SQLScopeError(scopeError);
|
|
547
|
-
return this.executeImpl(
|
|
591
|
+
return this.executeImpl(decoded);
|
|
548
592
|
}
|
|
549
593
|
/**
|
|
550
594
|
* Convert unknown database value to number.
|
|
@@ -666,62 +710,148 @@ function getTablesWithRelated(allTables, relationships, filter) {
|
|
|
666
710
|
return Array.from(result);
|
|
667
711
|
}
|
|
668
712
|
|
|
669
|
-
// packages/text2sql/src/lib/agents/
|
|
670
|
-
import { tool } from "ai";
|
|
671
|
-
import { createBashTool } from "bash-tool";
|
|
672
|
-
import chalk from "chalk";
|
|
673
|
-
import {
|
|
674
|
-
Bash,
|
|
675
|
-
MountableFs,
|
|
676
|
-
OverlayFs,
|
|
677
|
-
defineCommand,
|
|
678
|
-
parse as parse2
|
|
679
|
-
} from "just-bash";
|
|
680
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
681
|
-
import * as path2 from "node:path";
|
|
713
|
+
// packages/text2sql/src/lib/agents/sql-command.ts
|
|
682
714
|
import { v7 } from "uuid";
|
|
683
|
-
import
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
715
|
+
import {
|
|
716
|
+
buildSubcommandRepair,
|
|
717
|
+
defineSubcommandGroup,
|
|
718
|
+
repairQuotedArg,
|
|
719
|
+
useBashMeta
|
|
720
|
+
} from "@deepagents/context";
|
|
721
|
+
var SQL_VALIDATE_REMINDER = 'Always run `sql validate <db> "..."` before `sql run <db> "..."` to catch syntax errors early.';
|
|
722
|
+
function repairDbNameAndQuotedArg(rawArgs) {
|
|
723
|
+
const trimmed = rawArgs.trim();
|
|
724
|
+
if (!trimmed) return null;
|
|
725
|
+
const firstSpace = trimmed.search(/\s/);
|
|
726
|
+
if (firstSpace === -1) return null;
|
|
727
|
+
const dbName = trimmed.slice(0, firstSpace);
|
|
728
|
+
const rest = trimmed.slice(firstSpace + 1);
|
|
729
|
+
const repaired = repairQuotedArg(rest);
|
|
730
|
+
if (repaired == null) return null;
|
|
731
|
+
return `${dbName} ${repaired}`;
|
|
732
|
+
}
|
|
733
|
+
function resolveAdapter(adapters, subcommand, args) {
|
|
734
|
+
const [name, ...rest] = args;
|
|
735
|
+
const available = Object.keys(adapters).join(", ");
|
|
736
|
+
if (!name) {
|
|
737
|
+
return {
|
|
738
|
+
error: `sql ${subcommand}: missing database name. Usage: sql ${subcommand} <db> "SELECT ...". Available: ${available}`
|
|
739
|
+
};
|
|
692
740
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
741
|
+
const adapter = adapters[name];
|
|
742
|
+
if (!adapter) {
|
|
743
|
+
return {
|
|
744
|
+
error: `sql ${subcommand}: unknown database "${name}". Available: ${available}`
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
const sql = rest.join(" ").trim();
|
|
748
|
+
if (!sql) {
|
|
749
|
+
return { error: `sql ${subcommand}: no query provided` };
|
|
750
|
+
}
|
|
751
|
+
return { adapter, sql };
|
|
696
752
|
}
|
|
697
|
-
function
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
753
|
+
function createSqlCommand(adapters, { outputDir = "/sql" } = {}) {
|
|
754
|
+
const subcommands = {
|
|
755
|
+
run: {
|
|
756
|
+
usage: 'run <db> "SELECT ..."',
|
|
757
|
+
description: "Execute query against <db> and store results",
|
|
758
|
+
repair: repairDbNameAndQuotedArg,
|
|
759
|
+
handler: async (args, ctx) => {
|
|
760
|
+
const meta = useBashMeta();
|
|
761
|
+
meta?.setReminder(SQL_VALIDATE_REMINDER);
|
|
762
|
+
const resolved = resolveAdapter(adapters, "run", args);
|
|
763
|
+
if ("error" in resolved) {
|
|
764
|
+
return { stdout: "", stderr: resolved.error, exitCode: 1 };
|
|
765
|
+
}
|
|
766
|
+
const { adapter, sql: rawQuery } = resolved;
|
|
767
|
+
const query = adapter.format(rawQuery);
|
|
768
|
+
meta?.setHidden({ formattedSql: query });
|
|
769
|
+
const syntaxError = await adapter.validate(query);
|
|
770
|
+
if (syntaxError) {
|
|
771
|
+
return {
|
|
772
|
+
stdout: "",
|
|
773
|
+
stderr: `sql run: ${syntaxError}`,
|
|
774
|
+
exitCode: 1
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
try {
|
|
778
|
+
const rows = await adapter.execute(query);
|
|
779
|
+
if (!Array.isArray(rows)) {
|
|
780
|
+
throw new Error("adapter.execute must return an array of rows");
|
|
781
|
+
}
|
|
782
|
+
const rowsArray = rows;
|
|
783
|
+
const content = JSON.stringify(rowsArray, null, 2);
|
|
784
|
+
const filename = `${v7()}.json`;
|
|
785
|
+
const sqlPath = `${outputDir}/${filename}`;
|
|
786
|
+
const mkdir = await ctx.sandbox.executeCommand(
|
|
787
|
+
`mkdir -p ${outputDir}`
|
|
788
|
+
);
|
|
789
|
+
if (mkdir.exitCode !== 0) {
|
|
790
|
+
return {
|
|
791
|
+
stdout: "",
|
|
792
|
+
stderr: `sql run: failed to create ${outputDir}: ${mkdir.stderr}`,
|
|
793
|
+
exitCode: 1
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
await ctx.sandbox.writeFiles([{ path: sqlPath, content }]);
|
|
797
|
+
const columns = rowsArray.length > 0 ? Object.keys(rowsArray[0]) : [];
|
|
798
|
+
return {
|
|
799
|
+
stdout: [
|
|
800
|
+
`results stored in ${sqlPath}`,
|
|
801
|
+
`columns: ${columns.join(", ") || "(none)"}`,
|
|
802
|
+
`rows: ${rowsArray.length}`
|
|
803
|
+
].join("\n") + "\n",
|
|
804
|
+
stderr: "",
|
|
805
|
+
exitCode: 0
|
|
806
|
+
};
|
|
807
|
+
} catch (error) {
|
|
808
|
+
return {
|
|
809
|
+
stdout: "",
|
|
810
|
+
stderr: `sql run: ${error instanceof Error ? error.message : String(error)}`,
|
|
811
|
+
exitCode: 1
|
|
812
|
+
};
|
|
813
|
+
}
|
|
711
814
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
815
|
+
},
|
|
816
|
+
validate: {
|
|
817
|
+
usage: 'validate <db> "SELECT ..."',
|
|
818
|
+
description: "Validate query syntax against <db>",
|
|
819
|
+
repair: repairDbNameAndQuotedArg,
|
|
820
|
+
handler: async (args) => {
|
|
821
|
+
const meta = useBashMeta();
|
|
822
|
+
const resolved = resolveAdapter(adapters, "validate", args);
|
|
823
|
+
if ("error" in resolved) {
|
|
824
|
+
return { stdout: "", stderr: resolved.error, exitCode: 1 };
|
|
825
|
+
}
|
|
826
|
+
const { adapter, sql: rawQuery } = resolved;
|
|
827
|
+
const query = adapter.format(rawQuery);
|
|
828
|
+
meta?.setHidden({ formattedSql: query });
|
|
829
|
+
const syntaxError = await adapter.validate(query);
|
|
830
|
+
if (syntaxError) {
|
|
831
|
+
return {
|
|
832
|
+
stdout: "",
|
|
833
|
+
stderr: `sql validate: ${syntaxError}`,
|
|
834
|
+
exitCode: 1
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
return {
|
|
838
|
+
stdout: "valid\n",
|
|
839
|
+
stderr: "",
|
|
840
|
+
exitCode: 0
|
|
841
|
+
};
|
|
717
842
|
}
|
|
718
|
-
text += inner;
|
|
719
|
-
continue;
|
|
720
843
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
844
|
+
};
|
|
845
|
+
const command = defineSubcommandGroup("sql", subcommands);
|
|
846
|
+
const repair = buildSubcommandRepair("sql", subcommands);
|
|
847
|
+
return { command, repair };
|
|
724
848
|
}
|
|
849
|
+
|
|
850
|
+
// packages/text2sql/src/lib/agents/sql-transform-plugins.ts
|
|
851
|
+
import { parse, serialize } from "just-bash";
|
|
852
|
+
import { createHash } from "node:crypto";
|
|
853
|
+
import * as path from "node:path";
|
|
854
|
+
import { BashException, asStaticWordText } from "@deepagents/context";
|
|
725
855
|
function isScriptNode(value) {
|
|
726
856
|
if (typeof value !== "object" || value === null) {
|
|
727
857
|
return false;
|
|
@@ -748,14 +878,18 @@ var WRAPPER_COMMANDS = /* @__PURE__ */ new Set(["env", "command", "eval"]);
|
|
|
748
878
|
var SQL_PROXY_ENFORCEMENT_MESSAGE = [
|
|
749
879
|
"Direct database querying through bash is blocked.",
|
|
750
880
|
"Use SQL proxy commands in this order:",
|
|
751
|
-
'1) sql validate "SELECT ..."',
|
|
752
|
-
'2) sql run "SELECT ..."'
|
|
881
|
+
'1) sql validate <db> "SELECT ..."',
|
|
882
|
+
'2) sql run <db> "SELECT ..."'
|
|
753
883
|
].join("\n");
|
|
754
|
-
var SqlProxyViolationError = class extends
|
|
884
|
+
var SqlProxyViolationError = class extends BashException {
|
|
755
885
|
constructor() {
|
|
756
886
|
super(SQL_PROXY_ENFORCEMENT_MESSAGE);
|
|
757
887
|
this.name = "SqlProxyViolationError";
|
|
758
888
|
}
|
|
889
|
+
format() {
|
|
890
|
+
return { stdout: "", stderr: `${this.message}
|
|
891
|
+
`, exitCode: 1 };
|
|
892
|
+
}
|
|
759
893
|
};
|
|
760
894
|
function cloneInspectionContext(context) {
|
|
761
895
|
return {
|
|
@@ -1362,10 +1496,12 @@ function isSqlBacktickCommand(cmd) {
|
|
|
1362
1496
|
if (cmd.type !== "SimpleCommand") return false;
|
|
1363
1497
|
if (cmd.assignments.length > 0 || cmd.redirections.length > 0) return false;
|
|
1364
1498
|
if (asStaticWordText(cmd.name) !== "sql") return false;
|
|
1365
|
-
if (cmd.args.length <
|
|
1499
|
+
if (cmd.args.length < 3) return false;
|
|
1366
1500
|
const subcommand = asStaticWordText(cmd.args[0]);
|
|
1367
1501
|
if (subcommand !== "validate" && subcommand !== "run") return false;
|
|
1368
|
-
const
|
|
1502
|
+
const dbName = asStaticWordText(cmd.args[1]);
|
|
1503
|
+
if (!isValidAdapterName(dbName)) return false;
|
|
1504
|
+
const sqlArgs = cmd.args.slice(2);
|
|
1369
1505
|
return sqlArgs.some(
|
|
1370
1506
|
(arg) => wordPartsContainBacktickSubstitution(
|
|
1371
1507
|
arg.parts
|
|
@@ -1395,7 +1531,8 @@ function extractSqlText(args) {
|
|
|
1395
1531
|
}
|
|
1396
1532
|
function rewriteSqlBacktickCommand(cmd, ast) {
|
|
1397
1533
|
const subcommand = asStaticWordText(cmd.args[0]);
|
|
1398
|
-
const
|
|
1534
|
+
const dbName = asStaticWordText(cmd.args[1]);
|
|
1535
|
+
const sqlArgs = cmd.args.slice(2);
|
|
1399
1536
|
const unquotedSql = extractSqlText(sqlArgs);
|
|
1400
1537
|
const hash2 = createHash("sha256").update(serialize(ast)).digest("hex").slice(0, 12);
|
|
1401
1538
|
const sqlPath = `/tmp/sql-inline-${subcommand}-${hash2}.sql`;
|
|
@@ -1404,7 +1541,7 @@ function rewriteSqlBacktickCommand(cmd, ast) {
|
|
|
1404
1541
|
`{ cat > ${sqlPath} <<'${heredocTag}'`,
|
|
1405
1542
|
unquotedSql,
|
|
1406
1543
|
heredocTag,
|
|
1407
|
-
`sql ${subcommand} "$(cat ${sqlPath})"; }`
|
|
1544
|
+
`sql ${subcommand} ${dbName} "$(cat ${sqlPath})"; }`
|
|
1408
1545
|
].join("\n");
|
|
1409
1546
|
const groupAst = parse(groupScript);
|
|
1410
1547
|
return groupAst.statements[0].pipelines[0].commands[0];
|
|
@@ -1462,296 +1599,6 @@ var SqlBacktickRewritePlugin = class {
|
|
|
1462
1599
|
}
|
|
1463
1600
|
};
|
|
1464
1601
|
|
|
1465
|
-
// packages/text2sql/src/lib/agents/result-tools.ts
|
|
1466
|
-
function createCommand(name, subcommands) {
|
|
1467
|
-
const usageLines = Object.entries(subcommands).map(([, def]) => ` ${name} ${def.usage.padEnd(30)} ${def.description}`).join("\n");
|
|
1468
|
-
return defineCommand(name, async (args, ctx) => {
|
|
1469
|
-
const subcommand = args[0];
|
|
1470
|
-
const restArgs = args.slice(1);
|
|
1471
|
-
if (subcommand && subcommand in subcommands) {
|
|
1472
|
-
return subcommands[subcommand].handler(restArgs, ctx);
|
|
1473
|
-
}
|
|
1474
|
-
return {
|
|
1475
|
-
stdout: "",
|
|
1476
|
-
stderr: `${name}: ${subcommand ? `unknown subcommand '${subcommand}'` : "missing subcommand"}
|
|
1477
|
-
|
|
1478
|
-
Usage:
|
|
1479
|
-
${usageLines}`,
|
|
1480
|
-
exitCode: 1
|
|
1481
|
-
};
|
|
1482
|
-
});
|
|
1483
|
-
}
|
|
1484
|
-
function escapeRegExp(s) {
|
|
1485
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1486
|
-
}
|
|
1487
|
-
function buildRepair(name, subcommands) {
|
|
1488
|
-
const subNames = Object.keys(subcommands).map(escapeRegExp).join("|");
|
|
1489
|
-
const pattern = new RegExp(
|
|
1490
|
-
`^(\\s*${escapeRegExp(name)}\\s+(?:${subNames}))\\s+([\\s\\S]+)$`
|
|
1491
|
-
);
|
|
1492
|
-
return function repair(raw) {
|
|
1493
|
-
const match = raw.match(pattern);
|
|
1494
|
-
if (!match) return raw;
|
|
1495
|
-
try {
|
|
1496
|
-
parse2(raw);
|
|
1497
|
-
return raw;
|
|
1498
|
-
} catch {
|
|
1499
|
-
}
|
|
1500
|
-
const [, prefix, argsPart] = match;
|
|
1501
|
-
const sub = prefix.trim().split(/\s+/).pop();
|
|
1502
|
-
const repairFn = subcommands[sub]?.repair;
|
|
1503
|
-
if (!repairFn) return raw;
|
|
1504
|
-
const repairedArgs = repairFn(argsPart);
|
|
1505
|
-
if (repairedArgs == null) return raw;
|
|
1506
|
-
const repaired = `${prefix} ${repairedArgs}`;
|
|
1507
|
-
try {
|
|
1508
|
-
parse2(repaired);
|
|
1509
|
-
return repaired;
|
|
1510
|
-
} catch {
|
|
1511
|
-
return raw;
|
|
1512
|
-
}
|
|
1513
|
-
};
|
|
1514
|
-
}
|
|
1515
|
-
function validateReadOnly(query) {
|
|
1516
|
-
const upper = query.toUpperCase().trim();
|
|
1517
|
-
if (!upper.startsWith("SELECT") && !upper.startsWith("WITH")) {
|
|
1518
|
-
return { valid: false, error: "only SELECT or WITH queries allowed" };
|
|
1519
|
-
}
|
|
1520
|
-
return { valid: true };
|
|
1521
|
-
}
|
|
1522
|
-
var SQL_VALIDATE_REMINDER = "Always run `sql validate` before `sql run` to catch syntax errors early.";
|
|
1523
|
-
function normalizeShellArtifacts(raw) {
|
|
1524
|
-
return raw.replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\([().*])/g, "$1").replace(/\\(?=$)/gm, "");
|
|
1525
|
-
}
|
|
1526
|
-
function stripQuoteArtifacts(raw) {
|
|
1527
|
-
let sql = raw.trim();
|
|
1528
|
-
if (sql.startsWith('"')) {
|
|
1529
|
-
sql = sql.slice(1);
|
|
1530
|
-
if (sql.endsWith('"')) sql = sql.slice(0, -1);
|
|
1531
|
-
} else if (sql.startsWith("'")) {
|
|
1532
|
-
sql = sql.slice(1);
|
|
1533
|
-
if (sql.endsWith("'")) sql = sql.slice(0, -1);
|
|
1534
|
-
}
|
|
1535
|
-
return sql.trim();
|
|
1536
|
-
}
|
|
1537
|
-
function repairSqlArgs(rawArgs) {
|
|
1538
|
-
const sql = stripQuoteArtifacts(rawArgs);
|
|
1539
|
-
if (!sql) return null;
|
|
1540
|
-
const escaped = sql.replace(/'/g, "'\\''");
|
|
1541
|
-
return `'${escaped}'`;
|
|
1542
|
-
}
|
|
1543
|
-
function createSqlCommand(adapter, metaStore) {
|
|
1544
|
-
const subcommands = {
|
|
1545
|
-
run: {
|
|
1546
|
-
usage: 'run "SELECT ..."',
|
|
1547
|
-
description: "Execute query and store results",
|
|
1548
|
-
repair: repairSqlArgs,
|
|
1549
|
-
handler: async (args, ctx) => {
|
|
1550
|
-
const store = metaStore.getStore();
|
|
1551
|
-
if (store) {
|
|
1552
|
-
store.value = { ...store.value, reminder: SQL_VALIDATE_REMINDER };
|
|
1553
|
-
}
|
|
1554
|
-
const rawQuery = normalizeShellArtifacts(args.join(" ").trim());
|
|
1555
|
-
if (!rawQuery) {
|
|
1556
|
-
return {
|
|
1557
|
-
stdout: "",
|
|
1558
|
-
stderr: "sql run: no query provided",
|
|
1559
|
-
exitCode: 1
|
|
1560
|
-
};
|
|
1561
|
-
}
|
|
1562
|
-
const validation = validateReadOnly(rawQuery);
|
|
1563
|
-
if (!validation.valid) {
|
|
1564
|
-
return {
|
|
1565
|
-
stdout: "",
|
|
1566
|
-
stderr: `sql run: ${validation.error}`,
|
|
1567
|
-
exitCode: 1
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
const query = adapter.format(rawQuery);
|
|
1571
|
-
if (store) {
|
|
1572
|
-
store.value = { ...store.value, formattedSql: query };
|
|
1573
|
-
}
|
|
1574
|
-
const syntaxError = await adapter.validate(query);
|
|
1575
|
-
if (syntaxError) {
|
|
1576
|
-
return {
|
|
1577
|
-
stdout: "",
|
|
1578
|
-
stderr: `sql run: ${syntaxError}`,
|
|
1579
|
-
exitCode: 1
|
|
1580
|
-
};
|
|
1581
|
-
}
|
|
1582
|
-
try {
|
|
1583
|
-
const rows = await adapter.execute(query);
|
|
1584
|
-
const rowsArray = Array.isArray(rows) ? rows : [];
|
|
1585
|
-
const content = JSON.stringify(rowsArray, null, 2);
|
|
1586
|
-
const filename = `${v7()}.json`;
|
|
1587
|
-
const sqlPath = `/sql/${filename}`;
|
|
1588
|
-
await ctx.fs.mkdir("/sql", { recursive: true });
|
|
1589
|
-
await ctx.fs.writeFile(sqlPath, content);
|
|
1590
|
-
const columns = rowsArray.length > 0 ? Object.keys(rowsArray[0]) : [];
|
|
1591
|
-
return {
|
|
1592
|
-
stdout: [
|
|
1593
|
-
`results stored in ${sqlPath}`,
|
|
1594
|
-
`columns: ${columns.join(", ") || "(none)"}`,
|
|
1595
|
-
`rows: ${rowsArray.length}`
|
|
1596
|
-
].join("\n") + "\n",
|
|
1597
|
-
stderr: "",
|
|
1598
|
-
exitCode: 0
|
|
1599
|
-
};
|
|
1600
|
-
} catch (error) {
|
|
1601
|
-
return {
|
|
1602
|
-
stdout: "",
|
|
1603
|
-
stderr: `sql run: ${error instanceof Error ? error.message : String(error)}`,
|
|
1604
|
-
exitCode: 1
|
|
1605
|
-
};
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
},
|
|
1609
|
-
validate: {
|
|
1610
|
-
usage: 'validate "SELECT ..."',
|
|
1611
|
-
description: "Validate query syntax",
|
|
1612
|
-
repair: repairSqlArgs,
|
|
1613
|
-
handler: async (args) => {
|
|
1614
|
-
const rawQuery = normalizeShellArtifacts(args.join(" ").trim());
|
|
1615
|
-
if (!rawQuery) {
|
|
1616
|
-
return {
|
|
1617
|
-
stdout: "",
|
|
1618
|
-
stderr: "sql validate: no query provided",
|
|
1619
|
-
exitCode: 1
|
|
1620
|
-
};
|
|
1621
|
-
}
|
|
1622
|
-
const validation = validateReadOnly(rawQuery);
|
|
1623
|
-
if (!validation.valid) {
|
|
1624
|
-
return {
|
|
1625
|
-
stdout: "",
|
|
1626
|
-
stderr: `sql validate: ${validation.error}`,
|
|
1627
|
-
exitCode: 1
|
|
1628
|
-
};
|
|
1629
|
-
}
|
|
1630
|
-
const query = adapter.format(rawQuery);
|
|
1631
|
-
const store = metaStore.getStore();
|
|
1632
|
-
if (store) store.value = { ...store.value, formattedSql: query };
|
|
1633
|
-
const syntaxError = await adapter.validate(query);
|
|
1634
|
-
if (syntaxError) {
|
|
1635
|
-
return {
|
|
1636
|
-
stdout: "",
|
|
1637
|
-
stderr: `sql validate: ${syntaxError}`,
|
|
1638
|
-
exitCode: 1
|
|
1639
|
-
};
|
|
1640
|
-
}
|
|
1641
|
-
return {
|
|
1642
|
-
stdout: "valid\n",
|
|
1643
|
-
stderr: "",
|
|
1644
|
-
exitCode: 0
|
|
1645
|
-
};
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
};
|
|
1649
|
-
const command = createCommand("sql", subcommands);
|
|
1650
|
-
const repair = buildRepair("sql", subcommands);
|
|
1651
|
-
return { command, repair };
|
|
1652
|
-
}
|
|
1653
|
-
function toViolationResult(error) {
|
|
1654
|
-
if (error instanceof SqlProxyViolationError) {
|
|
1655
|
-
return { stdout: "", stderr: `${error.message}
|
|
1656
|
-
`, exitCode: 1 };
|
|
1657
|
-
}
|
|
1658
|
-
return null;
|
|
1659
|
-
}
|
|
1660
|
-
async function createResultTools(options) {
|
|
1661
|
-
const { adapter, skillMounts, filesystem: baseFs } = options;
|
|
1662
|
-
const metaStore = new AsyncLocalStorage();
|
|
1663
|
-
const { command: sqlCommand, repair: repairCommand } = createSqlCommand(
|
|
1664
|
-
adapter,
|
|
1665
|
-
metaStore
|
|
1666
|
-
);
|
|
1667
|
-
const fsMounts = skillMounts.map(({ host, sandbox: sandbox2 }) => ({
|
|
1668
|
-
mountPoint: path2.dirname(sandbox2),
|
|
1669
|
-
filesystem: new OverlayFs({
|
|
1670
|
-
root: path2.dirname(host),
|
|
1671
|
-
mountPoint: "/",
|
|
1672
|
-
readOnly: true
|
|
1673
|
-
})
|
|
1674
|
-
}));
|
|
1675
|
-
const filesystem = new MountableFs({
|
|
1676
|
-
base: baseFs,
|
|
1677
|
-
mounts: fsMounts
|
|
1678
|
-
});
|
|
1679
|
-
const bashInstance = new Bash({
|
|
1680
|
-
customCommands: [sqlCommand],
|
|
1681
|
-
fs: filesystem
|
|
1682
|
-
});
|
|
1683
|
-
bashInstance.registerTransformPlugin(new SqlBacktickRewritePlugin());
|
|
1684
|
-
bashInstance.registerTransformPlugin(new SqlProxyEnforcementPlugin());
|
|
1685
|
-
const { sandbox, tools } = await createBashTool({
|
|
1686
|
-
sandbox: bashInstance,
|
|
1687
|
-
destination: "/",
|
|
1688
|
-
extraInstructions: 'Every bash tool call must include a brief non-empty "reasoning" input explaining why the command is needed.',
|
|
1689
|
-
onBeforeBashCall: ({ command }) => {
|
|
1690
|
-
const repaired = repairCommand(command);
|
|
1691
|
-
console.log(chalk.cyan(`[onBeforeBashCall]: ${repaired}`));
|
|
1692
|
-
return { command: repaired };
|
|
1693
|
-
},
|
|
1694
|
-
onAfterBashCall: ({ result }) => {
|
|
1695
|
-
if (result.exitCode !== 0) {
|
|
1696
|
-
console.log(chalk.yellow(`[onAfterBashCall]: ${result.exitCode}`));
|
|
1697
|
-
}
|
|
1698
|
-
return { result };
|
|
1699
|
-
}
|
|
1700
|
-
});
|
|
1701
|
-
const guardedSandbox = {
|
|
1702
|
-
...sandbox,
|
|
1703
|
-
executeCommand: async (command) => {
|
|
1704
|
-
try {
|
|
1705
|
-
return await sandbox.executeCommand(command);
|
|
1706
|
-
} catch (error) {
|
|
1707
|
-
const violation = toViolationResult(error);
|
|
1708
|
-
if (violation) return violation;
|
|
1709
|
-
throw error;
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
};
|
|
1713
|
-
const bash = tool({
|
|
1714
|
-
...tools.bash,
|
|
1715
|
-
inputSchema: z.object({
|
|
1716
|
-
command: z.string().describe("The bash command to execute"),
|
|
1717
|
-
reasoning: z.string().trim().describe("Brief reason for executing this command")
|
|
1718
|
-
}),
|
|
1719
|
-
execute: async ({ command }, execOptions) => {
|
|
1720
|
-
const execute = tools.bash.execute;
|
|
1721
|
-
if (!execute) {
|
|
1722
|
-
throw new Error("bash tool execution is not available");
|
|
1723
|
-
}
|
|
1724
|
-
return metaStore.run({}, async () => {
|
|
1725
|
-
try {
|
|
1726
|
-
const result = await execute({ command }, execOptions);
|
|
1727
|
-
const storeValue = metaStore.getStore()?.value;
|
|
1728
|
-
if (!storeValue) return result;
|
|
1729
|
-
const { reminder, ...meta } = storeValue;
|
|
1730
|
-
return { ...result, meta, reminder };
|
|
1731
|
-
} catch (error) {
|
|
1732
|
-
const violation = toViolationResult(error);
|
|
1733
|
-
if (violation) return violation;
|
|
1734
|
-
throw error;
|
|
1735
|
-
}
|
|
1736
|
-
});
|
|
1737
|
-
},
|
|
1738
|
-
toModelOutput: ({ output }) => {
|
|
1739
|
-
if (typeof output !== "object" || output === null) {
|
|
1740
|
-
return { type: "json", value: output };
|
|
1741
|
-
}
|
|
1742
|
-
const { meta, ...rest } = output;
|
|
1743
|
-
return { type: "json", value: rest };
|
|
1744
|
-
}
|
|
1745
|
-
});
|
|
1746
|
-
return {
|
|
1747
|
-
sandbox: guardedSandbox,
|
|
1748
|
-
tools: {
|
|
1749
|
-
...tools,
|
|
1750
|
-
bash
|
|
1751
|
-
}
|
|
1752
|
-
};
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
1602
|
// packages/text2sql/src/lib/agents/sql.agent.ts
|
|
1756
1603
|
import { groq } from "@ai-sdk/groq";
|
|
1757
1604
|
import {
|
|
@@ -1766,7 +1613,7 @@ import {
|
|
|
1766
1613
|
} from "ai";
|
|
1767
1614
|
import dedent from "dedent";
|
|
1768
1615
|
import pRetry from "p-retry";
|
|
1769
|
-
import
|
|
1616
|
+
import z from "zod";
|
|
1770
1617
|
import "@deepagents/agent";
|
|
1771
1618
|
import {
|
|
1772
1619
|
ContextEngine,
|
|
@@ -2043,14 +1890,14 @@ Question: ${options.input}
|
|
|
2043
1890
|
const sqlOutput = structuredOutput({
|
|
2044
1891
|
model,
|
|
2045
1892
|
context,
|
|
2046
|
-
schema:
|
|
2047
|
-
result:
|
|
2048
|
-
|
|
2049
|
-
sql:
|
|
2050
|
-
reasoning:
|
|
1893
|
+
schema: z.object({
|
|
1894
|
+
result: z.union([
|
|
1895
|
+
z.object({
|
|
1896
|
+
sql: z.string().describe("The SQL query that answers the question"),
|
|
1897
|
+
reasoning: z.string().describe("The reasoning steps taken to generate the SQL")
|
|
2051
1898
|
}),
|
|
2052
|
-
|
|
2053
|
-
error:
|
|
1899
|
+
z.object({
|
|
1900
|
+
error: z.string().describe(
|
|
2054
1901
|
"Error message explaining why the question cannot be answered with the given schema"
|
|
2055
1902
|
)
|
|
2056
1903
|
})
|
|
@@ -2079,11 +1926,11 @@ Question: ${options.input}
|
|
|
2079
1926
|
const forcedSqlOutput = structuredOutput({
|
|
2080
1927
|
model,
|
|
2081
1928
|
context,
|
|
2082
|
-
schema:
|
|
2083
|
-
sql:
|
|
1929
|
+
schema: z.object({
|
|
1930
|
+
sql: z.string().describe(
|
|
2084
1931
|
"Best-effort SQL query that answers the core intent using only available schema entities."
|
|
2085
1932
|
),
|
|
2086
|
-
reasoning:
|
|
1933
|
+
reasoning: z.string().describe("Reasoning steps for best-effort schema mapping.")
|
|
2087
1934
|
})
|
|
2088
1935
|
});
|
|
2089
1936
|
try {
|
|
@@ -2168,17 +2015,17 @@ async function withRetry(computation, options = { retries: 3 }) {
|
|
|
2168
2015
|
// packages/text2sql/src/lib/agents/suggestions.agents.ts
|
|
2169
2016
|
import { groq as groq2 } from "@ai-sdk/groq";
|
|
2170
2017
|
import dedent2 from "dedent";
|
|
2171
|
-
import
|
|
2018
|
+
import z2 from "zod";
|
|
2172
2019
|
import { agent, thirdPersonPrompt } from "@deepagents/agent";
|
|
2173
2020
|
var suggestionsAgent = agent({
|
|
2174
2021
|
name: "text2sql-suggestions",
|
|
2175
2022
|
model: groq2("openai/gpt-oss-20b"),
|
|
2176
|
-
output:
|
|
2177
|
-
suggestions:
|
|
2178
|
-
|
|
2179
|
-
question:
|
|
2180
|
-
sql:
|
|
2181
|
-
businessValue:
|
|
2023
|
+
output: z2.object({
|
|
2024
|
+
suggestions: z2.array(
|
|
2025
|
+
z2.object({
|
|
2026
|
+
question: z2.string().describe("A complex, high-impact business question."),
|
|
2027
|
+
sql: z2.string().describe("The SQL statement needed to answer the question."),
|
|
2028
|
+
businessValue: z2.string().describe("Why the question matters to stakeholders.")
|
|
2182
2029
|
})
|
|
2183
2030
|
).min(1).max(5).describe("A set of up to two advanced question + SQL pairs.")
|
|
2184
2031
|
}),
|
|
@@ -2225,9 +2072,9 @@ var Checkpoint = class _Checkpoint {
|
|
|
2225
2072
|
points;
|
|
2226
2073
|
path;
|
|
2227
2074
|
configHash;
|
|
2228
|
-
constructor(
|
|
2075
|
+
constructor(path6, configHash, points) {
|
|
2229
2076
|
this.points = points;
|
|
2230
|
-
this.path =
|
|
2077
|
+
this.path = path6;
|
|
2231
2078
|
this.configHash = configHash;
|
|
2232
2079
|
}
|
|
2233
2080
|
/**
|
|
@@ -2235,14 +2082,14 @@ var Checkpoint = class _Checkpoint {
|
|
|
2235
2082
|
* Handles corrupted files and config changes gracefully.
|
|
2236
2083
|
*/
|
|
2237
2084
|
static async load(options) {
|
|
2238
|
-
const { path:
|
|
2239
|
-
if (existsSync(
|
|
2085
|
+
const { path: path6, configHash } = options;
|
|
2086
|
+
if (existsSync(path6)) {
|
|
2240
2087
|
try {
|
|
2241
|
-
const content = readFileSync(
|
|
2088
|
+
const content = readFileSync(path6, "utf-8");
|
|
2242
2089
|
const file = JSON.parse(content);
|
|
2243
2090
|
if (configHash && file.configHash && file.configHash !== configHash) {
|
|
2244
2091
|
console.log("\u26A0 Config changed, starting fresh");
|
|
2245
|
-
return new _Checkpoint(
|
|
2092
|
+
return new _Checkpoint(path6, configHash, {});
|
|
2246
2093
|
}
|
|
2247
2094
|
const points = file.points ?? {};
|
|
2248
2095
|
const totalEntries = Object.values(points).reduce(
|
|
@@ -2250,14 +2097,14 @@ var Checkpoint = class _Checkpoint {
|
|
|
2250
2097
|
0
|
|
2251
2098
|
);
|
|
2252
2099
|
console.log(`\u2713 Resuming from checkpoint (${totalEntries} entries)`);
|
|
2253
|
-
return new _Checkpoint(
|
|
2100
|
+
return new _Checkpoint(path6, configHash, points);
|
|
2254
2101
|
} catch {
|
|
2255
2102
|
console.log("\u26A0 Checkpoint corrupted, starting fresh");
|
|
2256
|
-
return new _Checkpoint(
|
|
2103
|
+
return new _Checkpoint(path6, configHash, {});
|
|
2257
2104
|
}
|
|
2258
2105
|
}
|
|
2259
2106
|
console.log("Starting new checkpoint");
|
|
2260
|
-
return new _Checkpoint(
|
|
2107
|
+
return new _Checkpoint(path6, configHash, {});
|
|
2261
2108
|
}
|
|
2262
2109
|
/**
|
|
2263
2110
|
* Run a single computation with checkpointing.
|
|
@@ -2391,12 +2238,12 @@ import { createHash as createHash3 } from "node:crypto";
|
|
|
2391
2238
|
import { existsSync as existsSync2 } from "node:fs";
|
|
2392
2239
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2393
2240
|
import { tmpdir } from "node:os";
|
|
2394
|
-
import
|
|
2241
|
+
import path2 from "node:path";
|
|
2395
2242
|
var FileCache = class {
|
|
2396
2243
|
path;
|
|
2397
2244
|
constructor(watermark, extension = ".txt") {
|
|
2398
2245
|
const hash2 = createHash3("md5").update(watermark).digest("hex");
|
|
2399
|
-
this.path =
|
|
2246
|
+
this.path = path2.join(tmpdir(), `text2sql-${hash2}${extension}`);
|
|
2400
2247
|
}
|
|
2401
2248
|
async get() {
|
|
2402
2249
|
if (existsSync2(this.path)) {
|
|
@@ -2425,7 +2272,7 @@ var JsonCache = class extends FileCache {
|
|
|
2425
2272
|
};
|
|
2426
2273
|
|
|
2427
2274
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
2428
|
-
import * as
|
|
2275
|
+
import * as path3 from "node:path";
|
|
2429
2276
|
import { DatabaseSync } from "node:sqlite";
|
|
2430
2277
|
|
|
2431
2278
|
// packages/text2sql/src/lib/fs/sqlite/ddl.sqlite-fs.sql
|
|
@@ -2473,7 +2320,7 @@ var SqliteFs = class {
|
|
|
2473
2320
|
const segments = p.split("/").filter(Boolean);
|
|
2474
2321
|
let currentPath = "/";
|
|
2475
2322
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
2476
|
-
currentPath =
|
|
2323
|
+
currentPath = path3.posix.join(currentPath, segments[i]);
|
|
2477
2324
|
const exists = this.#stmt("SELECT 1 FROM fs_entries WHERE path = ?").get(
|
|
2478
2325
|
currentPath
|
|
2479
2326
|
);
|
|
@@ -2494,7 +2341,7 @@ var SqliteFs = class {
|
|
|
2494
2341
|
return stmt;
|
|
2495
2342
|
}
|
|
2496
2343
|
#normalizeRoot(root) {
|
|
2497
|
-
return
|
|
2344
|
+
return path3.posix.resolve("/", root.trim());
|
|
2498
2345
|
}
|
|
2499
2346
|
#prefixPath(p) {
|
|
2500
2347
|
if (!this.#root) {
|
|
@@ -2503,7 +2350,7 @@ var SqliteFs = class {
|
|
|
2503
2350
|
if (p === "/") {
|
|
2504
2351
|
return this.#root;
|
|
2505
2352
|
}
|
|
2506
|
-
return
|
|
2353
|
+
return path3.posix.join(this.#root, p);
|
|
2507
2354
|
}
|
|
2508
2355
|
#unprefixPath(p) {
|
|
2509
2356
|
if (!this.#root) {
|
|
@@ -2529,10 +2376,10 @@ var SqliteFs = class {
|
|
|
2529
2376
|
}
|
|
2530
2377
|
}
|
|
2531
2378
|
#normalizePath(p) {
|
|
2532
|
-
return
|
|
2379
|
+
return path3.posix.resolve("/", p);
|
|
2533
2380
|
}
|
|
2534
2381
|
#dirname(p) {
|
|
2535
|
-
const dir =
|
|
2382
|
+
const dir = path3.posix.dirname(p);
|
|
2536
2383
|
return dir === "" ? "/" : dir;
|
|
2537
2384
|
}
|
|
2538
2385
|
#ensureParentExists(filePath) {
|
|
@@ -2595,7 +2442,7 @@ var SqliteFs = class {
|
|
|
2595
2442
|
}
|
|
2596
2443
|
seen.add(p);
|
|
2597
2444
|
const target = this.#normalizePath(
|
|
2598
|
-
|
|
2445
|
+
path3.posix.resolve(this.#dirname(p), entry.symlinkTarget)
|
|
2599
2446
|
);
|
|
2600
2447
|
return this.#resolveSymlink(target, seen);
|
|
2601
2448
|
}
|
|
@@ -2747,11 +2594,11 @@ var SqliteFs = class {
|
|
|
2747
2594
|
this.#useTransaction(() => {
|
|
2748
2595
|
if (options?.recursive) {
|
|
2749
2596
|
const rootPath = this.#root || "/";
|
|
2750
|
-
const relativePath =
|
|
2597
|
+
const relativePath = path3.posix.relative(rootPath, prefixed);
|
|
2751
2598
|
const segments = relativePath.split("/").filter(Boolean);
|
|
2752
2599
|
let currentPath = rootPath;
|
|
2753
2600
|
for (const segment of segments) {
|
|
2754
|
-
currentPath =
|
|
2601
|
+
currentPath = path3.posix.join(currentPath, segment);
|
|
2755
2602
|
const exists = this.#stmt(
|
|
2756
2603
|
"SELECT type FROM fs_entries WHERE path = ?"
|
|
2757
2604
|
).get(currentPath);
|
|
@@ -2802,7 +2649,7 @@ var SqliteFs = class {
|
|
|
2802
2649
|
AND path != ?
|
|
2803
2650
|
AND path NOT LIKE ? || '%/%'`
|
|
2804
2651
|
).all(prefix, resolved, prefix);
|
|
2805
|
-
return rows.map((row) =>
|
|
2652
|
+
return rows.map((row) => path3.posix.basename(row.path));
|
|
2806
2653
|
}
|
|
2807
2654
|
async readdirWithFileTypes(dirPath) {
|
|
2808
2655
|
const normalized = this.#normalizePath(dirPath);
|
|
@@ -2825,7 +2672,7 @@ var SqliteFs = class {
|
|
|
2825
2672
|
AND path NOT LIKE ? || '%/%'`
|
|
2826
2673
|
).all(prefix, resolved, prefix);
|
|
2827
2674
|
return rows.map((row) => ({
|
|
2828
|
-
name:
|
|
2675
|
+
name: path3.posix.basename(row.path),
|
|
2829
2676
|
isFile: row.type === "file",
|
|
2830
2677
|
isDirectory: row.type === "directory",
|
|
2831
2678
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -2880,8 +2727,8 @@ var SqliteFs = class {
|
|
|
2880
2727
|
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%'`
|
|
2881
2728
|
).all(srcPrefixed, srcPrefixed);
|
|
2882
2729
|
for (const entry of allEntries) {
|
|
2883
|
-
const relativePath =
|
|
2884
|
-
const newPath =
|
|
2730
|
+
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2731
|
+
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2885
2732
|
this.#stmt(
|
|
2886
2733
|
`INSERT OR REPLACE INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2887
2734
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
@@ -2948,8 +2795,8 @@ var SqliteFs = class {
|
|
|
2948
2795
|
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%' ORDER BY path DESC`
|
|
2949
2796
|
).all(srcPrefixed, srcPrefixed);
|
|
2950
2797
|
for (const entry of [...allEntries].reverse()) {
|
|
2951
|
-
const relativePath =
|
|
2952
|
-
const newPath =
|
|
2798
|
+
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2799
|
+
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2953
2800
|
this.#stmt(
|
|
2954
2801
|
`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2955
2802
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
@@ -3002,7 +2849,7 @@ var SqliteFs = class {
|
|
|
3002
2849
|
});
|
|
3003
2850
|
}
|
|
3004
2851
|
resolvePath(base, relativePath) {
|
|
3005
|
-
return
|
|
2852
|
+
return path3.posix.resolve(base, relativePath);
|
|
3006
2853
|
}
|
|
3007
2854
|
getAllPaths() {
|
|
3008
2855
|
const rows = this.#stmt(
|
|
@@ -3114,7 +2961,7 @@ var SqliteFs = class {
|
|
|
3114
2961
|
|
|
3115
2962
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
3116
2963
|
import { createRequire } from "node:module";
|
|
3117
|
-
import * as
|
|
2964
|
+
import * as path4 from "node:path";
|
|
3118
2965
|
|
|
3119
2966
|
// packages/text2sql/src/lib/fs/mssql/ddl.mssql-fs.ts
|
|
3120
2967
|
function mssqlFsDDL(schema) {
|
|
@@ -3240,7 +3087,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3240
3087
|
const segments = p.split("/").filter(Boolean);
|
|
3241
3088
|
let currentPath = "/";
|
|
3242
3089
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
3243
|
-
currentPath =
|
|
3090
|
+
currentPath = path4.posix.join(currentPath, segments[i]);
|
|
3244
3091
|
const exists = await this.#rawQuery(
|
|
3245
3092
|
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3246
3093
|
[currentPath]
|
|
@@ -3292,7 +3139,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3292
3139
|
}
|
|
3293
3140
|
}
|
|
3294
3141
|
#normalizeRoot(root) {
|
|
3295
|
-
return
|
|
3142
|
+
return path4.posix.resolve("/", root.trim());
|
|
3296
3143
|
}
|
|
3297
3144
|
#prefixPath(p) {
|
|
3298
3145
|
if (!this.#root) {
|
|
@@ -3301,7 +3148,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3301
3148
|
if (p === "/") {
|
|
3302
3149
|
return this.#root;
|
|
3303
3150
|
}
|
|
3304
|
-
return
|
|
3151
|
+
return path4.posix.join(this.#root, p);
|
|
3305
3152
|
}
|
|
3306
3153
|
#unprefixPath(p) {
|
|
3307
3154
|
if (!this.#root) {
|
|
@@ -3316,10 +3163,10 @@ var MssqlFs = class _MssqlFs {
|
|
|
3316
3163
|
return p;
|
|
3317
3164
|
}
|
|
3318
3165
|
#normalizePath(p) {
|
|
3319
|
-
return
|
|
3166
|
+
return path4.posix.resolve("/", p);
|
|
3320
3167
|
}
|
|
3321
3168
|
#dirname(p) {
|
|
3322
|
-
const dir =
|
|
3169
|
+
const dir = path4.posix.dirname(p);
|
|
3323
3170
|
return dir === "" ? "/" : dir;
|
|
3324
3171
|
}
|
|
3325
3172
|
async #ensureParentExists(filePath, transaction) {
|
|
@@ -3408,7 +3255,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3408
3255
|
}
|
|
3409
3256
|
seen.add(p);
|
|
3410
3257
|
const target = this.#normalizePath(
|
|
3411
|
-
|
|
3258
|
+
path4.posix.resolve(this.#dirname(p), entry.symlinkTarget)
|
|
3412
3259
|
);
|
|
3413
3260
|
return this.#resolveSymlink(target, seen);
|
|
3414
3261
|
}
|
|
@@ -3591,11 +3438,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
3591
3438
|
await this.#useTransaction(async (transaction) => {
|
|
3592
3439
|
if (options?.recursive) {
|
|
3593
3440
|
const rootPath = this.#root || "/";
|
|
3594
|
-
const relativePath =
|
|
3441
|
+
const relativePath = path4.posix.relative(rootPath, prefixed);
|
|
3595
3442
|
const segments = relativePath.split("/").filter(Boolean);
|
|
3596
3443
|
let currentPath = rootPath;
|
|
3597
3444
|
for (const segment of segments) {
|
|
3598
|
-
currentPath =
|
|
3445
|
+
currentPath = path4.posix.join(currentPath, segment);
|
|
3599
3446
|
const checkReq = transaction.request();
|
|
3600
3447
|
checkReq.input("p0", currentPath);
|
|
3601
3448
|
const result = await checkReq.query(
|
|
@@ -3659,7 +3506,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3659
3506
|
AND path NOT LIKE @p0 + '%/%'`,
|
|
3660
3507
|
[prefix, resolved]
|
|
3661
3508
|
);
|
|
3662
|
-
return rows.map((row) =>
|
|
3509
|
+
return rows.map((row) => path4.posix.basename(row.path));
|
|
3663
3510
|
}
|
|
3664
3511
|
async readdirWithFileTypes(dirPath) {
|
|
3665
3512
|
const normalized = this.#normalizePath(dirPath);
|
|
@@ -3685,7 +3532,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3685
3532
|
[prefix, resolved]
|
|
3686
3533
|
);
|
|
3687
3534
|
return rows.map((row) => ({
|
|
3688
|
-
name:
|
|
3535
|
+
name: path4.posix.basename(row.path),
|
|
3689
3536
|
isFile: row.type === "file",
|
|
3690
3537
|
isDirectory: row.type === "directory",
|
|
3691
3538
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -3754,8 +3601,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
3754
3601
|
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%'`
|
|
3755
3602
|
);
|
|
3756
3603
|
for (const entry of allEntriesResult.recordset) {
|
|
3757
|
-
const relativePath =
|
|
3758
|
-
const newPath =
|
|
3604
|
+
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
3605
|
+
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
3759
3606
|
const insertReq = transaction.request();
|
|
3760
3607
|
insertReq.input("p0", newPath);
|
|
3761
3608
|
insertReq.input("p1", entry.type);
|
|
@@ -3864,8 +3711,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
3864
3711
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @dp0 OR path LIKE @dp0 + '/%'`
|
|
3865
3712
|
);
|
|
3866
3713
|
for (const entry of [...allEntriesResult.recordset].reverse()) {
|
|
3867
|
-
const relativePath =
|
|
3868
|
-
const newPath =
|
|
3714
|
+
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
3715
|
+
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
3869
3716
|
const insertReq = transaction.request();
|
|
3870
3717
|
insertReq.input("p0", newPath);
|
|
3871
3718
|
insertReq.input("p1", entry.type);
|
|
@@ -3958,7 +3805,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3958
3805
|
});
|
|
3959
3806
|
}
|
|
3960
3807
|
resolvePath(base, relativePath) {
|
|
3961
|
-
return
|
|
3808
|
+
return path4.posix.resolve(base, relativePath);
|
|
3962
3809
|
}
|
|
3963
3810
|
getAllPaths() {
|
|
3964
3811
|
throw new Error(
|
|
@@ -4099,7 +3946,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
4099
3946
|
|
|
4100
3947
|
// packages/text2sql/src/lib/fs/postgres/postgres-fs.ts
|
|
4101
3948
|
import { createRequire as createRequire2 } from "node:module";
|
|
4102
|
-
import * as
|
|
3949
|
+
import * as path5 from "node:path";
|
|
4103
3950
|
|
|
4104
3951
|
// packages/text2sql/src/lib/fs/postgres/ddl.postgres-fs.ts
|
|
4105
3952
|
function postgresFsDDL(schema) {
|
|
@@ -4204,7 +4051,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4204
4051
|
const segments = p.split("/").filter(Boolean);
|
|
4205
4052
|
let currentPath = "/";
|
|
4206
4053
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
4207
|
-
currentPath =
|
|
4054
|
+
currentPath = path5.posix.join(currentPath, segments[i]);
|
|
4208
4055
|
const exists = await this.#rawQuery(
|
|
4209
4056
|
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4210
4057
|
[currentPath]
|
|
@@ -4249,7 +4096,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4249
4096
|
}
|
|
4250
4097
|
}
|
|
4251
4098
|
#normalizeRoot(root) {
|
|
4252
|
-
return
|
|
4099
|
+
return path5.posix.resolve("/", root.trim());
|
|
4253
4100
|
}
|
|
4254
4101
|
#prefixPath(p) {
|
|
4255
4102
|
if (!this.#root) {
|
|
@@ -4258,7 +4105,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4258
4105
|
if (p === "/") {
|
|
4259
4106
|
return this.#root;
|
|
4260
4107
|
}
|
|
4261
|
-
return
|
|
4108
|
+
return path5.posix.join(this.#root, p);
|
|
4262
4109
|
}
|
|
4263
4110
|
#unprefixPath(p) {
|
|
4264
4111
|
if (!this.#root) {
|
|
@@ -4273,10 +4120,10 @@ var PostgresFs = class _PostgresFs {
|
|
|
4273
4120
|
return p;
|
|
4274
4121
|
}
|
|
4275
4122
|
#normalizePath(p) {
|
|
4276
|
-
return
|
|
4123
|
+
return path5.posix.resolve("/", p);
|
|
4277
4124
|
}
|
|
4278
4125
|
#dirname(p) {
|
|
4279
|
-
const dir =
|
|
4126
|
+
const dir = path5.posix.dirname(p);
|
|
4280
4127
|
return dir === "" ? "/" : dir;
|
|
4281
4128
|
}
|
|
4282
4129
|
async #ensureParentExists(filePath, client) {
|
|
@@ -4356,7 +4203,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4356
4203
|
}
|
|
4357
4204
|
seen.add(p);
|
|
4358
4205
|
const target = this.#normalizePath(
|
|
4359
|
-
|
|
4206
|
+
path5.posix.resolve(this.#dirname(p), entry.symlink_target)
|
|
4360
4207
|
);
|
|
4361
4208
|
return this.#resolveSymlink(target, seen);
|
|
4362
4209
|
}
|
|
@@ -4522,11 +4369,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
4522
4369
|
await this.#useTransaction(async (client) => {
|
|
4523
4370
|
if (options?.recursive) {
|
|
4524
4371
|
const rootPath = this.#root || "/";
|
|
4525
|
-
const relativePath =
|
|
4372
|
+
const relativePath = path5.posix.relative(rootPath, prefixed);
|
|
4526
4373
|
const segments = relativePath.split("/").filter(Boolean);
|
|
4527
4374
|
let currentPath = rootPath;
|
|
4528
4375
|
for (const segment of segments) {
|
|
4529
|
-
currentPath =
|
|
4376
|
+
currentPath = path5.posix.join(currentPath, segment);
|
|
4530
4377
|
const result = await client.query(
|
|
4531
4378
|
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4532
4379
|
[currentPath]
|
|
@@ -4584,7 +4431,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4584
4431
|
AND path NOT LIKE $1 || '%/%'`,
|
|
4585
4432
|
[prefix, resolved]
|
|
4586
4433
|
);
|
|
4587
|
-
return rows.map((row) =>
|
|
4434
|
+
return rows.map((row) => path5.posix.basename(row.path));
|
|
4588
4435
|
}
|
|
4589
4436
|
async readdirWithFileTypes(dirPath) {
|
|
4590
4437
|
const normalized = this.#normalizePath(dirPath);
|
|
@@ -4610,7 +4457,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4610
4457
|
[prefix, resolved]
|
|
4611
4458
|
);
|
|
4612
4459
|
return rows.map((row) => ({
|
|
4613
|
-
name:
|
|
4460
|
+
name: path5.posix.basename(row.path),
|
|
4614
4461
|
isFile: row.type === "file",
|
|
4615
4462
|
isDirectory: row.type === "directory",
|
|
4616
4463
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -4675,8 +4522,8 @@ var PostgresFs = class _PostgresFs {
|
|
|
4675
4522
|
[srcPrefixed]
|
|
4676
4523
|
);
|
|
4677
4524
|
for (const entry of allEntriesResult.rows) {
|
|
4678
|
-
const relativePath =
|
|
4679
|
-
const newPath =
|
|
4525
|
+
const relativePath = path5.posix.relative(srcPrefixed, entry.path);
|
|
4526
|
+
const newPath = path5.posix.join(destPrefixed, relativePath);
|
|
4680
4527
|
await client.query(
|
|
4681
4528
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime, symlink_target)
|
|
4682
4529
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
@@ -4765,8 +4612,8 @@ var PostgresFs = class _PostgresFs {
|
|
|
4765
4612
|
[destPrefixed]
|
|
4766
4613
|
);
|
|
4767
4614
|
for (const entry of [...allEntriesResult.rows].reverse()) {
|
|
4768
|
-
const relativePath =
|
|
4769
|
-
const newPath =
|
|
4615
|
+
const relativePath = path5.posix.relative(srcPrefixed, entry.path);
|
|
4616
|
+
const newPath = path5.posix.join(destPrefixed, relativePath);
|
|
4770
4617
|
await client.query(
|
|
4771
4618
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime, symlink_target)
|
|
4772
4619
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
@@ -4839,7 +4686,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4839
4686
|
});
|
|
4840
4687
|
}
|
|
4841
4688
|
resolvePath(base, relativePath) {
|
|
4842
|
-
return
|
|
4689
|
+
return path5.posix.resolve(base, relativePath);
|
|
4843
4690
|
}
|
|
4844
4691
|
getAllPaths() {
|
|
4845
4692
|
throw new Error(
|
|
@@ -4975,29 +4822,29 @@ var ScopedFs = class {
|
|
|
4975
4822
|
this.#base = options.base;
|
|
4976
4823
|
this.#prefix = options.prefix.replace(/\/$/, "");
|
|
4977
4824
|
}
|
|
4978
|
-
#scope(
|
|
4979
|
-
return `${this.#prefix}${
|
|
4825
|
+
#scope(path6) {
|
|
4826
|
+
return `${this.#prefix}${path6}`;
|
|
4980
4827
|
}
|
|
4981
|
-
#unscope(
|
|
4982
|
-
if (
|
|
4828
|
+
#unscope(path6) {
|
|
4829
|
+
if (path6 === this.#prefix) {
|
|
4983
4830
|
return "/";
|
|
4984
4831
|
}
|
|
4985
|
-
if (
|
|
4986
|
-
return
|
|
4832
|
+
if (path6.startsWith(this.#prefix + "/")) {
|
|
4833
|
+
return path6.slice(this.#prefix.length) || "/";
|
|
4987
4834
|
}
|
|
4988
|
-
return
|
|
4835
|
+
return path6;
|
|
4989
4836
|
}
|
|
4990
|
-
async writeFile(
|
|
4991
|
-
await this.#base.writeFile(this.#scope(
|
|
4837
|
+
async writeFile(path6, content, options) {
|
|
4838
|
+
await this.#base.writeFile(this.#scope(path6), content, options);
|
|
4992
4839
|
}
|
|
4993
|
-
async appendFile(
|
|
4994
|
-
await this.#base.appendFile(this.#scope(
|
|
4840
|
+
async appendFile(path6, content, options) {
|
|
4841
|
+
await this.#base.appendFile(this.#scope(path6), content, options);
|
|
4995
4842
|
}
|
|
4996
|
-
async mkdir(
|
|
4997
|
-
return this.#base.mkdir(this.#scope(
|
|
4843
|
+
async mkdir(path6, options) {
|
|
4844
|
+
return this.#base.mkdir(this.#scope(path6), options);
|
|
4998
4845
|
}
|
|
4999
|
-
async rm(
|
|
5000
|
-
await this.#base.rm(this.#scope(
|
|
4846
|
+
async rm(path6, options) {
|
|
4847
|
+
await this.#base.rm(this.#scope(path6), options);
|
|
5001
4848
|
}
|
|
5002
4849
|
async cp(src, dest, options) {
|
|
5003
4850
|
await this.#base.cp(this.#scope(src), this.#scope(dest), options);
|
|
@@ -5005,8 +4852,8 @@ var ScopedFs = class {
|
|
|
5005
4852
|
async mv(src, dest) {
|
|
5006
4853
|
await this.#base.mv(this.#scope(src), this.#scope(dest));
|
|
5007
4854
|
}
|
|
5008
|
-
async chmod(
|
|
5009
|
-
return this.#base.chmod(this.#scope(
|
|
4855
|
+
async chmod(path6, mode) {
|
|
4856
|
+
return this.#base.chmod(this.#scope(path6), mode);
|
|
5010
4857
|
}
|
|
5011
4858
|
async symlink(target, linkPath) {
|
|
5012
4859
|
await this.#base.symlink(target, this.#scope(linkPath));
|
|
@@ -5014,35 +4861,35 @@ var ScopedFs = class {
|
|
|
5014
4861
|
async link(existingPath, newPath) {
|
|
5015
4862
|
await this.#base.link(this.#scope(existingPath), this.#scope(newPath));
|
|
5016
4863
|
}
|
|
5017
|
-
readFile(
|
|
5018
|
-
return this.#base.readFile(this.#scope(
|
|
4864
|
+
readFile(path6, options) {
|
|
4865
|
+
return this.#base.readFile(this.#scope(path6), options);
|
|
5019
4866
|
}
|
|
5020
|
-
readFileBuffer(
|
|
5021
|
-
return this.#base.readFileBuffer(this.#scope(
|
|
4867
|
+
readFileBuffer(path6) {
|
|
4868
|
+
return this.#base.readFileBuffer(this.#scope(path6));
|
|
5022
4869
|
}
|
|
5023
|
-
stat(
|
|
5024
|
-
return this.#base.stat(this.#scope(
|
|
4870
|
+
stat(path6) {
|
|
4871
|
+
return this.#base.stat(this.#scope(path6));
|
|
5025
4872
|
}
|
|
5026
|
-
lstat(
|
|
5027
|
-
return this.#base.lstat(this.#scope(
|
|
4873
|
+
lstat(path6) {
|
|
4874
|
+
return this.#base.lstat(this.#scope(path6));
|
|
5028
4875
|
}
|
|
5029
|
-
readdir(
|
|
5030
|
-
return this.#base.readdir(this.#scope(
|
|
4876
|
+
readdir(path6) {
|
|
4877
|
+
return this.#base.readdir(this.#scope(path6));
|
|
5031
4878
|
}
|
|
5032
|
-
readdirWithFileTypes(
|
|
5033
|
-
return this.#base.readdirWithFileTypes(this.#scope(
|
|
4879
|
+
readdirWithFileTypes(path6) {
|
|
4880
|
+
return this.#base.readdirWithFileTypes(this.#scope(path6));
|
|
5034
4881
|
}
|
|
5035
|
-
exists(
|
|
5036
|
-
return this.#base.exists(this.#scope(
|
|
4882
|
+
exists(path6) {
|
|
4883
|
+
return this.#base.exists(this.#scope(path6));
|
|
5037
4884
|
}
|
|
5038
|
-
readlink(
|
|
5039
|
-
return this.#base.readlink(this.#scope(
|
|
4885
|
+
readlink(path6) {
|
|
4886
|
+
return this.#base.readlink(this.#scope(path6));
|
|
5040
4887
|
}
|
|
5041
|
-
realpath(
|
|
5042
|
-
return this.#base.realpath(this.#scope(
|
|
4888
|
+
realpath(path6) {
|
|
4889
|
+
return this.#base.realpath(this.#scope(path6)).then((p) => this.#unscope(p));
|
|
5043
4890
|
}
|
|
5044
|
-
utimes(
|
|
5045
|
-
return this.#base.utimes(this.#scope(
|
|
4891
|
+
utimes(path6, atime, mtime) {
|
|
4892
|
+
return this.#base.utimes(this.#scope(path6), atime, mtime);
|
|
5046
4893
|
}
|
|
5047
4894
|
resolvePath(base, relativePath) {
|
|
5048
4895
|
return this.#base.resolvePath(base, relativePath);
|
|
@@ -5053,97 +4900,6 @@ var ScopedFs = class {
|
|
|
5053
4900
|
}
|
|
5054
4901
|
};
|
|
5055
4902
|
|
|
5056
|
-
// packages/text2sql/src/lib/fs/tracked-fs.ts
|
|
5057
|
-
var TrackedFs = class {
|
|
5058
|
-
#base;
|
|
5059
|
-
#createdFiles = /* @__PURE__ */ new Set();
|
|
5060
|
-
constructor(base) {
|
|
5061
|
-
this.#base = base;
|
|
5062
|
-
}
|
|
5063
|
-
getCreatedFiles() {
|
|
5064
|
-
return [...this.#createdFiles];
|
|
5065
|
-
}
|
|
5066
|
-
async writeFile(path7, content, options) {
|
|
5067
|
-
await this.#base.writeFile(path7, content, options);
|
|
5068
|
-
this.#createdFiles.add(path7);
|
|
5069
|
-
}
|
|
5070
|
-
async appendFile(path7, content, options) {
|
|
5071
|
-
await this.#base.appendFile(path7, content, options);
|
|
5072
|
-
this.#createdFiles.add(path7);
|
|
5073
|
-
}
|
|
5074
|
-
async mkdir(path7, options) {
|
|
5075
|
-
return this.#base.mkdir(path7, options);
|
|
5076
|
-
}
|
|
5077
|
-
async rm(path7, options) {
|
|
5078
|
-
await this.#base.rm(path7, options);
|
|
5079
|
-
this.#createdFiles.delete(path7);
|
|
5080
|
-
if (options?.recursive) {
|
|
5081
|
-
const prefix = path7.endsWith("/") ? path7 : path7 + "/";
|
|
5082
|
-
for (const file of this.#createdFiles) {
|
|
5083
|
-
if (file.startsWith(prefix)) {
|
|
5084
|
-
this.#createdFiles.delete(file);
|
|
5085
|
-
}
|
|
5086
|
-
}
|
|
5087
|
-
}
|
|
5088
|
-
}
|
|
5089
|
-
async cp(src, dest, options) {
|
|
5090
|
-
await this.#base.cp(src, dest, options);
|
|
5091
|
-
this.#createdFiles.add(dest);
|
|
5092
|
-
}
|
|
5093
|
-
async mv(src, dest) {
|
|
5094
|
-
await this.#base.mv(src, dest);
|
|
5095
|
-
this.#createdFiles.delete(src);
|
|
5096
|
-
this.#createdFiles.add(dest);
|
|
5097
|
-
}
|
|
5098
|
-
async chmod(path7, mode) {
|
|
5099
|
-
return this.#base.chmod(path7, mode);
|
|
5100
|
-
}
|
|
5101
|
-
async symlink(target, linkPath) {
|
|
5102
|
-
await this.#base.symlink(target, linkPath);
|
|
5103
|
-
this.#createdFiles.add(linkPath);
|
|
5104
|
-
}
|
|
5105
|
-
async link(existingPath, newPath) {
|
|
5106
|
-
await this.#base.link(existingPath, newPath);
|
|
5107
|
-
this.#createdFiles.add(newPath);
|
|
5108
|
-
}
|
|
5109
|
-
readFile(path7, options) {
|
|
5110
|
-
return this.#base.readFile(path7, options);
|
|
5111
|
-
}
|
|
5112
|
-
readFileBuffer(path7) {
|
|
5113
|
-
return this.#base.readFileBuffer(path7);
|
|
5114
|
-
}
|
|
5115
|
-
stat(path7) {
|
|
5116
|
-
return this.#base.stat(path7);
|
|
5117
|
-
}
|
|
5118
|
-
lstat(path7) {
|
|
5119
|
-
return this.#base.lstat(path7);
|
|
5120
|
-
}
|
|
5121
|
-
readdir(path7) {
|
|
5122
|
-
return this.#base.readdir(path7);
|
|
5123
|
-
}
|
|
5124
|
-
readdirWithFileTypes(path7) {
|
|
5125
|
-
return this.#base.readdirWithFileTypes(path7);
|
|
5126
|
-
}
|
|
5127
|
-
exists(path7) {
|
|
5128
|
-
return this.#base.exists(path7);
|
|
5129
|
-
}
|
|
5130
|
-
readlink(path7) {
|
|
5131
|
-
return this.#base.readlink(path7);
|
|
5132
|
-
}
|
|
5133
|
-
resolvePath(base, relativePath) {
|
|
5134
|
-
return this.#base.resolvePath(base, relativePath);
|
|
5135
|
-
}
|
|
5136
|
-
getAllPaths() {
|
|
5137
|
-
return this.#base.getAllPaths?.() ?? [];
|
|
5138
|
-
}
|
|
5139
|
-
realpath(path7) {
|
|
5140
|
-
return this.#base.realpath(path7);
|
|
5141
|
-
}
|
|
5142
|
-
utimes(path7, atime, mtime) {
|
|
5143
|
-
return this.#base.utimes(path7, atime, mtime);
|
|
5144
|
-
}
|
|
5145
|
-
};
|
|
5146
|
-
|
|
5147
4903
|
// packages/text2sql/src/lib/instructions.ts
|
|
5148
4904
|
import {
|
|
5149
4905
|
clarification,
|
|
@@ -5382,7 +5138,8 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
5382
5138
|
workflow2({
|
|
5383
5139
|
task: "Query execution",
|
|
5384
5140
|
steps: [
|
|
5385
|
-
|
|
5141
|
+
"Pick the target database from the schema fragments (each parent fragment is named after a configured database).",
|
|
5142
|
+
'Execute SQL through bash tool: sql run <db> "SELECT ..."',
|
|
5386
5143
|
"Read the output: file path, column names, and row count.",
|
|
5387
5144
|
"Use column names to construct jq filters: cat <path> | jq '.[] | {col1, col2}'",
|
|
5388
5145
|
"For large results, slice first: cat <path> | jq '.[:10]'"
|
|
@@ -5391,7 +5148,7 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
5391
5148
|
guardrail2({
|
|
5392
5149
|
rule: "Do not attempt SQL access through non-bash tools.",
|
|
5393
5150
|
reason: "SQL access is only available through the virtual bash environment.",
|
|
5394
|
-
action: 'Use
|
|
5151
|
+
action: 'Use `sql run <db> "SELECT ..."` and `sql validate <db> "SELECT ..."` through bash, where `<db>` is the configured database name.'
|
|
5395
5152
|
}),
|
|
5396
5153
|
explain({
|
|
5397
5154
|
concept: "sql command output format",
|
|
@@ -5429,214 +5186,128 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
5429
5186
|
return baseTeachings;
|
|
5430
5187
|
}
|
|
5431
5188
|
|
|
5189
|
+
// packages/text2sql/src/lib/sandbox.ts
|
|
5190
|
+
function sqlSandboxExtension(adapters, options = {}) {
|
|
5191
|
+
const adapterNames = Object.keys(adapters);
|
|
5192
|
+
if (adapterNames.length === 0) {
|
|
5193
|
+
throw new Error("sqlSandboxExtension requires at least one adapter");
|
|
5194
|
+
}
|
|
5195
|
+
validateAdapterNames(adapterNames);
|
|
5196
|
+
const { command, repair } = createSqlCommand(adapters, options);
|
|
5197
|
+
return {
|
|
5198
|
+
commands: [command],
|
|
5199
|
+
plugins: [new SqlBacktickRewritePlugin(), new SqlProxyEnforcementPlugin()],
|
|
5200
|
+
onBeforeBashCall: ({ command: c }) => ({ command: repair(c) })
|
|
5201
|
+
};
|
|
5202
|
+
}
|
|
5203
|
+
|
|
5432
5204
|
// packages/text2sql/src/lib/sql.ts
|
|
5433
|
-
import {
|
|
5434
|
-
APICallError as APICallError2,
|
|
5435
|
-
InvalidToolInputError,
|
|
5436
|
-
NoSuchToolError,
|
|
5437
|
-
ToolCallRepairError,
|
|
5438
|
-
createUIMessageStream,
|
|
5439
|
-
generateId
|
|
5440
|
-
} from "ai";
|
|
5441
|
-
import "just-bash";
|
|
5442
5205
|
import "@deepagents/agent";
|
|
5443
5206
|
import {
|
|
5444
5207
|
agent as agent2,
|
|
5445
|
-
|
|
5446
|
-
chatMessageToUIMessage,
|
|
5208
|
+
chat,
|
|
5447
5209
|
errorRecoveryGuardrail,
|
|
5448
|
-
|
|
5449
|
-
staticChatTitle,
|
|
5450
|
-
toMessageFragment
|
|
5210
|
+
fragment as fragment3
|
|
5451
5211
|
} from "@deepagents/context";
|
|
5452
5212
|
var Text2Sql = class {
|
|
5453
5213
|
#config;
|
|
5214
|
+
#introspection;
|
|
5454
5215
|
constructor(config) {
|
|
5216
|
+
const adapterNames = Object.keys(config.adapters);
|
|
5217
|
+
if (adapterNames.length === 0) {
|
|
5218
|
+
throw new Error("Text2Sql requires at least one adapter");
|
|
5219
|
+
}
|
|
5220
|
+
validateAdapterNames(adapterNames);
|
|
5455
5221
|
this.#config = {
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
tools: config.tools ?? {},
|
|
5459
|
-
model: config.model,
|
|
5460
|
-
transform: config.transform,
|
|
5461
|
-
filesystem: config.filesystem,
|
|
5462
|
-
introspection: new JsonCache(
|
|
5463
|
-
"introspection-" + config.version
|
|
5464
|
-
)
|
|
5222
|
+
...config,
|
|
5223
|
+
tools: config.tools ?? {}
|
|
5465
5224
|
};
|
|
5225
|
+
this.#introspection = new Map(
|
|
5226
|
+
Object.keys(config.adapters).map((name) => [
|
|
5227
|
+
name,
|
|
5228
|
+
new JsonCache(
|
|
5229
|
+
`introspection-${config.version}-${name}`
|
|
5230
|
+
)
|
|
5231
|
+
])
|
|
5232
|
+
);
|
|
5233
|
+
}
|
|
5234
|
+
#requireAdapter(name) {
|
|
5235
|
+
const adapter = this.#config.adapters[name];
|
|
5236
|
+
if (!adapter) {
|
|
5237
|
+
const available = Object.keys(this.#config.adapters).join(", ");
|
|
5238
|
+
throw new Error(`Unknown adapter "${name}". Available: ${available}`);
|
|
5239
|
+
}
|
|
5240
|
+
return adapter;
|
|
5466
5241
|
}
|
|
5467
|
-
async toSql(input) {
|
|
5468
|
-
const
|
|
5242
|
+
async toSql(input, adapterName) {
|
|
5243
|
+
const adapter = this.#requireAdapter(adapterName);
|
|
5244
|
+
const fragments = await this.#indexAdapter(adapterName, adapter);
|
|
5469
5245
|
const result = await toSql({
|
|
5470
5246
|
input,
|
|
5471
|
-
adapter
|
|
5472
|
-
fragments
|
|
5247
|
+
adapter,
|
|
5248
|
+
fragments,
|
|
5473
5249
|
model: this.#config.model
|
|
5474
5250
|
});
|
|
5475
5251
|
return result.sql;
|
|
5476
5252
|
}
|
|
5477
|
-
/**
|
|
5478
|
-
* Introspect the database schema and return context fragments.
|
|
5479
|
-
* Results are cached to avoid repeated introspection.
|
|
5480
|
-
*/
|
|
5481
5253
|
async index() {
|
|
5482
|
-
const
|
|
5254
|
+
const entries = Object.entries(this.#config.adapters);
|
|
5255
|
+
const wrapped = await Promise.all(
|
|
5256
|
+
entries.map(async ([name, adapter]) => {
|
|
5257
|
+
const schema = await this.#indexAdapter(name, adapter);
|
|
5258
|
+
return fragment3(name, ...schema);
|
|
5259
|
+
})
|
|
5260
|
+
);
|
|
5261
|
+
return wrapped;
|
|
5262
|
+
}
|
|
5263
|
+
async #indexAdapter(name, adapter) {
|
|
5264
|
+
const cache = this.#introspection.get(name);
|
|
5265
|
+
if (!cache) {
|
|
5266
|
+
throw new Error(`no introspection cache registered for "${name}"`);
|
|
5267
|
+
}
|
|
5268
|
+
const cached = await cache.read();
|
|
5483
5269
|
if (cached) {
|
|
5484
5270
|
return cached;
|
|
5485
5271
|
}
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5272
|
+
try {
|
|
5273
|
+
const fragments = await adapter.introspect();
|
|
5274
|
+
await cache.write(fragments);
|
|
5275
|
+
return fragments;
|
|
5276
|
+
} catch (error) {
|
|
5277
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
5278
|
+
throw new Error(`introspecting adapter "${name}": ${reason}`, {
|
|
5279
|
+
cause: error
|
|
5280
|
+
});
|
|
5281
|
+
}
|
|
5489
5282
|
}
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
*
|
|
5494
|
-
* @example
|
|
5495
|
-
* // Generate questions for existing SQL
|
|
5496
|
-
* const pairs = await text2sql.toPairs(
|
|
5497
|
-
* (adapter) => new SqlExtractor(sqls, adapter, { validateSql: true })
|
|
5498
|
-
* );
|
|
5499
|
-
*
|
|
5500
|
-
* @example
|
|
5501
|
-
* // Extract from chat history with validation
|
|
5502
|
-
* const pairs = await text2sql.toPairs(
|
|
5503
|
-
* (adapter) => new ValidatedProducer(
|
|
5504
|
-
* new MessageExtractor(messages),
|
|
5505
|
-
* adapter
|
|
5506
|
-
* )
|
|
5507
|
-
* );
|
|
5508
|
-
*/
|
|
5509
|
-
async toPairs(factory) {
|
|
5510
|
-
const producer = factory(this.#config.adapter);
|
|
5283
|
+
async toPairs(adapterName, factory) {
|
|
5284
|
+
const adapter = this.#requireAdapter(adapterName);
|
|
5285
|
+
const producer = factory(adapter);
|
|
5511
5286
|
return producer.toPairs();
|
|
5512
5287
|
}
|
|
5513
5288
|
async chat(messages, options) {
|
|
5514
5289
|
if (messages.length === 0) {
|
|
5515
5290
|
throw new Error("messages must not be empty");
|
|
5516
5291
|
}
|
|
5517
|
-
const trackedFs = new TrackedFs(this.#config.filesystem);
|
|
5518
5292
|
const context = this.#config.context(
|
|
5519
5293
|
...guidelines(),
|
|
5520
5294
|
...await this.index()
|
|
5521
5295
|
);
|
|
5522
|
-
const lastItem = messages[messages.length - 1];
|
|
5523
|
-
const lastFragment = toMessageFragment(lastItem);
|
|
5524
|
-
const lastUIMessage = chatMessageToUIMessage(lastItem);
|
|
5525
|
-
let assistantMsgId;
|
|
5526
|
-
if (lastUIMessage.role === "assistant") {
|
|
5527
|
-
context.set(lastFragment);
|
|
5528
|
-
await context.save({ branch: false });
|
|
5529
|
-
assistantMsgId = lastUIMessage.id;
|
|
5530
|
-
} else {
|
|
5531
|
-
context.set(lastFragment);
|
|
5532
|
-
await context.save();
|
|
5533
|
-
assistantMsgId = generateId();
|
|
5534
|
-
}
|
|
5535
|
-
const uiMessages = messages.map(chatMessageToUIMessage);
|
|
5536
|
-
let title = null;
|
|
5537
|
-
if (!context.chat?.title) {
|
|
5538
|
-
const firstUserMsg = uiMessages.find((m) => m.role === "user");
|
|
5539
|
-
if (firstUserMsg) {
|
|
5540
|
-
if (options?.generateTitle) {
|
|
5541
|
-
title = await generateChatTitle({
|
|
5542
|
-
message: firstUserMsg,
|
|
5543
|
-
model: this.#config.model,
|
|
5544
|
-
abortSignal: options?.abortSignal
|
|
5545
|
-
});
|
|
5546
|
-
} else {
|
|
5547
|
-
title = staticChatTitle(firstUserMsg);
|
|
5548
|
-
}
|
|
5549
|
-
await context.updateChat({ title });
|
|
5550
|
-
}
|
|
5551
|
-
}
|
|
5552
|
-
const { mounts: skillMounts } = context.getSkillMounts();
|
|
5553
|
-
const { tools } = await createResultTools({
|
|
5554
|
-
adapter: this.#config.adapter,
|
|
5555
|
-
skillMounts,
|
|
5556
|
-
filesystem: trackedFs
|
|
5557
|
-
});
|
|
5558
5296
|
const chatAgent = agent2({
|
|
5559
5297
|
name: "text2sql",
|
|
5298
|
+
sandbox: this.#config.sandbox,
|
|
5560
5299
|
model: this.#config.model,
|
|
5561
5300
|
context,
|
|
5562
|
-
tools:
|
|
5563
|
-
...tools,
|
|
5564
|
-
...this.#config.tools
|
|
5565
|
-
},
|
|
5301
|
+
tools: this.#config.tools,
|
|
5566
5302
|
guardrails: [errorRecoveryGuardrail],
|
|
5567
5303
|
maxGuardrailRetries: 3
|
|
5568
5304
|
});
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
const uiStream = result.toUIMessageStream({
|
|
5574
|
-
onError: (error) => this.#formatError(error),
|
|
5575
|
-
sendStart: true,
|
|
5576
|
-
sendFinish: true,
|
|
5577
|
-
sendReasoning: true,
|
|
5578
|
-
sendSources: true,
|
|
5579
|
-
originalMessages: uiMessages,
|
|
5580
|
-
generateMessageId: () => assistantMsgId,
|
|
5581
|
-
messageMetadata: ({ part }) => {
|
|
5582
|
-
if (part.type === "finish-step") {
|
|
5583
|
-
return {
|
|
5584
|
-
finishReason: part.finishReason,
|
|
5585
|
-
usage: part.usage
|
|
5586
|
-
};
|
|
5587
|
-
}
|
|
5588
|
-
if (part.type === "finish") {
|
|
5589
|
-
return {
|
|
5590
|
-
finishReason: part.finishReason,
|
|
5591
|
-
totalUsage: part.totalUsage
|
|
5592
|
-
};
|
|
5593
|
-
}
|
|
5594
|
-
return void 0;
|
|
5595
|
-
}
|
|
5596
|
-
});
|
|
5597
|
-
return createUIMessageStream({
|
|
5598
|
-
originalMessages: uiMessages,
|
|
5599
|
-
generateId: () => assistantMsgId,
|
|
5600
|
-
onStepFinish: async ({ responseMessage }) => {
|
|
5601
|
-
context.set(assistant({ ...responseMessage, id: assistantMsgId }));
|
|
5602
|
-
await context.save({ branch: false });
|
|
5603
|
-
},
|
|
5604
|
-
onFinish: async ({ responseMessage }) => {
|
|
5605
|
-
const createdFiles = trackedFs.getCreatedFiles();
|
|
5606
|
-
context.set(
|
|
5607
|
-
assistant({
|
|
5608
|
-
...responseMessage,
|
|
5609
|
-
id: assistantMsgId,
|
|
5610
|
-
metadata: {
|
|
5611
|
-
...responseMessage.metadata ?? {},
|
|
5612
|
-
createdFiles
|
|
5613
|
-
}
|
|
5614
|
-
})
|
|
5615
|
-
);
|
|
5616
|
-
await context.save({ branch: false });
|
|
5617
|
-
await context.trackUsage(await result.totalUsage);
|
|
5618
|
-
},
|
|
5619
|
-
execute: async ({ writer }) => {
|
|
5620
|
-
writer.merge(uiStream);
|
|
5621
|
-
if (title) {
|
|
5622
|
-
writer.write({ type: "data-chat-title", data: title });
|
|
5623
|
-
}
|
|
5624
|
-
}
|
|
5305
|
+
return chat(chatAgent, messages, {
|
|
5306
|
+
abortSignal: options?.abortSignal,
|
|
5307
|
+
generateTitle: options?.generateTitle,
|
|
5308
|
+
transform: this.#config.transform
|
|
5625
5309
|
});
|
|
5626
5310
|
}
|
|
5627
|
-
#formatError(error) {
|
|
5628
|
-
if (NoSuchToolError.isInstance(error)) {
|
|
5629
|
-
return "The model tried to call an unknown tool.";
|
|
5630
|
-
} else if (InvalidToolInputError.isInstance(error)) {
|
|
5631
|
-
return "The model called a tool with invalid arguments.";
|
|
5632
|
-
} else if (ToolCallRepairError.isInstance(error)) {
|
|
5633
|
-
return "The model tried to call a tool with invalid arguments, but it was repaired.";
|
|
5634
|
-
} else if (APICallError2.isInstance(error)) {
|
|
5635
|
-
console.error("Upstream API call failed:", error);
|
|
5636
|
-
return `Upstream API call failed with status ${error.statusCode}: ${error.message}`;
|
|
5637
|
-
}
|
|
5638
|
-
return JSON.stringify(error);
|
|
5639
|
-
}
|
|
5640
5311
|
};
|
|
5641
5312
|
export {
|
|
5642
5313
|
Adapter,
|
|
@@ -5646,17 +5317,20 @@ export {
|
|
|
5646
5317
|
MssqlFs,
|
|
5647
5318
|
Point,
|
|
5648
5319
|
PostgresFs,
|
|
5320
|
+
SQLReadOnlyError,
|
|
5649
5321
|
SQLScopeError,
|
|
5650
5322
|
SQLValidationError,
|
|
5651
5323
|
ScopedFs,
|
|
5324
|
+
SqlBacktickRewritePlugin,
|
|
5325
|
+
SqlProxyEnforcementPlugin,
|
|
5326
|
+
SqlProxyViolationError,
|
|
5652
5327
|
SqliteFs,
|
|
5653
5328
|
Text2Sql,
|
|
5654
|
-
TrackedFs,
|
|
5655
5329
|
UnanswerableSQLError,
|
|
5656
5330
|
applyTablesFilter,
|
|
5657
5331
|
column,
|
|
5658
5332
|
constraint,
|
|
5659
|
-
|
|
5333
|
+
createSqlCommand,
|
|
5660
5334
|
dialectInfo,
|
|
5661
5335
|
filterRelationshipsByTables,
|
|
5662
5336
|
filterTablesByName,
|
|
@@ -5664,11 +5338,14 @@ export {
|
|
|
5664
5338
|
guidelines,
|
|
5665
5339
|
hashConfig,
|
|
5666
5340
|
index,
|
|
5341
|
+
isValidAdapterName,
|
|
5667
5342
|
matchesFilter,
|
|
5668
5343
|
relationship,
|
|
5344
|
+
sqlSandboxExtension,
|
|
5669
5345
|
suggestionsAgent,
|
|
5670
5346
|
table,
|
|
5671
5347
|
toSql,
|
|
5348
|
+
validateAdapterNames,
|
|
5672
5349
|
view
|
|
5673
5350
|
};
|
|
5674
5351
|
//# sourceMappingURL=index.js.map
|