137 lines
3.3 KiB
TypeScript
137 lines
3.3 KiB
TypeScript
// 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<void> {
|
|
this.log.info("service started");
|
|
}
|
|
|
|
async stop(): Promise<void> {
|
|
this.log.info("service stopped");
|
|
}
|
|
|
|
async listByUser(userId: string): Promise<IChatSessionListItem[]> {
|
|
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<IChatSessionListItem[]> {
|
|
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<IChatSessionListItem> {
|
|
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<IChatSessionListItem | null> {
|
|
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<void> {
|
|
await ChatSession.findByIdAndUpdate(sessionId, { name });
|
|
this.log.info("ChatSession name updated", { sessionId, name });
|
|
}
|
|
|
|
async delete(sessionId: string, userId: string): Promise<void> {
|
|
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();
|