@dudousxd/nestjs-agent-store-drizzle 0.20.2 → 0.22.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as drizzle_orm_sqlite_core from 'drizzle-orm/sqlite-core';
2
2
  import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
3
- import { MessageRole, ToolCallRequest, ToolResult, MessageAttachment, MessageUsage, AgentUiComponent, MessageFeedback, Actor, PageContext, QueuePause, ToolKind, ToolCallStatus, UsagePurpose, AgentStore, ThreadTurnReader, ChatQueueStore, CreateThreadInput, ThreadSummary, ThreadDetail, ThreadTurnQuery, ThreadTurnPage, ToolCallApprovalState, EnqueueMessageInput, QueuedMessage, QueuedMessagePatch, UpdateThreadInput, RecordRunStartInput, AppendMessageInput, StoredMessage, RecordToolCallInput, UpdateToolCallInput, ToolCallOutcome, RecordUsageInput, AgentGovernanceQueries, AgentPricingStore, GovernanceRange, ModelSpendRow, ActorSpendRow, ThreadSpendRow, UsageTrendPoint, ToolCallActivityRow, ThreadActivityRow, RunMetrics, RunAgentBreakdownRow, RunErrorBreakdownRow, RunTrendPoint, RecentRunRow, PendingApprovalRow, ToolStatRow, GovernancePageQuery, ToolCallWhere, GovernancePage, ThreadWhere, RunWhere, ApprovalWhere, GovernanceRunDetail, GovernanceThreadDetailQuery, GovernanceThreadDetail, MemoryProvider, ListMemoriesInput, MemoryRecord, ForgetMemoryInput, StoreMemoryInput, ModelPriceInput, CurrentModelPrice } from '@dudousxd/nestjs-agent-core';
3
+ import { MessageRole, ToolCallRequest, ToolResult, MessageAttachment, MessageUsage, AgentUiComponent, MessageFeedback, Actor, PageContext, QueuePause, ToolKind, ToolCallStatus, UsagePurpose, AgentStore, ThreadTurnReader, ChatQueueStore, CreateThreadInput, ThreadSummary, ThreadDetail, ThreadTurnQuery, ThreadTurnPage, ToolCallApprovalState, EnqueueMessageInput, QueuedMessage, QueuedMessagePatch, UpdateThreadInput, RecordRunStartInput, AppendMessageInput, StoredMessage, RecordToolCallInput, UpdateToolCallInput, ToolCallOutcome, RecordUsageInput, AgentGovernanceQueries, AgentPricingStore, GovernanceRange, ModelSpendRow, ActorSpendRow, ThreadSpendRow, UsageTrendPoint, ToolCallActivityRow, ThreadActivityRow, RunMetrics, RunAgentBreakdownRow, RunErrorBreakdownRow, RunTrendPoint, RecentRunRow, PendingApprovalRow, ToolStatRow, GovernancePageQuery, ToolCallWhere, GovernancePage, ThreadWhere, RunWhere, ApprovalWhere, GovernanceRunDetail, GovernanceThreadDetailQuery, GovernanceThreadDetail, MemoryProvider, ListMemoriesInput, MemoryRecord, ForgetMemoryInput, StoreMemoryInput, ModelPriceInput, CurrentModelPrice, StreamFrameTable, StreamFrameRow, SqlTokenStreamSink, SqlTokenStreamSinkOptions, ConfirmTokenStore, ConfirmTokenClaim } from '@dudousxd/nestjs-agent-core';
4
4
  export { ThreadTurnPage, ThreadTurnQuery } from '@dudousxd/nestjs-agent-core';
5
5
  import { TablesRelationalConfig, SQL } from 'drizzle-orm';
6
6
  import { OnModuleInit, OnModuleDestroy, Type, DynamicModule } from '@nestjs/common';
@@ -2243,6 +2243,213 @@ declare const ragIngestionLog: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
2243
2243
  };
2244
2244
  dialect: "sqlite";
2245
2245
  }>;
2246
+ /**
2247
+ * Spent confirm tokens (`defineConfirmedTool`), one row per token, keyed by its SHA-256 — the
2248
+ * primary key is the lock that makes a confirmation single use across replicas. Only the hash, the
2249
+ * actor and the tool are kept, never an argument. `expires_at` is epoch-ms; past it the row is dead
2250
+ * weight for `DrizzleConfirmTokenStore.purgeExpired`.
2251
+ */
2252
+ declare const agentConfirmToken: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
2253
+ name: "agent_confirm_token";
2254
+ schema: undefined;
2255
+ columns: {
2256
+ hash: drizzle_orm_sqlite_core.SQLiteColumn<{
2257
+ name: "hash";
2258
+ tableName: "agent_confirm_token";
2259
+ dataType: "string";
2260
+ columnType: "SQLiteText";
2261
+ data: string;
2262
+ driverParam: string;
2263
+ notNull: true;
2264
+ hasDefault: false;
2265
+ isPrimaryKey: true;
2266
+ isAutoincrement: false;
2267
+ hasRuntimeDefault: false;
2268
+ enumValues: [string, ...string[]];
2269
+ baseColumn: never;
2270
+ identity: undefined;
2271
+ generated: undefined;
2272
+ }, {}, {
2273
+ length: number | undefined;
2274
+ }>;
2275
+ actorRef: drizzle_orm_sqlite_core.SQLiteColumn<{
2276
+ name: "actor_ref";
2277
+ tableName: "agent_confirm_token";
2278
+ dataType: "string";
2279
+ columnType: "SQLiteText";
2280
+ data: string;
2281
+ driverParam: string;
2282
+ notNull: true;
2283
+ hasDefault: false;
2284
+ isPrimaryKey: false;
2285
+ isAutoincrement: false;
2286
+ hasRuntimeDefault: false;
2287
+ enumValues: [string, ...string[]];
2288
+ baseColumn: never;
2289
+ identity: undefined;
2290
+ generated: undefined;
2291
+ }, {}, {
2292
+ length: number | undefined;
2293
+ }>;
2294
+ tool: drizzle_orm_sqlite_core.SQLiteColumn<{
2295
+ name: "tool";
2296
+ tableName: "agent_confirm_token";
2297
+ dataType: "string";
2298
+ columnType: "SQLiteText";
2299
+ data: string;
2300
+ driverParam: string;
2301
+ notNull: true;
2302
+ hasDefault: false;
2303
+ isPrimaryKey: false;
2304
+ isAutoincrement: false;
2305
+ hasRuntimeDefault: false;
2306
+ enumValues: [string, ...string[]];
2307
+ baseColumn: never;
2308
+ identity: undefined;
2309
+ generated: undefined;
2310
+ }, {}, {
2311
+ length: number | undefined;
2312
+ }>;
2313
+ expiresAt: drizzle_orm_sqlite_core.SQLiteColumn<{
2314
+ name: "expires_at";
2315
+ tableName: "agent_confirm_token";
2316
+ dataType: "number";
2317
+ columnType: "SQLiteInteger";
2318
+ data: number;
2319
+ driverParam: number;
2320
+ notNull: true;
2321
+ hasDefault: false;
2322
+ isPrimaryKey: false;
2323
+ isAutoincrement: false;
2324
+ hasRuntimeDefault: false;
2325
+ enumValues: undefined;
2326
+ baseColumn: never;
2327
+ identity: undefined;
2328
+ generated: undefined;
2329
+ }, {}, {}>;
2330
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
2331
+ name: "created_at";
2332
+ tableName: "agent_confirm_token";
2333
+ dataType: "number";
2334
+ columnType: "SQLiteInteger";
2335
+ data: number;
2336
+ driverParam: number;
2337
+ notNull: true;
2338
+ hasDefault: false;
2339
+ isPrimaryKey: false;
2340
+ isAutoincrement: false;
2341
+ hasRuntimeDefault: false;
2342
+ enumValues: undefined;
2343
+ baseColumn: never;
2344
+ identity: undefined;
2345
+ generated: undefined;
2346
+ }, {}, {}>;
2347
+ };
2348
+ dialect: "sqlite";
2349
+ }>;
2350
+ /**
2351
+ * One row per frame of a run's live stream (`DrizzleTokenStreamSink`), numbered per run from 1 with
2352
+ * no gaps. `frame` is one NDJSON line; `null` marks the end, with `error` set when the run failed.
2353
+ * `created_at` (epoch-ms) is what the TTL counts from — a run's LAST row.
2354
+ */
2355
+ declare const agentStreamFrame: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
2356
+ name: "agent_stream_frame";
2357
+ schema: undefined;
2358
+ columns: {
2359
+ runId: drizzle_orm_sqlite_core.SQLiteColumn<{
2360
+ name: "run_id";
2361
+ tableName: "agent_stream_frame";
2362
+ dataType: "string";
2363
+ columnType: "SQLiteText";
2364
+ data: string;
2365
+ driverParam: string;
2366
+ notNull: true;
2367
+ hasDefault: false;
2368
+ isPrimaryKey: false;
2369
+ isAutoincrement: false;
2370
+ hasRuntimeDefault: false;
2371
+ enumValues: [string, ...string[]];
2372
+ baseColumn: never;
2373
+ identity: undefined;
2374
+ generated: undefined;
2375
+ }, {}, {
2376
+ length: number | undefined;
2377
+ }>;
2378
+ seq: drizzle_orm_sqlite_core.SQLiteColumn<{
2379
+ name: "seq";
2380
+ tableName: "agent_stream_frame";
2381
+ dataType: "number";
2382
+ columnType: "SQLiteInteger";
2383
+ data: number;
2384
+ driverParam: number;
2385
+ notNull: true;
2386
+ hasDefault: false;
2387
+ isPrimaryKey: false;
2388
+ isAutoincrement: false;
2389
+ hasRuntimeDefault: false;
2390
+ enumValues: undefined;
2391
+ baseColumn: never;
2392
+ identity: undefined;
2393
+ generated: undefined;
2394
+ }, {}, {}>;
2395
+ frame: drizzle_orm_sqlite_core.SQLiteColumn<{
2396
+ name: "frame";
2397
+ tableName: "agent_stream_frame";
2398
+ dataType: "string";
2399
+ columnType: "SQLiteText";
2400
+ data: string;
2401
+ driverParam: string;
2402
+ notNull: false;
2403
+ hasDefault: false;
2404
+ isPrimaryKey: false;
2405
+ isAutoincrement: false;
2406
+ hasRuntimeDefault: false;
2407
+ enumValues: [string, ...string[]];
2408
+ baseColumn: never;
2409
+ identity: undefined;
2410
+ generated: undefined;
2411
+ }, {}, {
2412
+ length: number | undefined;
2413
+ }>;
2414
+ error: drizzle_orm_sqlite_core.SQLiteColumn<{
2415
+ name: "error";
2416
+ tableName: "agent_stream_frame";
2417
+ dataType: "string";
2418
+ columnType: "SQLiteText";
2419
+ data: string;
2420
+ driverParam: string;
2421
+ notNull: false;
2422
+ hasDefault: false;
2423
+ isPrimaryKey: false;
2424
+ isAutoincrement: false;
2425
+ hasRuntimeDefault: false;
2426
+ enumValues: [string, ...string[]];
2427
+ baseColumn: never;
2428
+ identity: undefined;
2429
+ generated: undefined;
2430
+ }, {}, {
2431
+ length: number | undefined;
2432
+ }>;
2433
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
2434
+ name: "created_at";
2435
+ tableName: "agent_stream_frame";
2436
+ dataType: "number";
2437
+ columnType: "SQLiteInteger";
2438
+ data: number;
2439
+ driverParam: number;
2440
+ notNull: true;
2441
+ hasDefault: false;
2442
+ isPrimaryKey: false;
2443
+ isAutoincrement: false;
2444
+ hasRuntimeDefault: false;
2445
+ enumValues: undefined;
2446
+ baseColumn: never;
2447
+ identity: undefined;
2448
+ generated: undefined;
2449
+ }, {}, {}>;
2450
+ };
2451
+ dialect: "sqlite";
2452
+ }>;
2246
2453
  /** The tables this store owns, as one schema object, ready for `drizzle(client, { schema })`. */
2247
2454
  declare const agentSchema: {
2248
2455
  agentThread: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
@@ -4401,6 +4608,104 @@ declare const agentSchema: {
4401
4608
  };
4402
4609
  dialect: "sqlite";
4403
4610
  }>;
4611
+ agentConfirmToken: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
4612
+ name: "agent_confirm_token";
4613
+ schema: undefined;
4614
+ columns: {
4615
+ hash: drizzle_orm_sqlite_core.SQLiteColumn<{
4616
+ name: "hash";
4617
+ tableName: "agent_confirm_token";
4618
+ dataType: "string";
4619
+ columnType: "SQLiteText";
4620
+ data: string;
4621
+ driverParam: string;
4622
+ notNull: true;
4623
+ hasDefault: false;
4624
+ isPrimaryKey: true;
4625
+ isAutoincrement: false;
4626
+ hasRuntimeDefault: false;
4627
+ enumValues: [string, ...string[]];
4628
+ baseColumn: never;
4629
+ identity: undefined;
4630
+ generated: undefined;
4631
+ }, {}, {
4632
+ length: number | undefined;
4633
+ }>;
4634
+ actorRef: drizzle_orm_sqlite_core.SQLiteColumn<{
4635
+ name: "actor_ref";
4636
+ tableName: "agent_confirm_token";
4637
+ dataType: "string";
4638
+ columnType: "SQLiteText";
4639
+ data: string;
4640
+ driverParam: string;
4641
+ notNull: true;
4642
+ hasDefault: false;
4643
+ isPrimaryKey: false;
4644
+ isAutoincrement: false;
4645
+ hasRuntimeDefault: false;
4646
+ enumValues: [string, ...string[]];
4647
+ baseColumn: never;
4648
+ identity: undefined;
4649
+ generated: undefined;
4650
+ }, {}, {
4651
+ length: number | undefined;
4652
+ }>;
4653
+ tool: drizzle_orm_sqlite_core.SQLiteColumn<{
4654
+ name: "tool";
4655
+ tableName: "agent_confirm_token";
4656
+ dataType: "string";
4657
+ columnType: "SQLiteText";
4658
+ data: string;
4659
+ driverParam: string;
4660
+ notNull: true;
4661
+ hasDefault: false;
4662
+ isPrimaryKey: false;
4663
+ isAutoincrement: false;
4664
+ hasRuntimeDefault: false;
4665
+ enumValues: [string, ...string[]];
4666
+ baseColumn: never;
4667
+ identity: undefined;
4668
+ generated: undefined;
4669
+ }, {}, {
4670
+ length: number | undefined;
4671
+ }>;
4672
+ expiresAt: drizzle_orm_sqlite_core.SQLiteColumn<{
4673
+ name: "expires_at";
4674
+ tableName: "agent_confirm_token";
4675
+ dataType: "number";
4676
+ columnType: "SQLiteInteger";
4677
+ data: number;
4678
+ driverParam: number;
4679
+ notNull: true;
4680
+ hasDefault: false;
4681
+ isPrimaryKey: false;
4682
+ isAutoincrement: false;
4683
+ hasRuntimeDefault: false;
4684
+ enumValues: undefined;
4685
+ baseColumn: never;
4686
+ identity: undefined;
4687
+ generated: undefined;
4688
+ }, {}, {}>;
4689
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
4690
+ name: "created_at";
4691
+ tableName: "agent_confirm_token";
4692
+ dataType: "number";
4693
+ columnType: "SQLiteInteger";
4694
+ data: number;
4695
+ driverParam: number;
4696
+ notNull: true;
4697
+ hasDefault: false;
4698
+ isPrimaryKey: false;
4699
+ isAutoincrement: false;
4700
+ hasRuntimeDefault: false;
4701
+ enumValues: undefined;
4702
+ baseColumn: never;
4703
+ identity: undefined;
4704
+ generated: undefined;
4705
+ }, {}, {}>;
4706
+ };
4707
+ dialect: "sqlite";
4708
+ }>;
4404
4709
  };
4405
4710
  /**
4406
4711
  * The dialect-portable Drizzle SQLite database handle the store operates on. Accepts any SQLite
@@ -4745,6 +5050,53 @@ declare class DrizzlePricingStore implements AgentPricingStore {
4745
5050
  listCurrentPrices(): Promise<CurrentModelPrice[]>;
4746
5051
  }
4747
5052
 
5053
+ /** {@link StreamFrameTable} over `agent_stream_frame`, through a Drizzle SQLite handle. */
5054
+ declare class DrizzleStreamFrameTable implements StreamFrameTable {
5055
+ private readonly db;
5056
+ constructor(db: AgentDrizzleDb);
5057
+ append(runId: string, row: {
5058
+ frame: string | null;
5059
+ error: string | null;
5060
+ createdAt: number;
5061
+ }): Promise<void>;
5062
+ read(runId: string, after: number, limit: number): Promise<StreamFrameRow[]>;
5063
+ has(runId: string): Promise<boolean>;
5064
+ remove(runIds: readonly string[]): Promise<void>;
5065
+ lapsedRuns(cutoff: number): Promise<string[]>;
5066
+ isUniqueViolation(error: unknown): boolean;
5067
+ }
5068
+ /**
5069
+ * A multi-replica `TokenStreamSink` over the app's Drizzle database — several replicas, no Redis.
5070
+ * Polled, with streamed text coalesced into one row per `flushMs`; see `SqlTokenStreamSink` for the
5071
+ * trade-offs. The `agent_stream_frame` table comes from `ensureAgentSchema` (or your migration).
5072
+ *
5073
+ * ```ts
5074
+ * AgentModule.forRoot({ model, sink: new DrizzleTokenStreamSink(db) });
5075
+ * ```
5076
+ */
5077
+ declare class DrizzleTokenStreamSink extends SqlTokenStreamSink {
5078
+ constructor(db: AgentDrizzleDb, options?: SqlTokenStreamSinkOptions);
5079
+ }
5080
+
5081
+ /**
5082
+ * A production `ConfirmTokenStore` (`defineConfirmedTool`) over the `agent_confirm_token` table —
5083
+ * what makes a confirmed write single use across replicas.
5084
+ *
5085
+ * `claim` is one `INSERT … ON CONFLICT DO NOTHING RETURNING`, so the primary key is the lock: of two
5086
+ * concurrent confirmations one inserts and the other touches no row. A statement that does not FAIL
5087
+ * on the duplicate, rather than an insert whose violation is caught, so it never aborts a
5088
+ * surrounding transaction. Only the token's SHA-256, the actor and the tool name are stored; call
5089
+ * {@link purgeExpired} from a scheduled job to drop the dead rows. The table comes from
5090
+ * `ensureAgentSchema` (or your own migration).
5091
+ */
5092
+ declare class DrizzleConfirmTokenStore implements ConfirmTokenStore {
5093
+ private readonly db;
5094
+ constructor(db: AgentDrizzleDb);
5095
+ claim(input: ConfirmTokenClaim): Promise<boolean>;
5096
+ release(hash: string): Promise<void>;
5097
+ purgeExpired(now?: number): Promise<number>;
5098
+ }
5099
+
4748
5100
  /**
4749
5101
  * The paging order: newest first, tiebroken on the primary key.
4750
5102
  *
@@ -4956,7 +5308,8 @@ interface DrizzleAgentStoreModuleOptions {
4956
5308
  * Binds {@link DrizzleAgentStore} to the {@link AGENT_STORE} token consumed by
4957
5309
  * `@dudousxd/nestjs-agent`, plus {@link DrizzleGovernanceQueries} to
4958
5310
  * {@link AGENT_GOVERNANCE_QUERIES} (the read-model the dashboard/telescope surfaces consume) and
4959
- * {@link DrizzlePricingStore} to {@link AGENT_PRICING_STORE} (the write side of that pricing table).
5311
+ * {@link DrizzlePricingStore} to {@link AGENT_PRICING_STORE} (the write side of that pricing table),
5312
+ * and {@link DrizzleConfirmTokenStore} to {@link AGENT_CONFIRM_TOKEN_STORE} (confirmed writes).
4960
5313
  * The host app supplies an already-opened Drizzle db — this module never opens a connection itself.
4961
5314
  *
4962
5315
  * The returned module is global, so {@link AGENT_STORE}, {@link AGENT_GOVERNANCE_QUERIES} and
@@ -4973,4 +5326,4 @@ declare class DrizzleAgentStoreModule {
4973
5326
  static forRoot(options: DrizzleAgentStoreModuleOptions): DynamicModule;
4974
5327
  }
4975
5328
 
4976
- export { type AgentDrizzleDb, type AgentMemoryRow, type AgentMessageRow, type AgentQueuedMessageRow, type AgentRunRow, type AgentRunStatus, type AgentThreadRow, DrizzleAgentStore, DrizzleAgentStoreModule, type DrizzleAgentStoreModuleOptions, DrizzleGovernanceQueries, DrizzleMemoryProvider, DrizzlePricingStore, DrizzleRagIngestionLog, RAG_INGESTION_LOG_PAGE_ORDER, type RagIngestionLogCursor, type RagIngestionLogIterateOptions, type RagIngestionLogQuery, type RagIngestionLogRow, type RagIngestionLogWhere, type RagIngestionStatus, agentMemory, agentMessage, agentModelPricing, agentQueuedMessage, agentRun, agentSchema, agentThread, agentTokenUsage, agentToolCall, ensureAgentSchema, ragIngestionLog };
5329
+ export { type AgentDrizzleDb, type AgentMemoryRow, type AgentMessageRow, type AgentQueuedMessageRow, type AgentRunRow, type AgentRunStatus, type AgentThreadRow, DrizzleAgentStore, DrizzleAgentStoreModule, type DrizzleAgentStoreModuleOptions, DrizzleConfirmTokenStore, DrizzleGovernanceQueries, DrizzleMemoryProvider, DrizzlePricingStore, DrizzleRagIngestionLog, DrizzleStreamFrameTable, DrizzleTokenStreamSink, RAG_INGESTION_LOG_PAGE_ORDER, type RagIngestionLogCursor, type RagIngestionLogIterateOptions, type RagIngestionLogQuery, type RagIngestionLogRow, type RagIngestionLogWhere, type RagIngestionStatus, agentConfirmToken, agentMemory, agentMessage, agentModelPricing, agentQueuedMessage, agentRun, agentSchema, agentStreamFrame, agentThread, agentTokenUsage, agentToolCall, ensureAgentSchema, ragIngestionLog };
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/schema.ts
5
- import { index, integer, real, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
5
+ import { index, integer, primaryKey, real, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
6
6
  var agentThread = sqliteTable("agent_thread", {
7
7
  id: text("id").primaryKey(),
8
8
  actorRef: text("actor_ref").notNull(),
@@ -266,6 +266,29 @@ var ragIngestionLog = sqliteTable("rag_ingestion_log", {
266
266
  }, (table) => [
267
267
  index("rag_ingestion_log_collection_idx").on(table.collection, table.updatedAt)
268
268
  ]);
269
+ var agentConfirmToken = sqliteTable("agent_confirm_token", {
270
+ hash: text("hash").primaryKey(),
271
+ actorRef: text("actor_ref").notNull(),
272
+ tool: text("tool").notNull(),
273
+ expiresAt: integer("expires_at").notNull(),
274
+ createdAt: integer("created_at").notNull()
275
+ }, (table) => [
276
+ index("agent_confirm_token_expires_idx").on(table.expiresAt)
277
+ ]);
278
+ var agentStreamFrame = sqliteTable("agent_stream_frame", {
279
+ runId: text("run_id").notNull(),
280
+ seq: integer("seq").notNull(),
281
+ frame: text("frame"),
282
+ error: text("error"),
283
+ createdAt: integer("created_at").notNull()
284
+ }, (table) => [
285
+ primaryKey({
286
+ columns: [
287
+ table.runId,
288
+ table.seq
289
+ ]
290
+ })
291
+ ]);
269
292
  var agentSchema = {
270
293
  agentThread,
271
294
  agentMessage,
@@ -275,7 +298,8 @@ var agentSchema = {
275
298
  agentModelPricing,
276
299
  agentRun,
277
300
  agentMemory,
278
- ragIngestionLog
301
+ ragIngestionLog,
302
+ agentConfirmToken
279
303
  };
280
304
 
281
305
  // src/ensure-schema.ts
@@ -430,7 +454,24 @@ var statements = [
430
454
  updated_at INTEGER NOT NULL
431
455
  )`,
432
456
  `CREATE INDEX IF NOT EXISTS rag_ingestion_log_collection_idx
433
- ON rag_ingestion_log (collection, updated_at)`
457
+ ON rag_ingestion_log (collection, updated_at)`,
458
+ `CREATE TABLE IF NOT EXISTS agent_stream_frame (
459
+ run_id TEXT NOT NULL,
460
+ seq INTEGER NOT NULL,
461
+ frame TEXT,
462
+ error TEXT,
463
+ created_at INTEGER NOT NULL,
464
+ PRIMARY KEY (run_id, seq)
465
+ )`,
466
+ `CREATE TABLE IF NOT EXISTS agent_confirm_token (
467
+ hash TEXT PRIMARY KEY NOT NULL,
468
+ actor_ref TEXT NOT NULL,
469
+ tool TEXT NOT NULL,
470
+ expires_at INTEGER NOT NULL,
471
+ created_at INTEGER NOT NULL
472
+ )`,
473
+ `CREATE INDEX IF NOT EXISTS agent_confirm_token_expires_idx
474
+ ON agent_confirm_token (expires_at)`
434
475
  ];
435
476
  var additiveColumns = [
436
477
  {
@@ -2131,10 +2172,106 @@ var DrizzlePricingStore = class {
2131
2172
  }
2132
2173
  };
2133
2174
 
2175
+ // src/drizzle-token-stream-sink.ts
2176
+ import { SqlTokenStreamSink } from "@dudousxd/nestjs-agent-core";
2177
+ import { and as and5, asc as asc3, eq as eq5, gt, inArray as inArray4, lt, max as max2, sql as sql4 } from "drizzle-orm";
2178
+ function isUniqueViolation(error) {
2179
+ for (let current = error; current !== null && typeof current === "object"; ) {
2180
+ const code = current.code;
2181
+ if (typeof code === "string" && code.startsWith("SQLITE_CONSTRAINT")) return true;
2182
+ current = current.cause;
2183
+ }
2184
+ return false;
2185
+ }
2186
+ __name(isUniqueViolation, "isUniqueViolation");
2187
+ var DrizzleStreamFrameTable = class {
2188
+ static {
2189
+ __name(this, "DrizzleStreamFrameTable");
2190
+ }
2191
+ db;
2192
+ constructor(db) {
2193
+ this.db = db;
2194
+ }
2195
+ async append(runId, row) {
2196
+ await this.db.run(sql4`INSERT INTO agent_stream_frame (run_id, seq, frame, error, created_at)
2197
+ SELECT ${runId}, COALESCE(MAX(seq), 0) + 1, ${row.frame}, ${row.error}, ${row.createdAt}
2198
+ FROM agent_stream_frame WHERE run_id = ${runId}`);
2199
+ }
2200
+ async read(runId, after, limit) {
2201
+ return this.db.select({
2202
+ seq: agentStreamFrame.seq,
2203
+ frame: agentStreamFrame.frame,
2204
+ error: agentStreamFrame.error
2205
+ }).from(agentStreamFrame).where(and5(eq5(agentStreamFrame.runId, runId), gt(agentStreamFrame.seq, after))).orderBy(asc3(agentStreamFrame.seq)).limit(limit);
2206
+ }
2207
+ async has(runId) {
2208
+ const rows = await this.db.select({
2209
+ seq: agentStreamFrame.seq
2210
+ }).from(agentStreamFrame).where(eq5(agentStreamFrame.runId, runId)).limit(1);
2211
+ return rows.length > 0;
2212
+ }
2213
+ async remove(runIds) {
2214
+ if (runIds.length === 0) return;
2215
+ await this.db.delete(agentStreamFrame).where(inArray4(agentStreamFrame.runId, [
2216
+ ...runIds
2217
+ ]));
2218
+ }
2219
+ async lapsedRuns(cutoff) {
2220
+ const rows = await this.db.select({
2221
+ runId: agentStreamFrame.runId
2222
+ }).from(agentStreamFrame).groupBy(agentStreamFrame.runId).having(lt(max2(agentStreamFrame.createdAt), cutoff));
2223
+ return rows.map((row) => row.runId);
2224
+ }
2225
+ isUniqueViolation(error) {
2226
+ return isUniqueViolation(error);
2227
+ }
2228
+ };
2229
+ var DrizzleTokenStreamSink = class extends SqlTokenStreamSink {
2230
+ static {
2231
+ __name(this, "DrizzleTokenStreamSink");
2232
+ }
2233
+ constructor(db, options = {}) {
2234
+ super(new DrizzleStreamFrameTable(db), options);
2235
+ }
2236
+ };
2237
+
2238
+ // src/drizzle-confirm-token-store.ts
2239
+ import { eq as eq6, lt as lt2 } from "drizzle-orm";
2240
+ var DrizzleConfirmTokenStore = class {
2241
+ static {
2242
+ __name(this, "DrizzleConfirmTokenStore");
2243
+ }
2244
+ db;
2245
+ constructor(db) {
2246
+ this.db = db;
2247
+ }
2248
+ async claim(input) {
2249
+ const inserted = await this.db.insert(agentConfirmToken).values({
2250
+ hash: input.hash,
2251
+ actorRef: input.actorRef,
2252
+ tool: input.tool,
2253
+ expiresAt: input.expiresAt,
2254
+ createdAt: Date.now()
2255
+ }).onConflictDoNothing().returning({
2256
+ hash: agentConfirmToken.hash
2257
+ });
2258
+ return inserted.length === 1;
2259
+ }
2260
+ async release(hash) {
2261
+ await this.db.delete(agentConfirmToken).where(eq6(agentConfirmToken.hash, hash));
2262
+ }
2263
+ async purgeExpired(now = Date.now()) {
2264
+ const purged = await this.db.delete(agentConfirmToken).where(lt2(agentConfirmToken.expiresAt, now)).returning({
2265
+ hash: agentConfirmToken.hash
2266
+ });
2267
+ return purged.length;
2268
+ }
2269
+ };
2270
+
2134
2271
  // src/drizzle-rag-ingestion-log.ts
2135
2272
  import { subscribe, unsubscribe } from "diagnostics_channel";
2136
2273
  import { Injectable, Logger } from "@nestjs/common";
2137
- import { and as and5, asc as asc3, count as count2, desc as desc3, eq as eq5, gt, lt, or as or2 } from "drizzle-orm";
2274
+ import { and as and6, asc as asc4, count as count2, desc as desc3, eq as eq7, gt as gt2, lt as lt3, or as or2 } from "drizzle-orm";
2138
2275
  function _ts_decorate(decorators, target, key, desc4) {
2139
2276
  var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
2140
2277
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -2183,7 +2320,7 @@ function num(value) {
2183
2320
  __name(num, "num");
2184
2321
  var RAG_INGESTION_LOG_PAGE_ORDER = [
2185
2322
  desc3(ragIngestionLog.updatedAt),
2186
- asc3(ragIngestionLog.documentId)
2323
+ asc4(ragIngestionLog.documentId)
2187
2324
  ];
2188
2325
  var DEFAULT_PAGE_SIZE = 200;
2189
2326
  var DEFAULT_BATCH_SIZE = 200;
@@ -2326,19 +2463,19 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2326
2463
  }
2327
2464
  /** The latest recorded outcome for one document, or null if it was never attempted. */
2328
2465
  async get(documentId) {
2329
- const [row] = await this.db.select().from(ragIngestionLog).where(eq5(ragIngestionLog.documentId, documentId));
2466
+ const [row] = await this.db.select().from(ragIngestionLog).where(eq7(ragIngestionLog.documentId, documentId));
2330
2467
  return row ?? null;
2331
2468
  }
2332
2469
  /** Forget one document's record. Returns whether a row was actually removed. */
2333
2470
  async remove(documentId) {
2334
- const removed = await this.db.delete(ragIngestionLog).where(eq5(ragIngestionLog.documentId, documentId)).returning({
2471
+ const removed = await this.db.delete(ragIngestionLog).where(eq7(ragIngestionLog.documentId, documentId)).returning({
2335
2472
  documentId: ragIngestionLog.documentId
2336
2473
  });
2337
2474
  return removed.length > 0;
2338
2475
  }
2339
2476
  /** Forget every record for a collection — for when the collection itself is deleted. */
2340
2477
  async removeByCollection(collection) {
2341
- const removed = await this.db.delete(ragIngestionLog).where(eq5(ragIngestionLog.collection, collection)).returning({
2478
+ const removed = await this.db.delete(ragIngestionLog).where(eq7(ragIngestionLog.collection, collection)).returning({
2342
2479
  documentId: ragIngestionLog.documentId
2343
2480
  });
2344
2481
  return removed.length;
@@ -2370,7 +2507,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2370
2507
  }
2371
2508
  }
2372
2509
  where(query) {
2373
- return and5(query.collection !== void 0 ? eq5(ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? eq5(ragIngestionLog.status, query.status) : void 0);
2510
+ return and6(query.collection !== void 0 ? eq7(ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? eq7(ragIngestionLog.status, query.status) : void 0);
2374
2511
  }
2375
2512
  /**
2376
2513
  * The coordinates filter AND'd with "strictly after `cursor` in
@@ -2385,7 +2522,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2385
2522
  if (cursor === void 0) {
2386
2523
  return base;
2387
2524
  }
2388
- return and5(base, or2(lt(ragIngestionLog.updatedAt, cursor.updatedAt), and5(eq5(ragIngestionLog.updatedAt, cursor.updatedAt), gt(ragIngestionLog.documentId, cursor.documentId))));
2525
+ return and6(base, or2(lt3(ragIngestionLog.updatedAt, cursor.updatedAt), and6(eq7(ragIngestionLog.updatedAt, cursor.updatedAt), gt2(ragIngestionLog.documentId, cursor.documentId))));
2389
2526
  }
2390
2527
  /**
2391
2528
  * Upsert one outcome. Keyed by document id so the row always reflects the *current* state — a
@@ -2461,7 +2598,7 @@ DrizzleRagIngestionLog = _ts_decorate([
2461
2598
  ], DrizzleRagIngestionLog);
2462
2599
 
2463
2600
  // src/drizzle-agent-store.module.ts
2464
- import { AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, AGENT_STORE } from "@dudousxd/nestjs-agent-core";
2601
+ import { AGENT_CONFIRM_TOKEN_STORE, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, AGENT_STORE } from "@dudousxd/nestjs-agent-core";
2465
2602
  import { Module } from "@nestjs/common";
2466
2603
  function _ts_decorate2(decorators, target, key, desc4) {
2467
2604
  var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
@@ -2531,6 +2668,15 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
2531
2668
  {
2532
2669
  provide: AGENT_GOVERNANCE_QUERIES,
2533
2670
  useExisting: DrizzleGovernanceQueries
2671
+ },
2672
+ // What makes a `defineConfirmedTool` confirmation single use across replicas.
2673
+ {
2674
+ provide: DrizzleConfirmTokenStore,
2675
+ useFactory: /* @__PURE__ */ __name(() => new DrizzleConfirmTokenStore(options.db), "useFactory")
2676
+ },
2677
+ {
2678
+ provide: AGENT_CONFIRM_TOKEN_STORE,
2679
+ useExisting: DrizzleConfirmTokenStore
2534
2680
  }
2535
2681
  ],
2536
2682
  exports: [
@@ -2543,7 +2689,9 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
2543
2689
  DrizzleGovernanceQueries,
2544
2690
  AGENT_GOVERNANCE_QUERIES,
2545
2691
  DrizzlePricingStore,
2546
- AGENT_PRICING_STORE
2692
+ AGENT_PRICING_STORE,
2693
+ DrizzleConfirmTokenStore,
2694
+ AGENT_CONFIRM_TOKEN_STORE
2547
2695
  ]
2548
2696
  };
2549
2697
  }
@@ -2554,17 +2702,22 @@ DrizzleAgentStoreModule = _ts_decorate2([
2554
2702
  export {
2555
2703
  DrizzleAgentStore,
2556
2704
  DrizzleAgentStoreModule,
2705
+ DrizzleConfirmTokenStore,
2557
2706
  DrizzleGovernanceQueries,
2558
2707
  DrizzleMemoryProvider,
2559
2708
  DrizzlePricingStore,
2560
2709
  DrizzleRagIngestionLog,
2710
+ DrizzleStreamFrameTable,
2711
+ DrizzleTokenStreamSink,
2561
2712
  RAG_INGESTION_LOG_PAGE_ORDER,
2713
+ agentConfirmToken,
2562
2714
  agentMemory,
2563
2715
  agentMessage,
2564
2716
  agentModelPricing,
2565
2717
  agentQueuedMessage,
2566
2718
  agentRun,
2567
2719
  agentSchema,
2720
+ agentStreamFrame,
2568
2721
  agentThread,
2569
2722
  agentTokenUsage,
2570
2723
  agentToolCall,