ARCH: довести planner-selected entity chains и ambiguity follow-up

This commit is contained in:
2026-04-22 17:32:24 +03:00
parent bc54cd9628
commit bd58ab490f
19 changed files with 1193 additions and 65 deletions
@@ -974,6 +974,54 @@ function summarizeEntityResolutionRows(result: AddressMcpQueryExecutorResult): s
return `${result.fetched_rows} MCP catalog rows fetched for entity search`;
}
function entityResolutionFollowupStepLimitation(): string {
return "Entity-resolution could not continue because the checked catalog search step did not return a confirmed slice";
}
function buildEntityResolutionResolveProbeResult(input: {
queryResult: AddressMcpQueryExecutorResult;
resolution: AssistantMcpDiscoveryDerivedEntityResolution | null;
}): AssistantMcpDiscoveryProbeResult {
if (!input.resolution) {
return {
primitive_id: "resolve_entity_reference",
status: "ok",
rows_received: input.queryResult.fetched_rows,
rows_matched: 0,
limitation: null
};
}
if (input.resolution.resolution_status === "resolved") {
return {
primitive_id: "resolve_entity_reference",
status: "ok",
rows_received: input.queryResult.fetched_rows,
rows_matched: 1,
limitation: null
};
}
return {
primitive_id: "resolve_entity_reference",
status: "ok",
rows_received: input.queryResult.fetched_rows,
rows_matched: 0,
limitation: null
};
}
function buildEntityResolutionCoverageProbeResult(input: {
resolution: AssistantMcpDiscoveryDerivedEntityResolution | null;
}): AssistantMcpDiscoveryProbeResult {
const resolved = input.resolution?.resolution_status === "resolved";
return {
primitive_id: "probe_coverage",
status: "ok",
rows_received: 1,
rows_matched: resolved ? 1 : 0,
limitation: null
};
}
function metadataRowText(row: Record<string, unknown>, keys: string[]): string | null {
for (const key of keys) {
const text = toNonEmptyString(row[key]);
@@ -2153,31 +2201,88 @@ export async function executeAssistantMcpDiscoveryPilot(
};
}
let derivedEntityResolution: AssistantMcpDiscoveryDerivedEntityResolution | null = null;
for (const step of dryRun.execution_steps) {
if (step.primitive_id !== "search_business_entity") {
skippedPrimitives.push(step.primitive_id);
probeResults.push(skippedProbeResult(step, "pilot_only_executes_search_business_entity"));
if (step.primitive_id === "search_business_entity") {
queryResult = await runtimeDeps.executeAddressMcpQuery({
query: ENTITY_RESOLUTION_COUNTERPARTY_QUERY_TEMPLATE.replaceAll(
"__LIMIT__",
String(ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT)
),
limit: ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT
});
pushUnique(executedPrimitives, step.primitive_id);
probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult));
if (queryResult.error) {
pushUnique(queryLimitations, queryResult.error);
pushReason(reasonCodes, "pilot_search_business_entity_mcp_error");
} else {
pushReason(reasonCodes, "pilot_search_business_entity_mcp_executed");
derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity);
}
continue;
}
queryResult = await runtimeDeps.executeAddressMcpQuery({
query: ENTITY_RESOLUTION_COUNTERPARTY_QUERY_TEMPLATE.replaceAll(
"__LIMIT__",
String(ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT)
),
limit: ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT
});
pushUnique(executedPrimitives, step.primitive_id);
probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult));
if (queryResult.error) {
pushUnique(queryLimitations, queryResult.error);
pushReason(reasonCodes, "pilot_search_business_entity_mcp_error");
} else {
pushReason(reasonCodes, "pilot_search_business_entity_mcp_executed");
if (step.primitive_id === "resolve_entity_reference") {
if (!queryResult || queryResult.error) {
skippedPrimitives.push(step.primitive_id);
probeResults.push(skippedProbeResult(step, entityResolutionFollowupStepLimitation()));
continue;
}
if (!derivedEntityResolution) {
derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity);
}
pushUnique(executedPrimitives, step.primitive_id);
probeResults.push(
buildEntityResolutionResolveProbeResult({
queryResult,
resolution: derivedEntityResolution
})
);
if (derivedEntityResolution?.resolution_status === "resolved") {
pushReason(reasonCodes, "pilot_resolve_entity_reference_from_catalog_rows");
} else if (derivedEntityResolution?.resolution_status === "ambiguous") {
pushReason(reasonCodes, "pilot_resolve_entity_reference_requires_clarification");
} else {
pushReason(reasonCodes, "pilot_resolve_entity_reference_not_confirmed");
}
continue;
}
if (step.primitive_id === "probe_coverage") {
if (!queryResult || queryResult.error) {
skippedPrimitives.push(step.primitive_id);
probeResults.push(skippedProbeResult(step, entityResolutionFollowupStepLimitation()));
continue;
}
if (!derivedEntityResolution) {
derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity);
}
pushUnique(executedPrimitives, step.primitive_id);
probeResults.push(
buildEntityResolutionCoverageProbeResult({
resolution: derivedEntityResolution
})
);
pushReason(reasonCodes, "pilot_probe_coverage_executed_for_entity_resolution");
if (derivedEntityResolution?.resolution_status === "resolved") {
pushReason(reasonCodes, "pilot_entity_resolution_grounding_stable_for_downstream_probe");
} else if (derivedEntityResolution?.resolution_status === "ambiguous") {
pushReason(reasonCodes, "pilot_entity_resolution_coverage_requires_clarification");
} else {
pushReason(reasonCodes, "pilot_entity_resolution_coverage_not_confirmed");
}
continue;
}
skippedPrimitives.push(step.primitive_id);
probeResults.push(skippedProbeResult(step, "pilot_entity_resolution_step_not_implemented"));
}
const sourceRowsSummary = queryResult ? summarizeEntityResolutionRows(queryResult) : null;
const derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity);
if (!derivedEntityResolution && queryResult && !queryResult.error) {
derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity);
}
if (derivedEntityResolution?.resolution_status === "resolved") {
pushReason(reasonCodes, "pilot_derived_entity_resolution_from_catalog_rows");
}
@@ -2195,7 +2300,7 @@ export async function executeAssistantMcpDiscoveryPilot(
unknownFacts: buildEntityResolutionUnknownFacts(derivedEntityResolution, requestedEntity),
sourceRowsSummary,
queryLimitations,
recommendedNextProbe: "resolve_entity_reference"
recommendedNextProbe: null
});
return {