330 lines
24 KiB
JavaScript
330 lines
24 KiB
JavaScript
"use strict";
|
||
// @ts-nocheck
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.createAssistantTurnMeaningPolicy = createAssistantTurnMeaningPolicy;
|
||
const SUPPORTED_ADDRESS_INTENTS = new Set([
|
||
"receivables_confirmed_as_of_date",
|
||
"payables_confirmed_as_of_date",
|
||
"list_documents_by_counterparty",
|
||
"customer_revenue_and_payments",
|
||
"inventory_on_hand_as_of_date",
|
||
"vat_liability_confirmed_for_tax_period",
|
||
"vat_payable_confirmed_as_of_date",
|
||
"vat_payable_forecast"
|
||
]);
|
||
function fallbackCompactWhitespace(value) {
|
||
return String(value ?? "").replace(/\s+/g, " ").trim();
|
||
}
|
||
function normalizeTurnText(value, deps) {
|
||
const compactWhitespace = typeof deps?.compactWhitespace === "function" ? deps.compactWhitespace : fallbackCompactWhitespace;
|
||
const repaired = typeof deps?.repairAddressMojibake === "function"
|
||
? deps.repairAddressMojibake(String(value ?? ""))
|
||
: String(value ?? "");
|
||
return compactWhitespace(repaired.toLowerCase())
|
||
.replace(/\u0451/gu, "\u0435")
|
||
.replace(/(^|[^\p{L}0-9_])\u043d\u0430\u043c\u0441(?=$|[^\p{L}0-9_])/giu, "$1\u043d\u0430\u043c")
|
||
.replace(/(^|[^\p{L}0-9_])\u043a\u0430\u043a\u0438\u0435\u043a(?=$|[^\p{L}0-9_])/giu, "$1\u043a\u0430\u043a\u0438\u0435");
|
||
}
|
||
function toNonEmptyString(value, deps) {
|
||
if (typeof deps?.toNonEmptyString === "function") {
|
||
return deps.toNonEmptyString(value);
|
||
}
|
||
if (value === null || value === undefined) {
|
||
return null;
|
||
}
|
||
const text = String(value).trim();
|
||
return text.length > 0 ? text : null;
|
||
}
|
||
function detectSupportedIntent(text, deps) {
|
||
const resolved = typeof deps?.resolveAddressIntent === "function" ? deps.resolveAddressIntent(text) : null;
|
||
const resolverIntent = toNonEmptyString(resolved?.intent, deps);
|
||
if (resolverIntent && resolverIntent !== "unknown" && SUPPORTED_ADDRESS_INTENTS.has(resolverIntent)) {
|
||
return {
|
||
intent: resolverIntent,
|
||
confidence: toNonEmptyString(resolved?.confidence, deps) ?? "medium",
|
||
reason: "address_intent_resolver_current_turn_signal"
|
||
};
|
||
}
|
||
if (/(?:\u043a\u0442\u043e\s+\u043d\u0430\u043c\s+\u0434\u043e\u043b\u0436|\u043d\u0430\u043c\s+\u043a\u0442\u043e\s+\u0434\u043e\u043b\u0436|\u0434\u0435\u0431\u0438\u0442\u043e\u0440|\u0434\u0435\u0431\u0438\u0442\u043e\u0440\u0441\u043a|\breceivables?\b)/iu.test(text)) {
|
||
return {
|
||
intent: "receivables_confirmed_as_of_date",
|
||
confidence: "high",
|
||
reason: "receivables_current_turn_meaning_signal"
|
||
};
|
||
}
|
||
if (/(?:\u043a\u043e\u043c\u0443\s+\u043c\u044b\s+\u0434\u043e\u043b\u0436|\u043c\u044b\s+\u043a\u043e\u043c\u0443\s+\u0434\u043e\u043b\u0436|\u043c\u044b\s+\u0434\u043e\u043b\u0436\u043d|\u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0440|\bpayables?\b)/iu.test(text)) {
|
||
return {
|
||
intent: "payables_confirmed_as_of_date",
|
||
confidence: "high",
|
||
reason: "payables_current_turn_meaning_signal"
|
||
};
|
||
}
|
||
if (/(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\u0434\u043e\u043a\u0438|docs?|documents?)/iu.test(text) && /(?:\u043f\u043e|by)\s+[\p{L}0-9._-]{2,}/iu.test(text)) {
|
||
return {
|
||
intent: "list_documents_by_counterparty",
|
||
confidence: "medium",
|
||
reason: "counterparty_documents_current_turn_signal"
|
||
};
|
||
}
|
||
if (/(?:\u043e\u0441\u0442\u0430\u0442|\u0441\u043a\u043b\u0430\u0434|inventory|stock)/iu.test(text)) {
|
||
return {
|
||
intent: "inventory_on_hand_as_of_date",
|
||
confidence: "medium",
|
||
reason: "inventory_snapshot_current_turn_signal"
|
||
};
|
||
}
|
||
return null;
|
||
}
|
||
function detectCounterpartyTurnoverFamily(text) {
|
||
const hasTurnoverCue = /(?:\u043e\u0431\u043e\u0440\u043e\u0442|\u0432\u044b\u0440\u0443\u0447\u043a|\u0434\u043e\u0445\u043e\u0434|turnover|revenue)/iu.test(text);
|
||
if (!hasTurnoverCue) {
|
||
return null;
|
||
}
|
||
const explicitEntityMatch = text.match(/(?:\u043f\u043e|by|for)?\s*([\p{L}0-9._-]{2,})\s*$/iu);
|
||
const rawEntity = explicitEntityMatch?.[1] ?? null;
|
||
const ignored = new Set([
|
||
"\u043e\u0431\u043e\u0440\u043e\u0442",
|
||
"\u0432\u044b\u0440\u0443\u0447\u043a\u0430",
|
||
"\u0434\u043e\u0445\u043e\u0434",
|
||
"\u0431\u044b\u043b",
|
||
"\u0431\u044b\u043b\u0430",
|
||
"\u0432\u0440\u0435\u043c\u044f",
|
||
"\u0432\u0440\u0435\u043c\u0435\u043d\u0438",
|
||
"\u0433\u043e\u0434",
|
||
"\u0433\u043e\u0434\u0430",
|
||
"\u043f\u0435\u0440\u0438\u043e\u0434",
|
||
"\u043f\u0435\u0440\u0438\u043e\u0434\u0430",
|
||
"\u043c\u0435\u0441\u044f\u0446",
|
||
"\u043c\u0435\u0441\u044f\u0446\u0430",
|
||
"\u043a\u0432\u0430\u0440\u0442\u0430\u043b",
|
||
"\u043a\u0432\u0430\u0440\u0442\u0430\u043b\u0430",
|
||
"turnover",
|
||
"revenue",
|
||
"time",
|
||
"year",
|
||
"period",
|
||
"month",
|
||
"quarter"
|
||
]);
|
||
const entity = rawEntity && !ignored.has(rawEntity) ? rawEntity : null;
|
||
return {
|
||
family: "counterparty_value_or_turnover",
|
||
entity
|
||
};
|
||
}
|
||
function hasExplicitCounterpartyValueObject(text) {
|
||
return /(?:\u043a\u043b\u0438\u0435\u043d\u0442|\u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b|\u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442|\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a|\u0434\u043e\u0433\u043e\u0432\u043e\u0440|\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442|\u0442\u043e\u0432\u0430\u0440|\u043d\u043e\u043c\u0435\u043d\u043a\u043b\u0430\u0442\u0443\u0440|\u0441\u0434\u0435\u043b\u043a|customer|client|counterparty|supplier|vendor|contract|item|product|deal)/iu.test(text);
|
||
}
|
||
function hasOrganizationLevelEarningsOverviewSignal(text) {
|
||
const normalized = String(text ?? "");
|
||
if (!normalized || hasExplicitCounterpartyValueObject(normalized)) {
|
||
return false;
|
||
}
|
||
const hasYearRankingCue = /(?:(?:\u043a\u0430\u043a\u043e\u0439|\u043a\u0430\u043a\u0438\u0435|\u043a\u0430\u043a\u0430\u044f|what|which)\s+(?:\u0443\s+\u043d\u0430\u0441\s+)?(?:[\p{L}0-9._-]+\s+){0,4}(?:\u0441\u0430\u043c|\u0441\u0430\u043c\u044b\u0435|best|top|most)[\s\S]{0,80}(?:\u0434\u043e\u0445\u043e\u0434\u043d|\u043f\u0440\u0438\u0431\u044b\u043b|\u0432\u044b\u0440\u0443\u0447\u043a|\u043e\u0431\u043e\u0440\u043e\u0442|revenue|profit|turnover)[\s\S]{0,40}(?:\u0433\u043e\u0434|year)|(?:\u0434\u043e\u0445\u043e\u0434\u043d|\u043f\u0440\u0438\u0431\u044b\u043b|\u0432\u044b\u0440\u0443\u0447\u043a|\u043e\u0431\u043e\u0440\u043e\u0442|revenue|profit|turnover)[\s\S]{0,60}(?:\u0441\u0430\u043c|\u0441\u0430\u043c\u044b\u0435|best|top|most)[\s\S]{0,40}(?:\u0433\u043e\u0434|year))/iu.test(normalized);
|
||
const hasCompanyEarningsCue = /(?:(?:\u0441\u043a\u043e\u043b\u044c\u043a\u043e|\u0441\u043a\u043e\u043a\w*|how\s+much)[\s\S]{0,120}(?:\u0437\u0430\u0440\u0430\u0431\u043e\u0442|\u0432\u044b\u0440\u0443\u0447)|(?:\u0437\u0430\u0440\u0430\u0431\u043e\u0442|\u0432\u044b\u0440\u0443\u0447)[\s\S]{0,80}(?:\u0437\u0430\s+(?:\u0432\u0441\u0435\s+\u0432\u0440\u0435\u043c\u044f|\d{2,4}\s*\u0433\u043e\u0434|(?:19|20)\d{2})|all\s+time|\b(?:19|20)\d{2}\b)|(?:\u043e\u0431\u0449\w*\s+(?:\u043e\u0431\u043e\u0440\u043e\u0442|\u0432\u044b\u0440\u0443\u0447\u043a)|(?:\u043e\u0431\u043e\u0440\u043e\u0442|\u0432\u044b\u0440\u0443\u0447\u043a)[\s\S]{0,40}\u0437\u0430\s+\u0432\u0441\u0435\s+\u0432\u0440\u0435\u043c\u044f))/iu.test(normalized);
|
||
const hasCompanyProfitMarginCue = /(?:\u043f\u0440\u0438\u0431\u044b\u043b\w*|\u043c\u0430\u0440\u0436\w*|\u0440\u0435\u043d\u0442\u0430\u0431\w*|\u0444\u0438\u043d(?:\u0430\u043d\u0441\w*)?\s*[- ]?\s*\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442|p\s*&\s*l|profit(?:ability)?|margin|financial\s+result)/iu.test(normalized) &&
|
||
/(?:\u043a\u0430\u043a\w*|\u0441\u043a\u043e\u043b\u044c\u043a\u043e|\u0441\u043a\u043e\u043a\w*|\u043f\u043e\u043a\u0430\u0436|\u0434\u0430\u0439|\u0443\s+\u043d\u0430\u0441|\u043d\u0430\u0448\w*|\u043c\u044b\b|\u043a\u043e\u043c\u043f\u0430\u043d|\u0431\u0438\u0437\u043d\u0435\u0441|\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u0432\s+\u0446\u0435\u043b\u043e\u043c|\u0432\u043e\u043e\u0431\u0449\u0435|(?:19|20)\d{2}|all\s+time|what|which|how\s+much|show|give|company|business|organization|our|we|us)/iu.test(normalized);
|
||
return hasYearRankingCue || hasCompanyEarningsCue || hasCompanyProfitMarginCue;
|
||
}
|
||
function hasOrganizationLevelDebtDueDateOverviewSignal(text) {
|
||
const normalized = String(text ?? "");
|
||
if (!normalized) {
|
||
return false;
|
||
}
|
||
if (/(?:\u043a\u0442\u043e|\u043a\u043e\u043c\u0443|\u043a\u0430\u043a\u0438\u0435\s+(?:\u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b|\u043a\u043b\u0438\u0435\u043d\u0442|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442|\u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a|\u0434\u043e\u043b\u0436\u043d\u0438\u043a)|who\b|which\s+(?:customers|clients|counterparties|debtors))/iu.test(normalized)) {
|
||
return false;
|
||
}
|
||
const hasDueDateDebtCue = /(?:\u043f\u0440\u043e\u0441\u0440\u043e\u0447\w*|\u0441\u0440\u043e\u043a\w*\s+\u043e\u043f\u043b\u0430\u0442|\u0441\u0440\u043e\u043a\u0438\s+\u0434\u0430\u0432\u043d\u043e\s+\u043f\u0440\u043e\u0448|\u0434\u043e\u043b\u0433\w*\s+aging|\u043a\u0430\u0447\u0435\u0441\u0442\u0432\w*\s+\u0434\u043e\u043b\u0433|\u0434\u043e\u043b\u0433\w*\s+\u043a\u0430\u0447\u0435\u0441\u0442\u0432|due[-\s]?date|overdue|debt\s+aging|debt\s+quality|credit\s+risk)/iu.test(normalized);
|
||
const hasCompanyScopeCue = /(?:\u0443\s+\u043d\u0430\u0441|\u043d\u0430\u0448\w*|\u043f\u043e\s+\u043a\u043e\u043c\u043f\u0430\u043d|\u043a\u043e\u043c\u043f\u0430\u043d|\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u0431\u0438\u0437\u043d\u0435\u0441|\u0432\s+\u0446\u0435\u043b\u043e\u043c|\u043e\u0431\u0449\w*|\u043a\u0430\u043a\w*|\u043f\u043e\u043a\u0430\u0436|\u0434\u0430\u0439|\u0441\u0440\u0435\u0437|\u0430\u043d\u0430\u043b\u0438\u0437|(?:19|20)\d{2}|company|business|organization|overall|our|we|us|show|give|analysis)/iu.test(normalized);
|
||
return hasDueDateDebtCue && hasCompanyScopeCue;
|
||
}
|
||
function hasOrganizationLevelInventoryReserveLiquidationOverviewSignal(text) {
|
||
const normalized = String(text ?? "");
|
||
if (!normalized) {
|
||
return false;
|
||
}
|
||
if (/(?:\u043a\u0430\u043a\u0438\u0435\s+(?:\u0442\u043e\u0432\u0430\u0440|\u043d\u043e\u043c\u0435\u043d\u043a\u043b\u0430\u0442\u0443\u0440|\u043f\u043e\u0437\u0438\u0446)|\u0447\u0442\u043e\s+(?:\u043b\u0435\u0436\u0438\u0442|\u043d\u0430\s+\u0441\u043a\u043b\u0430\u0434)|which\s+(?:items|products|goods))/iu.test(normalized)) {
|
||
return false;
|
||
}
|
||
const hasInventoryQualityCue = /(?:\u043d\u0435\u043b\u0438\u043a\u0432\u0438\u0434\w*|\u0440\u0435\u0437\u0435\u0440\u0432\w*|\u0441\u043f\u0438\u0441\u0430\u043d\w*|\u043b\u0438\u043a\u0432\u0438\u0434\u0430\u0446\w*|\u0443\u0441\u0442\u0430\u0440\u0435\u0432\w*|\u043e\u0431\u0435\u0441\u0446\u0435\u043d\w*|obsolete|obsolescence|reserve|write[-\s]?off|liquidation|inventory\s+quality|stock\s+quality)/iu.test(normalized);
|
||
const hasInventoryScopeCue = /(?:\u0441\u043a\u043b\u0430\u0434|\u043e\u0441\u0442\u0430\u0442|\u0437\u0430\u043f\u0430\u0441|\u0442\u043e\u0432\u0430\u0440|\u043d\u043e\u043c\u0435\u043d\u043a\u043b\u0430\u0442\u0443\u0440|inventory|stock|warehouse)/iu.test(normalized);
|
||
const hasCompanyScopeCue = /(?:\u0443\s+\u043d\u0430\u0441|\u043d\u0430\u0448\w*|\u043f\u043e\s+\u043a\u043e\u043c\u043f\u0430\u043d|\u043a\u043e\u043c\u043f\u0430\u043d|\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u0431\u0438\u0437\u043d\u0435\u0441|\u0432\s+\u0446\u0435\u043b\u043e\u043c|\u043e\u0431\u0449\w*|\u0441\u043a\u043b\u0430\u0434|\u043e\u0441\u0442\u0430\u0442|\u0437\u0430\u043f\u0430\u0441|\u043a\u0430\u043a\w*|\u043f\u043e\u043a\u0430\u0436|\u0434\u0430\u0439|\u0441\u0440\u0435\u0437|\u0430\u043d\u0430\u043b\u0438\u0437|(?:19|20)\d{2}|company|business|organization|overall|warehouse|stock|inventory|our|we|us|show|give|analysis)/iu.test(normalized);
|
||
return hasInventoryQualityCue && hasInventoryScopeCue && hasCompanyScopeCue;
|
||
}
|
||
function hasOrganizationLevelSupplierQualityOverviewSignal(text) {
|
||
const normalized = String(text ?? "");
|
||
if (!normalized) {
|
||
return false;
|
||
}
|
||
if (/(?:\u0445\u0432\u043e\u0441\u0442|\u0434\u043e\u043b\u0433|\u0437\u0430\u0434\u043e\u043b\u0436|\u0441\u0430\u043b\u044c\u0434\u043e|\u043e\u043f\u043b\u0430\u0442|\u043f\u043b\u0430\u0442[\u0435\u0451]\u0436|\u0430\u043a\u0442|\u043f\u0440\u0438\u0445\u043e\u0434|\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\b60\b|open\s+items?|payable|payment|invoice|bill|settlement|reconciliation)/iu.test(normalized)) {
|
||
return false;
|
||
}
|
||
const hasSupplierScopeCue = /(?:\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a|\u0432\u0435\u043d\u0434\u043e\u0440|\u0437\u0430\u043a\u0443\u043f|\u0441\u043d\u0430\u0431\u0436|supplier|vendor|procurement|sourcing)/iu.test(normalized);
|
||
const hasSupplierQualityCue = /(?:\u0440\u0438\u0441\u043a\w*|\u043a\u0430\u0447\u0435\u0441\u0442\u0432\w*|\u043f\u0440\u043e\u0431\u043b\u0435\u043c\w*|\u0437\u0430\u0432\u0438\u0441\u0438\w*|\u0437\u0430\u0432\u044f\u0437\u0430\u043d\w*|\u043a\u043e\u043d\u0446\u0435\u043d\u0442\u0440\u0430\u0446\w*|\u043a\u043b\u044e\u0447\u0435\u0432\w*|\u043a\u0440\u0438\u0442\u0438\u0447\w*|risk|quality|problem|dependency|concentration|critical|key\s+supplier)/iu.test(normalized);
|
||
const hasCompanyScopeCue = /(?:\u0443\s+\u043d\u0430\u0441|\u043d\u0430\u0448\w*|\u043f\u043e\s+\u043a\u043e\u043c\u043f\u0430\u043d|\u043a\u043e\u043c\u043f\u0430\u043d|\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u0431\u0438\u0437\u043d\u0435\u0441|\u0432\s+\u0446\u0435\u043b\u043e\u043c|\u043e\u0431\u0449\w*|\u043a\u0430\u043a\w*|\u043f\u043e\u043a\u0430\u0436|\u0434\u0430\u0439|\u0441\u0440\u0435\u0437|\u0430\u043d\u0430\u043b\u0438\u0437|(?:19|20)\d{2}|company|business|organization|overall|our|we|us|show|give|analysis)/iu.test(normalized);
|
||
return hasSupplierScopeCue && hasSupplierQualityCue && hasCompanyScopeCue;
|
||
}
|
||
function hasOrganizationLevelMoneyBreakdownSignal(text) {
|
||
const normalized = String(text ?? "");
|
||
if (!normalized) {
|
||
return false;
|
||
}
|
||
const hasIncomingCue = /(?:\u043f\u043e\u043b\u0443\u0447|\u0432\u0445\u043e\u0434\u044f\u0449|\u043f\u043e\u0441\u0442\u0443\u043f|\u043a\u043b\u0438\u0435\u043d\u0442|received|incoming|customer)/iu.test(normalized);
|
||
const hasOutgoingCue = /(?:\u0437\u0430\u043f\u043b\u0430\u0442|\u0438\u0441\u0445\u043e\u0434\u044f\u0449|\u0441\u043f\u0438\u0441\u0430\u043d|\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a|paid|outgoing|supplier)/iu.test(normalized);
|
||
const hasNetCue = /(?:\u043d\u0435\u0442\u0442\u043e|\u0447\u0438\u0441\u0442\p{L}*\s+\u0434\u0435\u043d\u0435\u0436\u043d\p{L}*\s+\u043f\u043e\u0442\u043e\u043a|net\s+(?:cash|flow)|cash\s+flow)/iu.test(normalized);
|
||
const hasRankingCue = /(?:\u0433\u043b\u0430\u0432\u043d\p{L}*\s+(?:\u043a\u043b\u0438\u0435\u043d\u0442|\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a)|top\s+(?:customer|supplier))/iu.test(normalized);
|
||
const hasBreakdownCue = /(?:\u0440\u0430\u0441\u043a\u0440\u043e\p{L}*|\u043f\u043e\u0434\u0440\u043e\u0431\u043d|\u0441\u043a\u043e\u043b\u044c\u043a\u043e\s+\u0432\u0441\u0435\u0433\u043e|\u0441\u0432\u043e\u0434\p{L}*|breakdown|detail)/iu.test(normalized);
|
||
return hasBreakdownCue && hasIncomingCue && hasOutgoingCue && (hasNetCue || hasRankingCue);
|
||
}
|
||
function detectBroadBusinessEvaluation(text) {
|
||
const normalized = String(text ?? "");
|
||
if (!normalized) {
|
||
return null;
|
||
}
|
||
if (/(?:\u0431\u0438\u0437\u043d\u0435\u0441[-\s]?\u043e\u0431\u0437\u043e\u0440|\u0431\u0438\u0437\u043d\u0435\u0441[-\s]?\u0430\u0443\u0434\u0438\u0442|\u043f\u043e\u043b\u043d\w*\s+\u0430\u043d\u0430\u043b\u0438\u0437\s+(?:\u043a\u043e\u043c\u043f\u0430\u043d|\u0431\u0438\u0437\u043d\u0435\u0441|\u0434\u0435\u044f\u0442\u0435\u043b)|\u0441\u0432\u043e\u0434\u043d\w*\s+\u0430\u043d\u0430\u043b\u0438\u0437\s+(?:\u043a\u043e\u043c\u043f\u0430\u043d|\u0431\u0438\u0437\u043d\u0435\u0441|\u0434\u0435\u044f\u0442\u0435\u043b)|\u043a\u0430\u043a\s+\u0442\u044b\s+\u043e\u0446\u0435\u043d(?:\u0438\u0448\u044c|\u0438)\s+\u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442|\u043a\u043e\u043c\u043f\u0430\u043d(?:\u0438\u0438|\u0438\u044e|\u0438\u044f)\s+\u0432\s+\u0446\u0435\u043b\u043e\u043c|company\s+(?:analysis|overview)|business\s+(?:overview|audit)|llm[-\s]?audit|бизнес[-\s]?обзор|бизнес[-\s]?аудит)/iu.test(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
if (/(?:как\s+ты\s+оценишь\s+деятельност[ьи]\s+компан|оценк[аи]?\s+деятельност[ьи]\s+компан|оцени\s+(?:компан|бизнес|деятельност)|(?:полный|сводный|нормальн\w*|взросл\w*)\s+анализ\s+(?:компан|бизнес|деятельност)|проанализируй\s+(?:компан|бизнес|деятельност)|(?:что\s+думаешь|какое\s+мнение)\s+(?:о|по)\s+(?:компан|бизнес)|(?:llm[-\s]?)?аудит\s+(?:компан|бизнес)|что\s+у\s+нас\s+вообще\s+происход|где\s+главн(?:ые|ый)\s+риски|как\s+у\s+нас\s+дела\s+по\s+компан)/iu.test(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
if (hasOrganizationLevelEarningsOverviewSignal(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
if (hasOrganizationLevelDebtDueDateOverviewSignal(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
if (hasOrganizationLevelInventoryReserveLiquidationOverviewSignal(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
if (hasOrganizationLevelSupplierQualityOverviewSignal(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
if (hasOrganizationLevelMoneyBreakdownSignal(normalized)) {
|
||
return {
|
||
family: "broad_business_evaluation"
|
||
};
|
||
}
|
||
return null;
|
||
}
|
||
function buildEntityCandidates(counterpartyTurnover) {
|
||
if (!counterpartyTurnover?.entity) {
|
||
return [];
|
||
}
|
||
return [
|
||
{
|
||
type: "counterparty",
|
||
value: counterpartyTurnover.entity,
|
||
source: "current_turn_loose_entity_tail"
|
||
}
|
||
];
|
||
}
|
||
function createAssistantTurnMeaningPolicy(deps = {}) {
|
||
function resolveAssistantTurnMeaning(input = {}) {
|
||
const rawMessage = String(input?.rawUserMessage ?? input?.userMessage ?? "");
|
||
const effectiveMessage = String(input?.effectiveAddressUserMessage ?? rawMessage);
|
||
const rawText = normalizeTurnText(rawMessage, deps);
|
||
const effectiveText = normalizeTurnText(effectiveMessage, deps);
|
||
const joinedText = fallbackCompactWhitespace(`${rawText} ${effectiveText}`);
|
||
const supportedIntent = detectSupportedIntent(joinedText, deps);
|
||
const counterpartyTurnover = detectCounterpartyTurnoverFamily(joinedText);
|
||
const broadBusinessEvaluation = detectBroadBusinessEvaluation(joinedText);
|
||
const llmIntent = toNonEmptyString(input?.llmPreDecomposeMeta?.predecomposeContract?.intent, deps);
|
||
const explicitIntentCandidate = broadBusinessEvaluation?.family
|
||
? null
|
||
: supportedIntent?.intent ?? (llmIntent && llmIntent !== "unknown" ? llmIntent : null);
|
||
const unsupportedFamily = broadBusinessEvaluation?.family
|
||
? broadBusinessEvaluation.family
|
||
: !explicitIntentCandidate && counterpartyTurnover?.family
|
||
? counterpartyTurnover.family
|
||
: null;
|
||
const reasonCodes = [];
|
||
if (supportedIntent?.reason) {
|
||
reasonCodes.push(supportedIntent.reason);
|
||
}
|
||
if (counterpartyTurnover?.family) {
|
||
reasonCodes.push("counterparty_turnover_current_turn_signal");
|
||
}
|
||
if (broadBusinessEvaluation?.family) {
|
||
reasonCodes.push("broad_business_evaluation_current_turn_signal");
|
||
}
|
||
if (rawText !== normalizeTurnText(rawMessage, { ...deps, repairAddressMojibake: (value) => String(value ?? "") })) {
|
||
reasonCodes.push("mojibake_repair_applied");
|
||
}
|
||
if (rawText.includes("\u043d\u0430\u043c") &&
|
||
/(^|[^\p{L}0-9_])\u043d\u0430\u043c\u0441(?=$|[^\p{L}0-9_])/iu.test(String(rawMessage ?? ""))) {
|
||
reasonCodes.push("known_turn_typo_normalized");
|
||
}
|
||
const askedDomainFamily = explicitIntentCandidate?.startsWith("receivables_")
|
||
? "receivables"
|
||
: explicitIntentCandidate?.startsWith("payables_")
|
||
? "payables"
|
||
: explicitIntentCandidate?.startsWith("vat_")
|
||
? "vat"
|
||
: explicitIntentCandidate?.startsWith("inventory_")
|
||
? "inventory"
|
||
: broadBusinessEvaluation?.family
|
||
? "business_summary"
|
||
: explicitIntentCandidate?.includes("counterparty")
|
||
? "counterparty"
|
||
: counterpartyTurnover?.family
|
||
? "counterparty"
|
||
: null;
|
||
const askedActionFamily = explicitIntentCandidate === "receivables_confirmed_as_of_date" ||
|
||
explicitIntentCandidate === "payables_confirmed_as_of_date" ||
|
||
explicitIntentCandidate === "inventory_on_hand_as_of_date"
|
||
? "confirmed_snapshot"
|
||
: broadBusinessEvaluation?.family
|
||
? "broad_evaluation"
|
||
: explicitIntentCandidate === "vat_liability_confirmed_for_tax_period"
|
||
? "confirmed_tax_period"
|
||
: explicitIntentCandidate === "vat_payable_confirmed_as_of_date"
|
||
? "confirmed_snapshot"
|
||
: explicitIntentCandidate === "vat_payable_forecast"
|
||
? "forecast"
|
||
: explicitIntentCandidate === "list_documents_by_counterparty"
|
||
? "list_documents"
|
||
: counterpartyTurnover?.family
|
||
? "counterparty_value_or_turnover"
|
||
: null;
|
||
const staleReplayForbidden = Boolean(unsupportedFamily || broadBusinessEvaluation?.family || (counterpartyTurnover?.entity && !explicitIntentCandidate));
|
||
return {
|
||
schema_version: "assistant_turn_meaning_v1",
|
||
raw_message: rawMessage,
|
||
effective_message: effectiveMessage,
|
||
normalized_raw_message: rawText,
|
||
normalized_effective_message: effectiveText,
|
||
asked_domain_family: askedDomainFamily,
|
||
asked_action_family: askedActionFamily,
|
||
explicit_intent_candidate: explicitIntentCandidate,
|
||
explicit_entity_candidates: broadBusinessEvaluation?.family ? [] : buildEntityCandidates(counterpartyTurnover),
|
||
meaning_confidence: broadBusinessEvaluation?.family
|
||
? "medium"
|
||
: supportedIntent?.confidence ?? (counterpartyTurnover?.family ? "medium" : "low"),
|
||
intent_override_strength: explicitIntentCandidate
|
||
? "explicit_current_turn_intent"
|
||
: staleReplayForbidden
|
||
? "explicit_new_action_or_entity"
|
||
: "none",
|
||
carryover_budget: staleReplayForbidden ? "none" : explicitIntentCandidate ? "matching_family_only" : "normal",
|
||
unsupported_but_understood_family: unsupportedFamily,
|
||
stale_replay_forbidden: staleReplayForbidden,
|
||
reason_codes: reasonCodes
|
||
};
|
||
}
|
||
return {
|
||
resolveAssistantTurnMeaning
|
||
};
|
||
}
|