// src/models/chat-history.ts // Copyright (C) 2025 DTP Technologies, LLC // All Rights Reserved import { Types, Schema, Document, model } from "mongoose"; import { IChatSession, ChatSessionMode } from "./chat-session.js"; import { IUser } from "./user.js"; export enum ChatHistoryStatus { Processing = "processing", Success = "success", Failed = "failed", } export interface IChatToolCallParameter { name: string; value: string; } export const ChatToolCallParameterSchema = new Schema( { name: { type: String, required: true }, value: { type: String, required: true }, }, { _id: false }, ); export interface IChatFileOperation { type: "read" | "write" | "edit" | "shell"; path?: string; diff?: string; linesAdded?: number; linesRemoved?: number; isBinary?: boolean; } export interface IChatToolCall { tool: { name: string; callId: string; parameters: IChatToolCallParameter[]; }; response: string; fileOperation?: IChatFileOperation; subagentStats?: { inputTokens: number; outputTokens: number; toolCallCount: number; }; } const ChatFileOperationSchema = new Schema( { type: { type: String, required: true, enum: ["read", "write", "edit", "shell"], }, path: { type: String }, diff: { type: String }, linesAdded: { type: Number }, linesRemoved: { type: Number }, isBinary: { type: Boolean }, }, { _id: false }, ); const SubagentStatsSchema = new Schema( { inputTokens: { type: Number }, outputTokens: { type: Number }, toolCallCount: { type: Number }, }, { _id: false }, ); export const ChatToolCallSchema = new Schema({ tool: { name: { type: String, required: true }, callId: { type: String, required: true }, parameters: { type: [ChatToolCallParameterSchema], default: [], required: true, }, }, response: { type: String }, fileOperation: { type: ChatFileOperationSchema }, subagentStats: { type: SubagentStatsSchema }, }); export interface IChatHistoryError { message: string; stack?: string; timestamp: Date; } export interface IChatHistory extends Document { createdAt: Date; user: IUser | Types.ObjectId; session: IChatSession | Types.ObjectId; prompt: string; mode: ChatSessionMode; status: ChatHistoryStatus; toolCalls: IChatToolCall[]; fileOperations: IChatFileOperation[]; response: { thinking?: string; message?: string; }; qdrantId?: string; isSubagent?: boolean; error?: IChatHistoryError; subagentHistory?: IChatHistory[]; // For sub-agents, reference to their own history entries inputTokens: number; outputTokens: number; } export const ChatHistorySchema = new Schema({ createdAt: { type: Date, default: Date.now, required: true }, user: { type: Types.ObjectId, required: true, ref: "User" }, session: { type: Types.ObjectId, required: true, ref: "ChatSession" }, prompt: { type: String, required: true }, mode: { type: String, enum: ChatSessionMode, required: true }, toolCalls: { type: [ChatToolCallSchema], default: [], required: true }, fileOperations: { type: [ChatFileOperationSchema], default: [], required: true, }, response: { thinking: { type: String }, message: { type: String }, }, qdrantId: { type: String }, status: { type: String, enum: ChatHistoryStatus, default: ChatHistoryStatus.Processing, }, isSubagent: { type: Boolean, default: false }, error: { message: { type: String }, stack: { type: String }, timestamp: { type: Date }, }, subagentHistory: [{ type: Schema.Types.ObjectId, ref: "ChatHistory" }], inputTokens: { type: Number, default: 0 }, outputTokens: { type: Number, default: 0 }, }); export const ChatHistory = model( "ChatHistory", ChatHistorySchema, ); export default ChatHistory; // Note: Index synchronization is now handled during application startup // to ensure the database connection is established first. // See src/lib/db.ts for the syncDatabaseIndexes function.