АРЧ АП11 - Архитектура: вынести data scope и organization history из assistantService в отдельный owner

This commit is contained in:
2026-04-17 16:59:24 +03:00
parent cd0b78d1de
commit 4b83e2b2de
6 changed files with 1162 additions and 223 deletions
@@ -19,6 +19,7 @@ import * as capabilitiesRegistry_1 from "./capabilitiesRegistry";
import * as assistantCanon_1 from "./assistantCanon";
import * as assistantAddressAttemptRuntimeAdapter_1 from "./assistantAddressAttemptRuntimeAdapter";
import * as assistantCoverageGrounding_1 from "./assistantCoverageGrounding";
import * as assistantDataScopePolicy_1 from "./assistantDataScopePolicy";
import * as assistantDeepTurnAttemptRuntimeAdapter_1 from "./assistantDeepTurnAttemptRuntimeAdapter";
import * as assistantBoundaryPolicy_1 from "./assistantBoundaryPolicy";
import * as assistantLivingModePolicy_1 from "./assistantLivingModePolicy";
@@ -35,8 +36,7 @@ import * as assistantTurnRuntimeInputBuilder_1 from "./assistantTurnRuntimeInput
import * as assistantUserTurnBootstrapRuntimeAdapter_1 from "./assistantUserTurnBootstrapRuntimeAdapter";
import * as assistantQueryPlanning_1 from "./assistantQueryPlanning";
import iconv from "iconv-lite";
const DATA_SCOPE_CACHE_TTL_MS = 60_000;
const dataScopeProbeCache = new Map();
const normalizeOrganizationScopeValue = assistantOrganizationMatcher_1.normalizeOrganizationScopeValue;
function retrievalSummaryForRoute(route) {
if (route === "store_canonical")
return "Canonical accounting data path selected.";
@@ -4185,105 +4185,6 @@ function hasLivingChatSignal(text) {
function buildAssistantCapabilityContractReply() {
return (0, capabilitiesRegistry_1.buildCapabilityContractReplyFromRegistry)();
}
function normalizeScopeLabel(value) {
const repaired = repairAddressMojibake(String(value ?? ""));
let normalized = compactWhitespace(repaired.trim());
for (let index = 0; index < 2; index += 1) {
const first = normalized[0];
const last = normalized[normalized.length - 1];
const wrappedInQuotes = (first === "\"" && last === "\"") ||
(first === "'" && last === "'") ||
(first === "«" && last === "»");
if (!wrappedInQuotes) {
break;
}
normalized = compactWhitespace(normalized.slice(1, -1).trim());
}
if (!normalized) {
return null;
}
if (/^(?:null|undefined|nan|0|не\s*заполнено)$/i.test(normalized)) {
return null;
}
return normalized;
}
function normalizeScopeKey(value) {
return repairAddressMojibake(String(value ?? "")).toLowerCase().replace(/ё/g, "е");
}
const ORGANIZATION_SCOPE_STOPWORDS = new Set([
"ооо",
"ao",
"ао",
"зао",
"ип",
"llc",
"ltd",
"company",
"компания",
"организация",
"организации",
"контора",
"конторы",
"фирма",
"фирмы",
"по",
"для",
"над",
"под",
"без",
"с",
"со",
"в",
"во",
"на",
"и",
"или",
"а",
"но",
"не",
"мы",
"нам",
"наш",
"наша",
"наше",
"наши",
"ты",
"тебе",
"твой",
"сейчас",
"щас",
"тут",
"вот",
"давай",
"го",
"погнали",
"тогда",
"обсудим",
"обсуждать",
"работать",
"работаем",
"работаешь",
"работаете",
"можем",
"можно",
"какая",
"какой",
"какие",
"чья",
"чье",
"чьи"
]);
function normalizeOrganizationScopeValue(value) {
const normalized = normalizeScopeLabel(value);
if (!normalized) {
return null;
}
const unwrapped = normalized
.replace(/^"+|"+$/g, "")
.replace(/^'+|'+$/g, "")
.trim();
return unwrapped ? unwrapped : null;
}
const assistantProviderExecutionPolicy = (0, assistantProviderExecutionPolicy_1.createAssistantProviderExecutionPolicy)();
const assistantLivingModePolicy = (0, assistantLivingModePolicy_1.createAssistantLivingModePolicy)({
featureAssistantLivingChatRouterV1: config_1.FEATURE_ASSISTANT_LIVING_CHAT_ROUTER_V1,
@@ -4380,6 +4281,78 @@ const assistantTransitionPolicy = (0, assistantTransitionPolicy_1.createAssistan
extractDisplayedAddressEntityCandidates,
resolveDisplayedAddressEntityMention
});
const assistantDataScopePolicy = (0, assistantDataScopePolicy_1.createAssistantDataScopePolicy)({
activeMcpChannel: config_1.ASSISTANT_MCP_CHANNEL,
mcpProxyUrl: config_1.ASSISTANT_MCP_PROXY_URL,
executeAddressMcpQuery: addressMcpClient_1.executeAddressMcpQuery,
repairAddressMojibake
});
function normalizeScopeKey(value) {
return repairAddressMojibake(String(value ?? "")).toLowerCase().replace(/ё/g, "е");
}
const ORGANIZATION_SCOPE_STOPWORDS = new Set([
"ооо",
"ao",
"ао",
"зао",
"ип",
"llc",
"ltd",
"company",
"компания",
"организация",
"организации",
"контора",
"конторы",
"фирма",
"фирмы",
"по",
"для",
"над",
"под",
"без",
"с",
"со",
"в",
"во",
"на",
"и",
"или",
"а",
"но",
"не",
"мы",
"нам",
"наш",
"наша",
"наше",
"наши",
"ты",
"тебе",
"твой",
"сейчас",
"щас",
"тут",
"вот",
"давай",
"го",
"погнали",
"тогда",
"обсудим",
"обсуждать",
"работать",
"работаем",
"работаешь",
"работаете",
"можем",
"можно",
"какая",
"какой",
"какие",
"чья",
"чье",
"чьи"
]);
function normalizeOrganizationScopeSearchText(value) {
const source = normalizeScopeKey(value);
return source
@@ -4638,9 +4611,9 @@ function resolveSessionOrganizationScopeContext(userMessage, items, addressNavig
userMessage,
items,
addressNavigationState,
extractKnownOrganizationsFromHistory,
extractKnownOrganizationsFromHistory: assistantDataScopePolicy.extractKnownOrganizationsFromHistory,
resolveOrganizationSelectionFromMessage,
findLastAssistantActiveOrganization,
findLastAssistantActiveOrganization: assistantDataScopePolicy.findLastAssistantActiveOrganization,
normalizeOrganizationScopeValue
});
}
@@ -4894,12 +4867,13 @@ function buildResolvedDataScopeProbe(status, organizations) {
};
}
export function extractOrganizationFactsFromRowsForTests(rows) {
return extractOrganizationFactsFromRows(rows);
return assistantDataScopePolicy.extractOrganizationFactsFromRows(rows);
}
export function resolveOrganizationNamesByRefsForTests(refs, facts) {
return resolveOrganizationNamesByRefs(refs, facts);
return assistantDataScopePolicy.resolveOrganizationNamesByRefs(refs, facts);
}
async function resolveAssistantDataScopeProbe() {
return assistantDataScopePolicy.resolveAssistantDataScopeProbe();
const cacheKey = `${config_1.ASSISTANT_MCP_PROXY_URL}|${config_1.ASSISTANT_MCP_CHANNEL}`;
const now = Date.now();
const cached = dataScopeProbeCache.get(cacheKey);