Архитектура: централизовать displayed-entity retarget в continuity policy и убрать dead owner из transition
This commit is contained in:
parent
ca91622d62
commit
15662cfe4f
|
|
@ -456,6 +456,11 @@ Still open after the accepted phase12 replay:
|
||||||
- this matters because `previous_filters.organization` is now aligned with the same continuity authority story that already drives route, living-chat, and data-scope, instead of keeping one more hot-path-only merge order inside transition glue;
|
- this matters because `previous_filters.organization` is now aligned with the same continuity authority story that already drives route, living-chat, and data-scope, instead of keeping one more hot-path-only merge order inside transition glue;
|
||||||
- targeted `assistantContinuityPolicy` and `assistantTransitionPolicy` suites are green after the move, with direct helper coverage for organization precedence and for preserving an already grounded organization value;
|
- targeted `assistantContinuityPolicy` and `assistantTransitionPolicy` suites are green after the move, with direct helper coverage for organization precedence and for preserving an already grounded organization value;
|
||||||
- a fresh live rerun of `address_truth_harness_phase12_wider_saved_session_pool` on `2026-04-19` remained semantically stable and again failed only on the already-known date-sensitive `today` expectations, not on the new shared organization carryover authority.
|
- a fresh live rerun of `address_truth_harness_phase12_wider_saved_session_pool` on `2026-04-19` remained semantically stable and again failed only on the already-known date-sensitive `today` expectations, not on the new shared organization carryover authority.
|
||||||
|
- the next continuity-authority pass now centralizes displayed-entity retargeting and removes another hidden duplicate owner from the transition hot path:
|
||||||
|
- continuity now owns `resolveDisplayedEntityFollowupRetarget(...)`, so `displayedEntityTargetIntent` and the companion carryover mutation for displayed counterparty / contract mentions are produced by one shared helper instead of being split between a local retarget branch and a separate transition mutation block;
|
||||||
|
- the shared retarget contract is now explicitly UTF-8-safe, which matters because a broken regex encoding in the first extraction attempt silently collapsed short phrases like `покажи договоры по СВК` back into stale previous-intent carryover;
|
||||||
|
- `assistantTransitionPolicy` no longer keeps a second local `resolveDisplayedEntityRetargetIntent(...)` owner beside the shared continuity helper, which reduces another chance that future follow-up fixes land in dead code or diverge between route retarget and anchor hydration;
|
||||||
|
- targeted `assistantContinuityPolicy` and `assistantTransitionPolicy` suites are green after the move, and a fresh live rerun of `address_truth_harness_phase11_manual_followup_meta_quality` on `2026-04-19` is accepted `10/10`, including the short displayed-counterparty retarget step.
|
||||||
|
|
||||||
## Next Execution Slice (2026-04-18)
|
## Next Execution Slice (2026-04-18)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ exports.applyTemporalCarryoverFilters = applyTemporalCarryoverFilters;
|
||||||
exports.applyOrganizationCarryoverFilters = applyOrganizationCarryoverFilters;
|
exports.applyOrganizationCarryoverFilters = applyOrganizationCarryoverFilters;
|
||||||
exports.applyHistoricalPartyCarryoverFilters = applyHistoricalPartyCarryoverFilters;
|
exports.applyHistoricalPartyCarryoverFilters = applyHistoricalPartyCarryoverFilters;
|
||||||
exports.applyReferencedEntityCarryover = applyReferencedEntityCarryover;
|
exports.applyReferencedEntityCarryover = applyReferencedEntityCarryover;
|
||||||
|
exports.resolveDisplayedEntityRetargetIntent = resolveDisplayedEntityRetargetIntent;
|
||||||
|
exports.resolveDisplayedEntityFollowupRetarget = resolveDisplayedEntityFollowupRetarget;
|
||||||
exports.applySelectedItemCarryover = applySelectedItemCarryover;
|
exports.applySelectedItemCarryover = applySelectedItemCarryover;
|
||||||
exports.buildInventoryRootFrameFromAddressDebug = buildInventoryRootFrameFromAddressDebug;
|
exports.buildInventoryRootFrameFromAddressDebug = buildInventoryRootFrameFromAddressDebug;
|
||||||
exports.isGroundedAddressDebug = isGroundedAddressDebug;
|
exports.isGroundedAddressDebug = isGroundedAddressDebug;
|
||||||
|
|
@ -353,6 +355,47 @@ function applyReferencedEntityCarryover(previousFilters, previousAnchorType, pre
|
||||||
resolvedCounterpartyFromDisplay
|
resolvedCounterpartyFromDisplay
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
function resolveDisplayedEntityRetargetIntent(userMessage, entityType, compactWhitespace, repairAddressMojibake) {
|
||||||
|
return resolveDisplayedEntityRetargetIntentUtf8Safe(userMessage, entityType, compactWhitespace, repairAddressMojibake);
|
||||||
|
}
|
||||||
|
function resolveDisplayedEntityRetargetIntentUtf8Safe(userMessage, entityType, compactWhitespace, repairAddressMojibake) {
|
||||||
|
const normalized = compactWhitespace(repairAddressMojibake(String(userMessage ?? "")).toLowerCase());
|
||||||
|
if (!normalized) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (String(entityType ?? "") === "counterparty") {
|
||||||
|
if (/(?:\u0434\u043e\u0433\u043e\u0432\u043e\u0440|\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442)/iu.test(normalized)) {
|
||||||
|
return "list_contracts_by_counterparty";
|
||||||
|
}
|
||||||
|
if (/(?:\u0431\u0430\u043d\u043a|\u0432\u044b\u043f\u0438\u0441\u043a|\u043f\u043b\u0430\u0442[\u0435\u0451]\u0436|\u043e\u043f\u043b\u0430\u0442|statement|payment|wire)/iu.test(normalized)) {
|
||||||
|
return "bank_operations_by_counterparty";
|
||||||
|
}
|
||||||
|
if (/(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\u043d\u0430\u043a\u043b\u0430\u0434\u043d|\u0441\u0447\u0435\u0442|\u0441\u0447[\u0435\u0451]\u0442|\u0430\u043a\u0442|\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446|\u043f\u043e\u0441\u0442\u0443\u043f\u043b)/iu.test(normalized)) {
|
||||||
|
return "list_documents_by_counterparty";
|
||||||
|
}
|
||||||
|
if (/(?:\u0441\u043a\u043e\u043b\u044c\u043a\u043e\s+\u0434\u0435\u043d\u0435\u0433|\u0441\u043a\u043e\u043b\u044c\u043a\u043e\s+\u043f\u0440\u0438\u043d\u0435\u0441|\u0432\u044b\u0440\u0443\u0447\u043a|\u0441\u0443\u043c\u043c[\u0430\u044b]?|\u043e\u043f\u043b\u0430\u0442\u0438\u043b|\u043f\u0440\u043e\u0434\u0430\u0436)/iu.test(normalized)) {
|
||||||
|
return "customer_revenue_and_payments";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (String(entityType ?? "") === "contract") {
|
||||||
|
if (/(?:\u0431\u0430\u043d\u043a|\u0432\u044b\u043f\u0438\u0441\u043a|\u043f\u043b\u0430\u0442[\u0435\u0451]\u0436|\u043e\u043f\u043b\u0430\u0442|statement|payment|wire)/iu.test(normalized)) {
|
||||||
|
return "bank_operations_by_contract";
|
||||||
|
}
|
||||||
|
if (/(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\u043d\u0430\u043a\u043b\u0430\u0434\u043d|\u0441\u0447\u0435\u0442|\u0441\u0447[\u0435\u0451]\u0442|\u0430\u043a\u0442|\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446|\u043f\u043e\u0441\u0442\u0443\u043f\u043b)/iu.test(normalized)) {
|
||||||
|
return "list_documents_by_contract";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function resolveDisplayedEntityFollowupRetarget(userMessage, resolvedEntityFromFollowup, previousFilters, previousAnchorType, previousAnchorValue, followupSelectionMode, rootScopedPivot, compactWhitespace, repairAddressMojibake, toNonEmptyString = fallbackToNonEmptyString) {
|
||||||
|
const displayedEntityTargetIntent = resolveDisplayedEntityRetargetIntentUtf8Safe(userMessage, resolvedEntityFromFollowup?.entityType, compactWhitespace, repairAddressMojibake);
|
||||||
|
const carryover = applyReferencedEntityCarryover(previousFilters, previousAnchorType, previousAnchorValue, followupSelectionMode, resolvedEntityFromFollowup, rootScopedPivot, toNonEmptyString);
|
||||||
|
return {
|
||||||
|
displayedEntityTargetIntent,
|
||||||
|
...carryover
|
||||||
|
};
|
||||||
|
}
|
||||||
function applySelectedItemCarryover(previousFilters, previousAnchorType, previousAnchorValue, rootScopedPivot, shouldApplySelectedItemCarryover, navigationFocusItemLabel, continuityActiveItem, selectedObjectLabelFromUser, selectedObjectLabelFromAlternate, toNonEmptyString = fallbackToNonEmptyString) {
|
function applySelectedItemCarryover(previousFilters, previousAnchorType, previousAnchorValue, rootScopedPivot, shouldApplySelectedItemCarryover, navigationFocusItemLabel, continuityActiveItem, selectedObjectLabelFromUser, selectedObjectLabelFromAlternate, toNonEmptyString = fallbackToNonEmptyString) {
|
||||||
const nextFilters = previousFilters && typeof previousFilters === "object" ? { ...previousFilters } : {};
|
const nextFilters = previousFilters && typeof previousFilters === "object" ? { ...previousFilters } : {};
|
||||||
if (rootScopedPivot || !shouldApplySelectedItemCarryover || toNonEmptyString(nextFilters.item)) {
|
if (rootScopedPivot || !shouldApplySelectedItemCarryover || toNonEmptyString(nextFilters.item)) {
|
||||||
|
|
|
||||||
|
|
@ -284,36 +284,6 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
function resolveDisplayedEntityRetargetIntent(userMessage, entityType) {
|
|
||||||
const normalized = deps.compactWhitespace(deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase());
|
|
||||||
if (!normalized) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (entityType === "counterparty") {
|
|
||||||
if (/(?:договор|контракт)/iu.test(normalized)) {
|
|
||||||
return "list_contracts_by_counterparty";
|
|
||||||
}
|
|
||||||
if (/(?:банк|выписк|плат[её]ж|оплат|statement|payment|wire)/iu.test(normalized)) {
|
|
||||||
return "bank_operations_by_counterparty";
|
|
||||||
}
|
|
||||||
if (/(?:документ|накладн|счет|сч[её]т|акт|реализац|поступл)/iu.test(normalized)) {
|
|
||||||
return "list_documents_by_counterparty";
|
|
||||||
}
|
|
||||||
if (/(?:сколько\s+денег|сколько\s+принес|выручк|сумм[аы]?|оплатил|продаж)/iu.test(normalized)) {
|
|
||||||
return "customer_revenue_and_payments";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (entityType === "contract") {
|
|
||||||
if (/(?:банк|выписк|плат[её]ж|оплат|statement|payment|wire)/iu.test(normalized)) {
|
|
||||||
return "bank_operations_by_contract";
|
|
||||||
}
|
|
||||||
if (/(?:документ|накладн|счет|сч[её]т|акт|реализац|поступл)/iu.test(normalized)) {
|
|
||||||
return "list_documents_by_contract";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
function resolveAddressFollowupCarryoverContext(userMessage, items, alternateMessage = null, llmPreDecomposeMeta = null, addressNavigationState = null) {
|
function resolveAddressFollowupCarryoverContext(userMessage, items, alternateMessage = null, llmPreDecomposeMeta = null, addressNavigationState = null) {
|
||||||
const rawCapabilityMetaQuery = deps.shouldHandleAsAssistantCapabilityMetaQuery(userMessage) ||
|
const rawCapabilityMetaQuery = deps.shouldHandleAsAssistantCapabilityMetaQuery(userMessage) ||
|
||||||
(deps.toNonEmptyString(alternateMessage)
|
(deps.toNonEmptyString(alternateMessage)
|
||||||
|
|
@ -657,16 +627,14 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
(deps.toNonEmptyString(alternateMessage)
|
(deps.toNonEmptyString(alternateMessage)
|
||||||
? deps.resolveDisplayedAddressEntityMention(String(alternateMessage ?? ""), displayedEntities)
|
? deps.resolveDisplayedAddressEntityMention(String(alternateMessage ?? ""), displayedEntities)
|
||||||
: null);
|
: null);
|
||||||
if (resolvedEntityFromFollowup && !rootScopedPivot) {
|
|
||||||
displayedEntityTargetIntent = resolveDisplayedEntityRetargetIntent(userMessage, resolvedEntityFromFollowup.entityType);
|
|
||||||
}
|
|
||||||
({
|
({
|
||||||
|
displayedEntityTargetIntent,
|
||||||
previousFilters,
|
previousFilters,
|
||||||
previousAnchorType,
|
previousAnchorType,
|
||||||
previousAnchorValue: previousAnchor,
|
previousAnchorValue: previousAnchor,
|
||||||
followupSelectionMode,
|
followupSelectionMode,
|
||||||
resolvedCounterpartyFromDisplay
|
resolvedCounterpartyFromDisplay
|
||||||
} = (0, assistantContinuityPolicy_1.applyReferencedEntityCarryover)(previousFilters, previousAnchorType, previousAnchor, followupSelectionMode, resolvedEntityFromFollowup, rootScopedPivot, deps.toNonEmptyString));
|
} = (0, assistantContinuityPolicy_1.resolveDisplayedEntityFollowupRetarget)(userMessage, resolvedEntityFromFollowup, previousFilters, previousAnchorType, previousAnchor, followupSelectionMode, rootScopedPivot, deps.compactWhitespace, deps.repairAddressMojibake, deps.toNonEmptyString));
|
||||||
({
|
({
|
||||||
previousFilters,
|
previousFilters,
|
||||||
previousAnchorType,
|
previousAnchorType,
|
||||||
|
|
|
||||||
|
|
@ -536,6 +536,122 @@ export function applyReferencedEntityCarryover(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveDisplayedEntityRetargetIntent(
|
||||||
|
userMessage: unknown,
|
||||||
|
entityType: unknown,
|
||||||
|
compactWhitespace: (value: string) => string,
|
||||||
|
repairAddressMojibake: (value: string) => string
|
||||||
|
): string | null {
|
||||||
|
return resolveDisplayedEntityRetargetIntentUtf8Safe(
|
||||||
|
userMessage,
|
||||||
|
entityType,
|
||||||
|
compactWhitespace,
|
||||||
|
repairAddressMojibake
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveDisplayedEntityRetargetIntentUtf8Safe(
|
||||||
|
userMessage: unknown,
|
||||||
|
entityType: unknown,
|
||||||
|
compactWhitespace: (value: string) => string,
|
||||||
|
repairAddressMojibake: (value: string) => string
|
||||||
|
): string | null {
|
||||||
|
const normalized = compactWhitespace(repairAddressMojibake(String(userMessage ?? "")).toLowerCase());
|
||||||
|
if (!normalized) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (String(entityType ?? "") === "counterparty") {
|
||||||
|
if (/(?:\u0434\u043e\u0433\u043e\u0432\u043e\u0440|\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442)/iu.test(normalized)) {
|
||||||
|
return "list_contracts_by_counterparty";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
/(?:\u0431\u0430\u043d\u043a|\u0432\u044b\u043f\u0438\u0441\u043a|\u043f\u043b\u0430\u0442[\u0435\u0451]\u0436|\u043e\u043f\u043b\u0430\u0442|statement|payment|wire)/iu.test(
|
||||||
|
normalized
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "bank_operations_by_counterparty";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
/(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\u043d\u0430\u043a\u043b\u0430\u0434\u043d|\u0441\u0447\u0435\u0442|\u0441\u0447[\u0435\u0451]\u0442|\u0430\u043a\u0442|\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446|\u043f\u043e\u0441\u0442\u0443\u043f\u043b)/iu.test(
|
||||||
|
normalized
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "list_documents_by_counterparty";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
/(?:\u0441\u043a\u043e\u043b\u044c\u043a\u043e\s+\u0434\u0435\u043d\u0435\u0433|\u0441\u043a\u043e\u043b\u044c\u043a\u043e\s+\u043f\u0440\u0438\u043d\u0435\u0441|\u0432\u044b\u0440\u0443\u0447\u043a|\u0441\u0443\u043c\u043c[\u0430\u044b]?|\u043e\u043f\u043b\u0430\u0442\u0438\u043b|\u043f\u0440\u043e\u0434\u0430\u0436)/iu.test(
|
||||||
|
normalized
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "customer_revenue_and_payments";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (String(entityType ?? "") === "contract") {
|
||||||
|
if (
|
||||||
|
/(?:\u0431\u0430\u043d\u043a|\u0432\u044b\u043f\u0438\u0441\u043a|\u043f\u043b\u0430\u0442[\u0435\u0451]\u0436|\u043e\u043f\u043b\u0430\u0442|statement|payment|wire)/iu.test(
|
||||||
|
normalized
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "bank_operations_by_contract";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
/(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|\u043d\u0430\u043a\u043b\u0430\u0434\u043d|\u0441\u0447\u0435\u0442|\u0441\u0447[\u0435\u0451]\u0442|\u0430\u043a\u0442|\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446|\u043f\u043e\u0441\u0442\u0443\u043f\u043b)/iu.test(
|
||||||
|
normalized
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "list_documents_by_contract";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveDisplayedEntityFollowupRetarget(
|
||||||
|
userMessage: unknown,
|
||||||
|
resolvedEntityFromFollowup:
|
||||||
|
| {
|
||||||
|
entityType?: unknown;
|
||||||
|
value?: unknown;
|
||||||
|
}
|
||||||
|
| null
|
||||||
|
| undefined,
|
||||||
|
previousFilters: Record<string, unknown> | null,
|
||||||
|
previousAnchorType: string | null,
|
||||||
|
previousAnchorValue: string | null,
|
||||||
|
followupSelectionMode: string | null,
|
||||||
|
rootScopedPivot: boolean,
|
||||||
|
compactWhitespace: (value: string) => string,
|
||||||
|
repairAddressMojibake: (value: string) => string,
|
||||||
|
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||||
|
): {
|
||||||
|
displayedEntityTargetIntent: string | null;
|
||||||
|
previousFilters: Record<string, unknown>;
|
||||||
|
previousAnchorType: string | null;
|
||||||
|
previousAnchorValue: string | null;
|
||||||
|
followupSelectionMode: string | null;
|
||||||
|
resolvedCounterpartyFromDisplay: boolean;
|
||||||
|
} {
|
||||||
|
const displayedEntityTargetIntent = resolveDisplayedEntityRetargetIntentUtf8Safe(
|
||||||
|
userMessage,
|
||||||
|
resolvedEntityFromFollowup?.entityType,
|
||||||
|
compactWhitespace,
|
||||||
|
repairAddressMojibake
|
||||||
|
);
|
||||||
|
const carryover = applyReferencedEntityCarryover(
|
||||||
|
previousFilters,
|
||||||
|
previousAnchorType,
|
||||||
|
previousAnchorValue,
|
||||||
|
followupSelectionMode,
|
||||||
|
resolvedEntityFromFollowup,
|
||||||
|
rootScopedPivot,
|
||||||
|
toNonEmptyString
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
displayedEntityTargetIntent,
|
||||||
|
...carryover
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function applySelectedItemCarryover(
|
export function applySelectedItemCarryover(
|
||||||
previousFilters: Record<string, unknown> | null,
|
previousFilters: Record<string, unknown> | null,
|
||||||
previousAnchorType: string | null,
|
previousAnchorType: string | null,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
import {
|
import {
|
||||||
applyHistoricalPartyCarryoverFilters,
|
applyHistoricalPartyCarryoverFilters,
|
||||||
applyOrganizationCarryoverFilters,
|
applyOrganizationCarryoverFilters,
|
||||||
applyReferencedEntityCarryover,
|
|
||||||
applySelectedItemCarryover,
|
applySelectedItemCarryover,
|
||||||
applyTemporalCarryoverFilters,
|
applyTemporalCarryoverFilters,
|
||||||
buildRootScopedCarryoverFilters,
|
buildRootScopedCarryoverFilters,
|
||||||
|
|
@ -13,6 +12,7 @@ import {
|
||||||
readAddressDebugTemporalScope,
|
readAddressDebugTemporalScope,
|
||||||
resolveAddressDebugCarryoverFilters,
|
resolveAddressDebugCarryoverFilters,
|
||||||
resolveAddressDebugAnchorContext,
|
resolveAddressDebugAnchorContext,
|
||||||
|
resolveDisplayedEntityFollowupRetarget,
|
||||||
resolveAssistantOrganizationAuthority
|
resolveAssistantOrganizationAuthority
|
||||||
} from "./assistantContinuityPolicy";
|
} from "./assistantContinuityPolicy";
|
||||||
|
|
||||||
|
|
@ -364,39 +364,6 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveDisplayedEntityRetargetIntent(userMessage, entityType) {
|
|
||||||
const normalized = deps.compactWhitespace(
|
|
||||||
deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase()
|
|
||||||
);
|
|
||||||
if (!normalized) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (entityType === "counterparty") {
|
|
||||||
if (/(?:договор|контракт)/iu.test(normalized)) {
|
|
||||||
return "list_contracts_by_counterparty";
|
|
||||||
}
|
|
||||||
if (/(?:банк|выписк|плат[её]ж|оплат|statement|payment|wire)/iu.test(normalized)) {
|
|
||||||
return "bank_operations_by_counterparty";
|
|
||||||
}
|
|
||||||
if (/(?:документ|накладн|счет|сч[её]т|акт|реализац|поступл)/iu.test(normalized)) {
|
|
||||||
return "list_documents_by_counterparty";
|
|
||||||
}
|
|
||||||
if (/(?:сколько\s+денег|сколько\s+принес|выручк|сумм[аы]?|оплатил|продаж)/iu.test(normalized)) {
|
|
||||||
return "customer_revenue_and_payments";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (entityType === "contract") {
|
|
||||||
if (/(?:банк|выписк|плат[её]ж|оплат|statement|payment|wire)/iu.test(normalized)) {
|
|
||||||
return "bank_operations_by_contract";
|
|
||||||
}
|
|
||||||
if (/(?:документ|накладн|счет|сч[её]т|акт|реализац|поступл)/iu.test(normalized)) {
|
|
||||||
return "list_documents_by_contract";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveAddressFollowupCarryoverContext(
|
function resolveAddressFollowupCarryoverContext(
|
||||||
userMessage,
|
userMessage,
|
||||||
items,
|
items,
|
||||||
|
|
@ -854,25 +821,23 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
(deps.toNonEmptyString(alternateMessage)
|
(deps.toNonEmptyString(alternateMessage)
|
||||||
? deps.resolveDisplayedAddressEntityMention(String(alternateMessage ?? ""), displayedEntities)
|
? deps.resolveDisplayedAddressEntityMention(String(alternateMessage ?? ""), displayedEntities)
|
||||||
: null);
|
: null);
|
||||||
if (resolvedEntityFromFollowup && !rootScopedPivot) {
|
|
||||||
displayedEntityTargetIntent = resolveDisplayedEntityRetargetIntent(
|
|
||||||
userMessage,
|
|
||||||
resolvedEntityFromFollowup.entityType
|
|
||||||
);
|
|
||||||
}
|
|
||||||
({
|
({
|
||||||
|
displayedEntityTargetIntent,
|
||||||
previousFilters,
|
previousFilters,
|
||||||
previousAnchorType,
|
previousAnchorType,
|
||||||
previousAnchorValue: previousAnchor,
|
previousAnchorValue: previousAnchor,
|
||||||
followupSelectionMode,
|
followupSelectionMode,
|
||||||
resolvedCounterpartyFromDisplay
|
resolvedCounterpartyFromDisplay
|
||||||
} = applyReferencedEntityCarryover(
|
} = resolveDisplayedEntityFollowupRetarget(
|
||||||
|
userMessage,
|
||||||
|
resolvedEntityFromFollowup,
|
||||||
previousFilters,
|
previousFilters,
|
||||||
previousAnchorType,
|
previousAnchorType,
|
||||||
previousAnchor,
|
previousAnchor,
|
||||||
followupSelectionMode,
|
followupSelectionMode,
|
||||||
resolvedEntityFromFollowup,
|
|
||||||
rootScopedPivot,
|
rootScopedPivot,
|
||||||
|
deps.compactWhitespace,
|
||||||
|
deps.repairAddressMojibake,
|
||||||
deps.toNonEmptyString
|
deps.toNonEmptyString
|
||||||
));
|
));
|
||||||
({
|
({
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
resolveAddressDebugCarryoverFilters,
|
resolveAddressDebugCarryoverFilters,
|
||||||
resolveAddressDebugContextFacts,
|
resolveAddressDebugContextFacts,
|
||||||
resolveAddressDebugAnchorContext,
|
resolveAddressDebugAnchorContext,
|
||||||
|
resolveDisplayedEntityFollowupRetarget,
|
||||||
resolveAssistantOrganizationAuthority
|
resolveAssistantOrganizationAuthority
|
||||||
} from "../src/services/assistantContinuityPolicy";
|
} from "../src/services/assistantContinuityPolicy";
|
||||||
|
|
||||||
|
|
@ -350,4 +351,35 @@ describe("assistantContinuityPolicy organization authority", () => {
|
||||||
previousAnchorValue: "Workstation Navigation"
|
previousAnchorValue: "Workstation Navigation"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("resolves displayed-entity follow-up retarget and carryover through one shared helper", () => {
|
||||||
|
const carryover = resolveDisplayedEntityFollowupRetarget(
|
||||||
|
"покажи договоры по СВК",
|
||||||
|
{
|
||||||
|
entityType: "counterparty",
|
||||||
|
value: "SVK Group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
organization: "Org Alt"
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"carry_previous_intent",
|
||||||
|
false,
|
||||||
|
(value) => String(value ?? "").replace(/\s+/g, " ").trim(),
|
||||||
|
(value) => value
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(carryover).toEqual({
|
||||||
|
displayedEntityTargetIntent: "list_contracts_by_counterparty",
|
||||||
|
previousFilters: {
|
||||||
|
organization: "Org Alt",
|
||||||
|
counterparty: "SVK Group"
|
||||||
|
},
|
||||||
|
previousAnchorType: "counterparty",
|
||||||
|
previousAnchorValue: "SVK Group",
|
||||||
|
followupSelectionMode: "carry_referenced_entity",
|
||||||
|
resolvedCounterpartyFromDisplay: true
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue