@dudousxd/nestjs-agent-store-drizzle 0.8.2 → 0.9.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/README.md +52 -3
- package/dist/index.cjs +206 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +231 -16
- package/dist/index.d.ts +231 -16
- package/dist/index.js +207 -9
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema.ts","../src/ensure-schema.ts","../src/drizzle-agent-store.ts","../src/drizzle-governance-queries.ts","../src/drizzle-pricing-store.ts","../src/drizzle-agent-store.module.ts"],"sourcesContent":["import type {\n MessageRole,\n MessageUsage,\n ToolCallRequest,\n ToolCallStatus,\n ToolKind,\n ToolResult,\n UsagePurpose,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n type BaseSQLiteDatabase,\n index,\n integer,\n real,\n sqliteTable,\n text,\n} from 'drizzle-orm/sqlite-core';\n\n/**\n * Drizzle schema mirroring the MikroORM agent entities (same logical columns/relations):\n * threads, messages, tool calls, token usage, model pricing and run outcomes. Targets the SQLite core so the\n * db-test runs on an in-memory better-sqlite3; timestamps are stored as integer epoch-ms columns\n * (`{ mode: 'timestamp_ms' }`) which Drizzle round-trips to/from JS `Date`, and the model-facing\n * message extras (tool calls/results, follow-ups, usage) live in JSON `text` columns.\n */\n\n/**\n * A conversation thread. `deletedAt` drives soft delete: a deleted thread is hidden from\n * {@link import('./drizzle-agent-store.js').DrizzleAgentStore.getThread}/`listThreads` but its\n * row survives.\n */\nexport const agentThread = sqliteTable(\n 'agent_thread',\n {\n id: text('id').primaryKey(),\n actorRef: text('actor_ref').notNull(),\n tenantRef: text('tenant_ref'),\n title: text('title').notNull(),\n transient: integer('transient', { mode: 'boolean' }).notNull().default(false),\n activeStreamId: text('active_stream_id'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),\n deletedAt: integer('deleted_at', { mode: 'timestamp_ms' }),\n },\n (table) => [index('agent_thread_actor_updated_idx').on(table.actorRef, table.updatedAt)],\n);\n\n/**\n * One stored message in a thread. The model-facing extras (`toolCalls`/`toolResults`/\n * `followUps`/`usage`) are folded into nullable JSON columns so a single row round-trips to a\n * {@link import('@dudousxd/nestjs-agent-core').StoredMessage}. `threadId` cascades on delete.\n */\nexport const agentMessage = sqliteTable(\n 'agent_message',\n {\n id: text('id').primaryKey(),\n threadId: text('thread_id')\n .notNull()\n .references(() => agentThread.id, { onDelete: 'cascade' }),\n role: text('role').$type<MessageRole>().notNull(),\n content: text('content').notNull(),\n toolCalls: text('tool_calls', { mode: 'json' }).$type<ToolCallRequest[]>(),\n toolResults: text('tool_results', { mode: 'json' }).$type<ToolResult[]>(),\n followUps: text('follow_ups', { mode: 'json' }).$type<string[]>(),\n usage: text('usage', { mode: 'json' }).$type<MessageUsage>(),\n agentName: text('agent_name'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n },\n (table) => [index('agent_message_thread_created_idx').on(table.threadId, table.createdAt)],\n);\n\n/** A tool call requested during an assistant turn. The pk is the model-supplied `toolCallId`. */\nexport const agentToolCall = sqliteTable('agent_tool_call', {\n id: text('id').primaryKey(),\n messageId: text('message_id')\n .notNull()\n .references(() => agentMessage.id, { onDelete: 'cascade' }),\n toolName: text('tool_name').notNull(),\n toolType: text('tool_type').$type<ToolKind>().notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n status: text('status').$type<ToolCallStatus>().notNull(),\n executedByRef: text('executed_by_ref'),\n executionMs: integer('execution_ms'),\n error: text('error'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n executedAt: integer('executed_at', { mode: 'timestamp_ms' }),\n /** The run (turn) this call belongs to, for a trace deep-link; null for a pre-rollout row. */\n runId: text('run_id'),\n});\n\n/** A token-usage ledger row, summed per actor per day by `quotaToday`. */\nexport const agentTokenUsage = sqliteTable(\n 'agent_token_usage',\n {\n id: text('id').primaryKey(),\n threadId: text('thread_id')\n .notNull()\n .references(() => agentThread.id, { onDelete: 'cascade' }),\n actorRef: text('actor_ref').notNull(),\n messageId: text('message_id'),\n modelId: text('model_id').notNull(),\n purpose: text('purpose').$type<UsagePurpose>().notNull(),\n inputTokens: integer('input_tokens').notNull(),\n outputTokens: integer('output_tokens').notNull(),\n /** Subset of `inputTokens` written to the prompt cache this turn; null when not reported. */\n cacheWriteTokens: integer('cache_write_tokens'),\n /** Subset of `inputTokens` served from the prompt cache this turn; null when not reported. */\n cacheReadTokens: integer('cache_read_tokens'),\n /** Provider-reported actual USD cost for the turn; null when only tokens were reported. */\n costUsd: real('cost_usd'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n },\n (table) => [index('agent_token_usage_actor_created_idx').on(table.actorRef, table.createdAt)],\n);\n\n/** Per-model token pricing, versioned by `effectiveFrom`; `isCurrent` flags the live row. */\nexport const agentModelPricing = sqliteTable('agent_model_pricing', {\n id: text('id').primaryKey(),\n modelId: text('model_id').notNull(),\n inputPricePer1m: real('input_price_per_1m').notNull(),\n outputPricePer1m: real('output_price_per_1m').notNull(),\n /** Per-1M price for cache-write input tokens; null → price them at the input rate. */\n cacheWritePricePer1m: real('cache_write_price_per_1m'),\n /** Per-1M price for cache-read input tokens; null → price them at the input rate. */\n cacheReadPricePer1m: real('cache_read_price_per_1m'),\n effectiveFrom: integer('effective_from', { mode: 'timestamp_ms' }).notNull(),\n isCurrent: integer('is_current', { mode: 'boolean' }).notNull(),\n});\n\n/** A run's lifecycle status. Not part of the core SPI (that surfaces `string`) — internal only. */\nexport type AgentRunStatus = 'running' | 'completed' | 'failed';\n\n/**\n * One recorded run (turn) outcome — the durable half of what `aviary:agent:*` diagnostics report\n * ephemerally. Written by {@link import('./drizzle-agent-store.js').DrizzleAgentStore.recordRunStart}/\n * `recordRunEnd`/`bumpRunRetries`, read by\n * {@link import('./drizzle-governance-queries.js').DrizzleGovernanceQueries} for the reliability\n * surfaces (success rate, error breakdown, duration percentiles, trend, recent runs). `threadId`\n * cascades on delete, like `agent_message`/`agent_token_usage`.\n */\nexport const agentRun = sqliteTable(\n 'agent_run',\n {\n id: text('id').primaryKey(),\n threadId: text('thread_id')\n .notNull()\n .references(() => agentThread.id, { onDelete: 'cascade' }),\n actorRef: text('actor_ref').notNull(),\n agentName: text('agent_name'),\n status: text('status').$type<AgentRunStatus>().notNull(),\n durationMs: integer('duration_ms'),\n errorCode: text('error_code'),\n errorMessage: text('error_message'),\n retries: integer('retries').notNull().default(0),\n startedAt: integer('started_at', { mode: 'timestamp_ms' }).notNull(),\n settledAt: integer('settled_at', { mode: 'timestamp_ms' }),\n /** sha256 hex of the run's resolved (pre-RAG) system prompt; null for a pre-existing run. */\n promptHash: text('prompt_hash'),\n },\n (table) => [index('agent_run_started_idx').on(table.startedAt)],\n);\n\n/** The six agent tables as one schema object, ready for `drizzle(client, { schema })`. */\nexport const agentSchema = {\n agentThread,\n agentMessage,\n agentToolCall,\n agentTokenUsage,\n agentModelPricing,\n agentRun,\n};\n\n/**\n * The dialect-portable Drizzle SQLite database handle the store operates on. Accepts any SQLite\n * driver (better-sqlite3, libsql, D1, …) in either sync or async result mode; the host app owns\n * the connection and passes the `drizzle(...)` instance in.\n */\nexport type AgentDrizzleDb = BaseSQLiteDatabase<'sync' | 'async', unknown>;\n\n/** A persisted thread row as Drizzle selects it. */\nexport type AgentThreadRow = typeof agentThread.$inferSelect;\n/** A persisted message row as Drizzle selects it. */\nexport type AgentMessageRow = typeof agentMessage.$inferSelect;\n/** A persisted run row as Drizzle selects it. */\nexport type AgentRunRow = typeof agentRun.$inferSelect;\n","import { sql } from 'drizzle-orm';\nimport type { AgentDrizzleDb } from './schema.js';\n\n/**\n * Idempotent `CREATE TABLE IF NOT EXISTS` DDL for the six agent tables, mirroring\n * {@link import('./schema.js').agentSchema}. SQLite dialect (the db-test driver); kept here rather\n * than relying on drizzle-kit so the package can stand up its schema with no migration files. Safe\n * to run on boot against a shared database — it never drops or alters existing columns.\n */\nconst statements: string[] = [\n `CREATE TABLE IF NOT EXISTS agent_thread (\n id TEXT PRIMARY KEY NOT NULL,\n actor_ref TEXT NOT NULL,\n tenant_ref TEXT,\n title TEXT NOT NULL,\n transient INTEGER NOT NULL DEFAULT 0,\n active_stream_id TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n deleted_at INTEGER\n )`,\n `CREATE INDEX IF NOT EXISTS agent_thread_actor_updated_idx\n ON agent_thread (actor_ref, updated_at)`,\n `CREATE TABLE IF NOT EXISTS agent_message (\n id TEXT PRIMARY KEY NOT NULL,\n thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n tool_calls TEXT,\n tool_results TEXT,\n follow_ups TEXT,\n usage TEXT,\n agent_name TEXT,\n created_at INTEGER NOT NULL\n )`,\n `CREATE INDEX IF NOT EXISTS agent_message_thread_created_idx\n ON agent_message (thread_id, created_at)`,\n `CREATE TABLE IF NOT EXISTS agent_tool_call (\n id TEXT PRIMARY KEY NOT NULL,\n message_id TEXT NOT NULL REFERENCES agent_message(id) ON DELETE CASCADE,\n tool_name TEXT NOT NULL,\n tool_type TEXT NOT NULL,\n input TEXT,\n output TEXT,\n status TEXT NOT NULL,\n executed_by_ref TEXT,\n execution_ms INTEGER,\n error TEXT,\n created_at INTEGER NOT NULL,\n executed_at INTEGER,\n run_id TEXT\n )`,\n `CREATE TABLE IF NOT EXISTS agent_token_usage (\n id TEXT PRIMARY KEY NOT NULL,\n thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,\n actor_ref TEXT NOT NULL,\n message_id TEXT,\n model_id TEXT NOT NULL,\n purpose TEXT NOT NULL,\n input_tokens INTEGER NOT NULL,\n output_tokens INTEGER NOT NULL,\n cache_write_tokens INTEGER,\n cache_read_tokens INTEGER,\n cost_usd REAL,\n created_at INTEGER NOT NULL\n )`,\n `CREATE INDEX IF NOT EXISTS agent_token_usage_actor_created_idx\n ON agent_token_usage (actor_ref, created_at)`,\n `CREATE TABLE IF NOT EXISTS agent_model_pricing (\n id TEXT PRIMARY KEY NOT NULL,\n model_id TEXT NOT NULL,\n input_price_per_1m REAL NOT NULL,\n output_price_per_1m REAL NOT NULL,\n cache_write_price_per_1m REAL,\n cache_read_price_per_1m REAL,\n effective_from INTEGER NOT NULL,\n is_current INTEGER NOT NULL\n )`,\n `CREATE TABLE IF NOT EXISTS agent_run (\n id TEXT PRIMARY KEY NOT NULL,\n thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,\n actor_ref TEXT NOT NULL,\n agent_name TEXT,\n status TEXT NOT NULL,\n duration_ms INTEGER,\n error_code TEXT,\n error_message TEXT,\n retries INTEGER NOT NULL DEFAULT 0,\n started_at INTEGER NOT NULL,\n settled_at INTEGER,\n prompt_hash TEXT\n )`,\n `CREATE INDEX IF NOT EXISTS agent_run_started_idx\n ON agent_run (started_at)`,\n];\n\n/** Runs the `CREATE TABLE IF NOT EXISTS` DDL above against the supplied Drizzle SQLite db. */\nexport async function ensureAgentSchema(db: AgentDrizzleDb): Promise<void> {\n for (const statement of statements) {\n await db.run(sql.raw(statement));\n }\n}\n","import type {\n AgentStore,\n AppendMessageInput,\n CreateThreadInput,\n RecordToolCallInput,\n RecordUsageInput,\n StoredMessage,\n ThreadDetail,\n ThreadSummary,\n UpdateToolCallInput,\n} from '@dudousxd/nestjs-agent-core';\nimport { and, asc, desc, eq, gte, inArray, isNull, lte, sql } from 'drizzle-orm';\nimport {\n type AgentDrizzleDb,\n type AgentMessageRow,\n type AgentRunRow,\n type AgentThreadRow,\n agentMessage,\n agentRun,\n agentThread,\n agentTokenUsage,\n agentToolCall,\n} from './schema.js';\n\n/**\n * {@link AgentStore} backed by Drizzle ORM — a second adapter alongside the MikroORM one, proving\n * the store SPI is ORM-portable. A POJO receiving a Drizzle SQLite database handle (the host app\n * owns the connection). Behaviour mirrors {@link import('@dudousxd/nestjs-agent-store-mikro-orm')}\n * exactly (fork/truncate/quota/active-stream/soft-delete semantics) so the two are interchangeable.\n */\nexport class DrizzleAgentStore implements AgentStore {\n constructor(private readonly db: AgentDrizzleDb) {}\n\n async createThread(input: CreateThreadInput): Promise<ThreadSummary> {\n const now = new Date();\n const thread: AgentThreadRow = {\n id: crypto.randomUUID(),\n actorRef: input.actor.id,\n tenantRef: input.actor.tenantRef ?? null,\n title: input.title ?? 'New chat',\n transient: input.transient ?? false,\n activeStreamId: null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n };\n await this.db.insert(agentThread).values(thread);\n return this.toSummary(thread);\n }\n\n async getThread(threadId: string): Promise<ThreadDetail | null> {\n const [thread] = await this.db\n .select()\n .from(agentThread)\n .where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));\n if (thread === undefined) {\n return null;\n }\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));\n const last = messages[messages.length - 1];\n return {\n ...this.toSummary(thread, last?.content),\n messages: messages.map((message) => this.toStoredMessage(message)),\n ...(thread.activeStreamId != null ? { activeStreamId: thread.activeStreamId } : {}),\n };\n }\n\n async listThreads(actorRef: string, limit = 50): Promise<ThreadSummary[]> {\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(\n and(\n eq(agentThread.actorRef, actorRef),\n eq(agentThread.transient, false),\n isNull(agentThread.deletedAt),\n ),\n )\n .orderBy(desc(agentThread.updatedAt))\n .limit(limit);\n const summaries: ThreadSummary[] = [];\n for (const thread of threads) {\n const [last] = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, thread.id))\n .orderBy(desc(agentMessage.createdAt), desc(agentMessage.id))\n .limit(1);\n summaries.push(this.toSummary(thread, last?.content));\n }\n return summaries;\n }\n\n async softDeleteThread(threadId: string): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ deletedAt: new Date() })\n .where(eq(agentThread.id, threadId));\n }\n\n async forkThread(threadId: string, fromMessageId: string): Promise<ThreadSummary> {\n const [source] = await this.db.select().from(agentThread).where(eq(agentThread.id, threadId));\n if (source === undefined) {\n throw new Error(`thread ${threadId} not found`);\n }\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));\n const cutoff = messages.findIndex((message) => message.id === fromMessageId);\n const kept = cutoff >= 0 ? messages.slice(0, cutoff + 1) : messages;\n const now = new Date();\n const fork: AgentThreadRow = {\n id: crypto.randomUUID(),\n actorRef: source.actorRef,\n tenantRef: source.tenantRef,\n title: source.title,\n transient: false,\n activeStreamId: null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n };\n await this.db.insert(agentThread).values(fork);\n if (kept.length > 0) {\n await this.db.insert(agentMessage).values(\n kept.map((message) => ({\n id: crypto.randomUUID(),\n threadId: fork.id,\n role: message.role,\n content: message.content,\n toolCalls: message.toolCalls,\n toolResults: message.toolResults,\n followUps: message.followUps,\n usage: message.usage,\n agentName: message.agentName,\n createdAt: message.createdAt,\n })),\n );\n }\n return this.toSummary(fork);\n }\n\n async ownerOfThread(threadId: string): Promise<string | null> {\n const [thread] = await this.db\n .select({ actorRef: agentThread.actorRef })\n .from(agentThread)\n .where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));\n return thread?.actorRef ?? null;\n }\n\n async ownerOfToolCall(toolCallId: string): Promise<string | null> {\n const [row] = await this.db\n .select({ actorRef: agentThread.actorRef })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(eq(agentToolCall.id, toolCallId));\n return row?.actorRef ?? null;\n }\n\n async runForToolCall(toolCallId: string): Promise<string | null> {\n const [row] = await this.db\n .select({ activeStreamId: agentThread.activeStreamId })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(eq(agentToolCall.id, toolCallId));\n return row?.activeStreamId ?? null;\n }\n\n async ownerOfActiveStream(runId: string): Promise<string | null> {\n const [thread] = await this.db\n .select({ actorRef: agentThread.actorRef })\n .from(agentThread)\n .where(and(eq(agentThread.activeStreamId, runId), isNull(agentThread.deletedAt)));\n return thread?.actorRef ?? null;\n }\n\n async setTitle(threadId: string, title: string): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ title, updatedAt: new Date() })\n .where(eq(agentThread.id, threadId));\n }\n\n async promoteThread(threadId: string): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ transient: false, updatedAt: new Date() })\n .where(and(eq(agentThread.id, threadId), eq(agentThread.transient, true)));\n }\n\n async setActiveStream(threadId: string, runId: string | null): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ activeStreamId: runId })\n .where(eq(agentThread.id, threadId));\n }\n\n /** Persist the start of a run (turn). Replay-safe: called under a durable localStep. */\n async recordRunStart(run: {\n runId: string;\n threadId: string;\n actorRef: string;\n agentName?: string;\n promptHash?: string;\n }): Promise<void> {\n const runRow: AgentRunRow = {\n id: run.runId,\n threadId: run.threadId,\n actorRef: run.actorRef,\n agentName: run.agentName ?? null,\n status: 'running',\n durationMs: null,\n errorCode: null,\n errorMessage: null,\n retries: 0,\n startedAt: new Date(),\n settledAt: null,\n promptHash: run.promptHash ?? null,\n };\n await this.db.insert(agentRun).values(runRow);\n }\n\n /** Settle a run's outcome. A no-op when the run is unknown (mirrors `setTitle`/`updateThread`). */\n async recordRunEnd(end: {\n runId: string;\n status: 'completed' | 'failed';\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n }): Promise<void> {\n const updates: Partial<typeof agentRun.$inferInsert> = {\n status: end.status,\n settledAt: new Date(),\n };\n if (end.durationMs !== undefined) {\n updates.durationMs = end.durationMs;\n }\n if (end.errorCode !== undefined) {\n updates.errorCode = end.errorCode;\n }\n if (end.errorMessage !== undefined) {\n updates.errorMessage = end.errorMessage;\n }\n await this.db.update(agentRun).set(updates).where(eq(agentRun.id, end.runId));\n }\n\n /** Bump the run's llm-step retry counter. Atomic `retries = retries + 1`, no read-modify-write. */\n async bumpRunRetries(runId: string): Promise<void> {\n await this.db\n .update(agentRun)\n .set({ retries: sql`${agentRun.retries} + 1` })\n .where(eq(agentRun.id, runId));\n }\n\n async appendMessage(input: AppendMessageInput): Promise<StoredMessage> {\n const [thread] = await this.db\n .select()\n .from(agentThread)\n .where(eq(agentThread.id, input.threadId));\n if (thread === undefined) {\n throw new Error(`thread ${input.threadId} not found`);\n }\n const now = new Date();\n const message: AgentMessageRow = {\n id: crypto.randomUUID(),\n threadId: input.threadId,\n role: input.role,\n content: input.content,\n toolCalls: input.toolCalls ?? null,\n toolResults: input.toolResults ?? null,\n followUps: input.followUps ?? null,\n usage: input.usage ?? null,\n agentName: input.agentName ?? null,\n createdAt: now,\n };\n await this.db.insert(agentMessage).values(message);\n await this.db\n .update(agentThread)\n .set({ updatedAt: now })\n .where(eq(agentThread.id, input.threadId));\n return this.toStoredMessage(message);\n }\n\n async truncateFrom(threadId: string, messageId: string): Promise<void> {\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));\n const cutoff = messages.findIndex((message) => message.id === messageId);\n if (cutoff < 0) {\n return;\n }\n const doomedIds = messages.slice(cutoff).map((message) => message.id);\n await this.db.delete(agentToolCall).where(inArray(agentToolCall.messageId, doomedIds));\n await this.db.delete(agentMessage).where(inArray(agentMessage.id, doomedIds));\n }\n\n async recordToolCall(input: RecordToolCallInput): Promise<void> {\n await this.db.insert(agentToolCall).values({\n id: input.toolCallId,\n messageId: input.messageId,\n toolName: input.toolName,\n toolType: input.toolType,\n input: input.input,\n output: null,\n status: input.status,\n executedByRef: null,\n executionMs: null,\n error: null,\n createdAt: new Date(),\n executedAt: null,\n runId: input.runId ?? null,\n });\n }\n\n async updateToolCall(input: UpdateToolCallInput): Promise<void> {\n const updates: Partial<typeof agentToolCall.$inferInsert> = { status: input.status };\n if (input.output !== undefined) {\n updates.output = input.output;\n }\n if (input.error !== undefined) {\n updates.error = input.error;\n }\n if (input.executionMs !== undefined) {\n updates.executionMs = input.executionMs;\n }\n if (input.executedByRef !== undefined) {\n updates.executedByRef = input.executedByRef;\n }\n if (input.status === 'executed' || input.status === 'auto_executed') {\n updates.executedAt = new Date();\n }\n await this.db.update(agentToolCall).set(updates).where(eq(agentToolCall.id, input.toolCallId));\n }\n\n async recordUsage(input: RecordUsageInput): Promise<void> {\n await this.db.insert(agentTokenUsage).values({\n id: crypto.randomUUID(),\n threadId: input.threadId,\n actorRef: input.actorRef,\n messageId: input.messageId ?? null,\n modelId: input.modelId,\n purpose: input.purpose,\n inputTokens: input.usage.inputTokens,\n outputTokens: input.usage.outputTokens,\n cacheWriteTokens: input.usage.cacheWriteTokens ?? null,\n cacheReadTokens: input.usage.cacheReadTokens ?? null,\n costUsd: input.costUsd ?? null,\n createdAt: new Date(),\n });\n }\n\n async quotaToday(\n actorRef: string,\n day: string,\n ): Promise<{ usedTokens: number; costUsd: number }> {\n const start = new Date(`${day}T00:00:00.000Z`);\n const end = new Date(`${day}T23:59:59.999Z`);\n const rows = await this.db\n .select()\n .from(agentTokenUsage)\n .where(\n and(\n eq(agentTokenUsage.actorRef, actorRef),\n gte(agentTokenUsage.createdAt, start),\n lte(agentTokenUsage.createdAt, end),\n ),\n );\n const usedTokens = rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);\n const costUsd = rows.reduce((sum, row) => sum + (row.costUsd ?? 0), 0);\n return { usedTokens, costUsd };\n }\n\n private toSummary(thread: AgentThreadRow, lastContent?: string): ThreadSummary {\n return {\n id: thread.id,\n title: thread.title,\n transient: thread.transient,\n createdAt: thread.createdAt.toISOString(),\n updatedAt: thread.updatedAt.toISOString(),\n ...(lastContent !== undefined ? { lastMessagePreview: lastContent.slice(0, 120) } : {}),\n };\n }\n\n private toStoredMessage(message: AgentMessageRow): StoredMessage {\n return {\n id: message.id,\n role: message.role,\n content: message.content,\n createdAt: message.createdAt.toISOString(),\n ...(message.toolCalls != null ? { toolCalls: message.toolCalls } : {}),\n ...(message.toolResults != null ? { toolResults: message.toolResults } : {}),\n ...(message.followUps != null ? { followUps: message.followUps } : {}),\n ...(message.usage != null ? { usage: message.usage } : {}),\n ...(message.agentName != null ? { agentName: message.agentName } : {}),\n };\n }\n}\n","import type {\n ActorSpendRow,\n AgentGovernanceQueries,\n AgentPricingStore,\n ApprovalWhere,\n GovernancePage,\n GovernancePageQuery,\n GovernanceRange,\n GovernanceRunDetail,\n GovernanceThreadDetail,\n GovernanceThreadDetailQuery,\n GovernanceUsageInput,\n ModelPrice,\n ModelSpendRow,\n PendingApprovalRow,\n RecentRunRow,\n RunAgentBreakdownRow,\n RunErrorBreakdownRow,\n RunMetrics,\n RunToolCallRow,\n RunTrendPoint,\n RunWhere,\n ThreadActivityRow,\n ThreadMessageRow,\n ThreadMeta,\n ThreadSpendRow,\n ThreadWhere,\n ToolCallActivityRow,\n ToolCallStatus,\n ToolCallWhere,\n ToolKind,\n ToolStatRow,\n UsageTrendPoint,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n bucketByActor,\n bucketByModel,\n bucketByThread,\n bucketUsageTrend,\n dayBoundsUtc,\n rollupThreadUsage,\n truncateDetailContent,\n} from '@dudousxd/nestjs-agent-core';\nimport { and, asc, count, desc, eq, gte, inArray, isNull, like, lte, sql, sum } from 'drizzle-orm';\nimport {\n type AgentDrizzleDb,\n type AgentRunStatus,\n agentMessage,\n agentRun,\n agentThread,\n agentTokenUsage,\n agentToolCall,\n} from './schema.js';\n\n/** No error code recorded on a failed run (the caller didn't classify it). Groups those together. */\nconst UNCLASSIFIED_ERROR_CODE = 'unknown';\n/** Bucket key for a run with no `agentName` (mirrors {@link RunAgentBreakdownRow}'s contract). */\nconst DEFAULT_AGENT_BUCKET = '(default)';\n\n// The paged where-builders below narrow a wire-typed `string` filter value down to the schema\n// column's literal-union `$type<...>()` before it's used in an `eq()` comparison (an unnarrowed\n// `string` isn't assignable to e.g. `agentToolCall.status`'s type). An unrecognized value can never\n// match a row anyway (the column only ever holds these literals), so the paged method short-circuits\n// to an empty page instead of querying with a value that would trivially return nothing.\nconst TOOL_CALL_STATUSES: readonly string[] = [\n 'auto_executed',\n 'pending_approval',\n 'executed',\n 'rejected',\n 'failed',\n];\nfunction isToolCallStatus(value: string): value is ToolCallStatus {\n return TOOL_CALL_STATUSES.includes(value);\n}\n\nconst TOOL_KINDS: readonly string[] = ['read', 'action', 'agent'];\nfunction isToolKind(value: string): value is ToolKind {\n return TOOL_KINDS.includes(value);\n}\n\nconst RUN_STATUSES: readonly string[] = ['running', 'completed', 'failed'];\nfunction isRunStatus(value: string): value is AgentRunStatus {\n return RUN_STATUSES.includes(value);\n}\n\n/** Inclusive UTC day start, reusing {@link dayBoundsUtc}'s date math so both bounds parse identically. */\nfunction dayStartUtc(day: string): Date {\n return dayBoundsUtc({ fromDay: day, toDay: day }).start;\n}\n\n/** Inclusive UTC day end, reusing {@link dayBoundsUtc}'s date math so both bounds parse identically. */\nfunction dayEndUtc(day: string): Date {\n return dayBoundsUtc({ fromDay: day, toDay: day }).end;\n}\n\n/** An empty page for the given query's page/pageSize — the shape every paged read falls back to. */\nfunction emptyPage<TRow>(query: GovernancePageQuery<unknown>): GovernancePage<TRow> {\n return { rows: [], total: 0, page: query.page, pageSize: query.pageSize };\n}\n\n/** Map a run row onto the SPI row. Shared by `recentRuns`/`runsPage`/`runDetail`/`threadDetail`. */\nfunction toRecentRunRow(run: typeof agentRun.$inferSelect): RecentRunRow {\n return {\n runId: run.id,\n threadId: run.threadId,\n actorRef: run.actorRef,\n agentName: run.agentName ?? null,\n status: run.status,\n durationMs: run.durationMs ?? null,\n errorCode: run.errorCode ?? null,\n errorMessage: run.errorMessage ?? null,\n retries: run.retries,\n startedAt: run.startedAt.toISOString(),\n promptHash: run.promptHash ?? null,\n };\n}\n\n/** Map a tool-call row onto the run drill-down's row (execution outcome, not activity-feed shape). */\nfunction toRunToolCallRow(toolCall: typeof agentToolCall.$inferSelect): RunToolCallRow {\n return {\n toolCallId: toolCall.id,\n toolName: toolCall.toolName,\n toolType: toolCall.toolType,\n status: toolCall.status,\n executionMs: toolCall.executionMs ?? null,\n executedByRef: toolCall.executedByRef ?? null,\n error: toolCall.error ?? null,\n createdAt: toolCall.createdAt.toISOString(),\n };\n}\n\n/** Map a Drizzle usage row onto the shared bucketer input (day derived from `createdAt`). */\nfunction toUsageInput(row: typeof agentTokenUsage.$inferSelect): GovernanceUsageInput {\n return {\n modelId: row.modelId,\n actorRef: row.actorRef,\n threadId: row.threadId,\n day: row.createdAt.toISOString().slice(0, 10),\n inputTokens: row.inputTokens,\n outputTokens: row.outputTokens,\n cacheWriteTokens: row.cacheWriteTokens,\n cacheReadTokens: row.cacheReadTokens,\n costUsd: row.costUsd,\n };\n}\n\n/**\n * MySQL-compatible percentile (no `PERCENTILE_CONT`): index into an ascending-sorted array by\n * offset. `null` when there are no settled durations in range. Shared by every reliability query\n * that reports p50/p95 so the SQL and in-memory adapters compute identically.\n */\nfunction percentileMs(sortedDurationsMs: number[], p: number): number | null {\n if (sortedDurationsMs.length === 0) {\n return null;\n }\n const offset = Math.min(sortedDurationsMs.length - 1, Math.floor(p * sortedDurationsMs.length));\n return sortedDurationsMs[offset] ?? null;\n}\n\n/**\n * {@link AgentGovernanceQueries} backed by Drizzle ORM — the read/analytics half of the store SPI,\n * mirroring {@link import('@dudousxd/nestjs-agent-store-mikro-orm')} exactly. Cost is the token\n * ledger priced against the current prices from the injected {@link AgentPricingStore}\n * (`AGENT_PRICING_STORE`), so a host that binds its own pricing store controls the cost every\n * governance surface reports. An unpriced model contributes 0 cost. Aggregation is in-process (like\n * `quotaToday`) so day-bucketing stays dialect-portable.\n */\nexport class DrizzleGovernanceQueries implements AgentGovernanceQueries {\n constructor(\n private readonly db: AgentDrizzleDb,\n private readonly pricingStore: AgentPricingStore,\n ) {}\n\n private async loadPricing(): Promise<Map<string, ModelPrice>> {\n const prices = await this.pricingStore.listCurrentPrices();\n const pricing = new Map<string, ModelPrice>();\n for (const price of prices) {\n pricing.set(price.modelId, {\n inputPricePer1m: price.inputPricePer1m,\n outputPricePer1m: price.outputPricePer1m,\n cacheWritePricePer1m: price.cacheWritePricePer1m ?? null,\n cacheReadPricePer1m: price.cacheReadPricePer1m ?? null,\n });\n }\n return pricing;\n }\n\n private async usageInRange(range: GovernanceRange): Promise<GovernanceUsageInput[]> {\n const { start, end } = dayBoundsUtc(range);\n const rows = await this.db\n .select()\n .from(agentTokenUsage)\n .where(and(gte(agentTokenUsage.createdAt, start), lte(agentTokenUsage.createdAt, end)));\n return rows.map(toUsageInput);\n }\n\n async spendByModel(range: GovernanceRange): Promise<ModelSpendRow[]> {\n const pricing = await this.loadPricing();\n return bucketByModel(await this.usageInRange(range), pricing);\n }\n\n async spendByActor(range: GovernanceRange): Promise<ActorSpendRow[]> {\n const pricing = await this.loadPricing();\n return bucketByActor(await this.usageInRange(range), pricing);\n }\n\n /**\n * Top threads by spend within the range, highest cost first, capped at `limit`. Usage rows for a\n * soft-deleted thread (`deletedAt` set) are excluded — the thread no longer surfaces as a\n * governance target even though its ledger rows survive.\n */\n async spendByThread(range: GovernanceRange, limit: number): Promise<ThreadSpendRow[]> {\n const pricing = await this.loadPricing();\n const rows = await this.usageInRange(range);\n const threadIds = [...new Set(rows.map((row) => row.threadId))];\n if (threadIds.length === 0) {\n return [];\n }\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(and(inArray(agentThread.id, threadIds), isNull(agentThread.deletedAt)));\n const threadsById = new Map<string, ThreadMeta>(\n threads.map((thread) => [thread.id, { title: thread.title, actorRef: thread.actorRef }]),\n );\n return bucketByThread(rows, pricing, threadsById, { limit, includeUnknownThreads: false });\n }\n\n async usageTrend(range: GovernanceRange): Promise<UsageTrendPoint[]> {\n const pricing = await this.loadPricing();\n return bucketUsageTrend(await this.usageInRange(range), pricing);\n }\n\n async recentToolCalls(limit: number): Promise<ToolCallActivityRow[]> {\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n toolType: agentToolCall.toolType,\n status: agentToolCall.status,\n threadId: agentMessage.threadId,\n createdAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .orderBy(desc(agentToolCall.createdAt), desc(agentToolCall.id))\n .limit(limit);\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n toolType: row.toolType,\n status: row.status,\n threadId: row.threadId,\n createdAt: row.createdAt.toISOString(),\n runId: row.runId,\n }));\n }\n\n /**\n * Message counts and token totals for a whole set of threads in TWO grouped queries, not two per\n * thread — a 200-row page used to cost four hundred round trips. Mirrors the MikroORM adapter's\n * `threadRollups`, which reaches the same numbers without a QueryBuilder.\n */\n private async threadRollups(\n threadIds: string[],\n ): Promise<Map<string, { messageCount: number; totalTokens: number }>> {\n const rollups = new Map<string, { messageCount: number; totalTokens: number }>(\n threadIds.map((threadId) => [threadId, { messageCount: 0, totalTokens: 0 }]),\n );\n if (threadIds.length === 0) {\n return rollups;\n }\n const messageCounts = await this.db\n .select({ threadId: agentMessage.threadId, value: count() })\n .from(agentMessage)\n .where(inArray(agentMessage.threadId, threadIds))\n .groupBy(agentMessage.threadId);\n for (const row of messageCounts) {\n const bucket = rollups.get(row.threadId);\n if (bucket !== undefined) {\n bucket.messageCount = row.value;\n }\n }\n const usageTotals = await this.db\n .select({\n threadId: agentTokenUsage.threadId,\n inputTokens: sum(agentTokenUsage.inputTokens),\n outputTokens: sum(agentTokenUsage.outputTokens),\n })\n .from(agentTokenUsage)\n .where(inArray(agentTokenUsage.threadId, threadIds))\n .groupBy(agentTokenUsage.threadId);\n for (const row of usageTotals) {\n const bucket = rollups.get(row.threadId);\n if (bucket !== undefined) {\n // Drizzle types SUM() as string|null (a dialect can widen it past a JS number).\n bucket.totalTokens = Number(row.inputTokens ?? 0) + Number(row.outputTokens ?? 0);\n }\n }\n return rollups;\n }\n\n /** Decorate an ordered thread list with its batched rollups, preserving the incoming order. */\n private async toThreadActivityRows(\n threads: (typeof agentThread.$inferSelect)[],\n ): Promise<ThreadActivityRow[]> {\n const rollups = await this.threadRollups(threads.map((thread) => thread.id));\n return threads.map((thread) => {\n const rollup = rollups.get(thread.id);\n return {\n threadId: thread.id,\n title: thread.title,\n actorRef: thread.actorRef,\n messageCount: rollup?.messageCount ?? 0,\n totalTokens: rollup?.totalTokens ?? 0,\n lastActivityAt: thread.updatedAt.toISOString(),\n };\n });\n }\n\n async recentThreads(limit: number): Promise<ThreadActivityRow[]> {\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(isNull(agentThread.deletedAt))\n .orderBy(desc(agentThread.updatedAt), desc(agentThread.id))\n .limit(limit);\n return this.toThreadActivityRows(threads);\n }\n\n private async runsInRange(range: GovernanceRange): Promise<(typeof agentRun.$inferSelect)[]> {\n const { start, end } = dayBoundsUtc(range);\n return this.db\n .select()\n .from(agentRun)\n .where(and(gte(agentRun.startedAt, start), lte(agentRun.startedAt, end)));\n }\n\n async runMetrics(range: GovernanceRange): Promise<RunMetrics> {\n const runs = await this.runsInRange(range);\n let completed = 0;\n let failed = 0;\n let retries = 0;\n const settledDurationsMs: number[] = [];\n for (const run of runs) {\n if (run.status === 'completed') {\n completed += 1;\n } else if (run.status === 'failed') {\n failed += 1;\n }\n retries += run.retries;\n if ((run.status === 'completed' || run.status === 'failed') && run.durationMs != null) {\n settledDurationsMs.push(run.durationMs);\n }\n }\n settledDurationsMs.sort((left, right) => left - right);\n return {\n runs: runs.length,\n completed,\n failed,\n successRate: runs.length === 0 ? 0 : completed / runs.length,\n retries,\n durationP50Ms: percentileMs(settledDurationsMs, 0.5),\n durationP95Ms: percentileMs(settledDurationsMs, 0.95),\n };\n }\n\n async runsByAgent(range: GovernanceRange): Promise<RunAgentBreakdownRow[]> {\n const runs = await this.runsInRange(range);\n const byAgent = new Map<string, { runs: number; failed: number; retries: number }>();\n for (const run of runs) {\n const agentName = run.agentName ?? DEFAULT_AGENT_BUCKET;\n const bucket = byAgent.get(agentName) ?? { runs: 0, failed: 0, retries: 0 };\n bucket.runs += 1;\n bucket.failed += run.status === 'failed' ? 1 : 0;\n bucket.retries += run.retries;\n byAgent.set(agentName, bucket);\n }\n const result: RunAgentBreakdownRow[] = [];\n for (const [agentName, bucket] of byAgent) {\n result.push({ agentName, ...bucket });\n }\n result.sort(\n (left, right) => right.runs - left.runs || left.agentName.localeCompare(right.agentName),\n );\n return result;\n }\n\n async runErrors(range: GovernanceRange): Promise<RunErrorBreakdownRow[]> {\n const { start, end } = dayBoundsUtc(range);\n const runs = await this.db\n .select()\n .from(agentRun)\n .where(\n and(\n gte(agentRun.startedAt, start),\n lte(agentRun.startedAt, end),\n eq(agentRun.status, 'failed'),\n ),\n );\n const byError = new Map<string, number>();\n for (const run of runs) {\n const errorCode = run.errorCode ?? UNCLASSIFIED_ERROR_CODE;\n byError.set(errorCode, (byError.get(errorCode) ?? 0) + 1);\n }\n const result: RunErrorBreakdownRow[] = [];\n for (const [errorCode, errorCount] of byError) {\n result.push({ errorCode, count: errorCount });\n }\n result.sort(\n (left, right) => right.count - left.count || left.errorCode.localeCompare(right.errorCode),\n );\n return result;\n }\n\n async runTrend(range: GovernanceRange): Promise<RunTrendPoint[]> {\n const runs = await this.runsInRange(range);\n const byDay = new Map<string, { runs: number; failed: number }>();\n for (const run of runs) {\n const day = run.startedAt.toISOString().slice(0, 10);\n const bucket = byDay.get(day) ?? { runs: 0, failed: 0 };\n bucket.runs += 1;\n bucket.failed += run.status === 'failed' ? 1 : 0;\n byDay.set(day, bucket);\n }\n const result: RunTrendPoint[] = [];\n for (const [day, bucket] of byDay) {\n result.push({ day, ...bucket });\n }\n result.sort((left, right) => left.day.localeCompare(right.day));\n return result;\n }\n\n async recentRuns(limit: number): Promise<RecentRunRow[]> {\n const runs = await this.db\n .select()\n .from(agentRun)\n .orderBy(desc(agentRun.startedAt), desc(agentRun.id))\n .limit(limit);\n return runs.map(toRecentRunRow);\n }\n\n /**\n * Tool calls sitting `pending_approval`, oldest first (an inbox drains from the back), joined\n * through their message to the owning thread for title/actorRef and to the message itself for\n * `agentName` (null when the message carries none).\n */\n async pendingApprovals(limit: number): Promise<PendingApprovalRow[]> {\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n input: agentToolCall.input,\n threadId: agentThread.id,\n threadTitle: agentThread.title,\n actorRef: agentThread.actorRef,\n agentName: agentMessage.agentName,\n requestedAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(eq(agentToolCall.status, 'pending_approval'))\n .orderBy(agentToolCall.createdAt, agentToolCall.id)\n .limit(limit);\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n input: row.input,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? null,\n requestedAt: row.requestedAt.toISOString(),\n runId: row.runId,\n }));\n }\n\n /**\n * Per-tool call/failure/rejection/latency rollup over the range, highest call count first.\n * `p50ExecutionMs`/`p95ExecutionMs` are computed over calls that recorded a non-null `executionMs`\n * (regardless of their final status); both `null` when none did. Percentiles are taken in-process\n * off the sorted sample rather than in SQL, matching the MikroORM adapter — MySQL has no\n * `PERCENTILE_CONT` and one portable implementation beats three dialect-specific ones.\n */\n async toolStats(range: GovernanceRange): Promise<ToolStatRow[]> {\n const { start, end } = dayBoundsUtc(range);\n const calls = await this.db\n .select()\n .from(agentToolCall)\n .where(and(gte(agentToolCall.createdAt, start), lte(agentToolCall.createdAt, end)));\n const byTool = new Map<\n string,\n {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n executionMs: number[];\n }\n >();\n for (const call of calls) {\n const key = `${call.toolName} ${call.toolType}`;\n const bucket = byTool.get(key) ?? {\n toolName: call.toolName,\n toolType: call.toolType,\n calls: 0,\n failed: 0,\n rejected: 0,\n executionMs: [],\n };\n bucket.calls += 1;\n bucket.failed += call.status === 'failed' ? 1 : 0;\n bucket.rejected += call.status === 'rejected' ? 1 : 0;\n if (call.executionMs != null) {\n bucket.executionMs.push(call.executionMs);\n }\n byTool.set(key, bucket);\n }\n const result: ToolStatRow[] = [];\n for (const bucket of byTool.values()) {\n bucket.executionMs.sort((left, right) => left - right);\n result.push({\n toolName: bucket.toolName,\n toolType: bucket.toolType,\n calls: bucket.calls,\n failed: bucket.failed,\n rejected: bucket.rejected,\n p50ExecutionMs: percentileMs(bucket.executionMs, 0.5),\n p95ExecutionMs: percentileMs(bucket.executionMs, 0.95),\n });\n }\n result.sort(\n (left, right) => right.calls - left.calls || left.toolName.localeCompare(right.toolName),\n );\n return result;\n }\n\n /**\n * Paged, filterable tool-call activity, newest-first (same ordering as {@link recentToolCalls}).\n * `toolType`/`status` values outside the known literals can never match a row — short-circuits to\n * an empty page rather than issuing a query. Joins `agent_message` unconditionally (like\n * `recentToolCalls`) to resolve `threadId` and to support the `threadId` filter.\n */\n async toolCallsPage(\n query: GovernancePageQuery<ToolCallWhere>,\n ): Promise<GovernancePage<ToolCallActivityRow>> {\n const filters = query.where;\n if (filters?.status !== undefined && !isToolCallStatus(filters.status)) {\n return emptyPage(query);\n }\n if (filters?.toolType !== undefined && !isToolKind(filters.toolType)) {\n return emptyPage(query);\n }\n const whereClause = and(\n filters?.toolName !== undefined ? eq(agentToolCall.toolName, filters.toolName) : undefined,\n filters?.toolType !== undefined && isToolKind(filters.toolType)\n ? eq(agentToolCall.toolType, filters.toolType)\n : undefined,\n filters?.status !== undefined && isToolCallStatus(filters.status)\n ? eq(agentToolCall.status, filters.status)\n : undefined,\n filters?.threadId !== undefined ? eq(agentMessage.threadId, filters.threadId) : undefined,\n filters?.fromDay !== undefined\n ? gte(agentToolCall.createdAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined\n ? lte(agentToolCall.createdAt, dayEndUtc(filters.toDay))\n : undefined,\n );\n const [totalRow] = await this.db\n .select({ value: count() })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .where(whereClause);\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n toolType: agentToolCall.toolType,\n status: agentToolCall.status,\n threadId: agentMessage.threadId,\n createdAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .where(whereClause)\n .orderBy(desc(agentToolCall.createdAt), desc(agentToolCall.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n return {\n rows: rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n toolType: row.toolType,\n status: row.status,\n threadId: row.threadId,\n createdAt: row.createdAt.toISOString(),\n runId: row.runId,\n })),\n total: totalRow?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n /**\n * Paged, filterable thread activity, newest-first (same ordering as {@link recentThreads}).\n * `title` is a case-insensitive substring match via `lower(...)` on both sides (portable across\n * dialects, regardless of the underlying column collation). Soft-deleted threads are excluded,\n * mirroring `recentThreads`.\n */\n async threadsPage(\n query: GovernancePageQuery<ThreadWhere>,\n ): Promise<GovernancePage<ThreadActivityRow>> {\n const filters = query.where;\n const whereClause = and(\n isNull(agentThread.deletedAt),\n filters?.actorRef !== undefined ? eq(agentThread.actorRef, filters.actorRef) : undefined,\n filters?.title !== undefined\n ? like(sql`lower(${agentThread.title})`, `%${filters.title.toLowerCase()}%`)\n : undefined,\n filters?.fromDay !== undefined\n ? gte(agentThread.updatedAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined\n ? lte(agentThread.updatedAt, dayEndUtc(filters.toDay))\n : undefined,\n );\n const [totalRow] = await this.db\n .select({ value: count() })\n .from(agentThread)\n .where(whereClause);\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(whereClause)\n .orderBy(desc(agentThread.updatedAt), desc(agentThread.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n const rows = await this.toThreadActivityRows(threads);\n return { rows, total: totalRow?.value ?? 0, page: query.page, pageSize: query.pageSize };\n }\n\n /**\n * Paged, filterable run activity, newest-first (same ordering as {@link recentRuns}). `status`\n * values outside the known literals can never match a row — short-circuits to an empty page.\n */\n async runsPage(query: GovernancePageQuery<RunWhere>): Promise<GovernancePage<RecentRunRow>> {\n const filters = query.where;\n if (filters?.status !== undefined && !isRunStatus(filters.status)) {\n return emptyPage(query);\n }\n const whereClause = and(\n filters?.agentName !== undefined ? eq(agentRun.agentName, filters.agentName) : undefined,\n filters?.status !== undefined && isRunStatus(filters.status)\n ? eq(agentRun.status, filters.status)\n : undefined,\n filters?.errorCode !== undefined ? eq(agentRun.errorCode, filters.errorCode) : undefined,\n filters?.threadId !== undefined ? eq(agentRun.threadId, filters.threadId) : undefined,\n filters?.fromDay !== undefined\n ? gte(agentRun.startedAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined ? lte(agentRun.startedAt, dayEndUtc(filters.toDay)) : undefined,\n );\n const [totalRow] = await this.db.select({ value: count() }).from(agentRun).where(whereClause);\n const runs = await this.db\n .select()\n .from(agentRun)\n .where(whereClause)\n .orderBy(desc(agentRun.startedAt), desc(agentRun.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n return {\n rows: runs.map(toRecentRunRow),\n total: totalRow?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n /**\n * Paged, filterable approvals inbox, oldest first — the same ordering as {@link pendingApprovals},\n * now with the `total` that method structurally cannot report. The join to `agent_message` /\n * `agent_thread` is unconditional (it already resolves title/actor/agentName), so the `threadId`/\n * `actorRef`/`agentName` filters cost nothing extra.\n *\n * The order is TOTAL (`created_at asc, id asc`, and `id` is the primary key), so no row can land on\n * two pages or on none for a given snapshot. Ascending order also means a newly requested approval\n * appends past the last page instead of shifting the page an operator is currently reading.\n */\n async approvalsPage(\n query: GovernancePageQuery<ApprovalWhere>,\n ): Promise<GovernancePage<PendingApprovalRow>> {\n const filters = query.where;\n const whereClause = and(\n eq(agentToolCall.status, 'pending_approval'),\n filters?.toolName !== undefined ? eq(agentToolCall.toolName, filters.toolName) : undefined,\n filters?.threadId !== undefined ? eq(agentThread.id, filters.threadId) : undefined,\n filters?.actorRef !== undefined ? eq(agentThread.actorRef, filters.actorRef) : undefined,\n filters?.agentName !== undefined ? eq(agentMessage.agentName, filters.agentName) : undefined,\n filters?.fromDay !== undefined\n ? gte(agentToolCall.createdAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined\n ? lte(agentToolCall.createdAt, dayEndUtc(filters.toDay))\n : undefined,\n );\n const [totalRow] = await this.db\n .select({ value: count() })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(whereClause);\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n input: agentToolCall.input,\n threadId: agentThread.id,\n threadTitle: agentThread.title,\n actorRef: agentThread.actorRef,\n agentName: agentMessage.agentName,\n requestedAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(whereClause)\n .orderBy(asc(agentToolCall.createdAt), asc(agentToolCall.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n return {\n rows: rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n input: row.input,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? null,\n requestedAt: row.requestedAt.toISOString(),\n runId: row.runId,\n })),\n total: totalRow?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n /**\n * One run, its owning thread's headline and its tool calls — TWO queries regardless of how many\n * tools the run called. `toolCalls` comes off `agent_tool_call.run_id`, so a run recorded before\n * that column was written reports none.\n */\n async runDetail(runId: string): Promise<GovernanceRunDetail | null> {\n const [row] = await this.db\n .select({ run: agentRun, thread: agentThread })\n .from(agentRun)\n .innerJoin(agentThread, eq(agentRun.threadId, agentThread.id))\n .where(eq(agentRun.id, runId))\n .limit(1);\n if (row === undefined) {\n return null;\n }\n const toolCalls = await this.db\n .select()\n .from(agentToolCall)\n .where(eq(agentToolCall.runId, runId))\n .orderBy(asc(agentToolCall.createdAt), asc(agentToolCall.id));\n return {\n run: toRecentRunRow(row.run),\n thread: {\n threadId: row.thread.id,\n title: row.thread.title,\n actorRef: row.thread.actorRef,\n deleted: row.thread.deletedAt != null,\n },\n toolCalls: toolCalls.map(toRunToolCallRow),\n };\n }\n\n /**\n * One thread with its lifetime usage rollup, its newest runs and its newest messages. A fixed six\n * queries (thread, usage, message count, message page, that page's tool-call counts, runs+count) —\n * the per-message tool-call counts are ONE grouped read over the returned message ids, not one per\n * message. Soft-deleted threads are returned with `deleted: true`; an audit still needs them.\n */\n async threadDetail(query: GovernanceThreadDetailQuery): Promise<GovernanceThreadDetail | null> {\n const [thread] = await this.db\n .select()\n .from(agentThread)\n .where(eq(agentThread.id, query.threadId))\n .limit(1);\n if (thread === undefined) {\n return null;\n }\n const pricing = await this.loadPricing();\n const usageRows = await this.db\n .select()\n .from(agentTokenUsage)\n .where(eq(agentTokenUsage.threadId, thread.id));\n const usage = rollupThreadUsage(usageRows.map(toUsageInput), pricing);\n const [messageCountRow] = await this.db\n .select({ value: count() })\n .from(agentMessage)\n .where(eq(agentMessage.threadId, thread.id));\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, thread.id))\n .orderBy(desc(agentMessage.createdAt), desc(agentMessage.id))\n .limit(query.messageLimit);\n const toolCallCounts = await this.toolCallCountsByMessage(\n messages.map((message) => message.id),\n );\n const [runTotalRow] = await this.db\n .select({ value: count() })\n .from(agentRun)\n .where(eq(agentRun.threadId, thread.id));\n const runs = await this.db\n .select()\n .from(agentRun)\n .where(eq(agentRun.threadId, thread.id))\n .orderBy(desc(agentRun.startedAt), desc(agentRun.id))\n .limit(query.runLimit);\n return {\n thread: {\n threadId: thread.id,\n title: thread.title,\n actorRef: thread.actorRef,\n messageCount: messageCountRow?.value ?? 0,\n totalTokens: usage.totalTokens,\n lastActivityAt: thread.updatedAt.toISOString(),\n },\n deleted: thread.deletedAt != null,\n usage,\n runs: runs.map(toRecentRunRow),\n runTotal: runTotalRow?.value ?? 0,\n messages: messages.map((message): ThreadMessageRow => {\n const { content, truncated } = truncateDetailContent(message.content);\n return {\n messageId: message.id,\n role: message.role,\n content,\n truncated,\n agentName: message.agentName ?? null,\n toolCallCount: toolCallCounts.get(message.id) ?? 0,\n createdAt: message.createdAt.toISOString(),\n };\n }),\n };\n }\n\n /** Tool-call counts for a set of messages in ONE grouped query — the detail view's no-N+1 guarantee. */\n private async toolCallCountsByMessage(messageIds: string[]): Promise<Map<string, number>> {\n const counts = new Map<string, number>();\n if (messageIds.length === 0) {\n return counts;\n }\n const rows = await this.db\n .select({ messageId: agentToolCall.messageId, value: count() })\n .from(agentToolCall)\n .where(inArray(agentToolCall.messageId, messageIds))\n .groupBy(agentToolCall.messageId);\n for (const row of rows) {\n counts.set(row.messageId, row.value);\n }\n return counts;\n }\n}\n","import type {\n AgentPricingStore,\n CurrentModelPrice,\n ModelPriceInput,\n} from '@dudousxd/nestjs-agent-core';\nimport { and, eq } from 'drizzle-orm';\nimport { type AgentDrizzleDb, agentModelPricing } from './schema.js';\n\n/**\n * {@link AgentPricingStore} backed by Drizzle ORM — the write side of the pricing table\n * {@link import('./drizzle-governance-queries.js').DrizzleGovernanceQueries} joins against. A POJO\n * receiving a Drizzle SQLite database handle (the host app owns the connection), mirroring\n * {@link import('@dudousxd/nestjs-agent-store-mikro-orm')} exactly (atomic supersede semantics).\n */\nexport class DrizzlePricingStore implements AgentPricingStore {\n constructor(private readonly db: AgentDrizzleDb) {}\n\n async upsertModelPrice(input: ModelPriceInput): Promise<void> {\n await this.db\n .update(agentModelPricing)\n .set({ isCurrent: false })\n .where(\n and(eq(agentModelPricing.modelId, input.modelId), eq(agentModelPricing.isCurrent, true)),\n );\n await this.db.insert(agentModelPricing).values({\n id: crypto.randomUUID(),\n modelId: input.modelId,\n inputPricePer1m: input.inputPricePer1m,\n outputPricePer1m: input.outputPricePer1m,\n cacheWritePricePer1m: input.cacheWritePricePer1m ?? null,\n cacheReadPricePer1m: input.cacheReadPricePer1m ?? null,\n effectiveFrom: new Date(),\n isCurrent: true,\n });\n }\n\n async listCurrentPrices(): Promise<CurrentModelPrice[]> {\n const rows = await this.db\n .select()\n .from(agentModelPricing)\n .where(eq(agentModelPricing.isCurrent, true));\n return rows.map((row) => ({\n modelId: row.modelId,\n inputPricePer1m: row.inputPricePer1m,\n outputPricePer1m: row.outputPricePer1m,\n effectiveFrom: row.effectiveFrom.toISOString(),\n ...(row.cacheWritePricePer1m != null\n ? { cacheWritePricePer1m: row.cacheWritePricePer1m }\n : {}),\n ...(row.cacheReadPricePer1m != null ? { cacheReadPricePer1m: row.cacheReadPricePer1m } : {}),\n }));\n }\n}\n","import {\n AGENT_GOVERNANCE_QUERIES,\n AGENT_PRICING_STORE,\n AGENT_STORE,\n type AgentPricingStore,\n} from '@dudousxd/nestjs-agent-core';\nimport { type DynamicModule, Module, type Type } from '@nestjs/common';\nimport { DrizzleAgentStore } from './drizzle-agent-store.js';\nimport { DrizzleGovernanceQueries } from './drizzle-governance-queries.js';\nimport { DrizzlePricingStore } from './drizzle-pricing-store.js';\nimport type { AgentDrizzleDb } from './schema.js';\n\n/** Options for {@link DrizzleAgentStoreModule.forRoot}. The app owns and supplies the db handle. */\nexport interface DrizzleAgentStoreModuleOptions {\n /** A Drizzle SQLite database instance (`drizzle(client, { schema: agentSchema })`). */\n db: AgentDrizzleDb;\n /**\n * Bind {@link AGENT_PRICING_STORE} (which {@link DrizzleGovernanceQueries} prices usage against) to\n * a host-supplied store instead of the default {@link DrizzlePricingStore} — make your OWN pricing\n * table the single source of cost truth without touching `agent_model_pricing`.\n */\n pricingStore?: Type<AgentPricingStore>;\n}\n\n/**\n * Binds {@link DrizzleAgentStore} to the {@link AGENT_STORE} token consumed by\n * `@dudousxd/nestjs-agent`, plus {@link DrizzleGovernanceQueries} to\n * {@link AGENT_GOVERNANCE_QUERIES} (the read-model the dashboard/telescope surfaces consume) and\n * {@link DrizzlePricingStore} to {@link AGENT_PRICING_STORE} (the write side of that pricing table).\n * The host app supplies an already-opened Drizzle db — this module never opens a connection itself.\n *\n * The returned module is global, so {@link AGENT_STORE}, {@link AGENT_GOVERNANCE_QUERIES} and\n * {@link AGENT_PRICING_STORE} are visible app-wide — `AgentModule` resolves the store without an\n * explicit `store` option, and the dashboard/telescope resolve {@link AGENT_GOVERNANCE_QUERIES}\n * without the host re-binding it.\n *\n * ```ts\n * @Module({ imports: [DrizzleAgentStoreModule.forRoot({ db })] })\n * export class AppModule {}\n * ```\n */\n@Module({})\nexport class DrizzleAgentStoreModule {\n static forRoot(options: DrizzleAgentStoreModuleOptions): DynamicModule {\n return {\n module: DrizzleAgentStoreModule,\n global: true,\n providers: [\n { provide: DrizzleAgentStore, useFactory: () => new DrizzleAgentStore(options.db) },\n { provide: AGENT_STORE, useExisting: DrizzleAgentStore },\n {\n provide: DrizzlePricingStore,\n useFactory: () => new DrizzlePricingStore(options.db),\n },\n // AGENT_PRICING_STORE: the host's own store when supplied, else the default Drizzle one.\n // DrizzleGovernanceQueries prices usage against whatever is bound here.\n options.pricingStore\n ? { provide: AGENT_PRICING_STORE, useClass: options.pricingStore }\n : { provide: AGENT_PRICING_STORE, useExisting: DrizzlePricingStore },\n {\n provide: DrizzleGovernanceQueries,\n useFactory: (pricingStore: AgentPricingStore) =>\n new DrizzleGovernanceQueries(options.db, pricingStore),\n inject: [AGENT_PRICING_STORE],\n },\n { provide: AGENT_GOVERNANCE_QUERIES, useExisting: DrizzleGovernanceQueries },\n ],\n exports: [\n DrizzleAgentStore,\n AGENT_STORE,\n DrizzleGovernanceQueries,\n AGENT_GOVERNANCE_QUERIES,\n DrizzlePricingStore,\n AGENT_PRICING_STORE,\n ],\n };\n }\n}\n"],"mappings":"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","names":["index","integer","real","sqliteTable","text","agentThread","id","primaryKey","actorRef","notNull","tenantRef","title","transient","mode","default","activeStreamId","createdAt","updatedAt","deletedAt","table","on","agentMessage","threadId","references","onDelete","role","$type","content","toolCalls","toolResults","followUps","usage","agentName","agentToolCall","messageId","toolName","toolType","input","output","status","executedByRef","executionMs","error","executedAt","runId","agentTokenUsage","modelId","purpose","inputTokens","outputTokens","cacheWriteTokens","cacheReadTokens","costUsd","agentModelPricing","inputPricePer1m","outputPricePer1m","cacheWritePricePer1m","cacheReadPricePer1m","effectiveFrom","isCurrent","agentRun","durationMs","errorCode","errorMessage","retries","startedAt","settledAt","promptHash","agentSchema","sql","statements","ensureAgentSchema","db","statement","run","sql","raw","and","asc","desc","eq","gte","inArray","isNull","lte","sql","DrizzleAgentStore","db","createThread","input","now","Date","thread","id","crypto","randomUUID","actorRef","actor","tenantRef","title","transient","activeStreamId","createdAt","updatedAt","deletedAt","insert","agentThread","values","toSummary","getThread","threadId","select","from","where","and","eq","isNull","undefined","messages","agentMessage","orderBy","asc","last","length","content","map","message","toStoredMessage","listThreads","limit","threads","desc","summaries","push","softDeleteThread","update","set","forkThread","fromMessageId","source","Error","cutoff","findIndex","kept","slice","fork","role","toolCalls","toolResults","followUps","usage","agentName","ownerOfThread","ownerOfToolCall","toolCallId","row","agentToolCall","innerJoin","messageId","runForToolCall","ownerOfActiveStream","runId","setTitle","promoteThread","setActiveStream","recordRunStart","run","runRow","status","durationMs","errorCode","errorMessage","retries","startedAt","settledAt","promptHash","agentRun","recordRunEnd","end","updates","bumpRunRetries","sql","appendMessage","truncateFrom","doomedIds","delete","inArray","recordToolCall","toolName","toolType","output","executedByRef","executionMs","error","executedAt","updateToolCall","recordUsage","agentTokenUsage","modelId","purpose","inputTokens","outputTokens","cacheWriteTokens","cacheReadTokens","costUsd","quotaToday","day","start","rows","gte","lte","usedTokens","reduce","sum","lastContent","toISOString","lastMessagePreview","bucketByActor","bucketByModel","bucketByThread","bucketUsageTrend","dayBoundsUtc","rollupThreadUsage","truncateDetailContent","and","asc","count","desc","eq","gte","inArray","isNull","like","lte","sql","sum","UNCLASSIFIED_ERROR_CODE","DEFAULT_AGENT_BUCKET","TOOL_CALL_STATUSES","isToolCallStatus","value","includes","TOOL_KINDS","isToolKind","RUN_STATUSES","isRunStatus","dayStartUtc","day","dayBoundsUtc","fromDay","toDay","start","dayEndUtc","end","emptyPage","query","rows","total","page","pageSize","toRecentRunRow","run","runId","id","threadId","actorRef","agentName","status","durationMs","errorCode","errorMessage","retries","startedAt","toISOString","promptHash","toRunToolCallRow","toolCall","toolCallId","toolName","toolType","executionMs","executedByRef","error","createdAt","toUsageInput","row","modelId","slice","inputTokens","outputTokens","cacheWriteTokens","cacheReadTokens","costUsd","percentileMs","sortedDurationsMs","p","length","offset","Math","min","floor","DrizzleGovernanceQueries","db","pricingStore","loadPricing","prices","listCurrentPrices","pricing","Map","price","set","inputPricePer1m","outputPricePer1m","cacheWritePricePer1m","cacheReadPricePer1m","usageInRange","range","select","from","agentTokenUsage","where","and","gte","lte","map","spendByModel","bucketByModel","spendByActor","bucketByActor","spendByThread","limit","threadIds","Set","threads","agentThread","inArray","isNull","deletedAt","threadsById","thread","title","bucketByThread","includeUnknownThreads","usageTrend","bucketUsageTrend","recentToolCalls","agentToolCall","agentMessage","innerJoin","eq","messageId","orderBy","desc","threadRollups","rollups","messageCount","totalTokens","messageCounts","count","groupBy","bucket","get","undefined","usageTotals","sum","Number","toThreadActivityRows","rollup","lastActivityAt","updatedAt","recentThreads","runsInRange","agentRun","runMetrics","runs","completed","failed","settledDurationsMs","push","sort","left","right","successRate","durationP50Ms","durationP95Ms","runsByAgent","byAgent","result","localeCompare","runErrors","byError","errorCount","runTrend","byDay","recentRuns","pendingApprovals","input","threadTitle","requestedAt","toolStats","calls","byTool","call","key","rejected","values","p50ExecutionMs","p95ExecutionMs","toolCallsPage","filters","whereClause","totalRow","threadsPage","like","sql","toLowerCase","runsPage","approvalsPage","asc","runDetail","toolCalls","deleted","threadDetail","usageRows","usage","rollupThreadUsage","messageCountRow","messages","messageLimit","toolCallCounts","toolCallCountsByMessage","message","runTotalRow","runLimit","runTotal","content","truncated","truncateDetailContent","role","toolCallCount","messageIds","counts","and","eq","DrizzlePricingStore","db","upsertModelPrice","input","update","agentModelPricing","set","isCurrent","where","and","eq","modelId","insert","values","id","crypto","randomUUID","inputPricePer1m","outputPricePer1m","cacheWritePricePer1m","cacheReadPricePer1m","effectiveFrom","Date","listCurrentPrices","rows","select","from","map","row","toISOString","AGENT_GOVERNANCE_QUERIES","AGENT_PRICING_STORE","AGENT_STORE","Module","DrizzleAgentStoreModule","forRoot","options","module","global","providers","provide","DrizzleAgentStore","useFactory","db","AGENT_STORE","useExisting","DrizzlePricingStore","pricingStore","AGENT_PRICING_STORE","useClass","DrizzleGovernanceQueries","inject","AGENT_GOVERNANCE_QUERIES","exports"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/ensure-schema.ts","../src/drizzle-agent-store.ts","../src/drizzle-governance-queries.ts","../src/drizzle-pricing-store.ts","../src/drizzle-agent-store.module.ts"],"sourcesContent":["import type {\n MessageAttachment,\n MessageRole,\n MessageUsage,\n ToolCallRequest,\n ToolCallStatus,\n ToolKind,\n ToolResult,\n UsagePurpose,\n} from '@dudousxd/nestjs-agent-core';\nimport type { TablesRelationalConfig } from 'drizzle-orm';\nimport {\n type BaseSQLiteDatabase,\n index,\n integer,\n real,\n sqliteTable,\n text,\n} from 'drizzle-orm/sqlite-core';\n\n/**\n * Drizzle schema mirroring the MikroORM agent entities (same logical columns/relations):\n * threads, messages, tool calls, token usage, model pricing and run outcomes. Targets the SQLite core so the\n * db-test runs on an in-memory better-sqlite3; timestamps are stored as integer epoch-ms columns\n * (`{ mode: 'timestamp_ms' }`) which Drizzle round-trips to/from JS `Date`, and the model-facing\n * message extras (tool calls/results, follow-ups, usage) live in JSON `text` columns.\n */\n\n/**\n * A conversation thread. `deletedAt` drives soft delete: a deleted thread is hidden from\n * {@link import('./drizzle-agent-store.js').DrizzleAgentStore.getThread}/`listThreads` but its\n * row survives.\n */\nexport const agentThread = sqliteTable(\n 'agent_thread',\n {\n id: text('id').primaryKey(),\n actorRef: text('actor_ref').notNull(),\n tenantRef: text('tenant_ref'),\n title: text('title').notNull(),\n transient: integer('transient', { mode: 'boolean' }).notNull().default(false),\n activeStreamId: text('active_stream_id'),\n /** The agent a new turn on this thread defaults to when the caller names none. */\n defaultAgent: text('default_agent'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),\n deletedAt: integer('deleted_at', { mode: 'timestamp_ms' }),\n },\n (table) => [index('agent_thread_actor_updated_idx').on(table.actorRef, table.updatedAt)],\n);\n\n/**\n * One stored message in a thread. The model-facing extras (`toolCalls`/`toolResults`/\n * `followUps`/`usage`) are folded into nullable JSON columns so a single row round-trips to a\n * {@link import('@dudousxd/nestjs-agent-core').StoredMessage}. `threadId` cascades on delete.\n */\nexport const agentMessage = sqliteTable(\n 'agent_message',\n {\n id: text('id').primaryKey(),\n threadId: text('thread_id')\n .notNull()\n .references(() => agentThread.id, { onDelete: 'cascade' }),\n role: text('role').$type<MessageRole>().notNull(),\n content: text('content').notNull(),\n toolCalls: text('tool_calls', { mode: 'json' }).$type<ToolCallRequest[]>(),\n toolResults: text('tool_results', { mode: 'json' }).$type<ToolResult[]>(),\n attachments: text('attachments', { mode: 'json' }).$type<MessageAttachment[]>(),\n followUps: text('follow_ups', { mode: 'json' }).$type<string[]>(),\n usage: text('usage', { mode: 'json' }).$type<MessageUsage>(),\n agentName: text('agent_name'),\n runId: text('run_id'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n },\n (table) => [index('agent_message_thread_created_idx').on(table.threadId, table.createdAt)],\n);\n\n/**\n * A tool call requested during an assistant turn. The pk is the model-supplied `toolCallId`.\n *\n * `messageId` carries its own index rather than relying on the foreign key: MySQL indexes a foreign\n * key column for you, Postgres does not — and every message-scoped read here filters on it (the\n * thread reader's `IN (…)` over a turn's calls, and `truncateFrom`'s delete).\n */\nexport const agentToolCall = sqliteTable(\n 'agent_tool_call',\n {\n id: text('id').primaryKey(),\n messageId: text('message_id')\n .notNull()\n .references(() => agentMessage.id, { onDelete: 'cascade' }),\n toolName: text('tool_name').notNull(),\n toolType: text('tool_type').$type<ToolKind>().notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n status: text('status').$type<ToolCallStatus>().notNull(),\n executedByRef: text('executed_by_ref'),\n executionMs: integer('execution_ms'),\n error: text('error'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n executedAt: integer('executed_at', { mode: 'timestamp_ms' }),\n /** The run (turn) this call belongs to, for a trace deep-link; null for a pre-rollout row. */\n runId: text('run_id'),\n },\n (table) => [index('agent_tool_call_message_idx').on(table.messageId)],\n);\n\n/** A token-usage ledger row, summed per actor per day by `quotaToday`. */\nexport const agentTokenUsage = sqliteTable(\n 'agent_token_usage',\n {\n id: text('id').primaryKey(),\n threadId: text('thread_id')\n .notNull()\n .references(() => agentThread.id, { onDelete: 'cascade' }),\n actorRef: text('actor_ref').notNull(),\n messageId: text('message_id'),\n modelId: text('model_id').notNull(),\n purpose: text('purpose').$type<UsagePurpose>().notNull(),\n inputTokens: integer('input_tokens').notNull(),\n outputTokens: integer('output_tokens').notNull(),\n /** Subset of `inputTokens` written to the prompt cache this turn; null when not reported. */\n cacheWriteTokens: integer('cache_write_tokens'),\n /** Subset of `inputTokens` served from the prompt cache this turn; null when not reported. */\n cacheReadTokens: integer('cache_read_tokens'),\n /** Provider-reported actual USD cost for the turn; null when only tokens were reported. */\n costUsd: real('cost_usd'),\n createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),\n },\n (table) => [index('agent_token_usage_actor_created_idx').on(table.actorRef, table.createdAt)],\n);\n\n/** Per-model token pricing, versioned by `effectiveFrom`; `isCurrent` flags the live row. */\nexport const agentModelPricing = sqliteTable('agent_model_pricing', {\n id: text('id').primaryKey(),\n modelId: text('model_id').notNull(),\n inputPricePer1m: real('input_price_per_1m').notNull(),\n outputPricePer1m: real('output_price_per_1m').notNull(),\n /** Per-1M price for cache-write input tokens; null → price them at the input rate. */\n cacheWritePricePer1m: real('cache_write_price_per_1m'),\n /** Per-1M price for cache-read input tokens; null → price them at the input rate. */\n cacheReadPricePer1m: real('cache_read_price_per_1m'),\n effectiveFrom: integer('effective_from', { mode: 'timestamp_ms' }).notNull(),\n isCurrent: integer('is_current', { mode: 'boolean' }).notNull(),\n});\n\n/**\n * A run's lifecycle status. Not part of the core SPI (that surfaces `string`) — internal only.\n *\n * `cancelled` is a third TERMINAL, not a flavour of `failed`: someone asked the run to stop and it\n * did. A reliability read that folded it into `failed` would page whoever is on call for model\n * failures every time a user pressed Stop.\n */\nexport type AgentRunStatus = 'running' | 'completed' | 'failed' | 'cancelled';\n\n/**\n * One recorded run (turn) outcome — the durable half of what `aviary:agent:*` diagnostics report\n * ephemerally. Written by {@link import('./drizzle-agent-store.js').DrizzleAgentStore.recordRunStart}/\n * `recordRunEnd`/`bumpRunRetries`, read by\n * {@link import('./drizzle-governance-queries.js').DrizzleGovernanceQueries} for the reliability\n * surfaces (success rate, error breakdown, duration percentiles, trend, recent runs). `threadId`\n * cascades on delete, like `agent_message`/`agent_token_usage`.\n */\nexport const agentRun = sqliteTable(\n 'agent_run',\n {\n id: text('id').primaryKey(),\n threadId: text('thread_id')\n .notNull()\n .references(() => agentThread.id, { onDelete: 'cascade' }),\n actorRef: text('actor_ref').notNull(),\n agentName: text('agent_name'),\n status: text('status').$type<AgentRunStatus>().notNull(),\n durationMs: integer('duration_ms'),\n errorCode: text('error_code'),\n errorMessage: text('error_message'),\n retries: integer('retries').notNull().default(0),\n startedAt: integer('started_at', { mode: 'timestamp_ms' }).notNull(),\n settledAt: integer('settled_at', { mode: 'timestamp_ms' }),\n /** sha256 hex of the run's resolved (pre-RAG) system prompt; null for a pre-existing run. */\n promptHash: text('prompt_hash'),\n /**\n * The run that delegated this one; null for a turn nobody delegated. The durable runtime's\n * journal holds the same edge, but only there — this column is what lets a reader of run ROWS\n * build the delegation tree and roll a child's cost up to the turn that asked for it, including\n * for a detached child, which outlives its parent's turn and so is paired by nothing in the\n * transcript.\n */\n parentRunId: text('parent_run_id'),\n },\n (table) => [index('agent_run_started_idx').on(table.startedAt)],\n);\n\n/** The six agent tables as one schema object, ready for `drizzle(client, { schema })`. */\nexport const agentSchema = {\n agentThread,\n agentMessage,\n agentToolCall,\n agentTokenUsage,\n agentModelPricing,\n agentRun,\n};\n\n/**\n * The dialect-portable Drizzle SQLite database handle the store operates on. Accepts any SQLite\n * driver (better-sqlite3, libsql, D1, …) in either sync or async result mode; the host app owns\n * the connection and passes the `drizzle(...)` instance in.\n */\nexport type AgentDrizzleDb = BaseSQLiteDatabase<\n 'sync' | 'async',\n unknown,\n Record<string, unknown>,\n TablesRelationalConfig\n>;\n\n/** A persisted thread row as Drizzle selects it. */\nexport type AgentThreadRow = typeof agentThread.$inferSelect;\n/** A persisted message row as Drizzle selects it. */\nexport type AgentMessageRow = typeof agentMessage.$inferSelect;\n/** A persisted run row as Drizzle selects it. */\nexport type AgentRunRow = typeof agentRun.$inferSelect;\n","import { sql } from 'drizzle-orm';\nimport type { AgentDrizzleDb } from './schema.js';\n\n/**\n * Idempotent `CREATE TABLE IF NOT EXISTS` DDL for the six agent tables, mirroring\n * {@link import('./schema.js').agentSchema}. SQLite dialect (the db-test driver); kept here rather\n * than relying on drizzle-kit so the package can stand up its schema with no migration files. Safe\n * to run on boot against a shared database — it never drops or alters existing columns.\n */\nconst statements: string[] = [\n `CREATE TABLE IF NOT EXISTS agent_thread (\n id TEXT PRIMARY KEY NOT NULL,\n actor_ref TEXT NOT NULL,\n tenant_ref TEXT,\n title TEXT NOT NULL,\n transient INTEGER NOT NULL DEFAULT 0,\n active_stream_id TEXT,\n default_agent TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n deleted_at INTEGER\n )`,\n `CREATE INDEX IF NOT EXISTS agent_thread_actor_updated_idx\n ON agent_thread (actor_ref, updated_at)`,\n `CREATE TABLE IF NOT EXISTS agent_message (\n id TEXT PRIMARY KEY NOT NULL,\n thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n tool_calls TEXT,\n tool_results TEXT,\n attachments TEXT,\n follow_ups TEXT,\n usage TEXT,\n agent_name TEXT,\n run_id TEXT,\n created_at INTEGER NOT NULL\n )`,\n `CREATE INDEX IF NOT EXISTS agent_message_thread_created_idx\n ON agent_message (thread_id, created_at)`,\n `CREATE TABLE IF NOT EXISTS agent_tool_call (\n id TEXT PRIMARY KEY NOT NULL,\n message_id TEXT NOT NULL REFERENCES agent_message(id) ON DELETE CASCADE,\n tool_name TEXT NOT NULL,\n tool_type TEXT NOT NULL,\n input TEXT,\n output TEXT,\n status TEXT NOT NULL,\n executed_by_ref TEXT,\n execution_ms INTEGER,\n error TEXT,\n created_at INTEGER NOT NULL,\n executed_at INTEGER,\n run_id TEXT\n )`,\n `CREATE INDEX IF NOT EXISTS agent_tool_call_message_idx\n ON agent_tool_call (message_id)`,\n `CREATE TABLE IF NOT EXISTS agent_token_usage (\n id TEXT PRIMARY KEY NOT NULL,\n thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,\n actor_ref TEXT NOT NULL,\n message_id TEXT,\n model_id TEXT NOT NULL,\n purpose TEXT NOT NULL,\n input_tokens INTEGER NOT NULL,\n output_tokens INTEGER NOT NULL,\n cache_write_tokens INTEGER,\n cache_read_tokens INTEGER,\n cost_usd REAL,\n created_at INTEGER NOT NULL\n )`,\n `CREATE INDEX IF NOT EXISTS agent_token_usage_actor_created_idx\n ON agent_token_usage (actor_ref, created_at)`,\n `CREATE TABLE IF NOT EXISTS agent_model_pricing (\n id TEXT PRIMARY KEY NOT NULL,\n model_id TEXT NOT NULL,\n input_price_per_1m REAL NOT NULL,\n output_price_per_1m REAL NOT NULL,\n cache_write_price_per_1m REAL,\n cache_read_price_per_1m REAL,\n effective_from INTEGER NOT NULL,\n is_current INTEGER NOT NULL\n )`,\n `CREATE TABLE IF NOT EXISTS agent_run (\n id TEXT PRIMARY KEY NOT NULL,\n thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,\n actor_ref TEXT NOT NULL,\n agent_name TEXT,\n status TEXT NOT NULL,\n duration_ms INTEGER,\n error_code TEXT,\n error_message TEXT,\n retries INTEGER NOT NULL DEFAULT 0,\n started_at INTEGER NOT NULL,\n settled_at INTEGER,\n prompt_hash TEXT,\n parent_run_id TEXT\n )`,\n `CREATE INDEX IF NOT EXISTS agent_run_started_idx\n ON agent_run (started_at)`,\n];\n\n/**\n * Columns added to a table this package already shipped. `CREATE TABLE IF NOT EXISTS` above is inert\n * against a database that already has the table, so a column introduced later would land on fresh\n * databases only and be missing everywhere the store is actually running. The MikroORM adapter has\n * no such gap — its `ensureAgentSchema` applies `getUpdateSchemaSQL({ safe: true })`, which is\n * add-column-capable — so without this list the two adapters would disagree about what the schema is\n * after an upgrade.\n *\n * Add-column only, never a type change or a drop: `safe` in the same sense as the sibling adapter.\n */\nconst additiveColumns: Array<{ table: string; column: string; ddl: string }> = [\n {\n table: 'agent_message',\n column: 'run_id',\n ddl: 'ALTER TABLE agent_message ADD COLUMN run_id TEXT',\n },\n {\n table: 'agent_message',\n column: 'attachments',\n ddl: 'ALTER TABLE agent_message ADD COLUMN attachments TEXT',\n },\n {\n table: 'agent_thread',\n column: 'default_agent',\n ddl: 'ALTER TABLE agent_thread ADD COLUMN default_agent TEXT',\n },\n {\n table: 'agent_run',\n column: 'parent_run_id',\n ddl: 'ALTER TABLE agent_run ADD COLUMN parent_run_id TEXT',\n },\n];\n\n/**\n * Runs the `CREATE TABLE IF NOT EXISTS` DDL above against the supplied Drizzle SQLite db, then adds\n * any column missing from a table that already existed.\n */\nexport async function ensureAgentSchema(db: AgentDrizzleDb): Promise<void> {\n for (const statement of statements) {\n await db.run(sql.raw(statement));\n }\n for (const { table, column, ddl } of additiveColumns) {\n // Asking the table what it has, rather than running the ALTER and swallowing the failure: a\n // swallowed error cannot tell \"the column is already there\" apart from \"the ALTER is malformed\",\n // and the second one would then go unnoticed until a query hit the missing column.\n const existing = await db.all<{ name: string }>(sql.raw(`PRAGMA table_info(${table})`));\n if (!existing.some((row) => row.name === column)) {\n await db.run(sql.raw(ddl));\n }\n }\n}\n","import type {\n AgentStore,\n AppendMessageInput,\n CreateThreadInput,\n RecordRunStartInput,\n RecordToolCallInput,\n RecordUsageInput,\n StoredMessage,\n ThreadDetail,\n ThreadSummary,\n ThreadTurnPage,\n ThreadTurnQuery,\n ThreadTurnReader,\n ToolResult,\n UpdateThreadInput,\n UpdateToolCallInput,\n} from '@dudousxd/nestjs-agent-core';\nimport { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, sql } from 'drizzle-orm';\nimport {\n type AgentDrizzleDb,\n type AgentMessageRow,\n type AgentRunRow,\n type AgentThreadRow,\n agentMessage,\n agentRun,\n agentThread,\n agentTokenUsage,\n agentToolCall,\n} from './schema.js';\n\n/**\n * Re-exported from the core SPI so a consumer can name this store's window read without importing a\n * second package. ONE definition of the shape, so the adapter and the seam the loop probes for\n * cannot drift apart.\n */\nexport type { ThreadTurnPage, ThreadTurnQuery };\n\n/** The message columns a model turn reads. `usage`, `follow_ups` and `run_id` are nobody's business here. */\nconst TURN_MESSAGE_COLUMNS = {\n id: agentMessage.id,\n role: agentMessage.role,\n content: agentMessage.content,\n agentName: agentMessage.agentName,\n toolCalls: agentMessage.toolCalls,\n toolResults: agentMessage.toolResults,\n attachments: agentMessage.attachments,\n createdAt: agentMessage.createdAt,\n};\n\ntype TurnMessageRow = { [K in keyof typeof TURN_MESSAGE_COLUMNS]: AgentMessageRow[K] };\n\n/**\n * {@link AgentStore} backed by Drizzle ORM — a second adapter alongside the MikroORM one, proving\n * the store SPI is ORM-portable. A POJO receiving a Drizzle SQLite database handle (the host app\n * owns the connection). Behaviour mirrors {@link import('@dudousxd/nestjs-agent-store-mikro-orm')}\n * exactly (fork/truncate/quota/active-stream/soft-delete semantics) so the two are interchangeable.\n */\nexport class DrizzleAgentStore implements AgentStore, ThreadTurnReader {\n constructor(private readonly db: AgentDrizzleDb) {}\n\n async createThread(input: CreateThreadInput): Promise<ThreadSummary> {\n const now = new Date();\n const thread: AgentThreadRow = {\n id: crypto.randomUUID(),\n actorRef: input.actor.id,\n tenantRef: input.actor.tenantRef ?? null,\n title: input.title ?? 'New chat',\n transient: input.transient ?? false,\n activeStreamId: null,\n defaultAgent: null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n };\n await this.db.insert(agentThread).values(thread);\n return this.toSummary(thread);\n }\n\n async getThread(threadId: string): Promise<ThreadDetail | null> {\n const [thread] = await this.db\n .select()\n .from(agentThread)\n .where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));\n if (thread === undefined) {\n return null;\n }\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));\n const last = messages[messages.length - 1];\n return {\n ...this.toSummary(thread, last?.content),\n messages: messages.map((message) => this.toStoredMessage(message)),\n ...(thread.activeStreamId != null ? { activeStreamId: thread.activeStreamId } : {}),\n };\n }\n\n /**\n * The window a turn reads off a thread: its newest `messageLimit` messages (oldest first), the\n * title, the default agent, and whether the thread has EVER been answered.\n *\n * {@link getThread} is the wrong read for a turn. It materializes the transcript — every message,\n * every attachment, every tool output the thread ever recorded — and the run then journals what it\n * loaded, so a long thread pays for its whole history on every turn and again on every replay.\n *\n * `hasAssistantMessage` is answered over the WHOLE thread, not the returned page: it answers \"has\n * this conversation been answered before?\", and a thread whose window happens to hold only the\n * user's last questions has still been answered. `null` when the thread is unknown or\n * soft-deleted, same as {@link getThread}.\n */\n async loadThreadForTurn(query: ThreadTurnQuery): Promise<ThreadTurnPage | null> {\n const [thread] = await this.db\n .select({ title: agentThread.title, defaultAgent: agentThread.defaultAgent })\n .from(agentThread)\n .where(and(eq(agentThread.id, query.threadId), isNull(agentThread.deletedAt)));\n if (thread === undefined) {\n return null;\n }\n const messages = await this.loadTurnWindow(query.threadId, query.messageLimit);\n const [answered] = await this.db\n .select({ id: agentMessage.id })\n .from(agentMessage)\n .where(and(eq(agentMessage.threadId, query.threadId), eq(agentMessage.role, 'assistant')))\n .limit(1);\n return {\n title: thread.title,\n defaultAgent: thread.defaultAgent,\n hasAssistantMessage: answered !== undefined,\n messages,\n };\n }\n\n /**\n * The newest `limit` messages of a thread, oldest first, projected to the columns a model turn\n * reads. Read newest-first so the LIMIT is the database's job, then reversed for the prompt.\n */\n private async loadTurnWindow(\n threadId: string,\n limit: number | undefined,\n ): Promise<StoredMessage[]> {\n if (limit !== undefined && limit <= 0) {\n return [];\n }\n const window = this.db\n .select(TURN_MESSAGE_COLUMNS)\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(desc(agentMessage.createdAt), desc(agentMessage.id));\n const rows: TurnMessageRow[] = limit === undefined ? await window : await window.limit(limit);\n return rows.reverse().map((row) => this.toStoredMessage(row));\n }\n\n async listThreads(actorRef: string, limit = 50): Promise<ThreadSummary[]> {\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(\n and(\n eq(agentThread.actorRef, actorRef),\n eq(agentThread.transient, false),\n isNull(agentThread.deletedAt),\n ),\n )\n .orderBy(desc(agentThread.updatedAt))\n .limit(limit);\n const summaries: ThreadSummary[] = [];\n for (const thread of threads) {\n const [last] = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, thread.id))\n .orderBy(desc(agentMessage.createdAt), desc(agentMessage.id))\n .limit(1);\n summaries.push(this.toSummary(thread, last?.content));\n }\n return summaries;\n }\n\n async softDeleteThread(threadId: string): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ deletedAt: new Date() })\n .where(eq(agentThread.id, threadId));\n }\n\n async forkThread(threadId: string, fromMessageId: string): Promise<ThreadSummary> {\n const [source] = await this.db.select().from(agentThread).where(eq(agentThread.id, threadId));\n if (source === undefined) {\n throw new Error(`thread ${threadId} not found`);\n }\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));\n const cutoff = messages.findIndex((message) => message.id === fromMessageId);\n const kept = cutoff >= 0 ? messages.slice(0, cutoff + 1) : messages;\n const now = new Date();\n const fork: AgentThreadRow = {\n id: crypto.randomUUID(),\n actorRef: source.actorRef,\n tenantRef: source.tenantRef,\n title: source.title,\n transient: false,\n activeStreamId: null,\n defaultAgent: source.defaultAgent,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n };\n await this.db.insert(agentThread).values(fork);\n if (kept.length > 0) {\n await this.db.insert(agentMessage).values(\n kept.map((message) => ({\n id: crypto.randomUUID(),\n threadId: fork.id,\n role: message.role,\n content: message.content,\n toolCalls: message.toolCalls,\n toolResults: message.toolResults,\n attachments: message.attachments,\n followUps: message.followUps,\n usage: message.usage,\n agentName: message.agentName,\n // The copy is the same message, so it keeps the run that wrote it. A reader asking which\n // turn produced this text gets the truthful answer; the run's own thread is still the\n // original, so a run-scoped read never picks the fork's rows up.\n runId: message.runId,\n createdAt: message.createdAt,\n })),\n );\n }\n return this.toSummary(fork);\n }\n\n async ownerOfThread(threadId: string): Promise<string | null> {\n const [thread] = await this.db\n .select({ actorRef: agentThread.actorRef })\n .from(agentThread)\n .where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));\n return thread?.actorRef ?? null;\n }\n\n async ownerOfToolCall(toolCallId: string): Promise<string | null> {\n const [row] = await this.db\n .select({ actorRef: agentThread.actorRef })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(eq(agentToolCall.id, toolCallId));\n return row?.actorRef ?? null;\n }\n\n async runForToolCall(toolCallId: string): Promise<string | null> {\n const [row] = await this.db\n .select({ runId: agentToolCall.runId, activeStreamId: agentThread.activeStreamId })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(eq(agentToolCall.id, toolCallId));\n return row?.runId ?? row?.activeStreamId ?? null;\n }\n\n async ownerOfActiveStream(runId: string): Promise<string | null> {\n const [thread] = await this.db\n .select({ actorRef: agentThread.actorRef })\n .from(agentThread)\n .where(and(eq(agentThread.activeStreamId, runId), isNull(agentThread.deletedAt)));\n return thread?.actorRef ?? null;\n }\n\n async setTitle(threadId: string, title: string): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ title, updatedAt: new Date() })\n .where(eq(agentThread.id, threadId));\n }\n\n async promoteThread(threadId: string): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ transient: false, updatedAt: new Date() })\n .where(and(eq(agentThread.id, threadId), eq(agentThread.transient, true)));\n }\n\n async setActiveStream(threadId: string, runId: string | null): Promise<void> {\n await this.db\n .update(agentThread)\n .set({ activeStreamId: runId })\n .where(eq(agentThread.id, threadId));\n }\n\n /**\n * Patch a thread's `title` and/or `defaultAgent`. Each field is only touched when PRESENT in\n * `patch` — `defaultAgent: null` clears it (falls back to the app default), while an omitted\n * `defaultAgent` leaves whatever is stored untouched. A no-op (including `updatedAt`) when the\n * patch is empty or the thread doesn't exist.\n */\n async updateThread(threadId: string, patch: UpdateThreadInput): Promise<void> {\n const updates: Partial<typeof agentThread.$inferInsert> = {};\n if (patch.title !== undefined) {\n updates.title = patch.title;\n }\n if (patch.defaultAgent !== undefined) {\n updates.defaultAgent = patch.defaultAgent;\n }\n if (Object.keys(updates).length === 0) {\n return;\n }\n updates.updatedAt = new Date();\n await this.db.update(agentThread).set(updates).where(eq(agentThread.id, threadId));\n }\n\n /**\n * The thread's default agent, projected — the caller wants one nullable scalar to decide which\n * agent answers the next turn, and {@link getThread} would materialize the whole transcript to\n * hand it over. `null` when the thread is unknown, soft-deleted, or has no default set.\n */\n async defaultAgentForThread(threadId: string): Promise<string | null> {\n const [thread] = await this.db\n .select({ defaultAgent: agentThread.defaultAgent })\n .from(agentThread)\n .where(and(eq(agentThread.id, threadId), isNull(agentThread.deletedAt)));\n return thread?.defaultAgent ?? null;\n }\n\n /**\n * Persist the start of a run (turn). Replay-safe: called under a durable localStep.\n *\n * Takes the SPI's own {@link RecordRunStartInput} rather than a hand-copied shape: a field added\n * to the input is otherwise accepted and dropped, silently, by every adapter that re-declares it.\n */\n async recordRunStart(run: RecordRunStartInput): Promise<void> {\n const runRow: AgentRunRow = {\n id: run.runId,\n threadId: run.threadId,\n actorRef: run.actorRef,\n agentName: run.agentName ?? null,\n status: 'running',\n durationMs: null,\n errorCode: null,\n errorMessage: null,\n retries: 0,\n startedAt: new Date(),\n settledAt: null,\n promptHash: run.promptHash ?? null,\n parentRunId: run.parentRunId ?? null,\n };\n await this.db.insert(agentRun).values(runRow);\n }\n\n /** Settle a run's outcome. A no-op when the run is unknown (mirrors `setTitle`/`updateThread`). */\n async recordRunEnd(end: {\n runId: string;\n status: 'completed' | 'failed' | 'cancelled';\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n }): Promise<void> {\n const updates: Partial<typeof agentRun.$inferInsert> = {\n status: end.status,\n settledAt: new Date(),\n };\n if (end.durationMs !== undefined) {\n updates.durationMs = end.durationMs;\n }\n if (end.errorCode !== undefined) {\n updates.errorCode = end.errorCode;\n }\n if (end.errorMessage !== undefined) {\n updates.errorMessage = end.errorMessage;\n }\n await this.db.update(agentRun).set(updates).where(eq(agentRun.id, end.runId));\n }\n\n /** Bump the run's llm-step retry counter. Atomic `retries = retries + 1`, no read-modify-write. */\n async bumpRunRetries(runId: string): Promise<void> {\n await this.db\n .update(agentRun)\n .set({ retries: sql`${agentRun.retries} + 1` })\n .where(eq(agentRun.id, runId));\n }\n\n async appendMessage(input: AppendMessageInput): Promise<StoredMessage> {\n const [thread] = await this.db\n .select()\n .from(agentThread)\n .where(eq(agentThread.id, input.threadId));\n if (thread === undefined) {\n throw new Error(`thread ${input.threadId} not found`);\n }\n const now = new Date();\n const message: AgentMessageRow = {\n id: crypto.randomUUID(),\n threadId: input.threadId,\n role: input.role,\n content: input.content,\n toolCalls: input.toolCalls ?? null,\n toolResults: input.toolResults ?? null,\n attachments: input.attachments ?? null,\n followUps: input.followUps ?? null,\n usage: input.usage ?? null,\n agentName: input.agentName ?? null,\n runId: input.runId ?? null,\n createdAt: now,\n };\n await this.db.insert(agentMessage).values(message);\n await this.db\n .update(agentThread)\n .set({ updatedAt: now })\n .where(eq(agentThread.id, input.threadId));\n return this.toStoredMessage(message);\n }\n\n async setMessageToolResults(messageId: string, results: ToolResult[]): Promise<void> {\n await this.db\n .update(agentMessage)\n .set({ toolResults: results })\n .where(eq(agentMessage.id, messageId));\n }\n\n async truncateFrom(threadId: string, messageId: string): Promise<void> {\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, threadId))\n .orderBy(asc(agentMessage.createdAt), asc(agentMessage.id));\n const cutoff = messages.findIndex((message) => message.id === messageId);\n if (cutoff < 0) {\n return;\n }\n const doomedIds = messages.slice(cutoff).map((message) => message.id);\n await this.db.delete(agentToolCall).where(inArray(agentToolCall.messageId, doomedIds));\n await this.db.delete(agentMessage).where(inArray(agentMessage.id, doomedIds));\n }\n\n async recordToolCall(input: RecordToolCallInput): Promise<void> {\n await this.db.insert(agentToolCall).values({\n id: input.toolCallId,\n messageId: input.messageId,\n toolName: input.toolName,\n toolType: input.toolType,\n input: input.input,\n output: null,\n status: input.status,\n executedByRef: null,\n executionMs: null,\n error: null,\n createdAt: new Date(),\n executedAt: null,\n runId: input.runId ?? null,\n });\n }\n\n async updateToolCall(input: UpdateToolCallInput): Promise<void> {\n const updates: Partial<typeof agentToolCall.$inferInsert> = { status: input.status };\n if (input.output !== undefined) {\n updates.output = input.output;\n }\n if (input.error !== undefined) {\n updates.error = input.error;\n }\n if (input.executionMs !== undefined) {\n updates.executionMs = input.executionMs;\n }\n if (input.executedByRef !== undefined) {\n updates.executedByRef = input.executedByRef;\n }\n if (input.status === 'executed' || input.status === 'auto_executed') {\n updates.executedAt = new Date();\n }\n await this.db.update(agentToolCall).set(updates).where(eq(agentToolCall.id, input.toolCallId));\n }\n\n /**\n * Of `mediaIds`, the ones a surviving message in one of this actor's threads still carries.\n *\n * Reads the `attachments` JSON back out and matches in memory rather than pushing the match into\n * SQL: the column holds an array of objects, and every dialect this adapter's sibling targets\n * spells that query differently (`jsonb` containment, `json_table`, `json_each`), while none of\n * them can use an index for it anyway. The scan is bounded by ONE actor's attachment-bearing\n * messages, which is a small set — attachments are rare, and a message without one is excluded\n * by the `is not null` before any JSON is parsed.\n *\n * Soft-deleted threads are deliberately included: their message rows survive, so the bytes they\n * point at are still reachable from stored state and are not garbage.\n */\n async referencedMediaIds(actorRef: string, mediaIds: readonly string[]): Promise<string[]> {\n if (mediaIds.length === 0) {\n return [];\n }\n const rows = await this.db\n .select({ attachments: agentMessage.attachments })\n .from(agentMessage)\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(and(eq(agentThread.actorRef, actorRef), isNotNull(agentMessage.attachments)));\n const wanted = new Set(mediaIds);\n const found = new Set<string>();\n for (const row of rows) {\n for (const attachment of row.attachments ?? []) {\n if (wanted.has(attachment.mediaId)) {\n found.add(attachment.mediaId);\n }\n }\n }\n return [...wanted].filter((mediaId) => found.has(mediaId));\n }\n\n async recordUsage(input: RecordUsageInput): Promise<void> {\n await this.db.insert(agentTokenUsage).values({\n id: crypto.randomUUID(),\n threadId: input.threadId,\n actorRef: input.actorRef,\n messageId: input.messageId ?? null,\n modelId: input.modelId,\n purpose: input.purpose,\n inputTokens: input.usage.inputTokens,\n outputTokens: input.usage.outputTokens,\n cacheWriteTokens: input.usage.cacheWriteTokens ?? null,\n cacheReadTokens: input.usage.cacheReadTokens ?? null,\n costUsd: input.costUsd ?? null,\n createdAt: new Date(),\n });\n }\n\n async quotaToday(\n actorRef: string,\n day: string,\n ): Promise<{ usedTokens: number; costUsd: number }> {\n const start = new Date(`${day}T00:00:00.000Z`);\n const end = new Date(`${day}T23:59:59.999Z`);\n const rows = await this.db\n .select()\n .from(agentTokenUsage)\n .where(\n and(\n eq(agentTokenUsage.actorRef, actorRef),\n gte(agentTokenUsage.createdAt, start),\n lte(agentTokenUsage.createdAt, end),\n ),\n );\n const usedTokens = rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);\n const costUsd = rows.reduce((sum, row) => sum + (row.costUsd ?? 0), 0);\n return { usedTokens, costUsd };\n }\n\n private toSummary(thread: AgentThreadRow, lastContent?: string): ThreadSummary {\n return {\n id: thread.id,\n title: thread.title,\n transient: thread.transient,\n createdAt: thread.createdAt.toISOString(),\n updatedAt: thread.updatedAt.toISOString(),\n defaultAgent: thread.defaultAgent,\n ...(lastContent !== undefined ? { lastMessagePreview: lastContent.slice(0, 120) } : {}),\n };\n }\n\n private toStoredMessage(message: TurnMessageRow & Partial<AgentMessageRow>): StoredMessage {\n return {\n id: message.id,\n role: message.role,\n content: message.content,\n createdAt: message.createdAt.toISOString(),\n ...(message.toolCalls != null ? { toolCalls: message.toolCalls } : {}),\n ...(message.toolResults != null ? { toolResults: message.toolResults } : {}),\n ...(message.attachments != null ? { attachments: message.attachments } : {}),\n ...(message.followUps != null ? { followUps: message.followUps } : {}),\n ...(message.usage != null ? { usage: message.usage } : {}),\n ...(message.agentName != null ? { agentName: message.agentName } : {}),\n ...(message.runId != null ? { runId: message.runId } : {}),\n };\n }\n}\n","import type {\n ActorSpendRow,\n AgentGovernanceQueries,\n AgentPricingStore,\n ApprovalWhere,\n GovernancePage,\n GovernancePageQuery,\n GovernanceRange,\n GovernanceRunDetail,\n GovernanceThreadDetail,\n GovernanceThreadDetailQuery,\n GovernanceUsageInput,\n ModelPrice,\n ModelSpendRow,\n PendingApprovalRow,\n RecentRunRow,\n RunAgentBreakdownRow,\n RunErrorBreakdownRow,\n RunMetrics,\n RunToolCallRow,\n RunTrendPoint,\n RunWhere,\n ThreadActivityRow,\n ThreadMessageRow,\n ThreadMeta,\n ThreadSpendRow,\n ThreadWhere,\n ToolCallActivityRow,\n ToolCallStatus,\n ToolCallWhere,\n ToolKind,\n ToolStatRow,\n UsageTrendPoint,\n} from '@dudousxd/nestjs-agent-core';\nimport {\n bucketByActor,\n bucketByModel,\n bucketByThread,\n bucketUsageTrend,\n dayBoundsUtc,\n rollupThreadUsage,\n truncateDetailContent,\n} from '@dudousxd/nestjs-agent-core';\nimport { and, asc, count, desc, eq, gte, inArray, isNull, like, lte, sql, sum } from 'drizzle-orm';\nimport {\n type AgentDrizzleDb,\n type AgentRunStatus,\n agentMessage,\n agentRun,\n agentThread,\n agentTokenUsage,\n agentToolCall,\n} from './schema.js';\n\n/** No error code recorded on a failed run (the caller didn't classify it). Groups those together. */\nconst UNCLASSIFIED_ERROR_CODE = 'unknown';\n/** Bucket key for a run with no `agentName` (mirrors {@link RunAgentBreakdownRow}'s contract). */\nconst DEFAULT_AGENT_BUCKET = '(default)';\n\n// The paged where-builders below narrow a wire-typed `string` filter value down to the schema\n// column's literal-union `$type<...>()` before it's used in an `eq()` comparison (an unnarrowed\n// `string` isn't assignable to e.g. `agentToolCall.status`'s type). An unrecognized value can never\n// match a row anyway (the column only ever holds these literals), so the paged method short-circuits\n// to an empty page instead of querying with a value that would trivially return nothing.\nconst TOOL_CALL_STATUSES: readonly string[] = [\n 'auto_executed',\n 'pending_approval',\n 'executed',\n 'rejected',\n 'failed',\n];\nfunction isToolCallStatus(value: string): value is ToolCallStatus {\n return TOOL_CALL_STATUSES.includes(value);\n}\n\nconst TOOL_KINDS: readonly string[] = ['read', 'action', 'agent'];\nfunction isToolKind(value: string): value is ToolKind {\n return TOOL_KINDS.includes(value);\n}\n\nconst RUN_STATUSES: readonly string[] = ['running', 'completed', 'failed', 'cancelled'];\nfunction isRunStatus(value: string): value is AgentRunStatus {\n return RUN_STATUSES.includes(value);\n}\n\n/** Inclusive UTC day start, reusing {@link dayBoundsUtc}'s date math so both bounds parse identically. */\nfunction dayStartUtc(day: string): Date {\n return dayBoundsUtc({ fromDay: day, toDay: day }).start;\n}\n\n/** Inclusive UTC day end, reusing {@link dayBoundsUtc}'s date math so both bounds parse identically. */\nfunction dayEndUtc(day: string): Date {\n return dayBoundsUtc({ fromDay: day, toDay: day }).end;\n}\n\n/** An empty page for the given query's page/pageSize — the shape every paged read falls back to. */\nfunction emptyPage<TRow>(query: GovernancePageQuery<unknown>): GovernancePage<TRow> {\n return { rows: [], total: 0, page: query.page, pageSize: query.pageSize };\n}\n\n/** Map a run row onto the SPI row. Shared by `recentRuns`/`runsPage`/`runDetail`/`threadDetail`. */\nfunction toRecentRunRow(run: typeof agentRun.$inferSelect): RecentRunRow {\n return {\n runId: run.id,\n threadId: run.threadId,\n actorRef: run.actorRef,\n agentName: run.agentName ?? null,\n status: run.status,\n durationMs: run.durationMs ?? null,\n errorCode: run.errorCode ?? null,\n errorMessage: run.errorMessage ?? null,\n retries: run.retries,\n startedAt: run.startedAt.toISOString(),\n promptHash: run.promptHash ?? null,\n parentRunId: run.parentRunId ?? null,\n };\n}\n\n/** Map a tool-call row onto the run drill-down's row (execution outcome, not activity-feed shape). */\nfunction toRunToolCallRow(toolCall: typeof agentToolCall.$inferSelect): RunToolCallRow {\n return {\n toolCallId: toolCall.id,\n toolName: toolCall.toolName,\n toolType: toolCall.toolType,\n status: toolCall.status,\n executionMs: toolCall.executionMs ?? null,\n executedByRef: toolCall.executedByRef ?? null,\n error: toolCall.error ?? null,\n createdAt: toolCall.createdAt.toISOString(),\n };\n}\n\n/** Map a Drizzle usage row onto the shared bucketer input (day derived from `createdAt`). */\nfunction toUsageInput(row: typeof agentTokenUsage.$inferSelect): GovernanceUsageInput {\n return {\n modelId: row.modelId,\n actorRef: row.actorRef,\n threadId: row.threadId,\n day: row.createdAt.toISOString().slice(0, 10),\n inputTokens: row.inputTokens,\n outputTokens: row.outputTokens,\n cacheWriteTokens: row.cacheWriteTokens,\n cacheReadTokens: row.cacheReadTokens,\n costUsd: row.costUsd,\n };\n}\n\n/**\n * MySQL-compatible percentile (no `PERCENTILE_CONT`): index into an ascending-sorted array by\n * offset. `null` when there are no settled durations in range. Shared by every reliability query\n * that reports p50/p95 so the SQL and in-memory adapters compute identically.\n */\nfunction percentileMs(sortedDurationsMs: number[], p: number): number | null {\n if (sortedDurationsMs.length === 0) {\n return null;\n }\n const offset = Math.min(sortedDurationsMs.length - 1, Math.floor(p * sortedDurationsMs.length));\n return sortedDurationsMs[offset] ?? null;\n}\n\n/**\n * {@link AgentGovernanceQueries} backed by Drizzle ORM — the read/analytics half of the store SPI,\n * mirroring {@link import('@dudousxd/nestjs-agent-store-mikro-orm')} exactly. Cost is the token\n * ledger priced against the current prices from the injected {@link AgentPricingStore}\n * (`AGENT_PRICING_STORE`), so a host that binds its own pricing store controls the cost every\n * governance surface reports. An unpriced model contributes 0 cost. Aggregation is in-process (like\n * `quotaToday`) so day-bucketing stays dialect-portable.\n */\nexport class DrizzleGovernanceQueries implements AgentGovernanceQueries {\n constructor(\n private readonly db: AgentDrizzleDb,\n private readonly pricingStore: AgentPricingStore,\n ) {}\n\n private async loadPricing(): Promise<Map<string, ModelPrice>> {\n const prices = await this.pricingStore.listCurrentPrices();\n const pricing = new Map<string, ModelPrice>();\n for (const price of prices) {\n pricing.set(price.modelId, {\n inputPricePer1m: price.inputPricePer1m,\n outputPricePer1m: price.outputPricePer1m,\n cacheWritePricePer1m: price.cacheWritePricePer1m ?? null,\n cacheReadPricePer1m: price.cacheReadPricePer1m ?? null,\n });\n }\n return pricing;\n }\n\n private async usageInRange(range: GovernanceRange): Promise<GovernanceUsageInput[]> {\n const { start, end } = dayBoundsUtc(range);\n const rows = await this.db\n .select()\n .from(agentTokenUsage)\n .where(and(gte(agentTokenUsage.createdAt, start), lte(agentTokenUsage.createdAt, end)));\n return rows.map(toUsageInput);\n }\n\n async spendByModel(range: GovernanceRange): Promise<ModelSpendRow[]> {\n const pricing = await this.loadPricing();\n return bucketByModel(await this.usageInRange(range), pricing);\n }\n\n async spendByActor(range: GovernanceRange): Promise<ActorSpendRow[]> {\n const pricing = await this.loadPricing();\n return bucketByActor(await this.usageInRange(range), pricing);\n }\n\n /**\n * Top threads by spend within the range, highest cost first, capped at `limit`. Usage rows for a\n * soft-deleted thread (`deletedAt` set) are excluded — the thread no longer surfaces as a\n * governance target even though its ledger rows survive.\n */\n async spendByThread(range: GovernanceRange, limit: number): Promise<ThreadSpendRow[]> {\n const pricing = await this.loadPricing();\n const rows = await this.usageInRange(range);\n const threadIds = [...new Set(rows.map((row) => row.threadId))];\n if (threadIds.length === 0) {\n return [];\n }\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(and(inArray(agentThread.id, threadIds), isNull(agentThread.deletedAt)));\n const threadsById = new Map<string, ThreadMeta>(\n threads.map((thread) => [thread.id, { title: thread.title, actorRef: thread.actorRef }]),\n );\n return bucketByThread(rows, pricing, threadsById, { limit, includeUnknownThreads: false });\n }\n\n async usageTrend(range: GovernanceRange): Promise<UsageTrendPoint[]> {\n const pricing = await this.loadPricing();\n return bucketUsageTrend(await this.usageInRange(range), pricing);\n }\n\n async recentToolCalls(limit: number): Promise<ToolCallActivityRow[]> {\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n toolType: agentToolCall.toolType,\n status: agentToolCall.status,\n threadId: agentMessage.threadId,\n createdAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .orderBy(desc(agentToolCall.createdAt), desc(agentToolCall.id))\n .limit(limit);\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n toolType: row.toolType,\n status: row.status,\n threadId: row.threadId,\n createdAt: row.createdAt.toISOString(),\n runId: row.runId,\n }));\n }\n\n /**\n * Message counts and token totals for a whole set of threads in TWO grouped queries, not two per\n * thread — a 200-row page used to cost four hundred round trips. Mirrors the MikroORM adapter's\n * `threadRollups`, which reaches the same numbers without a QueryBuilder.\n */\n private async threadRollups(\n threadIds: string[],\n ): Promise<Map<string, { messageCount: number; totalTokens: number }>> {\n const rollups = new Map<string, { messageCount: number; totalTokens: number }>(\n threadIds.map((threadId) => [threadId, { messageCount: 0, totalTokens: 0 }]),\n );\n if (threadIds.length === 0) {\n return rollups;\n }\n const messageCounts = await this.db\n .select({ threadId: agentMessage.threadId, value: count() })\n .from(agentMessage)\n .where(inArray(agentMessage.threadId, threadIds))\n .groupBy(agentMessage.threadId);\n for (const row of messageCounts) {\n const bucket = rollups.get(row.threadId);\n if (bucket !== undefined) {\n bucket.messageCount = row.value;\n }\n }\n const usageTotals = await this.db\n .select({\n threadId: agentTokenUsage.threadId,\n inputTokens: sum(agentTokenUsage.inputTokens),\n outputTokens: sum(agentTokenUsage.outputTokens),\n })\n .from(agentTokenUsage)\n .where(inArray(agentTokenUsage.threadId, threadIds))\n .groupBy(agentTokenUsage.threadId);\n for (const row of usageTotals) {\n const bucket = rollups.get(row.threadId);\n if (bucket !== undefined) {\n // Drizzle types SUM() as string|null (a dialect can widen it past a JS number).\n bucket.totalTokens = Number(row.inputTokens ?? 0) + Number(row.outputTokens ?? 0);\n }\n }\n return rollups;\n }\n\n /** Decorate an ordered thread list with its batched rollups, preserving the incoming order. */\n private async toThreadActivityRows(\n threads: (typeof agentThread.$inferSelect)[],\n ): Promise<ThreadActivityRow[]> {\n const rollups = await this.threadRollups(threads.map((thread) => thread.id));\n return threads.map((thread) => {\n const rollup = rollups.get(thread.id);\n return {\n threadId: thread.id,\n title: thread.title,\n actorRef: thread.actorRef,\n messageCount: rollup?.messageCount ?? 0,\n totalTokens: rollup?.totalTokens ?? 0,\n lastActivityAt: thread.updatedAt.toISOString(),\n };\n });\n }\n\n async recentThreads(limit: number): Promise<ThreadActivityRow[]> {\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(isNull(agentThread.deletedAt))\n .orderBy(desc(agentThread.updatedAt), desc(agentThread.id))\n .limit(limit);\n return this.toThreadActivityRows(threads);\n }\n\n private async runsInRange(range: GovernanceRange): Promise<(typeof agentRun.$inferSelect)[]> {\n const { start, end } = dayBoundsUtc(range);\n return this.db\n .select()\n .from(agentRun)\n .where(and(gte(agentRun.startedAt, start), lte(agentRun.startedAt, end)));\n }\n\n async runMetrics(range: GovernanceRange): Promise<RunMetrics> {\n const runs = await this.runsInRange(range);\n let completed = 0;\n let failed = 0;\n let retries = 0;\n const settledDurationsMs: number[] = [];\n for (const run of runs) {\n if (run.status === 'completed') {\n completed += 1;\n } else if (run.status === 'failed') {\n failed += 1;\n }\n retries += run.retries;\n if ((run.status === 'completed' || run.status === 'failed') && run.durationMs != null) {\n settledDurationsMs.push(run.durationMs);\n }\n }\n settledDurationsMs.sort((left, right) => left - right);\n return {\n runs: runs.length,\n completed,\n failed,\n successRate: runs.length === 0 ? 0 : completed / runs.length,\n retries,\n durationP50Ms: percentileMs(settledDurationsMs, 0.5),\n durationP95Ms: percentileMs(settledDurationsMs, 0.95),\n };\n }\n\n async runsByAgent(range: GovernanceRange): Promise<RunAgentBreakdownRow[]> {\n const runs = await this.runsInRange(range);\n const byAgent = new Map<string, { runs: number; failed: number; retries: number }>();\n for (const run of runs) {\n const agentName = run.agentName ?? DEFAULT_AGENT_BUCKET;\n const bucket = byAgent.get(agentName) ?? { runs: 0, failed: 0, retries: 0 };\n bucket.runs += 1;\n bucket.failed += run.status === 'failed' ? 1 : 0;\n bucket.retries += run.retries;\n byAgent.set(agentName, bucket);\n }\n const result: RunAgentBreakdownRow[] = [];\n for (const [agentName, bucket] of byAgent) {\n result.push({ agentName, ...bucket });\n }\n result.sort(\n (left, right) => right.runs - left.runs || left.agentName.localeCompare(right.agentName),\n );\n return result;\n }\n\n async runErrors(range: GovernanceRange): Promise<RunErrorBreakdownRow[]> {\n const { start, end } = dayBoundsUtc(range);\n const runs = await this.db\n .select()\n .from(agentRun)\n .where(\n and(\n gte(agentRun.startedAt, start),\n lte(agentRun.startedAt, end),\n eq(agentRun.status, 'failed'),\n ),\n );\n const byError = new Map<string, number>();\n for (const run of runs) {\n const errorCode = run.errorCode ?? UNCLASSIFIED_ERROR_CODE;\n byError.set(errorCode, (byError.get(errorCode) ?? 0) + 1);\n }\n const result: RunErrorBreakdownRow[] = [];\n for (const [errorCode, errorCount] of byError) {\n result.push({ errorCode, count: errorCount });\n }\n result.sort(\n (left, right) => right.count - left.count || left.errorCode.localeCompare(right.errorCode),\n );\n return result;\n }\n\n async runTrend(range: GovernanceRange): Promise<RunTrendPoint[]> {\n const runs = await this.runsInRange(range);\n const byDay = new Map<string, { runs: number; failed: number }>();\n for (const run of runs) {\n const day = run.startedAt.toISOString().slice(0, 10);\n const bucket = byDay.get(day) ?? { runs: 0, failed: 0 };\n bucket.runs += 1;\n bucket.failed += run.status === 'failed' ? 1 : 0;\n byDay.set(day, bucket);\n }\n const result: RunTrendPoint[] = [];\n for (const [day, bucket] of byDay) {\n result.push({ day, ...bucket });\n }\n result.sort((left, right) => left.day.localeCompare(right.day));\n return result;\n }\n\n async recentRuns(limit: number): Promise<RecentRunRow[]> {\n const runs = await this.db\n .select()\n .from(agentRun)\n .orderBy(desc(agentRun.startedAt), desc(agentRun.id))\n .limit(limit);\n return runs.map(toRecentRunRow);\n }\n\n /**\n * Tool calls sitting `pending_approval`, oldest first (an inbox drains from the back), joined\n * through their message to the owning thread for title/actorRef and to the message itself for\n * `agentName` (null when the message carries none).\n */\n async pendingApprovals(limit: number): Promise<PendingApprovalRow[]> {\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n input: agentToolCall.input,\n threadId: agentThread.id,\n threadTitle: agentThread.title,\n actorRef: agentThread.actorRef,\n agentName: agentMessage.agentName,\n requestedAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(eq(agentToolCall.status, 'pending_approval'))\n .orderBy(agentToolCall.createdAt, agentToolCall.id)\n .limit(limit);\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n input: row.input,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? null,\n requestedAt: row.requestedAt.toISOString(),\n runId: row.runId,\n }));\n }\n\n /**\n * Per-tool call/failure/rejection/latency rollup over the range, highest call count first.\n * `p50ExecutionMs`/`p95ExecutionMs` are computed over calls that recorded a non-null `executionMs`\n * (regardless of their final status); both `null` when none did. Percentiles are taken in-process\n * off the sorted sample rather than in SQL, matching the MikroORM adapter — MySQL has no\n * `PERCENTILE_CONT` and one portable implementation beats three dialect-specific ones.\n */\n async toolStats(range: GovernanceRange): Promise<ToolStatRow[]> {\n const { start, end } = dayBoundsUtc(range);\n const calls = await this.db\n .select()\n .from(agentToolCall)\n .where(and(gte(agentToolCall.createdAt, start), lte(agentToolCall.createdAt, end)));\n const byTool = new Map<\n string,\n {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n executionMs: number[];\n }\n >();\n for (const call of calls) {\n const key = `${call.toolName} ${call.toolType}`;\n const bucket = byTool.get(key) ?? {\n toolName: call.toolName,\n toolType: call.toolType,\n calls: 0,\n failed: 0,\n rejected: 0,\n executionMs: [],\n };\n bucket.calls += 1;\n bucket.failed += call.status === 'failed' ? 1 : 0;\n bucket.rejected += call.status === 'rejected' ? 1 : 0;\n if (call.executionMs != null) {\n bucket.executionMs.push(call.executionMs);\n }\n byTool.set(key, bucket);\n }\n const result: ToolStatRow[] = [];\n for (const bucket of byTool.values()) {\n bucket.executionMs.sort((left, right) => left - right);\n result.push({\n toolName: bucket.toolName,\n toolType: bucket.toolType,\n calls: bucket.calls,\n failed: bucket.failed,\n rejected: bucket.rejected,\n p50ExecutionMs: percentileMs(bucket.executionMs, 0.5),\n p95ExecutionMs: percentileMs(bucket.executionMs, 0.95),\n });\n }\n result.sort(\n (left, right) => right.calls - left.calls || left.toolName.localeCompare(right.toolName),\n );\n return result;\n }\n\n /**\n * Paged, filterable tool-call activity, newest-first (same ordering as {@link recentToolCalls}).\n * `toolType`/`status` values outside the known literals can never match a row — short-circuits to\n * an empty page rather than issuing a query. Joins `agent_message` unconditionally (like\n * `recentToolCalls`) to resolve `threadId` and to support the `threadId` filter.\n */\n async toolCallsPage(\n query: GovernancePageQuery<ToolCallWhere>,\n ): Promise<GovernancePage<ToolCallActivityRow>> {\n const filters = query.where;\n if (filters?.status !== undefined && !isToolCallStatus(filters.status)) {\n return emptyPage(query);\n }\n if (filters?.toolType !== undefined && !isToolKind(filters.toolType)) {\n return emptyPage(query);\n }\n const whereClause = and(\n filters?.toolName !== undefined ? eq(agentToolCall.toolName, filters.toolName) : undefined,\n filters?.toolType !== undefined && isToolKind(filters.toolType)\n ? eq(agentToolCall.toolType, filters.toolType)\n : undefined,\n filters?.status !== undefined && isToolCallStatus(filters.status)\n ? eq(agentToolCall.status, filters.status)\n : undefined,\n filters?.threadId !== undefined ? eq(agentMessage.threadId, filters.threadId) : undefined,\n filters?.fromDay !== undefined\n ? gte(agentToolCall.createdAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined\n ? lte(agentToolCall.createdAt, dayEndUtc(filters.toDay))\n : undefined,\n );\n const [totalRow] = await this.db\n .select({ value: count() })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .where(whereClause);\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n toolType: agentToolCall.toolType,\n status: agentToolCall.status,\n threadId: agentMessage.threadId,\n createdAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .where(whereClause)\n .orderBy(desc(agentToolCall.createdAt), desc(agentToolCall.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n return {\n rows: rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n toolType: row.toolType,\n status: row.status,\n threadId: row.threadId,\n createdAt: row.createdAt.toISOString(),\n runId: row.runId,\n })),\n total: totalRow?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n /**\n * Paged, filterable thread activity, newest-first (same ordering as {@link recentThreads}).\n * `title` is a case-insensitive substring match via `lower(...)` on both sides (portable across\n * dialects, regardless of the underlying column collation). Soft-deleted threads are excluded,\n * mirroring `recentThreads`.\n */\n async threadsPage(\n query: GovernancePageQuery<ThreadWhere>,\n ): Promise<GovernancePage<ThreadActivityRow>> {\n const filters = query.where;\n const whereClause = and(\n isNull(agentThread.deletedAt),\n filters?.actorRef !== undefined ? eq(agentThread.actorRef, filters.actorRef) : undefined,\n filters?.title !== undefined\n ? like(sql`lower(${agentThread.title})`, `%${filters.title.toLowerCase()}%`)\n : undefined,\n filters?.fromDay !== undefined\n ? gte(agentThread.updatedAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined\n ? lte(agentThread.updatedAt, dayEndUtc(filters.toDay))\n : undefined,\n );\n const [totalRow] = await this.db\n .select({ value: count() })\n .from(agentThread)\n .where(whereClause);\n const threads = await this.db\n .select()\n .from(agentThread)\n .where(whereClause)\n .orderBy(desc(agentThread.updatedAt), desc(agentThread.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n const rows = await this.toThreadActivityRows(threads);\n return { rows, total: totalRow?.value ?? 0, page: query.page, pageSize: query.pageSize };\n }\n\n /**\n * Paged, filterable run activity, newest-first (same ordering as {@link recentRuns}). `status`\n * values outside the known literals can never match a row — short-circuits to an empty page.\n */\n async runsPage(query: GovernancePageQuery<RunWhere>): Promise<GovernancePage<RecentRunRow>> {\n const filters = query.where;\n if (filters?.status !== undefined && !isRunStatus(filters.status)) {\n return emptyPage(query);\n }\n const whereClause = and(\n filters?.agentName !== undefined ? eq(agentRun.agentName, filters.agentName) : undefined,\n filters?.status !== undefined && isRunStatus(filters.status)\n ? eq(agentRun.status, filters.status)\n : undefined,\n filters?.errorCode !== undefined ? eq(agentRun.errorCode, filters.errorCode) : undefined,\n filters?.threadId !== undefined ? eq(agentRun.threadId, filters.threadId) : undefined,\n filters?.fromDay !== undefined\n ? gte(agentRun.startedAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined ? lte(agentRun.startedAt, dayEndUtc(filters.toDay)) : undefined,\n );\n const [totalRow] = await this.db.select({ value: count() }).from(agentRun).where(whereClause);\n const runs = await this.db\n .select()\n .from(agentRun)\n .where(whereClause)\n .orderBy(desc(agentRun.startedAt), desc(agentRun.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n return {\n rows: runs.map(toRecentRunRow),\n total: totalRow?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n /**\n * Paged, filterable approvals inbox, oldest first — the same ordering as {@link pendingApprovals},\n * now with the `total` that method structurally cannot report. The join to `agent_message` /\n * `agent_thread` is unconditional (it already resolves title/actor/agentName), so the `threadId`/\n * `actorRef`/`agentName` filters cost nothing extra.\n *\n * The order is TOTAL (`created_at asc, id asc`, and `id` is the primary key), so no row can land on\n * two pages or on none for a given snapshot. Ascending order also means a newly requested approval\n * appends past the last page instead of shifting the page an operator is currently reading.\n */\n async approvalsPage(\n query: GovernancePageQuery<ApprovalWhere>,\n ): Promise<GovernancePage<PendingApprovalRow>> {\n const filters = query.where;\n const whereClause = and(\n eq(agentToolCall.status, 'pending_approval'),\n filters?.toolName !== undefined ? eq(agentToolCall.toolName, filters.toolName) : undefined,\n filters?.threadId !== undefined ? eq(agentThread.id, filters.threadId) : undefined,\n filters?.actorRef !== undefined ? eq(agentThread.actorRef, filters.actorRef) : undefined,\n filters?.agentName !== undefined ? eq(agentMessage.agentName, filters.agentName) : undefined,\n filters?.fromDay !== undefined\n ? gte(agentToolCall.createdAt, dayStartUtc(filters.fromDay))\n : undefined,\n filters?.toDay !== undefined\n ? lte(agentToolCall.createdAt, dayEndUtc(filters.toDay))\n : undefined,\n );\n const [totalRow] = await this.db\n .select({ value: count() })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(whereClause);\n const rows = await this.db\n .select({\n toolCallId: agentToolCall.id,\n toolName: agentToolCall.toolName,\n input: agentToolCall.input,\n threadId: agentThread.id,\n threadTitle: agentThread.title,\n actorRef: agentThread.actorRef,\n agentName: agentMessage.agentName,\n requestedAt: agentToolCall.createdAt,\n runId: agentToolCall.runId,\n })\n .from(agentToolCall)\n .innerJoin(agentMessage, eq(agentToolCall.messageId, agentMessage.id))\n .innerJoin(agentThread, eq(agentMessage.threadId, agentThread.id))\n .where(whereClause)\n .orderBy(asc(agentToolCall.createdAt), asc(agentToolCall.id))\n .limit(query.pageSize)\n .offset((query.page - 1) * query.pageSize);\n return {\n rows: rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n input: row.input,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? null,\n requestedAt: row.requestedAt.toISOString(),\n runId: row.runId,\n })),\n total: totalRow?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n /**\n * One run, its owning thread's headline and its tool calls — TWO queries regardless of how many\n * tools the run called. `toolCalls` comes off `agent_tool_call.run_id`, so a run recorded before\n * that column was written reports none.\n */\n async runDetail(runId: string): Promise<GovernanceRunDetail | null> {\n const [row] = await this.db\n .select({ run: agentRun, thread: agentThread })\n .from(agentRun)\n .innerJoin(agentThread, eq(agentRun.threadId, agentThread.id))\n .where(eq(agentRun.id, runId))\n .limit(1);\n if (row === undefined) {\n return null;\n }\n const toolCalls = await this.db\n .select()\n .from(agentToolCall)\n .where(eq(agentToolCall.runId, runId))\n .orderBy(asc(agentToolCall.createdAt), asc(agentToolCall.id));\n return {\n run: toRecentRunRow(row.run),\n thread: {\n threadId: row.thread.id,\n title: row.thread.title,\n actorRef: row.thread.actorRef,\n deleted: row.thread.deletedAt != null,\n },\n toolCalls: toolCalls.map(toRunToolCallRow),\n };\n }\n\n /**\n * One thread with its lifetime usage rollup, its newest runs and its newest messages. A fixed six\n * queries (thread, usage, message count, message page, that page's tool-call counts, runs+count) —\n * the per-message tool-call counts are ONE grouped read over the returned message ids, not one per\n * message. Soft-deleted threads are returned with `deleted: true`; an audit still needs them.\n */\n async threadDetail(query: GovernanceThreadDetailQuery): Promise<GovernanceThreadDetail | null> {\n const [thread] = await this.db\n .select()\n .from(agentThread)\n .where(eq(agentThread.id, query.threadId))\n .limit(1);\n if (thread === undefined) {\n return null;\n }\n const pricing = await this.loadPricing();\n const usageRows = await this.db\n .select()\n .from(agentTokenUsage)\n .where(eq(agentTokenUsage.threadId, thread.id));\n const usage = rollupThreadUsage(usageRows.map(toUsageInput), pricing);\n const [messageCountRow] = await this.db\n .select({ value: count() })\n .from(agentMessage)\n .where(eq(agentMessage.threadId, thread.id));\n const messages = await this.db\n .select()\n .from(agentMessage)\n .where(eq(agentMessage.threadId, thread.id))\n .orderBy(desc(agentMessage.createdAt), desc(agentMessage.id))\n .limit(query.messageLimit);\n const toolCallCounts = await this.toolCallCountsByMessage(\n messages.map((message) => message.id),\n );\n const [runTotalRow] = await this.db\n .select({ value: count() })\n .from(agentRun)\n .where(eq(agentRun.threadId, thread.id));\n const runs = await this.db\n .select()\n .from(agentRun)\n .where(eq(agentRun.threadId, thread.id))\n .orderBy(desc(agentRun.startedAt), desc(agentRun.id))\n .limit(query.runLimit);\n return {\n thread: {\n threadId: thread.id,\n title: thread.title,\n actorRef: thread.actorRef,\n messageCount: messageCountRow?.value ?? 0,\n totalTokens: usage.totalTokens,\n lastActivityAt: thread.updatedAt.toISOString(),\n },\n deleted: thread.deletedAt != null,\n usage,\n runs: runs.map(toRecentRunRow),\n runTotal: runTotalRow?.value ?? 0,\n messages: messages.map((message): ThreadMessageRow => {\n const { content, truncated } = truncateDetailContent(message.content);\n return {\n messageId: message.id,\n role: message.role,\n content,\n truncated,\n agentName: message.agentName ?? null,\n toolCallCount: toolCallCounts.get(message.id) ?? 0,\n createdAt: message.createdAt.toISOString(),\n };\n }),\n };\n }\n\n /** Tool-call counts for a set of messages in ONE grouped query — the detail view's no-N+1 guarantee. */\n private async toolCallCountsByMessage(messageIds: string[]): Promise<Map<string, number>> {\n const counts = new Map<string, number>();\n if (messageIds.length === 0) {\n return counts;\n }\n const rows = await this.db\n .select({ messageId: agentToolCall.messageId, value: count() })\n .from(agentToolCall)\n .where(inArray(agentToolCall.messageId, messageIds))\n .groupBy(agentToolCall.messageId);\n for (const row of rows) {\n counts.set(row.messageId, row.value);\n }\n return counts;\n }\n}\n","import type {\n AgentPricingStore,\n CurrentModelPrice,\n ModelPriceInput,\n} from '@dudousxd/nestjs-agent-core';\nimport { and, eq } from 'drizzle-orm';\nimport { type AgentDrizzleDb, agentModelPricing } from './schema.js';\n\n/**\n * {@link AgentPricingStore} backed by Drizzle ORM — the write side of the pricing table\n * {@link import('./drizzle-governance-queries.js').DrizzleGovernanceQueries} joins against. A POJO\n * receiving a Drizzle SQLite database handle (the host app owns the connection), mirroring\n * {@link import('@dudousxd/nestjs-agent-store-mikro-orm')} exactly (atomic supersede semantics).\n */\nexport class DrizzlePricingStore implements AgentPricingStore {\n constructor(private readonly db: AgentDrizzleDb) {}\n\n async upsertModelPrice(input: ModelPriceInput): Promise<void> {\n await this.db\n .update(agentModelPricing)\n .set({ isCurrent: false })\n .where(\n and(eq(agentModelPricing.modelId, input.modelId), eq(agentModelPricing.isCurrent, true)),\n );\n await this.db.insert(agentModelPricing).values({\n id: crypto.randomUUID(),\n modelId: input.modelId,\n inputPricePer1m: input.inputPricePer1m,\n outputPricePer1m: input.outputPricePer1m,\n cacheWritePricePer1m: input.cacheWritePricePer1m ?? null,\n cacheReadPricePer1m: input.cacheReadPricePer1m ?? null,\n effectiveFrom: new Date(),\n isCurrent: true,\n });\n }\n\n async listCurrentPrices(): Promise<CurrentModelPrice[]> {\n const rows = await this.db\n .select()\n .from(agentModelPricing)\n .where(eq(agentModelPricing.isCurrent, true));\n return rows.map((row) => ({\n modelId: row.modelId,\n inputPricePer1m: row.inputPricePer1m,\n outputPricePer1m: row.outputPricePer1m,\n effectiveFrom: row.effectiveFrom.toISOString(),\n ...(row.cacheWritePricePer1m != null\n ? { cacheWritePricePer1m: row.cacheWritePricePer1m }\n : {}),\n ...(row.cacheReadPricePer1m != null ? { cacheReadPricePer1m: row.cacheReadPricePer1m } : {}),\n }));\n }\n}\n","import {\n AGENT_GOVERNANCE_QUERIES,\n AGENT_PRICING_STORE,\n AGENT_STORE,\n type AgentPricingStore,\n} from '@dudousxd/nestjs-agent-core';\nimport { type DynamicModule, Module, type Type } from '@nestjs/common';\nimport { DrizzleAgentStore } from './drizzle-agent-store.js';\nimport { DrizzleGovernanceQueries } from './drizzle-governance-queries.js';\nimport { DrizzlePricingStore } from './drizzle-pricing-store.js';\nimport type { AgentDrizzleDb } from './schema.js';\n\n/** Options for {@link DrizzleAgentStoreModule.forRoot}. The app owns and supplies the db handle. */\nexport interface DrizzleAgentStoreModuleOptions {\n /** A Drizzle SQLite database instance (`drizzle(client, { schema: agentSchema })`). */\n db: AgentDrizzleDb;\n /**\n * Bind {@link AGENT_PRICING_STORE} (which {@link DrizzleGovernanceQueries} prices usage against) to\n * a host-supplied store instead of the default {@link DrizzlePricingStore} — make your OWN pricing\n * table the single source of cost truth without touching `agent_model_pricing`.\n */\n pricingStore?: Type<AgentPricingStore>;\n}\n\n/**\n * Binds {@link DrizzleAgentStore} to the {@link AGENT_STORE} token consumed by\n * `@dudousxd/nestjs-agent`, plus {@link DrizzleGovernanceQueries} to\n * {@link AGENT_GOVERNANCE_QUERIES} (the read-model the dashboard/telescope surfaces consume) and\n * {@link DrizzlePricingStore} to {@link AGENT_PRICING_STORE} (the write side of that pricing table).\n * The host app supplies an already-opened Drizzle db — this module never opens a connection itself.\n *\n * The returned module is global, so {@link AGENT_STORE}, {@link AGENT_GOVERNANCE_QUERIES} and\n * {@link AGENT_PRICING_STORE} are visible app-wide — `AgentModule` resolves the store without an\n * explicit `store` option, and the dashboard/telescope resolve {@link AGENT_GOVERNANCE_QUERIES}\n * without the host re-binding it.\n *\n * ```ts\n * @Module({ imports: [DrizzleAgentStoreModule.forRoot({ db })] })\n * export class AppModule {}\n * ```\n */\n@Module({})\nexport class DrizzleAgentStoreModule {\n static forRoot(options: DrizzleAgentStoreModuleOptions): DynamicModule {\n return {\n module: DrizzleAgentStoreModule,\n global: true,\n providers: [\n { provide: DrizzleAgentStore, useFactory: () => new DrizzleAgentStore(options.db) },\n { provide: AGENT_STORE, useExisting: DrizzleAgentStore },\n {\n provide: DrizzlePricingStore,\n useFactory: () => new DrizzlePricingStore(options.db),\n },\n // AGENT_PRICING_STORE: the host's own store when supplied, else the default Drizzle one.\n // DrizzleGovernanceQueries prices usage against whatever is bound here.\n options.pricingStore\n ? { provide: AGENT_PRICING_STORE, useClass: options.pricingStore }\n : { provide: AGENT_PRICING_STORE, useExisting: DrizzlePricingStore },\n {\n provide: DrizzleGovernanceQueries,\n useFactory: (pricingStore: AgentPricingStore) =>\n new DrizzleGovernanceQueries(options.db, pricingStore),\n inject: [AGENT_PRICING_STORE],\n },\n { provide: AGENT_GOVERNANCE_QUERIES, useExisting: DrizzleGovernanceQueries },\n ],\n exports: [\n DrizzleAgentStore,\n AGENT_STORE,\n DrizzleGovernanceQueries,\n AGENT_GOVERNANCE_QUERIES,\n DrizzlePricingStore,\n AGENT_PRICING_STORE,\n ],\n };\n }\n}\n"],"mappings":"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","names":["index","integer","real","sqliteTable","text","agentThread","id","primaryKey","actorRef","notNull","tenantRef","title","transient","mode","default","activeStreamId","defaultAgent","createdAt","updatedAt","deletedAt","table","on","agentMessage","threadId","references","onDelete","role","$type","content","toolCalls","toolResults","attachments","followUps","usage","agentName","runId","agentToolCall","messageId","toolName","toolType","input","output","status","executedByRef","executionMs","error","executedAt","agentTokenUsage","modelId","purpose","inputTokens","outputTokens","cacheWriteTokens","cacheReadTokens","costUsd","agentModelPricing","inputPricePer1m","outputPricePer1m","cacheWritePricePer1m","cacheReadPricePer1m","effectiveFrom","isCurrent","agentRun","durationMs","errorCode","errorMessage","retries","startedAt","settledAt","promptHash","parentRunId","agentSchema","sql","statements","additiveColumns","table","column","ddl","ensureAgentSchema","db","statement","run","sql","raw","existing","all","some","row","name","and","asc","desc","eq","gte","inArray","isNotNull","isNull","lte","sql","TURN_MESSAGE_COLUMNS","id","agentMessage","role","content","agentName","toolCalls","toolResults","attachments","createdAt","DrizzleAgentStore","db","createThread","input","now","Date","thread","crypto","randomUUID","actorRef","actor","tenantRef","title","transient","activeStreamId","defaultAgent","updatedAt","deletedAt","insert","agentThread","values","toSummary","getThread","threadId","select","from","where","and","eq","isNull","undefined","messages","orderBy","asc","last","length","map","message","toStoredMessage","loadThreadForTurn","query","loadTurnWindow","messageLimit","answered","limit","hasAssistantMessage","window","desc","rows","reverse","row","listThreads","threads","summaries","push","softDeleteThread","update","set","forkThread","fromMessageId","source","Error","cutoff","findIndex","kept","slice","fork","followUps","usage","runId","ownerOfThread","ownerOfToolCall","toolCallId","agentToolCall","innerJoin","messageId","runForToolCall","ownerOfActiveStream","setTitle","promoteThread","setActiveStream","updateThread","patch","updates","Object","keys","defaultAgentForThread","recordRunStart","run","runRow","status","durationMs","errorCode","errorMessage","retries","startedAt","settledAt","promptHash","parentRunId","agentRun","recordRunEnd","end","bumpRunRetries","sql","appendMessage","setMessageToolResults","results","truncateFrom","doomedIds","delete","inArray","recordToolCall","toolName","toolType","output","executedByRef","executionMs","error","executedAt","updateToolCall","referencedMediaIds","mediaIds","isNotNull","wanted","Set","found","attachment","has","mediaId","add","filter","recordUsage","agentTokenUsage","modelId","purpose","inputTokens","outputTokens","cacheWriteTokens","cacheReadTokens","costUsd","quotaToday","day","start","gte","lte","usedTokens","reduce","sum","lastContent","toISOString","lastMessagePreview","bucketByActor","bucketByModel","bucketByThread","bucketUsageTrend","dayBoundsUtc","rollupThreadUsage","truncateDetailContent","and","asc","count","desc","eq","gte","inArray","isNull","like","lte","sql","sum","UNCLASSIFIED_ERROR_CODE","DEFAULT_AGENT_BUCKET","TOOL_CALL_STATUSES","isToolCallStatus","value","includes","TOOL_KINDS","isToolKind","RUN_STATUSES","isRunStatus","dayStartUtc","day","dayBoundsUtc","fromDay","toDay","start","dayEndUtc","end","emptyPage","query","rows","total","page","pageSize","toRecentRunRow","run","runId","id","threadId","actorRef","agentName","status","durationMs","errorCode","errorMessage","retries","startedAt","toISOString","promptHash","parentRunId","toRunToolCallRow","toolCall","toolCallId","toolName","toolType","executionMs","executedByRef","error","createdAt","toUsageInput","row","modelId","slice","inputTokens","outputTokens","cacheWriteTokens","cacheReadTokens","costUsd","percentileMs","sortedDurationsMs","p","length","offset","Math","min","floor","DrizzleGovernanceQueries","db","pricingStore","loadPricing","prices","listCurrentPrices","pricing","Map","price","set","inputPricePer1m","outputPricePer1m","cacheWritePricePer1m","cacheReadPricePer1m","usageInRange","range","select","from","agentTokenUsage","where","and","gte","lte","map","spendByModel","bucketByModel","spendByActor","bucketByActor","spendByThread","limit","threadIds","Set","threads","agentThread","inArray","isNull","deletedAt","threadsById","thread","title","bucketByThread","includeUnknownThreads","usageTrend","bucketUsageTrend","recentToolCalls","agentToolCall","agentMessage","innerJoin","eq","messageId","orderBy","desc","threadRollups","rollups","messageCount","totalTokens","messageCounts","count","groupBy","bucket","get","undefined","usageTotals","sum","Number","toThreadActivityRows","rollup","lastActivityAt","updatedAt","recentThreads","runsInRange","agentRun","runMetrics","runs","completed","failed","settledDurationsMs","push","sort","left","right","successRate","durationP50Ms","durationP95Ms","runsByAgent","byAgent","result","localeCompare","runErrors","byError","errorCount","runTrend","byDay","recentRuns","pendingApprovals","input","threadTitle","requestedAt","toolStats","calls","byTool","call","key","rejected","values","p50ExecutionMs","p95ExecutionMs","toolCallsPage","filters","whereClause","totalRow","threadsPage","like","sql","toLowerCase","runsPage","approvalsPage","asc","runDetail","toolCalls","deleted","threadDetail","usageRows","usage","rollupThreadUsage","messageCountRow","messages","messageLimit","toolCallCounts","toolCallCountsByMessage","message","runTotalRow","runLimit","runTotal","content","truncated","truncateDetailContent","role","toolCallCount","messageIds","counts","and","eq","DrizzlePricingStore","db","upsertModelPrice","input","update","agentModelPricing","set","isCurrent","where","and","eq","modelId","insert","values","id","crypto","randomUUID","inputPricePer1m","outputPricePer1m","cacheWritePricePer1m","cacheReadPricePer1m","effectiveFrom","Date","listCurrentPrices","rows","select","from","map","row","toISOString","AGENT_GOVERNANCE_QUERIES","AGENT_PRICING_STORE","AGENT_STORE","Module","DrizzleAgentStoreModule","forRoot","options","module","global","providers","provide","DrizzleAgentStore","useFactory","db","AGENT_STORE","useExisting","DrizzlePricingStore","pricingStore","AGENT_PRICING_STORE","useClass","DrizzleGovernanceQueries","inject","AGENT_GOVERNANCE_QUERIES","exports"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-agent-store-drizzle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/DavideCarvalho/nestjs-agent.git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@dudousxd/nestjs-agent-core": "0.
|
|
32
|
+
"@dudousxd/nestjs-agent-core": "0.13.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@nestjs/common": "^10.0.0 || ^11.0.0 || ^12.0.0",
|
|
@@ -43,10 +43,12 @@
|
|
|
43
43
|
"tsup": "8.3.5",
|
|
44
44
|
"typescript": "5.9.3",
|
|
45
45
|
"vitest": "2.1.9",
|
|
46
|
-
"@dudousxd/nestjs-agent-core": "0.
|
|
46
|
+
"@dudousxd/nestjs-agent-core": "0.13.0",
|
|
47
|
+
"@dudousxd/nestjs-agent-testing": "0.10.0"
|
|
47
48
|
},
|
|
48
49
|
"scripts": {
|
|
49
50
|
"build": "tsup",
|
|
50
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
51
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
52
|
+
"typecheck:specs": "tsc -p tsconfig.spec.json"
|
|
51
53
|
}
|
|
52
54
|
}
|