Архитектура: централизовать navigation focus authority в continuity policy и сделать phase15 replay time-stable

This commit is contained in:
2026-04-19 17:44:37 +03:00
parent 0e098cde38
commit 82cc5cfd1a
10 changed files with 199 additions and 92 deletions
@@ -45,6 +45,19 @@ export interface AssistantNavigationDateScope {
period_to?: unknown;
}
export interface AssistantNavigationFocusObject {
objectType: string | null;
label: string | null;
provenanceResultSetId: string | null;
}
export interface AssistantNavigationSessionContextState {
dateScope: AssistantNavigationDateScope | null;
organization: string | null;
focusObject: AssistantNavigationFocusObject | null;
activeResultSetId: string | null;
}
export interface AssistantAddressDebugAnchorContext {
anchorType: string | null;
anchorValue: string | null;
@@ -203,6 +216,28 @@ export function resolveAddressDebugAnchorContext(
};
}
export function resolveNavigationSessionContextState(
addressNavigationState: unknown,
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString,
normalizeOrganizationScopeValue: (value: unknown) => string | null = normalizeOrganizationScopeDefault
): AssistantNavigationSessionContextState {
const sessionContext = toRecordObject(toRecordObject(addressNavigationState)?.session_context);
const rawFocusObject = toRecordObject(sessionContext?.active_focus_object);
const focusObject = rawFocusObject
? {
objectType: toNonEmptyString(rawFocusObject.object_type),
label: toNonEmptyString(rawFocusObject.label),
provenanceResultSetId: toNonEmptyString(rawFocusObject.provenance_result_set_id)
}
: null;
return {
dateScope: toRecordObject(sessionContext?.date_scope) as AssistantNavigationDateScope | null,
organization: normalizeOrganizationScopeValue(sessionContext?.organization_scope),
focusObject,
activeResultSetId: toNonEmptyString(sessionContext?.active_result_set_id)
};
}
export function resolveAddressDebugContextFacts(
debug: Record<string, unknown> | null,
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
@@ -10,6 +10,7 @@ import {
readAddressDebugFilters,
readAddressDebugItem,
readAddressDebugTemporalScope,
resolveNavigationSessionContextState,
resolveAddressDebugCarryoverFilters,
resolveAddressDebugAnchorContext,
resolveDisplayedEntityFollowupRetarget,
@@ -145,20 +146,14 @@ export function createAssistantTransitionPolicy(deps) {
}
}
const sessionContext =
addressNavigationState &&
typeof addressNavigationState === "object" &&
addressNavigationState.session_context &&
typeof addressNavigationState.session_context === "object"
? addressNavigationState.session_context
: null;
const focusObject =
sessionContext && typeof sessionContext.active_focus_object === "object"
? sessionContext.active_focus_object
: null;
const navigationSessionState = resolveNavigationSessionContextState(
addressNavigationState,
deps.toNonEmptyString,
deps.normalizeOrganizationScopeValue
);
const focusObject = navigationSessionState.focusObject;
const preferredResultSetId =
deps.toNonEmptyString(focusObject?.provenance_result_set_id) ??
deps.toNonEmptyString(sessionContext?.active_result_set_id);
deps.toNonEmptyString(focusObject?.provenanceResultSetId) ?? navigationSessionState.activeResultSetId;
const resultSets = Array.isArray(addressNavigationState?.result_sets) ? addressNavigationState.result_sets : [];
const preferredResultSet =
(preferredResultSetId
@@ -431,18 +426,15 @@ export function createAssistantTransitionPolicy(deps) {
? deps.isImplicitAddressContinuationByLlm(alternateMessage, llmPreDecomposeMeta)
: false));
const sourceIntentHint = deps.toNonEmptyString(carryoverSourceDebug?.detected_intent);
const navigationFocusObjectHint =
addressNavigationState &&
typeof addressNavigationState === "object" &&
addressNavigationState.session_context &&
typeof addressNavigationState.session_context === "object" &&
addressNavigationState.session_context.active_focus_object &&
typeof addressNavigationState.session_context.active_focus_object === "object"
? addressNavigationState.session_context.active_focus_object
: null;
const navigationSessionState = resolveNavigationSessionContextState(
addressNavigationState,
deps.toNonEmptyString,
deps.normalizeOrganizationScopeValue
);
const navigationFocusObjectHint = navigationSessionState.focusObject;
const hasNavigationInventoryItemFocusHint = Boolean(
deps.toNonEmptyString(navigationFocusObjectHint?.label) &&
deps.toNonEmptyString(navigationFocusObjectHint?.object_type) === "item" &&
deps.toNonEmptyString(navigationFocusObjectHint?.objectType) === "item" &&
(sourceIntentHint === "inventory_on_hand_as_of_date" ||
sourceIntentHint === "inventory_supplier_stock_overlap_as_of_date" ||
deps.isInventorySelectedObjectIntent(sourceIntentHint))
@@ -643,22 +635,10 @@ export function createAssistantTransitionPolicy(deps) {
const previousAnchorContext = resolveAddressDebugAnchorContext(carryoverSourceDebug, deps.toNonEmptyString);
let previousAnchorType = previousAnchorContext.anchorType;
let previousAnchor = previousAnchorContext.anchorValue;
const navigationSessionContext =
addressNavigationState && typeof addressNavigationState === "object"
? addressNavigationState.session_context && typeof addressNavigationState.session_context === "object"
? addressNavigationState.session_context
: null
: null;
const navigationDateScope =
navigationSessionContext && typeof navigationSessionContext.date_scope === "object"
? navigationSessionContext.date_scope
: null;
const navigationOrganization = deps.normalizeOrganizationScopeValue(navigationSessionContext?.organization_scope);
const navigationFocusObject =
navigationSessionContext && typeof navigationSessionContext.active_focus_object === "object"
? navigationSessionContext.active_focus_object
: null;
const navigationFocusObjectType = deps.toNonEmptyString(navigationFocusObject?.object_type);
const navigationDateScope = navigationSessionState.dateScope;
const navigationOrganization = navigationSessionState.organization;
const navigationFocusObject = navigationSessionState.focusObject;
const navigationFocusObjectType = deps.toNonEmptyString(navigationFocusObject?.objectType);
const navigationFocusObjectLabel = deps.toNonEmptyString(navigationFocusObject?.label);
const hasInventoryItemFocusCarryover =
navigationFocusObjectType === "item" &&