@deepagents/text2sql 0.12.0 → 0.13.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/dist/index.js +263 -81
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/groundings/index.js +167 -11
- package/dist/lib/adapters/groundings/index.js.map +4 -4
- package/dist/lib/adapters/mysql/index.js +167 -11
- package/dist/lib/adapters/mysql/index.js.map +4 -4
- package/dist/lib/adapters/postgres/index.js +167 -11
- package/dist/lib/adapters/postgres/index.js.map +4 -4
- package/dist/lib/adapters/spreadsheet/index.js +2 -0
- package/dist/lib/adapters/spreadsheet/index.js.map +3 -3
- package/dist/lib/adapters/sqlite/index.js +167 -11
- package/dist/lib/adapters/sqlite/index.js.map +4 -4
- package/dist/lib/adapters/sqlserver/column-stats.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/index.js +168 -14
- package/dist/lib/adapters/sqlserver/index.js.map +4 -4
- package/dist/lib/agents/result-tools.d.ts +12 -3
- package/dist/lib/agents/result-tools.d.ts.map +1 -1
- package/dist/lib/agents/sql.agent.d.ts +1 -1
- package/dist/lib/agents/sql.agent.d.ts.map +1 -1
- package/dist/lib/instructions.d.ts.map +1 -1
- package/dist/lib/sql.d.ts +4 -15
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +176 -10
- package/dist/lib/synthesis/index.js.map +4 -4
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts +3 -3
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +1 -1
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -392,6 +392,7 @@ import z2 from "zod";
|
|
|
392
392
|
import { toState } from "@deepagents/agent";
|
|
393
393
|
|
|
394
394
|
// packages/context/dist/index.js
|
|
395
|
+
import { mergeWith } from "lodash-es";
|
|
395
396
|
import { encode } from "gpt-tokenizer";
|
|
396
397
|
import { generateId } from "ai";
|
|
397
398
|
import pluralize from "pluralize";
|
|
@@ -603,7 +604,7 @@ function message(content) {
|
|
|
603
604
|
} : content;
|
|
604
605
|
return {
|
|
605
606
|
id: message2.id,
|
|
606
|
-
name:
|
|
607
|
+
name: message2.role,
|
|
607
608
|
data: "content",
|
|
608
609
|
type: "message",
|
|
609
610
|
persist: true,
|
|
@@ -625,6 +626,22 @@ function assistantText(content, options) {
|
|
|
625
626
|
parts: [{ type: "text", text: content }]
|
|
626
627
|
});
|
|
627
628
|
}
|
|
629
|
+
var LAZY_ID = Symbol("lazy-id");
|
|
630
|
+
function isLazyFragment(fragment2) {
|
|
631
|
+
return LAZY_ID in fragment2;
|
|
632
|
+
}
|
|
633
|
+
function lastAssistantMessage(content) {
|
|
634
|
+
return {
|
|
635
|
+
name: "assistant",
|
|
636
|
+
type: "message",
|
|
637
|
+
persist: true,
|
|
638
|
+
data: "content",
|
|
639
|
+
[LAZY_ID]: {
|
|
640
|
+
type: "last-assistant",
|
|
641
|
+
content
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
628
645
|
var ContextRenderer = class {
|
|
629
646
|
options;
|
|
630
647
|
constructor(options = {}) {
|
|
@@ -951,6 +968,8 @@ var ContextEngine = class {
|
|
|
951
968
|
#branch = null;
|
|
952
969
|
#chatData = null;
|
|
953
970
|
#initialized = false;
|
|
971
|
+
/** Initial metadata to merge on first initialization */
|
|
972
|
+
#initialMetadata;
|
|
954
973
|
constructor(options) {
|
|
955
974
|
if (!options.chatId) {
|
|
956
975
|
throw new Error("chatId is required");
|
|
@@ -962,6 +981,7 @@ var ContextEngine = class {
|
|
|
962
981
|
this.#chatId = options.chatId;
|
|
963
982
|
this.#userId = options.userId;
|
|
964
983
|
this.#branchName = "main";
|
|
984
|
+
this.#initialMetadata = options.metadata;
|
|
965
985
|
}
|
|
966
986
|
/**
|
|
967
987
|
* Initialize the chat and branch if they don't exist.
|
|
@@ -974,6 +994,15 @@ var ContextEngine = class {
|
|
|
974
994
|
id: this.#chatId,
|
|
975
995
|
userId: this.#userId
|
|
976
996
|
});
|
|
997
|
+
if (this.#initialMetadata) {
|
|
998
|
+
this.#chatData = await this.#store.updateChat(this.#chatId, {
|
|
999
|
+
metadata: {
|
|
1000
|
+
...this.#chatData.metadata,
|
|
1001
|
+
...this.#initialMetadata
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
this.#initialMetadata = void 0;
|
|
1005
|
+
}
|
|
977
1006
|
this.#branch = await this.#store.getActiveBranch(this.#chatId);
|
|
978
1007
|
this.#initialized = true;
|
|
979
1008
|
}
|
|
@@ -1121,6 +1150,12 @@ var ContextEngine = class {
|
|
|
1121
1150
|
if (this.#pendingMessages.length === 0) {
|
|
1122
1151
|
return;
|
|
1123
1152
|
}
|
|
1153
|
+
for (let i = 0; i < this.#pendingMessages.length; i++) {
|
|
1154
|
+
const fragment2 = this.#pendingMessages[i];
|
|
1155
|
+
if (isLazyFragment(fragment2)) {
|
|
1156
|
+
this.#pendingMessages[i] = await this.#resolveLazyFragment(fragment2);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1124
1159
|
let parentId = this.#branch.headMessageId;
|
|
1125
1160
|
const now = Date.now();
|
|
1126
1161
|
for (const fragment2 of this.#pendingMessages) {
|
|
@@ -1140,6 +1175,39 @@ var ContextEngine = class {
|
|
|
1140
1175
|
this.#branch.headMessageId = parentId;
|
|
1141
1176
|
this.#pendingMessages = [];
|
|
1142
1177
|
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Resolve a lazy fragment by finding the appropriate ID.
|
|
1180
|
+
*/
|
|
1181
|
+
async #resolveLazyFragment(fragment2) {
|
|
1182
|
+
const lazy = fragment2[LAZY_ID];
|
|
1183
|
+
if (lazy.type === "last-assistant") {
|
|
1184
|
+
const lastId = await this.#getLastAssistantId();
|
|
1185
|
+
return assistantText(lazy.content, { id: lastId ?? crypto.randomUUID() });
|
|
1186
|
+
}
|
|
1187
|
+
throw new Error(`Unknown lazy fragment type: ${lazy.type}`);
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Find the most recent assistant message ID (pending or persisted).
|
|
1191
|
+
*/
|
|
1192
|
+
async #getLastAssistantId() {
|
|
1193
|
+
for (let i = this.#pendingMessages.length - 1; i >= 0; i--) {
|
|
1194
|
+
const msg = this.#pendingMessages[i];
|
|
1195
|
+
if (msg.name === "assistant" && !isLazyFragment(msg)) {
|
|
1196
|
+
return msg.id;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
if (this.#branch?.headMessageId) {
|
|
1200
|
+
const chain = await this.#store.getMessageChain(
|
|
1201
|
+
this.#branch.headMessageId
|
|
1202
|
+
);
|
|
1203
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
1204
|
+
if (chain[i].name === "assistant") {
|
|
1205
|
+
return chain[i].id;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
return void 0;
|
|
1210
|
+
}
|
|
1143
1211
|
/**
|
|
1144
1212
|
* Estimate token count and cost for the full context.
|
|
1145
1213
|
*
|
|
@@ -1408,6 +1476,36 @@ var ContextEngine = class {
|
|
|
1408
1476
|
}
|
|
1409
1477
|
this.#chatData = await this.#store.updateChat(this.#chatId, storeUpdates);
|
|
1410
1478
|
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Track token usage for the current chat.
|
|
1481
|
+
* Accumulates usage metrics in chat.metadata.usage.
|
|
1482
|
+
*
|
|
1483
|
+
* @param usage - Token usage from AI SDK (LanguageModelUsage)
|
|
1484
|
+
*
|
|
1485
|
+
* @example
|
|
1486
|
+
* ```ts
|
|
1487
|
+
* // In onFinish callback
|
|
1488
|
+
* const usage = await result.totalUsage;
|
|
1489
|
+
* await context.trackUsage(usage);
|
|
1490
|
+
* ```
|
|
1491
|
+
*/
|
|
1492
|
+
async trackUsage(usage) {
|
|
1493
|
+
await this.#ensureInitialized();
|
|
1494
|
+
const freshChatData = await this.#store.getChat(this.#chatId);
|
|
1495
|
+
const currentUsage = freshChatData?.metadata?.usage ?? {};
|
|
1496
|
+
const updatedUsage = mergeWith(
|
|
1497
|
+
{},
|
|
1498
|
+
currentUsage,
|
|
1499
|
+
usage,
|
|
1500
|
+
(a, b) => typeof a === "number" || typeof b === "number" ? (a ?? 0) + (b ?? 0) : void 0
|
|
1501
|
+
);
|
|
1502
|
+
this.#chatData = await this.#store.updateChat(this.#chatId, {
|
|
1503
|
+
metadata: {
|
|
1504
|
+
...freshChatData?.metadata,
|
|
1505
|
+
usage: updatedUsage
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1411
1509
|
/**
|
|
1412
1510
|
* Consolidate context fragments (no-op for now).
|
|
1413
1511
|
*
|
|
@@ -1419,6 +1517,35 @@ var ContextEngine = class {
|
|
|
1419
1517
|
consolidate() {
|
|
1420
1518
|
return void 0;
|
|
1421
1519
|
}
|
|
1520
|
+
/**
|
|
1521
|
+
* Extract skill path mappings from available_skills fragments.
|
|
1522
|
+
* Returns array of { host, sandbox } for mounting in sandbox filesystem.
|
|
1523
|
+
*
|
|
1524
|
+
* Reads the original `paths` configuration stored in fragment metadata
|
|
1525
|
+
* by the skills() fragment helper.
|
|
1526
|
+
*
|
|
1527
|
+
* @example
|
|
1528
|
+
* ```ts
|
|
1529
|
+
* const context = new ContextEngine({ store, chatId, userId })
|
|
1530
|
+
* .set(skills({ paths: [{ host: './skills', sandbox: '/skills' }] }));
|
|
1531
|
+
*
|
|
1532
|
+
* const mounts = context.getSkillMounts();
|
|
1533
|
+
* // [{ host: './skills', sandbox: '/skills' }]
|
|
1534
|
+
* ```
|
|
1535
|
+
*/
|
|
1536
|
+
getSkillMounts() {
|
|
1537
|
+
const mounts = [];
|
|
1538
|
+
for (const fragment2 of this.#fragments) {
|
|
1539
|
+
if (fragment2.name === "available_skills" && fragment2.metadata && Array.isArray(fragment2.metadata.paths)) {
|
|
1540
|
+
for (const mapping of fragment2.metadata.paths) {
|
|
1541
|
+
if (typeof mapping === "object" && mapping !== null && typeof mapping.host === "string" && typeof mapping.sandbox === "string") {
|
|
1542
|
+
mounts.push({ host: mapping.host, sandbox: mapping.sandbox });
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
return mounts;
|
|
1548
|
+
}
|
|
1422
1549
|
/**
|
|
1423
1550
|
* Inspect the full context state for debugging.
|
|
1424
1551
|
* Returns a JSON-serializable object with context information.
|
|
@@ -1658,9 +1785,10 @@ var errorRecoveryGuardrail = {
|
|
|
1658
1785
|
"My response format was invalid. Let me try again with a properly formatted response."
|
|
1659
1786
|
);
|
|
1660
1787
|
}
|
|
1788
|
+
console.dir({ part }, { depth: null });
|
|
1661
1789
|
return logAndFail(
|
|
1662
1790
|
"Unknown error",
|
|
1663
|
-
`An error occurred: ${errorText
|
|
1791
|
+
`An error occurred: ${errorText}. Let me try a different approach.`
|
|
1664
1792
|
);
|
|
1665
1793
|
}
|
|
1666
1794
|
};
|
|
@@ -1845,12 +1973,20 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1845
1973
|
}
|
|
1846
1974
|
async listChats(options) {
|
|
1847
1975
|
const params = [];
|
|
1848
|
-
|
|
1976
|
+
const whereClauses = [];
|
|
1849
1977
|
let limitClause = "";
|
|
1850
1978
|
if (options?.userId) {
|
|
1851
|
-
|
|
1979
|
+
whereClauses.push("c.userId = ?");
|
|
1852
1980
|
params.push(options.userId);
|
|
1853
1981
|
}
|
|
1982
|
+
if (options?.metadata) {
|
|
1983
|
+
whereClauses.push(`json_extract(c.metadata, '$.' || ?) = ?`);
|
|
1984
|
+
params.push(options.metadata.key);
|
|
1985
|
+
params.push(
|
|
1986
|
+
typeof options.metadata.value === "boolean" ? options.metadata.value ? 1 : 0 : options.metadata.value
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1989
|
+
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
1854
1990
|
if (options?.limit !== void 0) {
|
|
1855
1991
|
limitClause = " LIMIT ?";
|
|
1856
1992
|
params.push(options.limit);
|
|
@@ -1864,6 +2000,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1864
2000
|
c.id,
|
|
1865
2001
|
c.userId,
|
|
1866
2002
|
c.title,
|
|
2003
|
+
c.metadata,
|
|
1867
2004
|
c.createdAt,
|
|
1868
2005
|
c.updatedAt,
|
|
1869
2006
|
COUNT(DISTINCT m.id) as messageCount,
|
|
@@ -1879,6 +2016,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1879
2016
|
id: row.id,
|
|
1880
2017
|
userId: row.userId,
|
|
1881
2018
|
title: row.title ?? void 0,
|
|
2019
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
1882
2020
|
messageCount: row.messageCount,
|
|
1883
2021
|
branchCount: row.branchCount,
|
|
1884
2022
|
createdAt: row.createdAt,
|
|
@@ -1910,9 +2048,16 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1910
2048
|
async addMessage(message2) {
|
|
1911
2049
|
this.#db.prepare(
|
|
1912
2050
|
`INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
|
|
1913
|
-
VALUES (
|
|
2051
|
+
VALUES (
|
|
2052
|
+
?1,
|
|
2053
|
+
?2,
|
|
2054
|
+
CASE WHEN ?3 = ?1 THEN (SELECT parentId FROM messages WHERE id = ?1) ELSE ?3 END,
|
|
2055
|
+
?4,
|
|
2056
|
+
?5,
|
|
2057
|
+
?6,
|
|
2058
|
+
?7
|
|
2059
|
+
)
|
|
1914
2060
|
ON CONFLICT(id) DO UPDATE SET
|
|
1915
|
-
parentId = excluded.parentId,
|
|
1916
2061
|
name = excluded.name,
|
|
1917
2062
|
type = excluded.type,
|
|
1918
2063
|
data = excluded.data`
|
|
@@ -2387,13 +2532,9 @@ var Agent = class _Agent {
|
|
|
2387
2532
|
writer.write({ type: "finish" });
|
|
2388
2533
|
return;
|
|
2389
2534
|
}
|
|
2390
|
-
writer
|
|
2391
|
-
type: "text-delta",
|
|
2392
|
-
id: generateId2(),
|
|
2393
|
-
delta: ` ${failureFeedback}`
|
|
2394
|
-
});
|
|
2535
|
+
writeText(writer, failureFeedback);
|
|
2395
2536
|
const selfCorrectionText = accumulatedText + " " + failureFeedback;
|
|
2396
|
-
context.set(
|
|
2537
|
+
context.set(lastAssistantMessage(selfCorrectionText));
|
|
2397
2538
|
await context.save();
|
|
2398
2539
|
currentResult = await this.#createRawStream(
|
|
2399
2540
|
contextVariables,
|
|
@@ -2484,10 +2625,10 @@ var repairToolCall = async ({
|
|
|
2484
2625
|
if (NoSuchToolError.isInstance(error)) {
|
|
2485
2626
|
return null;
|
|
2486
2627
|
}
|
|
2487
|
-
const
|
|
2628
|
+
const tool4 = tools3[toolCall.toolName];
|
|
2488
2629
|
const { output } = await generateText({
|
|
2489
2630
|
model: groq("openai/gpt-oss-20b"),
|
|
2490
|
-
output: Output.object({ schema:
|
|
2631
|
+
output: Output.object({ schema: tool4.inputSchema }),
|
|
2491
2632
|
prompt: [
|
|
2492
2633
|
`The model tried to call the tool "${toolCall.toolName}" with the following inputs:`,
|
|
2493
2634
|
JSON.stringify(toolCall.input),
|
|
@@ -2498,6 +2639,22 @@ var repairToolCall = async ({
|
|
|
2498
2639
|
});
|
|
2499
2640
|
return { ...toolCall, input: JSON.stringify(output) };
|
|
2500
2641
|
};
|
|
2642
|
+
function writeText(writer, text) {
|
|
2643
|
+
const feedbackPartId = generateId2();
|
|
2644
|
+
writer.write({
|
|
2645
|
+
id: feedbackPartId,
|
|
2646
|
+
type: "text-start"
|
|
2647
|
+
});
|
|
2648
|
+
writer.write({
|
|
2649
|
+
id: feedbackPartId,
|
|
2650
|
+
type: "text-delta",
|
|
2651
|
+
delta: ` ${text}`
|
|
2652
|
+
});
|
|
2653
|
+
writer.write({
|
|
2654
|
+
id: feedbackPartId,
|
|
2655
|
+
type: "text-end"
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2501
2658
|
|
|
2502
2659
|
// packages/text2sql/src/lib/agents/explainer.agent.ts
|
|
2503
2660
|
import { groq as groq2 } from "@ai-sdk/groq";
|
|
@@ -2602,10 +2759,12 @@ var fragments = [
|
|
|
2602
2759
|
var developer_agent_default = { tools, fragments };
|
|
2603
2760
|
|
|
2604
2761
|
// packages/text2sql/src/lib/agents/result-tools.ts
|
|
2762
|
+
import "ai";
|
|
2605
2763
|
import { createBashTool as createBashTool2 } from "bash-tool";
|
|
2606
2764
|
import chalk3 from "chalk";
|
|
2607
2765
|
import {
|
|
2608
2766
|
Bash,
|
|
2767
|
+
InMemoryFs,
|
|
2609
2768
|
MountableFs,
|
|
2610
2769
|
OverlayFs,
|
|
2611
2770
|
ReadWriteFs,
|
|
@@ -2613,6 +2772,7 @@ import {
|
|
|
2613
2772
|
} from "just-bash";
|
|
2614
2773
|
import * as fs from "node:fs/promises";
|
|
2615
2774
|
import * as path from "node:path";
|
|
2775
|
+
import { v7 } from "uuid";
|
|
2616
2776
|
function createCommand(name, subcommands) {
|
|
2617
2777
|
const usageLines = Object.entries(subcommands).map(([, def]) => ` ${name} ${def.usage.padEnd(30)} ${def.description}`).join("\n");
|
|
2618
2778
|
return defineCommand2(name, async (args, ctx) => {
|
|
@@ -2663,12 +2823,20 @@ function createSqlCommand(adapter) {
|
|
|
2663
2823
|
try {
|
|
2664
2824
|
const rows = await adapter.execute(query);
|
|
2665
2825
|
const rowsArray = Array.isArray(rows) ? rows : [];
|
|
2666
|
-
const
|
|
2667
|
-
|
|
2826
|
+
const content = JSON.stringify(rowsArray, null, 2);
|
|
2827
|
+
const filename = `${v7()}.json`;
|
|
2828
|
+
const isolatedPath = `/results/${filename}`;
|
|
2829
|
+
const sharedPath = `/artifacts/${filename}`;
|
|
2830
|
+
await Promise.all([
|
|
2831
|
+
ctx.fs.writeFile(isolatedPath, content),
|
|
2832
|
+
// Current turn's isolated copy
|
|
2833
|
+
ctx.fs.writeFile(sharedPath, content)
|
|
2834
|
+
// Shared copy for cross-turn access
|
|
2835
|
+
]);
|
|
2668
2836
|
const columns = rowsArray.length > 0 ? Object.keys(rowsArray[0]) : [];
|
|
2669
2837
|
return {
|
|
2670
2838
|
stdout: [
|
|
2671
|
-
|
|
2839
|
+
`results stored in ${sharedPath}`,
|
|
2672
2840
|
`columns: ${columns.join(", ") || "(none)"}`,
|
|
2673
2841
|
`rows: ${rowsArray.length}`
|
|
2674
2842
|
].join("\n") + "\n",
|
|
@@ -2714,14 +2882,24 @@ function createSqlCommand(adapter) {
|
|
|
2714
2882
|
});
|
|
2715
2883
|
}
|
|
2716
2884
|
async function createResultTools(options) {
|
|
2717
|
-
const { adapter, chatId, messageId } = options;
|
|
2885
|
+
const { adapter, chatId, messageId, skillMounts = [] } = options;
|
|
2718
2886
|
const sqlCommand = createSqlCommand(adapter);
|
|
2719
|
-
const
|
|
2887
|
+
const root = process.env.TEXT2SQL_FS_ROOT || process.cwd();
|
|
2888
|
+
const chatDir = path.join(root, "artifacts", chatId);
|
|
2720
2889
|
const resultsDir = path.join(chatDir, messageId, "results");
|
|
2721
2890
|
await fs.mkdir(resultsDir, { recursive: true });
|
|
2891
|
+
const fsMounts = skillMounts.map(({ host, sandbox: sandbox2 }) => ({
|
|
2892
|
+
mountPoint: sandbox2,
|
|
2893
|
+
filesystem: new OverlayFs({
|
|
2894
|
+
root: host,
|
|
2895
|
+
mountPoint: "/",
|
|
2896
|
+
readOnly: true
|
|
2897
|
+
})
|
|
2898
|
+
}));
|
|
2722
2899
|
const filesystem = new MountableFs({
|
|
2723
|
-
base: new
|
|
2900
|
+
base: new InMemoryFs(),
|
|
2724
2901
|
mounts: [
|
|
2902
|
+
...fsMounts,
|
|
2725
2903
|
{
|
|
2726
2904
|
mountPoint: "/results",
|
|
2727
2905
|
filesystem: new ReadWriteFs({ root: resultsDir })
|
|
@@ -2739,10 +2917,6 @@ async function createResultTools(options) {
|
|
|
2739
2917
|
const { bash, sandbox } = await createBashTool2({
|
|
2740
2918
|
sandbox: bashInstance,
|
|
2741
2919
|
destination: "/",
|
|
2742
|
-
uploadDirectory: {
|
|
2743
|
-
source: process.cwd(),
|
|
2744
|
-
include: "packages/text2sql/src/skills/**/*.md"
|
|
2745
|
-
},
|
|
2746
2920
|
onBeforeBashCall: ({ command }) => {
|
|
2747
2921
|
console.log(chalk3.cyan(`[onBeforeBashCall]: ${command}`));
|
|
2748
2922
|
return { command };
|
|
@@ -2765,7 +2939,9 @@ import {
|
|
|
2765
2939
|
NoContentGeneratedError,
|
|
2766
2940
|
NoObjectGeneratedError,
|
|
2767
2941
|
NoOutputGeneratedError,
|
|
2768
|
-
TypeValidationError
|
|
2942
|
+
TypeValidationError,
|
|
2943
|
+
defaultSettingsMiddleware,
|
|
2944
|
+
wrapLanguageModel
|
|
2769
2945
|
} from "ai";
|
|
2770
2946
|
import { Console } from "node:console";
|
|
2771
2947
|
import { createWriteStream } from "node:fs";
|
|
@@ -2777,6 +2953,7 @@ var logger = new Console({
|
|
|
2777
2953
|
stderr: createWriteStream("./sql-agent-error.log", { flags: "a" }),
|
|
2778
2954
|
inspectOptions: { depth: null }
|
|
2779
2955
|
});
|
|
2956
|
+
var RETRY_TEMPERATURES = [0, 0.2, 0.3];
|
|
2780
2957
|
function extractSql(output) {
|
|
2781
2958
|
const match = output.match(/```sql\n?([\s\S]*?)```/);
|
|
2782
2959
|
return match ? match[1].trim() : output.trim();
|
|
@@ -2830,8 +3007,14 @@ async function toSql(options) {
|
|
|
2830
3007
|
} else {
|
|
2831
3008
|
context.set(user(options.input));
|
|
2832
3009
|
}
|
|
3010
|
+
const temperature = RETRY_TEMPERATURES[attemptNumber - 1] ?? RETRY_TEMPERATURES[RETRY_TEMPERATURES.length - 1];
|
|
3011
|
+
const baseModel = options.model ?? groq3("openai/gpt-oss-20b");
|
|
3012
|
+
const model = wrapLanguageModel({
|
|
3013
|
+
model: baseModel,
|
|
3014
|
+
middleware: defaultSettingsMiddleware({ settings: { temperature } })
|
|
3015
|
+
});
|
|
2833
3016
|
const sqlOutput = structuredOutput({
|
|
2834
|
-
model
|
|
3017
|
+
model,
|
|
2835
3018
|
context,
|
|
2836
3019
|
schema: z3.union([
|
|
2837
3020
|
z3.object({
|
|
@@ -2971,12 +3154,12 @@ var suggestionsAgent = agent2({
|
|
|
2971
3154
|
});
|
|
2972
3155
|
|
|
2973
3156
|
// packages/text2sql/src/lib/agents/text2sql.agent.ts
|
|
2974
|
-
import { tool as
|
|
3157
|
+
import { tool as tool3 } from "ai";
|
|
2975
3158
|
import z5 from "zod";
|
|
2976
3159
|
import { toState as toState2 } from "@deepagents/agent";
|
|
2977
3160
|
import { scratchpad_tool } from "@deepagents/toolbox";
|
|
2978
3161
|
var tools2 = {
|
|
2979
|
-
validate_query:
|
|
3162
|
+
validate_query: tool3({
|
|
2980
3163
|
description: `Validate SQL query syntax before execution. Use this to check if your SQL is valid before running db_query. This helps catch errors early and allows you to correct the query if needed.`,
|
|
2981
3164
|
inputSchema: z5.object({
|
|
2982
3165
|
sql: z5.string().describe("The SQL query to validate.")
|
|
@@ -2990,7 +3173,7 @@ var tools2 = {
|
|
|
2990
3173
|
return "Query is valid.";
|
|
2991
3174
|
}
|
|
2992
3175
|
}),
|
|
2993
|
-
db_query:
|
|
3176
|
+
db_query: tool3({
|
|
2994
3177
|
description: `Internal tool to fetch data from the store's database. Write a SQL query to retrieve the information needed to answer the user's question. The results will be returned as data that you can then present to the user in natural language.`,
|
|
2995
3178
|
inputSchema: z5.object({
|
|
2996
3179
|
reasoning: z5.string().describe(
|
|
@@ -3327,6 +3510,10 @@ function reasoningFramework() {
|
|
|
3327
3510
|
principle({
|
|
3328
3511
|
title: "Inhibit your response",
|
|
3329
3512
|
description: "Only take an action after all the above reasoning is completed. Once you've taken an action, you cannot take it back."
|
|
3513
|
+
}),
|
|
3514
|
+
principle({
|
|
3515
|
+
title: "Continuous self-monitoring",
|
|
3516
|
+
description: "Constantly evaluate your own reasoning process for any gaps, biases, or errors. Apply the above principles iteratively as needed."
|
|
3330
3517
|
})
|
|
3331
3518
|
)
|
|
3332
3519
|
];
|
|
@@ -3540,7 +3727,31 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
3540
3727
|
"Maintain consistency with previous query structure when possible."
|
|
3541
3728
|
],
|
|
3542
3729
|
notes: "If reference is ambiguous, ask which previous result or entity the user means."
|
|
3543
|
-
})
|
|
3730
|
+
}),
|
|
3731
|
+
fragment(
|
|
3732
|
+
"Bash tool usage",
|
|
3733
|
+
workflow({
|
|
3734
|
+
task: "Query execution",
|
|
3735
|
+
steps: [
|
|
3736
|
+
'Execute SQL through bash tool: sql run "SELECT ..."',
|
|
3737
|
+
"Read the output: file path, column names, and row count.",
|
|
3738
|
+
"Use column names to construct jq filters: cat <path> | jq '.[] | {col1, col2}'",
|
|
3739
|
+
"For large results, slice first: cat <path> | jq '.[:10]'"
|
|
3740
|
+
]
|
|
3741
|
+
}),
|
|
3742
|
+
hint(
|
|
3743
|
+
`You cannot access sql through a tool, it'll fail so the proper way to access it is through the bash tool using "sql run" and "sql validate" commands.`
|
|
3744
|
+
),
|
|
3745
|
+
hint(
|
|
3746
|
+
"The sql command outputs: file path, column names (comma-separated), and row count. Use column names to construct precise jq queries."
|
|
3747
|
+
),
|
|
3748
|
+
hint(
|
|
3749
|
+
'This is virtual bash environment and "sql" commands proxy to the database hence you cannot access sql files directly.'
|
|
3750
|
+
),
|
|
3751
|
+
hint(
|
|
3752
|
+
"If a query fails, the sql command returns an error message in stderr."
|
|
3753
|
+
)
|
|
3754
|
+
)
|
|
3544
3755
|
];
|
|
3545
3756
|
if (date === "strict") {
|
|
3546
3757
|
baseTeachings.push(
|
|
@@ -3573,12 +3784,9 @@ var Text2Sql = class {
|
|
|
3573
3784
|
#config;
|
|
3574
3785
|
constructor(config) {
|
|
3575
3786
|
this.#config = {
|
|
3787
|
+
teachingsOptions: config.teachingsOptions,
|
|
3576
3788
|
adapter: config.adapter,
|
|
3577
|
-
|
|
3578
|
-
instructions: [
|
|
3579
|
-
...guidelines(config.teachingsOptions),
|
|
3580
|
-
...config.instructions ?? []
|
|
3581
|
-
],
|
|
3789
|
+
context: config.context,
|
|
3582
3790
|
tools: config.tools ?? {},
|
|
3583
3791
|
model: config.model,
|
|
3584
3792
|
introspection: new JsonCache(
|
|
@@ -3592,7 +3800,7 @@ var Text2Sql = class {
|
|
|
3592
3800
|
input,
|
|
3593
3801
|
adapter: this.#config.adapter,
|
|
3594
3802
|
schemaFragments,
|
|
3595
|
-
instructions:
|
|
3803
|
+
instructions: [],
|
|
3596
3804
|
model: this.#config.model
|
|
3597
3805
|
});
|
|
3598
3806
|
return result.sql;
|
|
@@ -3652,45 +3860,24 @@ var Text2Sql = class {
|
|
|
3652
3860
|
})
|
|
3653
3861
|
];
|
|
3654
3862
|
}
|
|
3655
|
-
async chat(messages
|
|
3656
|
-
const
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
userId: params.userId
|
|
3661
|
-
}).set(
|
|
3662
|
-
...schemaFragments,
|
|
3663
|
-
...this.#buildRenderingInstructions(),
|
|
3664
|
-
fragment(
|
|
3665
|
-
"Bash tool usage",
|
|
3666
|
-
workflow({
|
|
3667
|
-
task: "Query execution",
|
|
3668
|
-
steps: [
|
|
3669
|
-
'Execute SQL through bash tool: sql run "SELECT ..."',
|
|
3670
|
-
"Read the output: file path, column names, and row count.",
|
|
3671
|
-
"Use column names to construct jq filters: cat <path> | jq '.[] | {col1, col2}'",
|
|
3672
|
-
"For large results, slice first: cat <path> | jq '.[:10]'"
|
|
3673
|
-
]
|
|
3674
|
-
}),
|
|
3675
|
-
hint(
|
|
3676
|
-
"The sql command outputs: file path, column names (comma-separated), and row count. Use column names to construct precise jq queries."
|
|
3677
|
-
),
|
|
3678
|
-
hint(
|
|
3679
|
-
"If a query fails, the sql command returns an error message in stderr."
|
|
3680
|
-
)
|
|
3681
|
-
),
|
|
3682
|
-
...this.#config.instructions
|
|
3863
|
+
async chat(messages) {
|
|
3864
|
+
const context = this.#config.context(
|
|
3865
|
+
...guidelines(this.#config.teachingsOptions),
|
|
3866
|
+
...await this.index(),
|
|
3867
|
+
...this.#buildRenderingInstructions()
|
|
3683
3868
|
);
|
|
3684
3869
|
const userMsg = messages.at(-1);
|
|
3685
3870
|
if (userMsg) {
|
|
3686
|
-
context.set(
|
|
3871
|
+
context.set(message(userMsg));
|
|
3687
3872
|
await context.save();
|
|
3688
3873
|
}
|
|
3689
3874
|
const messageId = userMsg?.id ?? generateId3();
|
|
3875
|
+
const skillMounts = context.getSkillMounts();
|
|
3690
3876
|
const { bash } = await createResultTools({
|
|
3691
3877
|
adapter: this.#config.adapter,
|
|
3692
|
-
chatId:
|
|
3693
|
-
messageId
|
|
3878
|
+
chatId: context.chatId,
|
|
3879
|
+
messageId,
|
|
3880
|
+
skillMounts
|
|
3694
3881
|
});
|
|
3695
3882
|
const chatAgent = agent({
|
|
3696
3883
|
name: "text2sql",
|
|
@@ -3710,31 +3897,25 @@ var Text2Sql = class {
|
|
|
3710
3897
|
sendFinish: true,
|
|
3711
3898
|
sendReasoning: true,
|
|
3712
3899
|
sendSources: true,
|
|
3900
|
+
originalMessages: messages,
|
|
3713
3901
|
generateMessageId: generateId3,
|
|
3714
3902
|
onFinish: async ({ responseMessage }) => {
|
|
3715
3903
|
context.set(assistant(responseMessage));
|
|
3716
3904
|
await context.save();
|
|
3905
|
+
await context.trackUsage(await result.totalUsage);
|
|
3717
3906
|
}
|
|
3718
3907
|
});
|
|
3719
3908
|
}
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
*/
|
|
3724
|
-
async developer(messages, params) {
|
|
3725
|
-
const schemaFragments = await this.index();
|
|
3726
|
-
const context = new ContextEngine({
|
|
3727
|
-
store: this.#config.store,
|
|
3728
|
-
chatId: params.chatId,
|
|
3729
|
-
userId: params.userId
|
|
3730
|
-
}).set(
|
|
3909
|
+
async developer(messages) {
|
|
3910
|
+
const context = this.#config.context(
|
|
3911
|
+
...guidelines(this.#config.teachingsOptions),
|
|
3731
3912
|
...developer_agent_default.fragments,
|
|
3732
|
-
...this
|
|
3733
|
-
...
|
|
3913
|
+
...await this.index(),
|
|
3914
|
+
...this.#buildRenderingInstructions()
|
|
3734
3915
|
);
|
|
3735
3916
|
const userMsg = messages.at(-1);
|
|
3736
3917
|
if (userMsg) {
|
|
3737
|
-
context.set(
|
|
3918
|
+
context.set(message(userMsg));
|
|
3738
3919
|
await context.save();
|
|
3739
3920
|
}
|
|
3740
3921
|
const developerAgent = agent({
|
|
@@ -3756,6 +3937,7 @@ var Text2Sql = class {
|
|
|
3756
3937
|
onFinish: async ({ responseMessage }) => {
|
|
3757
3938
|
context.set(assistant(responseMessage));
|
|
3758
3939
|
await context.save();
|
|
3940
|
+
await context.trackUsage(await result.totalUsage);
|
|
3759
3941
|
}
|
|
3760
3942
|
});
|
|
3761
3943
|
}
|