ARCH: добавить supplier payout pilot MCP discovery
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
type AssistantMcpDiscoveryProbeResult
|
||||
} from "./assistantMcpDiscoveryPolicy";
|
||||
import { buildAddressRecipePlan, selectAddressRecipe } from "./addressRecipeCatalog";
|
||||
import type { AddressFilterSet } from "../types/addressQuery";
|
||||
import type { AddressFilterSet, AddressIntent } from "../types/addressQuery";
|
||||
|
||||
export const ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION =
|
||||
"assistant_mcp_discovery_pilot_executor_v1" as const;
|
||||
@@ -41,6 +41,7 @@ export interface AssistantMcpDiscoveryDerivedActivityPeriod {
|
||||
}
|
||||
|
||||
export interface AssistantMcpDiscoveryDerivedValueFlow {
|
||||
value_flow_direction: "incoming_customer_revenue" | "outgoing_supplier_payout";
|
||||
counterparty: string | null;
|
||||
period_scope: string | null;
|
||||
rows_matched: number;
|
||||
@@ -49,12 +50,14 @@ export interface AssistantMcpDiscoveryDerivedValueFlow {
|
||||
total_amount_human_ru: string;
|
||||
first_movement_date: string | null;
|
||||
latest_movement_date: string | null;
|
||||
coverage_limited_by_probe_limit: boolean;
|
||||
inference_basis: "sum_of_confirmed_1c_value_flow_rows";
|
||||
}
|
||||
|
||||
export type AssistantMcpDiscoveryPilotScope =
|
||||
| "counterparty_lifecycle_query_documents_v1"
|
||||
| "counterparty_value_flow_query_movements_v1";
|
||||
| "counterparty_value_flow_query_movements_v1"
|
||||
| "counterparty_supplier_payout_query_movements_v1";
|
||||
|
||||
export interface AssistantMcpDiscoveryPilotExecutionContract {
|
||||
schema_version: typeof ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION;
|
||||
@@ -199,6 +202,39 @@ function isValueFlowPilotEligible(planner: AssistantMcpDiscoveryPlannerContract)
|
||||
);
|
||||
}
|
||||
|
||||
interface ValueFlowPilotProfile {
|
||||
scope: Extract<
|
||||
AssistantMcpDiscoveryPilotScope,
|
||||
"counterparty_value_flow_query_movements_v1" | "counterparty_supplier_payout_query_movements_v1"
|
||||
>;
|
||||
recipe_intent: Extract<AddressIntent, "customer_revenue_and_payments" | "supplier_payouts_profile">;
|
||||
direction: AssistantMcpDiscoveryDerivedValueFlow["value_flow_direction"];
|
||||
}
|
||||
|
||||
function valueFlowPilotProfile(planner: AssistantMcpDiscoveryPlannerContract): ValueFlowPilotProfile {
|
||||
const meaning = planner.discovery_plan.turn_meaning_ref;
|
||||
const action = String(meaning?.asked_action_family ?? "").toLowerCase();
|
||||
const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase();
|
||||
const combined = `${action} ${unsupported}`;
|
||||
if (
|
||||
combined.includes("payout") ||
|
||||
combined.includes("outflow") ||
|
||||
combined.includes("supplier") ||
|
||||
combined.includes("paid")
|
||||
) {
|
||||
return {
|
||||
scope: "counterparty_supplier_payout_query_movements_v1",
|
||||
recipe_intent: "supplier_payouts_profile",
|
||||
direction: "outgoing_supplier_payout"
|
||||
};
|
||||
}
|
||||
return {
|
||||
scope: "counterparty_value_flow_query_movements_v1",
|
||||
recipe_intent: "customer_revenue_and_payments",
|
||||
direction: "incoming_customer_revenue"
|
||||
};
|
||||
}
|
||||
|
||||
function skippedProbeResult(step: AssistantMcpDiscoveryRuntimeStepContract, limitation: string): AssistantMcpDiscoveryProbeResult {
|
||||
return {
|
||||
primitive_id: step.primitive_id,
|
||||
@@ -361,7 +397,9 @@ function formatAmountHumanRu(amount: number): string {
|
||||
function deriveValueFlow(
|
||||
result: AddressMcpQueryExecutorResult | null,
|
||||
counterparty: string | null,
|
||||
periodScope: string | null
|
||||
periodScope: string | null,
|
||||
direction: AssistantMcpDiscoveryDerivedValueFlow["value_flow_direction"],
|
||||
probeLimit: number
|
||||
): AssistantMcpDiscoveryDerivedValueFlow | null {
|
||||
if (!result || result.error || result.matched_rows <= 0) {
|
||||
return null;
|
||||
@@ -383,6 +421,7 @@ function deriveValueFlow(
|
||||
.filter((value): value is string => Boolean(value))
|
||||
.sort();
|
||||
return {
|
||||
value_flow_direction: direction,
|
||||
counterparty,
|
||||
period_scope: periodScope,
|
||||
rows_matched: result.matched_rows,
|
||||
@@ -391,6 +430,7 @@ function deriveValueFlow(
|
||||
total_amount_human_ru: formatAmountHumanRu(totalAmount),
|
||||
first_movement_date: dates[0] ?? null,
|
||||
latest_movement_date: dates[dates.length - 1] ?? null,
|
||||
coverage_limited_by_probe_limit: result.matched_rows >= probeLimit,
|
||||
inference_basis: "sum_of_confirmed_1c_value_flow_rows"
|
||||
};
|
||||
}
|
||||
@@ -406,10 +446,21 @@ function buildLifecycleConfirmedFacts(result: AddressMcpQueryExecutorResult, cou
|
||||
];
|
||||
}
|
||||
|
||||
function buildValueFlowConfirmedFacts(result: AddressMcpQueryExecutorResult, counterparty: string | null): string[] {
|
||||
function buildValueFlowConfirmedFacts(
|
||||
result: AddressMcpQueryExecutorResult,
|
||||
counterparty: string | null,
|
||||
direction: AssistantMcpDiscoveryDerivedValueFlow["value_flow_direction"]
|
||||
): string[] {
|
||||
if (result.error || result.matched_rows <= 0) {
|
||||
return [];
|
||||
}
|
||||
if (direction === "outgoing_supplier_payout") {
|
||||
return [
|
||||
counterparty
|
||||
? `1C supplier-payout rows were found for counterparty ${counterparty}`
|
||||
: "1C supplier-payout rows were found for the requested counterparty scope"
|
||||
];
|
||||
}
|
||||
return [
|
||||
counterparty
|
||||
? `1C value-flow rows were found for counterparty ${counterparty}`
|
||||
@@ -428,6 +479,9 @@ function buildValueFlowInferredFacts(derived: AssistantMcpDiscoveryDerivedValueF
|
||||
if (!derived) {
|
||||
return [];
|
||||
}
|
||||
if (derived.value_flow_direction === "outgoing_supplier_payout") {
|
||||
return ["Counterparty supplier-payout total was calculated from confirmed 1C outgoing payment rows"];
|
||||
}
|
||||
return ["Counterparty value-flow total was calculated from confirmed 1C movement rows"];
|
||||
}
|
||||
|
||||
@@ -435,12 +489,29 @@ function buildLifecycleUnknownFacts(): string[] {
|
||||
return ["Legal registration date is not proven by this MCP discovery pilot"];
|
||||
}
|
||||
|
||||
function buildValueFlowUnknownFacts(periodScope: string | null): string[] {
|
||||
return [
|
||||
function buildValueFlowUnknownFacts(
|
||||
periodScope: string | null,
|
||||
direction: AssistantMcpDiscoveryDerivedValueFlow["value_flow_direction"],
|
||||
derived: AssistantMcpDiscoveryDerivedValueFlow | null
|
||||
): string[] {
|
||||
const unknownFacts: string[] = [];
|
||||
if (derived?.coverage_limited_by_probe_limit) {
|
||||
unknownFacts.push("Complete requested-period coverage is not proven because the MCP discovery probe row limit was reached");
|
||||
}
|
||||
if (direction === "outgoing_supplier_payout") {
|
||||
unknownFacts.push(
|
||||
periodScope
|
||||
? "Full supplier-payout amount outside the checked period is not proven by this MCP discovery pilot"
|
||||
: "Full all-time supplier-payout amount is not proven without an explicit checked period"
|
||||
);
|
||||
return unknownFacts;
|
||||
}
|
||||
unknownFacts.push(
|
||||
periodScope
|
||||
? "Full turnover outside the checked period is not proven by this MCP discovery pilot"
|
||||
: "Full all-time turnover is not proven without an explicit checked period"
|
||||
];
|
||||
);
|
||||
return unknownFacts;
|
||||
}
|
||||
|
||||
function buildEmptyEvidence(
|
||||
@@ -548,7 +619,8 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
if (valueFlowPilotEligible) {
|
||||
let queryResult: AddressMcpQueryExecutorResult | null = null;
|
||||
const filters = buildValueFlowFilters(planner);
|
||||
const selection = selectAddressRecipe("customer_revenue_and_payments", filters);
|
||||
const valueFlowProfile = valueFlowPilotProfile(planner);
|
||||
const selection = selectAddressRecipe(valueFlowProfile.recipe_intent, filters);
|
||||
if (!selection.selected_recipe) {
|
||||
pushReason(reasonCodes, "pilot_value_flow_recipe_not_available");
|
||||
const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Value-flow recipe is not available");
|
||||
@@ -556,7 +628,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
schema_version: ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION,
|
||||
policy_owner: "assistantMcpDiscoveryPilotExecutor",
|
||||
pilot_status: "unsupported",
|
||||
pilot_scope: "counterparty_value_flow_query_movements_v1",
|
||||
pilot_scope: valueFlowProfile.scope,
|
||||
dry_run: dryRun,
|
||||
mcp_execution_performed: false,
|
||||
executed_primitives: executedPrimitives,
|
||||
@@ -570,6 +642,12 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
}
|
||||
pushReason(
|
||||
reasonCodes,
|
||||
valueFlowProfile.direction === "outgoing_supplier_payout"
|
||||
? "pilot_supplier_payout_recipe_selected"
|
||||
: "pilot_customer_revenue_recipe_selected"
|
||||
);
|
||||
|
||||
const recipePlan = buildAddressRecipePlan(selection.selected_recipe, filters);
|
||||
for (const step of dryRun.execution_steps) {
|
||||
@@ -594,16 +672,22 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
}
|
||||
|
||||
const sourceRowsSummary = queryResult ? summarizeValueFlowRows(queryResult) : null;
|
||||
const derivedValueFlow = deriveValueFlow(queryResult, counterparty, dateScope);
|
||||
const derivedValueFlow = deriveValueFlow(
|
||||
queryResult,
|
||||
counterparty,
|
||||
dateScope,
|
||||
valueFlowProfile.direction,
|
||||
planner.discovery_plan.execution_budget.max_rows_per_probe
|
||||
);
|
||||
if (derivedValueFlow) {
|
||||
pushReason(reasonCodes, "pilot_derived_value_flow_from_confirmed_rows");
|
||||
}
|
||||
const evidence = resolveAssistantMcpDiscoveryEvidence({
|
||||
plan: planner.discovery_plan,
|
||||
probeResults,
|
||||
confirmedFacts: queryResult ? buildValueFlowConfirmedFacts(queryResult, counterparty) : [],
|
||||
confirmedFacts: queryResult ? buildValueFlowConfirmedFacts(queryResult, counterparty, valueFlowProfile.direction) : [],
|
||||
inferredFacts: buildValueFlowInferredFacts(derivedValueFlow),
|
||||
unknownFacts: buildValueFlowUnknownFacts(dateScope),
|
||||
unknownFacts: buildValueFlowUnknownFacts(dateScope, valueFlowProfile.direction, derivedValueFlow),
|
||||
sourceRowsSummary,
|
||||
queryLimitations,
|
||||
recommendedNextProbe: "explain_evidence_basis"
|
||||
@@ -613,7 +697,7 @@ export async function executeAssistantMcpDiscoveryPilot(
|
||||
schema_version: ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION,
|
||||
policy_owner: "assistantMcpDiscoveryPilotExecutor",
|
||||
pilot_status: "executed",
|
||||
pilot_scope: "counterparty_value_flow_query_movements_v1",
|
||||
pilot_scope: valueFlowProfile.scope,
|
||||
dry_run: dryRun,
|
||||
mcp_execution_performed: executedPrimitives.length > 0,
|
||||
executed_primitives: executedPrimitives,
|
||||
|
||||
Reference in New Issue
Block a user