@deepagents/text2sql 0.12.1 → 0.13.1
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 +133 -70
- package/dist/index.js.map +3 -3
- package/dist/lib/adapters/groundings/index.js +65 -6
- package/dist/lib/adapters/groundings/index.js.map +3 -3
- package/dist/lib/adapters/mysql/index.js +65 -6
- package/dist/lib/adapters/mysql/index.js.map +3 -3
- package/dist/lib/adapters/postgres/index.js +65 -6
- package/dist/lib/adapters/postgres/index.js.map +3 -3
- package/dist/lib/adapters/spreadsheet/index.js +1 -0
- package/dist/lib/adapters/spreadsheet/index.js.map +3 -3
- package/dist/lib/adapters/sqlite/index.js +65 -6
- package/dist/lib/adapters/sqlite/index.js.map +3 -3
- package/dist/lib/adapters/sqlserver/index.js +65 -6
- package/dist/lib/adapters/sqlserver/index.js.map +3 -3
- package/dist/lib/agents/result-tools.d.ts +9 -3
- package/dist/lib/agents/result-tools.d.ts.map +1 -1
- package/dist/lib/instructions.d.ts.map +1 -1
- package/dist/lib/sql.d.ts +6 -16
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +65 -6
- package/dist/lib/synthesis/index.js.map +3 -3
- package/package.json +9 -6
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";
|
|
@@ -967,6 +968,8 @@ var ContextEngine = class {
|
|
|
967
968
|
#branch = null;
|
|
968
969
|
#chatData = null;
|
|
969
970
|
#initialized = false;
|
|
971
|
+
/** Initial metadata to merge on first initialization */
|
|
972
|
+
#initialMetadata;
|
|
970
973
|
constructor(options) {
|
|
971
974
|
if (!options.chatId) {
|
|
972
975
|
throw new Error("chatId is required");
|
|
@@ -978,6 +981,7 @@ var ContextEngine = class {
|
|
|
978
981
|
this.#chatId = options.chatId;
|
|
979
982
|
this.#userId = options.userId;
|
|
980
983
|
this.#branchName = "main";
|
|
984
|
+
this.#initialMetadata = options.metadata;
|
|
981
985
|
}
|
|
982
986
|
/**
|
|
983
987
|
* Initialize the chat and branch if they don't exist.
|
|
@@ -990,6 +994,15 @@ var ContextEngine = class {
|
|
|
990
994
|
id: this.#chatId,
|
|
991
995
|
userId: this.#userId
|
|
992
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
|
+
}
|
|
993
1006
|
this.#branch = await this.#store.getActiveBranch(this.#chatId);
|
|
994
1007
|
this.#initialized = true;
|
|
995
1008
|
}
|
|
@@ -1463,6 +1476,36 @@ var ContextEngine = class {
|
|
|
1463
1476
|
}
|
|
1464
1477
|
this.#chatData = await this.#store.updateChat(this.#chatId, storeUpdates);
|
|
1465
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
|
+
}
|
|
1466
1509
|
/**
|
|
1467
1510
|
* Consolidate context fragments (no-op for now).
|
|
1468
1511
|
*
|
|
@@ -1742,6 +1785,7 @@ var errorRecoveryGuardrail = {
|
|
|
1742
1785
|
"My response format was invalid. Let me try again with a properly formatted response."
|
|
1743
1786
|
);
|
|
1744
1787
|
}
|
|
1788
|
+
console.dir({ part }, { depth: null });
|
|
1745
1789
|
return logAndFail(
|
|
1746
1790
|
"Unknown error",
|
|
1747
1791
|
`An error occurred: ${errorText}. Let me try a different approach.`
|
|
@@ -1929,12 +1973,20 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1929
1973
|
}
|
|
1930
1974
|
async listChats(options) {
|
|
1931
1975
|
const params = [];
|
|
1932
|
-
|
|
1976
|
+
const whereClauses = [];
|
|
1933
1977
|
let limitClause = "";
|
|
1934
1978
|
if (options?.userId) {
|
|
1935
|
-
|
|
1979
|
+
whereClauses.push("c.userId = ?");
|
|
1936
1980
|
params.push(options.userId);
|
|
1937
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 ")}` : "";
|
|
1938
1990
|
if (options?.limit !== void 0) {
|
|
1939
1991
|
limitClause = " LIMIT ?";
|
|
1940
1992
|
params.push(options.limit);
|
|
@@ -1948,6 +2000,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1948
2000
|
c.id,
|
|
1949
2001
|
c.userId,
|
|
1950
2002
|
c.title,
|
|
2003
|
+
c.metadata,
|
|
1951
2004
|
c.createdAt,
|
|
1952
2005
|
c.updatedAt,
|
|
1953
2006
|
COUNT(DISTINCT m.id) as messageCount,
|
|
@@ -1963,6 +2016,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1963
2016
|
id: row.id,
|
|
1964
2017
|
userId: row.userId,
|
|
1965
2018
|
title: row.title ?? void 0,
|
|
2019
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
1966
2020
|
messageCount: row.messageCount,
|
|
1967
2021
|
branchCount: row.branchCount,
|
|
1968
2022
|
createdAt: row.createdAt,
|
|
@@ -1992,11 +2046,17 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1992
2046
|
// Message Operations (Graph Nodes)
|
|
1993
2047
|
// ==========================================================================
|
|
1994
2048
|
async addMessage(message2) {
|
|
1995
|
-
const existingParent = message2.parentId === message2.id ? this.#db.prepare("SELECT parentId FROM messages WHERE id = ?").get(message2.id) : void 0;
|
|
1996
|
-
const parentId = message2.parentId === message2.id ? existingParent?.parentId ?? null : message2.parentId;
|
|
1997
2049
|
this.#db.prepare(
|
|
1998
2050
|
`INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
|
|
1999
|
-
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
|
+
)
|
|
2000
2060
|
ON CONFLICT(id) DO UPDATE SET
|
|
2001
2061
|
name = excluded.name,
|
|
2002
2062
|
type = excluded.type,
|
|
@@ -2004,7 +2064,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2004
2064
|
).run(
|
|
2005
2065
|
message2.id,
|
|
2006
2066
|
message2.chatId,
|
|
2007
|
-
parentId,
|
|
2067
|
+
message2.parentId,
|
|
2008
2068
|
message2.name,
|
|
2009
2069
|
message2.type ?? null,
|
|
2010
2070
|
JSON.stringify(message2.data),
|
|
@@ -2565,10 +2625,10 @@ var repairToolCall = async ({
|
|
|
2565
2625
|
if (NoSuchToolError.isInstance(error)) {
|
|
2566
2626
|
return null;
|
|
2567
2627
|
}
|
|
2568
|
-
const
|
|
2628
|
+
const tool4 = tools3[toolCall.toolName];
|
|
2569
2629
|
const { output } = await generateText({
|
|
2570
2630
|
model: groq("openai/gpt-oss-20b"),
|
|
2571
|
-
output: Output.object({ schema:
|
|
2631
|
+
output: Output.object({ schema: tool4.inputSchema }),
|
|
2572
2632
|
prompt: [
|
|
2573
2633
|
`The model tried to call the tool "${toolCall.toolName}" with the following inputs:`,
|
|
2574
2634
|
JSON.stringify(toolCall.input),
|
|
@@ -2699,6 +2759,7 @@ var fragments = [
|
|
|
2699
2759
|
var developer_agent_default = { tools, fragments };
|
|
2700
2760
|
|
|
2701
2761
|
// packages/text2sql/src/lib/agents/result-tools.ts
|
|
2762
|
+
import "ai";
|
|
2702
2763
|
import { createBashTool as createBashTool2 } from "bash-tool";
|
|
2703
2764
|
import chalk3 from "chalk";
|
|
2704
2765
|
import {
|
|
@@ -2762,12 +2823,20 @@ function createSqlCommand(adapter) {
|
|
|
2762
2823
|
try {
|
|
2763
2824
|
const rows = await adapter.execute(query);
|
|
2764
2825
|
const rowsArray = Array.isArray(rows) ? rows : [];
|
|
2765
|
-
const
|
|
2766
|
-
|
|
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
|
+
]);
|
|
2767
2836
|
const columns = rowsArray.length > 0 ? Object.keys(rowsArray[0]) : [];
|
|
2768
2837
|
return {
|
|
2769
2838
|
stdout: [
|
|
2770
|
-
|
|
2839
|
+
`results stored in ${sharedPath}`,
|
|
2771
2840
|
`columns: ${columns.join(", ") || "(none)"}`,
|
|
2772
2841
|
`rows: ${rowsArray.length}`
|
|
2773
2842
|
].join("\n") + "\n",
|
|
@@ -3085,12 +3154,12 @@ var suggestionsAgent = agent2({
|
|
|
3085
3154
|
});
|
|
3086
3155
|
|
|
3087
3156
|
// packages/text2sql/src/lib/agents/text2sql.agent.ts
|
|
3088
|
-
import { tool as
|
|
3157
|
+
import { tool as tool3 } from "ai";
|
|
3089
3158
|
import z5 from "zod";
|
|
3090
3159
|
import { toState as toState2 } from "@deepagents/agent";
|
|
3091
3160
|
import { scratchpad_tool } from "@deepagents/toolbox";
|
|
3092
3161
|
var tools2 = {
|
|
3093
|
-
validate_query:
|
|
3162
|
+
validate_query: tool3({
|
|
3094
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.`,
|
|
3095
3164
|
inputSchema: z5.object({
|
|
3096
3165
|
sql: z5.string().describe("The SQL query to validate.")
|
|
@@ -3104,7 +3173,7 @@ var tools2 = {
|
|
|
3104
3173
|
return "Query is valid.";
|
|
3105
3174
|
}
|
|
3106
3175
|
}),
|
|
3107
|
-
db_query:
|
|
3176
|
+
db_query: tool3({
|
|
3108
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.`,
|
|
3109
3178
|
inputSchema: z5.object({
|
|
3110
3179
|
reasoning: z5.string().describe(
|
|
@@ -3441,6 +3510,10 @@ function reasoningFramework() {
|
|
|
3441
3510
|
principle({
|
|
3442
3511
|
title: "Inhibit your response",
|
|
3443
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."
|
|
3444
3517
|
})
|
|
3445
3518
|
)
|
|
3446
3519
|
];
|
|
@@ -3654,7 +3727,31 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
3654
3727
|
"Maintain consistency with previous query structure when possible."
|
|
3655
3728
|
],
|
|
3656
3729
|
notes: "If reference is ambiguous, ask which previous result or entity the user means."
|
|
3657
|
-
})
|
|
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
|
+
)
|
|
3658
3755
|
];
|
|
3659
3756
|
if (date === "strict") {
|
|
3660
3757
|
baseTeachings.push(
|
|
@@ -3687,14 +3784,12 @@ var Text2Sql = class {
|
|
|
3687
3784
|
#config;
|
|
3688
3785
|
constructor(config) {
|
|
3689
3786
|
this.#config = {
|
|
3787
|
+
teachingsOptions: config.teachingsOptions,
|
|
3690
3788
|
adapter: config.adapter,
|
|
3691
|
-
|
|
3692
|
-
instructions: [
|
|
3693
|
-
...guidelines(config.teachingsOptions),
|
|
3694
|
-
...config.instructions ?? []
|
|
3695
|
-
],
|
|
3789
|
+
context: config.context,
|
|
3696
3790
|
tools: config.tools ?? {},
|
|
3697
3791
|
model: config.model,
|
|
3792
|
+
transform: config.transform,
|
|
3698
3793
|
introspection: new JsonCache(
|
|
3699
3794
|
"introspection-" + config.version
|
|
3700
3795
|
)
|
|
@@ -3706,7 +3801,7 @@ var Text2Sql = class {
|
|
|
3706
3801
|
input,
|
|
3707
3802
|
adapter: this.#config.adapter,
|
|
3708
3803
|
schemaFragments,
|
|
3709
|
-
instructions:
|
|
3804
|
+
instructions: [],
|
|
3710
3805
|
model: this.#config.model
|
|
3711
3806
|
});
|
|
3712
3807
|
return result.sql;
|
|
@@ -3766,40 +3861,11 @@ var Text2Sql = class {
|
|
|
3766
3861
|
})
|
|
3767
3862
|
];
|
|
3768
3863
|
}
|
|
3769
|
-
async chat(messages
|
|
3770
|
-
const
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
userId: params.userId
|
|
3775
|
-
}).set(
|
|
3776
|
-
...schemaFragments,
|
|
3777
|
-
...this.#buildRenderingInstructions(),
|
|
3778
|
-
fragment(
|
|
3779
|
-
"Bash tool usage",
|
|
3780
|
-
workflow({
|
|
3781
|
-
task: "Query execution",
|
|
3782
|
-
steps: [
|
|
3783
|
-
'Execute SQL through bash tool: sql run "SELECT ..."',
|
|
3784
|
-
"Read the output: file path, column names, and row count.",
|
|
3785
|
-
"Use column names to construct jq filters: cat <path> | jq '.[] | {col1, col2}'",
|
|
3786
|
-
"For large results, slice first: cat <path> | jq '.[:10]'"
|
|
3787
|
-
]
|
|
3788
|
-
}),
|
|
3789
|
-
hint(
|
|
3790
|
-
`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.`
|
|
3791
|
-
),
|
|
3792
|
-
hint(
|
|
3793
|
-
"The sql command outputs: file path, column names (comma-separated), and row count. Use column names to construct precise jq queries."
|
|
3794
|
-
),
|
|
3795
|
-
hint(
|
|
3796
|
-
'This is virtual bash environment and "sql" commands proxy to the database hence you cannot access sql files directly.'
|
|
3797
|
-
),
|
|
3798
|
-
hint(
|
|
3799
|
-
"If a query fails, the sql command returns an error message in stderr."
|
|
3800
|
-
)
|
|
3801
|
-
),
|
|
3802
|
-
...this.#config.instructions
|
|
3864
|
+
async chat(messages) {
|
|
3865
|
+
const context = this.#config.context(
|
|
3866
|
+
...guidelines(this.#config.teachingsOptions),
|
|
3867
|
+
...await this.index(),
|
|
3868
|
+
...this.#buildRenderingInstructions()
|
|
3803
3869
|
);
|
|
3804
3870
|
const userMsg = messages.at(-1);
|
|
3805
3871
|
if (userMsg) {
|
|
@@ -3810,7 +3876,7 @@ var Text2Sql = class {
|
|
|
3810
3876
|
const skillMounts = context.getSkillMounts();
|
|
3811
3877
|
const { bash } = await createResultTools({
|
|
3812
3878
|
adapter: this.#config.adapter,
|
|
3813
|
-
chatId:
|
|
3879
|
+
chatId: context.chatId,
|
|
3814
3880
|
messageId,
|
|
3815
3881
|
skillMounts
|
|
3816
3882
|
});
|
|
@@ -3825,7 +3891,10 @@ var Text2Sql = class {
|
|
|
3825
3891
|
guardrails: [errorRecoveryGuardrail],
|
|
3826
3892
|
maxGuardrailRetries: 3
|
|
3827
3893
|
});
|
|
3828
|
-
const result = await chatAgent.stream(
|
|
3894
|
+
const result = await chatAgent.stream(
|
|
3895
|
+
{},
|
|
3896
|
+
{ transform: this.#config.transform }
|
|
3897
|
+
);
|
|
3829
3898
|
return result.toUIMessageStream({
|
|
3830
3899
|
onError: (error) => this.#formatError(error),
|
|
3831
3900
|
sendStart: true,
|
|
@@ -3837,23 +3906,16 @@ var Text2Sql = class {
|
|
|
3837
3906
|
onFinish: async ({ responseMessage }) => {
|
|
3838
3907
|
context.set(assistant(responseMessage));
|
|
3839
3908
|
await context.save();
|
|
3909
|
+
await context.trackUsage(await result.totalUsage);
|
|
3840
3910
|
}
|
|
3841
3911
|
});
|
|
3842
3912
|
}
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
*/
|
|
3847
|
-
async developer(messages, params) {
|
|
3848
|
-
const schemaFragments = await this.index();
|
|
3849
|
-
const context = new ContextEngine({
|
|
3850
|
-
store: this.#config.store,
|
|
3851
|
-
chatId: params.chatId,
|
|
3852
|
-
userId: params.userId
|
|
3853
|
-
}).set(
|
|
3913
|
+
async developer(messages) {
|
|
3914
|
+
const context = this.#config.context(
|
|
3915
|
+
...guidelines(this.#config.teachingsOptions),
|
|
3854
3916
|
...developer_agent_default.fragments,
|
|
3855
|
-
...this
|
|
3856
|
-
...
|
|
3917
|
+
...await this.index(),
|
|
3918
|
+
...this.#buildRenderingInstructions()
|
|
3857
3919
|
);
|
|
3858
3920
|
const userMsg = messages.at(-1);
|
|
3859
3921
|
if (userMsg) {
|
|
@@ -3879,6 +3941,7 @@ var Text2Sql = class {
|
|
|
3879
3941
|
onFinish: async ({ responseMessage }) => {
|
|
3880
3942
|
context.set(assistant(responseMessage));
|
|
3881
3943
|
await context.save();
|
|
3944
|
+
await context.trackUsage(await result.totalUsage);
|
|
3882
3945
|
}
|
|
3883
3946
|
});
|
|
3884
3947
|
}
|