gadget/gadget-code/src/models/chat-turn.ts
2026-05-11 19:07:48 -04:00

127 lines
3.9 KiB
TypeScript

// src/models/chat-turn.ts
// Copyright (C) 2026 Robert Colbert <rob.colbert@openplatform.us>
// All Rights Reserved
import { Schema, model } from "mongoose";
import {
ChatSessionMode,
ChatTurnStatus,
IChatTurnPrompts,
IChatSubagentProcess,
IChatToolCall,
IChatTurn,
IChatTurnStats,
IChatTurnBlock,
} from "@gadget/api";
import { nanoid } from "nanoid";
export const ChatTurnPromptsSchema = new Schema<IChatTurnPrompts>({
user: { type: String, required: true },
system: { type: String, required: false },
});
export const ChatTurnStatsSchema = new Schema<IChatTurnStats>({
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 },
});
const ChatTurnBlockSchema = new Schema<IChatTurnBlock>({
mode: {
type: String,
enum: ['thinking', 'responding', 'tool'],
required: true
},
createdAt: { type: Date, default: Date.now, required: true },
content: { type: Schema.Types.Mixed, required: true },
}, { _id: false });
export const ChatToolCallSchema = new Schema<IChatToolCall>({
callId: { type: String, required: true },
name: { type: String, required: true },
parameters: { type: String, required: false },
response: { type: String, required: false },
subagent: { type: Schema.Types.Mixed, required: false } as any,
});
export const ChatSubagentProcessSchema = new Schema<IChatSubagentProcess>({
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<IChatTurn>({
_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
reasoningEffort: {
type: String,
enum: ["off", "low", "medium", "high"],
default: "off",
},
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 },
blocks: { type: [ChatTurnBlockSchema], default: [], required: true },
errorMessage: { 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,
"prompts.user": "text",
"prompts.system": "text",
},
{
weights: {
"prompts.user": 10,
"prompts.system": 5,
},
name: "chat-turn-user-text-index",
},
);
export const ChatTurn = model<IChatTurn>("ChatTurn", ChatTurnSchema);
export default ChatTurn;