NODEDC_1C/llm_normalizer/backend/src/services/assistantTransitionPolicy.ts

1399 lines
62 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @ts-nocheck
import {
applyHistoricalPartyCarryoverFilters,
applyOrganizationCarryoverFilters,
applySelectedItemCarryover,
applyTemporalCarryoverFilters,
buildRootScopedCarryoverFilters,
buildInventoryRootFrameFromAddressDebug,
hydrateInventoryRootFrameState,
readAddressDebugIntent,
readAddressDebugFilters,
readAddressDebugItem,
readAssistantMcpDiscoveryMetadataAmbiguityDetected,
readAssistantMcpDiscoveryMetadataAmbiguityEntitySets,
readAssistantMcpDiscoveryEntityCandidates,
readAssistantMcpDiscoveryEntityAmbiguityCandidates,
readAssistantMcpDiscoveryEntityResolutionStatus,
readAssistantMcpDiscoveryMetadataRouteFamily,
readAssistantMcpDiscoveryMetadataRouteFamilySelectionBasis,
readAssistantMcpDiscoveryMetadataSelectedEntitySet,
readAssistantMcpDiscoveryMetadataSelectedSurfaceObjects,
readAssistantMcpDiscoveryMetadataRecommendedNextPrimitive,
readAssistantMcpDiscoveryRankingNeed,
readAssistantMcpDiscoveryLoopStatus,
readAssistantMcpDiscoveryLoopSelectedChainId,
readAssistantMcpDiscoveryLoopPendingAxes,
readAssistantMcpDiscoveryLoopProvidedAxes,
readAssistantMcpDiscoveryLoopAskedDomainFamily,
readAssistantMcpDiscoveryLoopAskedActionFamily,
readAssistantMcpDiscoveryLoopUnsupportedFamily,
readAssistantMcpDiscoveryLoopMetadataScopeHint,
readAssistantMcpDiscoveryLoopSubjectResolutionOptional,
readAddressDebugTemporalScope,
readAssistantMcpDiscoveryPilotScope,
resolveOrganizationClarificationContinuation,
resolveNavigationSessionContextState,
resolveAddressDebugCarryoverFilters,
resolveAddressDebugAnchorContext,
resolveDisplayedEntityFollowupRetarget,
resolveFollowupTargetIntent,
resolveInventoryFollowupPivotFlags,
resolveAssistantOrganizationAuthority
} from "./assistantContinuityPolicy";
export function createAssistantTransitionPolicy(deps) {
function normalizeFollowupText(value) {
return deps.compactWhitespace(deps.repairAddressMojibake(String(value ?? "")).toLowerCase()).replace(/ё/g, "е");
}
function hasBankOperationsPivotCue(text) {
const normalized = normalizeFollowupText(text);
if (!normalized) {
return false;
}
return /(?:плаСРµР|плаССР|банк|банковск|операС|РІСРїРёСЃРє|РїРѕСЃСуплен|списан)/iu.test(
normalized
);
}
function hasContractsPivotCue(text) {
const normalized = normalizeFollowupText(text);
if (!normalized) {
return false;
}
return /(?:РґРѕРіРѕРІРѕСЂ)/iu.test(normalized);
}
function hasDocumentsPivotCue(text) {
const normalized = normalizeFollowupText(text);
if (!normalized) {
return false;
}
return /(?:докуменС|СЃСРµС|СЃССС|накладн|акС)/iu.test(normalized);
}
function hasReadableBankOperationsPivotCue(text) {
const normalized = normalizeFollowupText(text).replace(/ё/g, "е");
if (!normalized) {
return false;
}
return /(?:платеж|оплат|банк|банковск|операц|поступлен|списан|выписк|перевод|payment|bank|transaction)/iu.test(
normalized
);
}
function hasReadableContractsPivotCue(text) {
const normalized = normalizeFollowupText(text).replace(/ё/g, "е");
if (!normalized) {
return false;
}
return /(?:договор|контракт|соглашен|contract|agreement)/iu.test(normalized);
}
function hasReadableDocumentsPivotCue(text) {
const normalized = normalizeFollowupText(text).replace(/ё/g, "е");
if (!normalized) {
return false;
}
return /(?:документ|счет|счет-фактур|накладн|акт|реализац|document|invoice|receipt)/iu.test(normalized);
}
function selectSuggestedIntentByPivotCue(suggestedIntents, userMessage, alternateMessage = null) {
if (!Array.isArray(suggestedIntents) || suggestedIntents.length === 0) {
return null;
}
const samples = [userMessage, alternateMessage].filter((item) => deps.toNonEmptyString(item));
if (samples.length === 0) {
return null;
}
if (
suggestedIntents.includes("bank_operations_by_counterparty") &&
samples.some((sample) => hasBankOperationsPivotCue(sample) || hasReadableBankOperationsPivotCue(sample))
) {
return "bank_operations_by_counterparty";
}
if (
suggestedIntents.includes("bank_operations_by_contract") &&
samples.some((sample) => hasBankOperationsPivotCue(sample) || hasReadableBankOperationsPivotCue(sample))
) {
return "bank_operations_by_contract";
}
if (
suggestedIntents.includes("list_contracts_by_counterparty") &&
samples.some((sample) => hasContractsPivotCue(sample) || hasReadableContractsPivotCue(sample))
) {
return "list_contracts_by_counterparty";
}
if (
suggestedIntents.includes("list_documents_by_counterparty") &&
samples.some((sample) => hasDocumentsPivotCue(sample) || hasReadableDocumentsPivotCue(sample))
) {
return "list_documents_by_counterparty";
}
if (
suggestedIntents.includes("list_documents_by_contract") &&
samples.some((sample) => hasDocumentsPivotCue(sample) || hasReadableDocumentsPivotCue(sample))
) {
return "list_documents_by_contract";
}
return null;
}
function hasSelectedObjectInventoryScopeSignal(text) {
const normalized = normalizeFollowupText(text);
if (!normalized) {
return false;
}
return /(?:по\s+выбранному\s+объекту|по\s+выбранной\s+позиции|по\s+этой\s+позиции|по\s+этому\s+товару|selected\s+object)/iu.test(
normalized
);
}
function extractSelectedObjectLabel(text) {
const repaired = deps.repairAddressMojibake(String(text ?? ""));
const quotedMatch = repaired.match(
/(?:по\s+выбранному\s+объекту|по\s+выбранной\s+позиции)\s*[:,-]?\s*[«"]([^"»]+?)["»]/iu
);
if (quotedMatch?.[1]) {
return deps.toNonEmptyString(quotedMatch[1]);
}
return null;
}
function inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage = null) {
const samples = [userMessage, alternateMessage].map((item) => normalizeFollowupText(item)).filter(Boolean);
if (samples.length === 0) {
return null;
}
if (
samples.some((sample) =>
/(?:где\s+(?:мы\s+)?взял|откуда\s+(?:мы\s+)?взял|у\s+кого\s+купил|кто\s+постав|поставщик|источник\s+поступл|от\s+кого\s+поступ)/iu.test(
sample
)
)
) {
return "inventory_purchase_provenance_for_item";
}
if (
samples.some((sample) =>
/(?:документ|накладн|счет|сч[её]т|акт|поступл|покажи\s+док|все\s+документ|все\s+операц)/iu.test(sample)
)
) {
return "inventory_purchase_documents_for_item";
}
if (
samples.some((sample) =>
/(?:кому\s+продал|кому\s+ушл|куда\s+продал|кто\s+купил|реализац|отгруз|продаж)/iu.test(sample)
)
) {
return "inventory_sale_trace_for_item";
}
if (samples.some((sample) => /(?:рентабел|маржин|прибыл|наценк|выгод)/iu.test(sample))) {
return "inventory_profitability_for_item";
}
if (samples.some((sample) => /(?:цепочк|от\s+закупк.*до\s+продаж|от\s+покупк.*до\s+продаж)/iu.test(sample))) {
return "inventory_purchase_to_sale_chain";
}
return null;
}
function hasExplicitSummaryBundleReuseSignal(userMessage, alternateMessage = null) {
const samples = [userMessage, alternateMessage].map((item) => normalizeFollowupText(item)).filter(Boolean);
return samples.some(
(sample) =>
/(?:итог|summary|резюм|вывод|что\s+(?:мы\s+)?подтверд|что\s+понят|что\s+можно|что\s+нельзя|собери\s+коротк)/iu.test(
sample
) && /(?:контрагент|группа\s+свк|свк|отдельн)/iu.test(sample)
);
}
function parseDmyDateToIso(value) {
const match = String(value ?? "").trim().match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
if (!match) {
return null;
}
return `${match[3]}-${match[2]}-${match[1]}`;
}
function computeMonthWindowFromIso(isoDate) {
const match = String(isoDate ?? "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
if (!match) {
return null;
}
const year = Number(match[1]);
const month = Number(match[2]);
if (!Number.isFinite(year) || !Number.isFinite(month) || month < 1 || month > 12) {
return null;
}
const lastDay = new Date(Date.UTC(year, month, 0)).getUTCDate();
const mm = String(month).padStart(2, "0");
const dd = String(lastDay).padStart(2, "0");
return {
purchase_date: isoDate,
period_from: `${year}-${mm}-01`,
period_to: `${year}-${mm}-${dd}`,
as_of_date: `${year}-${mm}-${dd}`
};
}
function extractEarliestDmyDateFromEntityRefs(entityRefs) {
const dates = [];
for (const entityRef of Array.isArray(entityRefs) ? entityRefs : []) {
const value = deps.toNonEmptyString(entityRef?.value);
if (!value) {
continue;
}
const matches = String(value).match(/\b(\d{2}\.\d{2}\.\d{4})\b/g);
if (!matches) {
continue;
}
for (const token of matches) {
const isoDate = parseDmyDateToIso(token);
if (isoDate) {
dates.push(isoDate);
}
}
}
if (dates.length === 0) {
return null;
}
return dates.sort()[0] ?? null;
}
function extractPurchaseDateBridgeWindow(previousAddressItem, addressNavigationState) {
const replyText = deps.toNonEmptyString(previousAddressItem?.text);
if (replyText) {
const repairedText = deps.repairAddressMojibake(replyText);
const explicitFirstDateMatch = repairedText.match(/первая\s+найденная\s+дата\s+закупки:\s*(\d{2}\.\d{2}\.\d{4})/iu);
const explicitFirstDateIso = explicitFirstDateMatch ? parseDmyDateToIso(explicitFirstDateMatch[1]) : null;
if (explicitFirstDateIso) {
return computeMonthWindowFromIso(explicitFirstDateIso);
}
}
const navigationSessionState = resolveNavigationSessionContextState(
addressNavigationState,
deps.toNonEmptyString,
deps.normalizeOrganizationScopeValue
);
const focusObject = navigationSessionState.focusObject;
const preferredResultSetId =
deps.toNonEmptyString(focusObject?.provenanceResultSetId) ?? navigationSessionState.activeResultSetId;
const resultSets = Array.isArray(addressNavigationState?.result_sets) ? addressNavigationState.result_sets : [];
const preferredResultSet =
(preferredResultSetId
? resultSets.find((item) => deps.toNonEmptyString(item?.result_set_id) === preferredResultSetId) ?? null
: null) ??
resultSets.find((item) => deps.toNonEmptyString(item?.intent) === "inventory_purchase_provenance_for_item") ??
null;
const earliestIsoDate = extractEarliestDmyDateFromEntityRefs(preferredResultSet?.entity_refs);
return earliestIsoDate ? computeMonthWindowFromIso(earliestIsoDate) : null;
}
function isUsableFollowupSourceDebug(debug) {
if (!debug || typeof debug !== "object") {
return false;
}
const executionLane = deps.toNonEmptyString(debug.execution_lane);
const detectedIntent = readAddressDebugIntent(debug, deps.toNonEmptyString);
const selectedRecipe = deps.toNonEmptyString(debug.selected_recipe);
const answerGroundingCheck =
debug.answer_grounding_check && typeof debug.answer_grounding_check === "object"
? debug.answer_grounding_check
: null;
const groundingStatus = deps.toNonEmptyString(answerGroundingCheck?.status);
const discoveryPilotScope = readAssistantMcpDiscoveryPilotScope(debug, deps.toNonEmptyString);
if (groundingStatus === "grounded") {
return true;
}
if (selectedRecipe) {
return true;
}
if (debug.mcp_discovery_response_applied === true && discoveryPilotScope) {
return true;
}
return executionLane === "address_query" && Boolean(detectedIntent && detectedIntent !== "unknown");
}
function findRecentUsableAddressAssistantItem(items) {
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
const item = items[index];
if (!item || item.role !== "assistant" || !item.debug || typeof item.debug !== "object") {
continue;
}
if (isUsableFollowupSourceDebug(item.debug)) {
return item;
}
}
return null;
}
function findRecentInventoryPurchaseProvenanceItem(items, itemHint = null) {
const normalizedItemHint = deps.toNonEmptyString(itemHint);
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
const item = items[index];
const debug = item?.debug;
if (!item || item.role !== "assistant" || !debug || typeof debug !== "object") {
continue;
}
if (deps.toNonEmptyString(debug.detected_intent) !== "inventory_purchase_provenance_for_item") {
continue;
}
if (!normalizedItemHint) {
return item;
}
const candidateItem = readAddressDebugItem(debug, deps.toNonEmptyString);
if (candidateItem && candidateItem === normalizedItemHint) {
return item;
}
}
return null;
}
function readMcpDiscoveryBidirectionalValueFlow(debug) {
const entryPoint = debug?.assistant_mcp_discovery_entry_point_v1;
const flow = entryPoint?.bridge?.pilot?.derived_bidirectional_value_flow;
if (!flow || typeof flow !== "object" || Array.isArray(flow)) {
return null;
}
return flow;
}
function readCounterpartyDocumentSummaryFromItem(item) {
const text = deps.toNonEmptyString(item?.text);
if (!text) {
return null;
}
const firstLine = text.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "";
const match = firstLine.match(/Контрагент:\s*([^.\n]+)\.\s*Найдено документов:\s*(\d+)/iu);
if (!match?.[1] || !match?.[2]) {
return null;
}
return {
counterparty: deps.toNonEmptyString(match[1]),
document_count: Number(match[2]),
direct_answer: firstLine
};
}
function findRecentDiscoveryValueFlowBundle(items) {
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
const item = items[index];
const debug = item?.debug;
if (!item || item.role !== "assistant" || !debug || typeof debug !== "object") {
continue;
}
const flow = readMcpDiscoveryBidirectionalValueFlow(debug);
if (flow) {
return flow;
}
}
return null;
}
function findRecentCounterpartyDocumentBundle(items) {
for (let index = Array.isArray(items) ? items.length - 1 : -1; index >= 0; index -= 1) {
const item = items[index];
if (!item || item.role !== "assistant" || !item.debug || typeof item.debug !== "object") {
continue;
}
const summary = readCounterpartyDocumentSummaryFromItem(item);
if (summary) {
return summary;
}
}
return null;
}
function hasInventoryPurchaseDateVatBridgeSignal(userMessage, alternateMessage, sourceIntentHint, hasInventoryItemFocusHint) {
if (
sourceIntentHint !== "inventory_purchase_provenance_for_item" &&
!hasInventoryItemFocusHint &&
!deps.isInventorySelectedObjectIntent(sourceIntentHint)
) {
return false;
}
const samples = [userMessage, alternateMessage]
.map((item) => deps.compactWhitespace(deps.repairAddressMojibake(String(item ?? "")).toLowerCase()))
.filter((item) => item.length > 0);
if (samples.length === 0) {
return false;
}
return samples.some(
(sample) =>
/(?:ндс|vat)/iu.test(sample) &&
/(?:на\s+дат[ауеы]\s+покупк|на\s+дат[ауеы]\s+закупк|по\s+дат[еу]\s+покупк|по\s+дат[еу]\s+закупк|дата\s+покупк|дата\s+закупк|purchase\s+date)/iu.test(
sample
)
);
}
function hasInventoryRootRestatementLikeSignal(userMessage, sourceIntentHint, hasInventoryRootFrame) {
if (!hasInventoryRootFrame) {
return false;
}
const normalized = deps
.compactWhitespace(deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase())
.replace(/ё/g, "е");
if (!normalized) {
return false;
}
if (deps.countTokens(normalized) > 10) {
return false;
}
const hasInventoryLexeme = /(?:остат|склад|товар|номенклатур|позиц)/iu.test(normalized);
const hasRestatementCue =
/(?:еще\s+раз|снова|повтори|повтори\s+еще\s+раз|верни|покажи)/iu.test(normalized) &&
/(?:на\s+ту\s+же\s+дат[ауеы]|на\s+эту\s+же\s+дат[ауеы]|на\s+эту\s+дат[ауеы]|эту\s+дат[ауеы]|та\s+же\s+дата|тот\s+же\s+период|этот\s+же\s+период)/iu.test(
normalized
);
const hasBareSnapshotSameDateCue =
hasInventoryLexeme &&
/(?:РЅР°\s+ССѓ\s+РРµ\s+РґР°С[ауеС]|РЅР°\s+СЌССѓ\s+РРµ\s+РґР°С[ауеС]|РЅР°\s+СЌССѓ\s+РґР°С[ауеС]|СЌССѓ\s+РґР°С[ауеС]|СР°\s+РРµ\s+РґР°СР°|СРѕС\s+РРµ\s+период|СЌСРѕС\s+РРµ\s+период)/iu.test(
normalized
);
const bareSnapshotSameDatePhrases = [
"\u043d\u0430 \u0442\u0443 \u0436\u0435 \u0434\u0430\u0442",
"\u043d\u0430 \u044d\u0442\u0443 \u0436\u0435 \u0434\u0430\u0442",
"\u043d\u0430 \u044d\u0442\u0443 \u0434\u0430\u0442",
"\u044d\u0442\u0443 \u0434\u0430\u0442",
"\u0442\u0430 \u0436\u0435 \u0434\u0430\u0442\u0430",
"\u0442\u043e\u0442 \u0436\u0435 \u043f\u0435\u0440\u0438\u043e\u0434",
"\u044d\u0442\u043e\u0442 \u0436\u0435 \u043f\u0435\u0440\u0438\u043e\u0434"
];
const hasBareSnapshotSameDatePhraseCue =
hasInventoryLexeme && bareSnapshotSameDatePhrases.some((phrase) => normalized.includes(phrase));
return (
hasInventoryLexeme &&
(hasRestatementCue || hasBareSnapshotSameDateCue || hasBareSnapshotSameDatePhraseCue) &&
!deps.hasForeignAccountingPivotOverInventoryMessage(normalized)
);
}
function hasExplicitInventorySameDatePivotSignal(userMessage) {
const normalized = deps
.compactWhitespace(deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase())
.replace(/ё/g, "е");
if (!normalized) {
return false;
}
const hasInventoryLexeme = /(?:остат|склад|товар|номенклатур|позиц)/iu.test(normalized);
if (!hasInventoryLexeme) {
return false;
}
const sameDatePhrases = [
"на ту же дат",
"на эту же дат",
"на эту дат",
"эту дат",
"та же дата",
"тот же период",
"этот же период"
];
return sameDatePhrases.some((phrase) => normalized.includes(phrase));
}
function hasShortValueFlowRetargetCue(text) {
const normalized = normalizeFollowupText(text);
if (!normalized) {
return false;
}
const tokenCount = deps.countTokens(normalized);
if (!Number.isFinite(tokenCount) || tokenCount > 8) {
return false;
}
const hasLeadCue =
deps.hasFollowupMarker(text) ||
deps.hasReferentialPointer(text) ||
/^(?:\u0430|\u0438|also|then|now)(?=$|[\s,.;:!?])/iu.test(normalized);
if (!hasLeadCue) {
return false;
}
return /(?:\u043d\u0435\u0442\u0442\u043e|\u0441\u0430\u043b\u044c\u0434\u043e|\u0440\u0430\u0437\u043d\u0438\u0446|\u043f\u043e\u043b\u0443\u0447|\u0437\u0430\u043f\u043b\u0430\u0442|\u043f\u043e\u0441\u0442\u0443\u043f|\u0432\u0445\u043e\u0434\u044f\u0449|\u0438\u0441\u0445\u043e\u0434\u044f\u0449|\u043e\u0431\u043e\u0440\u043e\u0442|\u0432\u044b\u0440\u0443\u0447\u043a|\u0434\u0435\u043d\u0435\u0436)/iu.test(
normalized
);
}
function shouldKeepPreviousIntentForShortCounterpartyRetarget(userMessage, sourceIntent) {
const normalized = deps.compactWhitespace(
deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase()
);
if (!normalized || deps.countTokens(normalized) > 4) {
return false;
}
if (sourceIntent !== "list_documents_by_counterparty" && sourceIntent !== "list_documents_by_contract") {
return false;
}
if (
/(?:банк|РІСРїРёСЃРє|плаС[РµС]Р|оплаС|списан|РїРѕСЃСуплен|bank|payment|wire|statement)/iu.test(
normalized
)
) {
return false;
}
return /^(?:Р°|Рё|РЅСѓ)?\s*РїРѕ\s+[a-zР°-СЏС0-9._-]{2,}(?:\s+[a-zР°-СЏС0-9._-]{2,})?$/iu.test(normalized);
}
function shouldKeepPreviousIntentForShortCounterpartyRetargetV2(userMessage, sourceIntent) {
const normalized = deps.compactWhitespace(
deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase()
);
if (!normalized || deps.countTokens(normalized) > 4) {
return false;
}
if (sourceIntent !== "list_documents_by_counterparty" && sourceIntent !== "list_documents_by_contract") {
return false;
}
if (/(?:bank|payment|wire|statement)/iu.test(normalized)) {
return false;
}
return /^(?:а|и|ну)?\s*(?:покажи\s+)?по\s+[a-zа-яё0-9._-]{2,}(?:\s+[a-zа-яё0-9._-]{2,})?$/iu.test(normalized);
}
function inferStandaloneAddressTopicFamily(userMessage) {
const normalized = deps.compactWhitespace(
deps.repairAddressMojibake(String(userMessage ?? "")).toLowerCase()
);
if (!normalized) {
return null;
}
if (/(?:ндс|vat)/iu.test(normalized)) {
return "vat";
}
if (/(?:остат|склад|товар|номенклатур|позици)/iu.test(normalized)) {
return "inventory";
}
return null;
}
function resolveAddressFollowupCarryoverContext(
userMessage,
items,
alternateMessage = null,
llmPreDecomposeMeta = null,
addressNavigationState = null
) {
const rawCapabilityMetaQuery =
deps.shouldHandleAsAssistantCapabilityMetaQuery(userMessage) ||
(deps.toNonEmptyString(alternateMessage)
? deps.shouldHandleAsAssistantCapabilityMetaQuery(String(alternateMessage ?? ""))
: false);
const rawDataRetrievalSignal =
deps.hasDataRetrievalRequestSignal(userMessage) ||
(deps.toNonEmptyString(alternateMessage)
? deps.hasDataRetrievalRequestSignal(String(alternateMessage ?? ""))
: false);
if (rawCapabilityMetaQuery && !rawDataRetrievalSignal) {
return null;
}
const assistantTurnMeaning =
typeof deps.resolveAssistantTurnMeaning === "function"
? deps.resolveAssistantTurnMeaning({
rawUserMessage: userMessage,
effectiveAddressUserMessage: alternateMessage ?? userMessage,
llmPreDecomposeMeta
})
: null;
if (
assistantTurnMeaning?.stale_replay_forbidden === true &&
!hasExplicitSummaryBundleReuseSignal(userMessage, alternateMessage)
) {
return null;
}
const latestAddressItem = deps.findLastAddressAssistantItem(items);
const previousAddressItem =
(latestAddressItem && isUsableFollowupSourceDebug(latestAddressItem?.debug)
? latestAddressItem
: findRecentUsableAddressAssistantItem(items)) ?? latestAddressItem;
const previousAddressDebug = previousAddressItem?.debug ?? null;
const lastOrganizationClarificationDebug = deps.findLastOrganizationClarificationAddressDebug(items);
const organizationAuthority = resolveAssistantOrganizationAuthority({
sessionItems: items,
lastOrganizationClarificationDebug,
toNonEmptyString: deps.toNonEmptyString,
normalizeOrganizationScopeValue: deps.normalizeOrganizationScopeValue,
mergeKnownOrganizations: deps.mergeKnownOrganizations
});
const continuitySnapshot = organizationAuthority.continuitySnapshot;
const continuityTemporalScope = readAddressDebugTemporalScope(
continuitySnapshot.lastGroundedAddressDebug,
deps.toNonEmptyString
);
const organizationClarificationCandidates = Array.isArray(organizationAuthority.organizationClarificationCandidates)
? organizationAuthority.organizationClarificationCandidates
: [];
const organizationClarificationContinuation = resolveOrganizationClarificationContinuation({
rawMessages: [userMessage, alternateMessage],
organizationClarificationCandidates,
organizationClarificationSelectionFromScope: organizationAuthority.organizationClarificationSelectionFromScope,
lastOrganizationClarificationDebug,
resolveOrganizationSelectionFromMessage: deps.resolveOrganizationSelectionFromMessage,
toNonEmptyString: deps.toNonEmptyString,
normalizeOrganizationScopeValue: deps.normalizeOrganizationScopeValue
});
const explicitOrganizationClarificationSelection = organizationClarificationContinuation.explicitSelection;
const organizationClarificationSelection = organizationClarificationContinuation.selection;
const hasOrganizationClarificationContinuation = organizationClarificationContinuation.hasContinuation;
const carryoverSourceDebug =
previousAddressDebug ??
(hasOrganizationClarificationContinuation ? lastOrganizationClarificationDebug : null);
const followupOffer = carryoverSourceDebug ? deps.buildAddressFollowupOffer(carryoverSourceDebug) : null;
const suggestedIntentFromPivotCue = selectSuggestedIntentByPivotCue(
Array.isArray(followupOffer?.suggested_intents) ? followupOffer.suggested_intents : [],
userMessage,
alternateMessage
);
const hasSuggestedIntentPivotSignal =
Boolean(previousAddressDebug) &&
Boolean(followupOffer?.enabled) &&
Boolean(suggestedIntentFromPivotCue);
const hasImplicitContinuationSignal =
Boolean(previousAddressDebug) &&
Boolean(followupOffer?.enabled) &&
(deps.isImplicitAddressContinuationByLlm(userMessage, llmPreDecomposeMeta) ||
(deps.toNonEmptyString(alternateMessage)
? deps.isImplicitAddressContinuationByLlm(alternateMessage, llmPreDecomposeMeta)
: false));
const sourceIntentHint = readAddressDebugIntent(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryPilotScopeHint = readAssistantMcpDiscoveryPilotScope(
carryoverSourceDebug,
deps.toNonEmptyString
);
const hasValueFlowCarryoverSourceHint =
sourceIntentHint === "customer_revenue_and_payments" ||
sourceDiscoveryPilotScopeHint === "counterparty_value_flow_query_movements_v1" ||
sourceDiscoveryPilotScopeHint === "counterparty_supplier_payout_query_movements_v1" ||
sourceDiscoveryPilotScopeHint === "counterparty_bidirectional_value_flow_query_movements_v1";
const navigationSessionState = resolveNavigationSessionContextState(
addressNavigationState,
deps.toNonEmptyString,
deps.normalizeOrganizationScopeValue
);
const navigationFocusObjectHint = navigationSessionState.focusObject;
const hasNavigationInventoryItemFocusHint = Boolean(
deps.toNonEmptyString(navigationFocusObjectHint?.label) &&
deps.toNonEmptyString(navigationFocusObjectHint?.objectType) === "item" &&
(sourceIntentHint === "inventory_on_hand_as_of_date" ||
sourceIntentHint === "inventory_supplier_stock_overlap_as_of_date" ||
deps.isInventorySelectedObjectIntent(sourceIntentHint))
);
const inventoryPurchaseDateVatBridge = hasInventoryPurchaseDateVatBridgeSignal(
userMessage,
alternateMessage,
sourceIntentHint,
hasNavigationInventoryItemFocusHint
);
let inventoryShortFollowupPrimary =
(deps.isInventorySelectedObjectIntent(sourceIntentHint) || hasNavigationInventoryItemFocusHint) &&
deps.hasShortInventoryObjectFollowupSignal(userMessage);
let inventoryShortFollowupAlternate =
(deps.isInventorySelectedObjectIntent(sourceIntentHint) || hasNavigationInventoryItemFocusHint) &&
deps.toNonEmptyString(alternateMessage)
? deps.hasShortInventoryObjectFollowupSignal(String(alternateMessage ?? ""))
: false;
const debtRoleSwapPrimary = sourceIntentHint
? deps.resolveDebtRoleSwapFollowupIntent(userMessage, sourceIntentHint)
: null;
const debtRoleSwapAlternate =
sourceIntentHint && deps.toNonEmptyString(alternateMessage)
? deps.resolveDebtRoleSwapFollowupIntent(String(alternateMessage ?? ""), sourceIntentHint)
: null;
const debtRoleSwapIntent = debtRoleSwapPrimary ?? debtRoleSwapAlternate ?? null;
const shortValueFlowRetargetPrimary =
hasValueFlowCarryoverSourceHint && hasShortValueFlowRetargetCue(userMessage);
const shortValueFlowRetargetAlternate =
hasValueFlowCarryoverSourceHint && deps.toNonEmptyString(alternateMessage)
? hasShortValueFlowRetargetCue(String(alternateMessage ?? ""))
: false;
const explicitSummaryBundleReuseSignal = hasExplicitSummaryBundleReuseSignal(userMessage, alternateMessage);
let hasPrimaryFollowupSignal =
deps.hasAddressFollowupContextSignal(userMessage) ||
Boolean(debtRoleSwapPrimary) ||
shortValueFlowRetargetPrimary ||
inventoryShortFollowupPrimary ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal;
let hasAlternateFollowupSignal = deps.toNonEmptyString(alternateMessage)
? deps.hasAddressFollowupContextSignal(alternateMessage) ||
Boolean(debtRoleSwapAlternate) ||
shortValueFlowRetargetAlternate ||
inventoryShortFollowupAlternate ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal
: false;
const hasPrimaryIndexReferenceSignal = deps.extractDisplayedEntityIndexMention(userMessage) !== null;
const hasAlternateIndexReferenceSignal = deps.toNonEmptyString(alternateMessage)
? deps.extractDisplayedEntityIndexMention(String(alternateMessage ?? "")) !== null
: false;
const hasIndexReferenceSignal = hasPrimaryIndexReferenceSignal || hasAlternateIndexReferenceSignal;
const recentInventoryRootFrame = deps.findRecentInventoryRootFrame(items);
const hasInventoryRootTemporalFollowupPrimary = deps.hasInventoryRootTemporalFollowupSignal(
userMessage,
sourceIntentHint,
Boolean(recentInventoryRootFrame)
);
const hasInventoryRootTemporalFollowupAlternate = deps.toNonEmptyString(alternateMessage)
? deps.hasInventoryRootTemporalFollowupSignal(
String(alternateMessage ?? ""),
sourceIntentHint,
Boolean(recentInventoryRootFrame)
)
: false;
const hasInventoryRootRestatementPrimary = hasInventoryRootRestatementLikeSignal(
userMessage,
sourceIntentHint,
Boolean(recentInventoryRootFrame)
);
const hasInventoryRootRestatementAlternate = deps.toNonEmptyString(alternateMessage)
? hasInventoryRootRestatementLikeSignal(
String(alternateMessage ?? ""),
sourceIntentHint,
Boolean(recentInventoryRootFrame)
)
: false;
const hasExplicitInventorySameDatePivotPrimary = hasExplicitInventorySameDatePivotSignal(userMessage);
const hasExplicitInventorySameDatePivotAlternate = deps.toNonEmptyString(alternateMessage)
? hasExplicitInventorySameDatePivotSignal(String(alternateMessage ?? ""))
: false;
let hasStrongFollowupReference =
hasPrimaryIndexReferenceSignal ||
hasAlternateIndexReferenceSignal ||
hasOrganizationClarificationContinuation ||
hasImplicitContinuationSignal ||
hasSuggestedIntentPivotSignal ||
inventoryShortFollowupPrimary ||
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
shortValueFlowRetargetPrimary ||
shortValueFlowRetargetAlternate ||
deps.hasFollowupMarker(userMessage) ||
deps.hasReferentialPointer(userMessage) ||
(deps.toNonEmptyString(alternateMessage)
? deps.hasFollowupMarker(String(alternateMessage ?? "")) ||
deps.hasReferentialPointer(String(alternateMessage ?? ""))
: false);
const hasConcreteFollowupReference =
hasPrimaryIndexReferenceSignal ||
hasAlternateIndexReferenceSignal ||
hasOrganizationClarificationContinuation ||
inventoryShortFollowupPrimary ||
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
shortValueFlowRetargetPrimary ||
shortValueFlowRetargetAlternate ||
deps.hasFollowupMarker(userMessage) ||
deps.hasReferentialPointer(userMessage) ||
(deps.toNonEmptyString(alternateMessage)
? deps.hasFollowupMarker(String(alternateMessage ?? "")) ||
deps.hasReferentialPointer(String(alternateMessage ?? ""))
: false);
const hasCurrentTurnExplicitEntity =
Array.isArray(assistantTurnMeaning?.explicit_entity_candidates) &&
assistantTurnMeaning.explicit_entity_candidates.length > 0;
if (
assistantTurnMeaning?.intent_override_strength === "explicit_current_turn_intent" &&
hasCurrentTurnExplicitEntity &&
!hasConcreteFollowupReference
) {
return null;
}
const hasStandaloneAddressTopic =
deps.hasStandaloneAddressTopicSignal(userMessage) ||
(deps.toNonEmptyString(alternateMessage) ? deps.hasStandaloneAddressTopicSignal(alternateMessage) : false);
if (
hasStandaloneAddressTopic &&
!hasPrimaryFollowupSignal &&
!hasAlternateFollowupSignal &&
!hasInventoryRootTemporalFollowupPrimary &&
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!hasImplicitContinuationSignal &&
!hasSuggestedIntentPivotSignal &&
!hasOrganizationClarificationContinuation &&
!hasIndexReferenceSignal &&
!explicitSummaryBundleReuseSignal
) {
return null;
}
if (
!hasPrimaryFollowupSignal &&
!hasAlternateFollowupSignal &&
!hasInventoryRootTemporalFollowupPrimary &&
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!hasImplicitContinuationSignal &&
!hasSuggestedIntentPivotSignal &&
!hasOrganizationClarificationContinuation &&
!hasIndexReferenceSignal &&
!explicitSummaryBundleReuseSignal
) {
return null;
}
if (!carryoverSourceDebug) {
return null;
}
const sourceIntent = readAddressDebugIntent(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryPilotScope = sourceDiscoveryPilotScopeHint;
const sourceDiscoveryMetadataRouteFamily = readAssistantMcpDiscoveryMetadataRouteFamily(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryMetadataRouteFamilySelectionBasis =
readAssistantMcpDiscoveryMetadataRouteFamilySelectionBasis(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataSelectedEntitySet = readAssistantMcpDiscoveryMetadataSelectedEntitySet(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryMetadataSelectedSurfaceObjects = readAssistantMcpDiscoveryMetadataSelectedSurfaceObjects(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryMetadataRecommendedNextPrimitive =
readAssistantMcpDiscoveryMetadataRecommendedNextPrimitive(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataAmbiguityDetected = readAssistantMcpDiscoveryMetadataAmbiguityDetected(
carryoverSourceDebug
);
const sourceDiscoveryMetadataAmbiguityEntitySets = readAssistantMcpDiscoveryMetadataAmbiguityEntitySets(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryEntityResolutionStatus = readAssistantMcpDiscoveryEntityResolutionStatus(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryEntityCandidates = readAssistantMcpDiscoveryEntityCandidates(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopStatus = readAssistantMcpDiscoveryLoopStatus(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryLoopSelectedChainId = readAssistantMcpDiscoveryLoopSelectedChainId(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopPendingAxes = readAssistantMcpDiscoveryLoopPendingAxes(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopProvidedAxes = readAssistantMcpDiscoveryLoopProvidedAxes(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopAskedDomainFamily = readAssistantMcpDiscoveryLoopAskedDomainFamily(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopAskedActionFamily = readAssistantMcpDiscoveryLoopAskedActionFamily(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopUnsupportedFamily = readAssistantMcpDiscoveryLoopUnsupportedFamily(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopMetadataScopeHint = readAssistantMcpDiscoveryLoopMetadataScopeHint(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryLoopSubjectResolutionOptional =
readAssistantMcpDiscoveryLoopSubjectResolutionOptional(carryoverSourceDebug);
const sourceDiscoveryRankingNeed = readAssistantMcpDiscoveryRankingNeed(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryEntityAmbiguityCandidates = readAssistantMcpDiscoveryEntityAmbiguityCandidates(
carryoverSourceDebug,
deps.toNonEmptyString
);
const sourceDiscoveryBidirectionalValueFlow =
readMcpDiscoveryBidirectionalValueFlow(carryoverSourceDebug) ?? findRecentDiscoveryValueFlowBundle(items);
const sourceDiscoveryDocumentSummary = findRecentCounterpartyDocumentBundle(items);
const llmExplicitIntent = deps.toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.intent);
const llmSelectedObjectScopeDetected =
llmPreDecomposeMeta?.predecomposeContract?.semantics?.selected_object_scope_detected === true;
const resolvedPrimaryIntent = deps.resolveAddressIntent(deps.repairAddressMojibake(String(userMessage ?? ""))).intent;
const resolvedAlternateIntent = deps.toNonEmptyString(alternateMessage)
? deps.resolveAddressIntent(deps.repairAddressMojibake(String(alternateMessage ?? ""))).intent
: null;
const assistantTurnMeaningIntent = deps.toNonEmptyString(assistantTurnMeaning?.explicit_intent_candidate);
const explicitIntent =
llmExplicitIntent && llmExplicitIntent !== "unknown"
? llmExplicitIntent
: resolvedPrimaryIntent && resolvedPrimaryIntent !== "unknown"
? resolvedPrimaryIntent
: resolvedAlternateIntent && resolvedAlternateIntent !== "unknown"
? resolvedAlternateIntent
: assistantTurnMeaningIntent && assistantTurnMeaningIntent !== "unknown"
? assistantTurnMeaningIntent
: null;
const sourceIntentFamily = deps.resolveAddressIntentFamily(sourceIntent);
const explicitIntentFamily =
deps.resolveAddressIntentFamily(explicitIntent) ??
inferStandaloneAddressTopicFamily(userMessage) ??
(deps.toNonEmptyString(alternateMessage) ? inferStandaloneAddressTopicFamily(String(alternateMessage ?? "")) : null);
const foreignAccountingPivotOverInventory = deps.hasForeignAccountingPivotOverInventoryMessage(
userMessage,
alternateMessage
);
const familyMismatchStandaloneTopic = Boolean(
hasStandaloneAddressTopic &&
sourceIntentFamily &&
explicitIntentFamily &&
sourceIntentFamily !== explicitIntentFamily &&
!hasOrganizationClarificationContinuation &&
!hasImplicitContinuationSignal &&
!hasIndexReferenceSignal &&
!hasInventoryRootTemporalFollowupPrimary &&
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!inventoryShortFollowupPrimary &&
!inventoryShortFollowupAlternate &&
!foreignAccountingPivotOverInventory &&
!deps.hasFollowupMarker(userMessage) &&
!deps.hasReferentialPointer(userMessage) &&
(!deps.toNonEmptyString(alternateMessage)
? true
: !deps.hasFollowupMarker(String(alternateMessage ?? "")) &&
!deps.hasReferentialPointer(String(alternateMessage ?? "")))
);
if (familyMismatchStandaloneTopic) {
return null;
}
if (
sourceIntentFamily &&
explicitIntentFamily &&
sourceIntentFamily !== explicitIntentFamily &&
!hasStrongFollowupReference &&
!foreignAccountingPivotOverInventory
) {
return null;
}
let previousIntent = sourceIntent;
let followupSelectionMode = "carry_previous_intent";
if (debtRoleSwapIntent) {
previousIntent = debtRoleSwapIntent;
}
if (hasImplicitContinuationSignal || hasSuggestedIntentPivotSignal) {
const suggestedIntent = Array.isArray(followupOffer?.suggested_intents)
? suggestedIntentFromPivotCue ?? deps.toNonEmptyString(followupOffer.suggested_intents[0])
: null;
const keepPreviousIntent = shouldKeepPreviousIntentForShortCounterpartyRetargetV2(userMessage, sourceIntent);
if (suggestedIntent && !keepPreviousIntent) {
previousIntent = suggestedIntent;
followupSelectionMode = "switch_to_suggested_intent";
}
}
const previousAnchorContext = resolveAddressDebugAnchorContext(carryoverSourceDebug, deps.toNonEmptyString);
let previousAnchorType = previousAnchorContext.anchorType;
let previousAnchor = previousAnchorContext.anchorValue;
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" &&
navigationFocusObjectLabel &&
(sourceIntentHint === "inventory_on_hand_as_of_date" ||
sourceIntentHint === "inventory_supplier_stock_overlap_as_of_date" ||
deps.isInventorySelectedObjectIntent(sourceIntentHint));
if (!inventoryShortFollowupPrimary && hasInventoryItemFocusCarryover) {
inventoryShortFollowupPrimary = deps.hasShortInventoryObjectFollowupSignal(userMessage);
}
if (!inventoryShortFollowupAlternate && hasInventoryItemFocusCarryover && deps.toNonEmptyString(alternateMessage)) {
inventoryShortFollowupAlternate = deps.hasShortInventoryObjectFollowupSignal(String(alternateMessage ?? ""));
}
hasPrimaryFollowupSignal =
deps.hasAddressFollowupContextSignal(userMessage) ||
hasSuggestedIntentPivotSignal ||
Boolean(debtRoleSwapPrimary) ||
shortValueFlowRetargetPrimary ||
inventoryShortFollowupPrimary ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
hasInventoryRootTemporalFollowupPrimary;
hasAlternateFollowupSignal = deps.toNonEmptyString(alternateMessage)
? deps.hasAddressFollowupContextSignal(alternateMessage) ||
hasSuggestedIntentPivotSignal ||
Boolean(debtRoleSwapAlternate) ||
shortValueFlowRetargetAlternate ||
inventoryShortFollowupAlternate ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
hasInventoryRootTemporalFollowupAlternate
: false;
hasStrongFollowupReference =
hasPrimaryIndexReferenceSignal ||
hasAlternateIndexReferenceSignal ||
hasOrganizationClarificationContinuation ||
hasSuggestedIntentPivotSignal ||
hasImplicitContinuationSignal ||
inventoryShortFollowupPrimary ||
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
shortValueFlowRetargetPrimary ||
shortValueFlowRetargetAlternate ||
deps.hasFollowupMarker(userMessage) ||
deps.hasReferentialPointer(userMessage) ||
(deps.toNonEmptyString(alternateMessage)
? deps.hasFollowupMarker(String(alternateMessage ?? "")) ||
deps.hasReferentialPointer(String(alternateMessage ?? ""))
: false);
const hasSelectedObjectInventorySignalPrimary =
llmSelectedObjectScopeDetected || hasSelectedObjectInventoryScopeSignal(userMessage);
const hasSelectedObjectInventorySignalAlternate = deps.toNonEmptyString(alternateMessage)
? hasSelectedObjectInventoryScopeSignal(String(alternateMessage ?? ""))
: false;
const selectedObjectRetargetIntent =
hasSelectedObjectInventorySignalPrimary || hasSelectedObjectInventorySignalAlternate
? inferSelectedObjectInventoryFollowupIntent(userMessage, alternateMessage)
: null;
const inventoryRootFrameCandidate =
deps.findRecentInventoryRootFrame(items) ??
continuitySnapshot.inventoryRootFrame ??
buildInventoryRootFrameFromAddressDebug(continuitySnapshot.lastGroundedAddressDebug, deps.toNonEmptyString);
let { inventoryRootFrame, currentFrameKind } = hydrateInventoryRootFrameState(
inventoryRootFrameCandidate,
sourceIntent,
navigationOrganization,
navigationDateScope,
deps.toNonEmptyString,
deps.isInventoryDrilldownFrameIntent,
deps.isInventoryRootFrameIntent
);
let resolvedCounterpartyFromDisplay = false;
let displayedEntityTargetIntent = null;
let previousFilters = resolveAddressDebugCarryoverFilters(carryoverSourceDebug, deps.toNonEmptyString);
const shouldBackfillHistoricalPartyAnchors =
sourceIntentHint === "list_contracts_by_counterparty" ||
sourceIntentHint === "list_documents_by_counterparty" ||
sourceIntentHint === "bank_operations_by_counterparty" ||
sourceIntentHint === "list_documents_by_contract" ||
sourceIntentHint === "bank_operations_by_contract" ||
sourceIntentHint === "open_items_by_counterparty_or_contract";
previousFilters = applyHistoricalPartyCarryoverFilters(
previousFilters,
shouldBackfillHistoricalPartyAnchors,
deps.findRecentAddressFilterValue(items, "contract"),
deps.findRecentAddressFilterValue(items, "counterparty"),
deps.toNonEmptyString
);
const historicalOrganization = deps.findRecentAddressFilterValue(items, "organization");
const authorityActiveOrganization =
deps.normalizeOrganizationScopeValue(organizationAuthority.activeOrganization) ??
deps.normalizeOrganizationScopeValue(organizationAuthority.continuityActiveOrganization);
previousFilters = applyOrganizationCarryoverFilters(
previousFilters,
historicalOrganization,
authorityActiveOrganization,
continuitySnapshot.activeOrganization,
navigationOrganization,
organizationClarificationSelection,
deps.toNonEmptyString
);
if (inventoryPurchaseDateVatBridge) {
const purchaseBridgeItem =
previousAddressItem &&
deps.toNonEmptyString(carryoverSourceDebug?.detected_intent) === "inventory_purchase_provenance_for_item"
? previousAddressItem
: findRecentInventoryPurchaseProvenanceItem(
items,
deps.toNonEmptyString(navigationFocusObjectLabel) ??
readAddressDebugItem(carryoverSourceDebug, deps.toNonEmptyString) ??
deps.toNonEmptyString(previousFilters.item)
) ?? previousAddressItem;
const purchaseBridgeWindow = extractPurchaseDateBridgeWindow(purchaseBridgeItem, addressNavigationState);
if (purchaseBridgeWindow) {
previousFilters.period_from = purchaseBridgeWindow.period_from;
previousFilters.period_to = purchaseBridgeWindow.period_to;
}
}
previousFilters = applyTemporalCarryoverFilters(
previousFilters,
navigationDateScope,
continuityTemporalScope,
sourceIntentHint,
deps.toNonEmptyString
);
const { rootScopedPivot, explicitInventorySameDatePivot } = resolveInventoryFollowupPivotFlags(
inventoryRootFrame,
sourceIntentHint,
currentFrameKind,
deps.hasForeignAccountingPivotOverInventoryMessage(userMessage, alternateMessage),
inventoryPurchaseDateVatBridge,
hasInventoryRootTemporalFollowupPrimary,
hasInventoryRootTemporalFollowupAlternate,
hasInventoryRootRestatementPrimary,
hasInventoryRootRestatementAlternate,
hasExplicitInventorySameDatePivotPrimary,
hasExplicitInventorySameDatePivotAlternate,
deps.isInventorySelectedObjectIntent,
deps.isInventoryRootFrameIntent
);
if (rootScopedPivot) {
previousIntent = null;
previousAnchorType = null;
previousAnchor = null;
previousFilters = buildRootScopedCarryoverFilters(previousFilters, inventoryRootFrame, deps.toNonEmptyString);
currentFrameKind = inventoryRootFrame ? "inventory_root" : currentFrameKind;
followupSelectionMode = "carry_root_context";
}
const displayedEntityType = deps.inferDisplayedEntityTypeFromIntent(sourceIntent);
const displayedEntities = deps.extractDisplayedAddressEntityCandidates(
deps.toNonEmptyString(previousAddressItem?.text) ?? "",
displayedEntityType
);
const resolvedEntityFromFollowup =
deps.resolveDisplayedAddressEntityMention(userMessage, displayedEntities) ??
(deps.toNonEmptyString(alternateMessage)
? deps.resolveDisplayedAddressEntityMention(String(alternateMessage ?? ""), displayedEntities)
: null);
({
displayedEntityTargetIntent,
previousFilters,
previousAnchorType,
previousAnchorValue: previousAnchor,
followupSelectionMode,
resolvedCounterpartyFromDisplay
} = resolveDisplayedEntityFollowupRetarget(
userMessage,
resolvedEntityFromFollowup,
previousFilters,
previousAnchorType,
previousAnchor,
followupSelectionMode,
rootScopedPivot,
deps.compactWhitespace,
deps.repairAddressMojibake,
deps.toNonEmptyString
));
({
previousFilters,
previousAnchorType,
previousAnchorValue: previousAnchor
} = applySelectedItemCarryover(
previousFilters,
previousAnchorType,
previousAnchor,
rootScopedPivot,
sourceIntentHint === "inventory_on_hand_as_of_date" ||
sourceIntentHint === "inventory_purchase_provenance_for_item" ||
sourceIntentHint === "inventory_purchase_documents_for_item" ||
sourceIntentHint === "inventory_sale_trace_for_item" ||
sourceIntentHint === "inventory_profitability_for_item" ||
sourceIntentHint === "inventory_purchase_to_sale_chain" ||
sourceIntentHint === "inventory_aging_by_purchase_date" ||
hasSelectedObjectInventorySignalPrimary ||
hasSelectedObjectInventorySignalAlternate,
navigationFocusObjectType === "item" ? navigationFocusObjectLabel : null,
continuitySnapshot.activeItem,
extractSelectedObjectLabel(userMessage),
deps.toNonEmptyString(alternateMessage) ? extractSelectedObjectLabel(String(alternateMessage ?? "")) : null,
deps.toNonEmptyString
));
if (explicitOrganizationClarificationSelection && !previousAnchor) {
previousAnchorType = "organization";
previousAnchor = explicitOrganizationClarificationSelection;
}
if (
inventoryRootFrame &&
organizationClarificationSelection &&
!deps.toNonEmptyString(inventoryRootFrame.filters?.organization)
) {
inventoryRootFrame = {
...inventoryRootFrame,
filters: {
...(inventoryRootFrame.filters ?? {}),
organization: organizationClarificationSelection
}
};
}
if (!previousIntent && !previousAnchor && Object.keys(previousFilters).length === 0) {
return null;
}
const shouldAttachInventoryRootFrame = Boolean(
inventoryRootFrame &&
(rootScopedPivot ||
deps.isInventoryRootFrameIntent(sourceIntentHint) ||
deps.isInventorySelectedObjectIntent(sourceIntentHint) ||
hasNavigationInventoryItemFocusHint ||
inventoryShortFollowupPrimary ||
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasSelectedObjectInventorySignalPrimary ||
hasSelectedObjectInventorySignalAlternate)
);
const carryoverTargetIntent = resolveFollowupTargetIntent(
inventoryPurchaseDateVatBridge,
selectedObjectRetargetIntent,
explicitIntent,
sourceIntent,
followupSelectionMode,
deps.toNonEmptyString(inventoryRootFrame?.intent),
displayedEntityTargetIntent,
previousIntent,
explicitInventorySameDatePivot
);
return {
followupContext: {
previous_intent: previousIntent ?? undefined,
target_intent: carryoverTargetIntent,
previous_filters: previousFilters,
previous_anchor_type: previousAnchorType ?? undefined,
previous_anchor_value: previousAnchor,
previous_discovery_pilot_scope: sourceDiscoveryPilotScope ?? undefined,
previous_discovery_entity_resolution_status: sourceDiscoveryEntityResolutionStatus ?? undefined,
previous_discovery_entity_candidates:
sourceDiscoveryEntityCandidates.length > 0 ? sourceDiscoveryEntityCandidates : undefined,
previous_discovery_loop_status: sourceDiscoveryLoopStatus ?? undefined,
previous_discovery_loop_selected_chain_id: sourceDiscoveryLoopSelectedChainId ?? undefined,
previous_discovery_loop_pending_axes:
sourceDiscoveryLoopPendingAxes.length > 0 ? sourceDiscoveryLoopPendingAxes : undefined,
previous_discovery_loop_provided_axes:
sourceDiscoveryLoopProvidedAxes.length > 0 ? sourceDiscoveryLoopProvidedAxes : undefined,
previous_discovery_loop_asked_domain_family: sourceDiscoveryLoopAskedDomainFamily ?? undefined,
previous_discovery_loop_asked_action_family: sourceDiscoveryLoopAskedActionFamily ?? undefined,
previous_discovery_loop_unsupported_family: sourceDiscoveryLoopUnsupportedFamily ?? undefined,
previous_discovery_loop_metadata_scope_hint: sourceDiscoveryLoopMetadataScopeHint ?? undefined,
previous_discovery_loop_subject_resolution_optional:
sourceDiscoveryLoopSubjectResolutionOptional || undefined,
previous_discovery_ranking_need: sourceDiscoveryRankingNeed ?? undefined,
previous_discovery_entity_ambiguity_candidates:
sourceDiscoveryEntityAmbiguityCandidates.length > 0
? sourceDiscoveryEntityAmbiguityCandidates
: undefined,
previous_discovery_metadata_route_family: sourceDiscoveryMetadataRouteFamily ?? undefined,
previous_discovery_metadata_route_family_selection_basis:
sourceDiscoveryMetadataRouteFamilySelectionBasis ?? undefined,
previous_discovery_metadata_selected_entity_set: sourceDiscoveryMetadataSelectedEntitySet ?? undefined,
previous_discovery_metadata_selected_surface_objects:
sourceDiscoveryMetadataSelectedSurfaceObjects.length > 0
? sourceDiscoveryMetadataSelectedSurfaceObjects
: undefined,
previous_discovery_metadata_recommended_next_primitive:
sourceDiscoveryMetadataRecommendedNextPrimitive ?? undefined,
previous_discovery_metadata_ambiguity_detected: sourceDiscoveryMetadataAmbiguityDetected || undefined,
previous_discovery_metadata_ambiguity_entity_sets:
sourceDiscoveryMetadataAmbiguityEntitySets.length > 0 ? sourceDiscoveryMetadataAmbiguityEntitySets : undefined,
previous_discovery_bidirectional_value_flow: sourceDiscoveryBidirectionalValueFlow ?? undefined,
previous_discovery_document_summary: sourceDiscoveryDocumentSummary ?? undefined,
resolved_counterparty_from_display: resolvedCounterpartyFromDisplay || undefined,
root_context_only: rootScopedPivot || undefined,
root_intent: shouldAttachInventoryRootFrame ? inventoryRootFrame?.intent ?? undefined : undefined,
root_filters: shouldAttachInventoryRootFrame ? inventoryRootFrame?.filters ?? undefined : undefined,
root_anchor_type: shouldAttachInventoryRootFrame ? inventoryRootFrame?.anchorType ?? undefined : undefined,
root_anchor_value: shouldAttachInventoryRootFrame ? inventoryRootFrame?.anchorValue ?? undefined : undefined,
current_frame_kind: shouldAttachInventoryRootFrame ? currentFrameKind ?? undefined : undefined
},
previousAddressIntent: previousIntent,
previousAddressAnchor: previousAnchor,
previousSourceIntent: sourceIntent,
followupSelectionMode,
hasImplicitContinuationSignal,
hasSuggestedIntentPivotSignal
};
}
function buildAddressDialogContinuationContractV2(
userMessage,
effectiveMessage,
carryoverMeta,
llmPreDecomposeMeta
) {
const sourceMessage = String(userMessage ?? "");
const canonicalMessage = String(effectiveMessage ?? sourceMessage);
const hasFollowupContext = Boolean(carryoverMeta?.followupContext);
const previousIntent = deps.toNonEmptyString(carryoverMeta?.previousSourceIntent) ?? null;
const selectionMode = deps.toNonEmptyString(carryoverMeta?.followupSelectionMode) ?? null;
const rootContextOnly = selectionMode === "carry_root_context";
const carryoverTargetIntent = deps.toNonEmptyString(carryoverMeta?.followupContext?.target_intent) ?? null;
const explicitIntentRaw = deps.toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.intent);
const explicitIntent = explicitIntentRaw === "unknown" ? null : explicitIntentRaw;
const rootIntent = deps.toNonEmptyString(carryoverMeta?.followupContext?.root_intent) ?? null;
const targetIntent =
selectionMode === "switch_to_suggested_intent"
? deps.toNonEmptyString(carryoverMeta?.previousAddressIntent) ?? null
: rootContextOnly
? carryoverTargetIntent ?? rootIntent ?? explicitIntent ?? null
: carryoverTargetIntent ?? explicitIntent ?? deps.toNonEmptyString(carryoverMeta?.previousAddressIntent) ?? null;
const hasImplicitContinuationSignal = Boolean(carryoverMeta?.hasImplicitContinuationSignal);
const hasSuggestedIntentPivotSignal = Boolean(carryoverMeta?.hasSuggestedIntentPivotSignal);
const rewrittenByPredecompose =
deps.compactWhitespace(sourceMessage.toLowerCase()) !== deps.compactWhitespace(canonicalMessage.toLowerCase());
const hasExplicitIntent = Boolean(explicitIntent);
const decision = !hasFollowupContext
? "new_topic"
: selectionMode === "switch_to_suggested_intent"
? "switch_to_suggested"
: "continue_previous";
const reasons = [];
if (hasFollowupContext) {
reasons.push("followup_context_detected");
}
if (hasImplicitContinuationSignal) {
reasons.push("implicit_continuation_by_llm");
}
if (hasSuggestedIntentPivotSignal) {
reasons.push("suggested_intent_followup_pivot");
}
if (rewrittenByPredecompose) {
reasons.push("effective_message_rewritten_by_predecompose");
}
if (hasExplicitIntent) {
reasons.push("llm_contract_intent_available");
}
if (selectionMode === "carry_referenced_entity" && explicitIntent && previousIntent && explicitIntent !== previousIntent) {
reasons.push("operation_intent_from_current_message");
}
if (rootContextOnly) {
reasons.push("root_context_only_carryover");
}
return {
schema_version: "address_dialog_continuation_contract_v2",
source_message: sourceMessage,
effective_message: canonicalMessage,
decision,
decision_reasons: reasons,
followup_context_applied: hasFollowupContext,
previous_intent: previousIntent,
target_intent: targetIntent,
intent_selection_mode: selectionMode,
anchor_type: carryoverMeta?.followupContext?.previous_anchor_type ?? null,
anchor_value: carryoverMeta?.followupContext?.previous_anchor_value ?? null,
implicit_continuation_signal: hasImplicitContinuationSignal,
suggested_intent_pivot_signal: hasSuggestedIntentPivotSignal
};
}
return {
resolveAddressFollowupCarryoverContext,
buildAddressDialogContinuationContractV2
};
}