// src/services/chat-session.ts // Copyright (C) 2026 DTP Technologies, LLC // All Rights Reserved import { ChatSession, ChatSessionType, ChatSessionMode, } from "../models/chat-session.js"; import { DtpService } from "../lib/service.js"; export interface IChatSessionListItem { _id: string; name: string; lastMessageAt: Date | null; turnCount: number; toolCallCount: number; createdAt: Date; } export class ChatSessionService extends DtpService { get name(): string { return "ChatSessionService"; } get slug(): string { return "chat-session"; } async start(): Promise { this.log.info("service started"); } async stop(): Promise { this.log.info("service stopped"); } async listByUser(userId: string): Promise { const sessions = await ChatSession.find({ user: userId }) .sort({ lastMessageAt: -1, createdAt: -1 }) .lean(); return sessions.map((s) => ({ _id: s._id.toString(), name: s.name, lastMessageAt: s.lastMessageAt ?? null, turnCount: s.stats.turnCount, toolCallCount: s.stats.toolCallCount, createdAt: s.createdAt, })); } async listByProject( projectId: string, userId: string, ): Promise { const sessions = await ChatSession.find({ user: userId, project: projectId, }) .sort({ lastMessageAt: -1, createdAt: -1 }) .lean(); return sessions.map((s) => ({ _id: s._id.toString(), name: s.name, lastMessageAt: s.lastMessageAt ?? null, turnCount: s.stats.turnCount, toolCallCount: s.stats.toolCallCount, createdAt: s.createdAt, })); } async create( userId: string, projectId?: string, name?: string, ): Promise { const session = new ChatSession({ user: userId, project: projectId, name: name ?? "New Session", type: ChatSessionType.Desktop, mode: ChatSessionMode.Build, }); await session.save(); this.log.info("ChatSession created", { sessionId: session._id, userId, projectId, }); return { _id: session._id.toString(), name: session.name, lastMessageAt: null, turnCount: 0, toolCallCount: 0, createdAt: session.createdAt, }; } async findById(sessionId: string): Promise { const session = await ChatSession.findById(sessionId).lean(); if (!session) { return null; } return { _id: session._id.toString(), name: session.name, lastMessageAt: session.lastMessageAt ?? null, turnCount: session.stats.turnCount, toolCallCount: session.stats.toolCallCount, createdAt: session.createdAt, }; } async updateName(sessionId: string, name: string): Promise { await ChatSession.findByIdAndUpdate(sessionId, { name }); this.log.info("ChatSession name updated", { sessionId, name }); } async delete(sessionId: string, userId: string): Promise { const result = await ChatSession.deleteOne({ _id: sessionId, user: userId, }); if (result.deletedCount === 0) { throw new Error("ChatSession not found or not owned by user"); } this.log.info("ChatSession deleted", { sessionId, userId }); } } export default new ChatSessionService();