@deepagents/text2sql 7.1.0 → 7.1.2
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 +61 -76
- package/dist/bin/sql.js +42 -584
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -265
- package/dist/index.js.map +4 -4
- package/dist/lib/adapter-index.d.ts +0 -2
- package/dist/lib/adapter-index.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/constraint.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/index.js +14 -17
- package/dist/lib/adapters/bigquery/index.js.map +2 -2
- package/dist/lib/adapters/bigquery/table.bigquery.grounding.d.ts +2 -2
- package/dist/lib/adapters/bigquery/table.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/clickhouse.sql-policy.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/index.js +13 -9
- package/dist/lib/adapters/clickhouse/index.js.map +3 -3
- package/dist/lib/adapters/duckdb/duckdb.d.ts.map +1 -1
- package/dist/lib/adapters/duckdb/duckdb.sql-policy.d.ts.map +1 -1
- package/dist/lib/adapters/duckdb/index.js +12 -4
- package/dist/lib/adapters/duckdb/index.js.map +4 -4
- package/dist/lib/adapters/groundings/index.js +2 -2
- package/dist/lib/adapters/groundings/index.js.map +2 -2
- package/dist/lib/adapters/groundings/table.grounding.d.ts +2 -2
- package/dist/lib/adapters/groundings/table.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/index.js +2 -2
- package/dist/lib/adapters/mysql/index.js.map +2 -2
- package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/index.js +17 -17
- package/dist/lib/adapters/postgres/index.js.map +2 -2
- package/dist/lib/adapters/posthog/index.js.map +2 -2
- package/dist/lib/adapters/posthog/posthog.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/schema.posthog.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/spreadsheet/index.js +9 -7
- package/dist/lib/adapters/spreadsheet/index.js.map +2 -2
- package/dist/lib/adapters/spreadsheet/spreadsheet.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/index.js +2 -5
- package/dist/lib/adapters/sqlite/index.js.map +2 -2
- package/dist/lib/adapters/sqlite/sqlite.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/index.js +45 -61
- package/dist/lib/adapters/sqlserver/index.js.map +2 -2
- package/dist/lib/adapters/sqlserver/table.sqlserver.grounding.d.ts +1 -1
- package/dist/lib/adapters/sqlserver/table.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/agents/question.agent.d.ts.map +1 -1
- package/dist/lib/agents/suggestions.agents.d.ts.map +1 -1
- package/dist/lib/fs/mssql/mssql-fs.d.ts +3 -2
- package/dist/lib/fs/mssql/mssql-fs.d.ts.map +1 -1
- package/dist/lib/fs/postgres/postgres-fs.d.ts +3 -2
- package/dist/lib/fs/postgres/postgres-fs.d.ts.map +1 -1
- package/dist/lib/fs/sqlite/sqlite-fs.d.ts.map +1 -1
- package/dist/lib/index-cache.d.ts +2 -3
- package/dist/lib/index-cache.d.ts.map +1 -1
- package/dist/lib/sql-command.d.ts +1 -4
- package/dist/lib/sql-command.d.ts.map +1 -1
- package/dist/lib/sql.d.ts +0 -5
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/decorators/filtered-producer.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/segmented-context-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +3 -3
- package/dist/lib/synthesis/index.js.map +2 -2
- package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts.map +1 -1
- package/package.json +18 -7
- package/dist/lib/index-lock.d.ts +0 -60
- package/dist/lib/index-lock.d.ts.map +0 -1
- package/dist/lib/prompt.d.ts +0 -2
- package/dist/lib/prompt.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ Requires Node.js LTS
|
|
|
37
37
|
import { groq } from '@ai-sdk/groq';
|
|
38
38
|
import pg from 'pg';
|
|
39
39
|
|
|
40
|
-
import {
|
|
40
|
+
import { Text2Sql, toSql } from '@deepagents/text2sql';
|
|
41
41
|
import {
|
|
42
42
|
Postgres,
|
|
43
43
|
columnValues,
|
|
@@ -69,22 +69,24 @@ const adapter = new Postgres({
|
|
|
69
69
|
],
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
const text2sql = new Text2Sql({
|
|
72
|
+
const text2sql = new Text2Sql({ adapters: { main: adapter } });
|
|
73
|
+
|
|
74
|
+
const fragments = await text2sql.index({ names: ['main'] });
|
|
75
|
+
const { sql } = await toSql({
|
|
76
|
+
input: 'Show me the top 10 customers by revenue',
|
|
77
|
+
adapter,
|
|
78
|
+
fragments,
|
|
73
79
|
model: groq('openai/gpt-oss-20b'),
|
|
74
|
-
adapters: { main: adapter },
|
|
75
|
-
lock: new FileIndexLock(),
|
|
76
80
|
});
|
|
77
|
-
|
|
78
|
-
// Generate SQL
|
|
79
|
-
const sql = await text2sql.toSql(
|
|
80
|
-
'Show me the top 10 customers by revenue',
|
|
81
|
-
'main',
|
|
82
|
-
);
|
|
83
81
|
console.log(sql);
|
|
84
82
|
```
|
|
85
83
|
|
|
84
|
+
`index()` introspects the database schema and returns it as context fragments.
|
|
85
|
+
`toSql()` gives these fragments to the model and validates the SQL that the
|
|
86
|
+
model writes.
|
|
87
|
+
|
|
86
88
|
The adapter-map key (`main` here) is the adapter name. Reuse that same key in
|
|
87
|
-
`text2sql.
|
|
89
|
+
`text2sql.index({ names: ['main'] })` and in any `sql validate <db> "..."` /
|
|
88
90
|
`sql run <db> "..."` calls from a sandbox where the package CLI is installed.
|
|
89
91
|
This is the configured connection name, not the SQL-level database or schema
|
|
90
92
|
name (for example, SQLite's default `main` schema).
|
|
@@ -223,7 +225,7 @@ The `sql` CLI caches introspected schema only when you opt in via env: set
|
|
|
223
225
|
`TEXT2SQL_INDEX_CACHE_DIR` (where cache files live) and/or
|
|
224
226
|
`TEXT2SQL_INDEX_VERSION` (an invalidation token — bump it when the schema
|
|
225
227
|
changes). With neither set, every `sql index` introspects fresh. See
|
|
226
|
-
[Schema index caching
|
|
228
|
+
[Schema index caching](#schema-index-caching) for
|
|
227
229
|
the underlying injectable primitives.
|
|
228
230
|
|
|
229
231
|
For in-process or virtual-sandbox usage (without installing the package CLI),
|
|
@@ -234,16 +236,11 @@ import { InMemoryFs, createVirtualSandbox } from '@deepagents/context';
|
|
|
234
236
|
import {
|
|
235
237
|
type CreateSqlCommandOptions,
|
|
236
238
|
type CreateSqlCommandResult,
|
|
237
|
-
FileIndexLock,
|
|
238
239
|
Text2Sql,
|
|
239
240
|
createSqlCommand,
|
|
240
241
|
} from '@deepagents/text2sql';
|
|
241
242
|
|
|
242
|
-
const text2sql = new Text2Sql({
|
|
243
|
-
model,
|
|
244
|
-
adapters: { main: adapter },
|
|
245
|
-
lock: new FileIndexLock(),
|
|
246
|
-
});
|
|
243
|
+
const text2sql = new Text2Sql({ adapters: { main: adapter } });
|
|
247
244
|
|
|
248
245
|
const commandOptions: CreateSqlCommandOptions = {
|
|
249
246
|
outputDir: '/sql-artifacts',
|
|
@@ -318,9 +315,9 @@ the model loop. Shell-escaped dollar-prefixed PostHog properties such as
|
|
|
318
315
|
## Fragments
|
|
319
316
|
|
|
320
317
|
Inject domain knowledge by setting fragments on the `ContextEngine` you build
|
|
321
|
-
for the agent. Those fragments affect every `chat()` turn.
|
|
322
|
-
|
|
323
|
-
|
|
318
|
+
for the agent. Those fragments affect every `chat()` turn. For direct SQL
|
|
319
|
+
generation, give `toSql({ fragments })` the fragments from `index()` and your
|
|
320
|
+
own fragments.
|
|
324
321
|
|
|
325
322
|
```typescript
|
|
326
323
|
import {
|
|
@@ -399,79 +396,68 @@ for await (const chunk of followUp) {
|
|
|
399
396
|
}
|
|
400
397
|
```
|
|
401
398
|
|
|
402
|
-
## Schema index caching
|
|
399
|
+
## Schema index caching
|
|
403
400
|
|
|
404
401
|
Schema introspection is the expensive part of indexing. `Text2Sql` and
|
|
405
|
-
`AdapterIndexer` own no storage
|
|
406
|
-
adapter
|
|
402
|
+
`AdapterIndexer` own no storage. You can give them a cache. The cache key is
|
|
403
|
+
the adapter name:
|
|
407
404
|
|
|
408
405
|
```typescript
|
|
409
406
|
export interface IndexCache {
|
|
410
407
|
read(key: string): Promise<ContextFragment[] | null>;
|
|
411
408
|
write(key: string, fragments: ContextFragment[]): Promise<void>;
|
|
412
409
|
}
|
|
413
|
-
|
|
414
|
-
export interface IndexLock {
|
|
415
|
-
// Acquire (waiting if held elsewhere), run fn, release — even on throw.
|
|
416
|
-
// Reject if the lock can't be acquired (callers fail closed).
|
|
417
|
-
run<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
418
|
-
}
|
|
419
410
|
```
|
|
420
411
|
|
|
421
|
-
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
- **`lock` + `cache`** → introspection is single-flight: concurrent callers for
|
|
425
|
-
the same adapter wait on the lock, then read the warm cache the holder wrote.
|
|
412
|
+
- **No `cache`**: each `index()` call introspects the database.
|
|
413
|
+
- **A `cache`**: `index()` reads the cache first. On a miss, it introspects the
|
|
414
|
+
database and writes the result to the cache.
|
|
426
415
|
|
|
427
|
-
|
|
428
|
-
primitives:
|
|
416
|
+
The package ships a file-backed cache:
|
|
429
417
|
|
|
430
418
|
```typescript
|
|
431
|
-
import { FileIndexCache,
|
|
419
|
+
import { FileIndexCache, Text2Sql } from '@deepagents/text2sql';
|
|
432
420
|
|
|
433
421
|
const text2sql = new Text2Sql({
|
|
434
|
-
model,
|
|
435
422
|
adapters: { main: adapter },
|
|
436
|
-
// Point both `dir`s at a shared volume to share one cache + lock across
|
|
437
|
-
// processes on the same filesystem.
|
|
438
423
|
cache: new FileIndexCache({ dir: '/var/cache/text2sql', namespace: 'v1' }),
|
|
439
|
-
lock: new FileIndexLock({ dir: '/var/cache/text2sql', namespace: 'v1' }),
|
|
440
424
|
});
|
|
441
425
|
```
|
|
442
426
|
|
|
443
|
-
`FileIndexCache` writes atomically (temp + rename)
|
|
444
|
-
not parse to context fragments as a miss, so a torn read
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
backed `
|
|
427
|
+
`FileIndexCache` writes atomically (temp + rename). It treats a file that does
|
|
428
|
+
not parse to context fragments as a miss, so a torn read causes a new
|
|
429
|
+
introspection. `dir` defaults to the OS temp directory.
|
|
430
|
+
|
|
431
|
+
### Introspect once for concurrent callers
|
|
432
|
+
|
|
433
|
+
`index()` does not make callers wait for each other. When two callers miss the
|
|
434
|
+
cache at the same time, both introspect the database. The result stays
|
|
435
|
+
correct, because each write replaces the whole cache file.
|
|
436
|
+
|
|
437
|
+
To let only one caller introspect, acquire a key around `index()`. This example
|
|
438
|
+
uses [`@zukhruf/mutex`](https://www.npmjs.com/package/@zukhruf/mutex):
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
import { Mutex, SqliteStore } from '@zukhruf/mutex';
|
|
442
|
+
|
|
443
|
+
const mutex = new Mutex(new SqliteStore('/var/lib/my-app/locks'));
|
|
444
|
+
|
|
445
|
+
const fragments = await mutex.acquire('text2sql:main', () =>
|
|
446
|
+
text2sql.index({ names: ['main'] }),
|
|
447
|
+
);
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
The first caller introspects the database and writes the cache. The other
|
|
451
|
+
callers wait. When each waiter gets the key, its `index()` call reads the cache
|
|
452
|
+
that the first caller wrote.
|
|
453
|
+
|
|
454
|
+
`SqliteStore` shares keys between the processes on one host. For a fleet of
|
|
455
|
+
hosts, acquire the key from a service that all hosts share, for example a
|
|
456
|
+
Postgres advisory lock, and give all hosts the same cache.
|
|
457
|
+
|
|
458
|
+
> On object-storage-backed volumes (GCS/S3 FUSE) `rename` is not atomic. The
|
|
459
|
+
> `FileIndexCache` parse-as-miss behavior tolerates a torn write: the next
|
|
460
|
+
> `index()` call introspects again.
|
|
475
461
|
|
|
476
462
|
## Streaming Index Progress
|
|
477
463
|
|
|
@@ -484,12 +470,11 @@ import { createUIMessageStream } from 'ai';
|
|
|
484
470
|
|
|
485
471
|
import {
|
|
486
472
|
AdapterIndexer,
|
|
487
|
-
FileIndexLock,
|
|
488
473
|
TEXT2SQL_INDEX_PROGRESS_CHUNK,
|
|
489
474
|
type Text2SqlIndexProgressEvent,
|
|
490
475
|
} from '@deepagents/text2sql';
|
|
491
476
|
|
|
492
|
-
const indexer = new AdapterIndexer({ adapters
|
|
477
|
+
const indexer = new AdapterIndexer({ adapters });
|
|
493
478
|
|
|
494
479
|
await context.continue(user('Show me top 10 customers'));
|
|
495
480
|
|