Укрепить банковские границы денежных потоков phase97
This commit is contained in:
@@ -13,6 +13,24 @@ const ACCOUNT_REVERSE_PATTERN = /(?:^|[\s,.;:!?()\-])(\d{2}(?:[.,]\d{1,2})?)(?=\
|
||||
const LIMIT_PATTERN = /(?:\btop\b|\blimit\b|первые|топ)[\s\-–—_:№#]*?(\d{1,3})/iu;
|
||||
const VALUE_ANALYTICS_SAMPLE_LIMIT = 1000;
|
||||
const COUNTERPARTY_PATTERN = /(?:по\s+контрагенту|контрагент(?:у|а)?|по\s+контре|контра|по\s+компан(?:ии|ию|ия)|компан(?:ия|ии|ию)|по\s+организац(?:ии|ию|ия)|организац(?:ия|ии|ию)|по\s+поставщик(?:у|а)?|поставщик(?:у|а)?|по\s+клиент(?:у|а)?|клиент(?:у|а)?|по\s+покупател(?:ю|я)|покупател(?:ю|я)|по\s+партнер(?:у|а)?|партнер(?:у|а)?|by\s+counterparty|counterparty|by\s+company|company|by\s+supplier|supplier|by\s+vendor|vendor|by\s+customer|customer|by\s+client|client|by\s+partner|partner)\s+([^\r\n,.;:]+)/iu;
|
||||
const KNOWN_FINANCIAL_COUNTERPARTY_ANCHORS = [
|
||||
{
|
||||
pattern: /(?<![\p{L}\p{N}])(?:\u043f\u0430\u043e\s+|\u0430\u043e\s+)?\u0441\u0431\u0435\u0440\u0431\u0430\u043d\u043a(?:\s*,?\s*(?:\u043f\u0430\u043e|\u0430\u043e))?(?![\p{L}\p{N}])/iu,
|
||||
value: "\u0421\u0411\u0415\u0420\u0411\u0410\u041d\u041a"
|
||||
},
|
||||
{
|
||||
pattern: /(?<![\p{L}\p{N}])(?:\u0431\u0430\u043d\u043a\s+)?\u0432\u0442\u0431(?![\p{L}\p{N}])/iu,
|
||||
value: "\u0412\u0422\u0411"
|
||||
},
|
||||
{
|
||||
pattern: /(?<![\p{L}\p{N}])\u0430\u043b\u044c\u0444\u0430[-\s]?\u0431\u0430\u043d\u043a(?![\p{L}\p{N}])/iu,
|
||||
value: "\u0410\u041b\u042c\u0424\u0410-\u0411\u0410\u041d\u041a"
|
||||
},
|
||||
{
|
||||
pattern: /(?<![\p{L}\p{N}])(?:\u0442\u0438\u043d\u044c\u043a\u043e\u0444\u0444|\u0442[-\s]?\u0431\u0430\u043d\u043a)(?![\p{L}\p{N}])/iu,
|
||||
value: "\u0422-\u0411\u0410\u041d\u041a"
|
||||
}
|
||||
];
|
||||
const CONTRACT_PATTERN = /(?:по\s+(?:договору|контракту)|(?:договор|контракт)(?:у|а)?\s*(?:№|#|n)?|by\s+contract|contract(?:\s*(?:no|number|#|n))?)\s+([^\r\n,.;:]+)/i;
|
||||
const DATE_DMY_PATTERN = /\b(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{2,4})\b/;
|
||||
const DATE_YMD_PATTERN = /\b(20\d{2})[.\/-](\d{1,2})[.\/-](\d{1,2})\b/;
|
||||
@@ -608,6 +626,18 @@ function isLikelyCounterpartyToken(rawToken) {
|
||||
}
|
||||
return !isCounterpartyNoiseToken(lowered);
|
||||
}
|
||||
function extractKnownFinancialCounterpartyAnchor(text) {
|
||||
const source = String(text ?? "");
|
||||
if (!source.trim()) {
|
||||
return undefined;
|
||||
}
|
||||
for (const anchor of KNOWN_FINANCIAL_COUNTERPARTY_ANCHORS) {
|
||||
if (anchor.pattern.test(source)) {
|
||||
return anchor.value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function isLowQualityCounterpartyAnchorValue(rawValue) {
|
||||
const value = String(rawValue ?? "")
|
||||
.trim()
|
||||
@@ -619,6 +649,9 @@ function isLowQualityCounterpartyAnchorValue(rawValue) {
|
||||
if (/(?:за\s+вс[её]\s+время|за\s+всю\s+истори(?:ю|и)|all\s+time|entire\s+period|full\s+history)/iu.test(value)) {
|
||||
return true;
|
||||
}
|
||||
if (/^(?:или|это|там|может|можно|обычн\p{L}*|клиентск\p{L}*|банковск\p{L}*(?:\/|\s+и\s+)?финансов\p{L}*)\b/iu.test(value)) {
|
||||
return true;
|
||||
}
|
||||
const tokens = value
|
||||
.split(/[^a-zа-я0-9]+/iu)
|
||||
.map((token) => token.trim())
|
||||
@@ -1495,6 +1528,13 @@ function shouldExpandSampleForValueAnalytics(intent) {
|
||||
intent === "supplier_payouts_profile" ||
|
||||
intent === "contract_usage_and_value");
|
||||
}
|
||||
function shouldPreferKnownFinancialCounterpartyAnchor(intent) {
|
||||
return (intent === "bank_operations_by_counterparty" ||
|
||||
intent === "customer_revenue_and_payments" ||
|
||||
intent === "supplier_payouts_profile" ||
|
||||
intent === "list_documents_by_counterparty" ||
|
||||
intent === "list_contracts_by_counterparty");
|
||||
}
|
||||
function extractAddressFilters(userMessage, intent) {
|
||||
const rawText = String(userMessage ?? "").trim();
|
||||
const text = normalizeMojibakeString(rawText);
|
||||
@@ -1573,6 +1613,13 @@ function extractAddressFilters(userMessage, intent) {
|
||||
}
|
||||
}
|
||||
const allowGenericCounterpartyAnchor = !isInventoryTraceIntent(intent);
|
||||
const knownFinancialCounterparty = allowGenericCounterpartyAnchor && shouldPreferKnownFinancialCounterpartyAnchor(intent)
|
||||
? extractKnownFinancialCounterpartyAnchor(text)
|
||||
: undefined;
|
||||
if (knownFinancialCounterparty && !filters.counterparty) {
|
||||
filters.counterparty = knownFinancialCounterparty;
|
||||
warnings.push("counterparty_anchor_derived_from_known_financial_name");
|
||||
}
|
||||
const counterpartyMatch = allowGenericCounterpartyAnchor ? text.match(COUNTERPARTY_PATTERN) : null;
|
||||
if (counterpartyMatch && !filters.counterparty) {
|
||||
filters.counterparty = cleanupAnchorValue(String(counterpartyMatch[1]));
|
||||
|
||||
@@ -1658,9 +1658,9 @@ function hasBidirectionalValueFlowComparisonSignal(text) {
|
||||
return false;
|
||||
}
|
||||
const hasIncomingCue = /(?:\u0432\u0445\u043e\u0434\u044f\u0449|\u043f\u043e\u0441\u0442\u0443\u043f|\u043f\u043e\u043b\u0443\u0447|inflow|incoming)/iu.test(normalized);
|
||||
const hasOutgoingCue = /(?:\u0438\u0441\u0445\u043e\u0434\u044f\u0449|\u0441\u043f\u0438\u0441\u0430\u043d|\u0437\u0430\u043f\u043b\u0430\u0442|\u043f\u043b\u0430\u0442\u0438\u043b|\u043e\u043f\u043b\u0430\u0442|outflow|outgoing|payout)/iu.test(normalized);
|
||||
const hasOutgoingCue = /(?:\u0438\u0441\u0445\u043e\u0434\u044f\u0449|\u0441\u043f\u0438\u0441\u0430\u043d|\u0437\u0430\u043f\u043b\u0430\u0442|\u043f\u043b\u0430\u0442\u0438\u043b|\u0432\u044b\u043f\u043b\u0430\u0442|\u0432\u044b\u043f\u043b\u0430\u0447|\u0443\u043f\u043b\u0430\u0442|\u043e\u043f\u043b\u0430\u0442|outflow|outgoing|payout|paid)/iu.test(normalized);
|
||||
const hasComparisonCue = /(?:\u0431\u043e\u043b\u044c\u0448|\u043c\u0435\u043d\u044c\u0448|\u0441\u0440\u0430\u0432|\u0438\u043b\u0438|\u043d\u0435\u0442\u0442\u043e|\u0441\u0430\u043b\u044c\u0434\u043e|vs|versus)/iu.test(normalized);
|
||||
const hasValueFlowCue = /(?:\u0434\u0435\u043d\u044c\u0433|\u0434\u0435\u043d\u0435\u0433|\u0434\u0435\u043d\u0435\u0436|\u043f\u043e\u0442\u043e\u043a|\u043e\u0431\u043e\u0440\u043e\u0442|money|cash|flow)/iu.test(normalized);
|
||||
const hasValueFlowCue = /(?:\u0434\u0435\u043d\u044c\u0433|\u0434\u0435\u043d\u0435\u0433|\u0434\u0435\u043d\u0435\u0436|\u0441\u0440\u0435\u0434\u0441\u0442\u0432|\u043f\u043e\u0442\u043e\u043a|\u043e\u0431\u043e\u0440\u043e\u0442|money|cash|funds|flow)/iu.test(normalized);
|
||||
const hasNetAmountCue = /(?:сколько|сумм|итог|нетто|сальдо|минус|net|total|sum)/iu.test(normalized);
|
||||
return hasIncomingCue && hasOutgoingCue && hasComparisonCue && (hasValueFlowCue || hasNetAmountCue);
|
||||
}
|
||||
|
||||
@@ -1189,6 +1189,9 @@ function toNormalizedRows(rows) {
|
||||
const organization = firstNonEmptyString(row.Организация, row.Organization, row.organization, row.organization_name, row.ОрганизацияПредставление);
|
||||
const counterparty = firstNonEmptyString(row.Контрагент, row.Counterparty, row.counterparty);
|
||||
const contract = firstNonEmptyString(row.Договор, row.Contract, row.contract);
|
||||
const operationKind = firstNonEmptyString(row.ВидОперации, row.OperationKind, row.operation_kind, row.operationType);
|
||||
const paymentPurpose = firstNonEmptyString(row.НазначениеПлатежа, row.PaymentPurpose, row.payment_purpose, row.paymentPurpose);
|
||||
const comment = firstNonEmptyString(row.Комментарий, row.Comment, row.comment);
|
||||
const analytics = collectAnalyticsStrings(row);
|
||||
return {
|
||||
period,
|
||||
@@ -1202,7 +1205,10 @@ function toNormalizedRows(rows) {
|
||||
warehouse,
|
||||
organization,
|
||||
counterparty,
|
||||
contract
|
||||
contract,
|
||||
operation_kind: operationKind,
|
||||
payment_purpose: paymentPurpose,
|
||||
comment
|
||||
};
|
||||
})
|
||||
.filter((item) => Boolean(item.period || item.registrator));
|
||||
|
||||
@@ -277,6 +277,77 @@ function isDirectBalanceQuestion(userMessage) {
|
||||
}
|
||||
return /(?:кто|кому|сколько|какой|какая|какие|есть\s+ли|долж|дебитор|кредитор|payables?|receivables?|who|how\s+much)/iu.test(text);
|
||||
}
|
||||
function hasBankIncomingRoleBoundaryQuestion(userMessage) {
|
||||
const text = normalizeQuestionText(userMessage);
|
||||
return (/(?:входящ|поступлен|клиентск|выручк|кредит|депозит|возврат)/iu.test(text) &&
|
||||
/(?:банк|сбербанк|финанс)/iu.test(text));
|
||||
}
|
||||
function hasBankOutgoingRoleBoundaryQuestion(userMessage) {
|
||||
const text = normalizeQuestionText(userMessage);
|
||||
return (/(?:исходящ|списан|платеж|поставщик|закуп|выплат)/iu.test(text) &&
|
||||
/(?:банк|сбербанк|финанс)/iu.test(text));
|
||||
}
|
||||
function bankOperationDirection(row) {
|
||||
const text = normalizeQuestionText(`${row.registrator} ${row.operation_kind ?? ""}`);
|
||||
if (/(?:поступлени[ея]\s+на\s+расчетн|bank\s+receipt|incoming)/iu.test(text)) {
|
||||
return "incoming";
|
||||
}
|
||||
if (/(?:списани[ея]\s+с\s+расчетн|bank\s+payment|outgoing|write[-\s]?off)/iu.test(text)) {
|
||||
return "outgoing";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
function bankOperationDirectionLabel(direction) {
|
||||
if (direction === "incoming") {
|
||||
return "входящее поступление";
|
||||
}
|
||||
if (direction === "outgoing") {
|
||||
return "исходящее списание";
|
||||
}
|
||||
return "банковская операция без надежно распознанного направления";
|
||||
}
|
||||
function bankOperationEvidenceLine(rows) {
|
||||
const sample = rows[0];
|
||||
if (!sample) {
|
||||
return "Проверенная строка 1С не найдена.";
|
||||
}
|
||||
const direction = bankOperationDirection(sample);
|
||||
const parts = [`тип по документу: ${bankOperationDirectionLabel(direction)}`];
|
||||
const operationKind = String(sample.operation_kind ?? "").trim();
|
||||
const paymentPurpose = String(sample.payment_purpose ?? "").trim();
|
||||
const contract = String(sample.contract ?? "").trim();
|
||||
if (operationKind) {
|
||||
parts.push(`вид операции: ${operationKind}`);
|
||||
}
|
||||
if (paymentPurpose) {
|
||||
parts.push(`назначение платежа: ${paymentPurpose}`);
|
||||
}
|
||||
if (contract) {
|
||||
parts.push(`договор: ${contract}`);
|
||||
}
|
||||
if (!operationKind && !paymentPurpose && !contract) {
|
||||
parts.push("вид операции/назначение платежа/договор в материализованной строке не заполнены");
|
||||
}
|
||||
return `Основание 1С: ${parts.join("; ")}.`;
|
||||
}
|
||||
function bankRoleBoundaryLine(userMessage, rows) {
|
||||
const incomingBoundary = hasBankIncomingRoleBoundaryQuestion(userMessage);
|
||||
const outgoingBoundary = hasBankOutgoingRoleBoundaryQuestion(userMessage);
|
||||
if (!incomingBoundary && !outgoingBoundary) {
|
||||
return null;
|
||||
}
|
||||
const directions = rows.map(bankOperationDirection);
|
||||
const hasIncomingRow = directions.includes("incoming");
|
||||
const hasOutgoingRow = directions.includes("outgoing");
|
||||
if (incomingBoundary) {
|
||||
return hasIncomingRow
|
||||
? "Выручкой от обычного клиента это не называю автоматически: для банка/финорганизации нужен вид операции, назначение платежа и договор; кредитный, депозитный или возвратный смысл без этих полей не исключаю и не притягиваю."
|
||||
: hasOutgoingRow
|
||||
? "В найденных строках по банку подтверждено исходящее списание, а входящее поступление от банка в этом срезе не подтверждено; клиентскую выручку, кредит или депозит по этой строке не доказываю."
|
||||
: "Входящее поступление от банка в найденных строках не подтверждено; клиентскую выручку, кредитный или депозитный смысл без вида операции/назначения платежа не доказываю.";
|
||||
}
|
||||
return "Обычным поставщиком это не называю автоматически: для банка/финорганизации нужен вид операции, назначение платежа и договор; текущий срез подтверждает банковский платежный контур, а не бизнес-роль поставщика.";
|
||||
}
|
||||
function hasInventoryPurchaseDateActionFocus(userMessage) {
|
||||
const text = normalizeQuestionText(userMessage);
|
||||
if (!text) {
|
||||
@@ -3820,9 +3891,15 @@ function composeFactualReplyBody(intent, rows, options = {}) {
|
||||
};
|
||||
}
|
||||
if (intent === "bank_operations_by_counterparty") {
|
||||
const rowCounterparties = uniqueStrings(rows
|
||||
.map((row) => extractCounterpartyName(row))
|
||||
.filter((item) => Boolean(item)));
|
||||
const counterparty = resolvePreferredCounterpartyDisplayLabel(options.counterpartyHint, rowCounterparties);
|
||||
const roleBoundary = bankRoleBoundaryLine(options.userMessage, rows);
|
||||
const lines = [
|
||||
`Коротко: найдено банковских операций по контрагенту — ${rows.length}.`,
|
||||
"Показываю подтвержденные банковские операции из текущего среза.",
|
||||
`Коротко: найдено банковских операций${counterparty ? ` по ${counterparty}` : " по контрагенту"} — ${rows.length}.`,
|
||||
roleBoundary ?? "Показываю подтвержденные банковские операции из текущего среза.",
|
||||
bankOperationEvidenceLine(rows),
|
||||
...formatTopRows(rows, rows.length)
|
||||
];
|
||||
return {
|
||||
|
||||
+30
-1
@@ -17,6 +17,23 @@ function toNonEmptyString(value) {
|
||||
const text = String(value).trim();
|
||||
return text.length > 0 ? text : null;
|
||||
}
|
||||
function normalizeQuestionText(value) {
|
||||
return String(value ?? "")
|
||||
.toLowerCase()
|
||||
.replace(/ё/g, "е")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
function requestsFinancialCounterpartyBoundary(turnMeaning, graph) {
|
||||
const text = normalizeQuestionText([
|
||||
turnMeaning?.raw_message,
|
||||
turnMeaning?.effective_message,
|
||||
graph?.source_message,
|
||||
graph?.question
|
||||
].join(" "));
|
||||
return (/(?:банк|сбербанк|финанс|кредит|депозит)/iu.test(text) &&
|
||||
/(?:клиент|поставщик|выручк|топ|обычн|роль|поток)/iu.test(text));
|
||||
}
|
||||
function toStringList(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
@@ -693,6 +710,12 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||
: `; крупнейший получатель исходящих денег: ${topSupplier}`
|
||||
: "";
|
||||
const roleBoundaryLead = topCustomer || topSupplier ? "; клиент/поставщик как бизнес-роли этим денежным срезом не подтверждены" : "";
|
||||
const financialBoundaryRequested = requestsFinancialCounterpartyBoundary(turnMeaning, graph);
|
||||
const requestedFinancialBoundaryLine = financialBoundaryRequested
|
||||
? topCustomerLooksFinancial || topSupplierLooksFinancial
|
||||
? "Отдельно по банкам: если денежный топ ведет банк/финансовая организация, это нельзя автоматически читать как обычного клиента или поставщика; нужны назначение платежа, вид операции и договор. Поэтому такой поток не является доказанной клиентской выручкой, обычной поставкой или чистой прибылью без отдельной проверки."
|
||||
: "Отдельно по банкам: банк/финансовую организацию в денежных топах нельзя автоматически читать как обычного клиента или поставщика; нужны назначение платежа, вид операции и договор. Поэтому такой поток не является доказанной клиентской выручкой, обычной поставкой или чистой прибылью без отдельной проверки."
|
||||
: null;
|
||||
const graphReasonCodes = toStringList(graph?.reason_codes);
|
||||
const directMoneyAnswer = graphReasonCodes.includes("data_need_graph_business_overview_direct_money_answer");
|
||||
const crossScopeExecutiveSummary = Boolean(separateSubject && previousCounterpartySummary);
|
||||
@@ -901,7 +924,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||
if (!leaderYear || !leaderAmount) {
|
||||
return null;
|
||||
}
|
||||
lines.push(`Коротко: в доступном проверенном срезе 1С по входящим денежным строкам лидирует ${leaderYear}: ${leaderAmount}${Number.isFinite(leaderRows) && leaderRows > 0 ? ` по ${leaderRows} строкам с суммой` : ""}; это не полный бухгалтерский рейтинг доходности.`);
|
||||
lines.push(`Коротко: ${organizationPrefix}в доступном проверенном срезе 1С по входящим денежным строкам лидирует ${leaderYear}: ${leaderAmount}${Number.isFinite(leaderRows) && leaderRows > 0 ? ` по ${leaderRows} строкам с суммой` : ""}; это не полный бухгалтерский рейтинг доходности.`);
|
||||
const netYear = toNonEmptyString(netLeader?.year_bucket);
|
||||
const netYearAmount = moneyText(netLeader?.net_amount_human_ru);
|
||||
if (netYear && netYearAmount) {
|
||||
@@ -912,6 +935,9 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||
if (incomingAmount && outgoingAmount && netAmount) {
|
||||
lines.push(`Сверка по окну: входящие ${incomingAmount}, исходящие ${outgoingAmount}, ${netDirection} ${sentenceAmount(netAmount) ?? netAmount}.`);
|
||||
}
|
||||
if (requestedFinancialBoundaryLine) {
|
||||
lines.push(requestedFinancialBoundaryLine);
|
||||
}
|
||||
const yearRows = businessOverviewYearRowsLine(overview);
|
||||
if (yearRows) {
|
||||
lines.push(yearRows);
|
||||
@@ -925,6 +951,9 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||
? `Крупнейший входящий денежный источник в этом срезе: ${customerName} — ${sentenceAmount(customerAmount) ?? customerAmount}. По названию это банк/финансовая организация, поэтому без назначения платежа не называю это клиентской выручкой.${nonFinancialCustomer ? ` Крупнейший небанковский входящий контрагент: ${nonFinancialCustomer}.` : ""}`
|
||||
: `Крупнейший подтвержденный источник входящих денег в этом срезе: ${customerName} — ${sentenceAmount(customerAmount) ?? customerAmount}.`);
|
||||
}
|
||||
if (requestedFinancialBoundaryLine) {
|
||||
lines.push(requestedFinancialBoundaryLine);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
||||
+14
@@ -705,12 +705,18 @@ function hasCrossScopeExecutiveSummarySignal(text) {
|
||||
/(?:\u043e\u0442\u0434\u0435\u043b\u044c\u043d\p{L}*\s+\u043f\u043e|\u043f\u043e\s+\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442\p{L}*|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442\p{L}*|\u0433\u0440\u0443\u043f\u043f\p{L}*\s+\u0441\u0432\u043a|\u0441\u0432\u043a|counterpart(?:y|ies)?)/iu.test(text) &&
|
||||
/(?:\u0447\u0442\u043e\s+\u043c\u043e\u0436\u043d\p{L}*|\u0447\u0442\u043e\s+\u043d\u0435\u043b\u044c\u0437\p{L}*|\u0432\u044b\u0432\u043e\u0434\p{L}*|allowed|forbidden|cannot|can\s+say)/iu.test(text));
|
||||
}
|
||||
function hasPlainBusinessOverviewSignal(text) {
|
||||
const hasPlainOverviewCue = /(?:\u0432\u0437\u0440\u043e\u0441\u043b\p{L}*[\s\S]{0,40}\u043e\u0431\u0437\u043e\u0440|\u043a\u0440\u0430\u0442\u043a\p{L}*\s+\u043e\u0431\u0437\u043e\u0440|\u043e\u0431\u0437\u043e\u0440[\s\S]{0,100}(?:\u0432\u0445\u043e\u0434\u044f\u0449|\u0438\u0441\u0445\u043e\u0434\u044f\u0449|\u043d\u0435\u0442\u0442\u043e|incoming|outgoing|net))/iu.test(text);
|
||||
const hasCompanyOrOperatingScopeCue = /(?:\u043e\u043e\u043e|\u0438\u043f|\u0430\u043e|\u043f\u0430\u043e|\u043a\u043e\u043c\u043f\u0430\u043d|\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446|\u0431\u0438\u0437\u043d\u0435\u0441|\u0443\s+\u043d\u0430\u0441|\u043d\u0430\u0448\p{L}*|(?:19|20)\d{2}|company|organization|business)/iu.test(text);
|
||||
return hasPlainOverviewCue && hasCompanyOrOperatingScopeCue;
|
||||
}
|
||||
function hasBusinessOverviewSignal(text) {
|
||||
if (hasCrossScopeExecutiveSummarySignal(text) ||
|
||||
hasOrganizationLevelEarningsOverviewSignal(text) ||
|
||||
hasOrganizationLevelDebtPositionOverviewSignal(text) ||
|
||||
hasOrganizationLevelDebtDueDateOverviewSignal(text) ||
|
||||
hasOrganizationLevelInventoryReserveLiquidationOverviewSignal(text) ||
|
||||
hasPlainBusinessOverviewSignal(text) ||
|
||||
hasOrganizationLevelSupplierQualityOverviewSignal(text)) {
|
||||
return true;
|
||||
}
|
||||
@@ -1786,6 +1792,8 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
||||
normalizedFollowupDateScope);
|
||||
const clarificationLoopSeedApplied = Boolean(followupSeed.loopStatus === "awaiting_clarification" && followupSeed.loopSelectedChainId);
|
||||
const turnMeaning = {
|
||||
raw_message: repairedUserText ?? rawUserText ?? null,
|
||||
effective_message: repairedEffectiveText ?? rawEffectiveText ?? null,
|
||||
asked_domain_family: businessOverviewSignal
|
||||
? "business_overview"
|
||||
: lifecycleSignal
|
||||
@@ -1882,6 +1890,12 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
||||
followupDiscoverySeedApplicable)
|
||||
};
|
||||
const cleanTurnMeaning = {};
|
||||
if (toNonEmptyString(turnMeaning.raw_message)) {
|
||||
cleanTurnMeaning.raw_message = turnMeaning.raw_message;
|
||||
}
|
||||
if (toNonEmptyString(turnMeaning.effective_message)) {
|
||||
cleanTurnMeaning.effective_message = turnMeaning.effective_message;
|
||||
}
|
||||
if (toNonEmptyString(turnMeaning.asked_domain_family)) {
|
||||
cleanTurnMeaning.asked_domain_family = turnMeaning.asked_domain_family;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user