/** * Drizzle Chat Session Repository Adapter * * Implements ChatSessionRepository interface using Drizzle ORM. */ import { eq, and, asc } from 'drizzle-orm'; import { nanoid } from 'nanoid'; import type { DrizzleDatabase } from '../../index.js'; import { chatSessions, chatMessages, type ChatSession, type ChatMessage } from '../../schema.js'; import type { ChatSessionRepository, CreateChatSessionData, CreateChatMessageData } from '../chat-session-repository.js'; export class DrizzleChatSessionRepository implements ChatSessionRepository { constructor(private db: DrizzleDatabase) {} async createSession(data: CreateChatSessionData): Promise { const now = new Date(); const id = nanoid(); await this.db.insert(chatSessions).values({ id, targetType: data.targetType, targetId: data.targetId, initiativeId: data.initiativeId, agentId: data.agentId ?? null, status: 'active', createdAt: now, updatedAt: now, }); return this.findSessionById(id) as Promise; } async findSessionById(id: string): Promise { const rows = await this.db .select() .from(chatSessions) .where(eq(chatSessions.id, id)) .limit(1); return rows[0] ?? null; } async findActiveSession(targetType: 'phase' | 'task', targetId: string): Promise { const rows = await this.db .select() .from(chatSessions) .where( and( eq(chatSessions.targetType, targetType), eq(chatSessions.targetId, targetId), eq(chatSessions.status, 'active' as 'active' | 'closed'), ), ) .limit(1); return rows[0] ?? null; } async findActiveSessionByAgentId(agentId: string): Promise { const rows = await this.db .select() .from(chatSessions) .where( and( eq(chatSessions.agentId, agentId), eq(chatSessions.status, 'active' as 'active' | 'closed'), ), ) .limit(1); return rows[0] ?? null; } async updateSession(id: string, data: { agentId?: string | null; status?: 'active' | 'closed' }): Promise { const updates: Record = { updatedAt: new Date() }; if (data.agentId !== undefined) updates.agentId = data.agentId; if (data.status !== undefined) updates.status = data.status; await this.db .update(chatSessions) .set(updates) .where(eq(chatSessions.id, id)); return this.findSessionById(id) as Promise; } async createMessage(data: CreateChatMessageData): Promise { const id = nanoid(); const now = new Date(); await this.db.insert(chatMessages).values({ id, chatSessionId: data.chatSessionId, role: data.role, content: data.content, changeSetId: data.changeSetId ?? null, createdAt: now, }); const rows = await this.db .select() .from(chatMessages) .where(eq(chatMessages.id, id)) .limit(1); return rows[0]!; } async findMessagesBySessionId(sessionId: string): Promise { return this.db .select() .from(chatMessages) .where(eq(chatMessages.chatSessionId, sessionId)) .orderBy(asc(chatMessages.createdAt)); } }