ARCH: стабилизировать continuity и защитить exact-ответы от discovery
This commit is contained in:
@@ -13,6 +13,7 @@ export type AssistantMcpDiscoveryResponsePolicyDecision = "apply_candidate" | "k
|
||||
export interface ApplyAssistantMcpDiscoveryResponsePolicyInput {
|
||||
currentReply: string;
|
||||
currentReplySource?: string | null;
|
||||
currentReplyType?: string | null;
|
||||
livingChatSource?: string | null;
|
||||
modeDecisionReason?: string | null;
|
||||
addressRuntimeMeta?: Record<string, unknown> | null;
|
||||
@@ -151,6 +152,69 @@ function isDiscoveryReadyAddressCandidate(
|
||||
);
|
||||
}
|
||||
|
||||
function hasAlignedFactualAddressReply(
|
||||
input: ApplyAssistantMcpDiscoveryResponsePolicyInput,
|
||||
entryPoint: AssistantMcpDiscoveryRuntimeEntryPointContract | null
|
||||
): boolean {
|
||||
if (!isDiscoveryReadyAddressCandidate(input, entryPoint)) {
|
||||
return false;
|
||||
}
|
||||
if (toNonEmptyString(input.currentReplyType) !== "factual") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const detectedIntent = toNonEmptyString(input.addressRuntimeMeta?.detected_intent);
|
||||
const turnInput = toRecordObject(entryPoint?.turn_input);
|
||||
const turnMeaning = toRecordObject(turnInput?.turn_meaning_ref);
|
||||
const askedDomain = toNonEmptyString(turnMeaning?.asked_domain_family);
|
||||
const askedAction = toNonEmptyString(turnMeaning?.asked_action_family);
|
||||
|
||||
if (detectedIntent === "counterparty_activity_lifecycle") {
|
||||
return askedDomain === "counterparty_lifecycle" || askedAction === "activity_duration";
|
||||
}
|
||||
if (detectedIntent === "supplier_payouts_profile") {
|
||||
return askedDomain === "counterparty_value" && askedAction === "payout";
|
||||
}
|
||||
if (detectedIntent === "customer_revenue_and_payments") {
|
||||
return askedDomain === "counterparty_value" && askedAction === "turnover";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasMatchedFactualAddressContinuationTarget(
|
||||
input: ApplyAssistantMcpDiscoveryResponsePolicyInput
|
||||
): boolean {
|
||||
if (toNonEmptyString(input.currentReplyType) !== "factual") {
|
||||
return false;
|
||||
}
|
||||
const detectedIntent = toNonEmptyString(input.addressRuntimeMeta?.detected_intent);
|
||||
const dialogContinuationContract = toRecordObject(input.addressRuntimeMeta?.dialogContinuationContract);
|
||||
const targetIntent = toNonEmptyString(dialogContinuationContract?.target_intent);
|
||||
return Boolean(detectedIntent && targetIntent && detectedIntent === targetIntent);
|
||||
}
|
||||
|
||||
function hasFullConfirmedFactualAddressReply(
|
||||
input: ApplyAssistantMcpDiscoveryResponsePolicyInput,
|
||||
entryPoint: AssistantMcpDiscoveryRuntimeEntryPointContract | null
|
||||
): boolean {
|
||||
if (!isDiscoveryReadyAddressCandidate(input, entryPoint)) {
|
||||
return false;
|
||||
}
|
||||
if (toNonEmptyString(input.currentReplyType) !== "factual") {
|
||||
return false;
|
||||
}
|
||||
const truthGateStatus = toNonEmptyString(input.addressRuntimeMeta?.truth_gate_contract_status);
|
||||
if (truthGateStatus === "full_confirmed") {
|
||||
return true;
|
||||
}
|
||||
const truthAnswerPolicy = toRecordObject(input.addressRuntimeMeta?.assistant_truth_answer_policy_v1);
|
||||
const truthGate = toRecordObject(truthAnswerPolicy?.truth_gate);
|
||||
const sourceTruthGateStatus = toNonEmptyString(truthGate?.source_truth_gate_status);
|
||||
const coverageStatus = toNonEmptyString(truthGate?.coverage_status);
|
||||
const groundingStatus = toNonEmptyString(truthGate?.grounding_status);
|
||||
return sourceTruthGateStatus === "full_confirmed" || (coverageStatus === "full" && groundingStatus === "grounded");
|
||||
}
|
||||
|
||||
export function applyAssistantMcpDiscoveryResponsePolicy(
|
||||
input: ApplyAssistantMcpDiscoveryResponsePolicyInput
|
||||
): AssistantMcpDiscoveryResponsePolicyResult {
|
||||
@@ -164,6 +228,9 @@ export function applyAssistantMcpDiscoveryResponsePolicy(
|
||||
const discoveryReadyChatCandidate = isDiscoveryReadyChatCandidate(input, entryPoint);
|
||||
const discoveryReadyDeepCandidate = isDiscoveryReadyDeepCandidate(input, entryPoint);
|
||||
const discoveryReadyAddressCandidate = isDiscoveryReadyAddressCandidate(input, entryPoint);
|
||||
const alignedFactualAddressReply = hasAlignedFactualAddressReply(input, entryPoint);
|
||||
const matchedFactualAddressContinuationTarget = hasMatchedFactualAddressContinuationTarget(input);
|
||||
const fullConfirmedFactualAddressReply = hasFullConfirmedFactualAddressReply(input, entryPoint);
|
||||
|
||||
if (!entryPoint) {
|
||||
pushReason(reasonCodes, "mcp_discovery_response_policy_no_entry_point");
|
||||
@@ -180,6 +247,15 @@ export function applyAssistantMcpDiscoveryResponsePolicy(
|
||||
if (!discoveryReadyAddressCandidate) {
|
||||
pushReason(reasonCodes, "mcp_discovery_response_policy_not_discovery_ready_address_candidate");
|
||||
}
|
||||
if (alignedFactualAddressReply) {
|
||||
pushReason(reasonCodes, "mcp_discovery_response_policy_keep_aligned_factual_address_reply");
|
||||
}
|
||||
if (matchedFactualAddressContinuationTarget) {
|
||||
pushReason(reasonCodes, "mcp_discovery_response_policy_keep_factual_address_continuation_target");
|
||||
}
|
||||
if (fullConfirmedFactualAddressReply) {
|
||||
pushReason(reasonCodes, "mcp_discovery_response_policy_keep_full_confirmed_factual_address_reply");
|
||||
}
|
||||
if (!ALLOWED_CANDIDATE_STATUSES.has(candidate.candidate_status)) {
|
||||
pushReason(reasonCodes, "mcp_discovery_response_policy_candidate_status_not_allowed");
|
||||
}
|
||||
@@ -196,6 +272,9 @@ export function applyAssistantMcpDiscoveryResponsePolicy(
|
||||
const canApply =
|
||||
Boolean(entryPoint) &&
|
||||
(unsupportedBoundary || discoveryReadyChatCandidate || discoveryReadyDeepCandidate || discoveryReadyAddressCandidate) &&
|
||||
!alignedFactualAddressReply &&
|
||||
!matchedFactualAddressContinuationTarget &&
|
||||
!fullConfirmedFactualAddressReply &&
|
||||
ALLOWED_CANDIDATE_STATUSES.has(candidate.candidate_status) &&
|
||||
candidate.eligible_for_future_hot_runtime &&
|
||||
Boolean(toNonEmptyString(candidate.reply_text)) &&
|
||||
|
||||
@@ -5,7 +5,10 @@ const SUPPORTED_ADDRESS_INTENTS = new Set([
|
||||
"payables_confirmed_as_of_date",
|
||||
"list_documents_by_counterparty",
|
||||
"customer_revenue_and_payments",
|
||||
"inventory_on_hand_as_of_date"
|
||||
"inventory_on_hand_as_of_date",
|
||||
"vat_liability_confirmed_for_tax_period",
|
||||
"vat_payable_confirmed_as_of_date",
|
||||
"vat_payable_forecast"
|
||||
]);
|
||||
|
||||
function fallbackCompactWhitespace(value) {
|
||||
@@ -89,8 +92,23 @@ function detectCounterpartyTurnoverFamily(text) {
|
||||
"\u0434\u043e\u0445\u043e\u0434",
|
||||
"\u0431\u044b\u043b",
|
||||
"\u0431\u044b\u043b\u0430",
|
||||
"\u0432\u0440\u0435\u043c\u044f",
|
||||
"\u0432\u0440\u0435\u043c\u0435\u043d\u0438",
|
||||
"\u0433\u043e\u0434",
|
||||
"\u0433\u043e\u0434\u0430",
|
||||
"\u043f\u0435\u0440\u0438\u043e\u0434",
|
||||
"\u043f\u0435\u0440\u0438\u043e\u0434\u0430",
|
||||
"\u043c\u0435\u0441\u044f\u0446",
|
||||
"\u043c\u0435\u0441\u044f\u0446\u0430",
|
||||
"\u043a\u0432\u0430\u0440\u0442\u0430\u043b",
|
||||
"\u043a\u0432\u0430\u0440\u0442\u0430\u043b\u0430",
|
||||
"turnover",
|
||||
"revenue"
|
||||
"revenue",
|
||||
"time",
|
||||
"year",
|
||||
"period",
|
||||
"month",
|
||||
"quarter"
|
||||
]);
|
||||
const entity = rawEntity && !ignored.has(rawEntity) ? rawEntity : null;
|
||||
return {
|
||||
@@ -146,6 +164,8 @@ export function createAssistantTurnMeaningPolicy(deps = {}) {
|
||||
? "receivables"
|
||||
: explicitIntentCandidate?.startsWith("payables_")
|
||||
? "payables"
|
||||
: explicitIntentCandidate?.startsWith("vat_")
|
||||
? "vat"
|
||||
: explicitIntentCandidate?.startsWith("inventory_")
|
||||
? "inventory"
|
||||
: explicitIntentCandidate?.includes("counterparty")
|
||||
@@ -158,6 +178,12 @@ export function createAssistantTurnMeaningPolicy(deps = {}) {
|
||||
explicitIntentCandidate === "payables_confirmed_as_of_date" ||
|
||||
explicitIntentCandidate === "inventory_on_hand_as_of_date"
|
||||
? "confirmed_snapshot"
|
||||
: explicitIntentCandidate === "vat_liability_confirmed_for_tax_period"
|
||||
? "confirmed_tax_period"
|
||||
: explicitIntentCandidate === "vat_payable_confirmed_as_of_date"
|
||||
? "confirmed_snapshot"
|
||||
: explicitIntentCandidate === "vat_payable_forecast"
|
||||
? "forecast"
|
||||
: explicitIntentCandidate === "list_documents_by_counterparty"
|
||||
? "list_documents"
|
||||
: counterpartyTurnover?.family
|
||||
|
||||
Reference in New Issue
Block a user