ARCH: перезапустить план на MCP bounded autonomy и добавить metadata pilot

This commit is contained in:
2026-04-21 22:04:23 +03:00
parent bda7ca9cc1
commit 561b4ea45c
15 changed files with 1214 additions and 57 deletions
@@ -64,9 +64,15 @@ function isValueFlowPilot(pilot) {
pilot.pilot_scope === "counterparty_supplier_payout_query_movements_v1" ||
pilot.pilot_scope === "counterparty_bidirectional_value_flow_query_movements_v1");
}
function isMetadataPilot(pilot) {
return pilot.pilot_scope === "metadata_inspection_v1";
}
function headlineFor(mode, pilot) {
const askedMonthlyBreakdown = pilot.derived_bidirectional_value_flow?.aggregation_axis === "month" ||
pilot.derived_value_flow?.aggregation_axis === "month";
if (pilot.derived_metadata_surface && mode === "confirmed_with_bounded_inference") {
return "По метаданным 1С найдена доступная схема для дальнейшего безопасного поиска.";
}
if (askedMonthlyBreakdown && pilot.derived_bidirectional_value_flow && mode === "confirmed_with_bounded_inference") {
return "По данным 1С найдены строки входящих и исходящих денежных движений; нетто и помесячная раскладка могут называться только как расчет по найденным строкам и проверенному периоду.";
}
@@ -124,6 +130,10 @@ function buildMustNotClaim(pilot) {
claims.push("Do not claim full all-time turnover unless the checked period and coverage prove it.");
claims.push("Do not present a derived sum as a legal/accounting final total outside the checked 1C rows.");
}
if (isMetadataPilot(pilot)) {
claims.push("Do not present metadata surface as confirmed business data rows.");
claims.push("Do not claim a document/register exists outside the checked metadata probe results.");
}
if (pilot.evidence.confirmed_facts.length === 0) {
claims.push("Do not claim a confirmed business fact when confirmed_facts is empty.");
}
@@ -172,6 +182,23 @@ function derivedActivityInferenceLine(pilot) {
"Это вывод по данным 1С, а не юридически подтвержденный возраст регистрации."
].join(" ");
}
function derivedMetadataConfirmedLine(pilot) {
const surface = pilot.derived_metadata_surface;
if (!surface) {
return null;
}
const scope = surface.metadata_scope ? ` по области "${surface.metadata_scope}"` : "";
const entitySets = surface.available_entity_sets.length > 0
? ` Типы объектов: ${surface.available_entity_sets.join(", ")}.`
: "";
const objects = surface.matched_objects.length > 0
? ` Найденные объекты: ${surface.matched_objects.slice(0, 8).join(", ")}.`
: "";
const fields = surface.available_fields.length > 0
? ` Доступные поля/секции: ${surface.available_fields.slice(0, 12).join(", ")}.`
: "";
return `Подтвержденная metadata-поверхность 1С${scope}: ${surface.matched_rows} строк metadata-ответа.${entitySets}${objects}${fields}`.replace(/\s+/g, " ").trim();
}
function derivedValueFlowConfirmedLine(pilot) {
const flow = pilot.derived_value_flow;
if (!flow) {
@@ -262,6 +289,7 @@ function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
const inferenceLines = derivedInferenceLine
? [derivedInferenceLine]
: pilot.evidence.inferred_facts;
const derivedMetadataLine = derivedMetadataConfirmedLine(pilot);
const derivedValueLine = derivedBidirectionalValueFlowConfirmedLine(pilot) ?? derivedValueFlowConfirmedLine(pilot);
const monthlyConfirmedLines = derivedBidirectionalValueFlowMonthlyLines(pilot).length > 0
? derivedBidirectionalValueFlowMonthlyLines(pilot)
@@ -271,7 +299,9 @@ function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
}
const confirmedLines = derivedValueLine
? [...pilot.evidence.confirmed_facts, derivedValueLine, ...monthlyConfirmedLines]
: pilot.evidence.confirmed_facts;
: derivedMetadataLine
? [...pilot.evidence.confirmed_facts, derivedMetadataLine]
: pilot.evidence.confirmed_facts;
return {
schema_version: exports.ASSISTANT_MCP_DISCOVERY_ANSWER_DRAFT_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryAnswerAdapter",
@@ -8,7 +8,8 @@ const assistantMcpDiscoveryPolicy_1 = require("./assistantMcpDiscoveryPolicy");
const addressRecipeCatalog_1 = require("./addressRecipeCatalog");
exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION = "assistant_mcp_discovery_pilot_executor_v1";
const DEFAULT_DEPS = {
executeAddressMcpQuery: addressMcpClient_1.executeAddressMcpQuery
executeAddressMcpQuery: addressMcpClient_1.executeAddressMcpQuery,
executeAddressMcpMetadata: addressMcpClient_1.executeAddressMcpMetadata
};
function toNonEmptyString(value) {
if (value === null || value === undefined) {
@@ -119,6 +120,55 @@ function isValueFlowPilotEligible(planner) {
combined.includes("payout") ||
combined.includes("value")));
}
function isMetadataPilotEligible(planner) {
const meaning = planner.discovery_plan.turn_meaning_ref;
const domain = String(meaning?.asked_domain_family ?? "").toLowerCase();
const action = String(meaning?.asked_action_family ?? "").toLowerCase();
const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase();
const semanticNeed = String(planner.semantic_data_need ?? "").toLowerCase();
const combined = `${domain} ${action} ${unsupported} ${semanticNeed}`;
return (planner.proposed_primitives.includes("inspect_1c_metadata") &&
(combined.includes("metadata") ||
combined.includes("schema") ||
combined.includes("catalog") ||
combined.includes("inspect_documents") ||
combined.includes("inspect_registers") ||
combined.includes("inspect_fields")));
}
function metadataScopeForPlanner(planner) {
const entityCandidate = firstEntityCandidate(planner);
if (entityCandidate) {
return entityCandidate;
}
const meaning = planner.discovery_plan.turn_meaning_ref;
const combined = `${meaning?.asked_domain_family ?? ""} ${meaning?.asked_action_family ?? ""} ${meaning?.unsupported_but_understood_family ?? ""}`
.toLowerCase()
.trim();
if (combined.includes("vat")) {
return "НДС";
}
if (combined.includes("inventory")) {
return "склад";
}
if (combined.includes("counterparty")) {
return "контрагент";
}
return null;
}
function metadataTypesForPlanner(planner) {
const meaning = planner.discovery_plan.turn_meaning_ref;
const action = String(meaning?.asked_action_family ?? "").toLowerCase();
if (action === "inspect_registers") {
return ["РегистрНакопления", "РегистрСведений"];
}
if (action === "inspect_documents") {
return ["Документ"];
}
if (action === "inspect_catalog") {
return ["Справочник"];
}
return ["Документ", "РегистрНакопления", "РегистрСведений", "Справочник"];
}
function valueFlowPilotProfile(planner) {
const meaning = planner.discovery_plan.turn_meaning_ref;
const action = String(meaning?.asked_action_family ?? "").toLowerCase();
@@ -168,6 +218,15 @@ function queryResultToProbeResult(primitiveId, result) {
limitation: result.error
};
}
function metadataResultToProbeResult(primitiveId, result) {
return {
primitive_id: primitiveId,
status: result.error ? "error" : "ok",
rows_received: result.fetched_rows,
rows_matched: result.error ? 0 : result.rows.length,
limitation: result.error
};
}
function toCoverageAwareQueryResult(result, options = {}) {
if (!result) {
return null;
@@ -332,6 +391,147 @@ function summarizeValueFlowRows(result) {
}
return `${result.fetched_rows} MCP value-flow rows fetched, ${result.matched_rows} matched value-flow scope`;
}
function summarizeMetadataRows(result) {
if (result.error) {
return null;
}
if (result.fetched_rows <= 0) {
return "0 MCP metadata rows fetched";
}
return `${result.fetched_rows} MCP metadata rows fetched`;
}
function metadataRowText(row, keys) {
for (const key of keys) {
const text = toNonEmptyString(row[key]);
if (text) {
return text;
}
}
return null;
}
function metadataObjectName(row) {
return metadataRowText(row, [
"ПолноеИмя",
"full_name",
"FullName",
"Имя",
"name",
"Name",
"presentation",
"Представление",
"synonym",
"Synonym"
]);
}
function metadataEntitySet(row) {
return metadataRowText(row, [
"ТипМетаданных",
"type",
"Type",
"meta_type",
"MetaType",
"ВидМетаданных",
"kind"
]);
}
function metadataChildNames(value) {
if (!Array.isArray(value)) {
return [];
}
const result = [];
for (const item of value) {
if (!item || typeof item !== "object" || Array.isArray(item)) {
continue;
}
const record = item;
const fieldName = metadataRowText(record, ["Имя", "name", "Name", "full_name", "FullName"]);
if (fieldName) {
pushUnique(result, fieldName);
}
}
return result;
}
function metadataAvailableFields(rows) {
const result = [];
for (const row of rows) {
for (const field of metadataChildNames(row["Реквизиты"])) {
pushUnique(result, field);
}
for (const field of metadataChildNames(row["attributes"])) {
pushUnique(result, field);
}
for (const field of metadataChildNames(row["Attributes"])) {
pushUnique(result, field);
}
for (const field of metadataChildNames(row["Измерения"])) {
pushUnique(result, field);
}
for (const field of metadataChildNames(row["dimensions"])) {
pushUnique(result, field);
}
for (const field of metadataChildNames(row["Ресурсы"])) {
pushUnique(result, field);
}
for (const field of metadataChildNames(row["resources"])) {
pushUnique(result, field);
}
}
return result;
}
function deriveMetadataSurface(result, metadataScope, requestedMetaTypes) {
if (!result || result.error || result.rows.length <= 0) {
return null;
}
const matchedObjects = [];
const availableEntitySets = [];
for (const row of result.rows) {
const objectName = metadataObjectName(row);
if (objectName) {
pushUnique(matchedObjects, objectName);
}
const entitySet = metadataEntitySet(row);
if (entitySet) {
pushUnique(availableEntitySets, entitySet);
}
}
return {
metadata_scope: metadataScope,
requested_meta_types: requestedMetaTypes,
matched_rows: result.rows.length,
available_entity_sets: availableEntitySets,
matched_objects: matchedObjects,
available_fields: metadataAvailableFields(result.rows),
known_limitations: [],
inference_basis: "confirmed_1c_metadata_surface_rows"
};
}
function buildMetadataConfirmedFacts(surface) {
if (!surface) {
return [];
}
const facts = [];
const scopeSuffix = surface.metadata_scope ? ` for ${surface.metadata_scope}` : "";
facts.push(`Confirmed 1C metadata surface${scopeSuffix}: ${surface.matched_rows} rows and ${surface.matched_objects.length} matching objects`);
if (surface.available_entity_sets.length > 0) {
facts.push(`Available metadata object sets: ${surface.available_entity_sets.join(", ")}`);
}
if (surface.available_fields.length > 0) {
facts.push(`Available metadata fields/sections: ${surface.available_fields.slice(0, 12).join(", ")}`);
}
return facts;
}
function buildMetadataUnknownFacts(surface, metadataScope) {
if (surface) {
if (surface.available_fields.length > 0) {
return [];
}
return ["Detailed metadata fields were not returned by this MCP metadata probe"];
}
if (metadataScope) {
return [`No matching 1C metadata objects were confirmed for scope "${metadataScope}"`];
}
return ["No matching 1C metadata objects were confirmed by this MCP metadata probe"];
}
function rowDateValue(row) {
const candidates = [
row["Период"],
@@ -756,13 +956,27 @@ function buildEmptyEvidence(planner, dryRun, probeResults, reason) {
recommendedNextProbe: dryRun.user_facing_fallback
});
}
function pilotScopeForPlanner(planner) {
if (isMetadataPilotEligible(planner)) {
return "metadata_inspection_v1";
}
if (isValueFlowPilotEligible(planner)) {
return valueFlowPilotProfile(planner).scope;
}
return "counterparty_lifecycle_query_documents_v1";
}
async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
const runtimeDeps = {
...DEFAULT_DEPS,
...deps
};
const dryRun = (0, assistantMcpDiscoveryRuntimeAdapter_1.buildAssistantMcpDiscoveryRuntimeDryRun)(planner);
const reasonCodes = [...dryRun.reason_codes];
const executedPrimitives = [];
const skippedPrimitives = [];
const probeResults = [];
const queryLimitations = [];
const pilotScope = pilotScopeForPlanner(planner);
if (dryRun.adapter_status === "blocked") {
pushReason(reasonCodes, "pilot_blocked_before_mcp_execution");
const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "MCP discovery pilot was blocked before execution");
@@ -770,7 +984,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryPilotExecutor",
pilot_status: "blocked",
pilot_scope: "counterparty_lifecycle_query_documents_v1",
pilot_scope: pilotScope,
dry_run: dryRun,
mcp_execution_performed: false,
executed_primitives: executedPrimitives,
@@ -778,6 +992,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: null,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -792,7 +1007,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryPilotExecutor",
pilot_status: "skipped_needs_clarification",
pilot_scope: "counterparty_lifecycle_query_documents_v1",
pilot_scope: pilotScope,
dry_run: dryRun,
mcp_execution_performed: false,
executed_primitives: executedPrimitives,
@@ -800,6 +1015,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: null,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -807,9 +1023,10 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
reason_codes: reasonCodes
};
}
const metadataPilotEligible = isMetadataPilotEligible(planner);
const lifecyclePilotEligible = isLifecyclePilotEligible(planner);
const valueFlowPilotEligible = isValueFlowPilotEligible(planner);
if (!lifecyclePilotEligible && !valueFlowPilotEligible) {
if (!metadataPilotEligible && !lifecyclePilotEligible && !valueFlowPilotEligible) {
pushReason(reasonCodes, "pilot_scope_unsupported_for_live_execution");
for (const step of dryRun.execution_steps) {
skippedPrimitives.push(step.primitive_id);
@@ -820,7 +1037,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryPilotExecutor",
pilot_status: "unsupported",
pilot_scope: "counterparty_lifecycle_query_documents_v1",
pilot_scope: pilotScope,
dry_run: dryRun,
mcp_execution_performed: false,
executed_primitives: executedPrimitives,
@@ -828,6 +1045,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: null,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -838,6 +1056,65 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
const counterparty = firstEntityCandidate(planner);
const dateScope = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.explicit_date_scope);
const aggregationAxis = aggregationAxisForPlanner(planner);
if (metadataPilotEligible) {
let metadataResult = null;
const metadataScope = metadataScopeForPlanner(planner);
const requestedMetaTypes = metadataTypesForPlanner(planner);
for (const step of dryRun.execution_steps) {
if (step.primitive_id !== "inspect_1c_metadata") {
skippedPrimitives.push(step.primitive_id);
probeResults.push(skippedProbeResult(step, "pilot_metadata_uses_only_inspect_1c_metadata"));
continue;
}
metadataResult = await runtimeDeps.executeAddressMcpMetadata({
meta_type: requestedMetaTypes,
name_mask: metadataScope ?? undefined,
limit: planner.discovery_plan.execution_budget.max_rows_per_probe
});
pushUnique(executedPrimitives, step.primitive_id);
probeResults.push(metadataResultToProbeResult(step.primitive_id, metadataResult));
if (metadataResult.error) {
pushUnique(queryLimitations, metadataResult.error);
pushReason(reasonCodes, "pilot_inspect_1c_metadata_mcp_error");
}
else {
pushReason(reasonCodes, "pilot_inspect_1c_metadata_mcp_executed");
}
}
const sourceRowsSummary = metadataResult ? summarizeMetadataRows(metadataResult) : null;
const derivedMetadataSurface = deriveMetadataSurface(metadataResult, metadataScope, requestedMetaTypes);
if (derivedMetadataSurface) {
pushReason(reasonCodes, "pilot_derived_metadata_surface_from_confirmed_rows");
}
const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({
plan: planner.discovery_plan,
probeResults,
confirmedFacts: buildMetadataConfirmedFacts(derivedMetadataSurface),
unknownFacts: buildMetadataUnknownFacts(derivedMetadataSurface, metadataScope),
sourceRowsSummary,
queryLimitations,
recommendedNextProbe: "inspect_1c_metadata"
});
return {
schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryPilotExecutor",
pilot_status: "executed",
pilot_scope: "metadata_inspection_v1",
dry_run: dryRun,
mcp_execution_performed: executedPrimitives.length > 0,
executed_primitives: executedPrimitives,
skipped_primitives: skippedPrimitives,
probe_results: probeResults,
evidence,
source_rows_summary: sourceRowsSummary,
derived_metadata_surface: derivedMetadataSurface,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
query_limitations: queryLimitations,
reason_codes: reasonCodes
};
}
if (valueFlowPilotEligible) {
let queryResult = null;
const filters = buildValueFlowFilters(planner);
@@ -862,6 +1139,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: null,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -883,7 +1161,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
dateScope,
maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count,
maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe,
deps
deps: runtimeDeps
});
const outgoingExecution = await executeCoverageAwareValueFlowQuery({
primitiveId: step.primitive_id,
@@ -892,7 +1170,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
dateScope,
maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count,
maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe,
deps
deps: runtimeDeps
});
incomingResult = incomingExecution.result;
outgoingResult = outgoingExecution.result;
@@ -953,6 +1231,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: sourceRowsSummary,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: derivedBidirectionalValueFlow,
@@ -977,6 +1256,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: null,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -1000,7 +1280,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
dateScope,
maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count,
maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe,
deps
deps: runtimeDeps
});
queryResult = execution.result;
pushUnique(executedPrimitives, step.primitive_id);
@@ -1048,6 +1328,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: sourceRowsSummary,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: derivedValueFlow,
derived_bidirectional_value_flow: null,
@@ -1073,6 +1354,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: null,
derived_metadata_surface: null,
derived_activity_period: null,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -1087,7 +1369,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probeResults.push(skippedProbeResult(step, "pilot_only_executes_query_documents"));
continue;
}
queryResult = await deps.executeAddressMcpQuery({
queryResult = await runtimeDeps.executeAddressMcpQuery({
query: recipePlan.query,
limit: recipePlan.limit,
account_scope: recipePlan.account_scope
@@ -1129,6 +1411,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
probe_results: probeResults,
evidence,
source_rows_summary: sourceRowsSummary,
derived_metadata_surface: null,
derived_activity_period: derivedActivityPeriod,
derived_value_flow: null,
derived_bidirectional_value_flow: null,
@@ -98,15 +98,6 @@ function recipeFor(input) {
: "planner_selected_value_flow_recipe"
};
}
if (includesAny(combined, ["document", "documents"])) {
pushUnique(axes, "coverage_target");
return {
semanticDataNeed: "document evidence",
primitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
axes,
reason: "planner_selected_document_recipe"
};
}
if (includesAny(combined, ["lifecycle", "activity", "duration", "age"])) {
pushUnique(axes, "document_date");
pushUnique(axes, "coverage_target");
@@ -127,6 +118,15 @@ function recipeFor(input) {
reason: "planner_selected_metadata_recipe"
};
}
if (includesAny(combined, ["document", "documents"])) {
pushUnique(axes, "coverage_target");
return {
semanticDataNeed: "document evidence",
primitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
axes,
reason: "planner_selected_document_recipe"
};
}
if (hasEntity(meaning)) {
pushUnique(axes, "business_entity");
return {
@@ -220,6 +220,28 @@ function hasBidirectionalValueFlowSignal(text) {
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 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;
}
return (/(?:\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b|\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b|\u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438|\u043f\u043e\u043b(?:\u0435|\u044f)|registers?|documents?|catalogs?|fields?)/iu.test(text) &&
/(?:\u0435\u0441\u0442\u044c|\u0434\u043e\u0441\u0442\u0443\u043f\u043d|\u0432\s+1\u0441|available|exist)/iu.test(text));
}
function metadataActionFromRawText(text) {
if (/(?:\u043f\u043e\u043b(?:\u0435|\u044f)|field)/iu.test(text)) {
return "inspect_fields";
}
if (/(?:\u0440\u0435\u0433\u0438\u0441\u0442\u0440|register)/iu.test(text)) {
return "inspect_registers";
}
if (/(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442|document)/iu.test(text)) {
return "inspect_documents";
}
if (/(?:\u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a|directory|catalog)/iu.test(text)) {
return "inspect_catalog";
}
return "inspect_catalog";
}
function hasExplicitDateScopeLiteral(text) {
return /(?:\b(?:19|20)\d{2}\b|\b\d{4}-\d{2}-\d{2}\b|\b\d{4}-\d{2}\b)/iu.test(text);
}
@@ -240,6 +262,9 @@ function collectDateScopeFromRawText(text) {
}
function semanticNeedFor(input) {
const combined = compactLower(`${input.domain ?? ""} ${input.action ?? ""} ${input.unsupported ?? ""}`);
if (input.metadataSignal || /(?:metadata|schema|catalog|inspect_(?:catalog|documents|registers|fields))/iu.test(combined)) {
return "1C metadata evidence";
}
if (input.lifecycleSignal || /(?:lifecycle|activity|duration|age)/iu.test(combined)) {
return "counterparty lifecycle evidence";
}
@@ -249,15 +274,15 @@ function semanticNeedFor(input) {
if (/(?:document|documents|list_documents)/iu.test(combined)) {
return "document evidence";
}
if (/(?:metadata|schema|catalog)/iu.test(combined)) {
return "1C metadata evidence";
}
return null;
}
function shouldRunDiscovery(input) {
if (input.lifecycleSignal || input.unsupported) {
return true;
}
if (input.metadataSignal) {
return true;
}
if (input.valueFlowSignal && !input.explicitIntentCandidate) {
return true;
}
@@ -280,6 +305,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
const rawLifecycleSignal = hasLifecycleSignal(rawText);
const rawBidirectionalValueFlowSignal = !rawLifecycleSignal && hasBidirectionalValueFlowSignal(rawText);
const rawValueFlowSignal = !rawLifecycleSignal && (hasValueFlowSignal(rawText) || rawBidirectionalValueFlowSignal);
const rawMetadataSignal = !rawLifecycleSignal && !rawValueFlowSignal && hasMetadataSignal(rawText);
const rawPayoutSignal = rawValueFlowSignal && !rawBidirectionalValueFlowSignal && hasPayoutSignal(rawText);
const monthlyAggregationSignal = hasMonthlyAggregationSignal(rawText);
const explicitDateScopeLiteralDetected = hasExplicitDateScopeLiteral(rawText);
@@ -311,7 +337,8 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
action: rawAction ?? seededAction,
unsupported: unsupported ?? seededUnsupported,
lifecycleSignal,
valueFlowSignal
valueFlowSignal,
metadataSignal: rawMetadataSignal
});
const entityCandidates = collectEntityCandidates(assistantTurnMeaning?.explicit_entity_candidates);
pushUnique(entityCandidates, predecomposeEntities.counterparty);
@@ -329,7 +356,9 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
? "counterparty_lifecycle"
: valueFlowSignal
? "counterparty_value"
: rawDomain ?? seededDomain,
: rawMetadataSignal
? "metadata"
: rawDomain ?? seededDomain,
asked_action_family: lifecycleSignal
? "activity_duration"
: valueFlowSignal
@@ -338,7 +367,9 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
: payoutSignal
? "payout"
: rawAction ?? seededAction ?? "turnover"
: rawAction ?? seededAction,
: rawMetadataSignal
? metadataActionFromRawText(rawText)
: rawAction ?? seededAction,
asked_aggregation_axis: monthlyAggregationSignal ? "month" : rawAggregationAxis,
explicit_entity_candidates: entityCandidates,
explicit_organization_scope: explicitOrganizationScope,
@@ -352,13 +383,16 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
: payoutSignal
? "counterparty_payouts_or_outflow"
: seededUnsupported ?? "counterparty_value_or_turnover"
: followupDiscoverySeedApplicable
? seededUnsupported
: null),
: rawMetadataSignal
? "1c_metadata_surface"
: followupDiscoverySeedApplicable
? seededUnsupported
: null),
stale_replay_forbidden: Boolean(assistantTurnMeaning?.stale_replay_forbidden ||
unsupported ||
lifecycleSignal ||
valueFlowSignal ||
rawMetadataSignal ||
followupDiscoverySeedApplicable)
};
const cleanTurnMeaning = {};
@@ -390,6 +424,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
unsupported: unsupported ?? seededUnsupported,
lifecycleSignal,
valueFlowSignal,
metadataSignal: rawMetadataSignal,
semanticDataNeed,
explicitIntentCandidate,
followupDiscoverySeedApplicable
@@ -405,13 +440,18 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
? "raw_text"
: valueFlowSignal
? "raw_text"
: "none";
: rawMetadataSignal
? "raw_text"
: "none";
if (lifecycleSignal) {
pushReason(reasonCodes, "mcp_discovery_lifecycle_signal_detected");
}
if (valueFlowSignal) {
pushReason(reasonCodes, "mcp_discovery_value_flow_signal_detected");
}
if (rawMetadataSignal) {
pushReason(reasonCodes, "mcp_discovery_metadata_signal_detected");
}
if (payoutSignal) {
pushReason(reasonCodes, "mcp_discovery_payout_signal_detected");
}