ДОМЕНЫ - ВОПРОСЫ - НДС: Исправить VAT follow-up контекст даты, кодировку data-scope probe и strict account scope для open-contract fallback

This commit is contained in:
2026-04-13 11:46:40 +03:00
parent fd159e13ac
commit 3e588ede81
7 changed files with 116 additions and 19 deletions
@@ -408,10 +408,14 @@ function hasFlexibleReceivablesDebtSignal(text: string): boolean {
if (!normalized) {
return false;
}
return (
/(?:кто(?:\s+\S+){0,4}\s+нам(?:\s+\S+){0,4}\s+долж)/iu.test(normalized) ||
/(?:нам(?:\s+\S+){0,4}\s+кто(?:\s+\S+){0,4}\s+долж)/iu.test(normalized)
);
const hasFlexibleWhoOwesUs =
/(?:\u043a\u0442\u043e(?:\s+\S+){0,4}\s+\u043d\u0430\u043c(?:\s+\S+){0,4}\s+\u0434\u043e\u043b\u0436)/iu.test(normalized) ||
/(?:\u043d\u0430\u043c(?:\s+\S+){0,4}\s+\u043a\u0442\u043e(?:\s+\S+){0,4}\s+\u0434\u043e\u043b\u0436)/iu.test(normalized);
const hasTorchatToUsSignal =
/(?:\u043d\u0430\u043c(?:\s+\S+){0,3}\s+\u0442\u043e\u0440\u0447(?:\u0430\u0442|\u0438\u0442)|\u0442\u043e\u0440\u0447(?:\u0430\u0442|\u0438\u0442)(?:\s+\S+){0,3}\s+\u043d\u0430\u043c)/iu.test(
normalized
);
return hasFlexibleWhoOwesUs || hasTorchatToUsSignal;
}
function hasFlexiblePayablesDebtSignal(text: string): boolean {
@@ -1526,7 +1526,13 @@ function enforceStrictAccountScopeForIntent(
plan: AddressRecipeExecutionPlan,
intent: AddressIntent
): AddressRecipeExecutionPlan {
if (intent !== "list_receivables_counterparties" || plan.account_scope_mode === "strict") {
const strictScopeIntents: AddressIntent[] = [
"list_receivables_counterparties",
"list_open_contracts",
"open_items_by_counterparty_or_contract"
];
const shouldEnforceStrictScope = strictScopeIntents.includes(intent);
if (!shouldEnforceStrictScope || plan.account_scope_mode === "strict") {
return plan;
}
return {
@@ -2829,7 +2835,8 @@ export class AddressQueryService {
plan.recipe.recipe_id === "address_movements_receivables_v1" ||
plan.recipe.recipe_id === "address_movements_payables_v1" ||
plan.recipe.recipe_id === "address_payables_confirmed_as_of_date_v1" ||
plan.recipe.recipe_id === "address_receivables_confirmed_as_of_date_v1";
plan.recipe.recipe_id === "address_receivables_confirmed_as_of_date_v1" ||
plan.recipe.recipe_id === "address_open_contracts_candidates_v1";
const missingSubcontoErrorDetected = Boolean(
mcp.error && missingSubcontoFallbackEligible && isMissingSubcontoFieldError(mcp.error)
);
@@ -53,7 +53,7 @@ function hasAllTimeHint(text: string): boolean {
}
function hasSameDateHint(text: string): boolean {
return /(?:на\s+ту\s+же\s+дат[ауеы]|на\s+эту\s+же\s+дат[ауеы]|та\s+же\s+дата|same\s+date|as\s+of\s+same\s+date|the\s+same\s+date)/iu.test(
return /(?:на\s+ту\s+же\s+дат[ауеы]|на\s+эту\s+же\s+дат[ауеы]|на\s+эту\s+дат[ауеы]|эту\s+дат[ауеы]|та\s+же\s+дата|same\s+date|as\s+of\s+same\s+date|the\s+same\s+date)/iu.test(
String(text ?? "")
);
}
@@ -651,7 +651,8 @@ function deriveIntentWithFollowupContext(
};
}
if (hasOpenItemsHint(normalizedMessage) && hasAnyPartyAnchor) {
const allowOpenItemsFollowupFallback = detectedIntent.intent === "unknown" && !isVatFollowup;
if (allowOpenItemsFollowupFallback && hasOpenItemsHint(normalizedMessage) && hasAnyPartyAnchor) {
return {
intent: "open_items_by_counterparty_or_contract",
confidence: "low",
@@ -5037,14 +5037,13 @@ async function resolveAssistantDataScopeProbe() {
};
}
const catalogQueryCandidates = [
"ВЫБРАТЬ ПЕРВЫЕ 20 ПРЕДСТАВЛЕН?Е(Организации.Ссылка) КАК Организация ?З Справочник.Организации КАК Организации",
"ВЫБРАТЬ ПЕРВЫЕ 20 Организации.Наименование КАК Организация ?З Справочник.Организации КАК Организации",
"ВЫБРАТЬ ПЕРВЫЕ 20 Организации.НаименованиеПолное КАК Организация ?З Справочник.Организации КАК Организации",
"ВЫБРАТЬ ПЕРВЫЕ 100 Организации.Ссылка КАК Организация, ПРЕДСТАВЛЕН?Е(Организации.Ссылка) КАК ОрганизацияПредставление ?З Справочник.Организации КАК Организации"
"ВЫБРАТЬ ПЕРВЫЕ 20 Организации.Наименование КАК Организация ИЗ Справочник.Организации КАК Организации",
"ВЫБРАТЬ ПЕРВЫЕ 20 Организации.НаименованиеПолное КАК Организация ИЗ Справочник.Организации КАК Организации",
"ВЫБРАТЬ ПЕРВЫЕ 100 Организации.Ссылка КАК Организация, ПРЕДСТАВЛЕНИЕ(Организации.Ссылка) КАК ОрганизацияПредставление ИЗ Справочник.Организации КАК Организации"
];
const movementProbeCandidates = [
"ВЫБРАТЬ ПЕРВЫЕ 60 Движения.Организация КАК Организация, ПРЕДСТАВЛЕН?Е(Движения.Организация) КАК ОрганизацияПредставление ?З РегистрБухгалтерии.Хозрасчетный КАК Движения УПОРЯДОЧ?ТЬ ПО Движения.Период УБЫВ",
"ВЫБРАТЬ ПЕРВЫЕ 60 Движения.Организация КАК Организация ?З РегистрБухгалтерии.Хозрасчетный КАК Движения"
"ВЫБРАТЬ ПЕРВЫЕ 60 Движения.Организация КАК Организация ИЗ РегистрБухгалтерии.Хозрасчетный КАК Движения УПОРЯДОЧИТЬ ПО Движения.Период УБЫВ",
"ВЫБРАТЬ ПЕРВЫЕ 60 Движения.Организация КАК Организация ИЗ РегистрБухгалтерии.Хозрасчетный КАК Движения"
];
let lastError = null;
const catalogFacts = { names: [], refs: [], pairs: [] };
@@ -5175,7 +5174,7 @@ function buildAssistantOperationalBoundaryReply() {
return [
"Понимаю, что ситуация срочная.",
"Я не могу сам настраивать 1С или менять базу/конфигурацию.",
"Могу помочь безопасно: разберем симптомы и подготовим точные шаги для вашего 1С/?Т-админа."
"Могу помочь безопасно: разберем симптомы и подготовим точные шаги для вашего 1С/ИТ-админа."
].join(" ");
}
function buildAssistantSafetyRefusalReply() {