@dudousxd/nestjs-agent-store-drizzle 0.32.0 → 0.33.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 CHANGED
@@ -94,7 +94,9 @@ var agentThread = (0, import_sqlite_core.sqliteTable)("agent_thread", {
94
94
  mode: "timestamp_ms"
95
95
  })
96
96
  }, (table) => [
97
- (0, import_sqlite_core.index)("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt)
97
+ (0, import_sqlite_core.index)("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt),
98
+ // `ownerOfActiveStream` reads by run id on every stream attach and reconnect.
99
+ (0, import_sqlite_core.index)("agent_thread_active_stream_idx").on(table.activeStreamId)
98
100
  ]);
99
101
  var agentMessage = (0, import_sqlite_core.sqliteTable)("agent_message", {
100
102
  id: (0, import_sqlite_core.text)("id").primaryKey(),
@@ -144,7 +146,9 @@ var agentMessage = (0, import_sqlite_core.sqliteTable)("agent_message", {
144
146
  mode: "timestamp_ms"
145
147
  }).notNull()
146
148
  }, (table) => [
147
- (0, import_sqlite_core.index)("agent_message_thread_created_idx").on(table.threadId, table.createdAt)
149
+ (0, import_sqlite_core.index)("agent_message_thread_created_idx").on(table.threadId, table.createdAt),
150
+ // Transcript reads order a thread's messages by `seq`.
151
+ (0, import_sqlite_core.index)("agent_message_thread_seq_idx").on(table.threadId, table.seq)
148
152
  ]);
149
153
  var agentToolCall = (0, import_sqlite_core.sqliteTable)("agent_tool_call", {
150
154
  proposalId: (0, import_sqlite_core.text)("proposal_id"),
@@ -189,7 +193,11 @@ var agentToolCall = (0, import_sqlite_core.sqliteTable)("agent_tool_call", {
189
193
  /** The surface the decision came through (`web`, `slack`, `remembered`, …). */
190
194
  decidedVia: (0, import_sqlite_core.text)("decided_via")
191
195
  }, (table) => [
192
- (0, import_sqlite_core.index)("agent_tool_call_message_idx").on(table.messageId)
196
+ (0, import_sqlite_core.index)("agent_tool_call_message_idx").on(table.messageId),
197
+ // The approvals inbox: `pending_approval`, oldest first.
198
+ (0, import_sqlite_core.index)("agent_tool_call_status_created_idx").on(table.status, table.createdAt),
199
+ (0, import_sqlite_core.index)("agent_tool_call_run_idx").on(table.runId),
200
+ (0, import_sqlite_core.index)("agent_tool_call_created_idx").on(table.createdAt)
193
201
  ]);
194
202
  var agentQueuedMessage = (0, import_sqlite_core.sqliteTable)("agent_queued_message", {
195
203
  uiCapabilities: (0, import_sqlite_core.text)("ui_capabilities", {
@@ -253,7 +261,9 @@ var agentTokenUsage = (0, import_sqlite_core.sqliteTable)("agent_token_usage", {
253
261
  mode: "timestamp_ms"
254
262
  }).notNull()
255
263
  }, (table) => [
256
- (0, import_sqlite_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt)
264
+ (0, import_sqlite_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt),
265
+ (0, import_sqlite_core.index)("agent_token_usage_created_idx").on(table.createdAt),
266
+ (0, import_sqlite_core.index)("agent_token_usage_thread_idx").on(table.threadId)
257
267
  ]);
258
268
  var agentGenuiCall = (0, import_sqlite_core.sqliteTable)("agent_genui_call", {
259
269
  id: (0, import_sqlite_core.text)("id").primaryKey(),
@@ -596,7 +606,9 @@ var agentThread2 = (0, import_mysql_core.mysqlTable)("agent_thread", {
596
606
  updatedAt: ts("updated_at").notNull(),
597
607
  deletedAt: ts("deleted_at")
598
608
  }, (table) => [
599
- (0, import_mysql_core.index)("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt)
609
+ (0, import_mysql_core.index)("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt),
610
+ // `ownerOfActiveStream` reads by run id on every stream attach and reconnect.
611
+ (0, import_mysql_core.index)("agent_thread_active_stream_idx").on(table.activeStreamId)
600
612
  ]);
601
613
  var agentMessage2 = (0, import_mysql_core.mysqlTable)("agent_message", {
602
614
  id: key("id").primaryKey(),
@@ -622,7 +634,9 @@ var agentMessage2 = (0, import_mysql_core.mysqlTable)("agent_message", {
622
634
  seq: (0, import_mysql_core.int)("seq"),
623
635
  createdAt: ts("created_at").notNull()
624
636
  }, (table) => [
625
- (0, import_mysql_core.index)("agent_message_thread_created_idx").on(table.threadId, table.createdAt)
637
+ (0, import_mysql_core.index)("agent_message_thread_created_idx").on(table.threadId, table.createdAt),
638
+ // Transcript reads order a thread's messages by `seq`.
639
+ (0, import_mysql_core.index)("agent_message_thread_seq_idx").on(table.threadId, table.seq)
626
640
  ]);
627
641
  var agentToolCall2 = (0, import_mysql_core.mysqlTable)("agent_tool_call", {
628
642
  proposalId: key("proposal_id"),
@@ -647,7 +661,11 @@ var agentToolCall2 = (0, import_mysql_core.mysqlTable)("agent_tool_call", {
647
661
  remember: (0, import_mysql_core.boolean)("remember"),
648
662
  decidedVia: key("decided_via")
649
663
  }, (table) => [
650
- (0, import_mysql_core.index)("agent_tool_call_message_idx").on(table.messageId)
664
+ (0, import_mysql_core.index)("agent_tool_call_message_idx").on(table.messageId),
665
+ // The approvals inbox: `pending_approval`, oldest first.
666
+ (0, import_mysql_core.index)("agent_tool_call_status_created_idx").on(table.status, table.createdAt),
667
+ (0, import_mysql_core.index)("agent_tool_call_run_idx").on(table.runId),
668
+ (0, import_mysql_core.index)("agent_tool_call_created_idx").on(table.createdAt)
651
669
  ]);
652
670
  var agentQueuedMessage2 = (0, import_mysql_core.mysqlTable)("agent_queued_message", {
653
671
  uiCapabilities: (0, import_mysql_core.json)("ui_capabilities").$type(),
@@ -689,7 +707,9 @@ var agentTokenUsage2 = (0, import_mysql_core.mysqlTable)("agent_token_usage", {
689
707
  costSource: key("cost_source").$type(),
690
708
  createdAt: ts("created_at").notNull()
691
709
  }, (table) => [
692
- (0, import_mysql_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt)
710
+ (0, import_mysql_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt),
711
+ (0, import_mysql_core.index)("agent_token_usage_created_idx").on(table.createdAt),
712
+ (0, import_mysql_core.index)("agent_token_usage_thread_idx").on(table.threadId)
693
713
  ]);
694
714
  var agentGenuiCall2 = (0, import_mysql_core.mysqlTable)("agent_genui_call", {
695
715
  id: key("id").primaryKey(),
@@ -1048,7 +1068,9 @@ var agentThread3 = (0, import_pg_core.pgTable)("agent_thread", {
1048
1068
  updatedAt: ts2("updated_at").notNull(),
1049
1069
  deletedAt: ts2("deleted_at")
1050
1070
  }, (table) => [
1051
- (0, import_pg_core.index)("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt)
1071
+ (0, import_pg_core.index)("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt),
1072
+ // `ownerOfActiveStream` reads by run id on every stream attach and reconnect.
1073
+ (0, import_pg_core.index)("agent_thread_active_stream_idx").on(table.activeStreamId)
1052
1074
  ]);
1053
1075
  var agentMessage3 = (0, import_pg_core.pgTable)("agent_message", {
1054
1076
  id: (0, import_pg_core.text)("id").primaryKey(),
@@ -1074,7 +1096,9 @@ var agentMessage3 = (0, import_pg_core.pgTable)("agent_message", {
1074
1096
  seq: (0, import_pg_core.integer)("seq"),
1075
1097
  createdAt: ts2("created_at").notNull()
1076
1098
  }, (table) => [
1077
- (0, import_pg_core.index)("agent_message_thread_created_idx").on(table.threadId, table.createdAt)
1099
+ (0, import_pg_core.index)("agent_message_thread_created_idx").on(table.threadId, table.createdAt),
1100
+ // Transcript reads order a thread's messages by `seq`.
1101
+ (0, import_pg_core.index)("agent_message_thread_seq_idx").on(table.threadId, table.seq)
1078
1102
  ]);
1079
1103
  var agentToolCall3 = (0, import_pg_core.pgTable)("agent_tool_call", {
1080
1104
  proposalId: (0, import_pg_core.text)("proposal_id"),
@@ -1099,7 +1123,11 @@ var agentToolCall3 = (0, import_pg_core.pgTable)("agent_tool_call", {
1099
1123
  remember: (0, import_pg_core.boolean)("remember"),
1100
1124
  decidedVia: (0, import_pg_core.text)("decided_via")
1101
1125
  }, (table) => [
1102
- (0, import_pg_core.index)("agent_tool_call_message_idx").on(table.messageId)
1126
+ (0, import_pg_core.index)("agent_tool_call_message_idx").on(table.messageId),
1127
+ // The approvals inbox: `pending_approval`, oldest first.
1128
+ (0, import_pg_core.index)("agent_tool_call_status_created_idx").on(table.status, table.createdAt),
1129
+ (0, import_pg_core.index)("agent_tool_call_run_idx").on(table.runId),
1130
+ (0, import_pg_core.index)("agent_tool_call_created_idx").on(table.createdAt)
1103
1131
  ]);
1104
1132
  var agentQueuedMessage3 = (0, import_pg_core.pgTable)("agent_queued_message", {
1105
1133
  uiCapabilities: (0, import_pg_core.jsonb)("ui_capabilities").$type(),
@@ -1141,7 +1169,9 @@ var agentTokenUsage3 = (0, import_pg_core.pgTable)("agent_token_usage", {
1141
1169
  costSource: (0, import_pg_core.text)("cost_source").$type(),
1142
1170
  createdAt: ts2("created_at").notNull()
1143
1171
  }, (table) => [
1144
- (0, import_pg_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt)
1172
+ (0, import_pg_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt),
1173
+ (0, import_pg_core.index)("agent_token_usage_created_idx").on(table.createdAt),
1174
+ (0, import_pg_core.index)("agent_token_usage_thread_idx").on(table.threadId)
1145
1175
  ]);
1146
1176
  var agentGenuiCall3 = (0, import_pg_core.pgTable)("agent_genui_call", {
1147
1177
  id: (0, import_pg_core.text)("id").primaryKey(),
@@ -2420,12 +2450,49 @@ var DrizzleAgentStore = class {
2420
2450
  }
2421
2451
  async listThreads(actorRef, limit = 50) {
2422
2452
  const threads = await this.db.select().from(this.t.agentThread).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(this.t.agentThread.actorRef, actorRef), (0, import_drizzle_orm4.eq)(this.t.agentThread.transient, false), (0, import_drizzle_orm4.isNull)(this.t.agentThread.deletedAt))).orderBy((0, import_drizzle_orm4.desc)(this.t.agentThread.updatedAt)).limit(limit);
2423
- const summaries = [];
2424
- for (const thread of threads) {
2425
- const [last] = await this.db.select().from(this.t.agentMessage).where((0, import_drizzle_orm4.eq)(this.t.agentMessage.threadId, thread.id)).orderBy(...this.messageOrderNewestFirst()).limit(1);
2426
- summaries.push(this.toSummary(thread, last?.content));
2453
+ const previews = await this.lastMessageContents(threads.map((thread) => thread.id));
2454
+ return threads.map((thread) => this.toSummary(thread, previews.get(thread.id)));
2455
+ }
2456
+ /**
2457
+ * The content of each thread's newest message ({@link messageOrderNewestFirst}), in a fixed two
2458
+ * reads for any number of threads: each thread's highest `seq`, then the rows holding it. Only a
2459
+ * thread whose every message predates `seq` is read on its own, by `created_at`.
2460
+ */
2461
+ async lastMessageContents(threadIds) {
2462
+ const contents = /* @__PURE__ */ new Map();
2463
+ if (threadIds.length === 0) {
2464
+ return contents;
2465
+ }
2466
+ const message = this.t.agentMessage;
2467
+ const highest = await this.db.select({
2468
+ threadId: message.threadId,
2469
+ seq: (0, import_drizzle_orm4.max)(message.seq)
2470
+ }).from(message).where((0, import_drizzle_orm4.inArray)(message.threadId, [
2471
+ ...threadIds
2472
+ ])).groupBy(message.threadId);
2473
+ const numbered = highest.filter((row) => row.seq !== null);
2474
+ if (numbered.length > 0) {
2475
+ const rows = await this.db.select({
2476
+ threadId: message.threadId,
2477
+ content: message.content
2478
+ }).from(message).where((0, import_drizzle_orm4.or)(...numbered.map((row) => (0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(message.threadId, row.threadId), (0, import_drizzle_orm4.eq)(message.seq, Number(row.seq)))))).orderBy(...this.messageOrderNewestFirst());
2479
+ for (const row of rows) {
2480
+ if (!contents.has(row.threadId)) {
2481
+ contents.set(row.threadId, row.content);
2482
+ }
2483
+ }
2484
+ }
2485
+ for (const row of highest) {
2486
+ if (row.seq === null) {
2487
+ const [last] = await this.db.select({
2488
+ content: message.content
2489
+ }).from(message).where((0, import_drizzle_orm4.eq)(message.threadId, row.threadId)).orderBy(...this.messageOrderNewestFirst()).limit(1);
2490
+ if (last !== void 0) {
2491
+ contents.set(row.threadId, last.content);
2492
+ }
2493
+ }
2427
2494
  }
2428
- return summaries;
2495
+ return contents;
2429
2496
  }
2430
2497
  async softDeleteThread(threadId) {
2431
2498
  await this.db.update(this.t.agentThread).set({
@@ -2802,6 +2869,24 @@ var DrizzleAgentStore = class {
2802
2869
  }).from(agentThread).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(this.t.agentThread.id, threadId), (0, import_drizzle_orm4.isNull)(this.t.agentThread.deletedAt)));
2803
2870
  return thread?.persona ?? null;
2804
2871
  }
2872
+ async threadSettings(threadId) {
2873
+ const thread = this.t.agentThread;
2874
+ const [row] = await this.db.select({
2875
+ actorRef: thread.actorRef,
2876
+ defaultAgent: thread.defaultAgent,
2877
+ persona: thread.persona,
2878
+ model: thread.model
2879
+ }).from(thread).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(thread.id, threadId), (0, import_drizzle_orm4.isNull)(thread.deletedAt)));
2880
+ if (row === void 0) {
2881
+ return null;
2882
+ }
2883
+ return {
2884
+ actorRef: row.actorRef,
2885
+ defaultAgent: row.defaultAgent ?? null,
2886
+ persona: row.persona ?? null,
2887
+ model: row.model ?? null
2888
+ };
2889
+ }
2805
2890
  async defaultAgentForThread(threadId) {
2806
2891
  const [thread] = await this.db.select({
2807
2892
  defaultAgent: this.t.agentThread.defaultAgent
@@ -3117,10 +3202,43 @@ var DrizzleAgentStore = class {
3117
3202
  return this.usageBetween(actorRef, day, day);
3118
3203
  }
3119
3204
  async usageBetween(actorRef, fromDay, toDay) {
3120
- const start = /* @__PURE__ */ new Date(`${fromDay}T00:00:00.000Z`);
3121
- const end = /* @__PURE__ */ new Date(`${toDay}T23:59:59.999Z`);
3122
- const rows = await this.db.select().from(this.t.agentTokenUsage).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(this.t.agentTokenUsage.actorRef, actorRef), (0, import_drizzle_orm4.gte)(this.t.agentTokenUsage.createdAt, start), (0, import_drizzle_orm4.lte)(this.t.agentTokenUsage.createdAt, end)));
3123
- return (0, import_nestjs_agent_core4.sumUsage)(rows);
3205
+ const [totals] = await this.usageWindows(actorRef, [
3206
+ {
3207
+ fromDay,
3208
+ toDay
3209
+ }
3210
+ ]);
3211
+ return totals ?? (0, import_nestjs_agent_core4.sumUsage)([]);
3212
+ }
3213
+ /**
3214
+ * Every range summed by the database in one statement, each as a conditional aggregate over the
3215
+ * rows of the smallest span covering them all — the actor's `(actor_ref, created_at)` index serves
3216
+ * it, and no usage row crosses the wire.
3217
+ */
3218
+ async usageWindows(actorRef, ranges) {
3219
+ if (ranges.length === 0) {
3220
+ return [];
3221
+ }
3222
+ const usage = this.t.agentTokenUsage;
3223
+ const bounds = ranges.map(({ fromDay, toDay }) => ({
3224
+ start: /* @__PURE__ */ new Date(`${fromDay}T00:00:00.000Z`),
3225
+ end: /* @__PURE__ */ new Date(`${toDay}T23:59:59.999Z`)
3226
+ }));
3227
+ const within = /* @__PURE__ */ __name((start, end) => (0, import_drizzle_orm4.and)((0, import_drizzle_orm4.gte)(usage.createdAt, start), (0, import_drizzle_orm4.lte)(usage.createdAt, end)), "within");
3228
+ const columns = {};
3229
+ bounds.forEach(({ start, end }, index4) => {
3230
+ columns[`tokens${index4}`] = import_drizzle_orm4.sql`sum(case when ${within(start, end)} then ${usage.inputTokens} + ${usage.outputTokens} else 0 end)`;
3231
+ columns[`cost${index4}`] = import_drizzle_orm4.sql`sum(case when ${within(start, end)} then ${usage.costUsd} else 0 end)`;
3232
+ columns[`estimated${index4}`] = import_drizzle_orm4.sql`sum(case when ${within(start, end)} and ${usage.costSource} = 'estimate' then ${usage.costUsd} else 0 end)`;
3233
+ });
3234
+ const from = new Date(Math.min(...bounds.map(({ start }) => start.getTime())));
3235
+ const to = new Date(Math.max(...bounds.map(({ end }) => end.getTime())));
3236
+ const [row] = await this.db.select(columns).from(usage).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(usage.actorRef, actorRef), within(from, to)));
3237
+ return bounds.map((_, index4) => ({
3238
+ usedTokens: Number(row?.[`tokens${index4}`] ?? 0),
3239
+ costUsd: Number(row?.[`cost${index4}`] ?? 0),
3240
+ estimatedCostUsd: Number(row?.[`estimated${index4}`] ?? 0)
3241
+ }));
3124
3242
  }
3125
3243
  toSummary(thread, lastContent) {
3126
3244
  return {
@@ -3416,7 +3534,18 @@ var DrizzleGovernanceQueries = class {
3416
3534
  }
3417
3535
  async usageInRange(range) {
3418
3536
  const { start, end } = (0, import_nestjs_agent_core5.dayBoundsUtc)(range);
3419
- const rows = await this.db.select().from(this.t.agentTokenUsage).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentTokenUsage.createdAt, start), (0, import_drizzle_orm5.lte)(this.t.agentTokenUsage.createdAt, end)));
3537
+ const usage = this.t.agentTokenUsage;
3538
+ const rows = await this.db.select({
3539
+ modelId: usage.modelId,
3540
+ actorRef: usage.actorRef,
3541
+ threadId: usage.threadId,
3542
+ createdAt: usage.createdAt,
3543
+ inputTokens: usage.inputTokens,
3544
+ outputTokens: usage.outputTokens,
3545
+ cacheWriteTokens: usage.cacheWriteTokens,
3546
+ cacheReadTokens: usage.cacheReadTokens,
3547
+ costUsd: usage.costUsd
3548
+ }).from(usage).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentTokenUsage.createdAt, start), (0, import_drizzle_orm5.lte)(this.t.agentTokenUsage.createdAt, end)));
3420
3549
  return rows.map(toUsageInput);
3421
3550
  }
3422
3551
  async spendByModel(range) {
@@ -3441,7 +3570,11 @@ var DrizzleGovernanceQueries = class {
3441
3570
  if (threadIds.length === 0) {
3442
3571
  return [];
3443
3572
  }
3444
- const threads = await this.db.select().from(this.t.agentThread).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.inArray)(this.t.agentThread.id, threadIds), (0, import_drizzle_orm5.isNull)(this.t.agentThread.deletedAt)));
3573
+ const threads = await this.db.select({
3574
+ id: this.t.agentThread.id,
3575
+ title: this.t.agentThread.title,
3576
+ actorRef: this.t.agentThread.actorRef
3577
+ }).from(this.t.agentThread).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.inArray)(this.t.agentThread.id, threadIds), (0, import_drizzle_orm5.isNull)(this.t.agentThread.deletedAt)));
3445
3578
  const threadsById = new Map(threads.map((thread) => [
3446
3579
  thread.id,
3447
3580
  {
@@ -3536,9 +3669,19 @@ var DrizzleGovernanceQueries = class {
3536
3669
  const threads = await this.db.select().from(this.t.agentThread).where((0, import_drizzle_orm5.isNull)(this.t.agentThread.deletedAt)).orderBy((0, import_drizzle_orm5.desc)(this.t.agentThread.updatedAt), (0, import_drizzle_orm5.desc)(this.t.agentThread.id)).limit(limit);
3537
3670
  return this.toThreadActivityRows(threads);
3538
3671
  }
3672
+ /** The range's runs, with only the columns the rollups read. */
3539
3673
  async runsInRange(range) {
3540
3674
  const { start, end } = (0, import_nestjs_agent_core5.dayBoundsUtc)(range);
3541
- return this.db.select().from(this.t.agentRun).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentRun.startedAt, start), (0, import_drizzle_orm5.lte)(this.t.agentRun.startedAt, end)));
3675
+ const run = this.t.agentRun;
3676
+ return this.db.select({
3677
+ agentName: run.agentName,
3678
+ status: run.status,
3679
+ retries: run.retries,
3680
+ durationMs: run.durationMs,
3681
+ ttftMs: run.ttftMs,
3682
+ parentRunId: run.parentRunId,
3683
+ startedAt: run.startedAt
3684
+ }).from(run).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(run.startedAt, start), (0, import_drizzle_orm5.lte)(run.startedAt, end)));
3542
3685
  }
3543
3686
  async runMetrics(range) {
3544
3687
  const runs = await this.runsInRange(range);
@@ -3602,7 +3745,9 @@ var DrizzleGovernanceQueries = class {
3602
3745
  }
3603
3746
  async runErrors(range) {
3604
3747
  const { start, end } = (0, import_nestjs_agent_core5.dayBoundsUtc)(range);
3605
- const runs = await this.db.select().from(this.t.agentRun).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentRun.startedAt, start), (0, import_drizzle_orm5.lte)(this.t.agentRun.startedAt, end), (0, import_drizzle_orm5.eq)(this.t.agentRun.status, "failed")));
3748
+ const runs = await this.db.select({
3749
+ errorCode: this.t.agentRun.errorCode
3750
+ }).from(this.t.agentRun).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentRun.startedAt, start), (0, import_drizzle_orm5.lte)(this.t.agentRun.startedAt, end), (0, import_drizzle_orm5.eq)(this.t.agentRun.status, "failed")));
3606
3751
  const byError = /* @__PURE__ */ new Map();
3607
3752
  for (const run of runs) {
3608
3753
  const errorCode = run.errorCode ?? UNCLASSIFIED_ERROR_CODE;
@@ -3683,7 +3828,12 @@ var DrizzleGovernanceQueries = class {
3683
3828
  */
3684
3829
  async toolStats(range) {
3685
3830
  const { start, end } = (0, import_nestjs_agent_core5.dayBoundsUtc)(range);
3686
- const calls = await this.db.select().from(this.t.agentToolCall).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentToolCall.createdAt, start), (0, import_drizzle_orm5.lte)(this.t.agentToolCall.createdAt, end)));
3831
+ const calls = await this.db.select({
3832
+ toolName: this.t.agentToolCall.toolName,
3833
+ toolType: this.t.agentToolCall.toolType,
3834
+ status: this.t.agentToolCall.status,
3835
+ executionMs: this.t.agentToolCall.executionMs
3836
+ }).from(this.t.agentToolCall).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentToolCall.createdAt, start), (0, import_drizzle_orm5.lte)(this.t.agentToolCall.createdAt, end)));
3687
3837
  const byTool = /* @__PURE__ */ new Map();
3688
3838
  for (const call of calls) {
3689
3839
  const key2 = `${call.toolName} ${call.toolType}`;