@dudousxd/nestjs-agent-store-drizzle 0.23.0 → 0.25.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.js CHANGED
@@ -40,6 +40,7 @@ var agentMessage = sqliteTable("agent_message", {
40
40
  onDelete: "cascade"
41
41
  }),
42
42
  role: text("role").$type().notNull(),
43
+ actionProposalOutcome: text("action_proposal_outcome"),
43
44
  content: text("content").notNull(),
44
45
  toolCalls: text("tool_calls", {
45
46
  mode: "json"
@@ -71,6 +72,12 @@ var agentMessage = sqliteTable("agent_message", {
71
72
  feedback: text("feedback", {
72
73
  mode: "json"
73
74
  }).$type(),
75
+ /**
76
+ * The message's place in its thread, 1-based, assigned on append — what orders a transcript.
77
+ * `created_at` cannot: two messages of one turn routinely share a timestamp, and the uuid that
78
+ * broke the tie is random. `null` on a row from before the column; those sort first.
79
+ */
80
+ seq: integer("seq"),
74
81
  createdAt: integer("created_at", {
75
82
  mode: "timestamp_ms"
76
83
  }).notNull()
@@ -78,6 +85,7 @@ var agentMessage = sqliteTable("agent_message", {
78
85
  index("agent_message_thread_created_idx").on(table.threadId, table.createdAt)
79
86
  ]);
80
87
  var agentToolCall = sqliteTable("agent_tool_call", {
88
+ proposalId: text("proposal_id"),
81
89
  id: text("id").primaryKey(),
82
90
  messageId: text("message_id").notNull().references(() => agentMessage.id, {
83
91
  onDelete: "cascade"
@@ -102,6 +110,10 @@ var agentToolCall = sqliteTable("agent_tool_call", {
102
110
  }),
103
111
  /** The run (turn) this call belongs to, for a trace deep-link; null for a pre-rollout row. */
104
112
  runId: text("run_id"),
113
+ /** Resolved per-call wording; null falls back to presentation templates. */
114
+ confirmation: text("confirmation", {
115
+ mode: "json"
116
+ }).$type(),
105
117
  /** Who had to approve it (`requester` or a role); null for a call no policy put to anyone. */
106
118
  approver: text("approver"),
107
119
  /** When the approval request lapses; null → never. */
@@ -118,6 +130,9 @@ var agentToolCall = sqliteTable("agent_tool_call", {
118
130
  index("agent_tool_call_message_idx").on(table.messageId)
119
131
  ]);
120
132
  var agentQueuedMessage = sqliteTable("agent_queued_message", {
133
+ uiCapabilities: text("ui_capabilities", {
134
+ mode: "json"
135
+ }).$type(),
121
136
  id: text("id").primaryKey(),
122
137
  threadId: text("thread_id").notNull().references(() => agentThread.id, {
123
138
  onDelete: "cascade"
@@ -295,7 +310,35 @@ var agentStreamFrame = sqliteTable("agent_stream_frame", {
295
310
  ]
296
311
  })
297
312
  ]);
313
+ var agentActionProposal = sqliteTable("agent_action_proposal", {
314
+ id: text("id").primaryKey(),
315
+ scopeKey: text("scope_key").notNull(),
316
+ decision: text("decision").$type().notNull(),
317
+ logicalSort: text("logical_sort").notNull(),
318
+ createFingerprint: text("create_fingerprint").notNull(),
319
+ proposal: text("proposal", {
320
+ mode: "json"
321
+ }).$type().notNull(),
322
+ version: integer("version").notNull().default(0),
323
+ executionStatus: text("execution_status").$type(),
324
+ leaseExpiresAt: integer("lease_expires_at"),
325
+ deliveryStatus: text("delivery_status"),
326
+ deliveryLeaseExpiresAt: integer("delivery_lease_expires_at"),
327
+ replacementGroupKey: text("replacement_group_key"),
328
+ outcomeIdKey: text("outcome_id_key"),
329
+ proposalExpiresAt: integer("proposal_expires_at"),
330
+ discoveryIndexVersion: integer("discovery_index_version").notNull().default(0),
331
+ createdAt: integer("created_at").notNull()
332
+ }, (table) => [
333
+ index("agent_action_proposal_execution_idx").on(table.discoveryIndexVersion, table.executionStatus, table.leaseExpiresAt, table.createdAt),
334
+ index("agent_action_proposal_expiry_idx").on(table.discoveryIndexVersion, table.decision, table.proposalExpiresAt, table.createdAt),
335
+ index("agent_action_proposal_replacement_idx").on(table.scopeKey, table.replacementGroupKey, table.decision),
336
+ index("agent_action_proposal_delivery_idx").on(table.deliveryStatus, table.deliveryLeaseExpiresAt, table.createdAt),
337
+ uniqueIndex("agent_action_proposal_outcome_idx").on(table.outcomeIdKey),
338
+ index("agent_action_proposal_scope_idx").on(table.scopeKey, table.createdAt, table.id)
339
+ ]);
298
340
  var agentSchema = {
341
+ agentActionProposal,
299
342
  agentThread,
300
343
  agentMessage,
301
344
  agentQueuedMessage,
@@ -305,303 +348,1375 @@ var agentSchema = {
305
348
  agentRun,
306
349
  agentMemory,
307
350
  ragIngestionLog,
308
- agentConfirmToken
351
+ agentConfirmToken,
352
+ agentStreamFrame
309
353
  };
310
354
 
311
355
  // src/ensure-schema.ts
312
- import { sql } from "drizzle-orm";
313
- var statements = [
314
- `CREATE TABLE IF NOT EXISTS agent_thread (
315
- id TEXT PRIMARY KEY NOT NULL,
316
- actor_ref TEXT NOT NULL,
317
- tenant_ref TEXT,
318
- title TEXT NOT NULL,
319
- transient INTEGER NOT NULL DEFAULT 0,
320
- active_stream_id TEXT,
321
- default_agent TEXT,
322
- model TEXT,
323
- persona TEXT,
324
- queue_pause TEXT,
325
- created_at INTEGER NOT NULL,
326
- updated_at INTEGER NOT NULL,
327
- deleted_at INTEGER
328
- )`,
329
- `CREATE INDEX IF NOT EXISTS agent_thread_actor_updated_idx
330
- ON agent_thread (actor_ref, updated_at)`,
331
- `CREATE TABLE IF NOT EXISTS agent_message (
332
- id TEXT PRIMARY KEY NOT NULL,
333
- thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,
334
- role TEXT NOT NULL,
335
- content TEXT NOT NULL,
336
- tool_calls TEXT,
337
- tool_results TEXT,
338
- attachments TEXT,
339
- follow_ups TEXT,
340
- usage TEXT,
341
- agent_name TEXT,
342
- persona TEXT,
343
- run_id TEXT,
344
- reasoning TEXT,
345
- reasoning_ms INTEGER,
346
- ui TEXT,
347
- feedback TEXT,
348
- created_at INTEGER NOT NULL
349
- )`,
350
- `CREATE INDEX IF NOT EXISTS agent_message_thread_created_idx
351
- ON agent_message (thread_id, created_at)`,
352
- `CREATE TABLE IF NOT EXISTS agent_queued_message (
353
- id TEXT PRIMARY KEY NOT NULL,
354
- thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,
355
- actor TEXT NOT NULL,
356
- content TEXT NOT NULL,
357
- attachments TEXT,
358
- agent_name TEXT,
359
- persona TEXT,
360
- model TEXT,
361
- page_context TEXT,
362
- interrupt INTEGER NOT NULL DEFAULT 0,
363
- position INTEGER NOT NULL,
364
- created_at INTEGER NOT NULL,
365
- updated_at INTEGER NOT NULL
366
- )`,
367
- `CREATE INDEX IF NOT EXISTS agent_queued_message_thread_position_idx
368
- ON agent_queued_message (thread_id, position)`,
369
- `CREATE TABLE IF NOT EXISTS agent_tool_call (
370
- id TEXT PRIMARY KEY NOT NULL,
371
- message_id TEXT NOT NULL REFERENCES agent_message(id) ON DELETE CASCADE,
372
- tool_name TEXT NOT NULL,
373
- tool_type TEXT NOT NULL,
374
- input TEXT,
375
- output TEXT,
376
- status TEXT NOT NULL,
377
- executed_by_ref TEXT,
378
- execution_ms INTEGER,
379
- error TEXT,
380
- created_at INTEGER NOT NULL,
381
- executed_at INTEGER,
382
- run_id TEXT,
383
- approver TEXT,
384
- expires_at INTEGER,
385
- remember INTEGER,
386
- decided_via TEXT
387
- )`,
388
- `CREATE INDEX IF NOT EXISTS agent_tool_call_message_idx
389
- ON agent_tool_call (message_id)`,
390
- `CREATE TABLE IF NOT EXISTS agent_token_usage (
391
- id TEXT PRIMARY KEY NOT NULL,
392
- thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,
393
- actor_ref TEXT NOT NULL,
394
- message_id TEXT,
395
- model_id TEXT NOT NULL,
396
- purpose TEXT NOT NULL,
397
- input_tokens INTEGER NOT NULL,
398
- output_tokens INTEGER NOT NULL,
399
- cache_write_tokens INTEGER,
400
- cache_read_tokens INTEGER,
401
- cost_usd REAL,
402
- created_at INTEGER NOT NULL
403
- )`,
404
- `CREATE INDEX IF NOT EXISTS agent_token_usage_actor_created_idx
405
- ON agent_token_usage (actor_ref, created_at)`,
406
- `CREATE TABLE IF NOT EXISTS agent_model_pricing (
407
- id TEXT PRIMARY KEY NOT NULL,
408
- model_id TEXT NOT NULL,
409
- input_price_per_1m REAL NOT NULL,
410
- output_price_per_1m REAL NOT NULL,
411
- cache_write_price_per_1m REAL,
412
- cache_read_price_per_1m REAL,
413
- effective_from INTEGER NOT NULL,
414
- is_current INTEGER NOT NULL
415
- )`,
416
- `CREATE TABLE IF NOT EXISTS agent_run (
417
- id TEXT PRIMARY KEY NOT NULL,
418
- thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,
419
- actor_ref TEXT NOT NULL,
420
- agent_name TEXT,
421
- status TEXT NOT NULL,
422
- duration_ms INTEGER,
423
- error_code TEXT,
424
- error_message TEXT,
425
- retries INTEGER NOT NULL DEFAULT 0,
426
- started_at INTEGER NOT NULL,
427
- settled_at INTEGER,
428
- prompt_hash TEXT,
429
- parent_run_id TEXT
430
- )`,
431
- `CREATE INDEX IF NOT EXISTS agent_run_started_idx
432
- ON agent_run (started_at)`,
433
- // `key` and `text` are quoted: both are keywords in at least one engine this DDL is read by, and
434
- // they are the SPI's own field names, which is worth more here than dodging the quoting.
435
- `CREATE TABLE IF NOT EXISTS agent_memory (
436
- id TEXT PRIMARY KEY NOT NULL,
437
- scope TEXT NOT NULL,
438
- "key" TEXT NOT NULL,
439
- "text" TEXT NOT NULL,
440
- origin_author TEXT NOT NULL,
441
- origin_thread_id TEXT,
442
- origin_run_id TEXT,
443
- origin_actor_ref TEXT,
444
- pinned INTEGER NOT NULL DEFAULT 0,
445
- created_at INTEGER NOT NULL,
446
- updated_at INTEGER NOT NULL
447
- )`,
448
- `CREATE UNIQUE INDEX IF NOT EXISTS agent_memory_scope_key_uq
449
- ON agent_memory (scope, "key")`,
450
- `CREATE TABLE IF NOT EXISTS rag_ingestion_log (
451
- document_id TEXT PRIMARY KEY NOT NULL,
452
- status TEXT NOT NULL,
453
- collection TEXT,
454
- owner_type TEXT,
455
- owner_id TEXT,
456
- source TEXT,
457
- mime_type TEXT,
458
- size INTEGER,
459
- chunks INTEGER,
460
- reason TEXT,
461
- error TEXT,
462
- created_at INTEGER NOT NULL,
463
- updated_at INTEGER NOT NULL
464
- )`,
465
- `CREATE INDEX IF NOT EXISTS rag_ingestion_log_collection_idx
466
- ON rag_ingestion_log (collection, updated_at)`,
467
- `CREATE TABLE IF NOT EXISTS agent_stream_frame (
468
- run_id TEXT NOT NULL,
469
- seq INTEGER NOT NULL,
470
- frame TEXT,
471
- error TEXT,
472
- created_at INTEGER NOT NULL,
473
- PRIMARY KEY (run_id, seq)
474
- )`,
475
- `CREATE TABLE IF NOT EXISTS agent_confirm_token (
476
- hash TEXT PRIMARY KEY NOT NULL,
477
- actor_ref TEXT NOT NULL,
478
- tool TEXT NOT NULL,
479
- expires_at INTEGER NOT NULL,
480
- created_at INTEGER NOT NULL
481
- )`,
482
- `CREATE INDEX IF NOT EXISTS agent_confirm_token_expires_idx
483
- ON agent_confirm_token (expires_at)`
484
- ];
485
- var additiveColumns = [
486
- {
487
- table: "agent_message",
488
- column: "run_id",
489
- ddl: "ALTER TABLE agent_message ADD COLUMN run_id TEXT"
490
- },
491
- {
492
- table: "agent_message",
493
- column: "attachments",
494
- ddl: "ALTER TABLE agent_message ADD COLUMN attachments TEXT"
495
- },
496
- {
497
- table: "agent_thread",
498
- column: "default_agent",
499
- ddl: "ALTER TABLE agent_thread ADD COLUMN default_agent TEXT"
500
- },
501
- {
502
- table: "agent_run",
503
- column: "parent_run_id",
504
- ddl: "ALTER TABLE agent_run ADD COLUMN parent_run_id TEXT"
505
- },
506
- {
507
- table: "agent_message",
508
- column: "reasoning",
509
- ddl: "ALTER TABLE agent_message ADD COLUMN reasoning TEXT"
510
- },
511
- {
512
- table: "agent_message",
513
- column: "reasoning_ms",
514
- ddl: "ALTER TABLE agent_message ADD COLUMN reasoning_ms INTEGER"
515
- },
516
- {
517
- table: "agent_message",
518
- column: "ui",
519
- ddl: "ALTER TABLE agent_message ADD COLUMN ui TEXT"
520
- },
521
- {
522
- table: "agent_message",
523
- column: "feedback",
524
- ddl: "ALTER TABLE agent_message ADD COLUMN feedback TEXT"
525
- },
526
- {
527
- table: "agent_thread",
528
- column: "model",
529
- ddl: "ALTER TABLE agent_thread ADD COLUMN model TEXT"
530
- },
531
- {
532
- table: "agent_tool_call",
533
- column: "approver",
534
- ddl: "ALTER TABLE agent_tool_call ADD COLUMN approver TEXT"
535
- },
536
- {
537
- table: "agent_tool_call",
538
- column: "expires_at",
539
- ddl: "ALTER TABLE agent_tool_call ADD COLUMN expires_at INTEGER"
540
- },
541
- {
542
- table: "agent_tool_call",
543
- column: "remember",
544
- ddl: "ALTER TABLE agent_tool_call ADD COLUMN remember INTEGER"
545
- },
546
- {
547
- table: "agent_thread",
548
- column: "queue_pause",
549
- ddl: "ALTER TABLE agent_thread ADD COLUMN queue_pause TEXT"
550
- },
551
- {
552
- table: "agent_tool_call",
553
- column: "decided_via",
554
- ddl: "ALTER TABLE agent_tool_call ADD COLUMN decided_via TEXT"
555
- },
556
- {
557
- table: "agent_thread",
558
- column: "persona",
559
- ddl: "ALTER TABLE agent_thread ADD COLUMN persona TEXT"
560
- },
561
- {
562
- table: "agent_message",
563
- column: "persona",
564
- ddl: "ALTER TABLE agent_message ADD COLUMN persona TEXT"
565
- },
566
- {
567
- table: "agent_queued_message",
568
- column: "persona",
569
- ddl: "ALTER TABLE agent_queued_message ADD COLUMN persona TEXT"
356
+ import { getTableName, sql } from "drizzle-orm";
357
+ import { getTableConfig as mysqlTableConfig } from "drizzle-orm/mysql-core";
358
+ import { getTableConfig as pgTableConfig } from "drizzle-orm/pg-core";
359
+ import { getTableConfig as sqliteTableConfig } from "drizzle-orm/sqlite-core";
360
+
361
+ // src/dialect.ts
362
+ import { is } from "drizzle-orm";
363
+ import { MySqlDatabase } from "drizzle-orm/mysql-core";
364
+ import { PgDatabase } from "drizzle-orm/pg-core";
365
+
366
+ // src/schema-mysql.ts
367
+ import { canonicalActionProposalJson } from "@dudousxd/nestjs-agent-core";
368
+ import { bigint, boolean, customType, datetime, double, index as index2, int, json, longtext, mysqlTable, primaryKey as primaryKey2, uniqueIndex as uniqueIndex2, varchar } from "drizzle-orm/mysql-core";
369
+ var ts = /* @__PURE__ */ __name((name) => datetime(name, {
370
+ mode: "date",
371
+ fsp: 3
372
+ }), "ts");
373
+ var key = /* @__PURE__ */ __name((name) => varchar(name, {
374
+ length: 255
375
+ }), "key");
376
+ var agentThread2 = mysqlTable("agent_thread", {
377
+ id: key("id").primaryKey(),
378
+ actorRef: key("actor_ref").notNull(),
379
+ tenantRef: key("tenant_ref"),
380
+ title: key("title").notNull(),
381
+ transient: boolean("transient").notNull().default(false),
382
+ activeStreamId: key("active_stream_id"),
383
+ defaultAgent: key("default_agent"),
384
+ model: key("model"),
385
+ /** The persona a send on this thread runs under when it names none; `null` → the agent's default. */
386
+ persona: key("persona"),
387
+ queuePause: json("queue_pause").$type(),
388
+ createdAt: ts("created_at").notNull(),
389
+ updatedAt: ts("updated_at").notNull(),
390
+ deletedAt: ts("deleted_at")
391
+ }, (table) => [
392
+ index2("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt)
393
+ ]);
394
+ var agentMessage2 = mysqlTable("agent_message", {
395
+ id: key("id").primaryKey(),
396
+ threadId: key("thread_id").notNull().references(() => agentThread2.id, {
397
+ onDelete: "cascade"
398
+ }),
399
+ role: key("role").$type().notNull(),
400
+ actionProposalOutcome: longtext("action_proposal_outcome"),
401
+ content: longtext("content").notNull(),
402
+ toolCalls: json("tool_calls").$type(),
403
+ toolResults: json("tool_results").$type(),
404
+ attachments: json("attachments").$type(),
405
+ followUps: json("follow_ups").$type(),
406
+ usage: json("usage").$type(),
407
+ agentName: key("agent_name"),
408
+ /** The persona the turn that wrote this message ran under; `null` → none. */
409
+ persona: key("persona"),
410
+ runId: key("run_id"),
411
+ reasoning: longtext("reasoning"),
412
+ reasoningMs: int("reasoning_ms"),
413
+ ui: json("ui").$type(),
414
+ feedback: json("feedback").$type(),
415
+ seq: int("seq"),
416
+ createdAt: ts("created_at").notNull()
417
+ }, (table) => [
418
+ index2("agent_message_thread_created_idx").on(table.threadId, table.createdAt)
419
+ ]);
420
+ var agentToolCall2 = mysqlTable("agent_tool_call", {
421
+ proposalId: key("proposal_id"),
422
+ id: key("id").primaryKey(),
423
+ messageId: key("message_id").notNull().references(() => agentMessage2.id, {
424
+ onDelete: "cascade"
425
+ }),
426
+ toolName: key("tool_name").notNull(),
427
+ toolType: key("tool_type").$type().notNull(),
428
+ input: json("input"),
429
+ output: json("output"),
430
+ status: key("status").$type().notNull(),
431
+ executedByRef: key("executed_by_ref"),
432
+ executionMs: int("execution_ms"),
433
+ error: longtext("error"),
434
+ createdAt: ts("created_at").notNull(),
435
+ executedAt: ts("executed_at"),
436
+ runId: key("run_id"),
437
+ confirmation: json("confirmation").$type(),
438
+ approver: key("approver"),
439
+ expiresAt: ts("expires_at"),
440
+ remember: boolean("remember"),
441
+ decidedVia: key("decided_via")
442
+ }, (table) => [
443
+ index2("agent_tool_call_message_idx").on(table.messageId)
444
+ ]);
445
+ var agentQueuedMessage2 = mysqlTable("agent_queued_message", {
446
+ uiCapabilities: json("ui_capabilities").$type(),
447
+ id: key("id").primaryKey(),
448
+ threadId: key("thread_id").notNull().references(() => agentThread2.id, {
449
+ onDelete: "cascade"
450
+ }),
451
+ actor: json("actor").$type().notNull(),
452
+ content: longtext("content").notNull(),
453
+ attachments: json("attachments").$type(),
454
+ agentName: key("agent_name"),
455
+ /** The persona the send resolved — what the message starts under. */
456
+ persona: key("persona"),
457
+ model: key("model"),
458
+ pageContext: json("page_context").$type(),
459
+ interrupt: boolean("interrupt").notNull().default(false),
460
+ position: int("position").notNull(),
461
+ createdAt: ts("created_at").notNull(),
462
+ updatedAt: ts("updated_at").notNull()
463
+ }, (table) => [
464
+ index2("agent_queued_message_thread_position_idx").on(table.threadId, table.position)
465
+ ]);
466
+ var agentTokenUsage2 = mysqlTable("agent_token_usage", {
467
+ id: key("id").primaryKey(),
468
+ threadId: key("thread_id").notNull().references(() => agentThread2.id, {
469
+ onDelete: "cascade"
470
+ }),
471
+ actorRef: key("actor_ref").notNull(),
472
+ messageId: key("message_id"),
473
+ modelId: key("model_id").notNull(),
474
+ purpose: key("purpose").$type().notNull(),
475
+ inputTokens: int("input_tokens").notNull(),
476
+ outputTokens: int("output_tokens").notNull(),
477
+ cacheWriteTokens: int("cache_write_tokens"),
478
+ cacheReadTokens: int("cache_read_tokens"),
479
+ costUsd: double("cost_usd"),
480
+ createdAt: ts("created_at").notNull()
481
+ }, (table) => [
482
+ index2("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt)
483
+ ]);
484
+ var agentModelPricing2 = mysqlTable("agent_model_pricing", {
485
+ id: key("id").primaryKey(),
486
+ modelId: key("model_id").notNull(),
487
+ inputPricePer1m: double("input_price_per_1m").notNull(),
488
+ outputPricePer1m: double("output_price_per_1m").notNull(),
489
+ cacheWritePricePer1m: double("cache_write_price_per_1m"),
490
+ cacheReadPricePer1m: double("cache_read_price_per_1m"),
491
+ effectiveFrom: ts("effective_from").notNull(),
492
+ isCurrent: boolean("is_current").notNull()
493
+ });
494
+ var agentRun2 = mysqlTable("agent_run", {
495
+ id: key("id").primaryKey(),
496
+ threadId: key("thread_id").notNull().references(() => agentThread2.id, {
497
+ onDelete: "cascade"
498
+ }),
499
+ actorRef: key("actor_ref").notNull(),
500
+ agentName: key("agent_name"),
501
+ status: key("status").$type().notNull(),
502
+ durationMs: int("duration_ms"),
503
+ errorCode: key("error_code"),
504
+ errorMessage: longtext("error_message"),
505
+ retries: int("retries").notNull().default(0),
506
+ startedAt: ts("started_at").notNull(),
507
+ settledAt: ts("settled_at"),
508
+ promptHash: key("prompt_hash"),
509
+ parentRunId: key("parent_run_id")
510
+ }, (table) => [
511
+ index2("agent_run_started_idx").on(table.startedAt)
512
+ ]);
513
+ var agentMemory2 = mysqlTable("agent_memory", {
514
+ id: key("id").primaryKey(),
515
+ scope: key("scope").notNull(),
516
+ key: key("key").notNull(),
517
+ text: longtext("text").notNull(),
518
+ originAuthor: key("origin_author").$type().notNull(),
519
+ originThreadId: key("origin_thread_id"),
520
+ originRunId: key("origin_run_id"),
521
+ originActorRef: key("origin_actor_ref"),
522
+ pinned: boolean("pinned").notNull().default(false),
523
+ createdAt: ts("created_at").notNull(),
524
+ updatedAt: ts("updated_at").notNull()
525
+ }, (table) => [
526
+ uniqueIndex2("agent_memory_scope_key_uq").on(table.scope, table.key)
527
+ ]);
528
+ var ragIngestionLog2 = mysqlTable("rag_ingestion_log", {
529
+ documentId: key("document_id").primaryKey(),
530
+ status: key("status").$type().notNull(),
531
+ collection: key("collection"),
532
+ ownerType: key("owner_type"),
533
+ ownerId: key("owner_id"),
534
+ source: longtext("source"),
535
+ mimeType: key("mime_type"),
536
+ size: bigint("size", {
537
+ mode: "number"
538
+ }),
539
+ chunks: int("chunks"),
540
+ reason: key("reason"),
541
+ error: longtext("error"),
542
+ createdAt: ts("created_at").notNull(),
543
+ updatedAt: ts("updated_at").notNull()
544
+ }, (table) => [
545
+ index2("rag_ingestion_log_collection_idx").on(table.collection, table.updatedAt)
546
+ ]);
547
+ var agentConfirmToken2 = mysqlTable("agent_confirm_token", {
548
+ hash: key("hash").primaryKey(),
549
+ actorRef: key("actor_ref").notNull(),
550
+ tool: key("tool").notNull(),
551
+ expiresAt: bigint("expires_at", {
552
+ mode: "number"
553
+ }).notNull(),
554
+ createdAt: bigint("created_at", {
555
+ mode: "number"
556
+ }).notNull()
557
+ }, (table) => [
558
+ index2("agent_confirm_token_expires_idx").on(table.expiresAt)
559
+ ]);
560
+ var agentStreamFrame2 = mysqlTable("agent_stream_frame", {
561
+ runId: key("run_id").notNull(),
562
+ seq: int("seq").notNull(),
563
+ frame: longtext("frame"),
564
+ error: longtext("error"),
565
+ createdAt: bigint("created_at", {
566
+ mode: "number"
567
+ }).notNull()
568
+ }, (table) => [
569
+ primaryKey2({
570
+ columns: [
571
+ table.runId,
572
+ table.seq
573
+ ]
574
+ })
575
+ ]);
576
+ var proposalJson = customType({
577
+ dataType: /* @__PURE__ */ __name(() => "longtext", "dataType"),
578
+ toDriver: /* @__PURE__ */ __name((value) => canonicalActionProposalJson(value), "toDriver"),
579
+ fromDriver: /* @__PURE__ */ __name((value) => JSON.parse(value), "fromDriver")
580
+ });
581
+ var agentActionProposal2 = mysqlTable("agent_action_proposal", {
582
+ id: key("id").primaryKey(),
583
+ scopeKey: key("scope_key").notNull(),
584
+ decision: key("decision").$type().notNull(),
585
+ logicalSort: varchar("logical_sort", {
586
+ length: 1020
587
+ }).notNull(),
588
+ createFingerprint: longtext("create_fingerprint").notNull(),
589
+ proposal: proposalJson("proposal").notNull(),
590
+ version: bigint("version", {
591
+ mode: "number"
592
+ }).notNull().default(0),
593
+ executionStatus: key("execution_status").$type(),
594
+ leaseExpiresAt: bigint("lease_expires_at", {
595
+ mode: "number"
596
+ }),
597
+ deliveryStatus: key("delivery_status"),
598
+ deliveryLeaseExpiresAt: bigint("delivery_lease_expires_at", {
599
+ mode: "number"
600
+ }),
601
+ replacementGroupKey: key("replacement_group_key"),
602
+ outcomeIdKey: key("outcome_id_key"),
603
+ proposalExpiresAt: bigint("proposal_expires_at", {
604
+ mode: "number"
605
+ }),
606
+ discoveryIndexVersion: bigint("discovery_index_version", {
607
+ mode: "number"
608
+ }).notNull().default(0),
609
+ createdAt: bigint("created_at", {
610
+ mode: "number"
611
+ }).notNull()
612
+ }, (table) => [
613
+ index2("agent_action_proposal_execution_idx").on(table.discoveryIndexVersion, table.executionStatus, table.leaseExpiresAt, table.createdAt),
614
+ index2("agent_action_proposal_expiry_idx").on(table.discoveryIndexVersion, table.decision, table.proposalExpiresAt, table.createdAt),
615
+ index2("agent_action_proposal_replacement_idx").on(table.scopeKey, table.replacementGroupKey, table.decision),
616
+ index2("agent_action_proposal_delivery_idx").on(table.deliveryStatus, table.deliveryLeaseExpiresAt, table.createdAt),
617
+ uniqueIndex2("agent_action_proposal_outcome_idx").on(table.outcomeIdKey),
618
+ index2("agent_action_proposal_scope_idx").on(table.scopeKey, table.createdAt, table.id)
619
+ ]);
620
+ var mysqlAgentSchema = {
621
+ agentActionProposal: agentActionProposal2,
622
+ agentThread: agentThread2,
623
+ agentMessage: agentMessage2,
624
+ agentQueuedMessage: agentQueuedMessage2,
625
+ agentToolCall: agentToolCall2,
626
+ agentTokenUsage: agentTokenUsage2,
627
+ agentModelPricing: agentModelPricing2,
628
+ agentRun: agentRun2,
629
+ agentMemory: agentMemory2,
630
+ ragIngestionLog: ragIngestionLog2,
631
+ agentConfirmToken: agentConfirmToken2,
632
+ agentStreamFrame: agentStreamFrame2
633
+ };
634
+
635
+ // src/schema-pg.ts
636
+ import { canonicalActionProposalJson as canonicalActionProposalJson2 } from "@dudousxd/nestjs-agent-core";
637
+ import { bigint as bigint2, boolean as boolean2, customType as customType2, doublePrecision, index as index3, integer as integer2, jsonb, pgTable, primaryKey as primaryKey3, text as text2, timestamp, uniqueIndex as uniqueIndex3 } from "drizzle-orm/pg-core";
638
+ var ts2 = /* @__PURE__ */ __name((name) => timestamp(name, {
639
+ withTimezone: true,
640
+ precision: 3,
641
+ mode: "date"
642
+ }), "ts");
643
+ var agentThread3 = pgTable("agent_thread", {
644
+ id: text2("id").primaryKey(),
645
+ actorRef: text2("actor_ref").notNull(),
646
+ tenantRef: text2("tenant_ref"),
647
+ title: text2("title").notNull(),
648
+ transient: boolean2("transient").notNull().default(false),
649
+ activeStreamId: text2("active_stream_id"),
650
+ defaultAgent: text2("default_agent"),
651
+ model: text2("model"),
652
+ /** The persona a send on this thread runs under when it names none; `null` → the agent's default. */
653
+ persona: text2("persona"),
654
+ queuePause: jsonb("queue_pause").$type(),
655
+ createdAt: ts2("created_at").notNull(),
656
+ updatedAt: ts2("updated_at").notNull(),
657
+ deletedAt: ts2("deleted_at")
658
+ }, (table) => [
659
+ index3("agent_thread_actor_updated_idx").on(table.actorRef, table.updatedAt)
660
+ ]);
661
+ var agentMessage3 = pgTable("agent_message", {
662
+ id: text2("id").primaryKey(),
663
+ threadId: text2("thread_id").notNull().references(() => agentThread3.id, {
664
+ onDelete: "cascade"
665
+ }),
666
+ role: text2("role").$type().notNull(),
667
+ actionProposalOutcome: text2("action_proposal_outcome"),
668
+ content: text2("content").notNull(),
669
+ toolCalls: jsonb("tool_calls").$type(),
670
+ toolResults: jsonb("tool_results").$type(),
671
+ attachments: jsonb("attachments").$type(),
672
+ followUps: jsonb("follow_ups").$type(),
673
+ usage: jsonb("usage").$type(),
674
+ agentName: text2("agent_name"),
675
+ /** The persona the turn that wrote this message ran under; `null` → none. */
676
+ persona: text2("persona"),
677
+ runId: text2("run_id"),
678
+ reasoning: text2("reasoning"),
679
+ reasoningMs: integer2("reasoning_ms"),
680
+ ui: jsonb("ui").$type(),
681
+ feedback: jsonb("feedback").$type(),
682
+ seq: integer2("seq"),
683
+ createdAt: ts2("created_at").notNull()
684
+ }, (table) => [
685
+ index3("agent_message_thread_created_idx").on(table.threadId, table.createdAt)
686
+ ]);
687
+ var agentToolCall3 = pgTable("agent_tool_call", {
688
+ proposalId: text2("proposal_id"),
689
+ id: text2("id").primaryKey(),
690
+ messageId: text2("message_id").notNull().references(() => agentMessage3.id, {
691
+ onDelete: "cascade"
692
+ }),
693
+ toolName: text2("tool_name").notNull(),
694
+ toolType: text2("tool_type").$type().notNull(),
695
+ input: jsonb("input"),
696
+ output: jsonb("output"),
697
+ status: text2("status").$type().notNull(),
698
+ executedByRef: text2("executed_by_ref"),
699
+ executionMs: integer2("execution_ms"),
700
+ error: text2("error"),
701
+ createdAt: ts2("created_at").notNull(),
702
+ executedAt: ts2("executed_at"),
703
+ runId: text2("run_id"),
704
+ confirmation: jsonb("confirmation").$type(),
705
+ approver: text2("approver"),
706
+ expiresAt: ts2("expires_at"),
707
+ remember: boolean2("remember"),
708
+ decidedVia: text2("decided_via")
709
+ }, (table) => [
710
+ index3("agent_tool_call_message_idx").on(table.messageId)
711
+ ]);
712
+ var agentQueuedMessage3 = pgTable("agent_queued_message", {
713
+ uiCapabilities: jsonb("ui_capabilities").$type(),
714
+ id: text2("id").primaryKey(),
715
+ threadId: text2("thread_id").notNull().references(() => agentThread3.id, {
716
+ onDelete: "cascade"
717
+ }),
718
+ actor: jsonb("actor").$type().notNull(),
719
+ content: text2("content").notNull(),
720
+ attachments: jsonb("attachments").$type(),
721
+ agentName: text2("agent_name"),
722
+ /** The persona the send resolved — what the message starts under. */
723
+ persona: text2("persona"),
724
+ model: text2("model"),
725
+ pageContext: jsonb("page_context").$type(),
726
+ interrupt: boolean2("interrupt").notNull().default(false),
727
+ position: integer2("position").notNull(),
728
+ createdAt: ts2("created_at").notNull(),
729
+ updatedAt: ts2("updated_at").notNull()
730
+ }, (table) => [
731
+ index3("agent_queued_message_thread_position_idx").on(table.threadId, table.position)
732
+ ]);
733
+ var agentTokenUsage3 = pgTable("agent_token_usage", {
734
+ id: text2("id").primaryKey(),
735
+ threadId: text2("thread_id").notNull().references(() => agentThread3.id, {
736
+ onDelete: "cascade"
737
+ }),
738
+ actorRef: text2("actor_ref").notNull(),
739
+ messageId: text2("message_id"),
740
+ modelId: text2("model_id").notNull(),
741
+ purpose: text2("purpose").$type().notNull(),
742
+ inputTokens: integer2("input_tokens").notNull(),
743
+ outputTokens: integer2("output_tokens").notNull(),
744
+ cacheWriteTokens: integer2("cache_write_tokens"),
745
+ cacheReadTokens: integer2("cache_read_tokens"),
746
+ costUsd: doublePrecision("cost_usd"),
747
+ createdAt: ts2("created_at").notNull()
748
+ }, (table) => [
749
+ index3("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt)
750
+ ]);
751
+ var agentModelPricing3 = pgTable("agent_model_pricing", {
752
+ id: text2("id").primaryKey(),
753
+ modelId: text2("model_id").notNull(),
754
+ inputPricePer1m: doublePrecision("input_price_per_1m").notNull(),
755
+ outputPricePer1m: doublePrecision("output_price_per_1m").notNull(),
756
+ cacheWritePricePer1m: doublePrecision("cache_write_price_per_1m"),
757
+ cacheReadPricePer1m: doublePrecision("cache_read_price_per_1m"),
758
+ effectiveFrom: ts2("effective_from").notNull(),
759
+ isCurrent: boolean2("is_current").notNull()
760
+ });
761
+ var agentRun3 = pgTable("agent_run", {
762
+ id: text2("id").primaryKey(),
763
+ threadId: text2("thread_id").notNull().references(() => agentThread3.id, {
764
+ onDelete: "cascade"
765
+ }),
766
+ actorRef: text2("actor_ref").notNull(),
767
+ agentName: text2("agent_name"),
768
+ status: text2("status").$type().notNull(),
769
+ durationMs: integer2("duration_ms"),
770
+ errorCode: text2("error_code"),
771
+ errorMessage: text2("error_message"),
772
+ retries: integer2("retries").notNull().default(0),
773
+ startedAt: ts2("started_at").notNull(),
774
+ settledAt: ts2("settled_at"),
775
+ promptHash: text2("prompt_hash"),
776
+ parentRunId: text2("parent_run_id")
777
+ }, (table) => [
778
+ index3("agent_run_started_idx").on(table.startedAt)
779
+ ]);
780
+ var agentMemory3 = pgTable("agent_memory", {
781
+ id: text2("id").primaryKey(),
782
+ scope: text2("scope").notNull(),
783
+ key: text2("key").notNull(),
784
+ text: text2("text").notNull(),
785
+ originAuthor: text2("origin_author").$type().notNull(),
786
+ originThreadId: text2("origin_thread_id"),
787
+ originRunId: text2("origin_run_id"),
788
+ originActorRef: text2("origin_actor_ref"),
789
+ pinned: boolean2("pinned").notNull().default(false),
790
+ createdAt: ts2("created_at").notNull(),
791
+ updatedAt: ts2("updated_at").notNull()
792
+ }, (table) => [
793
+ uniqueIndex3("agent_memory_scope_key_uq").on(table.scope, table.key)
794
+ ]);
795
+ var ragIngestionLog3 = pgTable("rag_ingestion_log", {
796
+ documentId: text2("document_id").primaryKey(),
797
+ status: text2("status").$type().notNull(),
798
+ collection: text2("collection"),
799
+ ownerType: text2("owner_type"),
800
+ ownerId: text2("owner_id"),
801
+ source: text2("source"),
802
+ mimeType: text2("mime_type"),
803
+ size: bigint2("size", {
804
+ mode: "number"
805
+ }),
806
+ chunks: integer2("chunks"),
807
+ reason: text2("reason"),
808
+ error: text2("error"),
809
+ createdAt: ts2("created_at").notNull(),
810
+ updatedAt: ts2("updated_at").notNull()
811
+ }, (table) => [
812
+ index3("rag_ingestion_log_collection_idx").on(table.collection, table.updatedAt)
813
+ ]);
814
+ var agentConfirmToken3 = pgTable("agent_confirm_token", {
815
+ hash: text2("hash").primaryKey(),
816
+ actorRef: text2("actor_ref").notNull(),
817
+ tool: text2("tool").notNull(),
818
+ expiresAt: bigint2("expires_at", {
819
+ mode: "number"
820
+ }).notNull(),
821
+ createdAt: bigint2("created_at", {
822
+ mode: "number"
823
+ }).notNull()
824
+ }, (table) => [
825
+ index3("agent_confirm_token_expires_idx").on(table.expiresAt)
826
+ ]);
827
+ var agentStreamFrame3 = pgTable("agent_stream_frame", {
828
+ runId: text2("run_id").notNull(),
829
+ seq: integer2("seq").notNull(),
830
+ frame: text2("frame"),
831
+ error: text2("error"),
832
+ createdAt: bigint2("created_at", {
833
+ mode: "number"
834
+ }).notNull()
835
+ }, (table) => [
836
+ primaryKey3({
837
+ columns: [
838
+ table.runId,
839
+ table.seq
840
+ ]
841
+ })
842
+ ]);
843
+ var proposalJson2 = customType2({
844
+ dataType: /* @__PURE__ */ __name(() => "text", "dataType"),
845
+ toDriver: /* @__PURE__ */ __name((value) => canonicalActionProposalJson2(value), "toDriver"),
846
+ fromDriver: /* @__PURE__ */ __name((value) => JSON.parse(value), "fromDriver")
847
+ });
848
+ var agentActionProposal3 = pgTable("agent_action_proposal", {
849
+ id: text2("id").primaryKey(),
850
+ scopeKey: text2("scope_key").notNull(),
851
+ decision: text2("decision").$type().notNull(),
852
+ logicalSort: text2("logical_sort").notNull(),
853
+ createFingerprint: text2("create_fingerprint").notNull(),
854
+ proposal: proposalJson2("proposal").notNull(),
855
+ version: bigint2("version", {
856
+ mode: "number"
857
+ }).notNull().default(0),
858
+ executionStatus: text2("execution_status").$type(),
859
+ leaseExpiresAt: bigint2("lease_expires_at", {
860
+ mode: "number"
861
+ }),
862
+ deliveryStatus: text2("delivery_status"),
863
+ deliveryLeaseExpiresAt: bigint2("delivery_lease_expires_at", {
864
+ mode: "number"
865
+ }),
866
+ replacementGroupKey: text2("replacement_group_key"),
867
+ outcomeIdKey: text2("outcome_id_key"),
868
+ proposalExpiresAt: bigint2("proposal_expires_at", {
869
+ mode: "number"
870
+ }),
871
+ discoveryIndexVersion: bigint2("discovery_index_version", {
872
+ mode: "number"
873
+ }).notNull().default(0),
874
+ createdAt: bigint2("created_at", {
875
+ mode: "number"
876
+ }).notNull()
877
+ }, (table) => [
878
+ index3("agent_action_proposal_execution_idx").on(table.discoveryIndexVersion, table.executionStatus, table.leaseExpiresAt, table.createdAt),
879
+ index3("agent_action_proposal_expiry_idx").on(table.discoveryIndexVersion, table.decision, table.proposalExpiresAt, table.createdAt),
880
+ index3("agent_action_proposal_replacement_idx").on(table.scopeKey, table.replacementGroupKey, table.decision),
881
+ index3("agent_action_proposal_delivery_idx").on(table.deliveryStatus, table.deliveryLeaseExpiresAt, table.createdAt),
882
+ uniqueIndex3("agent_action_proposal_outcome_idx").on(table.outcomeIdKey),
883
+ index3("agent_action_proposal_scope_idx").on(table.scopeKey, table.createdAt, table.id)
884
+ ]);
885
+ var pgAgentSchema = {
886
+ agentActionProposal: agentActionProposal3,
887
+ agentThread: agentThread3,
888
+ agentMessage: agentMessage3,
889
+ agentQueuedMessage: agentQueuedMessage3,
890
+ agentToolCall: agentToolCall3,
891
+ agentTokenUsage: agentTokenUsage3,
892
+ agentModelPricing: agentModelPricing3,
893
+ agentRun: agentRun3,
894
+ agentMemory: agentMemory3,
895
+ ragIngestionLog: ragIngestionLog3,
896
+ agentConfirmToken: agentConfirmToken3,
897
+ agentStreamFrame: agentStreamFrame3
898
+ };
899
+
900
+ // src/dialect.ts
901
+ function agentDialectOf(db) {
902
+ if (is(db, PgDatabase)) return "postgres";
903
+ if (is(db, MySqlDatabase)) return "mysql";
904
+ return "sqlite";
905
+ }
906
+ __name(agentDialectOf, "agentDialectOf");
907
+ function agentTablesFor(dialect) {
908
+ if (dialect === "postgres") return pgAgentSchema;
909
+ if (dialect === "mysql") return mysqlAgentSchema;
910
+ return agentSchema;
911
+ }
912
+ __name(agentTablesFor, "agentTablesFor");
913
+ function asBuilder(db) {
914
+ return db;
915
+ }
916
+ __name(asBuilder, "asBuilder");
917
+ async function affectedRows(dialect, statement, column) {
918
+ if (dialect !== "mysql") {
919
+ return (await statement.returning({
920
+ affected: column
921
+ })).length;
922
+ }
923
+ return mysqlAffectedRows(await statement);
924
+ }
925
+ __name(affectedRows, "affectedRows");
926
+ function mysqlAffectedRows(result) {
927
+ const header = Array.isArray(result) ? result[0] : result;
928
+ const counts = header;
929
+ const count3 = counts?.affectedRows ?? counts?.rowsAffected;
930
+ return typeof count3 === "number" ? count3 : 0;
931
+ }
932
+ __name(mysqlAffectedRows, "mysqlAffectedRows");
933
+ async function runSql(db, dialect, statement) {
934
+ if (dialect === "sqlite") {
935
+ await db.run(statement);
936
+ return;
570
937
  }
571
- ];
572
- async function ensureAgentSchema(db) {
573
- for (const statement of statements) {
574
- await db.run(sql.raw(statement));
938
+ if (dialect === "postgres") {
939
+ await db.execute(statement);
940
+ return;
575
941
  }
576
- for (const { table, column, ddl } of additiveColumns) {
577
- const existing = await db.all(sql.raw(`PRAGMA table_info(${table})`));
578
- if (!existing.some((row) => row.name === column)) {
579
- await db.run(sql.raw(ddl));
942
+ await db.execute(statement);
943
+ }
944
+ __name(runSql, "runSql");
945
+ async function querySql(db, dialect, statement) {
946
+ if (dialect === "sqlite") {
947
+ return db.all(statement);
948
+ }
949
+ const result = dialect === "postgres" ? await db.execute(statement) : await db.execute(statement);
950
+ if (dialect === "mysql") {
951
+ return Array.isArray(result) ? result[0] : [];
952
+ }
953
+ return Array.isArray(result) ? result : result.rows ?? [];
954
+ }
955
+ __name(querySql, "querySql");
956
+ function isUniqueViolation(error) {
957
+ for (let current = error; current !== null && typeof current === "object"; ) {
958
+ const { code, errno } = current;
959
+ if (code === "23505" || code === "ER_DUP_ENTRY" || errno === 1062 || code === "ER_LOCK_DEADLOCK" || errno === 1213 || typeof code === "string" && code.startsWith("SQLITE_CONSTRAINT")) {
960
+ return true;
580
961
  }
962
+ current = current.cause;
581
963
  }
964
+ return false;
965
+ }
966
+ __name(isUniqueViolation, "isUniqueViolation");
967
+ function upsert(dialect, insert, target, set) {
968
+ if (dialect === "mysql") {
969
+ return insert.onDuplicateKeyUpdate({
970
+ set
971
+ });
972
+ }
973
+ return insert.onConflictDoUpdate({
974
+ target,
975
+ set
976
+ });
977
+ }
978
+ __name(upsert, "upsert");
979
+
980
+ // src/ensure-schema.ts
981
+ async function ensureAgentSchema(db) {
982
+ const dialect = agentDialectOf(db);
983
+ if (dialect === "postgres") {
984
+ await db.transaction(async (tx) => {
985
+ await tx.execute(sql.raw(`select pg_advisory_xact_lock(hashtext('${LOCK_NAME}'))`));
986
+ await heal(tx, dialect);
987
+ });
988
+ return;
989
+ }
990
+ if (dialect === "mysql") {
991
+ await db.transaction(async (tx) => {
992
+ await tx.execute(sql.raw(`select get_lock('${LOCK_NAME}', 30)`));
993
+ try {
994
+ await heal(tx, dialect);
995
+ } finally {
996
+ await tx.execute(sql.raw(`select release_lock('${LOCK_NAME}')`));
997
+ }
998
+ });
999
+ return;
1000
+ }
1001
+ await heal(db, dialect);
582
1002
  }
583
1003
  __name(ensureAgentSchema, "ensureAgentSchema");
1004
+ var LOCK_NAME = "nestjs_agent_schema";
1005
+ var MYSQL_TABLE_OPTIONS = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin";
1006
+ function tableSpec(dialect, table) {
1007
+ const config = dialect === "postgres" ? pgTableConfig(table) : dialect === "mysql" ? mysqlTableConfig(table) : sqliteTableConfig(table);
1008
+ const columns = config.columns;
1009
+ const compositeKey = config.primaryKeys[0]?.columns.map((column) => column.name);
1010
+ return {
1011
+ name: config.name,
1012
+ columns,
1013
+ primaryKey: compositeKey ?? columns.filter((column) => column.primary).map((c) => c.name),
1014
+ foreignKeys: config.foreignKeys.map((foreignKey) => {
1015
+ const reference = foreignKey.reference();
1016
+ return {
1017
+ columns: reference.columns.map((column) => column.name),
1018
+ table: getTableName(reference.foreignTable),
1019
+ foreignColumns: reference.foreignColumns.map((column) => column.name),
1020
+ ...foreignKey.onDelete !== void 0 ? {
1021
+ onDelete: foreignKey.onDelete
1022
+ } : {}
1023
+ };
1024
+ }),
1025
+ indexes: config.indexes.map((index4) => ({
1026
+ name: String(index4.config.name),
1027
+ unique: index4.config.unique === true,
1028
+ columns: index4.config.columns.map((column) => String(column.name))
1029
+ }))
1030
+ };
1031
+ }
1032
+ __name(tableSpec, "tableSpec");
1033
+ function quote(dialect, identifier) {
1034
+ return dialect === "mysql" ? `\`${identifier}\`` : `"${identifier}"`;
1035
+ }
1036
+ __name(quote, "quote");
1037
+ function literal(dialect, value) {
1038
+ if (typeof value === "boolean") {
1039
+ return dialect === "sqlite" ? value ? "1" : "0" : value ? "true" : "false";
1040
+ }
1041
+ if (typeof value === "number") return String(value);
1042
+ return `'${String(value).replaceAll("'", "''")}'`;
1043
+ }
1044
+ __name(literal, "literal");
1045
+ function columnDefinition(dialect, column) {
1046
+ const parts = [
1047
+ quote(dialect, column.name),
1048
+ column.getSQLType()
1049
+ ];
1050
+ if (column.notNull) parts.push("NOT NULL");
1051
+ if (column.hasDefault && column.default !== void 0) {
1052
+ parts.push(`DEFAULT ${literal(dialect, column.default)}`);
1053
+ }
1054
+ return parts.join(" ");
1055
+ }
1056
+ __name(columnDefinition, "columnDefinition");
1057
+ function createTableSql(dialect, spec) {
1058
+ const q = /* @__PURE__ */ __name((identifier) => quote(dialect, identifier), "q");
1059
+ const lines = spec.columns.map((column) => columnDefinition(dialect, column));
1060
+ lines.push(`PRIMARY KEY (${spec.primaryKey.map(q).join(", ")})`);
1061
+ for (const foreignKey of spec.foreignKeys) {
1062
+ lines.push(`FOREIGN KEY (${foreignKey.columns.map(q).join(", ")}) REFERENCES ${q(foreignKey.table)} (${foreignKey.foreignColumns.map(q).join(", ")})${foreignKey.onDelete !== void 0 ? ` ON DELETE ${foreignKey.onDelete.toUpperCase()}` : ""}`);
1063
+ }
1064
+ const options = dialect === "mysql" ? ` ${MYSQL_TABLE_OPTIONS}` : "";
1065
+ return `CREATE TABLE IF NOT EXISTS ${q(spec.name)} (
1066
+ ${lines.join(",\n ")}
1067
+ )${options}`;
1068
+ }
1069
+ __name(createTableSql, "createTableSql");
1070
+ function agentSchemaDdl(dialect) {
1071
+ const statements = [];
1072
+ for (const spec of specs(dialect)) {
1073
+ statements.push(createTableSql(dialect, spec));
1074
+ for (const index4 of spec.indexes) {
1075
+ statements.push(createIndexSql(dialect, spec.name, index4));
1076
+ }
1077
+ }
1078
+ return statements;
1079
+ }
1080
+ __name(agentSchemaDdl, "agentSchemaDdl");
1081
+ function createIndexSql(dialect, table, index4) {
1082
+ const q = /* @__PURE__ */ __name((identifier) => quote(dialect, identifier), "q");
1083
+ const guard = dialect === "mysql" ? "" : "IF NOT EXISTS ";
1084
+ return `CREATE ${index4.unique ? "UNIQUE " : ""}INDEX ${guard}${q(index4.name)} ON ${q(table)} (${index4.columns.map(q).join(", ")})`;
1085
+ }
1086
+ __name(createIndexSql, "createIndexSql");
1087
+ function specs(dialect) {
1088
+ const all = Object.values(agentTablesFor(dialect)).map((table) => tableSpec(dialect, table));
1089
+ const ordered = [];
1090
+ const placed = /* @__PURE__ */ new Set();
1091
+ while (ordered.length < all.length) {
1092
+ const ready = all.filter((spec) => !placed.has(spec.name) && spec.foreignKeys.every((key2) => key2.table === spec.name || placed.has(key2.table)));
1093
+ if (ready.length === 0) throw new Error("agent schema: circular foreign keys");
1094
+ for (const spec of ready) {
1095
+ ordered.push(spec);
1096
+ placed.add(spec.name);
1097
+ }
1098
+ }
1099
+ return ordered;
1100
+ }
1101
+ __name(specs, "specs");
1102
+ async function existingColumns(db, dialect, table) {
1103
+ const rows = dialect === "sqlite" ? await querySql(db, dialect, sql.raw(`PRAGMA table_info("${table}")`)) : await querySql(db, dialect, sql`select column_name as name from information_schema.columns where table_schema = ${sql.raw(dialect === "mysql" ? "database()" : "current_schema()")} and table_name = ${table}`);
1104
+ return new Set(rows.map((row) => String(row.name)));
1105
+ }
1106
+ __name(existingColumns, "existingColumns");
1107
+ async function indexExists(db, dialect, table, index4) {
1108
+ let query;
1109
+ if (dialect === "sqlite") {
1110
+ query = sql`select name from sqlite_master where type = 'index' and name = ${index4}`;
1111
+ } else if (dialect === "postgres") {
1112
+ query = sql`select indexname as name from pg_indexes where schemaname = current_schema() and indexname = ${index4}`;
1113
+ } else {
1114
+ query = sql`select index_name as name from information_schema.statistics where table_schema = database() and table_name = ${table} and index_name = ${index4}`;
1115
+ }
1116
+ return (await querySql(db, dialect, query)).length > 0;
1117
+ }
1118
+ __name(indexExists, "indexExists");
1119
+ async function heal(db, dialect) {
1120
+ for (const spec of specs(dialect)) {
1121
+ await runSql(db, dialect, sql.raw(createTableSql(dialect, spec)));
1122
+ const present = await existingColumns(db, dialect, spec.name);
1123
+ for (const column of spec.columns) {
1124
+ if (!present.has(column.name)) {
1125
+ await runSql(db, dialect, sql.raw(`ALTER TABLE ${quote(dialect, spec.name)} ADD COLUMN ${columnDefinition(dialect, column)}`));
1126
+ }
1127
+ }
1128
+ for (const index4 of spec.indexes) {
1129
+ if (!await indexExists(db, dialect, spec.name, index4.name)) {
1130
+ await runSql(db, dialect, sql.raw(createIndexSql(dialect, spec.name, index4)));
1131
+ }
1132
+ }
1133
+ }
1134
+ }
1135
+ __name(heal, "heal");
584
1136
 
585
1137
  // src/drizzle-agent-store.ts
586
- import { toolCallApprovalFromRow } from "@dudousxd/nestjs-agent-core";
587
- import { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, max, min, or, sql as sql2 } from "drizzle-orm";
588
- var TURN_MESSAGE_COLUMNS = {
589
- id: agentMessage.id,
590
- role: agentMessage.role,
591
- content: agentMessage.content,
592
- agentName: agentMessage.agentName,
593
- toolCalls: agentMessage.toolCalls,
594
- toolResults: agentMessage.toolResults,
595
- attachments: agentMessage.attachments,
596
- createdAt: agentMessage.createdAt
1138
+ import { canonicalActionProposalJson as canonicalActionProposalJson4, toolCallApprovalFromRow } from "@dudousxd/nestjs-agent-core";
1139
+ import { and as and2, asc as asc2, desc, eq as eq2, gte, inArray, isNotNull, isNull as isNull2, lte as lte2, max as max2, min, or as or2, sql as sql3 } from "drizzle-orm";
1140
+
1141
+ // src/drizzle-action-proposal-store.ts
1142
+ import { createHash, randomUUID } from "crypto";
1143
+ import { actionProposalOutcomeFenceValid, actionProposalOutcomeText, actionProposalScopeMatches, canonicalActionProposalJson as canonicalActionProposalJson3, claimActionProposalOutcome, initialActionProposal, transitionActionProposalClaim, transitionActionProposalDecision, transitionActionProposalLease, transitionActionProposalSettlement, transitionActionProposalSupersession, validateActionProposalDiscoveryIndexBatch, validateActionProposalExpiryBatch, validateActionProposalListQuery, validateActionProposalWorkerClaim } from "@dudousxd/nestjs-agent-core";
1144
+ import { and, asc, entityKind, eq, gt, isNull, lte, max, or, sql as sql2 } from "drizzle-orm";
1145
+
1146
+ // src/action-proposal-transaction-mode.ts
1147
+ function actionProposalTransactionMode(kind) {
1148
+ if (kind === "BetterSQLite3Database" || kind === "BetterSQLiteTransaction") return "sync";
1149
+ if (kind !== void 0 && [
1150
+ "NodePgDatabase",
1151
+ "NodePgTransaction",
1152
+ "MySql2Database",
1153
+ "MySql2Transaction",
1154
+ "LibSQLDatabase",
1155
+ "LibSQLTransaction"
1156
+ ].includes(kind)) return "async";
1157
+ return "unsupported";
1158
+ }
1159
+ __name(actionProposalTransactionMode, "actionProposalTransactionMode");
1160
+
1161
+ // src/drizzle-action-proposal-store.ts
1162
+ var DrizzleActionProposalStore = class {
1163
+ static {
1164
+ __name(this, "DrizzleActionProposalStore");
1165
+ }
1166
+ db;
1167
+ rawDb;
1168
+ actionProposalAdmissionSupported;
1169
+ synchronousSqlite;
1170
+ dialect;
1171
+ table;
1172
+ clock;
1173
+ constructor(db, options = {}) {
1174
+ this.rawDb = db;
1175
+ const kind = db.constructor[entityKind];
1176
+ const transactionMode = actionProposalTransactionMode(kind);
1177
+ this.synchronousSqlite = transactionMode === "sync";
1178
+ this.actionProposalAdmissionSupported = transactionMode !== "unsupported";
1179
+ this.dialect = agentDialectOf(db);
1180
+ this.table = agentTablesFor(this.dialect).agentActionProposal;
1181
+ this.db = asBuilder(db);
1182
+ this.clock = options.clock ?? Date.now;
1183
+ }
1184
+ async createActionProposal(input) {
1185
+ const proposal = initialActionProposal(input, this.clock());
1186
+ const row = {
1187
+ id: physicalId(input.id),
1188
+ scopeKey: scopeKey(input),
1189
+ decision: proposal.decision,
1190
+ logicalSort: logicalSort(input.id),
1191
+ createFingerprint: canonicalActionProposalJson3(input),
1192
+ proposal,
1193
+ ...discoveryMetadata(proposal),
1194
+ version: 0,
1195
+ createdAt: proposal.createdAt
1196
+ };
1197
+ const table = this.table;
1198
+ const insert = this.db.insert(table);
1199
+ const inserted = this.dialect === "mysql" ? mysqlAffectedRows(await insert.ignore().values(row)) : await affectedRows(this.dialect, insert.values(row).onConflictDoNothing(), table.id);
1200
+ const stored = await this.read(input, input.id);
1201
+ if (!stored) return {
1202
+ status: "conflict"
1203
+ };
1204
+ if (inserted === 1) return {
1205
+ status: "created",
1206
+ proposal: stored.proposal
1207
+ };
1208
+ return {
1209
+ status: stored.createFingerprint === row.createFingerprint ? "unchanged" : "conflict",
1210
+ proposal: stored.proposal
1211
+ };
1212
+ }
1213
+ createReplacingActionProposal(input) {
1214
+ if (!input.replacementKey) return this.createActionProposal(input);
1215
+ const proposal = initialActionProposal(input, this.clock());
1216
+ return this.transactionSteps((db) => this.replacementSteps(db, input, proposal));
1217
+ }
1218
+ async supersedeActionProposal(scope, id, command) {
1219
+ const replacement = await this.getActionProposal(scope, command.replacementProposalId);
1220
+ if (!replacement) return {
1221
+ status: "not_found"
1222
+ };
1223
+ return this.mutate(scope, id, (row, now) => transitionActionProposalSupersession(row, replacement, command, now));
1224
+ }
1225
+ *replacementSteps(db, input, proposal) {
1226
+ const table = this.table;
1227
+ const thread = agentTablesFor(this.dialect).agentThread;
1228
+ if (this.dialect === "sqlite") yield {
1229
+ kind: "write",
1230
+ query: db.update(thread).set({
1231
+ updatedAt: sql2`${thread.updatedAt}`
1232
+ }).where(eq(thread.id, input.threadId))
1233
+ };
1234
+ const threads = yield {
1235
+ kind: "read",
1236
+ query: lockQuery(db.select().from(thread).where(eq(thread.id, input.threadId)).limit(1), this.dialect)
1237
+ };
1238
+ const owner = threads[0];
1239
+ if (!owner || owner.id !== input.threadId || owner.deletedAt || owner.actorRef !== input.actorRef || owner.tenantRef !== input.tenantRef) return {
1240
+ status: "conflict"
1241
+ };
1242
+ const existingRows = yield {
1243
+ kind: "read",
1244
+ query: db.select().from(table).where(eq(table.id, physicalId(input.id))).limit(1)
1245
+ };
1246
+ const existing = existingRows[0];
1247
+ if (existing) {
1248
+ if (existing.proposal.id !== input.id || !actionProposalScopeMatches(existing.proposal, input)) return {
1249
+ status: "conflict"
1250
+ };
1251
+ return {
1252
+ status: existing.createFingerprint === canonicalActionProposalJson3(input) ? "unchanged" : "conflict",
1253
+ proposal: existing.proposal
1254
+ };
1255
+ }
1256
+ const groupKey = replacementGroupKey(input);
1257
+ if (groupKey === null) throw new Error("Missing explicit replacement identity");
1258
+ const pending = yield {
1259
+ kind: "read",
1260
+ query: lockQuery(db.select().from(table).where(and(eq(table.scopeKey, scopeKey(input)), eq(table.replacementGroupKey, groupKey), eq(table.decision, "pending"))), this.dialect)
1261
+ };
1262
+ const row = {
1263
+ id: physicalId(input.id),
1264
+ scopeKey: scopeKey(input),
1265
+ decision: proposal.decision,
1266
+ logicalSort: logicalSort(input.id),
1267
+ createFingerprint: canonicalActionProposalJson3(input),
1268
+ proposal,
1269
+ ...discoveryMetadata(proposal),
1270
+ version: 0,
1271
+ createdAt: proposal.createdAt
1272
+ };
1273
+ const insert = db.insert(table);
1274
+ const inserted = yield {
1275
+ kind: "read",
1276
+ query: this.dialect === "mysql" ? insert.ignore().values(row) : insert.values(row).onConflictDoNothing().returning({
1277
+ id: table.id
1278
+ })
1279
+ };
1280
+ const count3 = this.dialect === "mysql" ? mysqlAffectedRows(inserted) : inserted.length;
1281
+ if (count3 !== 1) return {
1282
+ status: "conflict"
1283
+ };
1284
+ for (const old of pending) {
1285
+ const result = transitionActionProposalSupersession(old.proposal, proposal, {
1286
+ replacementProposalId: proposal.id,
1287
+ actorRef: proposal.actorRef,
1288
+ via: "replacement"
1289
+ }, this.clock());
1290
+ if (!result.proposal || canonicalActionProposalJson3(result.proposal) === canonicalActionProposalJson3(old.proposal)) continue;
1291
+ const next = result.proposal;
1292
+ const update = db.update(table).set({
1293
+ proposal: next,
1294
+ decision: next.decision,
1295
+ ...discoveryMetadata(next),
1296
+ version: old.version + 1
1297
+ }).where(and(eq(table.id, old.id), eq(table.version, old.version)));
1298
+ const updated = yield {
1299
+ kind: "read",
1300
+ query: this.dialect === "mysql" ? update : update.returning({
1301
+ id: table.id
1302
+ })
1303
+ };
1304
+ if ((this.dialect === "mysql" ? mysqlAffectedRows(updated) : updated.length) !== 1) throw new Error("Replacement lost its locked proposal fence");
1305
+ }
1306
+ return {
1307
+ status: "created",
1308
+ proposal
1309
+ };
1310
+ }
1311
+ async getActionProposal(scope, id) {
1312
+ return (await this.read(scope, id))?.proposal ?? null;
1313
+ }
1314
+ async listActionProposals(scope, query = {}) {
1315
+ const limit = validateActionProposalListQuery(query);
1316
+ const rows = await this.db.select().from(this.table).where(and(eq(this.table.scopeKey, scopeKey(scope)), query.after === void 0 ? void 0 : or(gt(this.table.createdAt, query.after.createdAt), and(eq(this.table.createdAt, query.after.createdAt), gt(this.table.logicalSort, logicalSort(query.after.id)))), query.decision === void 0 ? void 0 : eq(this.table.decision, query.decision))).orderBy(asc(this.table.createdAt), asc(this.table.logicalSort)).limit(limit);
1317
+ return rows.map((row) => row.proposal).filter((proposal) => actionProposalScopeMatches(proposal, scope));
1318
+ }
1319
+ decideActionProposal(scope, id, command) {
1320
+ return this.mutate(scope, id, (row, now) => transitionActionProposalDecision(row, command, now));
1321
+ }
1322
+ claimActionProposal(scope, id, command) {
1323
+ return this.mutate(scope, id, (row, now) => transitionActionProposalClaim(row, command, now, randomUUID()));
1324
+ }
1325
+ extendActionProposalLease(scope, id, command) {
1326
+ return this.mutate(scope, id, (row, now) => transitionActionProposalLease(row, command, now));
1327
+ }
1328
+ settleActionProposal(scope, id, command) {
1329
+ return this.mutate(scope, id, (row, now) => transitionActionProposalSettlement(row, command, now));
1330
+ }
1331
+ async claimNextActionProposal(command) {
1332
+ const now = this.clock();
1333
+ validateActionProposalWorkerClaim(command, now);
1334
+ const table = this.table;
1335
+ const candidates = await this.db.select().from(table).where(and(eq(table.discoveryIndexVersion, 1), eq(table.decision, "approved"), or(eq(table.executionStatus, "queued"), and(eq(table.executionStatus, "executing"), lte(table.leaseExpiresAt, now))))).orderBy(asc(table.createdAt), asc(table.logicalSort)).limit(32);
1336
+ for (const candidate of candidates) {
1337
+ const result = await this.claimActionProposal(candidate.proposal, candidate.proposal.id, command);
1338
+ if (result.status === "applied" && result.proposal) return result.proposal;
1339
+ }
1340
+ return null;
1341
+ }
1342
+ async expireActionProposals(command) {
1343
+ const now = this.clock();
1344
+ validateActionProposalExpiryBatch(command, now);
1345
+ const table = this.table;
1346
+ const candidates = await this.db.select().from(table).where(and(eq(table.discoveryIndexVersion, 1), eq(table.decision, "pending"), lte(table.proposalExpiresAt, now))).orderBy(asc(table.createdAt), asc(table.logicalSort)).limit(command.limit);
1347
+ let expired = 0;
1348
+ for (const candidate of candidates) {
1349
+ const result = await this.decideActionProposal(candidate.proposal, candidate.proposal.id, {
1350
+ decision: "expired",
1351
+ actorRef: "system",
1352
+ via: "expiry"
1353
+ });
1354
+ if (result.status === "applied") expired++;
1355
+ }
1356
+ return expired;
1357
+ }
1358
+ async backfillActionProposalDiscoveryIndex(command) {
1359
+ validateActionProposalDiscoveryIndexBatch(command);
1360
+ const table = this.table;
1361
+ const candidates = await this.db.select().from(table).where(eq(table.discoveryIndexVersion, 0)).orderBy(asc(table.createdAt), asc(table.logicalSort)).limit(command.limit);
1362
+ let changed = 0;
1363
+ for (const row of candidates) {
1364
+ changed += await affectedRows(this.dialect, this.db.update(table).set({
1365
+ ...discoveryMetadata(row.proposal),
1366
+ version: row.version + 1
1367
+ }).where(and(eq(table.id, row.id), eq(table.scopeKey, row.scopeKey), eq(table.version, row.version), eq(table.discoveryIndexVersion, 0))), table.id);
1368
+ }
1369
+ return changed;
1370
+ }
1371
+ async rememberedActionProposalApprovals(scope) {
1372
+ const table = this.table;
1373
+ const rows = await this.db.select().from(table).where(and(eq(table.scopeKey, scopeKey(scope)), eq(table.decision, "approved"), or(eq(table.executionStatus, "succeeded"), eq(table.executionStatus, "failed"))));
1374
+ return [
1375
+ ...new Set(rows.filter((row) => actionProposalScopeMatches(row.proposal, scope) && row.proposal.decisionAudit?.remember === true).map((row) => row.proposal.toolName))
1376
+ ];
1377
+ }
1378
+ async getThreadActionProposalScope(threadId) {
1379
+ const thread = agentTablesFor(this.dialect).agentThread;
1380
+ const [row] = await this.db.select().from(thread).where(and(eq(thread.id, threadId), isNull(thread.deletedAt))).limit(1);
1381
+ return row?.id === threadId ? {
1382
+ actorRef: row.actorRef,
1383
+ tenantRef: row.tenantRef,
1384
+ threadId: row.id
1385
+ } : null;
1386
+ }
1387
+ async claimNextActionProposalOutcome(command) {
1388
+ const now = this.clock();
1389
+ validateActionProposalWorkerClaim(command, now);
1390
+ const table = this.table;
1391
+ const candidates = await this.db.select().from(table).where(and(eq(table.deliveryStatus, "pending"), or(isNull(table.deliveryLeaseExpiresAt), lte(table.deliveryLeaseExpiresAt, now)))).orderBy(asc(table.createdAt), asc(table.logicalSort)).limit(32);
1392
+ for (const row of candidates) {
1393
+ const result = await this.mutate(row.proposal, row.proposal.id, (proposal, time) => {
1394
+ const claimed2 = claimActionProposalOutcome(proposal, command, time, randomUUID());
1395
+ return claimed2 ? {
1396
+ status: "applied",
1397
+ proposal: claimed2
1398
+ } : {
1399
+ status: "conflict",
1400
+ proposal
1401
+ };
1402
+ });
1403
+ const claimed = result.proposal;
1404
+ if (result.status === "applied" && claimed?.outcome && claimed.outcomeDelivery?.lease) {
1405
+ return {
1406
+ outcome: claimed.outcome,
1407
+ lease: {
1408
+ outcomeId: claimed.outcome.id,
1409
+ token: claimed.outcomeDelivery.lease.token,
1410
+ generation: claimed.outcomeDelivery.generation
1411
+ }
1412
+ };
1413
+ }
1414
+ }
1415
+ return null;
1416
+ }
1417
+ async admitActionProposalOutcome(command) {
1418
+ return this.transactionSteps((db) => this.admissionSteps(db, command));
1419
+ }
1420
+ async transactionSteps(factory) {
1421
+ if (!this.actionProposalAdmissionSupported) throw new Error("Independent actions require a certified transactional Drizzle driver (better-sqlite3, node-postgres, mysql2 or libsql)");
1422
+ if (this.synchronousSqlite) {
1423
+ const database2 = this.rawDb;
1424
+ return database2.transaction((tx) => runSync(factory(asBuilder(tx))), {
1425
+ behavior: "immediate"
1426
+ });
1427
+ }
1428
+ const database = this.rawDb;
1429
+ return database.transaction(async (tx) => runAsync(factory(asBuilder(tx))));
1430
+ }
1431
+ *admissionSteps(db, command) {
1432
+ if (typeof command.outcomeId !== "string" || !command.outcomeId || typeof command.token !== "string" || !command.token || !Number.isSafeInteger(command.generation) || command.generation < 1) throw new TypeError("Invalid outcome fence");
1433
+ const table = this.table;
1434
+ const tables = agentTablesFor(this.dialect);
1435
+ if (this.dialect === "sqlite") yield {
1436
+ kind: "write",
1437
+ query: db.update(table).set({
1438
+ version: sql2`${table.version}`
1439
+ }).where(eq(table.outcomeIdKey, physicalId(command.outcomeId)))
1440
+ };
1441
+ const query = db.select().from(table).where(eq(table.outcomeIdKey, physicalId(command.outcomeId))).limit(1);
1442
+ const rows = yield {
1443
+ kind: "read",
1444
+ query: lockQuery(query, this.dialect)
1445
+ };
1446
+ const row = rows[0];
1447
+ if (!row || row.proposal.outcome?.id !== command.outcomeId) return {
1448
+ status: "not_found"
1449
+ };
1450
+ const proposal = row.proposal;
1451
+ const outcome = proposal.outcome;
1452
+ const delivery = proposal.outcomeDelivery;
1453
+ if (!outcome || !delivery) return {
1454
+ status: "not_found"
1455
+ };
1456
+ if (proposal.outcomeDelivery?.status === "admitted") return {
1457
+ status: "unchanged",
1458
+ ...proposal.outcomeDelivery.messageId !== void 0 ? {
1459
+ messageId: proposal.outcomeDelivery.messageId
1460
+ } : {}
1461
+ };
1462
+ if (proposal.outcomeDelivery?.status === "discarded") return {
1463
+ status: "discarded"
1464
+ };
1465
+ if (!actionProposalOutcomeFenceValid(proposal, command, this.clock())) return {
1466
+ status: "conflict"
1467
+ };
1468
+ const threadQuery = db.select().from(tables.agentThread).where(eq(tables.agentThread.id, proposal.threadId)).limit(1);
1469
+ const threads = yield {
1470
+ kind: "read",
1471
+ query: lockQuery(threadQuery, this.dialect)
1472
+ };
1473
+ const thread = threads[0];
1474
+ const now = this.clock();
1475
+ if (!actionProposalOutcomeFenceValid(proposal, command, now)) return {
1476
+ status: "conflict"
1477
+ };
1478
+ if (!thread || thread.id !== proposal.threadId || thread.deletedAt || thread.actorRef !== proposal.actorRef || thread.tenantRef !== proposal.tenantRef) {
1479
+ const discarded = {
1480
+ ...proposal,
1481
+ outcomeDelivery: {
1482
+ ...delivery,
1483
+ status: "discarded",
1484
+ lease: null
1485
+ },
1486
+ updatedAt: now
1487
+ };
1488
+ yield {
1489
+ kind: "write",
1490
+ query: db.update(table).set({
1491
+ proposal: discarded,
1492
+ ...discoveryMetadata(discarded),
1493
+ version: row.version + 1
1494
+ }).where(and(eq(table.id, row.id), eq(table.version, row.version)))
1495
+ };
1496
+ return {
1497
+ status: "discarded"
1498
+ };
1499
+ }
1500
+ if (thread.activeStreamId !== null) return {
1501
+ status: "busy"
1502
+ };
1503
+ const seqRows = yield {
1504
+ kind: "read",
1505
+ query: db.select({
1506
+ last: max(tables.agentMessage.seq)
1507
+ }).from(tables.agentMessage).where(eq(tables.agentMessage.threadId, thread.id))
1508
+ };
1509
+ const messageId = physicalId(command.outcomeId);
1510
+ yield {
1511
+ kind: "write",
1512
+ query: db.insert(tables.agentMessage).values({
1513
+ id: messageId,
1514
+ threadId: thread.id,
1515
+ role: "assistant",
1516
+ content: actionProposalOutcomeText(outcome),
1517
+ actionProposalOutcome: canonicalActionProposalJson3(outcome),
1518
+ ui: null,
1519
+ seq: Number(seqRows[0]?.last ?? 0) + 1,
1520
+ createdAt: new Date(now)
1521
+ })
1522
+ };
1523
+ yield {
1524
+ kind: "write",
1525
+ query: db.update(tables.agentThread).set({
1526
+ updatedAt: new Date(now)
1527
+ }).where(eq(tables.agentThread.id, thread.id))
1528
+ };
1529
+ const admitted = {
1530
+ ...proposal,
1531
+ outcomeDelivery: {
1532
+ ...delivery,
1533
+ status: "admitted",
1534
+ lease: null,
1535
+ messageId
1536
+ },
1537
+ updatedAt: now
1538
+ };
1539
+ const update = db.update(table).set({
1540
+ proposal: admitted,
1541
+ ...discoveryMetadata(admitted),
1542
+ version: row.version + 1
1543
+ }).where(and(eq(table.id, row.id), eq(table.version, row.version)));
1544
+ const changed = yield {
1545
+ kind: "read",
1546
+ query: this.dialect === "mysql" ? update : update.returning({
1547
+ id: table.id
1548
+ })
1549
+ };
1550
+ const count3 = this.dialect === "mysql" ? mysqlAffectedRows(changed) : changed.length;
1551
+ if (count3 !== 1) throw new Error("Outcome admission lost its locked proposal fence");
1552
+ return {
1553
+ status: "applied",
1554
+ messageId
1555
+ };
1556
+ }
1557
+ async read(scope, id) {
1558
+ const [row] = await this.db.select().from(this.table).where(and(eq(this.table.id, physicalId(id)), eq(this.table.scopeKey, scopeKey(scope)))).limit(1);
1559
+ return row && row.proposal.id === id && actionProposalScopeMatches(row.proposal, scope) ? row : void 0;
1560
+ }
1561
+ async mutate(scope, id, transition) {
1562
+ for (let attempt = 0; attempt < 32; attempt++) {
1563
+ const row2 = await this.read(scope, id);
1564
+ if (!row2) return {
1565
+ status: "not_found"
1566
+ };
1567
+ const result = transition(row2.proposal, this.clock());
1568
+ if (!result.proposal || canonicalActionProposalJson3(result.proposal) === canonicalActionProposalJson3(row2.proposal)) return result;
1569
+ const changed = await affectedRows(this.dialect, this.db.update(this.table).set({
1570
+ proposal: result.proposal,
1571
+ decision: result.proposal.decision,
1572
+ ...discoveryMetadata(result.proposal),
1573
+ version: row2.version + 1
1574
+ }).where(and(eq(this.table.id, physicalId(id)), eq(this.table.scopeKey, scopeKey(scope)), eq(this.table.version, row2.version))), this.table.id);
1575
+ if (changed === 1) return result;
1576
+ }
1577
+ const row = await this.read(scope, id);
1578
+ return row ? {
1579
+ status: "conflict",
1580
+ proposal: row.proposal
1581
+ } : {
1582
+ status: "not_found"
1583
+ };
1584
+ }
597
1585
  };
1586
+ function scopeKey(scope) {
1587
+ return createHash("sha256").update(canonicalActionProposalJson3([
1588
+ scope.tenantRef,
1589
+ scope.actorRef,
1590
+ scope.threadId
1591
+ ])).digest("hex");
1592
+ }
1593
+ __name(scopeKey, "scopeKey");
1594
+ function physicalId(id) {
1595
+ return createHash("sha256").update(canonicalActionProposalJson3(id)).digest("hex");
1596
+ }
1597
+ __name(physicalId, "physicalId");
1598
+ function logicalSort(id) {
1599
+ let sort = "";
1600
+ for (let index4 = 0; index4 < id.length; index4++) sort += id.charCodeAt(index4).toString(16).padStart(4, "0");
1601
+ return sort;
1602
+ }
1603
+ __name(logicalSort, "logicalSort");
1604
+ function discoveryMetadata(proposal) {
1605
+ return {
1606
+ replacementGroupKey: replacementGroupKey(proposal),
1607
+ deliveryStatus: proposal.outcomeDelivery?.status ?? null,
1608
+ deliveryLeaseExpiresAt: proposal.outcomeDelivery?.lease?.expiresAt ?? null,
1609
+ outcomeIdKey: proposal.outcome ? physicalId(proposal.outcome.id) : null,
1610
+ executionStatus: proposal.execution?.status ?? null,
1611
+ leaseExpiresAt: proposal.execution?.lease?.expiresAt ?? null,
1612
+ proposalExpiresAt: proposal.expiresAt,
1613
+ discoveryIndexVersion: 1
1614
+ };
1615
+ }
1616
+ __name(discoveryMetadata, "discoveryMetadata");
1617
+ function lockQuery(query, dialect) {
1618
+ return dialect === "sqlite" ? query : query.for("update");
1619
+ }
1620
+ __name(lockQuery, "lockQuery");
1621
+ function runSync(steps) {
1622
+ let next = steps.next();
1623
+ while (!next.done) {
1624
+ const { kind, query } = next.value;
1625
+ const statement = query;
1626
+ next = steps.next(kind === "read" ? statement.all() : statement.run());
1627
+ }
1628
+ return next.value;
1629
+ }
1630
+ __name(runSync, "runSync");
1631
+ async function runAsync(steps) {
1632
+ let next = steps.next();
1633
+ while (!next.done) next = steps.next(await next.value.query);
1634
+ return next.value;
1635
+ }
1636
+ __name(runAsync, "runAsync");
1637
+ function replacementGroupKey(proposal) {
1638
+ return proposal.replacementKey ? physicalId(canonicalActionProposalJson3([
1639
+ proposal.toolName,
1640
+ proposal.replacementKey
1641
+ ])) : null;
1642
+ }
1643
+ __name(replacementGroupKey, "replacementGroupKey");
1644
+
1645
+ // src/drizzle-agent-store.ts
1646
+ function turnMessageColumns(message) {
1647
+ return {
1648
+ id: message.id,
1649
+ role: message.role,
1650
+ content: message.content,
1651
+ agentName: message.agentName,
1652
+ toolCalls: message.toolCalls,
1653
+ toolResults: message.toolResults,
1654
+ attachments: message.attachments,
1655
+ createdAt: message.createdAt
1656
+ };
1657
+ }
1658
+ __name(turnMessageColumns, "turnMessageColumns");
598
1659
  var DrizzleAgentStore = class {
599
1660
  static {
600
1661
  __name(this, "DrizzleAgentStore");
601
1662
  }
602
1663
  db;
603
- constructor(db) {
604
- this.db = db;
1664
+ dialect;
1665
+ t;
1666
+ proposals;
1667
+ constructor(db, options = {}) {
1668
+ this.proposals = new DrizzleActionProposalStore(db, options);
1669
+ this.dialect = agentDialectOf(db);
1670
+ this.t = agentTablesFor(this.dialect);
1671
+ this.db = asBuilder(db);
1672
+ }
1673
+ createActionProposal(...args) {
1674
+ return this.proposals.createActionProposal(...args);
1675
+ }
1676
+ getActionProposal(...args) {
1677
+ return this.proposals.getActionProposal(...args);
1678
+ }
1679
+ listActionProposals(...args) {
1680
+ return this.proposals.listActionProposals(...args);
1681
+ }
1682
+ decideActionProposal(...args) {
1683
+ return this.proposals.decideActionProposal(...args);
1684
+ }
1685
+ claimActionProposal(...args) {
1686
+ return this.proposals.claimActionProposal(...args);
1687
+ }
1688
+ extendActionProposalLease(...args) {
1689
+ return this.proposals.extendActionProposalLease(...args);
1690
+ }
1691
+ claimNextActionProposal(...args) {
1692
+ return this.proposals.claimNextActionProposal(...args);
1693
+ }
1694
+ expireActionProposals(...args) {
1695
+ return this.proposals.expireActionProposals(...args);
1696
+ }
1697
+ backfillActionProposalDiscoveryIndex(command) {
1698
+ return this.proposals.backfillActionProposalDiscoveryIndex(command);
1699
+ }
1700
+ settleActionProposal(...args) {
1701
+ return this.proposals.settleActionProposal(...args);
1702
+ }
1703
+ createReplacingActionProposal(...args) {
1704
+ return this.proposals.createReplacingActionProposal(...args);
1705
+ }
1706
+ supersedeActionProposal(...args) {
1707
+ return this.proposals.supersedeActionProposal(...args);
1708
+ }
1709
+ get actionProposalAdmissionSupported() {
1710
+ return this.proposals.actionProposalAdmissionSupported;
1711
+ }
1712
+ getThreadActionProposalScope(threadId) {
1713
+ return this.proposals.getThreadActionProposalScope(threadId);
1714
+ }
1715
+ claimNextActionProposalOutcome(...args) {
1716
+ return this.proposals.claimNextActionProposalOutcome(...args);
1717
+ }
1718
+ admitActionProposalOutcome(...args) {
1719
+ return this.proposals.admitActionProposalOutcome(...args);
605
1720
  }
606
1721
  async createThread(input) {
607
1722
  const now = /* @__PURE__ */ new Date();
@@ -620,15 +1735,15 @@ var DrizzleAgentStore = class {
620
1735
  updatedAt: now,
621
1736
  deletedAt: null
622
1737
  };
623
- await this.db.insert(agentThread).values(thread);
1738
+ await this.db.insert(this.t.agentThread).values(thread);
624
1739
  return this.toSummary(thread);
625
1740
  }
626
1741
  async getThread(threadId) {
627
- const [thread] = await this.db.select().from(agentThread).where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));
1742
+ const [thread] = await this.db.select().from(this.t.agentThread).where(and2(eq2(this.t.agentThread.id, threadId), isNull2(this.t.agentThread.deletedAt)));
628
1743
  if (thread === void 0) {
629
1744
  return null;
630
1745
  }
631
- const messages = await this.db.select().from(agentMessage).where(eq(agentMessage.threadId, threadId)).orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));
1746
+ const messages = await this.db.select().from(this.t.agentMessage).where(eq2(this.t.agentMessage.threadId, threadId)).orderBy(...this.messageOrder());
632
1747
  const last = messages[messages.length - 1];
633
1748
  const approvals = await this.approvalsFor(messages.map((message) => message.id));
634
1749
  return {
@@ -661,16 +1776,16 @@ var DrizzleAgentStore = class {
661
1776
  */
662
1777
  async loadThreadForTurn(query) {
663
1778
  const [thread] = await this.db.select({
664
- title: agentThread.title,
665
- defaultAgent: agentThread.defaultAgent
666
- }).from(agentThread).where(and(eq(agentThread.id, query.threadId), isNull(agentThread.deletedAt)));
1779
+ title: this.t.agentThread.title,
1780
+ defaultAgent: this.t.agentThread.defaultAgent
1781
+ }).from(this.t.agentThread).where(and2(eq2(this.t.agentThread.id, query.threadId), isNull2(this.t.agentThread.deletedAt)));
667
1782
  if (thread === void 0) {
668
1783
  return null;
669
1784
  }
670
1785
  const messages = await this.loadTurnWindow(query.threadId, query.messageLimit);
671
1786
  const [answered] = await this.db.select({
672
- id: agentMessage.id
673
- }).from(agentMessage).where(and(eq(agentMessage.threadId, query.threadId), eq(agentMessage.role, "assistant"))).limit(1);
1787
+ id: this.t.agentMessage.id
1788
+ }).from(this.t.agentMessage).where(and2(eq2(this.t.agentMessage.threadId, query.threadId), eq2(this.t.agentMessage.role, "assistant"))).limit(1);
674
1789
  return {
675
1790
  title: thread.title,
676
1791
  defaultAgent: thread.defaultAgent,
@@ -686,30 +1801,30 @@ var DrizzleAgentStore = class {
686
1801
  if (limit !== void 0 && limit <= 0) {
687
1802
  return [];
688
1803
  }
689
- const window = this.db.select(TURN_MESSAGE_COLUMNS).from(agentMessage).where(eq(agentMessage.threadId, threadId)).orderBy(desc(agentMessage.createdAt), desc(agentMessage.id));
1804
+ const window = this.db.select(turnMessageColumns(this.t.agentMessage)).from(this.t.agentMessage).where(eq2(this.t.agentMessage.threadId, threadId)).orderBy(...this.messageOrderNewestFirst());
690
1805
  const rows = limit === void 0 ? await window : await window.limit(limit);
691
1806
  return rows.reverse().map((row) => this.toStoredMessage(row));
692
1807
  }
693
1808
  async listThreads(actorRef, limit = 50) {
694
- const threads = await this.db.select().from(agentThread).where(and(eq(agentThread.actorRef, actorRef), eq(agentThread.transient, false), isNull(agentThread.deletedAt))).orderBy(desc(agentThread.updatedAt)).limit(limit);
1809
+ const threads = await this.db.select().from(this.t.agentThread).where(and2(eq2(this.t.agentThread.actorRef, actorRef), eq2(this.t.agentThread.transient, false), isNull2(this.t.agentThread.deletedAt))).orderBy(desc(this.t.agentThread.updatedAt)).limit(limit);
695
1810
  const summaries = [];
696
1811
  for (const thread of threads) {
697
- const [last] = await this.db.select().from(agentMessage).where(eq(agentMessage.threadId, thread.id)).orderBy(desc(agentMessage.createdAt), desc(agentMessage.id)).limit(1);
1812
+ const [last] = await this.db.select().from(this.t.agentMessage).where(eq2(this.t.agentMessage.threadId, thread.id)).orderBy(...this.messageOrderNewestFirst()).limit(1);
698
1813
  summaries.push(this.toSummary(thread, last?.content));
699
1814
  }
700
1815
  return summaries;
701
1816
  }
702
1817
  async softDeleteThread(threadId) {
703
- await this.db.update(agentThread).set({
1818
+ await this.db.update(this.t.agentThread).set({
704
1819
  deletedAt: /* @__PURE__ */ new Date()
705
- }).where(eq(agentThread.id, threadId));
1820
+ }).where(eq2(this.t.agentThread.id, threadId));
706
1821
  }
707
1822
  async forkThread(threadId, fromMessageId) {
708
- const [source] = await this.db.select().from(agentThread).where(eq(agentThread.id, threadId));
1823
+ const [source] = await this.db.select().from(this.t.agentThread).where(eq2(this.t.agentThread.id, threadId));
709
1824
  if (source === void 0) {
710
1825
  throw new Error(`thread ${threadId} not found`);
711
1826
  }
712
- const messages = await this.db.select().from(agentMessage).where(eq(agentMessage.threadId, threadId)).orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));
1827
+ const messages = await this.db.select().from(this.t.agentMessage).where(eq2(this.t.agentMessage.threadId, threadId)).orderBy(...this.messageOrder());
713
1828
  const cutoff = messages.findIndex((message) => message.id === fromMessageId);
714
1829
  const kept = cutoff >= 0 ? messages.slice(0, cutoff + 1) : messages;
715
1830
  const now = /* @__PURE__ */ new Date();
@@ -729,10 +1844,12 @@ var DrizzleAgentStore = class {
729
1844
  updatedAt: now,
730
1845
  deletedAt: null
731
1846
  };
732
- await this.db.insert(agentThread).values(fork);
1847
+ await this.db.insert(this.t.agentThread).values(fork);
733
1848
  if (kept.length > 0) {
734
- await this.db.insert(agentMessage).values(kept.map((message) => ({
1849
+ await this.db.insert(this.t.agentMessage).values(kept.map((message, index4) => ({
735
1850
  id: crypto.randomUUID(),
1851
+ // Numbered afresh in the order just read, so the copy reads back in the original's order.
1852
+ seq: index4 + 1,
736
1853
  threadId: fork.id,
737
1854
  role: message.role,
738
1855
  content: message.content,
@@ -750,6 +1867,7 @@ var DrizzleAgentStore = class {
750
1867
  reasoning: message.reasoning,
751
1868
  reasoningMs: message.reasoningMs,
752
1869
  ui: message.ui,
1870
+ actionProposalOutcome: message.actionProposalOutcome,
753
1871
  createdAt: message.createdAt
754
1872
  })));
755
1873
  }
@@ -757,21 +1875,21 @@ var DrizzleAgentStore = class {
757
1875
  }
758
1876
  async ownerOfThread(threadId) {
759
1877
  const [thread] = await this.db.select({
760
- actorRef: agentThread.actorRef
761
- }).from(agentThread).where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));
1878
+ actorRef: this.t.agentThread.actorRef
1879
+ }).from(this.t.agentThread).where(and2(eq2(this.t.agentThread.id, threadId), isNull2(this.t.agentThread.deletedAt)));
762
1880
  return thread?.actorRef ?? null;
763
1881
  }
764
1882
  async ownerOfToolCall(toolCallId) {
765
1883
  const [row] = await this.db.select({
766
- actorRef: agentThread.actorRef
767
- }).from(agentToolCall).innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id)).innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id)).where(eq(agentToolCall.id, toolCallId));
1884
+ actorRef: this.t.agentThread.actorRef
1885
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq2(this.t.agentToolCall.messageId, this.t.agentMessage.id)).innerJoin(this.t.agentThread, eq2(this.t.agentMessage.threadId, this.t.agentThread.id)).where(eq2(this.t.agentToolCall.id, toolCallId));
768
1886
  return row?.actorRef ?? null;
769
1887
  }
770
1888
  async runForToolCall(toolCallId) {
771
1889
  const [row] = await this.db.select({
772
- runId: agentToolCall.runId,
773
- activeStreamId: agentThread.activeStreamId
774
- }).from(agentToolCall).innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id)).innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id)).where(eq(agentToolCall.id, toolCallId));
1890
+ runId: this.t.agentToolCall.runId,
1891
+ activeStreamId: this.t.agentThread.activeStreamId
1892
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq2(this.t.agentToolCall.messageId, this.t.agentMessage.id)).innerJoin(this.t.agentThread, eq2(this.t.agentMessage.threadId, this.t.agentThread.id)).where(eq2(this.t.agentToolCall.id, toolCallId));
775
1893
  return row?.runId ?? row?.activeStreamId ?? null;
776
1894
  }
777
1895
  /**
@@ -785,16 +1903,17 @@ var DrizzleAgentStore = class {
785
1903
  return byMessage;
786
1904
  }
787
1905
  const rows = await this.db.select({
788
- id: agentToolCall.id,
789
- messageId: agentToolCall.messageId,
790
- status: agentToolCall.status,
791
- approver: agentToolCall.approver,
792
- expiresAt: agentToolCall.expiresAt,
793
- remember: agentToolCall.remember,
794
- executedByRef: agentToolCall.executedByRef,
795
- decidedVia: agentToolCall.decidedVia,
796
- error: agentToolCall.error
797
- }).from(agentToolCall).where(and(inArray(agentToolCall.messageId, messageIds), isNotNull(agentToolCall.approver))).orderBy(asc(agentToolCall.createdAt), asc(agentToolCall.id));
1906
+ id: this.t.agentToolCall.id,
1907
+ messageId: this.t.agentToolCall.messageId,
1908
+ status: this.t.agentToolCall.status,
1909
+ approver: this.t.agentToolCall.approver,
1910
+ confirmation: this.t.agentToolCall.confirmation,
1911
+ expiresAt: this.t.agentToolCall.expiresAt,
1912
+ remember: this.t.agentToolCall.remember,
1913
+ executedByRef: this.t.agentToolCall.executedByRef,
1914
+ decidedVia: this.t.agentToolCall.decidedVia,
1915
+ error: this.t.agentToolCall.error
1916
+ }).from(this.t.agentToolCall).where(and2(inArray(this.t.agentToolCall.messageId, messageIds), isNotNull(this.t.agentToolCall.approver))).orderBy(asc2(this.t.agentToolCall.createdAt), asc2(this.t.agentToolCall.id));
798
1917
  for (const row of rows) {
799
1918
  const approval = toolCallApprovalFromRow({
800
1919
  ...row,
@@ -812,22 +1931,29 @@ var DrizzleAgentStore = class {
812
1931
  /** Tools whose approval someone asked to remember in this thread. */
813
1932
  async rememberedApprovals(threadId) {
814
1933
  const rows = await this.db.selectDistinct({
815
- toolName: agentToolCall.toolName
816
- }).from(agentToolCall).innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id)).where(and(eq(agentMessage.threadId, threadId), eq(agentToolCall.remember, true)));
817
- return rows.map((row) => row.toolName);
1934
+ toolName: this.t.agentToolCall.toolName
1935
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq2(this.t.agentToolCall.messageId, this.t.agentMessage.id)).where(and2(eq2(this.t.agentMessage.threadId, threadId), eq2(this.t.agentToolCall.remember, true)));
1936
+ const scope = await this.getThreadActionProposalScope(threadId);
1937
+ const proposalNames = scope ? await this.proposals.rememberedActionProposalApprovals(scope) : [];
1938
+ return [
1939
+ .../* @__PURE__ */ new Set([
1940
+ ...rows.map((row) => row.toolName),
1941
+ ...proposalNames
1942
+ ])
1943
+ ];
818
1944
  }
819
1945
  async toolCallInput(toolCallId) {
820
1946
  const [row] = await this.db.select({
821
- input: agentToolCall.input
822
- }).from(agentToolCall).where(eq(agentToolCall.id, toolCallId));
1947
+ input: this.t.agentToolCall.input
1948
+ }).from(this.t.agentToolCall).where(eq2(this.t.agentToolCall.id, toolCallId));
823
1949
  return row?.input ?? null;
824
1950
  }
825
1951
  async toolCallApproval(toolCallId) {
826
1952
  const [row] = await this.db.select({
827
- status: agentToolCall.status,
828
- approver: agentToolCall.approver,
829
- expiresAt: agentToolCall.expiresAt
830
- }).from(agentToolCall).where(eq(agentToolCall.id, toolCallId));
1953
+ status: this.t.agentToolCall.status,
1954
+ approver: this.t.agentToolCall.approver,
1955
+ expiresAt: this.t.agentToolCall.expiresAt
1956
+ }).from(this.t.agentToolCall).where(eq2(this.t.agentToolCall.id, toolCallId));
831
1957
  if (row === void 0) {
832
1958
  return null;
833
1959
  }
@@ -839,27 +1965,67 @@ var DrizzleAgentStore = class {
839
1965
  }
840
1966
  async ownerOfActiveStream(runId) {
841
1967
  const [thread] = await this.db.select({
842
- actorRef: agentThread.actorRef
843
- }).from(agentThread).where(and(eq(agentThread.activeStreamId, runId), isNull(agentThread.deletedAt)));
1968
+ actorRef: this.t.agentThread.actorRef
1969
+ }).from(this.t.agentThread).where(and2(eq2(this.t.agentThread.activeStreamId, runId), isNull2(this.t.agentThread.deletedAt)));
844
1970
  return thread?.actorRef ?? null;
845
1971
  }
846
1972
  async setTitle(threadId, title) {
847
- await this.db.update(agentThread).set({
1973
+ await this.db.update(this.t.agentThread).set({
848
1974
  title,
849
1975
  updatedAt: /* @__PURE__ */ new Date()
850
- }).where(eq(agentThread.id, threadId));
1976
+ }).where(eq2(this.t.agentThread.id, threadId));
851
1977
  }
852
1978
  async promoteThread(threadId) {
853
- await this.db.update(agentThread).set({
1979
+ await this.db.update(this.t.agentThread).set({
854
1980
  transient: false,
855
1981
  updatedAt: /* @__PURE__ */ new Date()
856
- }).where(and(eq(agentThread.id, threadId), eq(agentThread.transient, true)));
1982
+ }).where(and2(eq2(this.t.agentThread.id, threadId), eq2(this.t.agentThread.transient, true)));
1983
+ }
1984
+ /** Who holds the thread's stream right now, deleted or not. */
1985
+ async activeHolder(threadId) {
1986
+ const [thread] = await this.db.select({
1987
+ activeStreamId: this.t.agentThread.activeStreamId
1988
+ }).from(this.t.agentThread).where(eq2(this.t.agentThread.id, threadId));
1989
+ return thread?.activeStreamId ?? null;
1990
+ }
1991
+ /**
1992
+ * A thread's messages in the order they were appended: by `seq`, which append assigns. A row from
1993
+ * before `seq` existed has none and counts as 0 — first, since every such row is older than every
1994
+ * numbered one — and those order among themselves by `created_at`, then `id`, as they always did.
1995
+ * `coalesce` rather than `nulls first`, which MySQL cannot spell and Postgres defaults the other way.
1996
+ */
1997
+ messageOrder() {
1998
+ const message = this.t.agentMessage;
1999
+ return [
2000
+ asc2(sql3`coalesce(${message.seq}, 0)`),
2001
+ asc2(message.createdAt),
2002
+ asc2(message.id)
2003
+ ];
2004
+ }
2005
+ /** {@link messageOrder}, newest first. */
2006
+ messageOrderNewestFirst() {
2007
+ const message = this.t.agentMessage;
2008
+ return [
2009
+ desc(sql3`coalesce(${message.seq}, 0)`),
2010
+ desc(message.createdAt),
2011
+ desc(message.id)
2012
+ ];
2013
+ }
2014
+ /**
2015
+ * The next `seq` in a thread: one past its highest. Two appends racing on ONE thread can draw the
2016
+ * same number — the turn loop never does that, and the tie then falls back to `created_at`, `id`.
2017
+ */
2018
+ async nextMessageSeq(threadId) {
2019
+ const [row] = await this.db.select({
2020
+ last: max2(this.t.agentMessage.seq)
2021
+ }).from(this.t.agentMessage).where(eq2(this.t.agentMessage.threadId, threadId));
2022
+ return Number(row?.last ?? 0) + 1;
857
2023
  }
858
2024
  /** The run streaming the thread, or `null` — a projection of the one column. */
859
2025
  async activeRunForThread(threadId) {
860
2026
  const [thread] = await this.db.select({
861
- activeStreamId: agentThread.activeStreamId
862
- }).from(agentThread).where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));
2027
+ activeStreamId: this.t.agentThread.activeStreamId
2028
+ }).from(this.t.agentThread).where(and2(eq2(this.t.agentThread.id, threadId), isNull2(this.t.agentThread.deletedAt)));
863
2029
  return thread?.activeStreamId ?? null;
864
2030
  }
865
2031
  /**
@@ -868,39 +2034,39 @@ var DrizzleAgentStore = class {
868
2034
  */
869
2035
  async claimActiveStream(threadId, runId, options = {}) {
870
2036
  const holders = [
871
- isNull(agentThread.activeStreamId),
872
- eq(agentThread.activeStreamId, runId),
2037
+ isNull2(this.t.agentThread.activeStreamId),
2038
+ eq2(this.t.agentThread.activeStreamId, runId),
873
2039
  ...options.replacing !== void 0 ? [
874
- eq(agentThread.activeStreamId, options.replacing)
2040
+ eq2(this.t.agentThread.activeStreamId, options.replacing)
875
2041
  ] : []
876
2042
  ];
877
- const claimed = await this.db.update(agentThread).set({
2043
+ const claimed = await affectedRows(this.dialect, this.db.update(this.t.agentThread).set({
878
2044
  activeStreamId: runId
879
- }).where(and(eq(agentThread.id, threadId), or(...holders))).returning({
880
- id: agentThread.id
881
- });
882
- return claimed.length > 0;
2045
+ }).where(and2(eq2(this.t.agentThread.id, threadId), or2(...holders))), this.t.agentThread.id);
2046
+ if (claimed > 0) {
2047
+ return true;
2048
+ }
2049
+ return await this.activeHolder(threadId) === runId;
883
2050
  }
884
2051
  async releaseActiveStream(threadId, runId) {
885
- const released = await this.db.update(agentThread).set({
2052
+ const released = await affectedRows(this.dialect, this.db.update(this.t.agentThread).set({
886
2053
  activeStreamId: null
887
- }).where(and(eq(agentThread.id, threadId), eq(agentThread.activeStreamId, runId))).returning({
888
- id: agentThread.id
889
- });
890
- return released.length > 0;
2054
+ }).where(and2(eq2(this.t.agentThread.id, threadId), eq2(this.t.agentThread.activeStreamId, runId))), this.t.agentThread.id);
2055
+ return released > 0;
891
2056
  }
892
2057
  async enqueueMessage(input) {
893
2058
  const now = /* @__PURE__ */ new Date();
894
2059
  const [edge] = await this.db.select({
895
- first: min(agentQueuedMessage.position),
896
- last: max(agentQueuedMessage.position)
897
- }).from(agentQueuedMessage).where(eq(agentQueuedMessage.threadId, input.threadId));
2060
+ first: min(this.t.agentQueuedMessage.position),
2061
+ last: max2(this.t.agentQueuedMessage.position)
2062
+ }).from(this.t.agentQueuedMessage).where(eq2(this.t.agentQueuedMessage.threadId, input.threadId));
898
2063
  const position = input.at === "head" ? (edge?.first ?? 1) - 1 : (edge?.last ?? -1) + 1;
899
2064
  const row = {
900
2065
  id: crypto.randomUUID(),
901
2066
  threadId: input.threadId,
902
2067
  actor: input.actor,
903
2068
  content: input.content,
2069
+ uiCapabilities: input.uiCapabilities ?? null,
904
2070
  attachments: input.attachments !== void 0 && input.attachments.length > 0 ? input.attachments : null,
905
2071
  agentName: input.agentName ?? null,
906
2072
  persona: input.persona ?? null,
@@ -911,15 +2077,15 @@ var DrizzleAgentStore = class {
911
2077
  createdAt: now,
912
2078
  updatedAt: now
913
2079
  };
914
- await this.db.insert(agentQueuedMessage).values(row);
2080
+ await this.db.insert(this.t.agentQueuedMessage).values(row);
915
2081
  return toQueuedMessage(row);
916
2082
  }
917
2083
  async listQueue(threadId) {
918
- const rows = await this.db.select().from(agentQueuedMessage).where(eq(agentQueuedMessage.threadId, threadId)).orderBy(asc(agentQueuedMessage.position), asc(agentQueuedMessage.createdAt));
2084
+ const rows = await this.db.select().from(this.t.agentQueuedMessage).where(eq2(this.t.agentQueuedMessage.threadId, threadId)).orderBy(asc2(this.t.agentQueuedMessage.position), asc2(this.t.agentQueuedMessage.createdAt));
919
2085
  return rows.map(toQueuedMessage);
920
2086
  }
921
2087
  async getQueuedMessage(id) {
922
- const [row] = await this.db.select().from(agentQueuedMessage).where(eq(agentQueuedMessage.id, id));
2088
+ const [row] = await this.db.select().from(this.t.agentQueuedMessage).where(eq2(this.t.agentQueuedMessage.id, id));
923
2089
  return row === void 0 ? null : toQueuedMessage(row);
924
2090
  }
925
2091
  async updateQueuedMessage(id, patch) {
@@ -935,52 +2101,47 @@ var DrizzleAgentStore = class {
935
2101
  if (patch.interrupt !== void 0) {
936
2102
  updates.interrupt = patch.interrupt;
937
2103
  }
938
- await this.db.update(agentQueuedMessage).set(updates).where(eq(agentQueuedMessage.id, id));
2104
+ await this.db.update(this.t.agentQueuedMessage).set(updates).where(eq2(this.t.agentQueuedMessage.id, id));
939
2105
  return this.getQueuedMessage(id);
940
2106
  }
941
2107
  /** Rewrites the thread's positions as 0..n-1 in the new order — a queue is a handful of rows. */
942
- async moveQueuedMessage(id, index2) {
2108
+ async moveQueuedMessage(id, index4) {
943
2109
  const moving = await this.getQueuedMessage(id);
944
2110
  if (moving === null) {
945
2111
  return false;
946
2112
  }
947
2113
  const order = (await this.listQueue(moving.threadId)).filter((message) => message.id !== id);
948
- const target = Math.max(0, Math.min(order.length, Math.trunc(index2)));
2114
+ const target = Math.max(0, Math.min(order.length, Math.trunc(index4)));
949
2115
  order.splice(target, 0, moving);
950
2116
  for (const [position, message] of order.entries()) {
951
- await this.db.update(agentQueuedMessage).set({
2117
+ await this.db.update(this.t.agentQueuedMessage).set({
952
2118
  position
953
- }).where(eq(agentQueuedMessage.id, message.id));
2119
+ }).where(eq2(this.t.agentQueuedMessage.id, message.id));
954
2120
  }
955
2121
  return true;
956
2122
  }
957
2123
  async removeQueuedMessage(id) {
958
- const removed = await this.db.delete(agentQueuedMessage).where(eq(agentQueuedMessage.id, id)).returning({
959
- id: agentQueuedMessage.id
960
- });
961
- return removed.length > 0;
2124
+ const removed = await affectedRows(this.dialect, this.db.delete(this.t.agentQueuedMessage).where(eq2(this.t.agentQueuedMessage.id, id)), this.t.agentQueuedMessage.id);
2125
+ return removed > 0;
962
2126
  }
963
2127
  async clearQueue(threadId) {
964
- const removed = await this.db.delete(agentQueuedMessage).where(eq(agentQueuedMessage.threadId, threadId)).returning({
965
- id: agentQueuedMessage.id
966
- });
967
- return removed.length;
2128
+ return affectedRows(this.dialect, this.db.delete(this.t.agentQueuedMessage).where(eq2(this.t.agentQueuedMessage.threadId, threadId)), this.t.agentQueuedMessage.id);
968
2129
  }
969
2130
  async queuePause(threadId) {
970
2131
  const [thread] = await this.db.select({
971
- queuePause: agentThread.queuePause
972
- }).from(agentThread).where(eq(agentThread.id, threadId));
2132
+ queuePause: this.t.agentThread.queuePause
2133
+ }).from(this.t.agentThread).where(eq2(this.t.agentThread.id, threadId));
973
2134
  return thread?.queuePause ?? null;
974
2135
  }
975
2136
  async setQueuePause(threadId, pause) {
976
- await this.db.update(agentThread).set({
2137
+ await this.db.update(this.t.agentThread).set({
977
2138
  queuePause: pause
978
- }).where(eq(agentThread.id, threadId));
2139
+ }).where(eq2(this.t.agentThread.id, threadId));
979
2140
  }
980
2141
  async setActiveStream(threadId, runId) {
981
- await this.db.update(agentThread).set({
2142
+ await this.db.update(this.t.agentThread).set({
982
2143
  activeStreamId: runId
983
- }).where(eq(agentThread.id, threadId));
2144
+ }).where(eq2(this.t.agentThread.id, threadId));
984
2145
  }
985
2146
  /**
986
2147
  * Patch a thread's `title` and/or `defaultAgent`. Each field is only touched when PRESENT in
@@ -1006,7 +2167,7 @@ var DrizzleAgentStore = class {
1006
2167
  return;
1007
2168
  }
1008
2169
  updates.updatedAt = /* @__PURE__ */ new Date();
1009
- await this.db.update(agentThread).set(updates).where(eq(agentThread.id, threadId));
2170
+ await this.db.update(this.t.agentThread).set(updates).where(eq2(this.t.agentThread.id, threadId));
1010
2171
  }
1011
2172
  /**
1012
2173
  * The thread's default agent, projected — the caller wants one nullable scalar to decide which
@@ -1016,21 +2177,21 @@ var DrizzleAgentStore = class {
1016
2177
  /** The thread's pinned model, projected like {@link defaultAgentForThread}. */
1017
2178
  async modelForThread(threadId) {
1018
2179
  const [thread] = await this.db.select({
1019
- model: agentThread.model
1020
- }).from(agentThread).where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));
2180
+ model: this.t.agentThread.model
2181
+ }).from(this.t.agentThread).where(and2(eq2(this.t.agentThread.id, threadId), isNull2(this.t.agentThread.deletedAt)));
1021
2182
  return thread?.model ?? null;
1022
2183
  }
1023
2184
  /** The thread's pinned persona, projected like {@link defaultAgentForThread}. */
1024
2185
  async personaForThread(threadId) {
1025
2186
  const [thread] = await this.db.select({
1026
- persona: agentThread.persona
1027
- }).from(agentThread).where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));
2187
+ persona: this.t.agentThread.persona
2188
+ }).from(agentThread).where(and2(eq2(this.t.agentThread.id, threadId), isNull2(this.t.agentThread.deletedAt)));
1028
2189
  return thread?.persona ?? null;
1029
2190
  }
1030
2191
  async defaultAgentForThread(threadId) {
1031
2192
  const [thread] = await this.db.select({
1032
- defaultAgent: agentThread.defaultAgent
1033
- }).from(agentThread).where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));
2193
+ defaultAgent: this.t.agentThread.defaultAgent
2194
+ }).from(this.t.agentThread).where(and2(eq2(this.t.agentThread.id, threadId), isNull2(this.t.agentThread.deletedAt)));
1034
2195
  return thread?.defaultAgent ?? null;
1035
2196
  }
1036
2197
  /**
@@ -1055,7 +2216,7 @@ var DrizzleAgentStore = class {
1055
2216
  promptHash: run.promptHash ?? null,
1056
2217
  parentRunId: run.parentRunId ?? null
1057
2218
  };
1058
- await this.db.insert(agentRun).values(runRow);
2219
+ await this.db.insert(this.t.agentRun).values(runRow);
1059
2220
  }
1060
2221
  /** Settle a run's outcome. A no-op when the run is unknown (mirrors `setTitle`/`updateThread`). */
1061
2222
  async recordRunEnd(end) {
@@ -1072,16 +2233,16 @@ var DrizzleAgentStore = class {
1072
2233
  if (end.errorMessage !== void 0) {
1073
2234
  updates.errorMessage = end.errorMessage;
1074
2235
  }
1075
- await this.db.update(agentRun).set(updates).where(eq(agentRun.id, end.runId));
2236
+ await this.db.update(this.t.agentRun).set(updates).where(eq2(this.t.agentRun.id, end.runId));
1076
2237
  }
1077
2238
  /** Bump the run's llm-step retry counter. Atomic `retries = retries + 1`, no read-modify-write. */
1078
2239
  async bumpRunRetries(runId) {
1079
- await this.db.update(agentRun).set({
1080
- retries: sql2`${agentRun.retries} + 1`
1081
- }).where(eq(agentRun.id, runId));
2240
+ await this.db.update(this.t.agentRun).set({
2241
+ retries: sql3`${this.t.agentRun.retries} + 1`
2242
+ }).where(eq2(this.t.agentRun.id, runId));
1082
2243
  }
1083
2244
  async appendMessage(input) {
1084
- const [thread] = await this.db.select().from(agentThread).where(eq(agentThread.id, input.threadId));
2245
+ const [thread] = await this.db.select().from(this.t.agentThread).where(eq2(this.t.agentThread.id, input.threadId));
1085
2246
  if (thread === void 0) {
1086
2247
  throw new Error(`thread ${input.threadId} not found`);
1087
2248
  }
@@ -1091,6 +2252,7 @@ var DrizzleAgentStore = class {
1091
2252
  threadId: input.threadId,
1092
2253
  role: input.role,
1093
2254
  content: input.content,
2255
+ actionProposalOutcome: input.actionProposalOutcome ? canonicalActionProposalJson4(input.actionProposalOutcome) : null,
1094
2256
  toolCalls: input.toolCalls ?? null,
1095
2257
  toolResults: input.toolResults ?? null,
1096
2258
  attachments: input.attachments ?? null,
@@ -1103,48 +2265,50 @@ var DrizzleAgentStore = class {
1103
2265
  reasoningMs: input.reasoningMs ?? null,
1104
2266
  ui: input.ui ?? null,
1105
2267
  feedback: null,
2268
+ seq: await this.nextMessageSeq(input.threadId),
1106
2269
  createdAt: now
1107
2270
  };
1108
- await this.db.insert(agentMessage).values(message);
1109
- await this.db.update(agentThread).set({
2271
+ await this.db.insert(this.t.agentMessage).values(message);
2272
+ await this.db.update(this.t.agentThread).set({
1110
2273
  updatedAt: now
1111
- }).where(eq(agentThread.id, input.threadId));
2274
+ }).where(eq2(this.t.agentThread.id, input.threadId));
1112
2275
  return this.toStoredMessage(message);
1113
2276
  }
1114
2277
  async setMessageToolResults(messageId, results) {
1115
- await this.db.update(agentMessage).set({
2278
+ await this.db.update(this.t.agentMessage).set({
1116
2279
  toolResults: results
1117
- }).where(eq(agentMessage.id, messageId));
2280
+ }).where(eq2(this.t.agentMessage.id, messageId));
1118
2281
  }
1119
2282
  async setMessageUi(messageId, ui) {
1120
- await this.db.update(agentMessage).set({
2283
+ await this.db.update(this.t.agentMessage).set({
1121
2284
  ui: ui.length > 0 ? ui : null
1122
- }).where(eq(agentMessage.id, messageId));
2285
+ }).where(eq2(this.t.agentMessage.id, messageId));
1123
2286
  }
1124
2287
  async threadOfMessage(messageId) {
1125
2288
  const [row] = await this.db.select({
1126
- threadId: agentMessage.threadId
1127
- }).from(agentMessage).where(eq(agentMessage.id, messageId)).limit(1);
2289
+ threadId: this.t.agentMessage.threadId
2290
+ }).from(this.t.agentMessage).where(eq2(this.t.agentMessage.id, messageId)).limit(1);
1128
2291
  return row?.threadId ?? null;
1129
2292
  }
1130
2293
  async setMessageFeedback(messageId, feedback) {
1131
- await this.db.update(agentMessage).set({
2294
+ await this.db.update(this.t.agentMessage).set({
1132
2295
  feedback
1133
- }).where(eq(agentMessage.id, messageId));
2296
+ }).where(eq2(this.t.agentMessage.id, messageId));
1134
2297
  }
1135
2298
  async truncateFrom(threadId, messageId) {
1136
- const messages = await this.db.select().from(agentMessage).where(eq(agentMessage.threadId, threadId)).orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));
2299
+ const messages = await this.db.select().from(this.t.agentMessage).where(eq2(this.t.agentMessage.threadId, threadId)).orderBy(...this.messageOrder());
1137
2300
  const cutoff = messages.findIndex((message) => message.id === messageId);
1138
2301
  if (cutoff < 0) {
1139
2302
  return;
1140
2303
  }
1141
2304
  const doomedIds = messages.slice(cutoff).map((message) => message.id);
1142
- await this.db.delete(agentToolCall).where(inArray(agentToolCall.messageId, doomedIds));
1143
- await this.db.delete(agentMessage).where(inArray(agentMessage.id, doomedIds));
2305
+ await this.db.delete(this.t.agentToolCall).where(inArray(this.t.agentToolCall.messageId, doomedIds));
2306
+ await this.db.delete(this.t.agentMessage).where(inArray(this.t.agentMessage.id, doomedIds));
1144
2307
  }
1145
2308
  async recordToolCall(input) {
1146
- await this.db.insert(agentToolCall).values({
2309
+ await this.db.insert(this.t.agentToolCall).values({
1147
2310
  id: input.toolCallId,
2311
+ proposalId: input.proposalId ?? null,
1148
2312
  messageId: input.messageId,
1149
2313
  toolName: input.toolName,
1150
2314
  toolType: input.toolType,
@@ -1158,6 +2322,7 @@ var DrizzleAgentStore = class {
1158
2322
  executedAt: null,
1159
2323
  runId: input.runId ?? null,
1160
2324
  approver: input.approver ?? null,
2325
+ confirmation: input.confirmation ?? null,
1161
2326
  expiresAt: input.expiresAt !== void 0 ? new Date(input.expiresAt) : null,
1162
2327
  remember: null,
1163
2328
  decidedVia: null
@@ -1188,18 +2353,18 @@ var DrizzleAgentStore = class {
1188
2353
  if (input.status === "executed" || input.status === "auto_executed") {
1189
2354
  updates.executedAt = /* @__PURE__ */ new Date();
1190
2355
  }
1191
- await this.db.update(agentToolCall).set(updates).where(eq(agentToolCall.id, input.toolCallId));
2356
+ await this.db.update(this.t.agentToolCall).set(updates).where(eq2(this.t.agentToolCall.id, input.toolCallId));
1192
2357
  }
1193
2358
  async toolCallOutcomes(toolCallIds) {
1194
2359
  if (toolCallIds.length === 0) {
1195
2360
  return [];
1196
2361
  }
1197
2362
  const rows = await this.db.select({
1198
- id: agentToolCall.id,
1199
- status: agentToolCall.status,
1200
- output: agentToolCall.output,
1201
- error: agentToolCall.error
1202
- }).from(agentToolCall).where(inArray(agentToolCall.id, [
2363
+ id: this.t.agentToolCall.id,
2364
+ status: this.t.agentToolCall.status,
2365
+ output: this.t.agentToolCall.output,
2366
+ error: this.t.agentToolCall.error
2367
+ }).from(this.t.agentToolCall).where(inArray(this.t.agentToolCall.id, [
1203
2368
  ...toolCallIds
1204
2369
  ]));
1205
2370
  return rows.map((row) => ({
@@ -1214,14 +2379,14 @@ var DrizzleAgentStore = class {
1214
2379
  }));
1215
2380
  }
1216
2381
  async failUnsettledToolCalls(runId, error) {
1217
- const pending = and(eq(agentToolCall.runId, runId), eq(agentToolCall.status, "pending_approval"));
2382
+ const pending = and2(eq2(this.t.agentToolCall.runId, runId), eq2(this.t.agentToolCall.status, "pending_approval"));
1218
2383
  const rows = await this.db.select({
1219
- id: agentToolCall.id
1220
- }).from(agentToolCall).where(pending);
2384
+ id: this.t.agentToolCall.id
2385
+ }).from(this.t.agentToolCall).where(pending);
1221
2386
  if (rows.length === 0) {
1222
2387
  return 0;
1223
2388
  }
1224
- await this.db.update(agentToolCall).set({
2389
+ await this.db.update(this.t.agentToolCall).set({
1225
2390
  status: "failed",
1226
2391
  error
1227
2392
  }).where(pending);
@@ -1246,11 +2411,11 @@ var DrizzleAgentStore = class {
1246
2411
  return [];
1247
2412
  }
1248
2413
  const rows = await this.db.select({
1249
- attachments: agentMessage.attachments
1250
- }).from(agentMessage).innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id)).where(and(eq(agentThread.actorRef, actorRef), isNotNull(agentMessage.attachments)));
2414
+ attachments: this.t.agentMessage.attachments
2415
+ }).from(this.t.agentMessage).innerJoin(this.t.agentThread, eq2(this.t.agentMessage.threadId, this.t.agentThread.id)).where(and2(eq2(this.t.agentThread.actorRef, actorRef), isNotNull(this.t.agentMessage.attachments)));
1251
2416
  const queued = await this.db.select({
1252
- attachments: agentQueuedMessage.attachments
1253
- }).from(agentQueuedMessage).innerJoin(agentThread, eq(agentQueuedMessage.threadId, agentThread.id)).where(and(eq(agentThread.actorRef, actorRef), isNotNull(agentQueuedMessage.attachments)));
2417
+ attachments: this.t.agentQueuedMessage.attachments
2418
+ }).from(this.t.agentQueuedMessage).innerJoin(this.t.agentThread, eq2(this.t.agentQueuedMessage.threadId, this.t.agentThread.id)).where(and2(eq2(this.t.agentThread.actorRef, actorRef), isNotNull(this.t.agentQueuedMessage.attachments)));
1254
2419
  const wanted = new Set(mediaIds);
1255
2420
  const found = /* @__PURE__ */ new Set();
1256
2421
  for (const row of [
@@ -1268,7 +2433,7 @@ var DrizzleAgentStore = class {
1268
2433
  ].filter((mediaId) => found.has(mediaId));
1269
2434
  }
1270
2435
  async recordUsage(input) {
1271
- await this.db.insert(agentTokenUsage).values({
2436
+ await this.db.insert(this.t.agentTokenUsage).values({
1272
2437
  id: crypto.randomUUID(),
1273
2438
  threadId: input.threadId,
1274
2439
  actorRef: input.actorRef,
@@ -1289,7 +2454,7 @@ var DrizzleAgentStore = class {
1289
2454
  async usageBetween(actorRef, fromDay, toDay) {
1290
2455
  const start = /* @__PURE__ */ new Date(`${fromDay}T00:00:00.000Z`);
1291
2456
  const end = /* @__PURE__ */ new Date(`${toDay}T23:59:59.999Z`);
1292
- const rows = await this.db.select().from(agentTokenUsage).where(and(eq(agentTokenUsage.actorRef, actorRef), gte(agentTokenUsage.createdAt, start), lte(agentTokenUsage.createdAt, end)));
2457
+ const rows = await this.db.select().from(this.t.agentTokenUsage).where(and2(eq2(this.t.agentTokenUsage.actorRef, actorRef), gte(this.t.agentTokenUsage.createdAt, start), lte2(this.t.agentTokenUsage.createdAt, end)));
1293
2458
  const usedTokens = rows.reduce((sum2, row) => sum2 + row.inputTokens + row.outputTokens, 0);
1294
2459
  const costUsd = rows.reduce((sum2, row) => sum2 + (row.costUsd ?? 0), 0);
1295
2460
  return {
@@ -1315,7 +2480,12 @@ var DrizzleAgentStore = class {
1315
2480
  };
1316
2481
  }
1317
2482
  toStoredMessage(message) {
2483
+ const outcome = message.actionProposalOutcome ? JSON.parse(message.actionProposalOutcome) : void 0;
1318
2484
  return {
2485
+ ...outcome ? {
2486
+ actionProposalOutcome: outcome,
2487
+ ui: outcome.ui
2488
+ } : {},
1319
2489
  id: message.id,
1320
2490
  role: message.role,
1321
2491
  content: message.content,
@@ -1361,6 +2531,9 @@ var DrizzleAgentStore = class {
1361
2531
  };
1362
2532
  function toQueuedMessage(row) {
1363
2533
  return {
2534
+ ...row.uiCapabilities !== null ? {
2535
+ uiCapabilities: row.uiCapabilities
2536
+ } : {},
1364
2537
  id: row.id,
1365
2538
  threadId: row.threadId,
1366
2539
  actor: row.actor,
@@ -1391,7 +2564,7 @@ __name(toQueuedMessage, "toQueuedMessage");
1391
2564
 
1392
2565
  // src/drizzle-governance-queries.ts
1393
2566
  import { bucketByActor, bucketByModel, bucketByThread, bucketUsageTrend, dayBoundsUtc, rollupThreadUsage, truncateDetailContent } from "@dudousxd/nestjs-agent-core";
1394
- import { and as and2, asc as asc2, count, desc as desc2, eq as eq2, gte as gte2, inArray as inArray2, isNull as isNull2, like, lte as lte2, sql as sql3, sum } from "drizzle-orm";
2567
+ import { and as and3, asc as asc3, count, desc as desc2, eq as eq3, gte as gte2, inArray as inArray2, isNull as isNull3, like, lte as lte3, sql as sql4, sum } from "drizzle-orm";
1395
2568
  var UNCLASSIFIED_ERROR_CODE = "unknown";
1396
2569
  var DEFAULT_AGENT_BUCKET = "(default)";
1397
2570
  var TOOL_CALL_STATUSES = [
@@ -1504,11 +2677,15 @@ var DrizzleGovernanceQueries = class {
1504
2677
  static {
1505
2678
  __name(this, "DrizzleGovernanceQueries");
1506
2679
  }
1507
- db;
1508
2680
  pricingStore;
2681
+ db;
2682
+ dialect;
2683
+ t;
1509
2684
  constructor(db, pricingStore) {
1510
- this.db = db;
1511
2685
  this.pricingStore = pricingStore;
2686
+ this.dialect = agentDialectOf(db);
2687
+ this.t = agentTablesFor(this.dialect);
2688
+ this.db = asBuilder(db);
1512
2689
  }
1513
2690
  async loadPricing() {
1514
2691
  const prices = await this.pricingStore.listCurrentPrices();
@@ -1525,7 +2702,7 @@ var DrizzleGovernanceQueries = class {
1525
2702
  }
1526
2703
  async usageInRange(range) {
1527
2704
  const { start, end } = dayBoundsUtc(range);
1528
- const rows = await this.db.select().from(agentTokenUsage).where(and2(gte2(agentTokenUsage.createdAt, start), lte2(agentTokenUsage.createdAt, end)));
2705
+ const rows = await this.db.select().from(this.t.agentTokenUsage).where(and3(gte2(this.t.agentTokenUsage.createdAt, start), lte3(this.t.agentTokenUsage.createdAt, end)));
1529
2706
  return rows.map(toUsageInput);
1530
2707
  }
1531
2708
  async spendByModel(range) {
@@ -1550,7 +2727,7 @@ var DrizzleGovernanceQueries = class {
1550
2727
  if (threadIds.length === 0) {
1551
2728
  return [];
1552
2729
  }
1553
- const threads = await this.db.select().from(agentThread).where(and2(inArray2(agentThread.id, threadIds), isNull2(agentThread.deletedAt)));
2730
+ const threads = await this.db.select().from(this.t.agentThread).where(and3(inArray2(this.t.agentThread.id, threadIds), isNull3(this.t.agentThread.deletedAt)));
1554
2731
  const threadsById = new Map(threads.map((thread) => [
1555
2732
  thread.id,
1556
2733
  {
@@ -1569,14 +2746,14 @@ var DrizzleGovernanceQueries = class {
1569
2746
  }
1570
2747
  async recentToolCalls(limit) {
1571
2748
  const rows = await this.db.select({
1572
- toolCallId: agentToolCall.id,
1573
- toolName: agentToolCall.toolName,
1574
- toolType: agentToolCall.toolType,
1575
- status: agentToolCall.status,
1576
- threadId: agentMessage.threadId,
1577
- createdAt: agentToolCall.createdAt,
1578
- runId: agentToolCall.runId
1579
- }).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).orderBy(desc2(agentToolCall.createdAt), desc2(agentToolCall.id)).limit(limit);
2749
+ toolCallId: this.t.agentToolCall.id,
2750
+ toolName: this.t.agentToolCall.toolName,
2751
+ toolType: this.t.agentToolCall.toolType,
2752
+ status: this.t.agentToolCall.status,
2753
+ threadId: this.t.agentMessage.threadId,
2754
+ createdAt: this.t.agentToolCall.createdAt,
2755
+ runId: this.t.agentToolCall.runId
2756
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq3(this.t.agentToolCall.messageId, this.t.agentMessage.id)).orderBy(desc2(this.t.agentToolCall.createdAt), desc2(this.t.agentToolCall.id)).limit(limit);
1580
2757
  return rows.map((row) => ({
1581
2758
  toolCallId: row.toolCallId,
1582
2759
  toolName: row.toolName,
@@ -1604,9 +2781,9 @@ var DrizzleGovernanceQueries = class {
1604
2781
  return rollups;
1605
2782
  }
1606
2783
  const messageCounts = await this.db.select({
1607
- threadId: agentMessage.threadId,
2784
+ threadId: this.t.agentMessage.threadId,
1608
2785
  value: count()
1609
- }).from(agentMessage).where(inArray2(agentMessage.threadId, threadIds)).groupBy(agentMessage.threadId);
2786
+ }).from(this.t.agentMessage).where(inArray2(this.t.agentMessage.threadId, threadIds)).groupBy(this.t.agentMessage.threadId);
1610
2787
  for (const row of messageCounts) {
1611
2788
  const bucket = rollups.get(row.threadId);
1612
2789
  if (bucket !== void 0) {
@@ -1614,10 +2791,10 @@ var DrizzleGovernanceQueries = class {
1614
2791
  }
1615
2792
  }
1616
2793
  const usageTotals = await this.db.select({
1617
- threadId: agentTokenUsage.threadId,
1618
- inputTokens: sum(agentTokenUsage.inputTokens),
1619
- outputTokens: sum(agentTokenUsage.outputTokens)
1620
- }).from(agentTokenUsage).where(inArray2(agentTokenUsage.threadId, threadIds)).groupBy(agentTokenUsage.threadId);
2794
+ threadId: this.t.agentTokenUsage.threadId,
2795
+ inputTokens: sum(this.t.agentTokenUsage.inputTokens),
2796
+ outputTokens: sum(this.t.agentTokenUsage.outputTokens)
2797
+ }).from(this.t.agentTokenUsage).where(inArray2(this.t.agentTokenUsage.threadId, threadIds)).groupBy(this.t.agentTokenUsage.threadId);
1621
2798
  for (const row of usageTotals) {
1622
2799
  const bucket = rollups.get(row.threadId);
1623
2800
  if (bucket !== void 0) {
@@ -1642,12 +2819,12 @@ var DrizzleGovernanceQueries = class {
1642
2819
  });
1643
2820
  }
1644
2821
  async recentThreads(limit) {
1645
- const threads = await this.db.select().from(agentThread).where(isNull2(agentThread.deletedAt)).orderBy(desc2(agentThread.updatedAt), desc2(agentThread.id)).limit(limit);
2822
+ const threads = await this.db.select().from(this.t.agentThread).where(isNull3(this.t.agentThread.deletedAt)).orderBy(desc2(this.t.agentThread.updatedAt), desc2(this.t.agentThread.id)).limit(limit);
1646
2823
  return this.toThreadActivityRows(threads);
1647
2824
  }
1648
2825
  async runsInRange(range) {
1649
2826
  const { start, end } = dayBoundsUtc(range);
1650
- return this.db.select().from(agentRun).where(and2(gte2(agentRun.startedAt, start), lte2(agentRun.startedAt, end)));
2827
+ return this.db.select().from(this.t.agentRun).where(and3(gte2(this.t.agentRun.startedAt, start), lte3(this.t.agentRun.startedAt, end)));
1651
2828
  }
1652
2829
  async runMetrics(range) {
1653
2830
  const runs = await this.runsInRange(range);
@@ -1704,7 +2881,7 @@ var DrizzleGovernanceQueries = class {
1704
2881
  }
1705
2882
  async runErrors(range) {
1706
2883
  const { start, end } = dayBoundsUtc(range);
1707
- const runs = await this.db.select().from(agentRun).where(and2(gte2(agentRun.startedAt, start), lte2(agentRun.startedAt, end), eq2(agentRun.status, "failed")));
2884
+ const runs = await this.db.select().from(this.t.agentRun).where(and3(gte2(this.t.agentRun.startedAt, start), lte3(this.t.agentRun.startedAt, end), eq3(this.t.agentRun.status, "failed")));
1708
2885
  const byError = /* @__PURE__ */ new Map();
1709
2886
  for (const run of runs) {
1710
2887
  const errorCode = run.errorCode ?? UNCLASSIFIED_ERROR_CODE;
@@ -1744,7 +2921,7 @@ var DrizzleGovernanceQueries = class {
1744
2921
  return result;
1745
2922
  }
1746
2923
  async recentRuns(limit) {
1747
- const runs = await this.db.select().from(agentRun).orderBy(desc2(agentRun.startedAt), desc2(agentRun.id)).limit(limit);
2924
+ const runs = await this.db.select().from(this.t.agentRun).orderBy(desc2(this.t.agentRun.startedAt), desc2(this.t.agentRun.id)).limit(limit);
1748
2925
  return runs.map(toRecentRunRow);
1749
2926
  }
1750
2927
  /**
@@ -1754,16 +2931,16 @@ var DrizzleGovernanceQueries = class {
1754
2931
  */
1755
2932
  async pendingApprovals(limit) {
1756
2933
  const rows = await this.db.select({
1757
- toolCallId: agentToolCall.id,
1758
- toolName: agentToolCall.toolName,
1759
- input: agentToolCall.input,
1760
- threadId: agentThread.id,
1761
- threadTitle: agentThread.title,
1762
- actorRef: agentThread.actorRef,
1763
- agentName: agentMessage.agentName,
1764
- requestedAt: agentToolCall.createdAt,
1765
- runId: agentToolCall.runId
1766
- }).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);
2934
+ toolCallId: this.t.agentToolCall.id,
2935
+ toolName: this.t.agentToolCall.toolName,
2936
+ input: this.t.agentToolCall.input,
2937
+ threadId: this.t.agentThread.id,
2938
+ threadTitle: this.t.agentThread.title,
2939
+ actorRef: this.t.agentThread.actorRef,
2940
+ agentName: this.t.agentMessage.agentName,
2941
+ requestedAt: this.t.agentToolCall.createdAt,
2942
+ runId: this.t.agentToolCall.runId
2943
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq3(this.t.agentToolCall.messageId, this.t.agentMessage.id)).innerJoin(this.t.agentThread, eq3(this.t.agentMessage.threadId, this.t.agentThread.id)).where(eq3(this.t.agentToolCall.status, "pending_approval")).orderBy(this.t.agentToolCall.createdAt, this.t.agentToolCall.id).limit(limit);
1767
2944
  return rows.map((row) => ({
1768
2945
  toolCallId: row.toolCallId,
1769
2946
  toolName: row.toolName,
@@ -1785,11 +2962,11 @@ var DrizzleGovernanceQueries = class {
1785
2962
  */
1786
2963
  async toolStats(range) {
1787
2964
  const { start, end } = dayBoundsUtc(range);
1788
- const calls = await this.db.select().from(agentToolCall).where(and2(gte2(agentToolCall.createdAt, start), lte2(agentToolCall.createdAt, end)));
2965
+ const calls = await this.db.select().from(this.t.agentToolCall).where(and3(gte2(this.t.agentToolCall.createdAt, start), lte3(this.t.agentToolCall.createdAt, end)));
1789
2966
  const byTool = /* @__PURE__ */ new Map();
1790
2967
  for (const call of calls) {
1791
- const key = `${call.toolName} ${call.toolType}`;
1792
- const bucket = byTool.get(key) ?? {
2968
+ const key2 = `${call.toolName} ${call.toolType}`;
2969
+ const bucket = byTool.get(key2) ?? {
1793
2970
  toolName: call.toolName,
1794
2971
  toolType: call.toolType,
1795
2972
  calls: 0,
@@ -1803,7 +2980,7 @@ var DrizzleGovernanceQueries = class {
1803
2980
  if (call.executionMs != null) {
1804
2981
  bucket.executionMs.push(call.executionMs);
1805
2982
  }
1806
- byTool.set(key, bucket);
2983
+ byTool.set(key2, bucket);
1807
2984
  }
1808
2985
  const result = [];
1809
2986
  for (const bucket of byTool.values()) {
@@ -1835,19 +3012,19 @@ var DrizzleGovernanceQueries = class {
1835
3012
  if (filters?.toolType !== void 0 && !isToolKind(filters.toolType)) {
1836
3013
  return emptyPage(query);
1837
3014
  }
1838
- 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);
3015
+ const whereClause = and3(filters?.toolName !== void 0 ? eq3(this.t.agentToolCall.toolName, filters.toolName) : void 0, filters?.toolType !== void 0 && isToolKind(filters.toolType) ? eq3(this.t.agentToolCall.toolType, filters.toolType) : void 0, filters?.status !== void 0 && isToolCallStatus(filters.status) ? eq3(this.t.agentToolCall.status, filters.status) : void 0, filters?.threadId !== void 0 ? eq3(this.t.agentMessage.threadId, filters.threadId) : void 0, filters?.fromDay !== void 0 ? gte2(this.t.agentToolCall.createdAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte3(this.t.agentToolCall.createdAt, dayEndUtc(filters.toDay)) : void 0);
1839
3016
  const [totalRow] = await this.db.select({
1840
3017
  value: count()
1841
- }).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).where(whereClause);
3018
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq3(this.t.agentToolCall.messageId, this.t.agentMessage.id)).where(whereClause);
1842
3019
  const rows = await this.db.select({
1843
- toolCallId: agentToolCall.id,
1844
- toolName: agentToolCall.toolName,
1845
- toolType: agentToolCall.toolType,
1846
- status: agentToolCall.status,
1847
- threadId: agentMessage.threadId,
1848
- createdAt: agentToolCall.createdAt,
1849
- runId: agentToolCall.runId
1850
- }).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);
3020
+ toolCallId: this.t.agentToolCall.id,
3021
+ toolName: this.t.agentToolCall.toolName,
3022
+ toolType: this.t.agentToolCall.toolType,
3023
+ status: this.t.agentToolCall.status,
3024
+ threadId: this.t.agentMessage.threadId,
3025
+ createdAt: this.t.agentToolCall.createdAt,
3026
+ runId: this.t.agentToolCall.runId
3027
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq3(this.t.agentToolCall.messageId, this.t.agentMessage.id)).where(whereClause).orderBy(desc2(this.t.agentToolCall.createdAt), desc2(this.t.agentToolCall.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
1851
3028
  return {
1852
3029
  rows: rows.map((row) => ({
1853
3030
  toolCallId: row.toolCallId,
@@ -1871,11 +3048,11 @@ var DrizzleGovernanceQueries = class {
1871
3048
  */
1872
3049
  async threadsPage(query) {
1873
3050
  const filters = query.where;
1874
- 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);
3051
+ const whereClause = and3(isNull3(this.t.agentThread.deletedAt), filters?.actorRef !== void 0 ? eq3(this.t.agentThread.actorRef, filters.actorRef) : void 0, filters?.title !== void 0 ? like(sql4`lower(${this.t.agentThread.title})`, `%${filters.title.toLowerCase()}%`) : void 0, filters?.fromDay !== void 0 ? gte2(this.t.agentThread.updatedAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte3(this.t.agentThread.updatedAt, dayEndUtc(filters.toDay)) : void 0);
1875
3052
  const [totalRow] = await this.db.select({
1876
3053
  value: count()
1877
- }).from(agentThread).where(whereClause);
1878
- 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);
3054
+ }).from(this.t.agentThread).where(whereClause);
3055
+ const threads = await this.db.select().from(this.t.agentThread).where(whereClause).orderBy(desc2(this.t.agentThread.updatedAt), desc2(this.t.agentThread.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
1879
3056
  const rows = await this.toThreadActivityRows(threads);
1880
3057
  return {
1881
3058
  rows,
@@ -1893,11 +3070,11 @@ var DrizzleGovernanceQueries = class {
1893
3070
  if (filters?.status !== void 0 && !isRunStatus(filters.status)) {
1894
3071
  return emptyPage(query);
1895
3072
  }
1896
- 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);
3073
+ const whereClause = and3(filters?.agentName !== void 0 ? eq3(this.t.agentRun.agentName, filters.agentName) : void 0, filters?.status !== void 0 && isRunStatus(filters.status) ? eq3(this.t.agentRun.status, filters.status) : void 0, filters?.errorCode !== void 0 ? eq3(this.t.agentRun.errorCode, filters.errorCode) : void 0, filters?.threadId !== void 0 ? eq3(this.t.agentRun.threadId, filters.threadId) : void 0, filters?.fromDay !== void 0 ? gte2(this.t.agentRun.startedAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte3(this.t.agentRun.startedAt, dayEndUtc(filters.toDay)) : void 0);
1897
3074
  const [totalRow] = await this.db.select({
1898
3075
  value: count()
1899
- }).from(agentRun).where(whereClause);
1900
- 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);
3076
+ }).from(this.t.agentRun).where(whereClause);
3077
+ const runs = await this.db.select().from(this.t.agentRun).where(whereClause).orderBy(desc2(this.t.agentRun.startedAt), desc2(this.t.agentRun.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
1901
3078
  return {
1902
3079
  rows: runs.map(toRecentRunRow),
1903
3080
  total: totalRow?.value ?? 0,
@@ -1917,21 +3094,21 @@ var DrizzleGovernanceQueries = class {
1917
3094
  */
1918
3095
  async approvalsPage(query) {
1919
3096
  const filters = query.where;
1920
- const whereClause = and2(eq2(agentToolCall.status, "pending_approval"), filters?.toolName !== void 0 ? eq2(agentToolCall.toolName, filters.toolName) : void 0, filters?.threadId !== void 0 ? eq2(agentThread.id, filters.threadId) : void 0, filters?.actorRef !== void 0 ? eq2(agentThread.actorRef, filters.actorRef) : void 0, filters?.agentName !== void 0 ? eq2(agentMessage.agentName, filters.agentName) : 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);
3097
+ const whereClause = and3(eq3(this.t.agentToolCall.status, "pending_approval"), filters?.toolName !== void 0 ? eq3(this.t.agentToolCall.toolName, filters.toolName) : void 0, filters?.threadId !== void 0 ? eq3(this.t.agentThread.id, filters.threadId) : void 0, filters?.actorRef !== void 0 ? eq3(this.t.agentThread.actorRef, filters.actorRef) : void 0, filters?.agentName !== void 0 ? eq3(this.t.agentMessage.agentName, filters.agentName) : void 0, filters?.fromDay !== void 0 ? gte2(this.t.agentToolCall.createdAt, dayStartUtc(filters.fromDay)) : void 0, filters?.toDay !== void 0 ? lte3(this.t.agentToolCall.createdAt, dayEndUtc(filters.toDay)) : void 0);
1921
3098
  const [totalRow] = await this.db.select({
1922
3099
  value: count()
1923
- }).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).innerJoin(agentThread, eq2(agentMessage.threadId, agentThread.id)).where(whereClause);
3100
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq3(this.t.agentToolCall.messageId, this.t.agentMessage.id)).innerJoin(this.t.agentThread, eq3(this.t.agentMessage.threadId, this.t.agentThread.id)).where(whereClause);
1924
3101
  const rows = await this.db.select({
1925
- toolCallId: agentToolCall.id,
1926
- toolName: agentToolCall.toolName,
1927
- input: agentToolCall.input,
1928
- threadId: agentThread.id,
1929
- threadTitle: agentThread.title,
1930
- actorRef: agentThread.actorRef,
1931
- agentName: agentMessage.agentName,
1932
- requestedAt: agentToolCall.createdAt,
1933
- runId: agentToolCall.runId
1934
- }).from(agentToolCall).innerJoin(agentMessage, eq2(agentToolCall.messageId, agentMessage.id)).innerJoin(agentThread, eq2(agentMessage.threadId, agentThread.id)).where(whereClause).orderBy(asc2(agentToolCall.createdAt), asc2(agentToolCall.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
3102
+ toolCallId: this.t.agentToolCall.id,
3103
+ toolName: this.t.agentToolCall.toolName,
3104
+ input: this.t.agentToolCall.input,
3105
+ threadId: this.t.agentThread.id,
3106
+ threadTitle: this.t.agentThread.title,
3107
+ actorRef: this.t.agentThread.actorRef,
3108
+ agentName: this.t.agentMessage.agentName,
3109
+ requestedAt: this.t.agentToolCall.createdAt,
3110
+ runId: this.t.agentToolCall.runId
3111
+ }).from(this.t.agentToolCall).innerJoin(this.t.agentMessage, eq3(this.t.agentToolCall.messageId, this.t.agentMessage.id)).innerJoin(this.t.agentThread, eq3(this.t.agentMessage.threadId, this.t.agentThread.id)).where(whereClause).orderBy(asc3(this.t.agentToolCall.createdAt), asc3(this.t.agentToolCall.id)).limit(query.pageSize).offset((query.page - 1) * query.pageSize);
1935
3112
  return {
1936
3113
  rows: rows.map((row) => ({
1937
3114
  toolCallId: row.toolCallId,
@@ -1956,13 +3133,13 @@ var DrizzleGovernanceQueries = class {
1956
3133
  */
1957
3134
  async runDetail(runId) {
1958
3135
  const [row] = await this.db.select({
1959
- run: agentRun,
1960
- thread: agentThread
1961
- }).from(agentRun).innerJoin(agentThread, eq2(agentRun.threadId, agentThread.id)).where(eq2(agentRun.id, runId)).limit(1);
3136
+ run: this.t.agentRun,
3137
+ thread: this.t.agentThread
3138
+ }).from(this.t.agentRun).innerJoin(this.t.agentThread, eq3(this.t.agentRun.threadId, this.t.agentThread.id)).where(eq3(this.t.agentRun.id, runId)).limit(1);
1962
3139
  if (row === void 0) {
1963
3140
  return null;
1964
3141
  }
1965
- const toolCalls = await this.db.select().from(agentToolCall).where(eq2(agentToolCall.runId, runId)).orderBy(asc2(agentToolCall.createdAt), asc2(agentToolCall.id));
3142
+ const toolCalls = await this.db.select().from(this.t.agentToolCall).where(eq3(this.t.agentToolCall.runId, runId)).orderBy(asc3(this.t.agentToolCall.createdAt), asc3(this.t.agentToolCall.id));
1966
3143
  return {
1967
3144
  run: toRecentRunRow(row.run),
1968
3145
  thread: {
@@ -1981,22 +3158,27 @@ var DrizzleGovernanceQueries = class {
1981
3158
  * message. Soft-deleted threads are returned with `deleted: true`; an audit still needs them.
1982
3159
  */
1983
3160
  async threadDetail(query) {
1984
- const [thread] = await this.db.select().from(agentThread).where(eq2(agentThread.id, query.threadId)).limit(1);
3161
+ const [thread] = await this.db.select().from(this.t.agentThread).where(eq3(this.t.agentThread.id, query.threadId)).limit(1);
1985
3162
  if (thread === void 0) {
1986
3163
  return null;
1987
3164
  }
1988
3165
  const pricing = await this.loadPricing();
1989
- const usageRows = await this.db.select().from(agentTokenUsage).where(eq2(agentTokenUsage.threadId, thread.id));
3166
+ const usageRows = await this.db.select().from(this.t.agentTokenUsage).where(eq3(this.t.agentTokenUsage.threadId, thread.id));
1990
3167
  const usage = rollupThreadUsage(usageRows.map(toUsageInput), pricing);
1991
3168
  const [messageCountRow] = await this.db.select({
1992
3169
  value: count()
1993
- }).from(agentMessage).where(eq2(agentMessage.threadId, thread.id));
1994
- const messages = await this.db.select().from(agentMessage).where(eq2(agentMessage.threadId, thread.id)).orderBy(desc2(agentMessage.createdAt), desc2(agentMessage.id)).limit(query.messageLimit);
3170
+ }).from(this.t.agentMessage).where(eq3(this.t.agentMessage.threadId, thread.id));
3171
+ const messages = await this.db.select().from(this.t.agentMessage).where(eq3(this.t.agentMessage.threadId, thread.id)).orderBy(
3172
+ // Append order (see DrizzleAgentStore's message order), newest first.
3173
+ desc2(sql4`coalesce(${this.t.agentMessage.seq}, 0)`),
3174
+ desc2(this.t.agentMessage.createdAt),
3175
+ desc2(this.t.agentMessage.id)
3176
+ ).limit(query.messageLimit);
1995
3177
  const toolCallCounts = await this.toolCallCountsByMessage(messages.map((message) => message.id));
1996
3178
  const [runTotalRow] = await this.db.select({
1997
3179
  value: count()
1998
- }).from(agentRun).where(eq2(agentRun.threadId, thread.id));
1999
- const runs = await this.db.select().from(agentRun).where(eq2(agentRun.threadId, thread.id)).orderBy(desc2(agentRun.startedAt), desc2(agentRun.id)).limit(query.runLimit);
3180
+ }).from(this.t.agentRun).where(eq3(this.t.agentRun.threadId, thread.id));
3181
+ const runs = await this.db.select().from(this.t.agentRun).where(eq3(this.t.agentRun.threadId, thread.id)).orderBy(desc2(this.t.agentRun.startedAt), desc2(this.t.agentRun.id)).limit(query.runLimit);
2000
3182
  return {
2001
3183
  thread: {
2002
3184
  threadId: thread.id,
@@ -2031,9 +3213,9 @@ var DrizzleGovernanceQueries = class {
2031
3213
  return counts;
2032
3214
  }
2033
3215
  const rows = await this.db.select({
2034
- messageId: agentToolCall.messageId,
3216
+ messageId: this.t.agentToolCall.messageId,
2035
3217
  value: count()
2036
- }).from(agentToolCall).where(inArray2(agentToolCall.messageId, messageIds)).groupBy(agentToolCall.messageId);
3218
+ }).from(this.t.agentToolCall).where(inArray2(this.t.agentToolCall.messageId, messageIds)).groupBy(this.t.agentToolCall.messageId);
2037
3219
  for (const row of rows) {
2038
3220
  counts.set(row.messageId, row.value);
2039
3221
  }
@@ -2043,7 +3225,7 @@ var DrizzleGovernanceQueries = class {
2043
3225
 
2044
3226
  // src/drizzle-memory-provider.ts
2045
3227
  import { actorScope } from "@dudousxd/nestjs-agent-core";
2046
- import { and as and3, eq as eq3, inArray as inArray3 } from "drizzle-orm";
3228
+ import { and as and4, eq as eq4, inArray as inArray3 } from "drizzle-orm";
2047
3229
  function toRecord(row) {
2048
3230
  return {
2049
3231
  id: row.id,
@@ -2072,8 +3254,12 @@ var DrizzleMemoryProvider = class {
2072
3254
  __name(this, "DrizzleMemoryProvider");
2073
3255
  }
2074
3256
  db;
3257
+ dialect;
3258
+ t;
2075
3259
  constructor(db) {
2076
- this.db = db;
3260
+ this.dialect = agentDialectOf(db);
3261
+ this.t = agentTablesFor(this.dialect);
3262
+ this.db = asBuilder(db);
2077
3263
  }
2078
3264
  /**
2079
3265
  * Every memory visible at `scopes` — asked on EVERY turn, so it is one indexed `scope in (…)`
@@ -2087,7 +3273,7 @@ var DrizzleMemoryProvider = class {
2087
3273
  if (scopes.length === 0) {
2088
3274
  return [];
2089
3275
  }
2090
- const rows = await this.db.select().from(agentMemory).where(inArray3(agentMemory.scope, [
3276
+ const rows = await this.db.select().from(this.t.agentMemory).where(inArray3(this.t.agentMemory.scope, [
2091
3277
  ...scopes
2092
3278
  ]));
2093
3279
  return rows.map(toRecord);
@@ -2103,10 +3289,8 @@ var DrizzleMemoryProvider = class {
2103
3289
  * answer cannot be used to find out which memories exist about other people.
2104
3290
  */
2105
3291
  async forget({ id, ctx }) {
2106
- const deleted = await this.db.delete(agentMemory).where(and3(eq3(agentMemory.id, id), eq3(agentMemory.scope, actorScope(ctx.actor)))).returning({
2107
- id: agentMemory.id
2108
- });
2109
- return deleted.length > 0;
3292
+ const deleted = await affectedRows(this.dialect, this.db.delete(this.t.agentMemory).where(and4(eq4(this.t.agentMemory.id, id), eq4(this.t.agentMemory.scope, actorScope(ctx.actor)))), this.t.agentMemory.id);
3293
+ return deleted > 0;
2110
3294
  }
2111
3295
  /**
2112
3296
  * Upsert on (`scope`, `key`) — one statement, against the unique index, rather than a read
@@ -2119,7 +3303,7 @@ var DrizzleMemoryProvider = class {
2119
3303
  * rewriting `createdAt` would lose when the belief was first formed; reassigning `id` would
2120
3304
  * invalidate the delete handle a person was already shown.
2121
3305
  */
2122
- async write({ key, text: text2, scope, origin, ctx }) {
3306
+ async write({ key: key2, text: text3, scope, origin, ctx }) {
2123
3307
  assertAuthorMayWriteScope({
2124
3308
  scope,
2125
3309
  origin,
@@ -2132,28 +3316,40 @@ var DrizzleMemoryProvider = class {
2132
3316
  originRunId: origin.runId ?? null,
2133
3317
  originActorRef: origin.actorRef ?? null
2134
3318
  };
2135
- const [row] = await this.db.insert(agentMemory).values({
3319
+ const memory = this.t.agentMemory;
3320
+ const set = {
3321
+ text: text3,
3322
+ ...columns,
3323
+ updatedAt: now
3324
+ };
3325
+ const insert = this.db.insert(memory).values({
2136
3326
  id: crypto.randomUUID(),
2137
3327
  scope,
2138
- key,
2139
- text: text2,
3328
+ key: key2,
3329
+ text: text3,
2140
3330
  ...columns,
2141
3331
  pinned: false,
2142
3332
  createdAt: now,
2143
3333
  updatedAt: now
2144
- }).onConflictDoUpdate({
2145
- target: [
2146
- agentMemory.scope,
2147
- agentMemory.key
2148
- ],
2149
- set: {
2150
- text: text2,
2151
- ...columns,
2152
- updatedAt: now
2153
- }
2154
- }).returning();
3334
+ });
3335
+ let row;
3336
+ if (this.dialect === "mysql") {
3337
+ await upsert(this.dialect, insert, [
3338
+ memory.scope,
3339
+ memory.key
3340
+ ], set);
3341
+ [row] = await this.db.select().from(memory).where(and4(eq4(memory.scope, scope), eq4(memory.key, key2)));
3342
+ } else {
3343
+ [row] = await insert.onConflictDoUpdate({
3344
+ target: [
3345
+ memory.scope,
3346
+ memory.key
3347
+ ],
3348
+ set
3349
+ }).returning();
3350
+ }
2155
3351
  if (row === void 0) {
2156
- throw new Error(`DrizzleMemoryProvider: the upsert of "${key}" at "${scope}" returned no row; the driver does not support RETURNING on conflict.`);
3352
+ throw new Error(`DrizzleMemoryProvider: the upsert of "${key2}" at "${scope}" returned no row; the driver does not support RETURNING on conflict.`);
2157
3353
  }
2158
3354
  return toRecord(row);
2159
3355
  }
@@ -2166,13 +3362,11 @@ var DrizzleMemoryProvider = class {
2166
3362
  * `false` where there is no such id.
2167
3363
  */
2168
3364
  async pin({ id, pinned }) {
2169
- const updated = await this.db.update(agentMemory).set({
3365
+ const updated = await affectedRows(this.dialect, this.db.update(this.t.agentMemory).set({
2170
3366
  pinned,
2171
3367
  updatedAt: /* @__PURE__ */ new Date()
2172
- }).where(eq3(agentMemory.id, id)).returning({
2173
- id: agentMemory.id
2174
- });
2175
- return updated.length > 0;
3368
+ }).where(eq4(this.t.agentMemory.id, id)), this.t.agentMemory.id);
3369
+ return updated > 0;
2176
3370
  }
2177
3371
  };
2178
3372
  function assertAuthorMayWriteScope({ scope, origin, ctx }) {
@@ -2184,20 +3378,24 @@ function assertAuthorMayWriteScope({ scope, origin, ctx }) {
2184
3378
  __name(assertAuthorMayWriteScope, "assertAuthorMayWriteScope");
2185
3379
 
2186
3380
  // src/drizzle-pricing-store.ts
2187
- import { and as and4, eq as eq4 } from "drizzle-orm";
3381
+ import { and as and5, eq as eq5 } from "drizzle-orm";
2188
3382
  var DrizzlePricingStore = class {
2189
3383
  static {
2190
3384
  __name(this, "DrizzlePricingStore");
2191
3385
  }
2192
3386
  db;
3387
+ dialect;
3388
+ t;
2193
3389
  constructor(db) {
2194
- this.db = db;
3390
+ this.dialect = agentDialectOf(db);
3391
+ this.t = agentTablesFor(this.dialect);
3392
+ this.db = asBuilder(db);
2195
3393
  }
2196
3394
  async upsertModelPrice(input) {
2197
- await this.db.update(agentModelPricing).set({
3395
+ await this.db.update(this.t.agentModelPricing).set({
2198
3396
  isCurrent: false
2199
- }).where(and4(eq4(agentModelPricing.modelId, input.modelId), eq4(agentModelPricing.isCurrent, true)));
2200
- await this.db.insert(agentModelPricing).values({
3397
+ }).where(and5(eq5(this.t.agentModelPricing.modelId, input.modelId), eq5(this.t.agentModelPricing.isCurrent, true)));
3398
+ await this.db.insert(this.t.agentModelPricing).values({
2201
3399
  id: crypto.randomUUID(),
2202
3400
  modelId: input.modelId,
2203
3401
  inputPricePer1m: input.inputPricePer1m,
@@ -2209,7 +3407,7 @@ var DrizzlePricingStore = class {
2209
3407
  });
2210
3408
  }
2211
3409
  async listCurrentPrices() {
2212
- const rows = await this.db.select().from(agentModelPricing).where(eq4(agentModelPricing.isCurrent, true));
3410
+ const rows = await this.db.select().from(this.t.agentModelPricing).where(eq5(this.t.agentModelPricing.isCurrent, true));
2213
3411
  return rows.map((row) => ({
2214
3412
  modelId: row.modelId,
2215
3413
  inputPricePer1m: row.inputPricePer1m,
@@ -2227,52 +3425,47 @@ var DrizzlePricingStore = class {
2227
3425
 
2228
3426
  // src/drizzle-token-stream-sink.ts
2229
3427
  import { SqlTokenStreamSink } from "@dudousxd/nestjs-agent-core";
2230
- import { and as and5, asc as asc3, eq as eq5, gt, inArray as inArray4, lt, max as max2, sql as sql4 } from "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");
3428
+ import { and as and6, asc as asc4, eq as eq6, gt as gt2, inArray as inArray4, lt, max as max3, sql as sql5 } from "drizzle-orm";
2240
3429
  var DrizzleStreamFrameTable = class {
2241
3430
  static {
2242
3431
  __name(this, "DrizzleStreamFrameTable");
2243
3432
  }
2244
3433
  db;
3434
+ dialect;
3435
+ t;
2245
3436
  constructor(db) {
2246
- this.db = db;
3437
+ this.dialect = agentDialectOf(db);
3438
+ this.t = agentTablesFor(this.dialect);
3439
+ this.db = asBuilder(db);
2247
3440
  }
2248
3441
  async append(runId, row) {
2249
- await this.db.run(sql4`INSERT INTO agent_stream_frame (run_id, seq, frame, error, created_at)
3442
+ await runSql(this.db, this.dialect, sql5`INSERT INTO agent_stream_frame (run_id, seq, frame, error, created_at)
2250
3443
  SELECT ${runId}, COALESCE(MAX(seq), 0) + 1, ${row.frame}, ${row.error}, ${row.createdAt}
2251
3444
  FROM agent_stream_frame WHERE run_id = ${runId}`);
2252
3445
  }
2253
3446
  async read(runId, after, limit) {
2254
3447
  return this.db.select({
2255
- seq: agentStreamFrame.seq,
2256
- frame: agentStreamFrame.frame,
2257
- error: agentStreamFrame.error
2258
- }).from(agentStreamFrame).where(and5(eq5(agentStreamFrame.runId, runId), gt(agentStreamFrame.seq, after))).orderBy(asc3(agentStreamFrame.seq)).limit(limit);
3448
+ seq: this.t.agentStreamFrame.seq,
3449
+ frame: this.t.agentStreamFrame.frame,
3450
+ error: this.t.agentStreamFrame.error
3451
+ }).from(this.t.agentStreamFrame).where(and6(eq6(this.t.agentStreamFrame.runId, runId), gt2(this.t.agentStreamFrame.seq, after))).orderBy(asc4(this.t.agentStreamFrame.seq)).limit(limit);
2259
3452
  }
2260
3453
  async has(runId) {
2261
3454
  const rows = await this.db.select({
2262
- seq: agentStreamFrame.seq
2263
- }).from(agentStreamFrame).where(eq5(agentStreamFrame.runId, runId)).limit(1);
3455
+ seq: this.t.agentStreamFrame.seq
3456
+ }).from(this.t.agentStreamFrame).where(eq6(this.t.agentStreamFrame.runId, runId)).limit(1);
2264
3457
  return rows.length > 0;
2265
3458
  }
2266
3459
  async remove(runIds) {
2267
3460
  if (runIds.length === 0) return;
2268
- await this.db.delete(agentStreamFrame).where(inArray4(agentStreamFrame.runId, [
3461
+ await this.db.delete(this.t.agentStreamFrame).where(inArray4(this.t.agentStreamFrame.runId, [
2269
3462
  ...runIds
2270
3463
  ]));
2271
3464
  }
2272
3465
  async lapsedRuns(cutoff) {
2273
3466
  const rows = await this.db.select({
2274
- runId: agentStreamFrame.runId
2275
- }).from(agentStreamFrame).groupBy(agentStreamFrame.runId).having(lt(max2(agentStreamFrame.createdAt), cutoff));
3467
+ runId: this.t.agentStreamFrame.runId
3468
+ }).from(this.t.agentStreamFrame).groupBy(this.t.agentStreamFrame.runId).having(lt(max3(this.t.agentStreamFrame.createdAt), cutoff));
2276
3469
  return rows.map((row) => row.runId);
2277
3470
  }
2278
3471
  isUniqueViolation(error) {
@@ -2289,54 +3482,60 @@ var DrizzleTokenStreamSink = class extends SqlTokenStreamSink {
2289
3482
  };
2290
3483
 
2291
3484
  // src/drizzle-confirm-token-store.ts
2292
- import { eq as eq6, lt as lt2 } from "drizzle-orm";
3485
+ import { eq as eq7, lt as lt2 } from "drizzle-orm";
2293
3486
  var DrizzleConfirmTokenStore = class {
2294
3487
  static {
2295
3488
  __name(this, "DrizzleConfirmTokenStore");
2296
3489
  }
2297
3490
  db;
3491
+ dialect;
3492
+ t;
2298
3493
  constructor(db) {
2299
- this.db = db;
3494
+ this.dialect = agentDialectOf(db);
3495
+ this.t = agentTablesFor(this.dialect);
3496
+ this.db = asBuilder(db);
2300
3497
  }
2301
3498
  async claim(input) {
2302
- const inserted = await this.db.insert(agentConfirmToken).values({
3499
+ const row = {
2303
3500
  hash: input.hash,
2304
3501
  actorRef: input.actorRef,
2305
3502
  tool: input.tool,
2306
3503
  expiresAt: input.expiresAt,
2307
3504
  createdAt: Date.now()
2308
- }).onConflictDoNothing().returning({
2309
- hash: agentConfirmToken.hash
2310
- });
2311
- return inserted.length === 1;
3505
+ };
3506
+ const table = this.t.agentConfirmToken;
3507
+ if (this.dialect === "mysql") {
3508
+ const insert = this.db.insert(table);
3509
+ return mysqlAffectedRows(await insert.ignore().values(row)) === 1;
3510
+ }
3511
+ const inserted = await affectedRows(this.dialect, this.db.insert(table).values(row).onConflictDoNothing(), table.hash);
3512
+ return inserted === 1;
2312
3513
  }
2313
3514
  async release(hash) {
2314
- await this.db.delete(agentConfirmToken).where(eq6(agentConfirmToken.hash, hash));
3515
+ await this.db.delete(this.t.agentConfirmToken).where(eq7(this.t.agentConfirmToken.hash, hash));
2315
3516
  }
2316
3517
  async purgeExpired(now = Date.now()) {
2317
- const purged = await this.db.delete(agentConfirmToken).where(lt2(agentConfirmToken.expiresAt, now)).returning({
2318
- hash: agentConfirmToken.hash
2319
- });
2320
- return purged.length;
3518
+ const table = this.t.agentConfirmToken;
3519
+ return affectedRows(this.dialect, this.db.delete(table).where(lt2(table.expiresAt, now)), table.hash);
2321
3520
  }
2322
3521
  };
2323
3522
 
2324
3523
  // src/drizzle-rag-ingestion-log.ts
2325
3524
  import { subscribe, unsubscribe } from "diagnostics_channel";
2326
3525
  import { Injectable, Logger } from "@nestjs/common";
2327
- 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";
2328
- function _ts_decorate(decorators, target, key, desc4) {
2329
- var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
3526
+ import { and as and7, asc as asc5, count as count2, desc as desc3, eq as eq8, gt as gt3, lt as lt3, or as or3 } from "drizzle-orm";
3527
+ function _ts_decorate(decorators, target, key2, desc4) {
3528
+ var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key2) : desc4, d;
2330
3529
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
2331
- r = Reflect.decorate(decorators, target, key, desc4);
3530
+ r = Reflect.decorate(decorators, target, key2, desc4);
2332
3531
  } else {
2333
3532
  for (var i = decorators.length - 1; i >= 0; i--) {
2334
3533
  if (d = decorators[i]) {
2335
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3534
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key2, r) : d(target, key2)) || r;
2336
3535
  }
2337
3536
  }
2338
3537
  }
2339
- return c > 3 && r && Object.defineProperty(target, key, r), r;
3538
+ return c > 3 && r && Object.defineProperty(target, key2, r), r;
2340
3539
  }
2341
3540
  __name(_ts_decorate, "_ts_decorate");
2342
3541
  function _ts_metadata(metadataKey, metadataValue) {
@@ -2373,7 +3572,7 @@ function num(value) {
2373
3572
  __name(num, "num");
2374
3573
  var RAG_INGESTION_LOG_PAGE_ORDER = [
2375
3574
  desc3(ragIngestionLog.updatedAt),
2376
- asc4(ragIngestionLog.documentId)
3575
+ asc5(ragIngestionLog.documentId)
2377
3576
  ];
2378
3577
  var DEFAULT_PAGE_SIZE = 200;
2379
3578
  var DEFAULT_BATCH_SIZE = 200;
@@ -2382,20 +3581,27 @@ function batches(batchSize) {
2382
3581
  return Number.isFinite(requested) && requested >= 1 ? requested : DEFAULT_BATCH_SIZE;
2383
3582
  }
2384
3583
  __name(batches, "batches");
2385
- var CURSOR_COLUMNS = {
2386
- documentId: ragIngestionLog.documentId,
2387
- updatedAt: ragIngestionLog.updatedAt
2388
- };
3584
+ function cursorColumns(log) {
3585
+ return {
3586
+ documentId: log.documentId,
3587
+ updatedAt: log.updatedAt
3588
+ };
3589
+ }
3590
+ __name(cursorColumns, "cursorColumns");
2389
3591
  var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2390
3592
  static {
2391
3593
  __name(this, "DrizzleRagIngestionLog");
2392
3594
  }
2393
- db;
2394
3595
  logger = new Logger(_DrizzleRagIngestionLog.name);
2395
3596
  teardowns = [];
2396
3597
  inFlight = /* @__PURE__ */ new Set();
3598
+ db;
3599
+ dialect;
3600
+ t;
2397
3601
  constructor(db) {
2398
- this.db = db;
3602
+ this.dialect = agentDialectOf(db);
3603
+ this.t = agentTablesFor(this.dialect);
3604
+ this.db = asBuilder(db);
2399
3605
  }
2400
3606
  onModuleInit() {
2401
3607
  for (const channel of CHANNELS) {
@@ -2424,7 +3630,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2424
3630
  }
2425
3631
  /** The latest recorded outcome per document, newest first. */
2426
3632
  async list(query = {}) {
2427
- const rows = this.db.select().from(ragIngestionLog).where(this.where(query)).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(query.limit ?? DEFAULT_PAGE_SIZE);
3633
+ const rows = this.db.select().from(this.t.ragIngestionLog).where(this.where(query)).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(query.limit ?? DEFAULT_PAGE_SIZE);
2428
3634
  return query.offset === void 0 ? rows : rows.offset(query.offset);
2429
3635
  }
2430
3636
  /**
@@ -2438,7 +3644,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2438
3644
  async listPage(query = {}) {
2439
3645
  const [totalRow] = await this.db.select({
2440
3646
  value: count2()
2441
- }).from(ragIngestionLog).where(this.where(query));
3647
+ }).from(this.t.ragIngestionLog).where(this.where(query));
2442
3648
  return {
2443
3649
  rows: await this.list(query),
2444
3650
  total: totalRow?.value ?? 0
@@ -2491,7 +3697,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2491
3697
  * sweep is run. A sweep that stops early stops by `break`ing out of the `for await`.
2492
3698
  */
2493
3699
  iterate(where = {}, options = {}) {
2494
- return this.sweep(where, batches(options.batchSize), options.after, (filter, limit) => this.db.select().from(ragIngestionLog).where(filter).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(limit));
3700
+ return this.sweep(where, batches(options.batchSize), options.after, (filter, limit) => this.db.select().from(this.t.ragIngestionLog).where(filter).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(limit));
2495
3701
  }
2496
3702
  /**
2497
3703
  * Just the document ids of the matching rows, in {@link RAG_INGESTION_LOG_PAGE_ORDER}.
@@ -2508,7 +3714,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2508
3714
  */
2509
3715
  async listDocumentIds(where = {}, options = {}) {
2510
3716
  const ids = [];
2511
- const rows = this.sweep(where, batches(options.batchSize), void 0, (filter, limit) => this.db.select(CURSOR_COLUMNS).from(ragIngestionLog).where(filter).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(limit));
3717
+ const rows = this.sweep(where, batches(options.batchSize), void 0, (filter, limit) => this.db.select(cursorColumns(this.t.ragIngestionLog)).from(this.t.ragIngestionLog).where(filter).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(limit));
2512
3718
  for await (const row of rows) {
2513
3719
  ids.push(row.documentId);
2514
3720
  }
@@ -2516,22 +3722,18 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2516
3722
  }
2517
3723
  /** The latest recorded outcome for one document, or null if it was never attempted. */
2518
3724
  async get(documentId) {
2519
- const [row] = await this.db.select().from(ragIngestionLog).where(eq7(ragIngestionLog.documentId, documentId));
3725
+ const [row] = await this.db.select().from(this.t.ragIngestionLog).where(eq8(this.t.ragIngestionLog.documentId, documentId));
2520
3726
  return row ?? null;
2521
3727
  }
2522
3728
  /** Forget one document's record. Returns whether a row was actually removed. */
2523
3729
  async remove(documentId) {
2524
- const removed = await this.db.delete(ragIngestionLog).where(eq7(ragIngestionLog.documentId, documentId)).returning({
2525
- documentId: ragIngestionLog.documentId
2526
- });
2527
- return removed.length > 0;
3730
+ const removed = await affectedRows(this.dialect, this.db.delete(this.t.ragIngestionLog).where(eq8(this.t.ragIngestionLog.documentId, documentId)), this.t.ragIngestionLog.documentId);
3731
+ return removed > 0;
2528
3732
  }
2529
3733
  /** Forget every record for a collection — for when the collection itself is deleted. */
2530
3734
  async removeByCollection(collection) {
2531
- const removed = await this.db.delete(ragIngestionLog).where(eq7(ragIngestionLog.collection, collection)).returning({
2532
- documentId: ragIngestionLog.documentId
2533
- });
2534
- return removed.length;
3735
+ const removed = await affectedRows(this.dialect, this.db.delete(this.t.ragIngestionLog).where(eq8(this.t.ragIngestionLog.collection, collection)), this.t.ragIngestionLog.documentId);
3736
+ return removed;
2535
3737
  }
2536
3738
  /**
2537
3739
  * The keyset sweep both {@link iterate} and {@link listDocumentIds} are made of. `page` decides
@@ -2560,7 +3762,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2560
3762
  }
2561
3763
  }
2562
3764
  where(query) {
2563
- return and6(query.collection !== void 0 ? eq7(ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? eq7(ragIngestionLog.status, query.status) : void 0);
3765
+ return and7(query.collection !== void 0 ? eq8(this.t.ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? eq8(this.t.ragIngestionLog.status, query.status) : void 0);
2564
3766
  }
2565
3767
  /**
2566
3768
  * The coordinates filter AND'd with "strictly after `cursor` in
@@ -2575,7 +3777,7 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2575
3777
  if (cursor === void 0) {
2576
3778
  return base;
2577
3779
  }
2578
- return and6(base, or2(lt3(ragIngestionLog.updatedAt, cursor.updatedAt), and6(eq7(ragIngestionLog.updatedAt, cursor.updatedAt), gt2(ragIngestionLog.documentId, cursor.documentId))));
3780
+ return and7(base, or3(lt3(this.t.ragIngestionLog.updatedAt, cursor.updatedAt), and7(eq8(this.t.ragIngestionLog.updatedAt, cursor.updatedAt), gt3(this.t.ragIngestionLog.documentId, cursor.documentId))));
2579
3781
  }
2580
3782
  /**
2581
3783
  * Upsert one outcome. Keyed by document id so the row always reflects the *current* state — a
@@ -2623,14 +3825,11 @@ var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
2623
3825
  size
2624
3826
  } : {}
2625
3827
  };
2626
- await this.db.insert(ragIngestionLog).values({
3828
+ await upsert(this.dialect, this.db.insert(this.t.ragIngestionLog).values({
2627
3829
  documentId,
2628
3830
  createdAt: now,
2629
3831
  ...outcome
2630
- }).onConflictDoUpdate({
2631
- target: ragIngestionLog.documentId,
2632
- set: outcome
2633
- });
3832
+ }), this.t.ragIngestionLog.documentId, outcome);
2634
3833
  } catch (error) {
2635
3834
  this.logger.warn(`Could not record RAG ingestion outcome for ${documentId}: ${error instanceof Error ? error.message : String(error)}`);
2636
3835
  }
@@ -2653,18 +3852,18 @@ DrizzleRagIngestionLog = _ts_decorate([
2653
3852
  // src/drizzle-agent-store.module.ts
2654
3853
  import { AGENT_CONFIRM_TOKEN_STORE, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, AGENT_STORE } from "@dudousxd/nestjs-agent-core";
2655
3854
  import { Module } from "@nestjs/common";
2656
- function _ts_decorate2(decorators, target, key, desc4) {
2657
- var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
3855
+ function _ts_decorate2(decorators, target, key2, desc4) {
3856
+ var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key2) : desc4, d;
2658
3857
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
2659
- r = Reflect.decorate(decorators, target, key, desc4);
3858
+ r = Reflect.decorate(decorators, target, key2, desc4);
2660
3859
  } else {
2661
3860
  for (var i = decorators.length - 1; i >= 0; i--) {
2662
3861
  if (d = decorators[i]) {
2663
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3862
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key2, r) : d(target, key2)) || r;
2664
3863
  }
2665
3864
  }
2666
3865
  }
2667
- return c > 3 && r && Object.defineProperty(target, key, r), r;
3866
+ return c > 3 && r && Object.defineProperty(target, key2, r), r;
2668
3867
  }
2669
3868
  __name(_ts_decorate2, "_ts_decorate");
2670
3869
  var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
@@ -2753,6 +3952,7 @@ DrizzleAgentStoreModule = _ts_decorate2([
2753
3952
  Module({})
2754
3953
  ], DrizzleAgentStoreModule);
2755
3954
  export {
3955
+ DrizzleActionProposalStore,
2756
3956
  DrizzleAgentStore,
2757
3957
  DrizzleAgentStoreModule,
2758
3958
  DrizzleConfirmTokenStore,
@@ -2763,18 +3963,23 @@ export {
2763
3963
  DrizzleStreamFrameTable,
2764
3964
  DrizzleTokenStreamSink,
2765
3965
  RAG_INGESTION_LOG_PAGE_ORDER,
3966
+ agentActionProposal,
2766
3967
  agentConfirmToken,
3968
+ agentDialectOf,
2767
3969
  agentMemory,
2768
3970
  agentMessage,
2769
3971
  agentModelPricing,
2770
3972
  agentQueuedMessage,
2771
3973
  agentRun,
2772
3974
  agentSchema,
3975
+ agentSchemaDdl,
2773
3976
  agentStreamFrame,
2774
3977
  agentThread,
2775
3978
  agentTokenUsage,
2776
3979
  agentToolCall,
2777
3980
  ensureAgentSchema,
3981
+ mysqlAgentSchema,
3982
+ pgAgentSchema,
2778
3983
  ragIngestionLog
2779
3984
  };
2780
3985
  //# sourceMappingURL=index.js.map