Архитектура: централизовать inventory root-frame state и root-scoped carryover в continuity policy
This commit is contained in:
@@ -39,6 +39,12 @@ export interface AssistantAddressDebugTemporalScope {
|
||||
periodTo: string | null;
|
||||
}
|
||||
|
||||
export interface AssistantNavigationDateScope {
|
||||
as_of_date?: unknown;
|
||||
period_from?: unknown;
|
||||
period_to?: unknown;
|
||||
}
|
||||
|
||||
export interface AssistantAddressDebugAnchorContext {
|
||||
anchorType: string | null;
|
||||
anchorValue: string | null;
|
||||
@@ -244,6 +250,125 @@ export function resolveAddressDebugCarryoverFilters(
|
||||
return nextFilters;
|
||||
}
|
||||
|
||||
export function hydrateInventoryRootFrameState(
|
||||
inventoryRootFrame: {
|
||||
intent: string;
|
||||
filters: Record<string, unknown>;
|
||||
anchorType: string | null;
|
||||
anchorValue: string | null;
|
||||
currentFrameKind?: string | null;
|
||||
} | null,
|
||||
sourceIntent: unknown,
|
||||
navigationOrganization: unknown,
|
||||
navigationDateScope: AssistantNavigationDateScope | null,
|
||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString,
|
||||
isInventoryDrilldownFrameIntent: (intent: unknown) => boolean = () => false,
|
||||
isInventoryRootFrameIntent: (intent: unknown) => boolean = () => false
|
||||
): {
|
||||
inventoryRootFrame: {
|
||||
intent: string;
|
||||
filters: Record<string, unknown>;
|
||||
anchorType: string | null;
|
||||
anchorValue: string | null;
|
||||
currentFrameKind: string;
|
||||
} | null;
|
||||
currentFrameKind: string | null;
|
||||
} {
|
||||
if (!inventoryRootFrame) {
|
||||
return { inventoryRootFrame: null, currentFrameKind: null };
|
||||
}
|
||||
|
||||
let hydratedRootFrame = {
|
||||
...inventoryRootFrame,
|
||||
filters: {
|
||||
...(inventoryRootFrame.filters ?? {})
|
||||
},
|
||||
currentFrameKind: toNonEmptyString(inventoryRootFrame.currentFrameKind) ?? null
|
||||
};
|
||||
|
||||
if (navigationOrganization && !toNonEmptyString(hydratedRootFrame.filters?.organization)) {
|
||||
hydratedRootFrame = {
|
||||
...hydratedRootFrame,
|
||||
filters: {
|
||||
...(hydratedRootFrame.filters ?? {}),
|
||||
organization: navigationOrganization
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (navigationDateScope) {
|
||||
hydratedRootFrame = {
|
||||
...hydratedRootFrame,
|
||||
filters: {
|
||||
...(hydratedRootFrame.filters ?? {}),
|
||||
as_of_date:
|
||||
toNonEmptyString(hydratedRootFrame.filters?.as_of_date) ??
|
||||
toNonEmptyString(navigationDateScope.as_of_date) ??
|
||||
undefined,
|
||||
period_from:
|
||||
toNonEmptyString(hydratedRootFrame.filters?.period_from) ??
|
||||
toNonEmptyString(navigationDateScope.period_from) ??
|
||||
undefined,
|
||||
period_to:
|
||||
toNonEmptyString(hydratedRootFrame.filters?.period_to) ??
|
||||
toNonEmptyString(navigationDateScope.period_to) ??
|
||||
undefined
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const currentFrameKind =
|
||||
toNonEmptyString(hydratedRootFrame.currentFrameKind) ??
|
||||
(isInventoryDrilldownFrameIntent(sourceIntent)
|
||||
? "inventory_drilldown"
|
||||
: isInventoryRootFrameIntent(sourceIntent)
|
||||
? "inventory_root"
|
||||
: "generic");
|
||||
|
||||
return {
|
||||
inventoryRootFrame: {
|
||||
...hydratedRootFrame,
|
||||
currentFrameKind
|
||||
},
|
||||
currentFrameKind
|
||||
};
|
||||
}
|
||||
|
||||
export function buildRootScopedCarryoverFilters(
|
||||
previousFilters: Record<string, unknown> | null,
|
||||
inventoryRootFrame: {
|
||||
filters?: Record<string, unknown> | null;
|
||||
} | null,
|
||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||
): Record<string, unknown> {
|
||||
const candidateFilters =
|
||||
inventoryRootFrame?.filters && typeof inventoryRootFrame.filters === "object"
|
||||
? inventoryRootFrame.filters
|
||||
: {};
|
||||
const nextFilters: Record<string, unknown> = {};
|
||||
const organization = toNonEmptyString(candidateFilters?.organization) ?? toNonEmptyString(previousFilters?.organization);
|
||||
const warehouse = toNonEmptyString(candidateFilters?.warehouse) ?? toNonEmptyString(previousFilters?.warehouse);
|
||||
const asOfDate = toNonEmptyString(previousFilters?.as_of_date) ?? toNonEmptyString(candidateFilters?.as_of_date);
|
||||
const periodFrom = toNonEmptyString(previousFilters?.period_from) ?? toNonEmptyString(candidateFilters?.period_from);
|
||||
const periodTo = toNonEmptyString(previousFilters?.period_to) ?? toNonEmptyString(candidateFilters?.period_to);
|
||||
if (organization) {
|
||||
nextFilters.organization = organization;
|
||||
}
|
||||
if (warehouse) {
|
||||
nextFilters.warehouse = warehouse;
|
||||
}
|
||||
if (asOfDate) {
|
||||
nextFilters.as_of_date = asOfDate;
|
||||
}
|
||||
if (periodFrom) {
|
||||
nextFilters.period_from = periodFrom;
|
||||
}
|
||||
if (periodTo) {
|
||||
nextFilters.period_to = periodTo;
|
||||
}
|
||||
return nextFilters;
|
||||
}
|
||||
|
||||
export function buildInventoryRootFrameFromAddressDebug(
|
||||
debug: Record<string, unknown> | null,
|
||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||
|
||||
@@ -2713,31 +2713,7 @@ function hasForeignAccountingPivotOverInventoryMessage(userMessage, alternateMes
|
||||
/(?:оплат|плат(?:е|ё)ж|аванс|зач(?:е|ё)т|выписк|statement|wire|settlement|payment|\b51(?:\.\d{1,2})?\b|\b60(?:\.\d{1,2})?\b|\b62(?:\.\d{1,2})?\b)/iu.test(sample));
|
||||
}
|
||||
function buildRootScopedCarryoverFilters(previousFilters, inventoryRootFrame) {
|
||||
const candidateFilters = inventoryRootFrame?.filters && typeof inventoryRootFrame.filters === "object"
|
||||
? inventoryRootFrame.filters
|
||||
: {};
|
||||
const nextFilters = {};
|
||||
const organization = toNonEmptyString(candidateFilters?.organization) ?? toNonEmptyString(previousFilters?.organization);
|
||||
const warehouse = toNonEmptyString(candidateFilters?.warehouse) ?? toNonEmptyString(previousFilters?.warehouse);
|
||||
const asOfDate = toNonEmptyString(previousFilters?.as_of_date) ?? toNonEmptyString(candidateFilters?.as_of_date);
|
||||
const periodFrom = toNonEmptyString(previousFilters?.period_from) ?? toNonEmptyString(candidateFilters?.period_from);
|
||||
const periodTo = toNonEmptyString(previousFilters?.period_to) ?? toNonEmptyString(candidateFilters?.period_to);
|
||||
if (organization) {
|
||||
nextFilters.organization = organization;
|
||||
}
|
||||
if (warehouse) {
|
||||
nextFilters.warehouse = warehouse;
|
||||
}
|
||||
if (asOfDate) {
|
||||
nextFilters.as_of_date = asOfDate;
|
||||
}
|
||||
if (periodFrom) {
|
||||
nextFilters.period_from = periodFrom;
|
||||
}
|
||||
if (periodTo) {
|
||||
nextFilters.period_to = periodTo;
|
||||
}
|
||||
return nextFilters;
|
||||
return (0, assistantContinuityPolicy_1.buildRootScopedCarryoverFilters)(previousFilters, inventoryRootFrame, toNonEmptyString);
|
||||
}
|
||||
function resolveDebtRoleSwapFollowupIntent(userMessage, previousIntent) {
|
||||
const normalized = compactWhitespace(String(userMessage ?? "").toLowerCase());
|
||||
@@ -4529,9 +4505,6 @@ function mergeFollowupContextWithOrganizationScope(followupContext, organization
|
||||
export function resolveSessionOrganizationScopeContextForTests(userMessage, items, addressNavigationState = null) {
|
||||
return resolveSessionOrganizationScopeContext(userMessage, items, addressNavigationState);
|
||||
}
|
||||
export function buildRootScopedCarryoverFiltersForTests(previousFilters, inventoryRootFrame) {
|
||||
return buildRootScopedCarryoverFilters(previousFilters, inventoryRootFrame);
|
||||
}
|
||||
function normalizeGuidValue(value) {
|
||||
const source = normalizeScopeLabel(value);
|
||||
if (!source) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// @ts-nocheck
|
||||
import {
|
||||
buildRootScopedCarryoverFilters,
|
||||
buildInventoryRootFrameFromAddressDebug,
|
||||
hydrateInventoryRootFrameState,
|
||||
readAddressDebugFilters,
|
||||
readAddressDebugItem,
|
||||
readAddressDebugTemporalScope,
|
||||
@@ -732,46 +734,19 @@ export function createAssistantTransitionPolicy(deps) {
|
||||
hasSelectedObjectInventorySignalPrimary || hasSelectedObjectInventorySignalAlternate
|
||||
? inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage)
|
||||
: null;
|
||||
let inventoryRootFrame =
|
||||
const inventoryRootFrameCandidate =
|
||||
deps.findRecentInventoryRootFrame(items) ??
|
||||
continuitySnapshot.inventoryRootFrame ??
|
||||
buildInventoryRootFrameFromAddressDebug(continuitySnapshot.lastGroundedAddressDebug, deps.toNonEmptyString);
|
||||
if (inventoryRootFrame && navigationOrganization && !deps.toNonEmptyString(inventoryRootFrame.filters?.organization)) {
|
||||
inventoryRootFrame = {
|
||||
...inventoryRootFrame,
|
||||
filters: {
|
||||
...(inventoryRootFrame.filters ?? {}),
|
||||
organization: navigationOrganization
|
||||
}
|
||||
};
|
||||
}
|
||||
if (inventoryRootFrame && navigationDateScope) {
|
||||
inventoryRootFrame = {
|
||||
...inventoryRootFrame,
|
||||
filters: {
|
||||
...(inventoryRootFrame.filters ?? {}),
|
||||
as_of_date:
|
||||
deps.toNonEmptyString(inventoryRootFrame.filters?.as_of_date) ??
|
||||
deps.toNonEmptyString(navigationDateScope.as_of_date) ??
|
||||
undefined,
|
||||
period_from:
|
||||
deps.toNonEmptyString(inventoryRootFrame.filters?.period_from) ??
|
||||
deps.toNonEmptyString(navigationDateScope.period_from) ??
|
||||
undefined,
|
||||
period_to:
|
||||
deps.toNonEmptyString(inventoryRootFrame.filters?.period_to) ??
|
||||
deps.toNonEmptyString(navigationDateScope.period_to) ??
|
||||
undefined
|
||||
}
|
||||
};
|
||||
}
|
||||
let currentFrameKind = inventoryRootFrame
|
||||
? deps.isInventoryDrilldownFrameIntent(sourceIntent)
|
||||
? "inventory_drilldown"
|
||||
: deps.isInventoryRootFrameIntent(sourceIntent)
|
||||
? "inventory_root"
|
||||
: "generic"
|
||||
: null;
|
||||
let { inventoryRootFrame, currentFrameKind } = hydrateInventoryRootFrameState(
|
||||
inventoryRootFrameCandidate,
|
||||
sourceIntent,
|
||||
navigationOrganization,
|
||||
navigationDateScope,
|
||||
deps.toNonEmptyString,
|
||||
deps.isInventoryDrilldownFrameIntent,
|
||||
deps.isInventoryRootFrameIntent
|
||||
);
|
||||
let resolvedCounterpartyFromDisplay = false;
|
||||
let displayedEntityTargetIntent = null;
|
||||
let previousFilters = resolveAddressDebugCarryoverFilters(previousAddressDebug, deps.toNonEmptyString);
|
||||
@@ -919,7 +894,7 @@ export function createAssistantTransitionPolicy(deps) {
|
||||
previousIntent = null;
|
||||
previousAnchorType = null;
|
||||
previousAnchor = null;
|
||||
previousFilters = deps.buildRootScopedCarryoverFilters(previousFilters, inventoryRootFrame);
|
||||
previousFilters = buildRootScopedCarryoverFilters(previousFilters, inventoryRootFrame, deps.toNonEmptyString);
|
||||
currentFrameKind = inventoryRootFrame ? "inventory_root" : currentFrameKind;
|
||||
followupSelectionMode = "carry_root_context";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user