Архитектура: вынести 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
@@ -16,11 +16,8 @@ function buildRuntimeInput(overrides: Record<string, unknown> = {}) {
addressRuntimeMeta: null,
traceIdFactory: () => "chat-trace-fixed",
toNonEmptyString: (value: unknown) => {
if (typeof value !== "string") {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
const text = String(value ?? "").trim();
return text.length > 0 ? text : null;
},
mergeKnownOrganizations: (values: unknown[]) =>
Array.from(
@@ -161,7 +158,11 @@ describe("assistant living chat runtime adapter", () => {
expect(output.debug?.living_chat_response_source).toBe("deterministic_smalltalk_with_proactive_scope_offer");
expect(output.debug?.living_chat_proactive_scope_offer_applied).toBe(true);
expect(output.debug?.living_chat_data_scope_probe_org_count).toBe(3);
expect(output.debug?.assistant_known_organizations).toEqual(["ООО Альтернатива Плюс", "ООО Лайсвуд", "РАЙМ"]);
expect(output.debug?.assistant_known_organizations).toEqual([
"ООО Альтернатива Плюс",
"ООО Лайсвуд",
"РАЙМ"
]);
});
it("does not add proactive organization offer after the session already has assistant context", async () => {
@@ -220,6 +221,7 @@ describe("assistant living chat runtime adapter", () => {
expect(output.debug?.living_chat_response_source).toBe("deterministic_memory_recap_contract");
expect(executeLlmChat).not.toHaveBeenCalled();
});
it("uses continuity-backed active organization for organization-fact boundary even when session scope is empty", async () => {
const executeLlmChat = vi.fn(async () => "raw-llm");
const input = buildRuntimeInput({
@@ -255,6 +257,7 @@ describe("assistant living chat runtime adapter", () => {
expect(output.debug?.living_chat_continuity_active_organization).toBe("ООО Альтернатива Плюс");
expect(executeLlmChat).not.toHaveBeenCalled();
});
it("builds deterministic answer inspection reply over grounded selected-object sale trace", async () => {
const executeLlmChat = vi.fn(async () => "raw-llm");
const input = buildRuntimeInput({
@@ -283,9 +286,7 @@ describe("assistant living chat runtime adapter", () => {
const output = await runAssistantLivingChatRuntime(input);
expect(output.handled).toBe(true);
expect(output.chatText).toContain("не контрагент");
expect(output.chatText).toContain("Рабочая станция универсального специалиста");
expect(output.chatText).toContain("Покупатель");
expect(output.debug?.living_chat_response_source).toBe("deterministic_answer_inspection_contract");
expect(executeLlmChat).not.toHaveBeenCalled();
});
@@ -1,6 +1,7 @@
import { describe, expect, it } from "vitest";
import {
buildAddressMemoryRecapReply,
buildSelectedObjectAnswerInspectionReply,
createAssistantMemoryRecapPolicy,
resolveAssistantLivingChatMemoryContext
} from "../src/services/assistantMemoryRecapPolicy";
@@ -241,4 +242,40 @@ describe("assistantMemoryRecapPolicy", () => {
expect(reply).toContain("разобрали, кто поставлял");
expect(reply).toContain("подняли документы закупки");
});
it("resolves grounded answer inspection from shared memory context", () => {
const context = resolveAssistantLivingChatMemoryContext({
modeDecisionReason: "answer_inspection_followup_detected",
sessionItems: [
{
role: "assistant",
debug: {
execution_lane: "address_query",
answer_grounding_check: {
status: "grounded"
},
detected_intent: "inventory_sale_trace_for_item",
extracted_filters: {
item: "Рабочая станция",
organization: "ООО Альтернатива Плюс",
as_of_date: "2016-03-31"
}
}
}
]
});
const reply = buildSelectedObjectAnswerInspectionReply({
addressDebug: context.lastAnswerInspectionAddressDebug,
toNonEmptyString: (value: unknown) => {
const text = String(value ?? "").trim();
return text.length > 0 ? text : null;
}
});
expect(context.contextualAnswerInspectionFollowup).toBe(true);
expect(reply).toContain("не контрагент");
expect(reply).toContain("Рабочая станция");
expect(reply).toContain("Покупатель");
});
});