// src/models/chat-turn.ts // Copyright (C) 2026 Robert Colbert // All Rights Reserved import { Schema, model } from "mongoose"; import { ChatSessionMode, ChatTurnStatus, IChatTurnPrompts, IChatSubagentProcess, IChatToolCall, IChatTurn, IChatTurnStats, } from "@gadget/api"; import { nanoid } from "nanoid"; export const ChatTurnPromptsSchema = new Schema({ user: { type: String, required: true }, system: { type: String, required: false }, }); export const ChatTurnStatsSchema = new Schema({ toolCallCount: { type: Number, default: 0, required: true }, inputTokens: { type: Number, default: 0, required: true }, thinkingTokenCount: { type: Number, default: 0, required: true }, responseTokens: { type: Number, default: 0, required: true }, durationMs: { type: Number, default: 0, required: true }, durationLabel: { type: String, default: "pending", required: true }, }); export const ChatToolCallSchema = new Schema({ callId: { type: String, required: true }, name: { type: String, required: true }, parameters: { type: String, required: false }, response: { type: String, required: false }, }); export const ChatSubagentProcessSchema = new Schema({ prompt: { type: String, required: true }, thinking: { type: String, required: false }, response: { type: String, required: false }, toolCalls: { type: [ChatToolCallSchema], default: [], required: true }, stats: { type: ChatTurnStatsSchema, default: {}, required: true }, }); export const ChatTurnSchema = new Schema({ _id: { type: String, default: () => nanoid() }, createdAt: { type: Date, default: Date.now, required: true }, user: { type: String, required: true, ref: "User" }, project: { type: String, required: false, ref: "Project" }, session: { type: String, required: true, ref: "ChatSession" }, provider: { type: String, required: true, ref: "AiProvider" }, llm: { type: String, required: true }, // id/name of the model used to process the prompt mode: { type: String, enum: ChatSessionMode, default: ChatSessionMode.Build, required: true, }, status: { type: String, enum: ChatTurnStatus, default: ChatTurnStatus.Processing, required: true, }, prompts: { type: ChatTurnPromptsSchema, required: true }, thinking: { type: String, required: false }, response: { type: String, required: false }, toolCalls: { type: [ChatToolCallSchema], default: [], required: true }, subagents: { type: [ChatSubagentProcessSchema], default: [], required: true }, stats: { toolCallCount: { type: Number, default: 0, required: true }, inputTokens: { type: Number, default: 0, required: true }, thinkingTokenCount: { type: Number, default: 0, required: true }, responseTokens: { type: Number, default: 0, required: true }, durationMs: { type: Number, default: 0, required: true }, durationLabel: { type: String, default: "pending", required: true }, }, }); ChatTurnSchema.index( { user: 1, project: 1, session: 1, }, { name: "chat-turn-user-project-session-index", }, ); ChatTurnSchema.index( { user: 1, prompt: "text", thinking: "text", response: "text", }, { weights: { prompt: 10, response: 5, thinking: 1, }, name: "chat-turn-user-text-index", }, ); export const ChatTurn = model("ChatTurn", ChatTurnSchema); export default ChatTurn;