67 lines
2.7 KiB
JavaScript
67 lines
2.7 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 },
|
|
/** Client-facing id for assistant replies (feedback). */
|
|
msgId: { type: String, default: null },
|
|
/** Thumb feedback: true = satisfied, false = not satisfied. */
|
|
satisfied: { type: Boolean, default: null },
|
|
feedbackAt: { type: Date, 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' },
|
|
organization: { type: mongoose.Schema.Types.ObjectId, ref: 'Organization' },
|
|
sessionId: { type: String, required: true, trim: true, index: true },
|
|
history: { type: [messageSchema], default: [] },
|
|
lastIntent: { type: String, default: null },
|
|
lastSeenAt: { type: Date, default: Date.now },
|
|
endedAt: { type: Date, default: null },
|
|
inputTokensTotal: { type: Number, default: 0 },
|
|
outputTokensTotal: { type: Number, default: 0 },
|
|
|
|
// Identity / OTP
|
|
participant: {
|
|
type: mongoose.Schema.Types.ObjectId,
|
|
ref: 'Participant',
|
|
default: null,
|
|
index: true,
|
|
},
|
|
identityVerifiedAt: { type: Date, default: null },
|
|
identityMethod: { type: String, default: null },
|
|
authState: {
|
|
type: String,
|
|
enum: ['awaiting_email', 'awaiting_otp'],
|
|
default: undefined,
|
|
},
|
|
authEmail: { type: String, trim: true, lowercase: true, default: null },
|
|
otpHash: { type: String, default: null },
|
|
otpExpiresAt: { type: Date, default: null },
|
|
pendingIntent: { type: String, default: null },
|
|
pendingMessage: { type: String, default: null },
|
|
pendingEntities: { type: mongoose.Schema.Types.Mixed, default: null },
|
|
/** Last session ids shown as cards — used to resolve "add it" / "yes". */
|
|
lastSessionIds: { type: [String], default: [] },
|
|
/** Rate-limit ticket QR emails from this chat session. */
|
|
lastTicketEmailAt: { type: Date, default: null },
|
|
/** Rate-limit organizer escalation emails from this chat session. */
|
|
lastEscalationEmailAt: { type: Date, default: null },
|
|
},
|
|
{ timestamps: true, collection: 'webchatsessions' },
|
|
);
|
|
|
|
webChatSessionSchema.index({ botId: 1, sessionId: 1 }, { unique: true });
|
|
|
|
module.exports =
|
|
mongoose.models.WebChatSession || mongoose.model('WebChatSession', webChatSessionSchema);
|