@deepagents/text2sql 3.1.0 → 4.0.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 +46 -21
- package/dist/bin/sql.js +95 -32
- package/dist/index.js +172 -114
- package/dist/index.js.map +4 -4
- package/dist/lib/adapter-index.d.ts +1 -1
- package/dist/lib/adapter-index.d.ts.map +1 -1
- package/dist/lib/adapter-name.d.ts +8 -0
- package/dist/lib/adapter-name.d.ts.map +1 -1
- package/dist/lib/index-lock.d.ts +37 -8
- package/dist/lib/index-lock.d.ts.map +1 -1
- package/dist/lib/resolve-adapter.d.ts +14 -0
- package/dist/lib/resolve-adapter.d.ts.map +1 -0
- package/dist/lib/sql-command.d.ts +4 -1
- package/dist/lib/sql-command.d.ts.map +1 -1
- package/dist/lib/sql.d.ts +1 -1
- package/dist/lib/sql.d.ts.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// packages/text2sql/src/lib/adapter-name.ts
|
|
2
2
|
var ADAPTER_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
3
|
+
var DATABASE_NAME_FRAGMENT = "database";
|
|
4
|
+
var RESERVED_ADAPTER_NAMES = /* @__PURE__ */ new Set([DATABASE_NAME_FRAGMENT]);
|
|
3
5
|
function isValidAdapterName(name) {
|
|
4
6
|
return name != null && ADAPTER_NAME_PATTERN.test(name);
|
|
5
7
|
}
|
|
@@ -10,6 +12,9 @@ function validateAdapterNames(names) {
|
|
|
10
12
|
`Invalid adapter name "${name}": must match ${ADAPTER_NAME_PATTERN}`
|
|
11
13
|
);
|
|
12
14
|
}
|
|
15
|
+
if (RESERVED_ADAPTER_NAMES.has(name)) {
|
|
16
|
+
throw new Error(`Adapter name "${name}" is reserved`);
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
}
|
|
15
20
|
|
|
@@ -1365,6 +1370,51 @@ var FileIndexCache = class {
|
|
|
1365
1370
|
}
|
|
1366
1371
|
};
|
|
1367
1372
|
|
|
1373
|
+
// packages/text2sql/src/lib/index-lock.ts
|
|
1374
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1375
|
+
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
1376
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
1377
|
+
import * as path2 from "node:path";
|
|
1378
|
+
import { lock as acquireLock } from "proper-lockfile";
|
|
1379
|
+
var DEFAULT_STALE_MS = 3e4;
|
|
1380
|
+
var DEFAULT_RETRIES = {
|
|
1381
|
+
retries: 10,
|
|
1382
|
+
factor: 2,
|
|
1383
|
+
minTimeout: 100,
|
|
1384
|
+
maxTimeout: 2e3
|
|
1385
|
+
};
|
|
1386
|
+
var FileIndexLock = class {
|
|
1387
|
+
#dir;
|
|
1388
|
+
#namespace;
|
|
1389
|
+
#stale;
|
|
1390
|
+
#retries;
|
|
1391
|
+
constructor(options = {}) {
|
|
1392
|
+
this.#dir = options.dir ?? tmpdir2();
|
|
1393
|
+
this.#namespace = options.namespace;
|
|
1394
|
+
this.#stale = options.stale ?? DEFAULT_STALE_MS;
|
|
1395
|
+
this.#retries = options.retries ?? DEFAULT_RETRIES;
|
|
1396
|
+
}
|
|
1397
|
+
async run(key, fn) {
|
|
1398
|
+
await mkdir2(this.#dir, { recursive: true });
|
|
1399
|
+
const release = await acquireLock(this.#lockPathFor(key), {
|
|
1400
|
+
realpath: false,
|
|
1401
|
+
stale: this.#stale,
|
|
1402
|
+
retries: this.#retries
|
|
1403
|
+
});
|
|
1404
|
+
try {
|
|
1405
|
+
return await fn();
|
|
1406
|
+
} finally {
|
|
1407
|
+
await release().catch(() => {
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
#lockPathFor(key) {
|
|
1412
|
+
const watermark = this.#namespace ? `${this.#namespace}-${key}` : key;
|
|
1413
|
+
const hash2 = createHash2("md5").update(watermark).digest("hex");
|
|
1414
|
+
return path2.join(this.#dir, `text2sql-lock-${hash2}`);
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1368
1418
|
// packages/text2sql/src/lib/adapter-index.ts
|
|
1369
1419
|
var TEXT2SQL_INDEX_PROGRESS_CHUNK = "data-text2sql-index-progress";
|
|
1370
1420
|
var noopProgressHandler = () => {
|
|
@@ -1378,6 +1428,9 @@ function timestampProgressHandler(onProgress) {
|
|
|
1378
1428
|
});
|
|
1379
1429
|
};
|
|
1380
1430
|
}
|
|
1431
|
+
function databaseNameFragment(name) {
|
|
1432
|
+
return { name: DATABASE_NAME_FRAGMENT, data: name };
|
|
1433
|
+
}
|
|
1381
1434
|
var AdapterIndexer = class {
|
|
1382
1435
|
#adapters;
|
|
1383
1436
|
#cache;
|
|
@@ -1404,7 +1457,7 @@ var AdapterIndexer = class {
|
|
|
1404
1457
|
const settled = await Promise.allSettled(
|
|
1405
1458
|
entries.map(async ([name, adapter]) => {
|
|
1406
1459
|
const schema = await this.#indexAdapter(name, adapter, progress);
|
|
1407
|
-
return fragment2(name, ...schema);
|
|
1460
|
+
return fragment2(name, databaseNameFragment(name), ...schema);
|
|
1408
1461
|
})
|
|
1409
1462
|
);
|
|
1410
1463
|
const failed = settled.find((result) => result.status === "rejected");
|
|
@@ -1491,7 +1544,7 @@ var AdapterIndexer = class {
|
|
|
1491
1544
|
});
|
|
1492
1545
|
return cached;
|
|
1493
1546
|
}
|
|
1494
|
-
const fragments =
|
|
1547
|
+
const fragments = await this.#lock.run(key, populate);
|
|
1495
1548
|
if (servedFromCache) emitCacheHit();
|
|
1496
1549
|
progress({
|
|
1497
1550
|
type: "adapter:end",
|
|
@@ -1543,16 +1596,16 @@ function errorMessage(error) {
|
|
|
1543
1596
|
}
|
|
1544
1597
|
|
|
1545
1598
|
// packages/text2sql/src/lib/checkpoint.ts
|
|
1546
|
-
import { createHash as
|
|
1599
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
1547
1600
|
import { existsSync as existsSync2, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
1548
1601
|
import pLimit from "p-limit";
|
|
1549
1602
|
var Checkpoint = class _Checkpoint {
|
|
1550
1603
|
points;
|
|
1551
1604
|
path;
|
|
1552
1605
|
configHash;
|
|
1553
|
-
constructor(
|
|
1606
|
+
constructor(path7, configHash, points) {
|
|
1554
1607
|
this.points = points;
|
|
1555
|
-
this.path =
|
|
1608
|
+
this.path = path7;
|
|
1556
1609
|
this.configHash = configHash;
|
|
1557
1610
|
}
|
|
1558
1611
|
/**
|
|
@@ -1560,14 +1613,14 @@ var Checkpoint = class _Checkpoint {
|
|
|
1560
1613
|
* Handles corrupted files and config changes gracefully.
|
|
1561
1614
|
*/
|
|
1562
1615
|
static async load(options) {
|
|
1563
|
-
const { path:
|
|
1564
|
-
if (existsSync2(
|
|
1616
|
+
const { path: path7, configHash } = options;
|
|
1617
|
+
if (existsSync2(path7)) {
|
|
1565
1618
|
try {
|
|
1566
|
-
const content = readFileSync(
|
|
1619
|
+
const content = readFileSync(path7, "utf-8");
|
|
1567
1620
|
const file = JSON.parse(content);
|
|
1568
1621
|
if (configHash && file.configHash && file.configHash !== configHash) {
|
|
1569
1622
|
console.log("\u26A0 Config changed, starting fresh");
|
|
1570
|
-
return new _Checkpoint(
|
|
1623
|
+
return new _Checkpoint(path7, configHash, {});
|
|
1571
1624
|
}
|
|
1572
1625
|
const points = file.points ?? {};
|
|
1573
1626
|
const totalEntries = Object.values(points).reduce(
|
|
@@ -1575,14 +1628,14 @@ var Checkpoint = class _Checkpoint {
|
|
|
1575
1628
|
0
|
|
1576
1629
|
);
|
|
1577
1630
|
console.log(`\u2713 Resuming from checkpoint (${totalEntries} entries)`);
|
|
1578
|
-
return new _Checkpoint(
|
|
1631
|
+
return new _Checkpoint(path7, configHash, points);
|
|
1579
1632
|
} catch {
|
|
1580
1633
|
console.log("\u26A0 Checkpoint corrupted, starting fresh");
|
|
1581
|
-
return new _Checkpoint(
|
|
1634
|
+
return new _Checkpoint(path7, configHash, {});
|
|
1582
1635
|
}
|
|
1583
1636
|
}
|
|
1584
1637
|
console.log("Starting new checkpoint");
|
|
1585
|
-
return new _Checkpoint(
|
|
1638
|
+
return new _Checkpoint(path7, configHash, {});
|
|
1586
1639
|
}
|
|
1587
1640
|
/**
|
|
1588
1641
|
* Run a single computation with checkpointing.
|
|
@@ -1664,7 +1717,7 @@ var Checkpoint = class _Checkpoint {
|
|
|
1664
1717
|
}
|
|
1665
1718
|
};
|
|
1666
1719
|
function hash(value) {
|
|
1667
|
-
return
|
|
1720
|
+
return createHash3("md5").update(JSON.stringify(value)).digest("hex");
|
|
1668
1721
|
}
|
|
1669
1722
|
var Point = class {
|
|
1670
1723
|
#cache;
|
|
@@ -1708,11 +1761,11 @@ var Point = class {
|
|
|
1708
1761
|
}
|
|
1709
1762
|
};
|
|
1710
1763
|
function hashConfig(config) {
|
|
1711
|
-
return
|
|
1764
|
+
return createHash3("md5").update(JSON.stringify(config)).digest("hex");
|
|
1712
1765
|
}
|
|
1713
1766
|
|
|
1714
1767
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
1715
|
-
import * as
|
|
1768
|
+
import * as path3 from "node:path";
|
|
1716
1769
|
import { DatabaseSync } from "node:sqlite";
|
|
1717
1770
|
|
|
1718
1771
|
// packages/text2sql/src/lib/fs/sqlite/ddl.sqlite-fs.sql
|
|
@@ -1760,7 +1813,7 @@ var SqliteFs = class {
|
|
|
1760
1813
|
const segments = p.split("/").filter(Boolean);
|
|
1761
1814
|
let currentPath = "/";
|
|
1762
1815
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
1763
|
-
currentPath =
|
|
1816
|
+
currentPath = path3.posix.join(currentPath, segments[i]);
|
|
1764
1817
|
const exists = this.#stmt("SELECT 1 FROM fs_entries WHERE path = ?").get(
|
|
1765
1818
|
currentPath
|
|
1766
1819
|
);
|
|
@@ -1781,7 +1834,7 @@ var SqliteFs = class {
|
|
|
1781
1834
|
return stmt;
|
|
1782
1835
|
}
|
|
1783
1836
|
#normalizeRoot(root) {
|
|
1784
|
-
return
|
|
1837
|
+
return path3.posix.resolve("/", root.trim());
|
|
1785
1838
|
}
|
|
1786
1839
|
#prefixPath(p) {
|
|
1787
1840
|
if (!this.#root) {
|
|
@@ -1790,7 +1843,7 @@ var SqliteFs = class {
|
|
|
1790
1843
|
if (p === "/") {
|
|
1791
1844
|
return this.#root;
|
|
1792
1845
|
}
|
|
1793
|
-
return
|
|
1846
|
+
return path3.posix.join(this.#root, p);
|
|
1794
1847
|
}
|
|
1795
1848
|
#unprefixPath(p) {
|
|
1796
1849
|
if (!this.#root) {
|
|
@@ -1816,10 +1869,10 @@ var SqliteFs = class {
|
|
|
1816
1869
|
}
|
|
1817
1870
|
}
|
|
1818
1871
|
#normalizePath(p) {
|
|
1819
|
-
return
|
|
1872
|
+
return path3.posix.resolve("/", p);
|
|
1820
1873
|
}
|
|
1821
1874
|
#dirname(p) {
|
|
1822
|
-
const dir =
|
|
1875
|
+
const dir = path3.posix.dirname(p);
|
|
1823
1876
|
return dir === "" ? "/" : dir;
|
|
1824
1877
|
}
|
|
1825
1878
|
#ensureParentExists(filePath) {
|
|
@@ -1882,7 +1935,7 @@ var SqliteFs = class {
|
|
|
1882
1935
|
}
|
|
1883
1936
|
seen.add(p);
|
|
1884
1937
|
const target = this.#normalizePath(
|
|
1885
|
-
|
|
1938
|
+
path3.posix.resolve(this.#dirname(p), entry.symlinkTarget)
|
|
1886
1939
|
);
|
|
1887
1940
|
return this.#resolveSymlink(target, seen);
|
|
1888
1941
|
}
|
|
@@ -2034,11 +2087,11 @@ var SqliteFs = class {
|
|
|
2034
2087
|
this.#useTransaction(() => {
|
|
2035
2088
|
if (options?.recursive) {
|
|
2036
2089
|
const rootPath = this.#root || "/";
|
|
2037
|
-
const relativePath =
|
|
2090
|
+
const relativePath = path3.posix.relative(rootPath, prefixed);
|
|
2038
2091
|
const segments = relativePath.split("/").filter(Boolean);
|
|
2039
2092
|
let currentPath = rootPath;
|
|
2040
2093
|
for (const segment of segments) {
|
|
2041
|
-
currentPath =
|
|
2094
|
+
currentPath = path3.posix.join(currentPath, segment);
|
|
2042
2095
|
const exists = this.#stmt(
|
|
2043
2096
|
"SELECT type FROM fs_entries WHERE path = ?"
|
|
2044
2097
|
).get(currentPath);
|
|
@@ -2089,7 +2142,7 @@ var SqliteFs = class {
|
|
|
2089
2142
|
AND path != ?
|
|
2090
2143
|
AND path NOT LIKE ? || '%/%'`
|
|
2091
2144
|
).all(prefix, resolved, prefix);
|
|
2092
|
-
return rows.map((row) =>
|
|
2145
|
+
return rows.map((row) => path3.posix.basename(row.path));
|
|
2093
2146
|
}
|
|
2094
2147
|
async readdirWithFileTypes(dirPath) {
|
|
2095
2148
|
const normalized = this.#normalizePath(dirPath);
|
|
@@ -2112,7 +2165,7 @@ var SqliteFs = class {
|
|
|
2112
2165
|
AND path NOT LIKE ? || '%/%'`
|
|
2113
2166
|
).all(prefix, resolved, prefix);
|
|
2114
2167
|
return rows.map((row) => ({
|
|
2115
|
-
name:
|
|
2168
|
+
name: path3.posix.basename(row.path),
|
|
2116
2169
|
isFile: row.type === "file",
|
|
2117
2170
|
isDirectory: row.type === "directory",
|
|
2118
2171
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -2167,8 +2220,8 @@ var SqliteFs = class {
|
|
|
2167
2220
|
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%'`
|
|
2168
2221
|
).all(srcPrefixed, srcPrefixed);
|
|
2169
2222
|
for (const entry of allEntries) {
|
|
2170
|
-
const relativePath =
|
|
2171
|
-
const newPath =
|
|
2223
|
+
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2224
|
+
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2172
2225
|
this.#stmt(
|
|
2173
2226
|
`INSERT OR REPLACE INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2174
2227
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
@@ -2235,8 +2288,8 @@ var SqliteFs = class {
|
|
|
2235
2288
|
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%' ORDER BY path DESC`
|
|
2236
2289
|
).all(srcPrefixed, srcPrefixed);
|
|
2237
2290
|
for (const entry of [...allEntries].reverse()) {
|
|
2238
|
-
const relativePath =
|
|
2239
|
-
const newPath =
|
|
2291
|
+
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2292
|
+
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2240
2293
|
this.#stmt(
|
|
2241
2294
|
`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2242
2295
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
@@ -2289,7 +2342,7 @@ var SqliteFs = class {
|
|
|
2289
2342
|
});
|
|
2290
2343
|
}
|
|
2291
2344
|
resolvePath(base, relativePath) {
|
|
2292
|
-
return
|
|
2345
|
+
return path3.posix.resolve(base, relativePath);
|
|
2293
2346
|
}
|
|
2294
2347
|
getAllPaths() {
|
|
2295
2348
|
const rows = this.#stmt(
|
|
@@ -2401,7 +2454,7 @@ var SqliteFs = class {
|
|
|
2401
2454
|
|
|
2402
2455
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
2403
2456
|
import { createRequire } from "node:module";
|
|
2404
|
-
import * as
|
|
2457
|
+
import * as path4 from "node:path";
|
|
2405
2458
|
|
|
2406
2459
|
// packages/text2sql/src/lib/fs/mssql/ddl.mssql-fs.ts
|
|
2407
2460
|
function mssqlFsDDL(schema) {
|
|
@@ -2527,7 +2580,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2527
2580
|
const segments = p.split("/").filter(Boolean);
|
|
2528
2581
|
let currentPath = "/";
|
|
2529
2582
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
2530
|
-
currentPath =
|
|
2583
|
+
currentPath = path4.posix.join(currentPath, segments[i]);
|
|
2531
2584
|
const exists = await this.#rawQuery(
|
|
2532
2585
|
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2533
2586
|
[currentPath]
|
|
@@ -2579,7 +2632,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2579
2632
|
}
|
|
2580
2633
|
}
|
|
2581
2634
|
#normalizeRoot(root) {
|
|
2582
|
-
return
|
|
2635
|
+
return path4.posix.resolve("/", root.trim());
|
|
2583
2636
|
}
|
|
2584
2637
|
#prefixPath(p) {
|
|
2585
2638
|
if (!this.#root) {
|
|
@@ -2588,7 +2641,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2588
2641
|
if (p === "/") {
|
|
2589
2642
|
return this.#root;
|
|
2590
2643
|
}
|
|
2591
|
-
return
|
|
2644
|
+
return path4.posix.join(this.#root, p);
|
|
2592
2645
|
}
|
|
2593
2646
|
#unprefixPath(p) {
|
|
2594
2647
|
if (!this.#root) {
|
|
@@ -2603,10 +2656,10 @@ var MssqlFs = class _MssqlFs {
|
|
|
2603
2656
|
return p;
|
|
2604
2657
|
}
|
|
2605
2658
|
#normalizePath(p) {
|
|
2606
|
-
return
|
|
2659
|
+
return path4.posix.resolve("/", p);
|
|
2607
2660
|
}
|
|
2608
2661
|
#dirname(p) {
|
|
2609
|
-
const dir =
|
|
2662
|
+
const dir = path4.posix.dirname(p);
|
|
2610
2663
|
return dir === "" ? "/" : dir;
|
|
2611
2664
|
}
|
|
2612
2665
|
async #ensureParentExists(filePath, transaction) {
|
|
@@ -2695,7 +2748,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2695
2748
|
}
|
|
2696
2749
|
seen.add(p);
|
|
2697
2750
|
const target = this.#normalizePath(
|
|
2698
|
-
|
|
2751
|
+
path4.posix.resolve(this.#dirname(p), entry.symlinkTarget)
|
|
2699
2752
|
);
|
|
2700
2753
|
return this.#resolveSymlink(target, seen);
|
|
2701
2754
|
}
|
|
@@ -2878,11 +2931,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2878
2931
|
await this.#useTransaction(async (transaction) => {
|
|
2879
2932
|
if (options?.recursive) {
|
|
2880
2933
|
const rootPath = this.#root || "/";
|
|
2881
|
-
const relativePath =
|
|
2934
|
+
const relativePath = path4.posix.relative(rootPath, prefixed);
|
|
2882
2935
|
const segments = relativePath.split("/").filter(Boolean);
|
|
2883
2936
|
let currentPath = rootPath;
|
|
2884
2937
|
for (const segment of segments) {
|
|
2885
|
-
currentPath =
|
|
2938
|
+
currentPath = path4.posix.join(currentPath, segment);
|
|
2886
2939
|
const checkReq = transaction.request();
|
|
2887
2940
|
checkReq.input("p0", currentPath);
|
|
2888
2941
|
const result = await checkReq.query(
|
|
@@ -2946,7 +2999,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2946
2999
|
AND path NOT LIKE @p0 + '%/%'`,
|
|
2947
3000
|
[prefix, resolved]
|
|
2948
3001
|
);
|
|
2949
|
-
return rows.map((row) =>
|
|
3002
|
+
return rows.map((row) => path4.posix.basename(row.path));
|
|
2950
3003
|
}
|
|
2951
3004
|
async readdirWithFileTypes(dirPath) {
|
|
2952
3005
|
const normalized = this.#normalizePath(dirPath);
|
|
@@ -2972,7 +3025,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2972
3025
|
[prefix, resolved]
|
|
2973
3026
|
);
|
|
2974
3027
|
return rows.map((row) => ({
|
|
2975
|
-
name:
|
|
3028
|
+
name: path4.posix.basename(row.path),
|
|
2976
3029
|
isFile: row.type === "file",
|
|
2977
3030
|
isDirectory: row.type === "directory",
|
|
2978
3031
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -3041,8 +3094,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
3041
3094
|
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%'`
|
|
3042
3095
|
);
|
|
3043
3096
|
for (const entry of allEntriesResult.recordset) {
|
|
3044
|
-
const relativePath =
|
|
3045
|
-
const newPath =
|
|
3097
|
+
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
3098
|
+
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
3046
3099
|
const insertReq = transaction.request();
|
|
3047
3100
|
insertReq.input("p0", newPath);
|
|
3048
3101
|
insertReq.input("p1", entry.type);
|
|
@@ -3151,8 +3204,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
3151
3204
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @dp0 OR path LIKE @dp0 + '/%'`
|
|
3152
3205
|
);
|
|
3153
3206
|
for (const entry of [...allEntriesResult.recordset].reverse()) {
|
|
3154
|
-
const relativePath =
|
|
3155
|
-
const newPath =
|
|
3207
|
+
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
3208
|
+
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
3156
3209
|
const insertReq = transaction.request();
|
|
3157
3210
|
insertReq.input("p0", newPath);
|
|
3158
3211
|
insertReq.input("p1", entry.type);
|
|
@@ -3245,7 +3298,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3245
3298
|
});
|
|
3246
3299
|
}
|
|
3247
3300
|
resolvePath(base, relativePath) {
|
|
3248
|
-
return
|
|
3301
|
+
return path4.posix.resolve(base, relativePath);
|
|
3249
3302
|
}
|
|
3250
3303
|
getAllPaths() {
|
|
3251
3304
|
throw new Error(
|
|
@@ -3386,7 +3439,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3386
3439
|
|
|
3387
3440
|
// packages/text2sql/src/lib/fs/postgres/postgres-fs.ts
|
|
3388
3441
|
import { createRequire as createRequire2 } from "node:module";
|
|
3389
|
-
import * as
|
|
3442
|
+
import * as path5 from "node:path";
|
|
3390
3443
|
|
|
3391
3444
|
// packages/text2sql/src/lib/fs/postgres/ddl.postgres-fs.ts
|
|
3392
3445
|
function postgresFsDDL(schema) {
|
|
@@ -3491,7 +3544,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3491
3544
|
const segments = p.split("/").filter(Boolean);
|
|
3492
3545
|
let currentPath = "/";
|
|
3493
3546
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
3494
|
-
currentPath =
|
|
3547
|
+
currentPath = path5.posix.join(currentPath, segments[i]);
|
|
3495
3548
|
const exists = await this.#rawQuery(
|
|
3496
3549
|
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3497
3550
|
[currentPath]
|
|
@@ -3536,7 +3589,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3536
3589
|
}
|
|
3537
3590
|
}
|
|
3538
3591
|
#normalizeRoot(root) {
|
|
3539
|
-
return
|
|
3592
|
+
return path5.posix.resolve("/", root.trim());
|
|
3540
3593
|
}
|
|
3541
3594
|
#prefixPath(p) {
|
|
3542
3595
|
if (!this.#root) {
|
|
@@ -3545,7 +3598,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3545
3598
|
if (p === "/") {
|
|
3546
3599
|
return this.#root;
|
|
3547
3600
|
}
|
|
3548
|
-
return
|
|
3601
|
+
return path5.posix.join(this.#root, p);
|
|
3549
3602
|
}
|
|
3550
3603
|
#unprefixPath(p) {
|
|
3551
3604
|
if (!this.#root) {
|
|
@@ -3560,10 +3613,10 @@ var PostgresFs = class _PostgresFs {
|
|
|
3560
3613
|
return p;
|
|
3561
3614
|
}
|
|
3562
3615
|
#normalizePath(p) {
|
|
3563
|
-
return
|
|
3616
|
+
return path5.posix.resolve("/", p);
|
|
3564
3617
|
}
|
|
3565
3618
|
#dirname(p) {
|
|
3566
|
-
const dir =
|
|
3619
|
+
const dir = path5.posix.dirname(p);
|
|
3567
3620
|
return dir === "" ? "/" : dir;
|
|
3568
3621
|
}
|
|
3569
3622
|
async #ensureParentExists(filePath, client) {
|
|
@@ -3643,7 +3696,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3643
3696
|
}
|
|
3644
3697
|
seen.add(p);
|
|
3645
3698
|
const target = this.#normalizePath(
|
|
3646
|
-
|
|
3699
|
+
path5.posix.resolve(this.#dirname(p), entry.symlink_target)
|
|
3647
3700
|
);
|
|
3648
3701
|
return this.#resolveSymlink(target, seen);
|
|
3649
3702
|
}
|
|
@@ -3809,11 +3862,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3809
3862
|
await this.#useTransaction(async (client) => {
|
|
3810
3863
|
if (options?.recursive) {
|
|
3811
3864
|
const rootPath = this.#root || "/";
|
|
3812
|
-
const relativePath =
|
|
3865
|
+
const relativePath = path5.posix.relative(rootPath, prefixed);
|
|
3813
3866
|
const segments = relativePath.split("/").filter(Boolean);
|
|
3814
3867
|
let currentPath = rootPath;
|
|
3815
3868
|
for (const segment of segments) {
|
|
3816
|
-
currentPath =
|
|
3869
|
+
currentPath = path5.posix.join(currentPath, segment);
|
|
3817
3870
|
const result = await client.query(
|
|
3818
3871
|
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3819
3872
|
[currentPath]
|
|
@@ -3871,7 +3924,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3871
3924
|
AND path NOT LIKE $1 || '%/%'`,
|
|
3872
3925
|
[prefix, resolved]
|
|
3873
3926
|
);
|
|
3874
|
-
return rows.map((row) =>
|
|
3927
|
+
return rows.map((row) => path5.posix.basename(row.path));
|
|
3875
3928
|
}
|
|
3876
3929
|
async readdirWithFileTypes(dirPath) {
|
|
3877
3930
|
const normalized = this.#normalizePath(dirPath);
|
|
@@ -3897,7 +3950,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3897
3950
|
[prefix, resolved]
|
|
3898
3951
|
);
|
|
3899
3952
|
return rows.map((row) => ({
|
|
3900
|
-
name:
|
|
3953
|
+
name: path5.posix.basename(row.path),
|
|
3901
3954
|
isFile: row.type === "file",
|
|
3902
3955
|
isDirectory: row.type === "directory",
|
|
3903
3956
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -3962,8 +4015,8 @@ var PostgresFs = class _PostgresFs {
|
|
|
3962
4015
|
[srcPrefixed]
|
|
3963
4016
|
);
|
|
3964
4017
|
for (const entry of allEntriesResult.rows) {
|
|
3965
|
-
const relativePath =
|
|
3966
|
-
const newPath =
|
|
4018
|
+
const relativePath = path5.posix.relative(srcPrefixed, entry.path);
|
|
4019
|
+
const newPath = path5.posix.join(destPrefixed, relativePath);
|
|
3967
4020
|
await client.query(
|
|
3968
4021
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime, symlink_target)
|
|
3969
4022
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
@@ -4052,8 +4105,8 @@ var PostgresFs = class _PostgresFs {
|
|
|
4052
4105
|
[destPrefixed]
|
|
4053
4106
|
);
|
|
4054
4107
|
for (const entry of [...allEntriesResult.rows].reverse()) {
|
|
4055
|
-
const relativePath =
|
|
4056
|
-
const newPath =
|
|
4108
|
+
const relativePath = path5.posix.relative(srcPrefixed, entry.path);
|
|
4109
|
+
const newPath = path5.posix.join(destPrefixed, relativePath);
|
|
4057
4110
|
await client.query(
|
|
4058
4111
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime, symlink_target)
|
|
4059
4112
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
@@ -4126,7 +4179,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
4126
4179
|
});
|
|
4127
4180
|
}
|
|
4128
4181
|
resolvePath(base, relativePath) {
|
|
4129
|
-
return
|
|
4182
|
+
return path5.posix.resolve(base, relativePath);
|
|
4130
4183
|
}
|
|
4131
4184
|
getAllPaths() {
|
|
4132
4185
|
throw new Error(
|
|
@@ -4262,29 +4315,29 @@ var ScopedFs = class {
|
|
|
4262
4315
|
this.#base = options.base;
|
|
4263
4316
|
this.#prefix = options.prefix.replace(/\/$/, "");
|
|
4264
4317
|
}
|
|
4265
|
-
#scope(
|
|
4266
|
-
return `${this.#prefix}${
|
|
4318
|
+
#scope(path7) {
|
|
4319
|
+
return `${this.#prefix}${path7}`;
|
|
4267
4320
|
}
|
|
4268
|
-
#unscope(
|
|
4269
|
-
if (
|
|
4321
|
+
#unscope(path7) {
|
|
4322
|
+
if (path7 === this.#prefix) {
|
|
4270
4323
|
return "/";
|
|
4271
4324
|
}
|
|
4272
|
-
if (
|
|
4273
|
-
return
|
|
4325
|
+
if (path7.startsWith(this.#prefix + "/")) {
|
|
4326
|
+
return path7.slice(this.#prefix.length) || "/";
|
|
4274
4327
|
}
|
|
4275
|
-
return
|
|
4328
|
+
return path7;
|
|
4276
4329
|
}
|
|
4277
|
-
async writeFile(
|
|
4278
|
-
await this.#base.writeFile(this.#scope(
|
|
4330
|
+
async writeFile(path7, content, options) {
|
|
4331
|
+
await this.#base.writeFile(this.#scope(path7), content, options);
|
|
4279
4332
|
}
|
|
4280
|
-
async appendFile(
|
|
4281
|
-
await this.#base.appendFile(this.#scope(
|
|
4333
|
+
async appendFile(path7, content, options) {
|
|
4334
|
+
await this.#base.appendFile(this.#scope(path7), content, options);
|
|
4282
4335
|
}
|
|
4283
|
-
async mkdir(
|
|
4284
|
-
return this.#base.mkdir(this.#scope(
|
|
4336
|
+
async mkdir(path7, options) {
|
|
4337
|
+
return this.#base.mkdir(this.#scope(path7), options);
|
|
4285
4338
|
}
|
|
4286
|
-
async rm(
|
|
4287
|
-
await this.#base.rm(this.#scope(
|
|
4339
|
+
async rm(path7, options) {
|
|
4340
|
+
await this.#base.rm(this.#scope(path7), options);
|
|
4288
4341
|
}
|
|
4289
4342
|
async cp(src, dest, options) {
|
|
4290
4343
|
await this.#base.cp(this.#scope(src), this.#scope(dest), options);
|
|
@@ -4292,8 +4345,8 @@ var ScopedFs = class {
|
|
|
4292
4345
|
async mv(src, dest) {
|
|
4293
4346
|
await this.#base.mv(this.#scope(src), this.#scope(dest));
|
|
4294
4347
|
}
|
|
4295
|
-
async chmod(
|
|
4296
|
-
return this.#base.chmod(this.#scope(
|
|
4348
|
+
async chmod(path7, mode) {
|
|
4349
|
+
return this.#base.chmod(this.#scope(path7), mode);
|
|
4297
4350
|
}
|
|
4298
4351
|
async symlink(target, linkPath) {
|
|
4299
4352
|
await this.#base.symlink(target, this.#scope(linkPath));
|
|
@@ -4301,35 +4354,35 @@ var ScopedFs = class {
|
|
|
4301
4354
|
async link(existingPath, newPath) {
|
|
4302
4355
|
await this.#base.link(this.#scope(existingPath), this.#scope(newPath));
|
|
4303
4356
|
}
|
|
4304
|
-
readFile(
|
|
4305
|
-
return this.#base.readFile(this.#scope(
|
|
4357
|
+
readFile(path7, options) {
|
|
4358
|
+
return this.#base.readFile(this.#scope(path7), options);
|
|
4306
4359
|
}
|
|
4307
|
-
readFileBuffer(
|
|
4308
|
-
return this.#base.readFileBuffer(this.#scope(
|
|
4360
|
+
readFileBuffer(path7) {
|
|
4361
|
+
return this.#base.readFileBuffer(this.#scope(path7));
|
|
4309
4362
|
}
|
|
4310
|
-
stat(
|
|
4311
|
-
return this.#base.stat(this.#scope(
|
|
4363
|
+
stat(path7) {
|
|
4364
|
+
return this.#base.stat(this.#scope(path7));
|
|
4312
4365
|
}
|
|
4313
|
-
lstat(
|
|
4314
|
-
return this.#base.lstat(this.#scope(
|
|
4366
|
+
lstat(path7) {
|
|
4367
|
+
return this.#base.lstat(this.#scope(path7));
|
|
4315
4368
|
}
|
|
4316
|
-
readdir(
|
|
4317
|
-
return this.#base.readdir(this.#scope(
|
|
4369
|
+
readdir(path7) {
|
|
4370
|
+
return this.#base.readdir(this.#scope(path7));
|
|
4318
4371
|
}
|
|
4319
|
-
readdirWithFileTypes(
|
|
4320
|
-
return this.#base.readdirWithFileTypes(this.#scope(
|
|
4372
|
+
readdirWithFileTypes(path7) {
|
|
4373
|
+
return this.#base.readdirWithFileTypes(this.#scope(path7));
|
|
4321
4374
|
}
|
|
4322
|
-
exists(
|
|
4323
|
-
return this.#base.exists(this.#scope(
|
|
4375
|
+
exists(path7) {
|
|
4376
|
+
return this.#base.exists(this.#scope(path7));
|
|
4324
4377
|
}
|
|
4325
|
-
readlink(
|
|
4326
|
-
return this.#base.readlink(this.#scope(
|
|
4378
|
+
readlink(path7) {
|
|
4379
|
+
return this.#base.readlink(this.#scope(path7));
|
|
4327
4380
|
}
|
|
4328
|
-
realpath(
|
|
4329
|
-
return this.#base.realpath(this.#scope(
|
|
4381
|
+
realpath(path7) {
|
|
4382
|
+
return this.#base.realpath(this.#scope(path7)).then((p) => this.#unscope(p));
|
|
4330
4383
|
}
|
|
4331
|
-
utimes(
|
|
4332
|
-
return this.#base.utimes(this.#scope(
|
|
4384
|
+
utimes(path7, atime, mtime) {
|
|
4385
|
+
return this.#base.utimes(this.#scope(path7), atime, mtime);
|
|
4333
4386
|
}
|
|
4334
4387
|
resolvePath(base, relativePath) {
|
|
4335
4388
|
return this.#base.resolvePath(base, relativePath);
|
|
@@ -4578,7 +4631,7 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
4578
4631
|
workflow2({
|
|
4579
4632
|
task: "Query execution",
|
|
4580
4633
|
steps: [
|
|
4581
|
-
|
|
4634
|
+
`Pick the target database by the <database> value shown at the top of each schema fragment \u2014 that is the exact connection name to pass as <db>. It is NOT the SQL-level database/schema name (e.g. SQLite's default "main").`,
|
|
4582
4635
|
'Execute SQL through bash tool: sql run <db> "SELECT ..."',
|
|
4583
4636
|
"Read the output: file path, column names, and row count.",
|
|
4584
4637
|
"Use column names to construct jq filters: cat <path> | jq '.[] | {col1, col2}'",
|
|
@@ -4588,7 +4641,7 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
4588
4641
|
guardrail2({
|
|
4589
4642
|
rule: "Do not attempt SQL access through non-bash tools.",
|
|
4590
4643
|
reason: "SQL access is only available through the bash tool.",
|
|
4591
|
-
action: 'Use `sql run <db> "SELECT ..."` and `sql validate <db> "SELECT ..."` through bash, where `<db>` is the configured database name.'
|
|
4644
|
+
action: 'Use `sql run <db> "SELECT ..."` and `sql validate <db> "SELECT ..."` through bash, where `<db>` is the exact configured connection name (not the SQL-level database/schema name).'
|
|
4592
4645
|
}),
|
|
4593
4646
|
explain({
|
|
4594
4647
|
concept: "sql command output format",
|
|
@@ -4754,8 +4807,8 @@ import { BashTransformPipeline } from "just-bash";
|
|
|
4754
4807
|
|
|
4755
4808
|
// packages/text2sql/src/lib/agents/sql-transform-plugins.ts
|
|
4756
4809
|
import { parse as parse2, serialize } from "just-bash";
|
|
4757
|
-
import { createHash as
|
|
4758
|
-
import * as
|
|
4810
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
4811
|
+
import * as path6 from "node:path";
|
|
4759
4812
|
import { BashException, asStaticWordText as asStaticWordText2 } from "@deepagents/context";
|
|
4760
4813
|
function isScriptNode(value) {
|
|
4761
4814
|
if (typeof value !== "object" || value === null) {
|
|
@@ -5267,7 +5320,7 @@ function isBlockedSimpleCommand(command, context, mode, options) {
|
|
|
5267
5320
|
if (!commandName) {
|
|
5268
5321
|
return false;
|
|
5269
5322
|
}
|
|
5270
|
-
const normalizedName =
|
|
5323
|
+
const normalizedName = path6.posix.basename(commandName).toLowerCase();
|
|
5271
5324
|
if (BLOCKED_DB_CLIENT_COMMANDS.has(normalizedName)) {
|
|
5272
5325
|
return true;
|
|
5273
5326
|
}
|
|
@@ -5456,7 +5509,7 @@ function rewriteSqlCommand(cmd, ast) {
|
|
|
5456
5509
|
const dbName = asStaticWordText2(cmd.args[1]);
|
|
5457
5510
|
const sqlArgs = cmd.args.slice(2);
|
|
5458
5511
|
const unquotedSql = extractSqlText(sqlArgs);
|
|
5459
|
-
const hash2 =
|
|
5512
|
+
const hash2 = createHash4("sha256").update(serialize(ast)).digest("hex").slice(0, 12);
|
|
5460
5513
|
const sqlPath = `/tmp/sql-inline-${subcommand}-${hash2}.sql`;
|
|
5461
5514
|
const heredocTag = `SQL_${hash2.toUpperCase()}`;
|
|
5462
5515
|
const groupScript = [
|
|
@@ -5681,6 +5734,15 @@ var Text2Sql = class {
|
|
|
5681
5734
|
}
|
|
5682
5735
|
};
|
|
5683
5736
|
|
|
5737
|
+
// packages/text2sql/src/lib/resolve-adapter.ts
|
|
5738
|
+
function resolveAdapter(text2Sql, db) {
|
|
5739
|
+
if (text2Sql.hasAdapter(db)) return db;
|
|
5740
|
+
const names = text2Sql.adapterNames();
|
|
5741
|
+
if (names.length === 1) return names[0];
|
|
5742
|
+
const available = names.join(", ") || "(none configured)";
|
|
5743
|
+
throw new Error(`unknown database "${db}". Available: ${available}`);
|
|
5744
|
+
}
|
|
5745
|
+
|
|
5684
5746
|
// packages/text2sql/src/lib/sql-command.ts
|
|
5685
5747
|
var SQL_VALIDATE_REMINDER2 = 'Always run `sql validate <db> "..."` before `sql run <db> "..."` to catch syntax errors early.';
|
|
5686
5748
|
var SqlCommandError = class extends BashException2 {
|
|
@@ -5778,7 +5840,7 @@ async function runHandler(subcommand, fn) {
|
|
|
5778
5840
|
return await fn();
|
|
5779
5841
|
} catch (error) {
|
|
5780
5842
|
if (error instanceof BashException2) return error.format();
|
|
5781
|
-
if (Text2SqlValidationError.isInstance(error)
|
|
5843
|
+
if (Text2SqlValidationError.isInstance(error)) {
|
|
5782
5844
|
return new SqlCommandError(subcommand, error.message).format();
|
|
5783
5845
|
}
|
|
5784
5846
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -5787,24 +5849,19 @@ async function runHandler(subcommand, fn) {
|
|
|
5787
5849
|
}
|
|
5788
5850
|
function takeDbAndSql(subcommand, positional, text2Sql) {
|
|
5789
5851
|
const [db, ...rest] = positional;
|
|
5790
|
-
const available = text2Sql.adapterNames().join(", ");
|
|
5791
5852
|
if (!db) {
|
|
5853
|
+
const available = text2Sql.adapterNames().join(", ");
|
|
5792
5854
|
throw new SqlCommandError(
|
|
5793
5855
|
subcommand,
|
|
5794
5856
|
`missing database name. Usage: sql ${subcommand} <db> "SELECT ...". Available: ${available}`
|
|
5795
5857
|
);
|
|
5796
5858
|
}
|
|
5797
|
-
|
|
5798
|
-
throw new SqlCommandError(
|
|
5799
|
-
subcommand,
|
|
5800
|
-
`unknown database "${db}". Available: ${available}`
|
|
5801
|
-
);
|
|
5802
|
-
}
|
|
5859
|
+
const name = resolveAdapter(text2Sql, db);
|
|
5803
5860
|
const sql = rest.join(" ").trim();
|
|
5804
5861
|
if (!sql) {
|
|
5805
5862
|
throw new SqlCommandError(subcommand, "no query provided");
|
|
5806
5863
|
}
|
|
5807
|
-
return { name
|
|
5864
|
+
return { name, sql };
|
|
5808
5865
|
}
|
|
5809
5866
|
function repairDbNameAndQuotedArg(rawArgs) {
|
|
5810
5867
|
const trimmed = rawArgs.trim();
|
|
@@ -5823,6 +5880,7 @@ export {
|
|
|
5823
5880
|
Checkpoint,
|
|
5824
5881
|
FileCache,
|
|
5825
5882
|
FileIndexCache,
|
|
5883
|
+
FileIndexLock,
|
|
5826
5884
|
JsonCache,
|
|
5827
5885
|
MssqlFs,
|
|
5828
5886
|
Point,
|