@deepagents/text2sql 0.13.0 → 0.14.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.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1065 -219
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/groundings/index.js +166 -154
- package/dist/lib/adapters/groundings/index.js.map +4 -4
- package/dist/lib/adapters/mysql/index.js +166 -154
- package/dist/lib/adapters/mysql/index.js.map +4 -4
- package/dist/lib/adapters/postgres/index.js +168 -155
- package/dist/lib/adapters/postgres/index.js.map +4 -4
- package/dist/lib/adapters/postgres/info.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/spreadsheet/index.js +22 -2
- package/dist/lib/adapters/spreadsheet/index.js.map +4 -4
- package/dist/lib/adapters/sqlite/index.js +166 -154
- package/dist/lib/adapters/sqlite/index.js.map +4 -4
- package/dist/lib/adapters/sqlserver/index.js +166 -154
- package/dist/lib/adapters/sqlserver/index.js.map +4 -4
- package/dist/lib/agents/result-tools.d.ts +20 -23
- package/dist/lib/agents/result-tools.d.ts.map +1 -1
- package/dist/lib/fs/index.d.ts +4 -0
- package/dist/lib/fs/index.d.ts.map +1 -0
- package/dist/lib/fs/scoped-fs.d.ts +53 -0
- package/dist/lib/fs/scoped-fs.d.ts.map +1 -0
- package/dist/lib/fs/sqlite-fs.d.ts +66 -0
- package/dist/lib/fs/sqlite-fs.d.ts.map +1 -0
- package/dist/lib/fs/tracked-fs.d.ts +40 -0
- package/dist/lib/fs/tracked-fs.d.ts.map +1 -0
- package/dist/lib/sql.d.ts +5 -5
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +181 -181
- package/dist/lib/synthesis/index.js.map +4 -4
- package/package.json +10 -7
|
@@ -221,7 +221,7 @@ var InfoGrounding = class extends AbstractGrounding {
|
|
|
221
221
|
// packages/text2sql/src/lib/adapters/groundings/report.grounding.ts
|
|
222
222
|
import { groq as groq2 } from "@ai-sdk/groq";
|
|
223
223
|
import { tool } from "ai";
|
|
224
|
-
import
|
|
224
|
+
import dedent2 from "dedent";
|
|
225
225
|
import z from "zod";
|
|
226
226
|
import "@deepagents/agent";
|
|
227
227
|
|
|
@@ -239,6 +239,7 @@ import spawn2 from "nano-spawn";
|
|
|
239
239
|
import {
|
|
240
240
|
createBashTool
|
|
241
241
|
} from "bash-tool";
|
|
242
|
+
import dedent from "dedent";
|
|
242
243
|
import YAML from "yaml";
|
|
243
244
|
import { DatabaseSync } from "node:sqlite";
|
|
244
245
|
import { groq } from "@ai-sdk/groq";
|
|
@@ -460,7 +461,7 @@ function assistantText(content, options) {
|
|
|
460
461
|
parts: [{ type: "text", text: content }]
|
|
461
462
|
});
|
|
462
463
|
}
|
|
463
|
-
var LAZY_ID = Symbol("lazy-id");
|
|
464
|
+
var LAZY_ID = Symbol.for("@deepagents/context:lazy-id");
|
|
464
465
|
function isLazyFragment(fragment2) {
|
|
465
466
|
return LAZY_ID in fragment2;
|
|
466
467
|
}
|
|
@@ -847,7 +848,7 @@ var ContextEngine = class {
|
|
|
847
848
|
async #createBranchFrom(messageId, switchTo) {
|
|
848
849
|
const branches = await this.#store.listBranches(this.#chatId);
|
|
849
850
|
const samePrefix = branches.filter(
|
|
850
|
-
(
|
|
851
|
+
(it) => it.name === this.#branchName || it.name.startsWith(`${this.#branchName}-v`)
|
|
851
852
|
);
|
|
852
853
|
const newBranchName = `${this.#branchName}-v${samePrefix.length + 1}`;
|
|
853
854
|
const newBranch = {
|
|
@@ -875,6 +876,15 @@ var ContextEngine = class {
|
|
|
875
876
|
createdAt: newBranch.createdAt
|
|
876
877
|
};
|
|
877
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Rewind to a message without clearing pending messages.
|
|
881
|
+
* Used internally when saving an update to an existing message.
|
|
882
|
+
*/
|
|
883
|
+
async #rewindForUpdate(messageId) {
|
|
884
|
+
const pendingBackup = [...this.#pendingMessages];
|
|
885
|
+
await this.rewind(messageId);
|
|
886
|
+
this.#pendingMessages = pendingBackup;
|
|
887
|
+
}
|
|
878
888
|
/**
|
|
879
889
|
* Get the current chat ID.
|
|
880
890
|
*/
|
|
@@ -959,7 +969,18 @@ var ContextEngine = class {
|
|
|
959
969
|
messages.push(message(msg.data).codec?.decode());
|
|
960
970
|
}
|
|
961
971
|
}
|
|
972
|
+
for (let i = 0; i < this.#pendingMessages.length; i++) {
|
|
973
|
+
const fragment2 = this.#pendingMessages[i];
|
|
974
|
+
if (isLazyFragment(fragment2)) {
|
|
975
|
+
this.#pendingMessages[i] = await this.#resolveLazyFragment(fragment2);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
962
978
|
for (const fragment2 of this.#pendingMessages) {
|
|
979
|
+
if (!fragment2.codec) {
|
|
980
|
+
throw new Error(
|
|
981
|
+
`Fragment "${fragment2.name}" is missing codec. Lazy fragments must be resolved before decode.`
|
|
982
|
+
);
|
|
983
|
+
}
|
|
963
984
|
const decoded = fragment2.codec.decode();
|
|
964
985
|
messages.push(decoded);
|
|
965
986
|
}
|
|
@@ -990,9 +1011,24 @@ var ContextEngine = class {
|
|
|
990
1011
|
this.#pendingMessages[i] = await this.#resolveLazyFragment(fragment2);
|
|
991
1012
|
}
|
|
992
1013
|
}
|
|
1014
|
+
for (const fragment2 of this.#pendingMessages) {
|
|
1015
|
+
if (fragment2.id) {
|
|
1016
|
+
const existing = await this.#store.getMessage(fragment2.id);
|
|
1017
|
+
if (existing && existing.parentId) {
|
|
1018
|
+
await this.#rewindForUpdate(existing.parentId);
|
|
1019
|
+
fragment2.id = crypto.randomUUID();
|
|
1020
|
+
break;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
993
1024
|
let parentId = this.#branch.headMessageId;
|
|
994
1025
|
const now = Date.now();
|
|
995
1026
|
for (const fragment2 of this.#pendingMessages) {
|
|
1027
|
+
if (!fragment2.codec) {
|
|
1028
|
+
throw new Error(
|
|
1029
|
+
`Fragment "${fragment2.name}" is missing codec. Lazy fragments must be resolved before encode.`
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
996
1032
|
const messageData = {
|
|
997
1033
|
id: fragment2.id ?? crypto.randomUUID(),
|
|
998
1034
|
chatId: this.#chatId,
|
|
@@ -1352,33 +1388,28 @@ var ContextEngine = class {
|
|
|
1352
1388
|
return void 0;
|
|
1353
1389
|
}
|
|
1354
1390
|
/**
|
|
1355
|
-
* Extract skill
|
|
1356
|
-
* Returns
|
|
1357
|
-
*
|
|
1358
|
-
* Reads the original `paths` configuration stored in fragment metadata
|
|
1359
|
-
* by the skills() fragment helper.
|
|
1391
|
+
* Extract skill mounts from available_skills fragments.
|
|
1392
|
+
* Returns unified mount array where entries with `name` are individual skills.
|
|
1360
1393
|
*
|
|
1361
1394
|
* @example
|
|
1362
1395
|
* ```ts
|
|
1363
1396
|
* const context = new ContextEngine({ store, chatId, userId })
|
|
1364
1397
|
* .set(skills({ paths: [{ host: './skills', sandbox: '/skills' }] }));
|
|
1365
1398
|
*
|
|
1366
|
-
* const mounts = context.getSkillMounts();
|
|
1367
|
-
* // [{ host: './skills', sandbox: '/skills' }]
|
|
1399
|
+
* const { mounts } = context.getSkillMounts();
|
|
1400
|
+
* // mounts: [{ name: 'bi-dashboards', host: './skills/bi-dashboards/SKILL.md', sandbox: '/skills/bi-dashboards/SKILL.md' }]
|
|
1401
|
+
*
|
|
1402
|
+
* // Extract skills only (entries with name)
|
|
1403
|
+
* const skills = mounts.filter(m => m.name);
|
|
1368
1404
|
* ```
|
|
1369
1405
|
*/
|
|
1370
1406
|
getSkillMounts() {
|
|
1371
|
-
const mounts = [];
|
|
1372
1407
|
for (const fragment2 of this.#fragments) {
|
|
1373
|
-
if (fragment2.name === "available_skills" && fragment2.metadata
|
|
1374
|
-
|
|
1375
|
-
if (typeof mapping === "object" && mapping !== null && typeof mapping.host === "string" && typeof mapping.sandbox === "string") {
|
|
1376
|
-
mounts.push({ host: mapping.host, sandbox: mapping.sandbox });
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1408
|
+
if (fragment2.name === "available_skills" && fragment2.metadata?.mounts) {
|
|
1409
|
+
return { mounts: fragment2.metadata.mounts };
|
|
1379
1410
|
}
|
|
1380
1411
|
}
|
|
1381
|
-
return mounts;
|
|
1412
|
+
return { mounts: [] };
|
|
1382
1413
|
}
|
|
1383
1414
|
/**
|
|
1384
1415
|
* Inspect the full context state for debugging.
|
|
@@ -1447,91 +1478,53 @@ function runGuardrailChain(part, guardrails, context) {
|
|
|
1447
1478
|
let currentPart = part;
|
|
1448
1479
|
for (const guardrail2 of guardrails) {
|
|
1449
1480
|
const result = guardrail2.handle(currentPart, context);
|
|
1450
|
-
if (result.type === "fail") {
|
|
1481
|
+
if (result.type === "fail" || result.type === "stop") {
|
|
1451
1482
|
return result;
|
|
1452
1483
|
}
|
|
1453
1484
|
currentPart = result.part;
|
|
1454
1485
|
}
|
|
1455
1486
|
return pass(currentPart);
|
|
1456
1487
|
}
|
|
1457
|
-
var
|
|
1458
|
-
-- Chats table
|
|
1459
|
-
-- createdAt/updatedAt: DEFAULT for insert, inline SET for updates
|
|
1460
|
-
CREATE TABLE IF NOT EXISTS chats (
|
|
1461
|
-
id TEXT PRIMARY KEY,
|
|
1462
|
-
userId TEXT NOT NULL,
|
|
1463
|
-
title TEXT,
|
|
1464
|
-
metadata TEXT,
|
|
1465
|
-
createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
|
|
1466
|
-
updatedAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)
|
|
1467
|
-
);
|
|
1468
|
-
|
|
1469
|
-
CREATE INDEX IF NOT EXISTS idx_chats_updatedAt ON chats(updatedAt);
|
|
1470
|
-
CREATE INDEX IF NOT EXISTS idx_chats_userId ON chats(userId);
|
|
1471
|
-
|
|
1472
|
-
-- Messages table (nodes in the DAG)
|
|
1473
|
-
CREATE TABLE IF NOT EXISTS messages (
|
|
1474
|
-
id TEXT PRIMARY KEY,
|
|
1475
|
-
chatId TEXT NOT NULL,
|
|
1476
|
-
parentId TEXT,
|
|
1477
|
-
name TEXT NOT NULL,
|
|
1478
|
-
type TEXT,
|
|
1479
|
-
data TEXT NOT NULL,
|
|
1480
|
-
createdAt INTEGER NOT NULL,
|
|
1481
|
-
FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,
|
|
1482
|
-
FOREIGN KEY (parentId) REFERENCES messages(id)
|
|
1483
|
-
);
|
|
1484
|
-
|
|
1485
|
-
CREATE INDEX IF NOT EXISTS idx_messages_chatId ON messages(chatId);
|
|
1486
|
-
CREATE INDEX IF NOT EXISTS idx_messages_parentId ON messages(parentId);
|
|
1487
|
-
|
|
1488
|
-
-- Branches table (pointers to head messages)
|
|
1489
|
-
CREATE TABLE IF NOT EXISTS branches (
|
|
1490
|
-
id TEXT PRIMARY KEY,
|
|
1491
|
-
chatId TEXT NOT NULL,
|
|
1492
|
-
name TEXT NOT NULL,
|
|
1493
|
-
headMessageId TEXT,
|
|
1494
|
-
isActive INTEGER NOT NULL DEFAULT 0,
|
|
1495
|
-
createdAt INTEGER NOT NULL,
|
|
1496
|
-
FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,
|
|
1497
|
-
FOREIGN KEY (headMessageId) REFERENCES messages(id),
|
|
1498
|
-
UNIQUE(chatId, name)
|
|
1499
|
-
);
|
|
1500
|
-
|
|
1501
|
-
CREATE INDEX IF NOT EXISTS idx_branches_chatId ON branches(chatId);
|
|
1488
|
+
var SKILLS_INSTRUCTIONS = dedent`A skill is a set of local instructions to follow that is stored in a \`SKILL.md\` file. Below is the list of skills that can be used. Each entry includes a name, description, and file path so you can open the source for full instructions when using a specific skill.
|
|
1502
1489
|
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
messageId UNINDEXED,
|
|
1522
|
-
chatId UNINDEXED,
|
|
1523
|
-
name UNINDEXED,
|
|
1524
|
-
content,
|
|
1525
|
-
tokenize='porter unicode61'
|
|
1526
|
-
);
|
|
1527
|
-
`;
|
|
1490
|
+
### How to use skills
|
|
1491
|
+
- Discovery: The list below shows the skills available in this session (name + description + file path). Skill bodies live on disk at the listed paths.
|
|
1492
|
+
- Trigger rules: If the user names a skill (with \`$SkillName\` or plain text) OR the task clearly matches a skill's description shown below, you must use that skill for that turn before doing anything else. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned.
|
|
1493
|
+
- Missing/blocked: If a named skill isn't in the list or the path can't be read, say so briefly and continue with the best fallback.
|
|
1494
|
+
- How to use a skill (progressive disclosure):
|
|
1495
|
+
1) After deciding to use a skill, open its \`SKILL.md\`. Read only enough to follow the workflow.
|
|
1496
|
+
2) If \`SKILL.md\` points to extra folders such as \`references/\`, load only the specific files needed for the request; don't bulk-load everything.
|
|
1497
|
+
3) If \`scripts/\` exist, prefer running or patching them instead of retyping large code blocks.
|
|
1498
|
+
4) If \`assets/\` or templates exist, reuse them instead of recreating from scratch.
|
|
1499
|
+
- Coordination and sequencing:
|
|
1500
|
+
- If multiple skills apply, choose the minimal set that covers the request and state the order you'll use them.
|
|
1501
|
+
- Announce which skill(s) you're using and why (one short line). If you skip an obvious skill, say why.
|
|
1502
|
+
- Context hygiene:
|
|
1503
|
+
- Keep context small: summarize long sections instead of pasting them; only load extra files when needed.
|
|
1504
|
+
- Avoid deep reference-chasing: prefer opening only files directly linked from \`SKILL.md\` unless you're blocked.
|
|
1505
|
+
- When variants exist (frameworks, providers, domains), pick only the relevant reference file(s) and note that choice.
|
|
1506
|
+
- Safety and fallback: If a skill can't be applied cleanly (missing files, unclear instructions), state the issue, pick the next-best approach, and continue.`;
|
|
1507
|
+
var ddl_sqlite_default = "-- Context Store DDL for SQLite\n-- This schema implements a DAG-based message history with branching and checkpoints.\n\n-- Performance PRAGMAs (session-level, run on each connection)\nPRAGMA journal_mode = WAL;\nPRAGMA synchronous = NORMAL;\nPRAGMA cache_size = -64000;\nPRAGMA temp_store = MEMORY;\nPRAGMA mmap_size = 268435456;\n\n-- Integrity\nPRAGMA foreign_keys = ON;\n\n-- Chats table\n-- createdAt/updatedAt: DEFAULT for insert, inline SET for updates\nCREATE TABLE IF NOT EXISTS chats (\n id TEXT PRIMARY KEY,\n userId TEXT NOT NULL,\n title TEXT,\n metadata TEXT,\n createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updatedAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\nCREATE INDEX IF NOT EXISTS idx_chats_updatedAt ON chats(updatedAt);\nCREATE INDEX IF NOT EXISTS idx_chats_userId ON chats(userId);\n-- Composite index for listChats(): WHERE userId = ? ORDER BY updatedAt DESC\nCREATE INDEX IF NOT EXISTS idx_chats_userId_updatedAt ON chats(userId, updatedAt DESC);\n\n-- Messages table (nodes in the DAG)\nCREATE TABLE IF NOT EXISTS messages (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n parentId TEXT,\n name TEXT NOT NULL,\n type TEXT,\n data TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (parentId) REFERENCES messages(id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_messages_chatId ON messages(chatId);\nCREATE INDEX IF NOT EXISTS idx_messages_parentId ON messages(parentId);\n-- Composite index for recursive CTE parent traversal in getMessageChain()\nCREATE INDEX IF NOT EXISTS idx_messages_chatId_parentId ON messages(chatId, parentId);\n\n-- Branches table (pointers to head messages)\nCREATE TABLE IF NOT EXISTS branches (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n headMessageId TEXT,\n isActive INTEGER NOT NULL DEFAULT 0,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (headMessageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_branches_chatId ON branches(chatId);\n-- Composite index for getActiveBranch(): WHERE chatId = ? AND isActive = 1\nCREATE INDEX IF NOT EXISTS idx_branches_chatId_isActive ON branches(chatId, isActive);\n\n-- Checkpoints table (pointers to message nodes)\nCREATE TABLE IF NOT EXISTS checkpoints (\n id TEXT PRIMARY KEY,\n chatId TEXT NOT NULL,\n name TEXT NOT NULL,\n messageId TEXT NOT NULL,\n createdAt INTEGER NOT NULL,\n FOREIGN KEY (chatId) REFERENCES chats(id) ON DELETE CASCADE,\n FOREIGN KEY (messageId) REFERENCES messages(id),\n UNIQUE(chatId, name)\n);\n\nCREATE INDEX IF NOT EXISTS idx_checkpoints_chatId ON checkpoints(chatId);\n\n-- FTS5 virtual table for full-text search\n-- messageId/chatId/name are UNINDEXED (stored but not searchable, used for filtering/joining)\n-- Only 'content' is indexed for full-text search\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n messageId UNINDEXED,\n chatId UNINDEXED,\n name UNINDEXED,\n content,\n tokenize='porter unicode61'\n);\n";
|
|
1528
1508
|
var SqliteContextStore = class extends ContextStore {
|
|
1529
1509
|
#db;
|
|
1510
|
+
#statements = /* @__PURE__ */ new Map();
|
|
1511
|
+
/**
|
|
1512
|
+
* Get or create a prepared statement.
|
|
1513
|
+
* Statements are cached for the lifetime of the store to avoid
|
|
1514
|
+
* repeated SQL parsing and compilation overhead.
|
|
1515
|
+
*/
|
|
1516
|
+
#stmt(sql) {
|
|
1517
|
+
let stmt = this.#statements.get(sql);
|
|
1518
|
+
if (!stmt) {
|
|
1519
|
+
stmt = this.#db.prepare(sql);
|
|
1520
|
+
this.#statements.set(sql, stmt);
|
|
1521
|
+
}
|
|
1522
|
+
return stmt;
|
|
1523
|
+
}
|
|
1530
1524
|
constructor(path3) {
|
|
1531
1525
|
super();
|
|
1532
1526
|
this.#db = new DatabaseSync(path3);
|
|
1533
|
-
this.#db.exec(
|
|
1534
|
-
this.#db.exec(STORE_DDL);
|
|
1527
|
+
this.#db.exec(ddl_sqlite_default);
|
|
1535
1528
|
}
|
|
1536
1529
|
/**
|
|
1537
1530
|
* Execute a function within a transaction.
|
|
@@ -1552,11 +1545,12 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1552
1545
|
// Chat Operations
|
|
1553
1546
|
// ==========================================================================
|
|
1554
1547
|
async createChat(chat) {
|
|
1555
|
-
this.#useTransaction(() => {
|
|
1556
|
-
this.#db.prepare(
|
|
1548
|
+
return this.#useTransaction(() => {
|
|
1549
|
+
const row = this.#db.prepare(
|
|
1557
1550
|
`INSERT INTO chats (id, userId, title, metadata)
|
|
1558
|
-
VALUES (?, ?, ?, ?)
|
|
1559
|
-
|
|
1551
|
+
VALUES (?, ?, ?, ?)
|
|
1552
|
+
RETURNING *`
|
|
1553
|
+
).get(
|
|
1560
1554
|
chat.id,
|
|
1561
1555
|
chat.userId,
|
|
1562
1556
|
chat.title ?? null,
|
|
@@ -1566,6 +1560,14 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1566
1560
|
`INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
|
|
1567
1561
|
VALUES (?, ?, 'main', NULL, 1, ?)`
|
|
1568
1562
|
).run(crypto.randomUUID(), chat.id, Date.now());
|
|
1563
|
+
return {
|
|
1564
|
+
id: row.id,
|
|
1565
|
+
userId: row.userId,
|
|
1566
|
+
title: row.title ?? void 0,
|
|
1567
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
1568
|
+
createdAt: row.createdAt,
|
|
1569
|
+
updatedAt: row.updatedAt
|
|
1570
|
+
};
|
|
1569
1571
|
});
|
|
1570
1572
|
}
|
|
1571
1573
|
async upsertChat(chat) {
|
|
@@ -1708,21 +1710,16 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1708
1710
|
// Message Operations (Graph Nodes)
|
|
1709
1711
|
// ==========================================================================
|
|
1710
1712
|
async addMessage(message2) {
|
|
1711
|
-
|
|
1713
|
+
if (message2.parentId === message2.id) {
|
|
1714
|
+
throw new Error(`Message ${message2.id} cannot be its own parent`);
|
|
1715
|
+
}
|
|
1716
|
+
this.#stmt(
|
|
1712
1717
|
`INSERT INTO messages (id, chatId, parentId, name, type, data, createdAt)
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
?5,
|
|
1719
|
-
?6,
|
|
1720
|
-
?7
|
|
1721
|
-
)
|
|
1722
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
1723
|
-
name = excluded.name,
|
|
1724
|
-
type = excluded.type,
|
|
1725
|
-
data = excluded.data`
|
|
1718
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1719
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
1720
|
+
name = excluded.name,
|
|
1721
|
+
type = excluded.type,
|
|
1722
|
+
data = excluded.data`
|
|
1726
1723
|
).run(
|
|
1727
1724
|
message2.id,
|
|
1728
1725
|
message2.chatId,
|
|
@@ -1733,14 +1730,16 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1733
1730
|
message2.createdAt
|
|
1734
1731
|
);
|
|
1735
1732
|
const content = typeof message2.data === "string" ? message2.data : JSON.stringify(message2.data);
|
|
1736
|
-
this.#
|
|
1737
|
-
this.#
|
|
1733
|
+
this.#stmt(`DELETE FROM messages_fts WHERE messageId = ?`).run(message2.id);
|
|
1734
|
+
this.#stmt(
|
|
1738
1735
|
`INSERT INTO messages_fts(messageId, chatId, name, content)
|
|
1739
|
-
|
|
1736
|
+
VALUES (?, ?, ?, ?)`
|
|
1740
1737
|
).run(message2.id, message2.chatId, message2.name, content);
|
|
1741
1738
|
}
|
|
1742
1739
|
async getMessage(messageId) {
|
|
1743
|
-
const row = this.#
|
|
1740
|
+
const row = this.#stmt("SELECT * FROM messages WHERE id = ?").get(
|
|
1741
|
+
messageId
|
|
1742
|
+
);
|
|
1744
1743
|
if (!row) {
|
|
1745
1744
|
return void 0;
|
|
1746
1745
|
}
|
|
@@ -1755,15 +1754,16 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1755
1754
|
};
|
|
1756
1755
|
}
|
|
1757
1756
|
async getMessageChain(headId) {
|
|
1758
|
-
const rows = this.#
|
|
1757
|
+
const rows = this.#stmt(
|
|
1759
1758
|
`WITH RECURSIVE chain AS (
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1759
|
+
SELECT *, 0 as depth FROM messages WHERE id = ?
|
|
1760
|
+
UNION ALL
|
|
1761
|
+
SELECT m.*, c.depth + 1 FROM messages m
|
|
1762
|
+
INNER JOIN chain c ON m.id = c.parentId
|
|
1763
|
+
WHERE c.depth < 100000
|
|
1764
|
+
)
|
|
1765
|
+
SELECT * FROM chain
|
|
1766
|
+
ORDER BY depth DESC`
|
|
1767
1767
|
).all(headId);
|
|
1768
1768
|
return rows.map((row) => ({
|
|
1769
1769
|
id: row.id,
|
|
@@ -1776,7 +1776,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1776
1776
|
}));
|
|
1777
1777
|
}
|
|
1778
1778
|
async hasChildren(messageId) {
|
|
1779
|
-
const row = this.#
|
|
1779
|
+
const row = this.#stmt(
|
|
1780
1780
|
"SELECT EXISTS(SELECT 1 FROM messages WHERE parentId = ?) as hasChildren"
|
|
1781
1781
|
).get(messageId);
|
|
1782
1782
|
return row.hasChildren === 1;
|
|
@@ -1823,7 +1823,9 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1823
1823
|
};
|
|
1824
1824
|
}
|
|
1825
1825
|
async getActiveBranch(chatId) {
|
|
1826
|
-
const row = this.#
|
|
1826
|
+
const row = this.#stmt(
|
|
1827
|
+
"SELECT * FROM branches WHERE chatId = ? AND isActive = 1"
|
|
1828
|
+
).get(chatId);
|
|
1827
1829
|
if (!row) {
|
|
1828
1830
|
return void 0;
|
|
1829
1831
|
}
|
|
@@ -1841,45 +1843,43 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
1841
1843
|
this.#db.prepare("UPDATE branches SET isActive = 1 WHERE id = ?").run(branchId);
|
|
1842
1844
|
}
|
|
1843
1845
|
async updateBranchHead(branchId, messageId) {
|
|
1844
|
-
this.#
|
|
1846
|
+
this.#stmt("UPDATE branches SET headMessageId = ? WHERE id = ?").run(
|
|
1847
|
+
messageId,
|
|
1848
|
+
branchId
|
|
1849
|
+
);
|
|
1845
1850
|
}
|
|
1846
1851
|
async listBranches(chatId) {
|
|
1847
|
-
const
|
|
1852
|
+
const rows = this.#db.prepare(
|
|
1848
1853
|
`SELECT
|
|
1849
1854
|
b.id,
|
|
1850
1855
|
b.name,
|
|
1851
1856
|
b.headMessageId,
|
|
1852
1857
|
b.isActive,
|
|
1853
|
-
b.createdAt
|
|
1858
|
+
b.createdAt,
|
|
1859
|
+
COALESCE(
|
|
1860
|
+
(
|
|
1861
|
+
WITH RECURSIVE chain AS (
|
|
1862
|
+
SELECT id, parentId FROM messages WHERE id = b.headMessageId
|
|
1863
|
+
UNION ALL
|
|
1864
|
+
SELECT m.id, m.parentId FROM messages m
|
|
1865
|
+
INNER JOIN chain c ON m.id = c.parentId
|
|
1866
|
+
)
|
|
1867
|
+
SELECT COUNT(*) FROM chain
|
|
1868
|
+
),
|
|
1869
|
+
0
|
|
1870
|
+
) as messageCount
|
|
1854
1871
|
FROM branches b
|
|
1855
1872
|
WHERE b.chatId = ?
|
|
1856
1873
|
ORDER BY b.createdAt ASC`
|
|
1857
1874
|
).all(chatId);
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
SELECT m.id, m.parentId FROM messages m
|
|
1867
|
-
INNER JOIN chain c ON m.id = c.parentId
|
|
1868
|
-
)
|
|
1869
|
-
SELECT COUNT(*) as count FROM chain`
|
|
1870
|
-
).get(branch.headMessageId);
|
|
1871
|
-
messageCount = countRow.count;
|
|
1872
|
-
}
|
|
1873
|
-
result.push({
|
|
1874
|
-
id: branch.id,
|
|
1875
|
-
name: branch.name,
|
|
1876
|
-
headMessageId: branch.headMessageId,
|
|
1877
|
-
isActive: branch.isActive === 1,
|
|
1878
|
-
messageCount,
|
|
1879
|
-
createdAt: branch.createdAt
|
|
1880
|
-
});
|
|
1881
|
-
}
|
|
1882
|
-
return result;
|
|
1875
|
+
return rows.map((row) => ({
|
|
1876
|
+
id: row.id,
|
|
1877
|
+
name: row.name,
|
|
1878
|
+
headMessageId: row.headMessageId,
|
|
1879
|
+
isActive: row.isActive === 1,
|
|
1880
|
+
messageCount: row.messageCount,
|
|
1881
|
+
createdAt: row.createdAt
|
|
1882
|
+
}));
|
|
1883
1883
|
}
|
|
1884
1884
|
// ==========================================================================
|
|
1885
1885
|
// Checkpoint Operations
|
|
@@ -2147,8 +2147,10 @@ var Agent = class _Agent {
|
|
|
2147
2147
|
execute: async ({ writer }) => {
|
|
2148
2148
|
let currentResult = result;
|
|
2149
2149
|
let attempt = 0;
|
|
2150
|
+
const { mounts } = context.getSkillMounts();
|
|
2150
2151
|
const guardrailContext = {
|
|
2151
|
-
availableTools: Object.keys(this.tools)
|
|
2152
|
+
availableTools: Object.keys(this.tools),
|
|
2153
|
+
availableSkills: mounts
|
|
2152
2154
|
};
|
|
2153
2155
|
while (attempt < maxRetries) {
|
|
2154
2156
|
if (config?.abortSignal?.aborted) {
|
|
@@ -2176,10 +2178,20 @@ var Agent = class _Agent {
|
|
|
2176
2178
|
);
|
|
2177
2179
|
break;
|
|
2178
2180
|
}
|
|
2181
|
+
if (checkResult.type === "stop") {
|
|
2182
|
+
console.log(
|
|
2183
|
+
chalk2.red(
|
|
2184
|
+
`[${this.#options.name}] Guardrail stopped - unrecoverable error, no retry`
|
|
2185
|
+
)
|
|
2186
|
+
);
|
|
2187
|
+
writer.write(part);
|
|
2188
|
+
writer.write({ type: "finish" });
|
|
2189
|
+
return;
|
|
2190
|
+
}
|
|
2179
2191
|
if (checkResult.part.type === "text-delta") {
|
|
2180
2192
|
accumulatedText += checkResult.part.delta;
|
|
2181
2193
|
}
|
|
2182
|
-
writer.write(
|
|
2194
|
+
writer.write(part);
|
|
2183
2195
|
}
|
|
2184
2196
|
if (!guardrailFailed) {
|
|
2185
2197
|
writer.write({ type: "finish" });
|
|
@@ -2307,7 +2319,7 @@ var ReportGrounding = class extends AbstractGrounding {
|
|
|
2307
2319
|
}),
|
|
2308
2320
|
fragment(
|
|
2309
2321
|
"instructions",
|
|
2310
|
-
|
|
2322
|
+
dedent2`
|
|
2311
2323
|
Write a business context that helps another agent answer questions accurately.
|
|
2312
2324
|
|
|
2313
2325
|
For EACH table, do queries ONE AT A TIME:
|