ARCH: перезапустить план на MCP bounded autonomy и добавить metadata pilot
This commit is contained in:
@@ -97,10 +97,17 @@ function isValueFlowPilot(pilot: AssistantMcpDiscoveryPilotExecutionContract): b
|
||||
);
|
||||
}
|
||||
|
||||
function isMetadataPilot(pilot: AssistantMcpDiscoveryPilotExecutionContract): boolean {
|
||||
return pilot.pilot_scope === "metadata_inspection_v1";
|
||||
}
|
||||
|
||||
function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpDiscoveryPilotExecutionContract): string {
|
||||
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С найдены строки входящих и исходящих денежных движений; нетто и помесячная раскладка могут называться только как расчет по найденным строкам и проверенному периоду.";
|
||||
}
|
||||
@@ -160,6 +167,10 @@ function buildMustNotClaim(pilot: AssistantMcpDiscoveryPilotExecutionContract):
|
||||
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.");
|
||||
}
|
||||
@@ -213,6 +224,27 @@ function derivedActivityInferenceLine(pilot: AssistantMcpDiscoveryPilotExecution
|
||||
].join(" ");
|
||||
}
|
||||
|
||||
function derivedMetadataConfirmedLine(pilot: AssistantMcpDiscoveryPilotExecutionContract): string | null {
|
||||
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: AssistantMcpDiscoveryPilotExecutionContract): string | null {
|
||||
const flow = pilot.derived_value_flow;
|
||||
if (!flow) {
|
||||
@@ -318,6 +350,7 @@ export function buildAssistantMcpDiscoveryAnswerDraft(
|
||||
const inferenceLines = derivedInferenceLine
|
||||
? [derivedInferenceLine]
|
||||
: pilot.evidence.inferred_facts;
|
||||
const derivedMetadataLine = derivedMetadataConfirmedLine(pilot);
|
||||
const derivedValueLine = derivedBidirectionalValueFlowConfirmedLine(pilot) ?? derivedValueFlowConfirmedLine(pilot);
|
||||
const monthlyConfirmedLines =
|
||||
derivedBidirectionalValueFlowMonthlyLines(pilot).length > 0
|
||||
@@ -328,7 +361,9 @@ export function buildAssistantMcpDiscoveryAnswerDraft(
|
||||
}
|
||||
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: ASSISTANT_MCP_DISCOVERY_ANSWER_DRAFT_SCHEMA_VERSION,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
executeAddressMcpMetadata,
|
||||
executeAddressMcpQuery,
|
||||
type AddressMcpMetadataRowsResult
|
||||
} from "./addressMcpClient";
|
||||
@@ -26,7 +27,13 @@ export type AssistantMcpDiscoveryPilotStatus =
|
||||
| "unsupported";
|
||||
|
||||
export interface AssistantMcpDiscoveryPilotExecutorDeps {
|
||||
executeAddressMcpQuery?: typeof executeAddressMcpQuery;
|
||||
executeAddressMcpMetadata?: typeof executeAddressMcpMetadata;
|
||||
}
|
||||
|
||||
interface ResolvedAssistantMcpDiscoveryPilotExecutorDeps {
|
||||
executeAddressMcpQuery: typeof executeAddressMcpQuery;
|
||||
executeAddressMcpMetadata: typeof executeAddressMcpMetadata;
|
||||
}
|
||||
|
||||
export interface AssistantMcpDiscoveryDerivedActivityPeriod {
|
||||
@@ -109,6 +116,17 @@ export interface AssistantMcpDiscoveryDerivedBidirectionalValueFlow {
|
||||
inference_basis: "incoming_minus_outgoing_confirmed_1c_value_flow_rows";
|
||||
}
|
||||
|
||||
export interface AssistantMcpDiscoveryDerivedMetadataSurface {
|
||||
metadata_scope: string | null;
|
||||
requested_meta_types: string[];
|
||||
matched_rows: number;
|
||||
available_entity_sets: string[];
|
||||
matched_objects: string[];
|
||||
available_fields: string[];
|
||||
known_limitations: string[];
|
||||
inference_basis: "confirmed_1c_metadata_surface_rows";
|
||||
}
|
||||
|
||||
interface AssistantMcpDiscoveryCoverageAwareQueryResult extends AddressMcpQueryExecutorResult {
|
||||
coverage_limited_by_probe_limit: boolean;
|
||||
coverage_recovered_by_period_chunking: boolean;
|
||||
@@ -124,6 +142,7 @@ interface AssistantMcpDiscoveryCoverageAwareQueryExecution {
|
||||
}
|
||||
|
||||
export type AssistantMcpDiscoveryPilotScope =
|
||||
| "metadata_inspection_v1"
|
||||
| "counterparty_lifecycle_query_documents_v1"
|
||||
| "counterparty_value_flow_query_movements_v1"
|
||||
| "counterparty_supplier_payout_query_movements_v1"
|
||||
@@ -141,6 +160,7 @@ export interface AssistantMcpDiscoveryPilotExecutionContract {
|
||||
probe_results: AssistantMcpDiscoveryProbeResult[];
|
||||
evidence: AssistantMcpDiscoveryEvidenceContract;
|
||||
source_rows_summary: string | null;
|
||||
derived_metadata_surface: AssistantMcpDiscoveryDerivedMetadataSurface | null;
|
||||
derived_activity_period: AssistantMcpDiscoveryDerivedActivityPeriod | null;
|
||||
derived_value_flow: AssistantMcpDiscoveryDerivedValueFlow | null;
|
||||
derived_bidirectional_value_flow: AssistantMcpDiscoveryDerivedBidirectionalValueFlow | null;
|
||||
@@ -150,8 +170,9 @@ export interface AssistantMcpDiscoveryPilotExecutionContract {
|
||||
|
||||
type AddressMcpQueryExecutorResult = Awaited<ReturnType<typeof executeAddressMcpQuery>>;
|
||||
|
||||
const DEFAULT_DEPS: AssistantMcpDiscoveryPilotExecutorDeps = {
|
||||
executeAddressMcpQuery
|
||||
const DEFAULT_DEPS: ResolvedAssistantMcpDiscoveryPilotExecutorDeps = {
|
||||
executeAddressMcpQuery,
|
||||
executeAddressMcpMetadata
|
||||
};
|
||||
|
||||
function toNonEmptyString(value: unknown): string | null {
|
||||
@@ -280,6 +301,60 @@ function isValueFlowPilotEligible(planner: AssistantMcpDiscoveryPlannerContract)
|
||||
);
|
||||
}
|
||||
|
||||
function isMetadataPilotEligible(planner: AssistantMcpDiscoveryPlannerContract): boolean {
|
||||
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: AssistantMcpDiscoveryPlannerContract): string | null {
|
||||
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: AssistantMcpDiscoveryPlannerContract): string[] {
|
||||
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 ["Документ", "РегистрНакопления", "РегистрСведений", "Справочник"];
|
||||
}
|
||||
|
||||
interface ValueFlowPilotProfile {
|
||||
scope: Extract<
|
||||
AssistantMcpDiscoveryPilotScope,
|
||||
@@ -350,6 +425,19 @@ function queryResultToProbeResult(
|
||||
};
|
||||
}
|
||||
|
||||
function metadataResultToProbeResult(
|
||||
primitiveId: string,
|
||||
result: AddressMcpMetadataRowsResult
|
||||
): AssistantMcpDiscoveryProbeResult {
|
||||
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: AddressMcpQueryExecutorResult | null,
|
||||
options: {
|
||||
@@ -428,7 +516,7 @@ async function executeCoverageAwareValueFlowQuery(input: {
|
||||
dateScope: string | null;
|
||||
maxProbeCount: number;
|
||||
maxRowsPerProbe: number;
|
||||
deps: AssistantMcpDiscoveryPilotExecutorDeps;
|
||||
deps: ResolvedAssistantMcpDiscoveryPilotExecutorDeps;
|
||||
}): Promise<AssistantMcpDiscoveryCoverageAwareQueryExecution> {
|
||||
const queryLimitations: string[] = [];
|
||||
const probeResults: AssistantMcpDiscoveryProbeResult[] = [];
|
||||
@@ -560,6 +648,167 @@ function summarizeValueFlowRows(result: AssistantMcpDiscoveryCoverageAwareQueryR
|
||||
return `${result.fetched_rows} MCP value-flow rows fetched, ${result.matched_rows} matched value-flow scope`;
|
||||
}
|
||||
|
||||
function summarizeMetadataRows(result: AddressMcpMetadataRowsResult): string | null {
|
||||
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: Record<string, unknown>, keys: string[]): string | null {
|
||||
for (const key of keys) {
|
||||
const text = toNonEmptyString(row[key]);
|
||||
if (text) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function metadataObjectName(row: Record<string, unknown>): string | null {
|
||||
return metadataRowText(row, [
|
||||
"ПолноеИмя",
|
||||
"full_name",
|
||||
"FullName",
|
||||
"Имя",
|
||||
"name",
|
||||
"Name",
|
||||
"presentation",
|
||||
"Представление",
|
||||
"synonym",
|
||||
"Synonym"
|
||||
]);
|
||||
}
|
||||
|
||||
function metadataEntitySet(row: Record<string, unknown>): string | null {
|
||||
return metadataRowText(row, [
|
||||
"ТипМетаданных",
|
||||
"type",
|
||||
"Type",
|
||||
"meta_type",
|
||||
"MetaType",
|
||||
"ВидМетаданных",
|
||||
"kind"
|
||||
]);
|
||||
}
|
||||
|
||||
function metadataChildNames(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
const result: string[] = [];
|
||||
for (const item of value) {
|
||||
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
||||
continue;
|
||||
}
|
||||
const record = item as Record<string, unknown>;
|
||||
const fieldName = metadataRowText(record, ["Имя", "name", "Name", "full_name", "FullName"]);
|
||||
if (fieldName) {
|
||||
pushUnique(result, fieldName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function metadataAvailableFields(rows: Array<Record<string, unknown>>): string[] {
|
||||
const result: string[] = [];
|
||||
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: AddressMcpMetadataRowsResult | null,
|
||||
metadataScope: string | null,
|
||||
requestedMetaTypes: string[]
|
||||
): AssistantMcpDiscoveryDerivedMetadataSurface | null {
|
||||
if (!result || result.error || result.rows.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
const matchedObjects: string[] = [];
|
||||
const availableEntitySets: string[] = [];
|
||||
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: AssistantMcpDiscoveryDerivedMetadataSurface | null
|
||||
): string[] {
|
||||
if (!surface) {
|
||||
return [];
|
||||
}
|
||||
const facts: string[] = [];
|
||||
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: AssistantMcpDiscoveryDerivedMetadataSurface | null,
|
||||
metadataScope: string | null
|
||||
): string[] {
|
||||
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: Record<string, unknown>): string | null {
|
||||
const candidates = [
|
||||
row["Период"],
|
||||
@@ -1072,16 +1321,31 @@ function buildEmptyEvidence(
|
||||
});
|
||||
}
|
||||
|
||||
function pilotScopeForPlanner(planner: AssistantMcpDiscoveryPlannerContract): AssistantMcpDiscoveryPilotScope {
|
||||
if (isMetadataPilotEligible(planner)) {
|
||||
return "metadata_inspection_v1";
|
||||
}
|
||||
if (isValueFlowPilotEligible(planner)) {
|
||||
return valueFlowPilotProfile(planner).scope;
|
||||
}
|
||||
return "counterparty_lifecycle_query_documents_v1";
|
||||
}
|
||||
|
||||
export async function executeAssistantMcpDiscoveryPilot(
|
||||
planner: AssistantMcpDiscoveryPlannerContract,
|
||||
deps: AssistantMcpDiscoveryPilotExecutorDeps = DEFAULT_DEPS
|
||||
): Promise<AssistantMcpDiscoveryPilotExecutionContract> {
|
||||
const runtimeDeps: ResolvedAssistantMcpDiscoveryPilotExecutorDeps = {
|
||||
...DEFAULT_DEPS,
|
||||
...deps
|
||||
};
|
||||
const dryRun = buildAssistantMcpDiscoveryRuntimeDryRun(planner);
|
||||
const reasonCodes = [...dryRun.reason_codes];
|
||||
const executedPrimitives: string[] = [];
|
||||
const skippedPrimitives: string[] = [];
|
||||
const probeResults: AssistantMcpDiscoveryProbeResult[] = [];
|
||||
const queryLimitations: string[] = [];
|
||||
const pilotScope = pilotScopeForPlanner(planner);
|
||||
|
||||
if (dryRun.adapter_status === "blocked") {
|
||||
pushReason(reasonCodes, "pilot_blocked_before_mcp_execution");
|
||||
@@ -1090,7 +1354,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
schema_version: 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,
|
||||
@@ -1098,6 +1362,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1113,7 +1378,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
schema_version: 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,
|
||||
@@ -1121,6 +1386,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1129,10 +1395,11 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -1143,7 +1410,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
schema_version: 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,
|
||||
@@ -1151,6 +1418,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1163,6 +1431,68 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
const dateScope = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.explicit_date_scope);
|
||||
const aggregationAxis = aggregationAxisForPlanner(planner);
|
||||
|
||||
if (metadataPilotEligible) {
|
||||
let metadataResult: AddressMcpMetadataRowsResult | null = 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 = resolveAssistantMcpDiscoveryEvidence({
|
||||
plan: planner.discovery_plan,
|
||||
probeResults,
|
||||
confirmedFacts: buildMetadataConfirmedFacts(derivedMetadataSurface),
|
||||
unknownFacts: buildMetadataUnknownFacts(derivedMetadataSurface, metadataScope),
|
||||
sourceRowsSummary,
|
||||
queryLimitations,
|
||||
recommendedNextProbe: "inspect_1c_metadata"
|
||||
});
|
||||
|
||||
return {
|
||||
schema_version: 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: AssistantMcpDiscoveryCoverageAwareQueryResult | null = null;
|
||||
const filters = buildValueFlowFilters(planner);
|
||||
@@ -1187,6 +1517,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1213,7 +1544,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1222,7 +1553,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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;
|
||||
@@ -1285,6 +1616,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1310,6 +1642,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1337,7 +1670,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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);
|
||||
@@ -1392,6 +1725,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1418,6 +1752,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
@@ -1433,7 +1768,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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
|
||||
@@ -1476,6 +1811,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
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,
|
||||
|
||||
@@ -148,16 +148,6 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
||||
};
|
||||
}
|
||||
|
||||
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");
|
||||
@@ -180,6 +170,16 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
||||
};
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -306,6 +306,38 @@ function hasMonthlyAggregationSignal(text: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function hasMetadataSignal(text: string): boolean {
|
||||
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: string): string {
|
||||
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: string): boolean {
|
||||
return /(?:\b(?:19|20)\d{2}\b|\b\d{4}-\d{2}-\d{2}\b|\b\d{4}-\d{2}\b)/iu.test(text);
|
||||
}
|
||||
@@ -332,8 +364,12 @@ function semanticNeedFor(input: {
|
||||
unsupported: string | null;
|
||||
lifecycleSignal: boolean;
|
||||
valueFlowSignal: boolean;
|
||||
metadataSignal: boolean;
|
||||
}): string | null {
|
||||
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";
|
||||
}
|
||||
@@ -343,9 +379,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -353,6 +386,7 @@ function shouldRunDiscovery(input: {
|
||||
unsupported: string | null;
|
||||
lifecycleSignal: boolean;
|
||||
valueFlowSignal: boolean;
|
||||
metadataSignal: boolean;
|
||||
semanticDataNeed: string | null;
|
||||
explicitIntentCandidate: string | null;
|
||||
followupDiscoverySeedApplicable: boolean;
|
||||
@@ -360,6 +394,9 @@ function shouldRunDiscovery(input: {
|
||||
if (input.lifecycleSignal || input.unsupported) {
|
||||
return true;
|
||||
}
|
||||
if (input.metadataSignal) {
|
||||
return true;
|
||||
}
|
||||
if (input.valueFlowSignal && !input.explicitIntentCandidate) {
|
||||
return true;
|
||||
}
|
||||
@@ -386,6 +423,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
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);
|
||||
@@ -424,7 +462,8 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
action: rawAction ?? seededAction,
|
||||
unsupported: unsupported ?? seededUnsupported,
|
||||
lifecycleSignal,
|
||||
valueFlowSignal
|
||||
valueFlowSignal,
|
||||
metadataSignal: rawMetadataSignal
|
||||
});
|
||||
const entityCandidates = collectEntityCandidates(assistantTurnMeaning?.explicit_entity_candidates);
|
||||
pushUnique(entityCandidates, predecomposeEntities.counterparty);
|
||||
@@ -445,7 +484,9 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
? "counterparty_lifecycle"
|
||||
: valueFlowSignal
|
||||
? "counterparty_value"
|
||||
: rawDomain ?? seededDomain,
|
||||
: rawMetadataSignal
|
||||
? "metadata"
|
||||
: rawDomain ?? seededDomain,
|
||||
asked_action_family: lifecycleSignal
|
||||
? "activity_duration"
|
||||
: valueFlowSignal
|
||||
@@ -454,7 +495,9 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
: 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,
|
||||
@@ -469,6 +512,8 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
: payoutSignal
|
||||
? "counterparty_payouts_or_outflow"
|
||||
: seededUnsupported ?? "counterparty_value_or_turnover"
|
||||
: rawMetadataSignal
|
||||
? "1c_metadata_surface"
|
||||
: followupDiscoverySeedApplicable
|
||||
? seededUnsupported
|
||||
: null),
|
||||
@@ -477,6 +522,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
unsupported ||
|
||||
lifecycleSignal ||
|
||||
valueFlowSignal ||
|
||||
rawMetadataSignal ||
|
||||
followupDiscoverySeedApplicable
|
||||
)
|
||||
};
|
||||
@@ -511,6 +557,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
unsupported: unsupported ?? seededUnsupported,
|
||||
lifecycleSignal,
|
||||
valueFlowSignal,
|
||||
metadataSignal: rawMetadataSignal,
|
||||
semanticDataNeed,
|
||||
explicitIntentCandidate,
|
||||
followupDiscoverySeedApplicable
|
||||
@@ -526,6 +573,8 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
? "raw_text"
|
||||
: valueFlowSignal
|
||||
? "raw_text"
|
||||
: rawMetadataSignal
|
||||
? "raw_text"
|
||||
: "none";
|
||||
|
||||
if (lifecycleSignal) {
|
||||
@@ -534,6 +583,9 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user