Очистить память ассистента от ролевых фрагментов контрагентов
This commit is contained in:
@@ -5,6 +5,7 @@ exports.cloneAddressNavigationState = cloneAddressNavigationState;
|
||||
exports.normalizeAddressNavigationState = normalizeAddressNavigationState;
|
||||
exports.evolveAddressNavigationStateWithAssistantItem = evolveAddressNavigationStateWithAssistantItem;
|
||||
const nanoid_1 = require("nanoid");
|
||||
const addressTextRepair_1 = require("./addressTextRepair");
|
||||
const assistantContinuityPolicy_1 = require("./assistantContinuityPolicy");
|
||||
const addressNavigation_1 = require("../types/addressNavigation");
|
||||
const MAX_RESULT_SETS = 40;
|
||||
@@ -295,6 +296,32 @@ function normalizeFilters(value) {
|
||||
}
|
||||
return { ...record };
|
||||
}
|
||||
function isBusinessOverviewRoleCounterpartyFragment(value) {
|
||||
const text = (0, addressTextRepair_1.normalizeRussianComparableText)(value);
|
||||
if (!text) {
|
||||
return false;
|
||||
}
|
||||
const hasRoleWord = /(?:^|\s)(?:клиент|поставщик|контрагент|получатель|источник|покупатель|заказчик)(?:\s|$)/u.test(text);
|
||||
if (!hasRoleWord) {
|
||||
return false;
|
||||
}
|
||||
const hasRankingWord = /(?:^|\s)(?:главн[а-яёa-z0-9_-]*|крупнейш[а-яёa-z0-9_-]*|основн[а-яёa-z0-9_-]*|топ(?:-\d+)?)(?:\s|$)/u.test(text);
|
||||
const hasRoleOnlyExplanation = /(?:^|\s)(?:клиент|поставщик)(?:\s|$).{0,40}(?:^|\s)как(?:\s|$).{0,30}(?:^|\s)рол/u.test(text);
|
||||
const endsWithDanglingPreposition = /(?:^|\s)(?:в|за|по|на|от|для|к)$/u.test(text);
|
||||
return hasRoleOnlyExplanation || (hasRankingWord && (endsWithDanglingPreposition || text.length <= 48));
|
||||
}
|
||||
function shouldSuppressBusinessOverviewCounterpartyFocus(debug, counterparty) {
|
||||
return (toNonEmptyString(debug.mcp_discovery_selected_chain_id) === "business_overview" &&
|
||||
debug.mcp_discovery_response_applied === true &&
|
||||
isBusinessOverviewRoleCounterpartyFragment(counterparty));
|
||||
}
|
||||
function sanitizeBusinessOverviewNavigationFilters(filters, debug) {
|
||||
if (!shouldSuppressBusinessOverviewCounterpartyFocus(debug, filters.counterparty)) {
|
||||
return filters;
|
||||
}
|
||||
const { counterparty: _counterparty, ...rest } = filters;
|
||||
return rest;
|
||||
}
|
||||
function resolveNavigationAction(debug, hasFocusObject) {
|
||||
const continuationContract = toObject(debug.dialog_continuation_contract_v2);
|
||||
const decision = toNonEmptyString(continuationContract?.decision);
|
||||
@@ -361,7 +388,7 @@ function buildFocusObjectFromDebug(debug, resultSetId, createdAt) {
|
||||
const selectedDiscoveryChain = toNonEmptyString(debug.mcp_discovery_selected_chain_id);
|
||||
if (selectedDiscoveryChain === "business_overview" && debug.mcp_discovery_response_applied === true) {
|
||||
const counterparty = (0, assistantContinuityPolicy_1.readAddressDebugCounterparty)(debug, toNonEmptyString) ?? readNavigationDiscoveryCounterparty(debug);
|
||||
if (counterparty) {
|
||||
if (counterparty && !shouldSuppressBusinessOverviewCounterpartyFocus(debug, counterparty)) {
|
||||
return buildFocusObject("counterparty", counterparty, resultSetId, createdAt);
|
||||
}
|
||||
const organization = (0, assistantContinuityPolicy_1.readAddressDebugOrganization)(debug, toNonEmptyString);
|
||||
@@ -574,7 +601,7 @@ function evolveAddressNavigationStateWithAssistantItem(state, item, turnIndex) {
|
||||
const createdAt = toNonEmptyString(item.created_at) ?? new Date().toISOString();
|
||||
const resultSetId = `rs-${item.message_id}`;
|
||||
const routeId = toNonEmptyString(debug.selected_recipe) ?? selectedDiscoveryChain;
|
||||
const filters = normalizeFilters(debug.extracted_filters);
|
||||
const filters = sanitizeBusinessOverviewNavigationFilters(normalizeFilters(debug.extracted_filters), debug);
|
||||
const derivedOrganizationScope = resolveDerivedOrganizationScope(debug, filters, item.text) ?? (0, assistantContinuityPolicy_1.readAddressDebugOrganization)(debug, toNonEmptyString);
|
||||
const derivedCounterpartyScope = selectedDiscoveryChain === "value_flow_comparison" && debug.mcp_discovery_response_applied === true
|
||||
? (0, assistantContinuityPolicy_1.readAddressDebugCounterparty)(debug, toNonEmptyString) ?? readNavigationDiscoveryCounterparty(debug)
|
||||
@@ -610,9 +637,12 @@ function evolveAddressNavigationStateWithAssistantItem(state, item, turnIndex) {
|
||||
const debugFocusObject = buildFocusObjectFromDebug(debug, resultSetId, createdAt);
|
||||
const primaryEntityFocusObject = buildFocusObjectFromPrimaryEntityRef(resultSet, createdAt);
|
||||
const focusObject = resolveFocusObjectForNavigation(state, intent, resultSet, debugFocusObject, primaryEntityFocusObject);
|
||||
const comparisonCounterparty = selectedDiscoveryChain === "business_overview" && debug.mcp_discovery_response_applied === true
|
||||
const rawComparisonCounterparty = selectedDiscoveryChain === "business_overview" && debug.mcp_discovery_response_applied === true
|
||||
? readNavigationDiscoveryCounterparty(debug)
|
||||
: null;
|
||||
const comparisonCounterparty = rawComparisonCounterparty && !shouldSuppressBusinessOverviewCounterpartyFocus(debug, rawComparisonCounterparty)
|
||||
? rawComparisonCounterparty
|
||||
: null;
|
||||
const comparisonOrganization = selectedDiscoveryChain === "business_overview" && debug.mcp_discovery_response_applied === true
|
||||
? derivedOrganizationScope ?? toNonEmptyString(filtersWithDerivedScope.organization)
|
||||
: null;
|
||||
|
||||
@@ -411,11 +411,25 @@ function isReferentialCounterpartyPlaceholder(value) {
|
||||
}
|
||||
function normalizeCounterpartyCandidate(value, toNonEmptyString) {
|
||||
const text = toNonEmptyString(value);
|
||||
if (!text || isReferentialCounterpartyPlaceholder(text)) {
|
||||
if (!text || isReferentialCounterpartyPlaceholder(text) || isCounterpartyRoleFragment(text)) {
|
||||
return null;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
function isCounterpartyRoleFragment(value) {
|
||||
const text = (0, addressTextRepair_1.normalizeRussianComparableText)(value);
|
||||
if (!text) {
|
||||
return false;
|
||||
}
|
||||
const hasRoleWord = /(?:^|\s)(?:клиент|поставщик|контрагент|получатель|источник|покупатель|заказчик)(?:\s|$)/u.test(text);
|
||||
if (!hasRoleWord) {
|
||||
return false;
|
||||
}
|
||||
const hasRankingWord = /(?:^|\s)(?:главн[а-яёa-z0-9_-]*|крупнейш[а-яёa-z0-9_-]*|основн[а-яёa-z0-9_-]*|топ(?:-\d+)?)(?:\s|$)/u.test(text);
|
||||
const hasRoleOnlyExplanation = /(?:^|\s)(?:клиент|поставщик)(?:\s|$).{0,40}(?:^|\s)как(?:\s|$).{0,30}(?:^|\s)рол/u.test(text);
|
||||
const endsWithDanglingPreposition = /(?:^|\s)(?:в|за|по|на|от|для|к)$/u.test(text);
|
||||
return hasRoleOnlyExplanation || (hasRankingWord && (endsWithDanglingPreposition || text.length <= 48));
|
||||
}
|
||||
function sameCounterpartyCandidate(left, right) {
|
||||
return Boolean(left &&
|
||||
right &&
|
||||
@@ -590,6 +604,9 @@ function resolveAddressDebugCarryoverFilters(debug, toNonEmptyString = fallbackT
|
||||
const organization = readAddressDebugOrganization(debug, toNonEmptyString);
|
||||
const preferGroundedDiscoveryCounterparty = hasGroundedDiscoveryBusinessAnswer(debug, toNonEmptyString) && Boolean(counterparty);
|
||||
const existingCounterparty = normalizeCounterpartyCandidate(nextFilters.counterparty, toNonEmptyString);
|
||||
if (!existingCounterparty) {
|
||||
delete nextFilters.counterparty;
|
||||
}
|
||||
if (counterparty && (preferGroundedDiscoveryCounterparty || !existingCounterparty)) {
|
||||
nextFilters.counterparty = counterparty;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user