EventBuzz_Backend/src/models/WebChatSession.js

108 lines
4.0 KiB
JavaScript

const mongoose = require('mongoose');
const messageSchema = new mongoose.Schema(
{
role: { type: String, enum: ['user', 'assistant'], required: true },
text: { type: String, required: true },
ts: { type: Date, default: Date.now },
modelId: { type: String, default: null },
inputTokens: { type: Number, default: 0 },
outputTokens: { type: Number, default: 0 },
},
{ _id: false },
);
// Two-stage concierge pipeline turn log. Kept in sync with the turn log shape
// produced by utils/conciergePipelineLog.js. Stores previews only (no raw PII).
const pipelineCall1Schema = new mongoose.Schema(
{
skipped: { type: Boolean, default: false },
path: { type: String, default: null },
modelId: { type: String, default: null },
intent: { type: String, default: null },
needsSecondCall: { type: Boolean, default: null },
inputTokens: { type: Number, default: 0 },
outputTokens: { type: Number, default: 0 },
latencyMs: { type: Number, default: 0 },
rawPreview: { type: String, default: null },
},
{ _id: false },
);
const pipelineHandlerSchema = new mongoose.Schema(
{
name: { type: String, default: null },
skippedCall2: { type: Boolean, default: false },
cardCount: { type: Number, default: 0 },
cardTypes: { type: [String], default: [] },
latencyMs: { type: Number, default: 0 },
},
{ _id: false },
);
const pipelineCall2Schema = new mongoose.Schema(
{
skipped: { type: Boolean, default: true },
reason: { type: String, default: null },
modelId: { type: String, default: null },
inputTokens: { type: Number, default: 0 },
outputTokens: { type: Number, default: 0 },
latencyMs: { type: Number, default: 0 },
retrievalSources: { type: Number, default: 0 },
rawPreview: { type: String, default: null },
},
{ _id: false },
);
const pipelineTotalsSchema = new mongoose.Schema(
{
inputTokens: { type: Number, default: 0 },
outputTokens: { type: Number, default: 0 },
totalTokens: { type: Number, default: 0 },
latencyMs: { type: Number, default: 0 },
},
{ _id: false },
);
const pipelineTurnSchema = new mongoose.Schema(
{
ts: { type: Date, default: Date.now },
sessionId: { type: String, default: null },
botId: { type: String, default: null },
userMessagePreview: { type: String, default: null },
call1: { type: pipelineCall1Schema, default: () => ({}) },
handler: { type: pipelineHandlerSchema, default: () => ({}) },
call2: { type: pipelineCall2Schema, default: () => ({}) },
totals: { type: pipelineTotalsSchema, default: () => ({}) },
replyPreview: { type: String, default: null },
},
{ _id: false },
);
const webChatSessionSchema = new mongoose.Schema(
{
botId: { type: mongoose.Schema.Types.ObjectId, ref: 'ConciergeBot', required: true, index: true },
eventId: { type: mongoose.Schema.Types.ObjectId, ref: 'Event', required: true, index: true },
organization: { type: mongoose.Schema.Types.ObjectId, ref: 'Organization', required: true, index: true },
sessionId: { type: String, required: true, index: true },
participant: { type: mongoose.Schema.Types.ObjectId, ref: 'Participant', default: null, index: true },
awaitingPersonalEmail: { type: Boolean, default: false },
/** Last successfully routed information intent (for affirmative "yes" continuations). */
lastIntent: { type: String, default: null },
identityVerifiedAt: { type: Date, default: null },
identityMethod: { type: String, enum: ['email'], default: null },
endedAt: { type: Date, default: null, index: true },
history: { type: [messageSchema], default: [] },
pipelineLog: { type: [pipelineTurnSchema], default: [] },
lastSeenAt: { type: Date, default: Date.now, index: true },
inputTokensTotal: { type: Number, default: 0 },
outputTokensTotal: { type: Number, default: 0 },
},
{ timestamps: true },
);
webChatSessionSchema.index({ botId: 1, sessionId: 1 }, { unique: true });
module.exports = mongoose.model('WebChatSession', webChatSessionSchema);