ARCH: довести surface-aware planner и catalog search

This commit is contained in:
2026-04-23 10:25:03 +03:00
parent 8b6cd4c329
commit 3a89cca6bb
30 changed files with 2521 additions and 157 deletions
@@ -6,7 +6,10 @@ exports.readAssistantMcpDiscoveryEntityCandidates = readAssistantMcpDiscoveryEnt
exports.readAssistantMcpDiscoveryPilotScope = readAssistantMcpDiscoveryPilotScope;
exports.readAssistantMcpDiscoveryRankingNeed = readAssistantMcpDiscoveryRankingNeed;
exports.readAssistantMcpDiscoveryMetadataRouteFamily = readAssistantMcpDiscoveryMetadataRouteFamily;
exports.readAssistantMcpDiscoveryMetadataRouteFamilySelectionBasis = readAssistantMcpDiscoveryMetadataRouteFamilySelectionBasis;
exports.readAssistantMcpDiscoveryMetadataSelectedEntitySet = readAssistantMcpDiscoveryMetadataSelectedEntitySet;
exports.readAssistantMcpDiscoveryMetadataSelectedSurfaceObjects = readAssistantMcpDiscoveryMetadataSelectedSurfaceObjects;
exports.readAssistantMcpDiscoveryMetadataRecommendedNextPrimitive = readAssistantMcpDiscoveryMetadataRecommendedNextPrimitive;
exports.readAssistantMcpDiscoveryMetadataAmbiguityDetected = readAssistantMcpDiscoveryMetadataAmbiguityDetected;
exports.readAssistantMcpDiscoveryMetadataAmbiguityEntitySets = readAssistantMcpDiscoveryMetadataAmbiguityEntitySets;
exports.formatIsoDateForReply = formatIsoDateForReply;
@@ -154,9 +157,22 @@ function readAssistantMcpDiscoveryRankingNeed(debug, toNonEmptyString = fallback
function readAssistantMcpDiscoveryMetadataRouteFamily(debug, toNonEmptyString = fallbackToNonEmptyString) {
return toNonEmptyString(readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.downstream_route_family);
}
function readAssistantMcpDiscoveryMetadataRouteFamilySelectionBasis(debug, toNonEmptyString = fallbackToNonEmptyString) {
return toNonEmptyString(readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.route_family_selection_basis);
}
function readAssistantMcpDiscoveryMetadataSelectedEntitySet(debug, toNonEmptyString = fallbackToNonEmptyString) {
return toNonEmptyString(readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.selected_entity_set);
}
function readAssistantMcpDiscoveryMetadataSelectedSurfaceObjects(debug, toNonEmptyString = fallbackToNonEmptyString) {
const values = readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.selected_surface_objects;
if (!Array.isArray(values)) {
return [];
}
return values.map((item) => toNonEmptyString(item)).filter((item) => Boolean(item));
}
function readAssistantMcpDiscoveryMetadataRecommendedNextPrimitive(debug, toNonEmptyString = fallbackToNonEmptyString) {
return toNonEmptyString(readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.recommended_next_primitive);
}
function readAssistantMcpDiscoveryMetadataAmbiguityDetected(debug) {
return (readAssistantMcpDiscoveryDerivedMetadataSurface(debug)?.ambiguity_detected === true ||
readAssistantMcpDiscoveryTurnMeaningMetadataAmbiguityEntitySets(debug).length > 0);
@@ -2,6 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.ASSISTANT_MCP_CATALOG_PLAN_REVIEW_SCHEMA_VERSION = exports.ASSISTANT_MCP_CATALOG_INDEX_SCHEMA_VERSION = void 0;
exports.searchAssistantMcpCatalogPrimitivesByDecompositionCandidates = searchAssistantMcpCatalogPrimitivesByDecompositionCandidates;
exports.searchAssistantMcpCatalogPrimitivesByFactAxis = searchAssistantMcpCatalogPrimitivesByFactAxis;
exports.searchAssistantMcpCatalogPrimitivesByMetadataSurface = searchAssistantMcpCatalogPrimitivesByMetadataSurface;
exports.buildAssistantMcpCatalogIndex = buildAssistantMcpCatalogIndex;
exports.getAssistantMcpCatalogPrimitive = getAssistantMcpCatalogPrimitive;
exports.reviewAssistantMcpDiscoveryPlanAgainstCatalog = reviewAssistantMcpDiscoveryPlanAgainstCatalog;
@@ -13,6 +15,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "search_business_entity",
purpose: "Find candidate 1C business entities by user wording before a fact query is executed.",
decomposition_hints: ["search_business_entity"],
supported_fact_families: ["entity_grounding"],
supported_action_families: ["search_business_entity"],
planning_tags: ["subject_resolution"],
required_axes_any_of: [["business_entity"], ["counterparty"], ["organization"], ["contract"], ["item"]],
optional_axes: ["period", "document", "account"],
output_fact_kinds: ["entity_candidates", "entity_ambiguity"],
@@ -24,6 +29,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "inspect_1c_metadata",
purpose: "Inspect available 1C schema/catalog/document/register surface before selecting a query lane.",
decomposition_hints: ["inspect_metadata_surface"],
supported_fact_families: ["schema_surface"],
supported_action_families: ["inspect_catalog", "inspect_documents", "inspect_registers", "inspect_fields", "inspect_surface"],
planning_tags: ["metadata", "surface_inspection"],
required_axes_any_of: [["metadata_scope"], ["domain_family"], ["document"], ["register"]],
optional_axes: ["business_entity", "account", "counterparty"],
output_fact_kinds: ["available_fields", "available_entity_sets", "known_limitations"],
@@ -35,6 +43,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "resolve_entity_reference",
purpose: "Resolve a user-visible entity name to a concrete 1C reference candidate.",
decomposition_hints: ["resolve_entity_reference"],
supported_fact_families: ["entity_grounding", "value_flow", "document_evidence", "movement_evidence", "activity_lifecycle"],
supported_action_families: ["search_business_entity", "turnover", "payout", "net_value_flow", "list_documents", "list_movements", "activity_duration"],
planning_tags: ["subject_resolution"],
required_axes_any_of: [["business_entity"], ["counterparty"], ["organization"], ["contract"], ["item"]],
optional_axes: ["period", "inn", "document"],
output_fact_kinds: ["resolved_entity_ref", "entity_conflict"],
@@ -51,6 +62,9 @@ const PRIMITIVE_CONTRACTS = [
"collect_outgoing_movements",
"fetch_scoped_movements"
],
supported_fact_families: ["value_flow", "movement_evidence"],
supported_action_families: ["turnover", "payout", "net_value_flow", "list_movements"],
planning_tags: ["movement", "comparison", "ranking", "aggregation", "monthly_aggregation"],
required_axes_any_of: [["period", "account"], ["period", "counterparty"], ["period", "organization"]],
optional_axes: ["contract", "document", "amount", "item", "warehouse"],
output_fact_kinds: ["movement_rows", "turnover", "balance_delta"],
@@ -62,6 +76,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "query_documents",
purpose: "Fetch documents related to a scoped entity, period, contract, or movement explanation.",
decomposition_hints: ["fetch_scoped_documents", "fetch_supporting_documents"],
supported_fact_families: ["document_evidence", "activity_lifecycle"],
supported_action_families: ["list_documents", "activity_duration"],
planning_tags: ["document"],
required_axes_any_of: [["document"], ["counterparty"], ["contract"], ["period", "organization"]],
optional_axes: ["account", "amount", "item", "warehouse"],
output_fact_kinds: ["document_rows", "document_dates", "document_amounts"],
@@ -73,6 +90,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "aggregate_by_axis",
purpose: "Aggregate already-scoped 1C evidence by a business axis such as counterparty, contract, or period.",
decomposition_hints: ["aggregate_checked_amounts", "aggregate_ranked_axis_values", "aggregate_by_month"],
supported_fact_families: ["value_flow"],
supported_action_families: ["turnover", "payout", "net_value_flow"],
planning_tags: ["aggregation", "ranking", "monthly_aggregation"],
required_axes_any_of: [["aggregate_axis", "period"], ["aggregate_axis", "counterparty"], ["aggregate_axis", "account"]],
optional_axes: ["organization", "contract", "document", "amount"],
output_fact_kinds: ["aggregate_totals", "ranked_axis_values"],
@@ -84,6 +104,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "drilldown_related_objects",
purpose: "Drill from a known entity or document into related contracts, documents, movements, or payments.",
decomposition_hints: ["drilldown_related_objects"],
supported_fact_families: [],
supported_action_families: [],
planning_tags: ["drilldown"],
required_axes_any_of: [["business_entity"], ["document"], ["contract"], ["counterparty"]],
optional_axes: ["period", "account", "amount"],
output_fact_kinds: ["related_objects", "relationship_edges"],
@@ -95,6 +118,29 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "probe_coverage",
purpose: "Check whether the selected MCP/schema route can prove the requested fact or only support a bounded inference.",
decomposition_hints: ["probe_coverage"],
supported_fact_families: [
"schema_surface",
"entity_grounding",
"value_flow",
"document_evidence",
"movement_evidence",
"activity_lifecycle"
],
supported_action_families: [
"inspect_catalog",
"inspect_documents",
"inspect_registers",
"inspect_fields",
"inspect_surface",
"search_business_entity",
"turnover",
"payout",
"net_value_flow",
"list_documents",
"list_movements",
"activity_duration"
],
planning_tags: ["coverage"],
required_axes_any_of: [["coverage_target"], ["domain_family"], ["primitive_id"]],
optional_axes: ["period", "organization", "counterparty", "document", "account"],
output_fact_kinds: ["coverage_status", "known_gaps"],
@@ -106,6 +152,9 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "explain_evidence_basis",
purpose: "Produce a machine-readable explanation of which checked MCP evidence supports, limits, or fails the answer.",
decomposition_hints: ["explain_evidence_basis"],
supported_fact_families: ["activity_lifecycle"],
supported_action_families: ["activity_duration"],
planning_tags: ["explanation"],
required_axes_any_of: [["evidence_basis"], ["primitive_id"], ["source_rows_summary"]],
optional_axes: ["coverage_target", "domain_family"],
output_fact_kinds: ["confirmed_facts", "inferred_facts", "unknown_facts"],
@@ -141,6 +190,146 @@ function missingAxisGroups(axisSet, groups) {
function normalizeDecompositionStep(value) {
return value.trim().toLowerCase();
}
function normalizePlanningToken(value) {
return value.trim().toLowerCase();
}
function countAxisOverlap(axisSet, groups) {
let best = 0;
for (const group of groups) {
const overlap = group.filter((axis) => axisSet.has(axis)).length;
if (overlap > best) {
best = overlap;
}
}
return best;
}
function tagSetFromFactAxisInput(input) {
const tags = new Set();
const requiredAxes = input.required_axes ?? [];
if (input.business_fact_family === "schema_surface") {
tags.add("metadata");
tags.add("surface_inspection");
}
if (input.business_fact_family === "entity_grounding" ||
input.has_subject_candidates ||
requiredAxes.some((axis) => ["business_entity", "counterparty", "contract", "item"].includes(axis))) {
tags.add("subject_resolution");
}
if (input.business_fact_family === "document_evidence") {
tags.add("document");
}
if (input.business_fact_family === "movement_evidence") {
tags.add("movement");
}
if (input.business_fact_family === "value_flow") {
tags.add("movement");
}
if (input.comparison_need) {
tags.add("comparison");
}
if (input.ranking_need) {
tags.add("ranking");
tags.add("aggregation");
}
if ((input.aggregation_need ?? "") === "by_month" || requiredAxes.includes("calendar_month")) {
tags.add("monthly_aggregation");
tags.add("aggregation");
}
if (requiredAxes.includes("aggregate_axis")) {
tags.add("aggregation");
}
if (requiredAxes.includes("coverage_target")) {
tags.add("coverage");
}
if (input.business_fact_family === "activity_lifecycle" || requiredAxes.includes("evidence_basis")) {
tags.add("explanation");
}
return tags;
}
function matchesPlanningToken(value, candidates) {
const normalizedValue = normalizePlanningToken(value ?? "");
return normalizedValue.length > 0 && candidates.some((candidate) => normalizePlanningToken(candidate) === normalizedValue);
}
function normalizeMetadataSurfaceToken(value) {
return value.trim().toLowerCase().replace(/[\s_.-]+/g, "");
}
function metadataSurfaceSuggestsDocument(value) {
const token = normalizeMetadataSurfaceToken(value);
return (token.includes("документ") ||
token.includes("document") ||
token.includes("invoice") ||
token.includes("waybill") ||
token.includes("накладн") ||
token.includes("счетфактур") ||
token.includes("счётфактур") ||
token.includes("акт"));
}
function metadataSurfaceSuggestsMovement(value) {
const token = normalizeMetadataSurfaceToken(value);
return (token.includes("регистр") ||
token.includes("register") ||
token.includes("movement") ||
token.includes("движени") ||
token.includes("операц") ||
token.includes("проводк") ||
token.includes("bank"));
}
function metadataSurfaceSuggestsCatalog(value) {
const token = normalizeMetadataSurfaceToken(value);
return (token.includes("справочник") ||
token.includes("catalog") ||
token.includes("directory"));
}
function tagSetFromMetadataSurfaceInput(input) {
const tags = new Set();
const routeFamily = normalizePlanningToken(input.downstream_route_family ?? "");
const recommendedPrimitive = normalizePlanningToken(input.recommended_next_primitive ?? "");
const surfaceValues = [
input.selected_entity_set ?? "",
...(input.selected_surface_objects ?? [])
];
if (routeFamily === "document_evidence" || recommendedPrimitive === "query_documents") {
tags.add("document");
}
if (routeFamily === "movement_evidence" || recommendedPrimitive === "query_movements") {
tags.add("movement");
}
if (routeFamily === "catalog_drilldown" || recommendedPrimitive === "drilldown_related_objects") {
tags.add("drilldown");
}
for (const value of surfaceValues) {
if (metadataSurfaceSuggestsDocument(value)) {
tags.add("document");
}
if (metadataSurfaceSuggestsMovement(value)) {
tags.add("movement");
}
if (metadataSurfaceSuggestsCatalog(value)) {
tags.add("drilldown");
}
}
const requiredAxisSet = toStringSet(input.required_axes ?? []);
if (requiredAxisSet.has("coverage_target")) {
tags.add("coverage");
}
if (requiredAxisSet.has("counterparty") ||
requiredAxisSet.has("business_entity") ||
requiredAxisSet.has("contract")) {
tags.add("subject_resolution");
}
return tags;
}
function factFamiliesFromMetadataSurfaceInput(input) {
const families = new Set();
const routeFamily = normalizePlanningToken(input.downstream_route_family ?? "");
if (routeFamily === "document_evidence") {
families.add("document_evidence");
}
if (routeFamily === "movement_evidence") {
families.add("movement_evidence");
}
return families;
}
function searchAssistantMcpCatalogPrimitivesByDecompositionCandidates(input) {
const allowAggregateByAxis = input.allow_aggregate_by_axis !== false;
const result = [];
@@ -165,6 +354,121 @@ function searchAssistantMcpCatalogPrimitivesByDecompositionCandidates(input) {
}
return result;
}
function searchAssistantMcpCatalogPrimitivesByFactAxis(input) {
const allowAggregateByAxis = input.allow_aggregate_by_axis !== false;
const requiredAxisSet = toStringSet(input.required_axes ?? []);
const desiredTags = tagSetFromFactAxisInput(input);
const scored = [];
for (const contract of PRIMITIVE_CONTRACTS) {
if (contract.primitive_id === "aggregate_by_axis" && !allowAggregateByAxis) {
continue;
}
if (contract.primitive_id === "search_business_entity" && input.business_fact_family !== "entity_grounding") {
continue;
}
if (input.business_fact_family === "schema_surface" && contract.primitive_id !== "inspect_1c_metadata") {
continue;
}
const factMatch = matchesPlanningToken(input.business_fact_family, contract.supported_fact_families);
const actionMatch = matchesPlanningToken(input.action_family, contract.supported_action_families);
const tagMatches = contract.planning_tags.filter((tag) => desiredTags.has(normalizePlanningToken(tag)));
if (contract.primitive_id === "search_business_entity" && !desiredTags.has("subject_resolution")) {
continue;
}
if (contract.primitive_id === "resolve_entity_reference" && !desiredTags.has("subject_resolution")) {
continue;
}
if (contract.primitive_id === "aggregate_by_axis" && !desiredTags.has("aggregation")) {
continue;
}
if (contract.primitive_id === "explain_evidence_basis" && !desiredTags.has("explanation")) {
continue;
}
if (!factMatch && !actionMatch && tagMatches.length <= 0) {
continue;
}
const hasCompatibleAxisGroup = requiredAxisSet.size > 0 && hasAnyAxisGroup(requiredAxisSet, contract.required_axes_any_of);
const axisOverlap = requiredAxisSet.size > 0 ? countAxisOverlap(requiredAxisSet, contract.required_axes_any_of) : 0;
let score = 0;
if (factMatch) {
score += 5;
}
if (actionMatch) {
score += 3;
}
score += tagMatches.length * 2;
if (hasCompatibleAxisGroup) {
score += 2;
}
else if (axisOverlap > 0) {
score += 1;
}
if (score <= 0) {
continue;
}
scored.push({
primitive: contract.primitive_id,
score
});
}
return scored
.sort((left, right) => right.score - left.score)
.map((item) => item.primitive);
}
function searchAssistantMcpCatalogPrimitivesByMetadataSurface(input) {
const allowAggregateByAxis = input.allow_aggregate_by_axis !== false;
const requiredAxisSet = toStringSet(input.required_axes ?? []);
const desiredTags = tagSetFromMetadataSurfaceInput(input);
const desiredFactFamilies = factFamiliesFromMetadataSurfaceInput(input);
const recommendedPrimitive = normalizePlanningToken(input.recommended_next_primitive ?? "");
const scored = [];
for (const contract of PRIMITIVE_CONTRACTS) {
if (contract.primitive_id === "aggregate_by_axis" && !allowAggregateByAxis) {
continue;
}
if (contract.primitive_id === "search_business_entity") {
continue;
}
const tagMatches = contract.planning_tags.filter((tag) => desiredTags.has(normalizePlanningToken(tag)));
const factMatch = contract.supported_fact_families.some((family) => desiredFactFamilies.has(normalizePlanningToken(family)));
const primitiveRecommended = normalizePlanningToken(contract.primitive_id) === recommendedPrimitive;
if (contract.primitive_id === "resolve_entity_reference" && !desiredTags.has("subject_resolution")) {
continue;
}
if (contract.primitive_id === "aggregate_by_axis" && !desiredTags.has("aggregation")) {
continue;
}
if (!primitiveRecommended && !factMatch && tagMatches.length <= 0) {
continue;
}
const hasCompatibleAxisGroup = requiredAxisSet.size > 0 && hasAnyAxisGroup(requiredAxisSet, contract.required_axes_any_of);
const axisOverlap = requiredAxisSet.size > 0 ? countAxisOverlap(requiredAxisSet, contract.required_axes_any_of) : 0;
let score = 0;
if (primitiveRecommended) {
score += 6;
}
if (factMatch) {
score += 5;
}
score += tagMatches.length * 2;
if (hasCompatibleAxisGroup) {
score += 2;
}
else if (axisOverlap > 0) {
score += 1;
}
if (score <= 0) {
continue;
}
scored.push({
primitive: contract.primitive_id,
score
});
}
return scored
.sort((left, right) => right.score - left.score)
.map((item) => item.primitive);
}
function buildAssistantMcpCatalogIndex() {
const reasonCodes = [];
const missingContracts = assistantMcpDiscoveryPolicy_1.ASSISTANT_MCP_DISCOVERY_PRIMITIVES.filter((primitive) => !PRIMITIVE_CONTRACT_MAP.has(primitive));
@@ -89,7 +89,9 @@ function isEntityResolutionPilot(pilot) {
}
function isMetadataLaneChoiceClarification(pilot) {
return (pilot.reason_codes.includes("planner_selected_metadata_lane_clarification_recipe") ||
pilot.dry_run.reason_codes.includes("planner_selected_metadata_lane_clarification_recipe"));
pilot.reason_codes.includes("planner_selected_metadata_lane_clarification_from_data_need_graph") ||
pilot.dry_run.reason_codes.includes("planner_selected_metadata_lane_clarification_recipe") ||
pilot.dry_run.reason_codes.includes("planner_selected_metadata_lane_clarification_from_data_need_graph"));
}
function askedActionFamily(pilot) {
const action = pilot.evidence.query_plan.turn_meaning_ref?.asked_action_family;
@@ -67,10 +67,20 @@ function aggregationNeedFor(axis) {
}
return `by_${axis}`;
}
function hasAllTimeScopeHint(rawUtterance) {
if (!rawUtterance) {
return false;
}
return /(?:\u0437\u0430\s+\u0432\u0441[\u0435\u0451]\s+\u0432\u0440\u0435\u043c\u044f|\u0437\u0430\s+\u0432\u0435\u0441\u044c\s+\u043f\u0435\u0440\u0438\u043e\u0434|\u0437\u0430\s+\u0432\u0441\u044e\s+\u0438\u0441\u0442\u043e\u0440\u0438(?:\u044e|\u0438)|\u0437\u0430\s+\u043b\u044e\u0431\u043e\u0439\s+\u043f\u0435\u0440\u0438\u043e\u0434|for\s+all\s+time|all\s+time|entire\s+period|full\s+history|any\s+period)/iu.test(rawUtterance);
}
function timeScopeNeedFor(input) {
if (input.explicitDateScope) {
return "explicit_period";
}
if (input.allTimeScopeHint &&
(input.family === "value_flow" || input.family === "movement_evidence" || input.family === "document_evidence")) {
return "all_time_scope";
}
if (input.family === "value_flow" || input.family === "movement_evidence" || input.family === "document_evidence") {
return "period_required";
}
@@ -254,6 +264,7 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
const aggregationNeed = aggregationNeedFor(aggregationAxis);
const comparisonNeed = comparisonNeedFor(action);
const rankingNeed = rankingNeedFromRawUtterance(rawUtterance) ?? seededRankingNeed;
const allTimeScopeHint = hasAllTimeScopeHint(rawUtterance);
const oneSidedOpenScopeTotalHint = hasOpenScopeOneSidedValueTotalHintUtf8Safe(rawUtterance, action);
const openScopeWithoutSubject = subjectCandidates.length === 0 &&
allowsOpenScopeWithoutSubject({
@@ -279,7 +290,8 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
}
const timeScopeNeed = timeScopeNeedFor({
family: businessFactFamily,
explicitDateScope
explicitDateScope,
allTimeScopeHint
});
if (timeScopeNeed === "period_required" && !explicitDateScope) {
pushUnique(clarificationGaps, "period");
@@ -312,6 +324,9 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
if (openScopeWithoutSubject && !rankingNeed && !comparisonNeed) {
pushReason(reasonCodes, "data_need_graph_open_scope_total_without_subject");
}
if (allTimeScopeHint) {
pushReason(reasonCodes, "data_need_graph_all_time_scope_hint");
}
if (clarificationGaps.includes("organization")) {
pushReason(reasonCodes, "data_need_graph_open_scope_total_needs_organization");
}
@@ -824,6 +824,29 @@ function metadataRouteFamilyForEntitySet(entitySet) {
}
return null;
}
function metadataRouteFamilyForEntitySetRelaxed(entitySet) {
const strict = metadataRouteFamilyForEntitySet(entitySet);
if (strict) {
return strict;
}
const raw = String(entitySet ?? "").trim();
if (!raw) {
return null;
}
if (raw.includes("Документ") || raw.includes("Документ")) {
return "document_evidence";
}
if (raw.includes("РегистрНакопления") ||
raw.includes("РегистрСведений") ||
raw.includes("РегистрНакопления") ||
raw.includes("РегистрСведений")) {
return "movement_evidence";
}
if (raw.includes("Справочник") || raw.includes("Справочник")) {
return "catalog_drilldown";
}
return null;
}
function metadataNextPrimitiveForRouteFamily(routeFamily) {
if (routeFamily === "document_evidence") {
return "query_documents";
@@ -871,6 +894,50 @@ function metadataObjectsForEntitySet(entitySet, matchedObjects) {
}
return matchedObjects.filter((item) => item.startsWith(`${entitySet}.`) || item.includes(entitySet));
}
function emptyMetadataSurfaceFamilyScores() {
return {
document_evidence: 0,
movement_evidence: 0,
catalog_drilldown: 0
};
}
function metadataSurfaceFamilyScores(matchedObjects) {
const scores = emptyMetadataSurfaceFamilyScores();
for (const objectName of matchedObjects) {
const entitySet = inferMetadataEntitySetFromObjectName(objectName);
const routeFamily = entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) : null;
if (routeFamily) {
scores[routeFamily] += 1;
}
}
return scores;
}
function metadataObjectsForRouteFamily(routeFamily, matchedObjects) {
if (!routeFamily) {
return [];
}
return matchedObjects.filter((objectName) => {
const entitySet = inferMetadataEntitySetFromObjectName(objectName);
return entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) === routeFamily : false;
});
}
function selectMetadataRouteFamilyFromSurfaceScores(scores) {
const ranked = Object.entries(scores)
.filter(([, score]) => score > 0)
.sort((left, right) => right[1] - left[1]);
const top = ranked[0];
const second = ranked[1];
if (!top) {
return null;
}
if (!second) {
return top[0];
}
const absoluteMargin = top[1] - second[1];
const relativeRatio = second[1] > 0 ? top[1] / second[1] : Number.POSITIVE_INFINITY;
const clearlyDominant = absoluteMargin >= 2 || relativeRatio >= 1.5;
return clearlyDominant ? top[0] : null;
}
function deriveMetadataSurface(result, metadataScope, requestedMetaTypes) {
if (!result || result.error || result.rows.length <= 0) {
return null;
@@ -888,13 +955,28 @@ function deriveMetadataSurface(result, metadataScope, requestedMetaTypes) {
}
}
const grounding = selectMetadataEntityGrounding(availableEntitySets, requestedMetaTypes);
const downstreamRouteFamily = grounding.selectedEntitySet
? metadataRouteFamilyForEntitySet(grounding.selectedEntitySet)
const surfaceFamilyScores = metadataSurfaceFamilyScores(matchedObjects);
const selectedEntitySetRouteFamily = grounding.selectedEntitySet
? metadataRouteFamilyForEntitySetRelaxed(grounding.selectedEntitySet)
: null;
const scoredRouteFamily = selectedEntitySetRouteFamily === null ? selectMetadataRouteFamilyFromSurfaceScores(surfaceFamilyScores) : null;
const downstreamRouteFamily = selectedEntitySetRouteFamily ?? scoredRouteFamily;
const routeFamilySelectionBasis = selectedEntitySetRouteFamily
? "selected_entity_set"
: scoredRouteFamily
? "dominant_surface_objects"
: null;
const selectedSurfaceObjects = grounding.selectedEntitySet !== null
? metadataObjectsForEntitySet(grounding.selectedEntitySet, matchedObjects)
: metadataObjectsForRouteFamily(downstreamRouteFamily, matchedObjects);
const knownLimitations = [];
if (grounding.ambiguityDetected && grounding.ambiguityEntitySets.length > 0) {
const ambiguityRemainsUnresolved = grounding.ambiguityDetected && !downstreamRouteFamily;
if (ambiguityRemainsUnresolved && grounding.ambiguityEntitySets.length > 0) {
knownLimitations.push(`Exact downstream metadata surface remains ambiguous across: ${grounding.ambiguityEntitySets.join(", ")}`);
}
if (grounding.ambiguityDetected && downstreamRouteFamily && routeFamilySelectionBasis === "dominant_surface_objects") {
knownLimitations.push(`Metadata surface spans multiple object sets, but dominant confirmed objects point to ${downstreamRouteFamily}`);
}
return {
metadata_scope: metadataScope,
requested_meta_types: requestedMetaTypes,
@@ -902,11 +984,13 @@ function deriveMetadataSurface(result, metadataScope, requestedMetaTypes) {
available_entity_sets: availableEntitySets,
matched_objects: matchedObjects,
selected_entity_set: grounding.selectedEntitySet,
selected_surface_objects: metadataObjectsForEntitySet(grounding.selectedEntitySet, matchedObjects),
selected_surface_objects: selectedSurfaceObjects,
surface_family_scores: surfaceFamilyScores,
downstream_route_family: downstreamRouteFamily,
route_family_selection_basis: routeFamilySelectionBasis,
recommended_next_primitive: metadataNextPrimitiveForRouteFamily(downstreamRouteFamily),
ambiguity_detected: grounding.ambiguityDetected,
ambiguity_entity_sets: grounding.ambiguityEntitySets,
ambiguity_detected: ambiguityRemainsUnresolved,
ambiguity_entity_sets: ambiguityRemainsUnresolved ? grounding.ambiguityEntitySets : [],
available_fields: metadataAvailableFields(result.rows),
known_limitations: knownLimitations,
inference_basis: "confirmed_1c_metadata_surface_rows"
@@ -928,13 +1012,18 @@ function buildMetadataConfirmedFacts(surface) {
if (surface.selected_surface_objects.length > 0) {
facts.push(`Selected metadata objects: ${surface.selected_surface_objects.slice(0, 8).join(", ")}`);
}
if (surface.surface_family_scores.document_evidence > 0 ||
surface.surface_family_scores.movement_evidence > 0 ||
surface.surface_family_scores.catalog_drilldown > 0) {
facts.push(`Metadata surface family scores: document=${surface.surface_family_scores.document_evidence}, movement=${surface.surface_family_scores.movement_evidence}, catalog=${surface.surface_family_scores.catalog_drilldown}`);
}
if (surface.available_fields.length > 0) {
facts.push(`Available metadata fields/sections: ${surface.available_fields.slice(0, 12).join(", ")}`);
}
return facts;
}
function buildMetadataInferredFacts(surface) {
if (!surface || !surface.selected_entity_set || !surface.downstream_route_family || !surface.recommended_next_primitive) {
if (!surface || !surface.downstream_route_family || !surface.recommended_next_primitive) {
return [];
}
return [
@@ -1737,6 +1826,9 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
const derivedMetadataSurface = deriveMetadataSurface(metadataResult, metadataScope, requestedMetaTypes);
if (derivedMetadataSurface) {
pushReason(reasonCodes, "pilot_derived_metadata_surface_from_confirmed_rows");
if (derivedMetadataSurface.route_family_selection_basis === "dominant_surface_objects") {
pushReason(reasonCodes, "pilot_selected_metadata_route_family_from_dominant_surface_objects");
}
}
const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({
plan: planner.discovery_plan,
@@ -64,35 +64,148 @@ function includesAny(text, tokens) {
function isYearDateScope(meaning) {
return /^\d{4}$/.test(toNonEmptyString(meaning?.explicit_date_scope) ?? "");
}
function primitivesFromGraphDecomposition(input) {
const decompositionCandidates = input.dataNeedGraph?.decomposition_candidates ?? [];
if (decompositionCandidates.length <= 0) {
return { primitives: input.fallbackPrimitives, reasonCodes: [] };
function mergeCatalogPrimitivesWithFallback(catalogPrimitives, fallbackPrimitives) {
const result = [];
for (const primitive of fallbackPrimitives) {
if (catalogPrimitives.includes(primitive) && !result.includes(primitive)) {
result.push(primitive);
}
}
const searchedPrimitives = (0, assistantMcpCatalogIndex_1.searchAssistantMcpCatalogPrimitivesByDecompositionCandidates)({
decomposition_candidates: decompositionCandidates,
allow_aggregate_by_axis: input.allowAggregateByAxis
for (const primitive of catalogPrimitives) {
if (!result.includes(primitive)) {
result.push(primitive);
}
}
for (const primitive of fallbackPrimitives) {
if (!result.includes(primitive)) {
result.push(primitive);
}
}
return result;
}
function preferredPrimitiveFromMetadataSurface(surface) {
const recommendedPrimitive = surface?.recommended_next_primitive ?? null;
if (recommendedPrimitive) {
return recommendedPrimitive;
}
if (surface?.ambiguity_detected) {
return null;
}
if (surface?.downstream_route_family === "document_evidence") {
return "query_documents";
}
if (surface?.downstream_route_family === "movement_evidence") {
return "query_movements";
}
if (surface?.downstream_route_family === "catalog_drilldown") {
return "drilldown_related_objects";
}
return null;
}
function filterCatalogPrimitivesByMetadataSurface(input) {
const preferredPrimitive = preferredPrimitiveFromMetadataSurface(input.metadataSurface);
const reasonCodes = [];
if (!preferredPrimitive ||
input.metadataSurface?.ambiguity_detected ||
!input.fallbackPrimitives.includes(preferredPrimitive)) {
return {
primitives: input.catalogPrimitives,
reasonCodes
};
}
const laneSensitivePrimitives = new Set([
"query_documents",
"query_movements",
"drilldown_related_objects"
]);
const filteredPrimitives = input.catalogPrimitives.filter((primitive) => !laneSensitivePrimitives.has(primitive) || primitive === preferredPrimitive);
if (filteredPrimitives.length !== input.catalogPrimitives.length) {
reasonCodes.push("planner_filtered_catalog_primitives_by_confirmed_metadata_surface");
}
if ((filteredPrimitives.includes(preferredPrimitive) || input.fallbackPrimitives.includes(preferredPrimitive)) &&
input.metadataSurface?.selected_surface_objects.length) {
reasonCodes.push("planner_surface_aware_next_lane_from_confirmed_metadata_objects");
}
return {
primitives: filteredPrimitives,
reasonCodes
};
}
function selectPrimitivesFromGraphAndCatalog(input) {
const reasonCodes = [];
const decompositionCandidates = input.dataNeedGraph?.decomposition_candidates ?? [];
const decompositionPrimitives = decompositionCandidates.length > 0
? (0, assistantMcpCatalogIndex_1.searchAssistantMcpCatalogPrimitivesByDecompositionCandidates)({
decomposition_candidates: decompositionCandidates,
allow_aggregate_by_axis: input.allowAggregateByAxis
})
: [];
if (decompositionPrimitives.length > 0) {
reasonCodes.push("planner_selected_catalog_primitives_from_decomposition_candidates");
}
const metadataSurfacePrimitives = input.metadataSurface
? (0, assistantMcpCatalogIndex_1.searchAssistantMcpCatalogPrimitivesByMetadataSurface)({
downstream_route_family: input.metadataSurface.downstream_route_family,
selected_entity_set: input.metadataSurface.selected_entity_set,
selected_surface_objects: input.metadataSurface.selected_surface_objects,
recommended_next_primitive: input.metadataSurface.recommended_next_primitive,
required_axes: input.requiredAxes,
allow_aggregate_by_axis: input.allowAggregateByAxis
})
: [];
if (metadataSurfacePrimitives.length > 0) {
reasonCodes.push("planner_selected_catalog_primitives_from_metadata_surface_search");
}
const factAxisPrimitives = input.dataNeedGraph
? (0, assistantMcpCatalogIndex_1.searchAssistantMcpCatalogPrimitivesByFactAxis)({
business_fact_family: input.dataNeedGraph.business_fact_family,
action_family: input.actionFamily ?? input.dataNeedGraph.action_family,
required_axes: input.requiredAxes,
comparison_need: input.dataNeedGraph.comparison_need,
ranking_need: input.dataNeedGraph.ranking_need,
aggregation_need: input.dataNeedGraph.aggregation_need,
has_subject_candidates: hasSubjectCandidates(input.dataNeedGraph),
allow_aggregate_by_axis: input.allowAggregateByAxis
})
: [];
if (factAxisPrimitives.length > 0) {
reasonCodes.push("planner_selected_catalog_primitives_from_fact_axis_search");
}
const combinedCatalogPrimitives = [];
for (const primitive of decompositionPrimitives) {
if (!combinedCatalogPrimitives.includes(primitive)) {
combinedCatalogPrimitives.push(primitive);
}
}
for (const primitive of metadataSurfacePrimitives) {
if (!combinedCatalogPrimitives.includes(primitive)) {
combinedCatalogPrimitives.push(primitive);
}
}
for (const primitive of factAxisPrimitives) {
if (!combinedCatalogPrimitives.includes(primitive)) {
combinedCatalogPrimitives.push(primitive);
}
}
const filteredCatalogPrimitives = filterCatalogPrimitivesByMetadataSurface({
catalogPrimitives: combinedCatalogPrimitives,
fallbackPrimitives: input.fallbackPrimitives,
metadataSurface: input.metadataSurface
});
if (searchedPrimitives.length <= 0) {
reasonCodes.push(...filteredCatalogPrimitives.reasonCodes);
if (filteredCatalogPrimitives.primitives.length <= 0) {
return {
primitives: input.fallbackPrimitives,
reasonCodes: ["planner_fell_back_to_recipe_primitives_after_empty_catalog_search"]
};
}
const mergedPrimitives = [...searchedPrimitives];
for (const primitive of input.fallbackPrimitives) {
if (!mergedPrimitives.includes(primitive)) {
mergedPrimitives.push(primitive);
}
const mergedPrimitives = mergeCatalogPrimitivesWithFallback(filteredCatalogPrimitives.primitives, input.fallbackPrimitives);
if (input.fallbackPrimitives.some((primitive) => !filteredCatalogPrimitives.primitives.includes(primitive))) {
reasonCodes.push("planner_completed_catalog_searched_chain_with_recipe_primitives");
}
return {
primitives: mergedPrimitives,
reasonCodes: mergedPrimitives.length === searchedPrimitives.length
? ["planner_selected_catalog_primitives_from_decomposition_candidates"]
: [
"planner_selected_catalog_primitives_from_decomposition_candidates",
"planner_completed_catalog_searched_chain_with_recipe_primitives"
]
reasonCodes
};
}
function budgetOverrideFor(input, recipe) {
@@ -110,6 +223,36 @@ function budgetOverrideFor(input, recipe) {
}
return {};
}
function routeFamilyFromThinMetadataSurfaceInput(input) {
const surface = input.metadataSurface ?? null;
if (!surface || surface.ambiguity_detected || !surface.downstream_route_family || !surface.recommended_next_primitive) {
return null;
}
const meaning = input.turnMeaning ?? null;
const dataNeedGraph = input.dataNeedGraph ?? null;
const graphFactFamily = lower(dataNeedGraph?.business_fact_family);
const domain = lower(meaning?.asked_domain_family);
const action = lower(meaning?.asked_action_family);
const unsupported = lower(meaning?.unsupported_but_understood_family);
const semanticNeed = lower(input.semanticDataNeed);
const combined = `${domain} ${action} ${unsupported} ${semanticNeed}`.trim();
const explicitlyOtherFamily = includesAny(combined, ["value_flow", "turnover", "revenue", "payment", "payout", "net", "lifecycle", "activity", "duration", "metadata lane clarification"]);
if (explicitlyOtherFamily) {
return null;
}
if (graphFactFamily === "document_evidence" || includesAny(combined, ["document", "documents", "list_documents"])) {
return surface.downstream_route_family === "document_evidence" ? "document_evidence" : null;
}
if (graphFactFamily === "movement_evidence" || includesAny(combined, ["movement", "movements", "list_movements", "bank_operations"])) {
return surface.downstream_route_family === "movement_evidence" ? "movement_evidence" : null;
}
if (!graphFactFamily && !domain && !action) {
if (surface.downstream_route_family === "document_evidence" || surface.downstream_route_family === "movement_evidence") {
return surface.downstream_route_family;
}
}
return null;
}
function recipeFor(input) {
const meaning = input.turnMeaning ?? null;
const dataNeedGraph = input.dataNeedGraph ?? null;
@@ -139,18 +282,60 @@ function recipeFor(input) {
reason: "planner_selected_metadata_lane_clarification_from_data_need_graph"
};
}
const thinSurfaceRouteFamily = routeFamilyFromThinMetadataSurfaceInput(input);
if (thinSurfaceRouteFamily === "document_evidence") {
pushUnique(axes, "coverage_target");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "document evidence",
chainId: "document_evidence",
chainSummary: "Ground the next checked document lane from the confirmed metadata surface, then fetch scoped document rows and probe coverage before answering.",
primitives: primitiveSelection.primitives,
axes,
reason: "planner_selected_document_from_confirmed_metadata_surface_ref",
extraReasons: primitiveSelection.reasonCodes
};
}
if (thinSurfaceRouteFamily === "movement_evidence") {
pushUnique(axes, "coverage_target");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "movement evidence",
chainId: "movement_evidence",
chainSummary: "Ground the next checked movement lane from the confirmed metadata surface, then fetch scoped movement rows and probe coverage before answering.",
primitives: primitiveSelection.primitives,
axes,
reason: "planner_selected_movement_from_confirmed_metadata_surface_ref",
extraReasons: primitiveSelection.reasonCodes
};
}
if (graphFactFamily === "value_flow") {
if (dataNeedGraph?.comparison_need === "incoming_vs_outgoing" && !hasSubjectCandidates(dataNeedGraph)) {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["query_movements", "probe_coverage"],
allowAggregateByAxis: false
});
pushUnique(axes, "amount");
pushUnique(axes, "coverage_target");
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
pushUnique(axes, "calendar_month");
}
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["query_movements", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action,
allowAggregateByAxis: false
});
return {
semanticDataNeed: "bidirectional value-flow comparison evidence",
chainId: "value_flow_comparison",
@@ -162,14 +347,17 @@ function recipeFor(input) {
};
}
if (dataNeedGraph?.ranking_need && !hasSubjectCandidates(dataNeedGraph)) {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
allowAggregateByAxis: true
});
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "amount");
pushUnique(axes, "coverage_target");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action,
allowAggregateByAxis: true
});
return {
semanticDataNeed: "ranked value-flow evidence",
chainId: "value_flow_ranking",
@@ -183,11 +371,6 @@ function recipeFor(input) {
};
}
if (openScopeTotalWithoutSubject) {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
allowAggregateByAxis: true
});
pushUnique(axes, "organization");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "amount");
@@ -195,6 +378,13 @@ function recipeFor(input) {
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
pushUnique(axes, "calendar_month");
}
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
requiredAxes: axes,
actionFamily: action,
allowAggregateByAxis: true
});
return {
semanticDataNeed: "organization-scoped value-flow evidence",
chainId: "value_flow",
@@ -207,17 +397,20 @@ function recipeFor(input) {
extraReasons: primitiveSelection.reasonCodes
};
}
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "aggregate_by_axis", "probe_coverage"],
allowAggregateByAxis: true
});
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "amount");
pushUnique(axes, "coverage_target");
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
pushUnique(axes, "calendar_month");
}
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "aggregate_by_axis", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action,
allowAggregateByAxis: true
});
return {
semanticDataNeed: "counterparty value-flow evidence",
chainId: "value_flow",
@@ -231,13 +424,16 @@ function recipeFor(input) {
};
}
if (graphFactFamily === "activity_lifecycle") {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage", "explain_evidence_basis"]
});
pushUnique(axes, "document_date");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage", "explain_evidence_basis"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "counterparty lifecycle evidence",
chainId: "lifecycle",
@@ -249,11 +445,14 @@ function recipeFor(input) {
};
}
if (graphFactFamily === "schema_surface") {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["inspect_1c_metadata"]
});
pushUnique(axes, "metadata_scope");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["inspect_1c_metadata"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "1C metadata evidence",
chainId: "metadata_inspection",
@@ -265,11 +464,14 @@ function recipeFor(input) {
};
}
if (graphFactFamily === "movement_evidence") {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "probe_coverage"]
});
pushUnique(axes, "coverage_target");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "movement evidence",
chainId: "movement_evidence",
@@ -281,11 +483,14 @@ function recipeFor(input) {
};
}
if (graphFactFamily === "document_evidence") {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage"]
});
pushUnique(axes, "coverage_target");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "document evidence",
chainId: "document_evidence",
@@ -297,12 +502,15 @@ function recipeFor(input) {
};
}
if (graphFactFamily === "entity_grounding" || (!graphFactFamily && (dataNeedGraph?.subject_candidates.length ?? 0) > 0)) {
const primitiveSelection = primitivesFromGraphDecomposition({
dataNeedGraph,
fallbackPrimitives: ["search_business_entity", "resolve_entity_reference", "probe_coverage"]
});
pushUnique(axes, "business_entity");
pushUnique(axes, "coverage_target");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: ["search_business_entity", "resolve_entity_reference", "probe_coverage"],
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action
});
return {
semanticDataNeed: "entity discovery evidence",
chainId: "entity_resolution",
@@ -425,6 +633,7 @@ function planAssistantMcpDiscovery(input) {
const budgetOverride = budgetOverrideFor(input, recipe);
const semanticDataNeed = toNonEmptyString(input.semanticDataNeed) ?? recipe.semanticDataNeed;
const dataNeedGraph = input.dataNeedGraph ?? null;
const metadataSurface = input.metadataSurface ?? null;
const reasonCodes = [];
pushReason(reasonCodes, recipe.reason);
for (const reason of recipe.extraReasons ?? []) {
@@ -433,6 +642,9 @@ function planAssistantMcpDiscovery(input) {
if (dataNeedGraph) {
pushReason(reasonCodes, "planner_consumed_data_need_graph_v1");
}
if (metadataSurface) {
pushReason(reasonCodes, "planner_consumed_metadata_surface_ref_v1");
}
if (budgetOverride.maxProbeCount) {
pushReason(reasonCodes, "planner_enabled_chunked_coverage_probe_budget");
}
@@ -480,6 +692,7 @@ function planAssistantMcpDiscovery(input) {
planner_status: plannerStatus,
semantic_data_need: semanticDataNeed,
data_need_graph: dataNeedGraph,
metadata_surface_ref: metadataSurface,
selected_chain_id: recipe.chainId,
selected_chain_summary: recipe.chainSummary,
proposed_primitives: recipe.primitives,
@@ -52,6 +52,7 @@ async function runAssistantMcpDiscoveryRuntimeBridge(input) {
const planner = (0, assistantMcpDiscoveryPlanner_1.planAssistantMcpDiscovery)({
semanticDataNeed: input.semanticDataNeed,
dataNeedGraph: input.dataNeedGraph,
metadataSurface: input.metadataSurface,
turnMeaning: input.turnMeaning
});
const pilot = await (0, assistantMcpDiscoveryPilotExecutor_1.executeAssistantMcpDiscoveryPilot)(planner, input.deps);
@@ -63,6 +63,7 @@ async function runAssistantMcpDiscoveryRuntimeEntryPoint(input) {
const bridge = await (0, assistantMcpDiscoveryRuntimeBridge_1.runAssistantMcpDiscoveryRuntimeBridge)({
semanticDataNeed: turnInput.semantic_data_need,
dataNeedGraph: turnInput.data_need_graph,
metadataSurface: turnInput.metadata_surface_ref,
turnMeaning: turnInput.turn_meaning_ref,
deps: input.deps
});
@@ -145,6 +145,24 @@ function collectDateScopeFromFilters(filters) {
}
return periodFrom ?? periodTo ?? null;
}
function normalizeMetadataRouteFamily(value) {
const text = toNonEmptyString(value);
if (text === "document_evidence" || text === "movement_evidence" || text === "catalog_drilldown") {
return text;
}
return null;
}
function normalizeMetadataRecommendedPrimitive(value) {
const text = toNonEmptyString(value);
if (text === "query_documents" || text === "query_movements" || text === "drilldown_related_objects") {
return text;
}
return null;
}
function normalizeMetadataRouteFamilySelectionBasis(value) {
const text = toNonEmptyString(value);
return text === "selected_entity_set" || text === "dominant_surface_objects" ? text : null;
}
function mapPilotScopeToFollowupMeaning(pilotScope) {
if (pilotScope === "counterparty_lifecycle_query_documents_v1") {
return {
@@ -273,12 +291,39 @@ function collectFollowupDiscoverySeed(followupContext) {
rankingNeed: toNonEmptyString(followupContext?.previous_discovery_ranking_need),
organization,
dateScope,
metadataRouteFamily: toNonEmptyString(followupContext?.previous_discovery_metadata_route_family),
metadataRouteFamily: normalizeMetadataRouteFamily(followupContext?.previous_discovery_metadata_route_family),
metadataRouteFamilySelectionBasis: normalizeMetadataRouteFamilySelectionBasis(followupContext?.previous_discovery_metadata_route_family_selection_basis),
metadataSelectedEntitySet: toNonEmptyString(followupContext?.previous_discovery_metadata_selected_entity_set),
metadataSelectedSurfaceObjects: collectEntityCandidates(followupContext?.previous_discovery_metadata_selected_surface_objects),
metadataRecommendedNextPrimitive: normalizeMetadataRecommendedPrimitive(followupContext?.previous_discovery_metadata_recommended_next_primitive),
metadataAmbiguityDetected: followupContext?.previous_discovery_metadata_ambiguity_detected === true,
metadataAmbiguityEntitySets: collectEntityCandidates(followupContext?.previous_discovery_metadata_ambiguity_entity_sets)
};
}
function buildMetadataSurfaceRef(followupSeed) {
if (followupSeed.pilotScope !== "metadata_inspection_v1") {
return null;
}
const hasPayload = Boolean(followupSeed.metadataRouteFamily ||
followupSeed.metadataSelectedEntitySet ||
followupSeed.metadataRecommendedNextPrimitive ||
followupSeed.metadataRouteFamilySelectionBasis) ||
followupSeed.metadataSelectedSurfaceObjects.length > 0 ||
followupSeed.metadataAmbiguityDetected ||
followupSeed.metadataAmbiguityEntitySets.length > 0;
if (!hasPayload) {
return null;
}
return {
selected_entity_set: followupSeed.metadataSelectedEntitySet,
selected_surface_objects: followupSeed.metadataSelectedSurfaceObjects,
downstream_route_family: followupSeed.metadataRouteFamily,
route_family_selection_basis: followupSeed.metadataRouteFamilySelectionBasis,
recommended_next_primitive: followupSeed.metadataRecommendedNextPrimitive,
ambiguity_detected: followupSeed.metadataAmbiguityDetected,
ambiguity_entity_sets: followupSeed.metadataAmbiguityEntitySets
};
}
function metadataEntitySetsSuggestDocumentLane(values) {
return values.some((value) => /(?:документ|document|invoice|waybill|накладн|счет[- ]?фактур|акт)/iu.test(value));
}
@@ -295,7 +340,7 @@ function hasLifecycleSignal(text) {
return /(?:сколько\s+лет|как\s+давно|давно\s+ли|возраст|перв(?:ая|ый)\s+актив|когда\s+начал|когда\s+появ|lifecycle|activity\s+duration|business\s+age|how\s+long)/iu.test(text);
}
function hasValueFlowSignal(text) {
return /(?:оборот|выручк|оплат|плат[её]ж|заплат|перечисл|списан|расход|исходящ|входящ|получ(?:ил|ено|ен)|поступил|поступлен|денежн[а-яёa-z0-9_-]*\s+поток|supplier|value[-\s]?flow|turnover|revenue|payment|payout|outflow|cash\s+flow)/iu.test(text);
return /(?:оборот|выручк|оплат|плат[её]ж|заплат|перечисл|списан|расход|исходящ|входящ|получ(?:ил|ено|ен)|поступил|поступлен|денежн[а-яёa-z0-9_-]*\s+поток|(?<!\p{L})заработ(?:ал|али|ало|аем|ает|ать|ано|ок)(?!\p{L})|supplier|value[-\s]?flow|turnover|revenue|payment|payout|outflow|cash\s+flow|\bearn(?:ed|ing|ings)?\b)/iu.test(text);
}
function hasPayoutSignal(text) {
return /(?:\bмы\s+(?:за)?плат|(?:за)?платил|оплатил|перечисл|списан|расход|поставщик|исходящ|supplier|payout|outflow|paid\s+to|payment\s+to)/iu.test(text);
@@ -328,6 +373,9 @@ function extractOrganizationScopeFromRawText(value) {
function hasMonthlyAggregationSignal(text) {
return /(?:\u043f\u043e\s+\u043c\u0435\u0441\u044f\u0446\u0430\u043c|\u043f\u043e\u043c\u0435\u0441\u044f\u0447\u043d\u043e|\u0435\u0436\u0435\u043c\u0435\u0441\u044f\u0447\u043d\u043e|month\s+by\s+month|by\s+month|monthly)/iu.test(text);
}
function hasAllTimeScopeHint(text) {
return /(?:\u0437\u0430\s+\u0432\u0441[\u0435\u0451]\s+\u0432\u0440\u0435\u043c\u044f|\u0437\u0430\s+\u0432\u0435\u0441\u044c\s+\u043f\u0435\u0440\u0438\u043e\u0434|\u0437\u0430\s+\u0432\u0441\u044e\s+\u0438\u0441\u0442\u043e\u0440\u0438(?:\u044e|\u0438)|\u0437\u0430\s+\u043b\u044e\u0431\u043e\u0439\s+\u043f\u0435\u0440\u0438\u043e\u0434|for\s+all\s+time|all\s+time|entire\s+period|full\s+history|any\s+period)/iu.test(text);
}
function hasMetadataSignal(text) {
if (/(?:\u043c\u0435\u0442\u0430\u0434\u0430\u043d|schema|catalog|metadata\s+surface|\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440[\u0430\u044b]\s+1\u0441|\u0441\u0445\u0435\u043c[\u0430\u044b]\s+1\u0441)/iu.test(text)) {
return true;
@@ -570,6 +618,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
const followupContext = toRecordObject(input.followupContext);
const predecomposeEntities = collectPredecomposeEntities(predecomposeContract);
const followupSeed = collectFollowupDiscoverySeed(followupContext);
const metadataSurfaceRef = buildMetadataSurfaceRef(followupSeed);
const reasonCodes = [];
const rawUserText = toNonEmptyString(input.userMessage);
const rawEffectiveText = toNonEmptyString(input.effectiveMessage);
@@ -584,6 +633,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
const rawEntityResolutionSignal = !rawLifecycleSignal && !rawValueFlowSignal && !rawMetadataSignal && hasEntityResolutionSignal(rawText);
const rawPayoutSignal = rawValueFlowSignal && !rawBidirectionalValueFlowSignal && hasPayoutSignal(rawText);
const monthlyAggregationSignal = hasMonthlyAggregationSignal(rawText);
const rawAllTimeScopeSignal = hasAllTimeScopeHint(rawText);
const explicitDateScopeLiteralDetected = hasExplicitDateScopeLiteral(rawText);
const rawDateScope = collectDateScopeFromRawText(rawText);
const rawMetadataScopeHint = rawMetadataSignal ? metadataScopeHintFromRawText(rawText) : null;
@@ -889,7 +939,14 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
}
}
}
const explicitDateScope = assistantTurnMeaningDateScope ?? predecomposeDateScope ?? rawDateScope ?? followupSeed.dateScope;
const explicitDateScope = rawAllTimeScopeSignal
? null
: assistantTurnMeaningDateScope ?? predecomposeDateScope ?? rawDateScope ?? followupSeed.dateScope;
const followupDateScopeApplied = Boolean(!rawAllTimeScopeSignal &&
!assistantTurnMeaningDateScope &&
!predecomposeDateScope &&
!rawDateScope &&
followupSeed.dateScope);
const turnMeaning = {
asked_domain_family: lifecycleSignal
? "counterparty_lifecycle"
@@ -1072,6 +1129,9 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (monthlyAggregationSignal) {
pushReason(reasonCodes, "mcp_discovery_monthly_aggregation_signal_detected");
}
if (rawAllTimeScopeSignal) {
pushReason(reasonCodes, "mcp_discovery_all_time_scope_signal_detected");
}
if (followupDiscoverySeedApplicable) {
pushReason(reasonCodes, "mcp_discovery_seeded_from_followup_context");
}
@@ -1139,9 +1199,15 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (followupSeed.counterparty) {
pushReason(reasonCodes, "mcp_discovery_counterparty_from_followup_context");
}
if (followupSeed.dateScope) {
if (followupDateScopeApplied) {
pushReason(reasonCodes, "mcp_discovery_date_scope_from_followup_context");
}
if (metadataSurfaceRef) {
pushReason(reasonCodes, "mcp_discovery_metadata_surface_ref_from_followup_context");
}
if (metadataSurfaceRef?.recommended_next_primitive) {
pushReason(reasonCodes, "mcp_discovery_metadata_next_primitive_from_followup_context");
}
if (entityCandidates.length > 0) {
pushReason(reasonCodes, "mcp_discovery_entity_scope_available");
}
@@ -1168,6 +1234,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
should_run_discovery: runDiscovery,
semantic_data_need: runDiscovery ? semanticDataNeed : null,
data_need_graph: dataNeedGraph,
metadata_surface_ref: runDiscovery ? metadataSurfaceRef : null,
turn_meaning_ref: runDiscovery && hasTurnMeaning ? cleanTurnMeaning : null,
source_signal: sourceSignal,
reason_codes: reasonCodes
@@ -500,7 +500,10 @@ function createAssistantTransitionPolicy(deps) {
const sourceIntent = (0, assistantContinuityPolicy_1.readAddressDebugIntent)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryPilotScope = sourceDiscoveryPilotScopeHint;
const sourceDiscoveryMetadataRouteFamily = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataRouteFamily)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataRouteFamilySelectionBasis = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataRouteFamilySelectionBasis)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataSelectedEntitySet = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataSelectedEntitySet)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataSelectedSurfaceObjects = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataSelectedSurfaceObjects)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataRecommendedNextPrimitive = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataRecommendedNextPrimitive)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryMetadataAmbiguityDetected = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataAmbiguityDetected)(carryoverSourceDebug);
const sourceDiscoveryMetadataAmbiguityEntitySets = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryMetadataAmbiguityEntitySets)(carryoverSourceDebug, deps.toNonEmptyString);
const sourceDiscoveryEntityResolutionStatus = (0, assistantContinuityPolicy_1.readAssistantMcpDiscoveryEntityResolutionStatus)(carryoverSourceDebug, deps.toNonEmptyString);
@@ -748,7 +751,12 @@ function createAssistantTransitionPolicy(deps) {
? 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,
resolved_counterparty_from_display: resolvedCounterpartyFromDisplay || undefined,