feat: add scoped context payload and rollbackable document changes
This commit is contained in:
@@ -4,6 +4,7 @@ import { getAuthContext } from "../utils/auth";
|
||||
import { prisma } from "../utils/prisma";
|
||||
import { buildChangeSet, captureSnapshot } from "../utils/changeSet";
|
||||
import { persistChatMessage, runCrmAgentFor, type AgentTraceEvent } from "../agent/crmAgent";
|
||||
import type { PilotContextPayload } from "../agent/crmAgent";
|
||||
import type { ChangeSet } from "../utils/changeSet";
|
||||
|
||||
function extractMessageText(message: any): string {
|
||||
@@ -25,6 +26,69 @@ function getLastUserText(messages: any[]): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
function sanitizeContextPayload(raw: unknown): PilotContextPayload | null {
|
||||
if (!raw || typeof raw !== "object") return null;
|
||||
const item = raw as Record<string, any>;
|
||||
const scopesRaw = Array.isArray(item.scopes) ? item.scopes : [];
|
||||
const scopes = scopesRaw
|
||||
.map((scope) => String(scope))
|
||||
.filter((scope) => scope === "summary" || scope === "deal" || scope === "message" || scope === "calendar") as PilotContextPayload["scopes"];
|
||||
if (!scopes.length) return null;
|
||||
|
||||
const payload: PilotContextPayload = { scopes };
|
||||
|
||||
if (item.summary && typeof item.summary === "object") {
|
||||
const contactId = String(item.summary.contactId ?? "").trim();
|
||||
const name = String(item.summary.name ?? "").trim();
|
||||
if (contactId && name) payload.summary = { contactId, name };
|
||||
}
|
||||
|
||||
if (item.deal && typeof item.deal === "object") {
|
||||
const dealId = String(item.deal.dealId ?? "").trim();
|
||||
const title = String(item.deal.title ?? "").trim();
|
||||
const contact = String(item.deal.contact ?? "").trim();
|
||||
if (dealId && title && contact) payload.deal = { dealId, title, contact };
|
||||
}
|
||||
|
||||
if (item.message && typeof item.message === "object") {
|
||||
const contactId = String(item.message.contactId ?? "").trim();
|
||||
const contact = String(item.message.contact ?? "").trim();
|
||||
const intent = String(item.message.intent ?? "").trim();
|
||||
if (intent === "add_message_or_reminder") {
|
||||
payload.message = {
|
||||
...(contactId ? { contactId } : {}),
|
||||
...(contact ? { contact } : {}),
|
||||
intent: "add_message_or_reminder",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (item.calendar && typeof item.calendar === "object") {
|
||||
const view = String(item.calendar.view ?? "").trim();
|
||||
const period = String(item.calendar.period ?? "").trim();
|
||||
const selectedDateKey = String(item.calendar.selectedDateKey ?? "").trim();
|
||||
const focusedEventId = String(item.calendar.focusedEventId ?? "").trim();
|
||||
const eventIds = Array.isArray(item.calendar.eventIds)
|
||||
? item.calendar.eventIds.map((id: any) => String(id ?? "").trim()).filter(Boolean)
|
||||
: [];
|
||||
if (
|
||||
(view === "day" || view === "week" || view === "month" || view === "year" || view === "agenda") &&
|
||||
period &&
|
||||
selectedDateKey
|
||||
) {
|
||||
payload.calendar = {
|
||||
view,
|
||||
period,
|
||||
selectedDateKey,
|
||||
...(focusedEventId ? { focusedEventId } : {}),
|
||||
eventIds,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function humanizeTraceText(trace: AgentTraceEvent): string {
|
||||
if (trace.toolRun?.name) {
|
||||
return `Использую инструмент: ${trace.toolRun.name}`;
|
||||
@@ -62,9 +126,10 @@ function renderChangeSetSummary(changeSet: ChangeSet): string {
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const auth = await getAuthContext(event);
|
||||
const body = await readBody<{ messages?: any[] }>(event);
|
||||
const body = await readBody<{ messages?: any[]; contextPayload?: unknown }>(event);
|
||||
const messages = Array.isArray(body?.messages) ? body.messages : [];
|
||||
const userText = getLastUserText(messages);
|
||||
const contextPayload = sanitizeContextPayload(body?.contextPayload);
|
||||
|
||||
if (!userText) {
|
||||
throw createError({ statusCode: 400, statusMessage: "Last user message is required" });
|
||||
@@ -94,6 +159,7 @@ export default defineEventHandler(async (event) => {
|
||||
teamId: auth.teamId,
|
||||
userId: auth.userId,
|
||||
userText,
|
||||
contextPayload,
|
||||
requestId,
|
||||
conversationId: auth.conversationId,
|
||||
onTrace: async (trace: AgentTraceEvent) => {
|
||||
|
||||
Reference in New Issue
Block a user