/** * Drizzle Conversation Repository Adapter * * Implements ConversationRepository interface using Drizzle ORM. */ import { eq, and, asc, count, inArray } from 'drizzle-orm'; import { nanoid } from 'nanoid'; import type { DrizzleDatabase } from '../../index.js'; import { conversations, type Conversation } from '../../schema.js'; import type { ConversationRepository, CreateConversationData } from '../conversation-repository.js'; export class DrizzleConversationRepository implements ConversationRepository { constructor(private db: DrizzleDatabase) {} async create(data: CreateConversationData): Promise { const now = new Date(); const id = nanoid(); await this.db.insert(conversations).values({ id, fromAgentId: data.fromAgentId, toAgentId: data.toAgentId, initiativeId: data.initiativeId ?? null, phaseId: data.phaseId ?? null, taskId: data.taskId ?? null, question: data.question, status: 'pending', createdAt: now, updatedAt: now, }); return this.findById(id) as Promise; } async findById(id: string): Promise { const rows = await this.db .select() .from(conversations) .where(eq(conversations.id, id)) .limit(1); return rows[0] ?? null; } async findPendingForAgent(toAgentId: string): Promise { return this.db .select() .from(conversations) .where( and( eq(conversations.toAgentId, toAgentId), eq(conversations.status, 'pending' as 'pending' | 'answered'), ), ) .orderBy(asc(conversations.createdAt)); } async answer(id: string, answer: string): Promise { await this.db .update(conversations) .set({ answer, status: 'answered' as 'pending' | 'answered', updatedAt: new Date(), }) .where(eq(conversations.id, id)); return this.findById(id); } async countByFromAgentIds(agentIds: string[]): Promise<{ agentId: string; count: number }[]> { if (agentIds.length === 0) return []; const rows = await this.db .select({ agentId: conversations.fromAgentId, count: count(), }) .from(conversations) .where(inArray(conversations.fromAgentId, agentIds)) .groupBy(conversations.fromAgentId); return rows.map(r => ({ agentId: r.agentId, count: Number(r.count) })); } async findByFromAgentId(agentId: string): Promise { return this.db .select() .from(conversations) .where(eq(conversations.fromAgentId, agentId)) .orderBy(asc(conversations.createdAt)) .limit(200); } }