@dudousxd/nestjs-agent-store-drizzle 0.5.1 → 0.7.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.cjs +178 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +179 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -72,7 +72,9 @@ var agentToolCall = sqliteTable("agent_tool_call", {
|
|
|
72
72
|
}).notNull(),
|
|
73
73
|
executedAt: integer("executed_at", {
|
|
74
74
|
mode: "timestamp_ms"
|
|
75
|
-
})
|
|
75
|
+
}),
|
|
76
|
+
/** The run (turn) this call belongs to, for a trace deep-link; null for a pre-rollout row. */
|
|
77
|
+
runId: text("run_id")
|
|
76
78
|
});
|
|
77
79
|
var agentTokenUsage = sqliteTable("agent_token_usage", {
|
|
78
80
|
id: text("id").primaryKey(),
|
|
@@ -187,7 +189,8 @@ var statements = [
|
|
|
187
189
|
execution_ms INTEGER,
|
|
188
190
|
error TEXT,
|
|
189
191
|
created_at INTEGER NOT NULL,
|
|
190
|
-
executed_at INTEGER
|
|
192
|
+
executed_at INTEGER,
|
|
193
|
+
run_id TEXT
|
|
191
194
|
)`,
|
|
192
195
|
`CREATE TABLE IF NOT EXISTS agent_token_usage (
|
|
193
196
|
id TEXT PRIMARY KEY NOT NULL,
|
|
@@ -460,7 +463,8 @@ var DrizzleAgentStore = class {
|
|
|
460
463
|
executionMs: null,
|
|
461
464
|
error: null,
|
|
462
465
|
createdAt: /* @__PURE__ */ new Date(),
|
|
463
|
-
executedAt: null
|
|
466
|
+
executedAt: null,
|
|
467
|
+
runId: input.runId ?? null
|
|
464
468
|
});
|
|
465
469
|
}
|
|
466
470
|
async updateToolCall(input) {
|
|
@@ -550,9 +554,61 @@ var DrizzleAgentStore = class {
|
|
|
550
554
|
|
|
551
555
|
// src/drizzle-governance-queries.ts
|
|
552
556
|
import { bucketByActor, bucketByModel, bucketByThread, bucketUsageTrend, dayBoundsUtc } from "@dudousxd/nestjs-agent-core";
|
|
553
|
-
import { and as and2, count, desc as desc2, eq as eq2, gte as gte2, inArray as inArray2, isNull as isNull2, lte as lte2 } from "drizzle-orm";
|
|
557
|
+
import { and as and2, count, desc as desc2, eq as eq2, gte as gte2, inArray as inArray2, isNull as isNull2, like, lte as lte2, sql as sql3 } from "drizzle-orm";
|
|
554
558
|
var UNCLASSIFIED_ERROR_CODE = "unknown";
|
|
555
559
|
var DEFAULT_AGENT_BUCKET = "(default)";
|
|
560
|
+
var TOOL_CALL_STATUSES = [
|
|
561
|
+
"auto_executed",
|
|
562
|
+
"pending_approval",
|
|
563
|
+
"executed",
|
|
564
|
+
"rejected",
|
|
565
|
+
"failed"
|
|
566
|
+
];
|
|
567
|
+
function isToolCallStatus(value) {
|
|
568
|
+
return TOOL_CALL_STATUSES.includes(value);
|
|
569
|
+
}
|
|
570
|
+
__name(isToolCallStatus, "isToolCallStatus");
|
|
571
|
+
var TOOL_KINDS = [
|
|
572
|
+
"read",
|
|
573
|
+
"action",
|
|
574
|
+
"agent"
|
|
575
|
+
];
|
|
576
|
+
function isToolKind(value) {
|
|
577
|
+
return TOOL_KINDS.includes(value);
|
|
578
|
+
}
|
|
579
|
+
__name(isToolKind, "isToolKind");
|
|
580
|
+
var RUN_STATUSES = [
|
|
581
|
+
"running",
|
|
582
|
+
"completed",
|
|
583
|
+
"failed"
|
|
584
|
+
];
|
|
585
|
+
function isRunStatus(value) {
|
|
586
|
+
return RUN_STATUSES.includes(value);
|
|
587
|
+
}
|
|
588
|
+
__name(isRunStatus, "isRunStatus");
|
|
589
|
+
function dayStartUtc(day) {
|
|
590
|
+
return dayBoundsUtc({
|
|
591
|
+
fromDay: day,
|
|
592
|
+
toDay: day
|
|
593
|
+
}).start;
|
|
594
|
+
}
|
|
595
|
+
__name(dayStartUtc, "dayStartUtc");
|
|
596
|
+
function dayEndUtc(day) {
|
|
597
|
+
return dayBoundsUtc({
|
|
598
|
+
fromDay: day,
|
|
599
|
+
toDay: day
|
|
600
|
+
}).end;
|
|
601
|
+
}
|
|
602
|
+
__name(dayEndUtc, "dayEndUtc");
|
|
603
|
+
function emptyPage(query) {
|
|
604
|
+
return {
|
|
605
|
+
rows: [],
|
|
606
|
+
total: 0,
|
|
607
|
+
page: query.page,
|
|
608
|
+
pageSize: query.pageSize
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
__name(emptyPage, "emptyPage");
|
|
556
612
|
function toUsageInput(row) {
|
|
557
613
|
return {
|
|
558
614
|
modelId: row.modelId,
|
|
@@ -649,7 +705,8 @@ var DrizzleGovernanceQueries = class {
|
|
|
649
705
|
toolType: agentToolCall.toolType,
|
|
650
706
|
status: agentToolCall.status,
|
|
651
707
|
threadId: agentMessage.threadId,
|
|
652
|
-
createdAt: agentToolCall.createdAt
|
|
708
|
+
createdAt: agentToolCall.createdAt,
|
|
709
|
+
runId: agentToolCall.runId
|
|
653
710
|
}).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).orderBy(desc2(agentToolCall.createdAt), desc2(agentToolCall.id)).limit(limit);
|
|
654
711
|
return rows.map((row) => ({
|
|
655
712
|
toolCallId: row.toolCallId,
|
|
@@ -657,7 +714,8 @@ var DrizzleGovernanceQueries = class {
|
|
|
657
714
|
toolType: row.toolType,
|
|
658
715
|
status: row.status,
|
|
659
716
|
threadId: row.threadId,
|
|
660
|
-
createdAt: row.createdAt.toISOString()
|
|
717
|
+
createdAt: row.createdAt.toISOString(),
|
|
718
|
+
runId: row.runId
|
|
661
719
|
}));
|
|
662
720
|
}
|
|
663
721
|
async recentThreads(limit) {
|
|
@@ -808,7 +866,8 @@ var DrizzleGovernanceQueries = class {
|
|
|
808
866
|
threadTitle: agentThread.title,
|
|
809
867
|
actorRef: agentThread.actorRef,
|
|
810
868
|
agentName: agentMessage.agentName,
|
|
811
|
-
requestedAt: agentToolCall.createdAt
|
|
869
|
+
requestedAt: agentToolCall.createdAt,
|
|
870
|
+
runId: agentToolCall.runId
|
|
812
871
|
}).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).innerJoin(agentThread, eq2(agentMessage.threadId, agentThread.id)).where(eq2(agentToolCall.status, "pending_approval")).orderBy(agentToolCall.createdAt, agentToolCall.id).limit(limit);
|
|
813
872
|
return rows.map((row) => ({
|
|
814
873
|
toolCallId: row.toolCallId,
|
|
@@ -818,7 +877,8 @@ var DrizzleGovernanceQueries = class {
|
|
|
818
877
|
threadTitle: row.threadTitle,
|
|
819
878
|
actorRef: row.actorRef,
|
|
820
879
|
agentName: row.agentName ?? null,
|
|
821
|
-
requestedAt: row.requestedAt.toISOString()
|
|
880
|
+
requestedAt: row.requestedAt.toISOString(),
|
|
881
|
+
runId: row.runId
|
|
822
882
|
}));
|
|
823
883
|
}
|
|
824
884
|
/**
|
|
@@ -863,6 +923,117 @@ var DrizzleGovernanceQueries = class {
|
|
|
863
923
|
result.sort((left, right) => right.calls - left.calls || left.toolName.localeCompare(right.toolName));
|
|
864
924
|
return result;
|
|
865
925
|
}
|
|
926
|
+
/**
|
|
927
|
+
* Paged, filterable tool-call activity, newest-first (same ordering as {@link recentToolCalls}).
|
|
928
|
+
* `toolType`/`status` values outside the known literals can never match a row — short-circuits to
|
|
929
|
+
* an empty page rather than issuing a query. Joins `agent_message` unconditionally (like
|
|
930
|
+
* `recentToolCalls`) to resolve `threadId` and to support the `threadId` filter.
|
|
931
|
+
*/
|
|
932
|
+
async toolCallsPage(query) {
|
|
933
|
+
const filters = query.where;
|
|
934
|
+
if (filters?.status !== void 0 && !isToolCallStatus(filters.status)) {
|
|
935
|
+
return emptyPage(query);
|
|
936
|
+
}
|
|
937
|
+
if (filters?.toolType !== void 0 && !isToolKind(filters.toolType)) {
|
|
938
|
+
return emptyPage(query);
|
|
939
|
+
}
|
|
940
|
+
const whereClause = and2(filters?.toolName !== void 0 ? eq2(agentToolCall.toolName, filters.toolName) : void 0, filters?.toolType !== void 0 && isToolKind(filters.toolType) ? eq2(agentToolCall.toolType, filters.toolType) : void 0, filters?.status !== void 0 && isToolCallStatus(filters.status) ? eq2(agentToolCall.status, filters.status) : void 0, filters?.threadId !== void 0 ? eq2(agentMessage.threadId, filters.threadId) : void 0, filters?.fromDay !== void 0 ? gte2(agentToolCall.createdAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte2(agentToolCall.createdAt, dayEndUtc(filters.toDay)) : void 0);
|
|
941
|
+
const [totalRow] = await this.db.select({
|
|
942
|
+
value: count()
|
|
943
|
+
}).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).where(whereClause);
|
|
944
|
+
const rows = await this.db.select({
|
|
945
|
+
toolCallId: agentToolCall.id,
|
|
946
|
+
toolName: agentToolCall.toolName,
|
|
947
|
+
toolType: agentToolCall.toolType,
|
|
948
|
+
status: agentToolCall.status,
|
|
949
|
+
threadId: agentMessage.threadId,
|
|
950
|
+
createdAt: agentToolCall.createdAt,
|
|
951
|
+
runId: agentToolCall.runId
|
|
952
|
+
}).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).where(whereClause).orderBy(desc2(agentToolCall.createdAt), desc2(agentToolCall.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
|
|
953
|
+
return {
|
|
954
|
+
rows: rows.map((row) => ({
|
|
955
|
+
toolCallId: row.toolCallId,
|
|
956
|
+
toolName: row.toolName,
|
|
957
|
+
toolType: row.toolType,
|
|
958
|
+
status: row.status,
|
|
959
|
+
threadId: row.threadId,
|
|
960
|
+
createdAt: row.createdAt.toISOString(),
|
|
961
|
+
runId: row.runId
|
|
962
|
+
})),
|
|
963
|
+
total: totalRow?.value ?? 0,
|
|
964
|
+
page: query.page,
|
|
965
|
+
pageSize: query.pageSize
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Paged, filterable thread activity, newest-first (same ordering as {@link recentThreads}).
|
|
970
|
+
* `title` is a case-insensitive substring match via `lower(...)` on both sides (portable across
|
|
971
|
+
* dialects, regardless of the underlying column collation). Soft-deleted threads are excluded,
|
|
972
|
+
* mirroring `recentThreads`.
|
|
973
|
+
*/
|
|
974
|
+
async threadsPage(query) {
|
|
975
|
+
const filters = query.where;
|
|
976
|
+
const whereClause = and2(isNull2(agentThread.deletedAt), filters?.actorRef !== void 0 ? eq2(agentThread.actorRef, filters.actorRef) : void 0, filters?.title !== void 0 ? like(sql3`lower(${agentThread.title})`, `%${filters.title.toLowerCase()}%`) : void 0, filters?.fromDay !== void 0 ? gte2(agentThread.updatedAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte2(agentThread.updatedAt, dayEndUtc(filters.toDay)) : void 0);
|
|
977
|
+
const [totalRow] = await this.db.select({
|
|
978
|
+
value: count()
|
|
979
|
+
}).from(agentThread).where(whereClause);
|
|
980
|
+
const threads = await this.db.select().from(agentThread).where(whereClause).orderBy(desc2(agentThread.updatedAt), desc2(agentThread.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
|
|
981
|
+
const rows = [];
|
|
982
|
+
for (const thread of threads) {
|
|
983
|
+
const [messageCountRow] = await this.db.select({
|
|
984
|
+
value: count()
|
|
985
|
+
}).from(agentMessage).where(eq2(agentMessage.threadId, thread.id));
|
|
986
|
+
const usageRows = await this.db.select().from(agentTokenUsage).where(eq2(agentTokenUsage.threadId, thread.id));
|
|
987
|
+
const totalTokens = usageRows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);
|
|
988
|
+
rows.push({
|
|
989
|
+
threadId: thread.id,
|
|
990
|
+
title: thread.title,
|
|
991
|
+
actorRef: thread.actorRef,
|
|
992
|
+
messageCount: messageCountRow?.value ?? 0,
|
|
993
|
+
totalTokens,
|
|
994
|
+
lastActivityAt: thread.updatedAt.toISOString()
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
return {
|
|
998
|
+
rows,
|
|
999
|
+
total: totalRow?.value ?? 0,
|
|
1000
|
+
page: query.page,
|
|
1001
|
+
pageSize: query.pageSize
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Paged, filterable run activity, newest-first (same ordering as {@link recentRuns}). `status`
|
|
1006
|
+
* values outside the known literals can never match a row — short-circuits to an empty page.
|
|
1007
|
+
*/
|
|
1008
|
+
async runsPage(query) {
|
|
1009
|
+
const filters = query.where;
|
|
1010
|
+
if (filters?.status !== void 0 && !isRunStatus(filters.status)) {
|
|
1011
|
+
return emptyPage(query);
|
|
1012
|
+
}
|
|
1013
|
+
const whereClause = and2(filters?.agentName !== void 0 ? eq2(agentRun.agentName, filters.agentName) : void 0, filters?.status !== void 0 && isRunStatus(filters.status) ? eq2(agentRun.status, filters.status) : void 0, filters?.errorCode !== void 0 ? eq2(agentRun.errorCode, filters.errorCode) : void 0, filters?.threadId !== void 0 ? eq2(agentRun.threadId, filters.threadId) : void 0, filters?.fromDay !== void 0 ? gte2(agentRun.startedAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte2(agentRun.startedAt, dayEndUtc(filters.toDay)) : void 0);
|
|
1014
|
+
const [totalRow] = await this.db.select({
|
|
1015
|
+
value: count()
|
|
1016
|
+
}).from(agentRun).where(whereClause);
|
|
1017
|
+
const runs = await this.db.select().from(agentRun).where(whereClause).orderBy(desc2(agentRun.startedAt), desc2(agentRun.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
|
|
1018
|
+
return {
|
|
1019
|
+
rows: runs.map((run) => ({
|
|
1020
|
+
runId: run.id,
|
|
1021
|
+
threadId: run.threadId,
|
|
1022
|
+
actorRef: run.actorRef,
|
|
1023
|
+
agentName: run.agentName ?? null,
|
|
1024
|
+
status: run.status,
|
|
1025
|
+
durationMs: run.durationMs ?? null,
|
|
1026
|
+
errorCode: run.errorCode ?? null,
|
|
1027
|
+
errorMessage: run.errorMessage ?? null,
|
|
1028
|
+
retries: run.retries,
|
|
1029
|
+
startedAt: run.startedAt.toISOString(),
|
|
1030
|
+
promptHash: run.promptHash ?? null
|
|
1031
|
+
})),
|
|
1032
|
+
total: totalRow?.value ?? 0,
|
|
1033
|
+
page: query.page,
|
|
1034
|
+
pageSize: query.pageSize
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
866
1037
|
};
|
|
867
1038
|
|
|
868
1039
|
// src/drizzle-pricing-store.ts
|