Архитектура: вынести grounded answer-inspection в shared policy и обновить статус turnaround

This commit is contained in:
2026-04-18 23:53:20 +03:00
parent 1d48f01841
commit 0fb5190cbd
10 changed files with 215 additions and 54 deletions
@@ -142,9 +142,10 @@ async function runAssistantLivingChatRuntime(input) {
});
const contextualInventoryHistoryCapabilityFollowup = memoryRecapContext.contextualInventoryHistoryCapabilityFollowup;
const contextualMemoryRecapFollowup = memoryRecapContext.contextualMemoryRecapFollowup;
const contextualAnswerInspectionFollowup = memoryRecapContext.contextualAnswerInspectionFollowup;
const lastGroundedInventoryAddressDebug = memoryRecapContext.lastGroundedInventoryAddressDebug;
const lastMemoryAddressDebug = memoryRecapContext.lastMemoryAddressDebug;
const contextualAnswerInspectionFollowup = String(input.modeDecision?.reason ?? "") === "answer_inspection_followup_detected";
const lastAnswerInspectionAddressDebug = memoryRecapContext.lastAnswerInspectionAddressDebug;
if (capabilityMetaQuery && (destructiveSignal || dangerSignal)) {
chatText = input.buildAssistantSafetyRefusalReply();
livingChatSource = "deterministic_safety_refusal";
@@ -210,8 +211,8 @@ async function runAssistantLivingChatRuntime(input) {
livingChatSource = "deterministic_memory_recap_contract";
}
else if (contextualAnswerInspectionFollowup) {
chatText = buildSelectedObjectAnswerInspectionReply({
addressDebug: continuitySnapshot.lastGroundedItemAddressDebug ?? continuitySnapshot.lastGroundedAddressDebug,
chatText = (0, assistantMemoryRecapPolicy_1.buildSelectedObjectAnswerInspectionReply)({
addressDebug: lastAnswerInspectionAddressDebug,
toNonEmptyString: input.toNonEmptyString
});
livingChatSource = "deterministic_answer_inspection_contract";
@@ -3,6 +3,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildInventoryHistoryCapabilityFollowupReply = buildInventoryHistoryCapabilityFollowupReply;
exports.buildAddressMemoryRecapReply = buildAddressMemoryRecapReply;
exports.buildSelectedObjectAnswerInspectionReply = buildSelectedObjectAnswerInspectionReply;
exports.resolveAssistantLivingChatMemoryContext = resolveAssistantLivingChatMemoryContext;
exports.createAssistantMemoryRecapPolicy = createAssistantMemoryRecapPolicy;
const assistantContinuityPolicy_1 = require("./assistantContinuityPolicy");
@@ -175,9 +176,33 @@ function buildAddressMemoryRecapReply(input) {
}
return "Да, помню предыдущий адресный контур. Могу кратко напомнить, что мы уже подтвердили, или сразу продолжить следующий шаг.";
}
function buildSelectedObjectAnswerInspectionReply(input) {
const contextFacts = (0, assistantContinuityPolicy_1.resolveAddressDebugContextFacts)(input.addressDebug, input.toNonEmptyString);
const itemLabel = contextFacts.item ?? "эта позиция";
const detectedIntent = String(input.addressDebug?.detected_intent ?? "");
if (detectedIntent === "inventory_sale_trace_for_item") {
return [
`Да, если так прозвучало, это ошибка чтения ответа. «${itemLabel}» здесь не контрагент, а сама позиция, по которой мы смотрели продажу.`,
"В предыдущем ответе я показывал документы выбытия по этой позиции. Покупатель в доступных данных отдельно не выделен, поэтому назвать контрагента-покупателя я там не мог.",
"Если хочешь, следующим шагом могу отдельно проверить, можно ли вытащить покупателя по связанным документам реализации."
].join(" ");
}
if (detectedIntent === "inventory_purchase_provenance_for_item" ||
detectedIntent === "inventory_purchase_documents_for_item") {
return [
`Да, если так прозвучало, это ошибка чтения ответа. «${itemLabel}» здесь не контрагент, а сама позиция / номенклатура.`,
"В предыдущем ответе речь шла о закупке этой позиции: я перечислял поставщиков или закупочные документы по ней, а не называл саму позицию контрагентом."
].join(" ");
}
return [
`Да, если так прозвучало, это ошибка чтения ответа. «${itemLabel}» здесь не контрагент, а выбранный объект разбора.`,
"Я сейчас уточняю именно смысл предыдущего grounded-ответа по этой позиции, а не запускаю новый адресный поиск."
].join(" ");
}
function resolveAssistantLivingChatMemoryContext(input) {
const contextualInventoryHistoryCapabilityFollowup = String(input.modeDecisionReason ?? "") === "inventory_history_capability_followup_detected";
const contextualMemoryRecapFollowup = String(input.modeDecisionReason ?? "") === "memory_recap_followup_detected";
const contextualAnswerInspectionFollowup = String(input.modeDecisionReason ?? "") === "answer_inspection_followup_detected";
const continuity = (0, assistantContinuityPolicy_1.resolveAssistantContinuitySnapshot)({
sessionItems: input.sessionItems,
toNonEmptyString
@@ -185,10 +210,14 @@ function resolveAssistantLivingChatMemoryContext(input) {
return {
contextualInventoryHistoryCapabilityFollowup,
contextualMemoryRecapFollowup,
contextualAnswerInspectionFollowup,
lastGroundedInventoryAddressDebug: contextualInventoryHistoryCapabilityFollowup
? continuity.lastGroundedInventoryAddressDebug
: null,
lastMemoryAddressDebug: contextualMemoryRecapFollowup
? continuity.lastGroundedItemAddressDebug ?? continuity.lastGroundedAddressDebug
: null,
lastAnswerInspectionAddressDebug: contextualAnswerInspectionFollowup
? continuity.lastGroundedItemAddressDebug ?? continuity.lastGroundedAddressDebug
: null
};