Seed 20 Odoo+AI prospects and enforce model-only chat responses
This commit is contained in:
@@ -856,30 +856,64 @@ export async function runLangGraphCrmAgentFor(input: {
|
||||
{ recursionLimit: 30 },
|
||||
);
|
||||
|
||||
const extractText = (value: unknown, depth = 0): string => {
|
||||
if (depth > 5 || value == null) return "";
|
||||
if (typeof value === "string") return value.trim();
|
||||
if (Array.isArray(value)) {
|
||||
const parts = value
|
||||
.map((item) => extractText(item, depth + 1))
|
||||
.filter(Boolean);
|
||||
return parts.join("\n").trim();
|
||||
}
|
||||
if (typeof value !== "object") return "";
|
||||
|
||||
const obj = value as Record<string, unknown>;
|
||||
for (const key of ["text", "content", "answer", "output_text", "final_text"]) {
|
||||
const text = extractText(obj[key], depth + 1);
|
||||
if (text) return text;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj.parts)) {
|
||||
const text = extractText(obj.parts, depth + 1);
|
||||
if (text) return text;
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
const messageType = (msg: any): string => {
|
||||
if (typeof msg?._getType === "function") {
|
||||
try {
|
||||
return String(msg._getType() ?? "");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return String(msg?.type ?? msg?.role ?? msg?.constructor?.name ?? "");
|
||||
};
|
||||
|
||||
const structured = res?.structuredResponse as { answer?: string; plan?: string[] } | undefined;
|
||||
const fallbackText = (() => {
|
||||
const messages = Array.isArray(res?.messages) ? res.messages : [];
|
||||
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
||||
const msg = messages[i];
|
||||
const type = String(msg?.type ?? "").toLowerCase();
|
||||
if (type !== "ai") continue;
|
||||
const content = msg?.content;
|
||||
if (typeof content === "string" && content.trim()) return content.trim();
|
||||
if (Array.isArray(content)) {
|
||||
const text = content
|
||||
.map((part: any) => (typeof part?.text === "string" ? part.text : ""))
|
||||
.filter(Boolean)
|
||||
.join("\n")
|
||||
.trim();
|
||||
if (text) return text;
|
||||
}
|
||||
const type = messageType(msg).toLowerCase();
|
||||
if (!type.includes("ai") && !type.includes("assistant")) continue;
|
||||
const text = extractText(msg?.content) || extractText(msg);
|
||||
if (text) return text;
|
||||
}
|
||||
return "";
|
||||
return (
|
||||
extractText(res?.output) ||
|
||||
extractText(res?.response) ||
|
||||
extractText(res?.finalResponse) ||
|
||||
""
|
||||
);
|
||||
})();
|
||||
const text = structured?.answer?.trim() || fallbackText || "Готово.";
|
||||
const plan = Array.isArray(structured?.plan) && structured.plan.length
|
||||
? structured.plan
|
||||
: ["Собрать данные", "Сформировать ответ"];
|
||||
const text = structured?.answer?.trim() || fallbackText;
|
||||
if (!text) {
|
||||
throw new Error("Model returned empty response");
|
||||
}
|
||||
const plan = Array.isArray(structured?.plan) ? structured.plan : [];
|
||||
|
||||
return {
|
||||
text,
|
||||
|
||||
Reference in New Issue
Block a user