@dudousxd/nestjs-agent-store-drizzle 0.21.0 → 0.22.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/README.md CHANGED
@@ -150,7 +150,7 @@ reader's `IN (…)` and `truncateFrom`'s delete) filter on it.
150
150
  ## Attachment housekeeping
151
151
 
152
152
  `referencedMediaIds(actorRef, mediaIds)` answers which of a set of media ids a message that still
153
- exists carries, for one actor — the inverse of the host's own staged-media inventory, and the half a
153
+ exists — or one still waiting in a thread's queue (`agent_queued_message`) — carries, for one actor — the inverse of the host's own staged-media inventory, and the half a
154
154
  sweep cannot work out for itself. It needs **no schema change**: it reads the `attachments` JSON
155
155
  column messages have carried since attachments shipped, so an existing database answers correctly
156
156
  the moment you upgrade, with nothing to backfill.
package/dist/index.cjs CHANGED
@@ -28,6 +28,8 @@ __export(index_exports, {
28
28
  DrizzleMemoryProvider: () => DrizzleMemoryProvider,
29
29
  DrizzlePricingStore: () => DrizzlePricingStore,
30
30
  DrizzleRagIngestionLog: () => DrizzleRagIngestionLog,
31
+ DrizzleStreamFrameTable: () => DrizzleStreamFrameTable,
32
+ DrizzleTokenStreamSink: () => DrizzleTokenStreamSink,
31
33
  RAG_INGESTION_LOG_PAGE_ORDER: () => RAG_INGESTION_LOG_PAGE_ORDER,
32
34
  agentConfirmToken: () => agentConfirmToken,
33
35
  agentMemory: () => agentMemory,
@@ -36,6 +38,7 @@ __export(index_exports, {
36
38
  agentQueuedMessage: () => agentQueuedMessage,
37
39
  agentRun: () => agentRun,
38
40
  agentSchema: () => agentSchema,
41
+ agentStreamFrame: () => agentStreamFrame,
39
42
  agentThread: () => agentThread,
40
43
  agentTokenUsage: () => agentTokenUsage,
41
44
  agentToolCall: () => agentToolCall,
@@ -318,6 +321,20 @@ var agentConfirmToken = (0, import_sqlite_core.sqliteTable)("agent_confirm_token
318
321
  }, (table) => [
319
322
  (0, import_sqlite_core.index)("agent_confirm_token_expires_idx").on(table.expiresAt)
320
323
  ]);
324
+ var agentStreamFrame = (0, import_sqlite_core.sqliteTable)("agent_stream_frame", {
325
+ runId: (0, import_sqlite_core.text)("run_id").notNull(),
326
+ seq: (0, import_sqlite_core.integer)("seq").notNull(),
327
+ frame: (0, import_sqlite_core.text)("frame"),
328
+ error: (0, import_sqlite_core.text)("error"),
329
+ createdAt: (0, import_sqlite_core.integer)("created_at").notNull()
330
+ }, (table) => [
331
+ (0, import_sqlite_core.primaryKey)({
332
+ columns: [
333
+ table.runId,
334
+ table.seq
335
+ ]
336
+ })
337
+ ]);
321
338
  var agentSchema = {
322
339
  agentThread,
323
340
  agentMessage,
@@ -484,6 +501,14 @@ var statements = [
484
501
  )`,
485
502
  `CREATE INDEX IF NOT EXISTS rag_ingestion_log_collection_idx
486
503
  ON rag_ingestion_log (collection, updated_at)`,
504
+ `CREATE TABLE IF NOT EXISTS agent_stream_frame (
505
+ run_id TEXT NOT NULL,
506
+ seq INTEGER NOT NULL,
507
+ frame TEXT,
508
+ error TEXT,
509
+ created_at INTEGER NOT NULL,
510
+ PRIMARY KEY (run_id, seq)
511
+ )`,
487
512
  `CREATE TABLE IF NOT EXISTS agent_confirm_token (
488
513
  hash TEXT PRIMARY KEY NOT NULL,
489
514
  actor_ref TEXT NOT NULL,
@@ -1210,7 +1235,8 @@ var DrizzleAgentStore = class {
1210
1235
  return rows.length;
1211
1236
  }
1212
1237
  /**
1213
- * Of `mediaIds`, the ones a surviving message in one of this actor's threads still carries.
1238
+ * Of `mediaIds`, the ones a surviving message — or a message waiting in the queue — in one of
1239
+ * this actor's threads still carries.
1214
1240
  *
1215
1241
  * Reads the `attachments` JSON back out and matches in memory rather than pushing the match into
1216
1242
  * SQL: the column holds an array of objects, and every dialect this adapter's sibling targets
@@ -1229,9 +1255,15 @@ var DrizzleAgentStore = class {
1229
1255
  const rows = await this.db.select({
1230
1256
  attachments: agentMessage.attachments
1231
1257
  }).from(agentMessage).innerJoin(agentThread, (0, import_drizzle_orm2.eq)(agentMessage.threadId, agentThread.id)).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentThread.actorRef, actorRef), (0, import_drizzle_orm2.isNotNull)(agentMessage.attachments)));
1258
+ const queued = await this.db.select({
1259
+ attachments: agentQueuedMessage.attachments
1260
+ }).from(agentQueuedMessage).innerJoin(agentThread, (0, import_drizzle_orm2.eq)(agentQueuedMessage.threadId, agentThread.id)).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentThread.actorRef, actorRef), (0, import_drizzle_orm2.isNotNull)(agentQueuedMessage.attachments)));
1232
1261
  const wanted = new Set(mediaIds);
1233
1262
  const found = /* @__PURE__ */ new Set();
1234
- for (const row of rows) {
1263
+ for (const row of [
1264
+ ...rows,
1265
+ ...queued
1266
+ ]) {
1235
1267
  for (const attachment of row.attachments ?? []) {
1236
1268
  if (wanted.has(attachment.mediaId)) {
1237
1269
  found.add(attachment.mediaId);
@@ -2193,8 +2225,71 @@ var DrizzlePricingStore = class {
2193
2225
  }
2194
2226
  };
2195
2227
 
2196
- // src/drizzle-confirm-token-store.ts
2228
+ // src/drizzle-token-stream-sink.ts
2229
+ var import_nestjs_agent_core4 = require("@dudousxd/nestjs-agent-core");
2197
2230
  var import_drizzle_orm6 = require("drizzle-orm");
2231
+ function isUniqueViolation(error) {
2232
+ for (let current = error; current !== null && typeof current === "object"; ) {
2233
+ const code = current.code;
2234
+ if (typeof code === "string" && code.startsWith("SQLITE_CONSTRAINT")) return true;
2235
+ current = current.cause;
2236
+ }
2237
+ return false;
2238
+ }
2239
+ __name(isUniqueViolation, "isUniqueViolation");
2240
+ var DrizzleStreamFrameTable = class {
2241
+ static {
2242
+ __name(this, "DrizzleStreamFrameTable");
2243
+ }
2244
+ db;
2245
+ constructor(db) {
2246
+ this.db = db;
2247
+ }
2248
+ async append(runId, row) {
2249
+ await this.db.run(import_drizzle_orm6.sql`INSERT INTO agent_stream_frame (run_id, seq, frame, error, created_at)
2250
+ SELECT ${runId}, COALESCE(MAX(seq), 0) + 1, ${row.frame}, ${row.error}, ${row.createdAt}
2251
+ FROM agent_stream_frame WHERE run_id = ${runId}`);
2252
+ }
2253
+ async read(runId, after, limit) {
2254
+ return this.db.select({
2255
+ seq: agentStreamFrame.seq,
2256
+ frame: agentStreamFrame.frame,
2257
+ error: agentStreamFrame.error
2258
+ }).from(agentStreamFrame).where((0, import_drizzle_orm6.and)((0, import_drizzle_orm6.eq)(agentStreamFrame.runId, runId), (0, import_drizzle_orm6.gt)(agentStreamFrame.seq, after))).orderBy((0, import_drizzle_orm6.asc)(agentStreamFrame.seq)).limit(limit);
2259
+ }
2260
+ async has(runId) {
2261
+ const rows = await this.db.select({
2262
+ seq: agentStreamFrame.seq
2263
+ }).from(agentStreamFrame).where((0, import_drizzle_orm6.eq)(agentStreamFrame.runId, runId)).limit(1);
2264
+ return rows.length > 0;
2265
+ }
2266
+ async remove(runIds) {
2267
+ if (runIds.length === 0) return;
2268
+ await this.db.delete(agentStreamFrame).where((0, import_drizzle_orm6.inArray)(agentStreamFrame.runId, [
2269
+ ...runIds
2270
+ ]));
2271
+ }
2272
+ async lapsedRuns(cutoff) {
2273
+ const rows = await this.db.select({
2274
+ runId: agentStreamFrame.runId
2275
+ }).from(agentStreamFrame).groupBy(agentStreamFrame.runId).having((0, import_drizzle_orm6.lt)((0, import_drizzle_orm6.max)(agentStreamFrame.createdAt), cutoff));
2276
+ return rows.map((row) => row.runId);
2277
+ }
2278
+ isUniqueViolation(error) {
2279
+ return isUniqueViolation(error);
2280
+ }
2281
+ };
2282
+ var DrizzleTokenStreamSink = class extends import_nestjs_agent_core4.SqlTokenStreamSink {
2283
+ static {
2284
+ __name(this, "DrizzleTokenStreamSink");
2285
+ }
2286
+ constructor(db, options = {}) {
2287
+ super(new DrizzleStreamFrameTable(db), options);
2288
+ }
2289
+ };
2290
+
2291
+ // src/drizzle-confirm-token-store.ts
2292
+ var import_drizzle_orm7 = require("drizzle-orm");
2198
2293
  var DrizzleConfirmTokenStore = class {
2199
2294
  static {
2200
2295
  __name(this, "DrizzleConfirmTokenStore");
@@ -2216,10 +2311,10 @@ var DrizzleConfirmTokenStore = class {
2216
2311
  return inserted.length === 1;
2217
2312
  }
2218
2313
  async release(hash) {
2219
- await this.db.delete(agentConfirmToken).where((0, import_drizzle_orm6.eq)(agentConfirmToken.hash, hash));
2314
+ await this.db.delete(agentConfirmToken).where((0, import_drizzle_orm7.eq)(agentConfirmToken.hash, hash));
2220
2315
  }
2221
2316
  async purgeExpired(now = Date.now()) {
2222
- const purged = await this.db.delete(agentConfirmToken).where((0, import_drizzle_orm6.lt)(agentConfirmToken.expiresAt, now)).returning({
2317
+ const purged = await this.db.delete(agentConfirmToken).where((0, import_drizzle_orm7.lt)(agentConfirmToken.expiresAt, now)).returning({
2223
2318
  hash: agentConfirmToken.hash
2224
2319
  });
2225
2320
  return purged.length;
@@ -2229,7 +2324,7 @@ var DrizzleConfirmTokenStore = class {
2229
2324
  // src/drizzle-rag-ingestion-log.ts
2230
2325
  var import_node_diagnostics_channel = require("diagnostics_channel");
2231
2326
  var import_common = require("@nestjs/common");
2232
- var import_drizzle_orm7 = require("drizzle-orm");
2327
+ var import_drizzle_orm8 = require("drizzle-orm");
2233
2328
  function _ts_decorate(decorators, target, key, desc4) {
2234
2329
  var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
2235
2330
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -2277,8 +2372,8 @@ function num(value) {
2277
2372
  }
2278
2373
  __name(num, "num");
2279
2374
  var RAG_INGESTION_LOG_PAGE_ORDER = [
2280
- (0, import_drizzle_orm7.desc)(ragIngestionLog.updatedAt),
2281
- (0, import_drizzle_orm7.asc)(ragIngestionLog.documentId)
2375
+ (0, import_drizzle_orm8.desc)(ragIngestionLog.updatedAt),
2376
+ (0, import_drizzle_orm8.asc)(ragIngestionLog.documentId)
2282
2377
  ];
2283
2378
  var DEFAULT_PAGE_SIZE = 200;
2284
2379
  var DEFAULT_BATCH_SIZE = 200;
@@ -2342,7 +2437,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2342
2437
  */
2343
2438
  async listPage(query = {}) {
2344
2439
  const [totalRow] = await this.db.select({
2345
- value: (0, import_drizzle_orm7.count)()
2440
+ value: (0, import_drizzle_orm8.count)()
2346
2441
  }).from(ragIngestionLog).where(this.where(query));
2347
2442
  return {
2348
2443
  rows: await this.list(query),
@@ -2421,19 +2516,19 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2421
2516
  }
2422
2517
  /** The latest recorded outcome for one document, or null if it was never attempted. */
2423
2518
  async get(documentId) {
2424
- const [row] = await this.db.select().from(ragIngestionLog).where((0, import_drizzle_orm7.eq)(ragIngestionLog.documentId, documentId));
2519
+ const [row] = await this.db.select().from(ragIngestionLog).where((0, import_drizzle_orm8.eq)(ragIngestionLog.documentId, documentId));
2425
2520
  return row ?? null;
2426
2521
  }
2427
2522
  /** Forget one document's record. Returns whether a row was actually removed. */
2428
2523
  async remove(documentId) {
2429
- const removed = await this.db.delete(ragIngestionLog).where((0, import_drizzle_orm7.eq)(ragIngestionLog.documentId, documentId)).returning({
2524
+ const removed = await this.db.delete(ragIngestionLog).where((0, import_drizzle_orm8.eq)(ragIngestionLog.documentId, documentId)).returning({
2430
2525
  documentId: ragIngestionLog.documentId
2431
2526
  });
2432
2527
  return removed.length > 0;
2433
2528
  }
2434
2529
  /** Forget every record for a collection — for when the collection itself is deleted. */
2435
2530
  async removeByCollection(collection) {
2436
- const removed = await this.db.delete(ragIngestionLog).where((0, import_drizzle_orm7.eq)(ragIngestionLog.collection, collection)).returning({
2531
+ const removed = await this.db.delete(ragIngestionLog).where((0, import_drizzle_orm8.eq)(ragIngestionLog.collection, collection)).returning({
2437
2532
  documentId: ragIngestionLog.documentId
2438
2533
  });
2439
2534
  return removed.length;
@@ -2465,7 +2560,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2465
2560
  }
2466
2561
  }
2467
2562
  where(query) {
2468
- return (0, import_drizzle_orm7.and)(query.collection !== void 0 ? (0, import_drizzle_orm7.eq)(ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? (0, import_drizzle_orm7.eq)(ragIngestionLog.status, query.status) : void 0);
2563
+ return (0, import_drizzle_orm8.and)(query.collection !== void 0 ? (0, import_drizzle_orm8.eq)(ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? (0, import_drizzle_orm8.eq)(ragIngestionLog.status, query.status) : void 0);
2469
2564
  }
2470
2565
  /**
2471
2566
  * The coordinates filter AND'd with "strictly after `cursor` in
@@ -2480,7 +2575,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2480
2575
  if (cursor === void 0) {
2481
2576
  return base;
2482
2577
  }
2483
- return (0, import_drizzle_orm7.and)(base, (0, import_drizzle_orm7.or)((0, import_drizzle_orm7.lt)(ragIngestionLog.updatedAt, cursor.updatedAt), (0, import_drizzle_orm7.and)((0, import_drizzle_orm7.eq)(ragIngestionLog.updatedAt, cursor.updatedAt), (0, import_drizzle_orm7.gt)(ragIngestionLog.documentId, cursor.documentId))));
2578
+ return (0, import_drizzle_orm8.and)(base, (0, import_drizzle_orm8.or)((0, import_drizzle_orm8.lt)(ragIngestionLog.updatedAt, cursor.updatedAt), (0, import_drizzle_orm8.and)((0, import_drizzle_orm8.eq)(ragIngestionLog.updatedAt, cursor.updatedAt), (0, import_drizzle_orm8.gt)(ragIngestionLog.documentId, cursor.documentId))));
2484
2579
  }
2485
2580
  /**
2486
2581
  * Upsert one outcome. Keyed by document id so the row always reflects the *current* state — a
@@ -2556,7 +2651,7 @@ DrizzleRagIngestionLog = _ts_decorate([
2556
2651
  ], DrizzleRagIngestionLog);
2557
2652
 
2558
2653
  // src/drizzle-agent-store.module.ts
2559
- var import_nestjs_agent_core4 = require("@dudousxd/nestjs-agent-core");
2654
+ var import_nestjs_agent_core5 = require("@dudousxd/nestjs-agent-core");
2560
2655
  var import_common2 = require("@nestjs/common");
2561
2656
  function _ts_decorate2(decorators, target, key, desc4) {
2562
2657
  var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
@@ -2593,7 +2688,7 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
2593
2688
  useFactory: /* @__PURE__ */ __name(() => new DrizzleAgentStore(options.db), "useFactory")
2594
2689
  },
2595
2690
  {
2596
- provide: import_nestjs_agent_core4.AGENT_STORE,
2691
+ provide: import_nestjs_agent_core5.AGENT_STORE,
2597
2692
  useExisting: DrizzleAgentStore
2598
2693
  },
2599
2694
  // Exported, never bound to AGENT_MEMORY: that token's PRESENCE is what turns memory on, so
@@ -2610,21 +2705,21 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
2610
2705
  // AGENT_PRICING_STORE: the host's own store when supplied, else the default Drizzle one.
2611
2706
  // DrizzleGovernanceQueries prices usage against whatever is bound here.
2612
2707
  options.pricingStore ? {
2613
- provide: import_nestjs_agent_core4.AGENT_PRICING_STORE,
2708
+ provide: import_nestjs_agent_core5.AGENT_PRICING_STORE,
2614
2709
  useClass: options.pricingStore
2615
2710
  } : {
2616
- provide: import_nestjs_agent_core4.AGENT_PRICING_STORE,
2711
+ provide: import_nestjs_agent_core5.AGENT_PRICING_STORE,
2617
2712
  useExisting: DrizzlePricingStore
2618
2713
  },
2619
2714
  {
2620
2715
  provide: DrizzleGovernanceQueries,
2621
2716
  useFactory: /* @__PURE__ */ __name((pricingStore) => new DrizzleGovernanceQueries(options.db, pricingStore), "useFactory"),
2622
2717
  inject: [
2623
- import_nestjs_agent_core4.AGENT_PRICING_STORE
2718
+ import_nestjs_agent_core5.AGENT_PRICING_STORE
2624
2719
  ]
2625
2720
  },
2626
2721
  {
2627
- provide: import_nestjs_agent_core4.AGENT_GOVERNANCE_QUERIES,
2722
+ provide: import_nestjs_agent_core5.AGENT_GOVERNANCE_QUERIES,
2628
2723
  useExisting: DrizzleGovernanceQueries
2629
2724
  },
2630
2725
  // What makes a `defineConfirmedTool` confirmation single use across replicas.
@@ -2633,7 +2728,7 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
2633
2728
  useFactory: /* @__PURE__ */ __name(() => new DrizzleConfirmTokenStore(options.db), "useFactory")
2634
2729
  },
2635
2730
  {
2636
- provide: import_nestjs_agent_core4.AGENT_CONFIRM_TOKEN_STORE,
2731
+ provide: import_nestjs_agent_core5.AGENT_CONFIRM_TOKEN_STORE,
2637
2732
  useExisting: DrizzleConfirmTokenStore
2638
2733
  }
2639
2734
  ],
@@ -2642,14 +2737,14 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
2642
2737
  DrizzleRagIngestionLog
2643
2738
  ],
2644
2739
  DrizzleAgentStore,
2645
- import_nestjs_agent_core4.AGENT_STORE,
2740
+ import_nestjs_agent_core5.AGENT_STORE,
2646
2741
  DrizzleMemoryProvider,
2647
2742
  DrizzleGovernanceQueries,
2648
- import_nestjs_agent_core4.AGENT_GOVERNANCE_QUERIES,
2743
+ import_nestjs_agent_core5.AGENT_GOVERNANCE_QUERIES,
2649
2744
  DrizzlePricingStore,
2650
- import_nestjs_agent_core4.AGENT_PRICING_STORE,
2745
+ import_nestjs_agent_core5.AGENT_PRICING_STORE,
2651
2746
  DrizzleConfirmTokenStore,
2652
- import_nestjs_agent_core4.AGENT_CONFIRM_TOKEN_STORE
2747
+ import_nestjs_agent_core5.AGENT_CONFIRM_TOKEN_STORE
2653
2748
  ]
2654
2749
  };
2655
2750
  }
@@ -2666,6 +2761,8 @@ DrizzleAgentStoreModule = _ts_decorate2([
2666
2761
  DrizzleMemoryProvider,
2667
2762
  DrizzlePricingStore,
2668
2763
  DrizzleRagIngestionLog,
2764
+ DrizzleStreamFrameTable,
2765
+ DrizzleTokenStreamSink,
2669
2766
  RAG_INGESTION_LOG_PAGE_ORDER,
2670
2767
  agentConfirmToken,
2671
2768
  agentMemory,
@@ -2674,6 +2771,7 @@ DrizzleAgentStoreModule = _ts_decorate2([
2674
2771
  agentQueuedMessage,
2675
2772
  agentRun,
2676
2773
  agentSchema,
2774
+ agentStreamFrame,
2677
2775
  agentThread,
2678
2776
  agentTokenUsage,
2679
2777
  agentToolCall,