feat(chat): threads UI + graphql flow + qwen/gigachat integration

This commit is contained in:
Ruslan Bakiev
2026-02-18 19:41:34 +07:00
parent 676bb9e105
commit d7af2d0a46
21 changed files with 2432 additions and 437 deletions

View File

@@ -19,6 +19,14 @@ export type AgentReply = {
text: string;
plan: string[];
tools: string[];
thinking?: string[];
toolRuns?: Array<{
name: string;
status: "ok" | "error";
input: string;
output: string;
at: string;
}>;
dbWrites?: Array<{ kind: string; detail: string }>;
};
@@ -76,7 +84,14 @@ export async function runCrmAgentFor(
input: { teamId: string; userId: string; userText: string },
): Promise<AgentReply> {
const mode = (process.env.CF_AGENT_MODE ?? "langgraph").toLowerCase();
if (mode !== "rule" && process.env.OPENAI_API_KEY) {
const llmApiKey =
process.env.LLM_API_KEY ||
process.env.OPENAI_API_KEY ||
process.env.DASHSCOPE_API_KEY ||
process.env.QWEN_API_KEY;
const hasGigachat = Boolean((process.env.GIGACHAT_AUTH_KEY ?? "").trim() && (process.env.GIGACHAT_SCOPE ?? "").trim());
if (mode !== "rule" && (llmApiKey || hasGigachat)) {
return runLangGraphCrmAgentFor(input);
}
@@ -109,6 +124,15 @@ export async function runCrmAgentFor(
"Отсортировать и показать топ",
],
tools: ["read index/contacts.json", "read messages/{contactId}.jsonl", "read events/{contactId}.jsonl"],
toolRuns: [
{
name: "dataset:index_contacts",
status: "ok",
input: "index/contacts.json",
output: "Loaded contacts index",
at: new Date().toISOString(),
},
],
text:
`Топ-10 по активности (сообщения + события):\n` +
top.map(formatContactLine).join("\n") +
@@ -163,6 +187,15 @@ export async function runCrmAgentFor(
"Сформировать короткий список действий",
],
tools: ["read index/contacts.json", "read events/{contactId}.jsonl"],
toolRuns: [
{
name: "dataset:query_events",
status: "ok",
input: "events/*.jsonl (today)",
output: `Found ${todayEvents.length} events`,
at: new Date().toISOString(),
},
],
text: lines.join("\n"),
};
}
@@ -171,6 +204,7 @@ export async function runCrmAgentFor(
return {
plan: ["Уточнить цель", "Выбрать данные для анализа", "Предложить план действий и, если нужно, изменения в CRM"],
tools: ["read index/contacts.json (по необходимости)", "search messages/events (по необходимости)"],
toolRuns: [],
text:
"Ок. Скажи, что нужно сделать.\n" +
"Примеры:\n" +
@@ -185,17 +219,38 @@ export async function persistChatMessage(input: {
text: string;
plan?: string[];
tools?: string[];
thinking?: string[];
toolRuns?: Array<{
name: string;
status: "ok" | "error";
input: string;
output: string;
at: string;
}>;
teamId: string;
conversationId: string;
authorUserId?: string | null;
}) {
const hasDebugPayload = Boolean(
(input.plan && input.plan.length) ||
(input.tools && input.tools.length) ||
(input.thinking && input.thinking.length) ||
(input.toolRuns && input.toolRuns.length),
);
const data: Prisma.ChatMessageCreateInput = {
team: { connect: { id: input.teamId } },
conversation: { connect: { id: input.conversationId } },
authorUser: input.authorUserId ? { connect: { id: input.authorUserId } } : undefined,
role: input.role,
text: input.text,
planJson: input.plan || input.tools ? ({ steps: input.plan ?? [], tools: input.tools ?? [] } as any) : undefined,
planJson: hasDebugPayload
? ({
steps: input.plan ?? [],
tools: input.tools ?? [],
thinking: input.thinking ?? input.plan ?? [],
toolRuns: input.toolRuns ?? [],
} as any)
: undefined,
};
return prisma.chatMessage.create({ data });
}

File diff suppressed because it is too large Load Diff