diff --git a/docs/TECH/1CLLMARCH-FACT.md b/docs/TECH/1CLLMARCH-FACT.md index 5d81a75..46f316f 100644 --- a/docs/TECH/1CLLMARCH-FACT.md +++ b/docs/TECH/1CLLMARCH-FACT.md @@ -1374,7 +1374,38 @@ Validation: - `assistantDeepTurnPackagingRuntimeAdapter.test.ts` - `assistantWave10SettlementCorrectiveRegression.test.ts` -Status: **In progress (Phase 2.1 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 2.10 + 2.11 + 2.12 + 2.13 + 2.14 + 2.15 + 2.16 + 2.17 + 2.18 + 2.19 + 2.20 + 2.21 + 2.22 + 2.23 + 2.24 + 2.25 + 2.26 + 2.27 + 2.28 + 2.29 + 2.30 + 2.31 + 2.32 + 2.33 + 2.34 + 2.35 + 2.36 + 2.37 + 2.38 + 2.39 + 2.40 + 2.41 + 2.42 + 2.43 completed)** +Implemented in current pass (Phase 2.44): +1. Extracted deep-response bridge (`deepTurnResponseRuntime` wiring) from `assistantService` into dedicated runtime adapter: + - `assistantDeepTurnResponseAttemptRuntimeAdapter.ts` + - introduced: + - `runAssistantDeepTurnResponseAttemptRuntime(...)` +2. Centralized deep-response handoff logic (behavior-preserving): + - mapping from deep-analysis runtime output into response/packaging/finalization runtime contract moved behind a single runtime boundary; + - preserved existing debug/state persistence hooks and session finalization callbacks. +3. Rewired `assistantService` to consume deep-response attempt runtime adapter. +4. Added focused unit tests: + - `assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts` + +Validation: +1. `npm run build` passed. +2. Targeted living/address/deep followup pack passed: + - `assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts` + - `assistantDeepTurnAnalysisAttemptRuntimeAdapter.test.ts` + - `assistantDeepTurnAnalysisRuntimeAdapter.test.ts` + - `assistantAddressLaneResponseAttemptRuntimeAdapter.test.ts` + - `assistantLivingChatAttemptRuntimeAdapter.test.ts` + - `assistantAddressLaneAttemptRuntimeAdapter.test.ts` + - `assistantUserTurnBootstrapRuntimeAdapter.test.ts` + - `assistantLivingChatLlmRuntimeAdapter.test.ts` + - `assistantLivingChatHandlerRuntimeAdapter.test.ts` + - `assistantLivingChatRuntimeAdapter.test.ts` + - `assistantAddressRuntimeAdapter.test.ts` + - `assistantAddressLaneResponseRuntimeAdapter.test.ts` + - `assistantDeepTurnResponseRuntimeAdapter.test.ts` + - `assistantDeepTurnPackagingRuntimeAdapter.test.ts` + - `assistantWave10SettlementCorrectiveRegression.test.ts` + +Status: **In progress (Phase 2.1 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 2.10 + 2.11 + 2.12 + 2.13 + 2.14 + 2.15 + 2.16 + 2.17 + 2.18 + 2.19 + 2.20 + 2.21 + 2.22 + 2.23 + 2.24 + 2.25 + 2.26 + 2.27 + 2.28 + 2.29 + 2.30 + 2.31 + 2.32 + 2.33 + 2.34 + 2.35 + 2.36 + 2.37 + 2.38 + 2.39 + 2.40 + 2.41 + 2.42 + 2.43 + 2.44 completed)** ## Stage 3 (P2): Hybrid Semantic Layer (LLM + Deterministic Guards) diff --git a/llm_normalizer/backend/dist/services/assistantDeepTurnResponseAttemptRuntimeAdapter.js b/llm_normalizer/backend/dist/services/assistantDeepTurnResponseAttemptRuntimeAdapter.js new file mode 100644 index 0000000..7a17ea4 --- /dev/null +++ b/llm_normalizer/backend/dist/services/assistantDeepTurnResponseAttemptRuntimeAdapter.js @@ -0,0 +1,61 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.runAssistantDeepTurnResponseAttemptRuntime = runAssistantDeepTurnResponseAttemptRuntime; +const assistantDeepTurnResponseRuntimeAdapter_1 = require("./assistantDeepTurnResponseRuntimeAdapter"); +function runAssistantDeepTurnResponseAttemptRuntime(input) { + const runDeepTurnResponseRuntimeSafe = input.runDeepTurnResponseRuntime ?? assistantDeepTurnResponseRuntimeAdapter_1.runAssistantDeepTurnResponseRuntime; + const analysis = input.deepTurnAnalysisRuntime; + const responseRuntime = runDeepTurnResponseRuntimeSafe({ + featureInvestigationStateV1: input.featureInvestigationStateV1, + featureContractsV11: input.featureContractsV11, + featureAnswerPolicyV11: input.featureAnswerPolicyV11, + sessionId: input.sessionId, + questionId: input.questionId, + userMessage: input.userMessage, + normalized: input.normalized, + normalizedQuestion: input.normalizedQuestion, + routeSummary: analysis.resolvedRouteSummary, + executionPlan: analysis.executionPlan, + requirementExtractionRequirements: analysis.requirementExtraction.requirements, + coverageEvaluationRequirements: analysis.coverageEvaluation.requirements, + coverageReport: analysis.coverageEvaluation.coverage, + groundingCheck: analysis.groundingCheck, + retrievalCalls: analysis.retrievalCalls, + retrievalResultsRaw: analysis.retrievalResultsRaw, + retrievalResults: analysis.retrievalResults, + questionTypeClass: analysis.questionTypeClass, + companyAnchors: analysis.companyAnchors, + runtimeAnalysisContext: input.runtimeAnalysisContext, + businessScopeResolution: analysis.businessScopeResolution, + temporalGuard: analysis.temporalGuard, + polarityAudit: analysis.polarityGuardResult.audit, + claimAnchorAudit: analysis.claimAnchorAudit, + targetedEvidenceAudit: analysis.targetedEvidenceResult.audit, + evidenceAdmissibilityGateAudit: analysis.evidenceGateResult.audit, + rbpLiveRouteAudit: analysis.rbpLiveRouteAudit, + faLiveRouteAudit: analysis.faLiveRouteAudit, + groundedAnswerEligibilityGuard: analysis.groundedAnswerEligibilityGuard, + followupStateUsage: input.followupStateUsage, + followupApplied: input.followupApplied, + composition: analysis.composition, + previousInvestigationState: input.previousInvestigationState ?? null, + addressRuntimeMetaForDeep: input.addressRuntimeMetaForDeep, + extractDroppedIntentSegments: input.extractDroppedIntentSegments, + buildDebugRoutes: input.buildDebugRoutes, + extractExecutionState: input.extractExecutionState, + sanitizeReply: input.sanitizeReply, + persistInvestigationState: input.persistInvestigationState, + messageIdFactory: input.messageIdFactory, + appendItem: input.appendItem, + getSession: input.getSession, + persistSession: input.persistSession, + cloneConversation: input.cloneConversation, + logEvent: input.logEvent, + runPackagingRuntime: input.runPackagingRuntime, + runFinalizeDeepTurn: input.runFinalizeDeepTurn + }); + return { + response: responseRuntime.response, + debug: responseRuntime.debug + }; +} diff --git a/llm_normalizer/backend/dist/services/assistantService.js b/llm_normalizer/backend/dist/services/assistantService.js index b77c117..982bb77 100644 --- a/llm_normalizer/backend/dist/services/assistantService.js +++ b/llm_normalizer/backend/dist/services/assistantService.js @@ -65,10 +65,8 @@ const assistantCanon_1 = __importStar(require("./assistantCanon")); const assistantAddressLaneResponseAttemptRuntimeAdapter_1 = __importStar(require("./assistantAddressLaneResponseAttemptRuntimeAdapter")); const assistantCoverageGrounding_1 = __importStar(require("./assistantCoverageGrounding")); const assistantDeepTurnAnalysisAttemptRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnAnalysisAttemptRuntimeAdapter")); -const assistantDeepTurnFinalizeRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnFinalizeRuntimeAdapter")); -const assistantDeepTurnPackagingRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnPackagingRuntimeAdapter")); const assistantDeepTurnNormalizationRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnNormalizationRuntimeAdapter")); -const assistantDeepTurnResponseRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnResponseRuntimeAdapter")); +const assistantDeepTurnResponseAttemptRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnResponseAttemptRuntimeAdapter")); const assistantAddressRuntimeAdapter_1 = __importStar(require("./assistantAddressRuntimeAdapter")); const assistantAddressLaneAttemptRuntimeAdapter_1 = __importStar(require("./assistantAddressLaneAttemptRuntimeAdapter")); const assistantLivingChatAttemptRuntimeAdapter_1 = __importStar(require("./assistantLivingChatAttemptRuntimeAdapter")); @@ -4532,27 +4530,7 @@ class AssistantService { collectFaLiveRouteAudit, hasExplicitPeriodAnchor: (normalizedPayload) => hasExplicitPeriodAnchorFromNormalized(normalizedPayload) }); - const companyAnchors = deepTurnAnalysisRuntime.companyAnchors; - const temporalGuard = deepTurnAnalysisRuntime.temporalGuard; - const claimAnchorAudit = deepTurnAnalysisRuntime.claimAnchorAudit; - const businessScopeResolution = deepTurnAnalysisRuntime.businessScopeResolution; - const resolvedRouteSummary = deepTurnAnalysisRuntime.resolvedRouteSummary; - const requirementExtraction = deepTurnAnalysisRuntime.requirementExtraction; - const executionPlan = deepTurnAnalysisRuntime.executionPlan; - const retrievalCalls = deepTurnAnalysisRuntime.retrievalCalls; - const retrievalResultsRaw = deepTurnAnalysisRuntime.retrievalResultsRaw; - const retrievalResults = deepTurnAnalysisRuntime.retrievalResults; - const polarityGuardResult = deepTurnAnalysisRuntime.polarityGuardResult; - const targetedEvidenceResult = deepTurnAnalysisRuntime.targetedEvidenceResult; - const evidenceGateResult = deepTurnAnalysisRuntime.evidenceGateResult; - const rbpLiveRouteAudit = deepTurnAnalysisRuntime.rbpLiveRouteAudit; - const faLiveRouteAudit = deepTurnAnalysisRuntime.faLiveRouteAudit; - const coverageEvaluation = deepTurnAnalysisRuntime.coverageEvaluation; - const groundedAnswerEligibilityGuard = deepTurnAnalysisRuntime.groundedAnswerEligibilityGuard; - const groundingCheck = deepTurnAnalysisRuntime.groundingCheck; - const questionTypeClass = deepTurnAnalysisRuntime.questionTypeClass; - const composition = deepTurnAnalysisRuntime.composition; - const deepTurnResponseRuntime = (0, assistantDeepTurnResponseRuntimeAdapter_1.runAssistantDeepTurnResponseRuntime)({ + const deepTurnResponseRuntime = (0, assistantDeepTurnResponseAttemptRuntimeAdapter_1.runAssistantDeepTurnResponseAttemptRuntime)({ featureInvestigationStateV1: config_1.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1, featureContractsV11: config_1.FEATURE_ASSISTANT_CONTRACTS_V11, featureAnswerPolicyV11: config_1.FEATURE_ASSISTANT_ANSWER_POLICY_V11, @@ -4566,30 +4544,10 @@ class AssistantService { normalized: normalized.normalized }, normalizedQuestion: followupBinding.normalizedQuestion, - routeSummary: resolvedRouteSummary, - executionPlan, - requirementExtractionRequirements: requirementExtraction.requirements, - coverageEvaluationRequirements: coverageEvaluation.requirements, - coverageReport: coverageEvaluation.coverage, - groundingCheck, - retrievalCalls, - retrievalResultsRaw, - retrievalResults, - questionTypeClass, - companyAnchors, + deepTurnAnalysisRuntime, runtimeAnalysisContext, - businessScopeResolution, - temporalGuard, - polarityAudit: polarityGuardResult.audit, - claimAnchorAudit, - targetedEvidenceAudit: targetedEvidenceResult.audit, - evidenceAdmissibilityGateAudit: evidenceGateResult.audit, - rbpLiveRouteAudit, - faLiveRouteAudit, - groundedAnswerEligibilityGuard, followupStateUsage: followupBinding.usage, followupApplied: Boolean(followupBinding.usage?.applied), - composition, previousInvestigationState: session.investigation_state, addressRuntimeMetaForDeep, extractDroppedIntentSegments: (normalizedPayload) => extractDiscardedIntentSegments(normalizedPayload), @@ -4602,9 +4560,7 @@ class AssistantService { getSession: (targetSessionId) => this.sessions.getSession(targetSessionId), persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState), cloneConversation: (items) => cloneItems(items), - logEvent: (payload) => (0, log_1.logJson)(payload), - runPackagingRuntime: (input) => (0, assistantDeepTurnPackagingRuntimeAdapter_1.runAssistantDeepTurnPackagingRuntime)(input), - runFinalizeDeepTurn: (input) => (0, assistantDeepTurnFinalizeRuntimeAdapter_1.finalizeAssistantDeepTurn)(input) + logEvent: (payload) => (0, log_1.logJson)(payload) }); return deepTurnResponseRuntime.response; } diff --git a/llm_normalizer/backend/src/services/assistantDeepTurnResponseAttemptRuntimeAdapter.ts b/llm_normalizer/backend/src/services/assistantDeepTurnResponseAttemptRuntimeAdapter.ts new file mode 100644 index 0000000..5006a44 --- /dev/null +++ b/llm_normalizer/backend/src/services/assistantDeepTurnResponseAttemptRuntimeAdapter.ts @@ -0,0 +1,116 @@ +import type { AssistantMessageResponsePayload } from "../types/assistant"; +import type { NormalizeResponsePayload } from "../types/normalizer"; +import type { InvestigationStateWithProblemUnits } from "../types/stage2ProblemUnits"; +import type { RunAssistantDeepTurnAnalysisRuntimeOutput } from "./assistantDeepTurnAnalysisRuntimeAdapter"; +import { + runAssistantDeepTurnResponseRuntime, + type RunAssistantDeepTurnResponseRuntimeInput, + type RunAssistantDeepTurnResponseRuntimeOutput +} from "./assistantDeepTurnResponseRuntimeAdapter"; + +export interface RunAssistantDeepTurnResponseAttemptRuntimeInput< + ResponseType = AssistantMessageResponsePayload +> { + featureInvestigationStateV1: boolean; + featureContractsV11: boolean; + featureAnswerPolicyV11: boolean; + sessionId: string; + questionId: string; + userMessage: string; + normalized: { + trace_id: string; + prompt_version: string; + schema_version: string; + normalized: NormalizeResponsePayload["normalized"]; + }; + normalizedQuestion: string; + deepTurnAnalysisRuntime: RunAssistantDeepTurnAnalysisRuntimeOutput; + runtimeAnalysisContext: unknown; + followupStateUsage: unknown; + followupApplied: boolean; + previousInvestigationState: InvestigationStateWithProblemUnits | null | undefined; + addressRuntimeMetaForDeep: unknown; + extractDroppedIntentSegments: RunAssistantDeepTurnResponseRuntimeInput["extractDroppedIntentSegments"]; + buildDebugRoutes: RunAssistantDeepTurnResponseRuntimeInput["buildDebugRoutes"]; + extractExecutionState: RunAssistantDeepTurnResponseRuntimeInput["extractExecutionState"]; + sanitizeReply: RunAssistantDeepTurnResponseRuntimeInput["sanitizeReply"]; + persistInvestigationState: RunAssistantDeepTurnResponseRuntimeInput["persistInvestigationState"]; + messageIdFactory: RunAssistantDeepTurnResponseRuntimeInput["messageIdFactory"]; + appendItem: RunAssistantDeepTurnResponseRuntimeInput["appendItem"]; + getSession: RunAssistantDeepTurnResponseRuntimeInput["getSession"]; + persistSession: RunAssistantDeepTurnResponseRuntimeInput["persistSession"]; + cloneConversation: RunAssistantDeepTurnResponseRuntimeInput["cloneConversation"]; + logEvent: RunAssistantDeepTurnResponseRuntimeInput["logEvent"]; + runPackagingRuntime?: RunAssistantDeepTurnResponseRuntimeInput["runPackagingRuntime"]; + runFinalizeDeepTurn?: RunAssistantDeepTurnResponseRuntimeInput["runFinalizeDeepTurn"]; + runDeepTurnResponseRuntime?: ( + input: RunAssistantDeepTurnResponseRuntimeInput + ) => RunAssistantDeepTurnResponseRuntimeOutput; +} + +export function runAssistantDeepTurnResponseAttemptRuntime< + ResponseType = AssistantMessageResponsePayload +>( + input: RunAssistantDeepTurnResponseAttemptRuntimeInput +): { + response: ResponseType; + debug: Record; +} { + const runDeepTurnResponseRuntimeSafe = + input.runDeepTurnResponseRuntime ?? runAssistantDeepTurnResponseRuntime; + const analysis = input.deepTurnAnalysisRuntime; + const responseRuntime = runDeepTurnResponseRuntimeSafe({ + featureInvestigationStateV1: input.featureInvestigationStateV1, + featureContractsV11: input.featureContractsV11, + featureAnswerPolicyV11: input.featureAnswerPolicyV11, + sessionId: input.sessionId, + questionId: input.questionId, + userMessage: input.userMessage, + normalized: input.normalized, + normalizedQuestion: input.normalizedQuestion, + routeSummary: analysis.resolvedRouteSummary, + executionPlan: analysis.executionPlan, + requirementExtractionRequirements: analysis.requirementExtraction.requirements, + coverageEvaluationRequirements: analysis.coverageEvaluation.requirements, + coverageReport: analysis.coverageEvaluation.coverage, + groundingCheck: analysis.groundingCheck, + retrievalCalls: analysis.retrievalCalls, + retrievalResultsRaw: analysis.retrievalResultsRaw, + retrievalResults: analysis.retrievalResults, + questionTypeClass: analysis.questionTypeClass, + companyAnchors: analysis.companyAnchors, + runtimeAnalysisContext: input.runtimeAnalysisContext, + businessScopeResolution: analysis.businessScopeResolution, + temporalGuard: analysis.temporalGuard, + polarityAudit: analysis.polarityGuardResult.audit, + claimAnchorAudit: analysis.claimAnchorAudit, + targetedEvidenceAudit: analysis.targetedEvidenceResult.audit, + evidenceAdmissibilityGateAudit: analysis.evidenceGateResult.audit, + rbpLiveRouteAudit: analysis.rbpLiveRouteAudit, + faLiveRouteAudit: analysis.faLiveRouteAudit, + groundedAnswerEligibilityGuard: analysis.groundedAnswerEligibilityGuard, + followupStateUsage: input.followupStateUsage, + followupApplied: input.followupApplied, + composition: analysis.composition as any, + previousInvestigationState: input.previousInvestigationState ?? null, + addressRuntimeMetaForDeep: input.addressRuntimeMetaForDeep, + extractDroppedIntentSegments: input.extractDroppedIntentSegments, + buildDebugRoutes: input.buildDebugRoutes, + extractExecutionState: input.extractExecutionState, + sanitizeReply: input.sanitizeReply, + persistInvestigationState: input.persistInvestigationState, + messageIdFactory: input.messageIdFactory, + appendItem: input.appendItem, + getSession: input.getSession, + persistSession: input.persistSession, + cloneConversation: input.cloneConversation, + logEvent: input.logEvent, + runPackagingRuntime: input.runPackagingRuntime, + runFinalizeDeepTurn: input.runFinalizeDeepTurn + }); + + return { + response: responseRuntime.response as ResponseType, + debug: responseRuntime.debug + }; +} diff --git a/llm_normalizer/backend/src/services/assistantService.ts b/llm_normalizer/backend/src/services/assistantService.ts index 0399b59..27a0487 100644 --- a/llm_normalizer/backend/src/services/assistantService.ts +++ b/llm_normalizer/backend/src/services/assistantService.ts @@ -19,10 +19,8 @@ import * as assistantCanon_1 from "./assistantCanon"; import * as assistantAddressLaneResponseAttemptRuntimeAdapter_1 from "./assistantAddressLaneResponseAttemptRuntimeAdapter"; import * as assistantCoverageGrounding_1 from "./assistantCoverageGrounding"; import * as assistantDeepTurnAnalysisAttemptRuntimeAdapter_1 from "./assistantDeepTurnAnalysisAttemptRuntimeAdapter"; -import * as assistantDeepTurnFinalizeRuntimeAdapter_1 from "./assistantDeepTurnFinalizeRuntimeAdapter"; -import * as assistantDeepTurnPackagingRuntimeAdapter_1 from "./assistantDeepTurnPackagingRuntimeAdapter"; import * as assistantDeepTurnNormalizationRuntimeAdapter_1 from "./assistantDeepTurnNormalizationRuntimeAdapter"; -import * as assistantDeepTurnResponseRuntimeAdapter_1 from "./assistantDeepTurnResponseRuntimeAdapter"; +import * as assistantDeepTurnResponseAttemptRuntimeAdapter_1 from "./assistantDeepTurnResponseAttemptRuntimeAdapter"; import * as assistantAddressRuntimeAdapter_1 from "./assistantAddressRuntimeAdapter"; import * as assistantAddressLaneAttemptRuntimeAdapter_1 from "./assistantAddressLaneAttemptRuntimeAdapter"; import * as assistantLivingChatAttemptRuntimeAdapter_1 from "./assistantLivingChatAttemptRuntimeAdapter"; @@ -4487,27 +4485,7 @@ export class AssistantService { collectFaLiveRouteAudit, hasExplicitPeriodAnchor: (normalizedPayload) => hasExplicitPeriodAnchorFromNormalized(normalizedPayload) }); - const companyAnchors = deepTurnAnalysisRuntime.companyAnchors; - const temporalGuard = deepTurnAnalysisRuntime.temporalGuard; - const claimAnchorAudit = deepTurnAnalysisRuntime.claimAnchorAudit; - const businessScopeResolution = deepTurnAnalysisRuntime.businessScopeResolution; - const resolvedRouteSummary = deepTurnAnalysisRuntime.resolvedRouteSummary; - const requirementExtraction = deepTurnAnalysisRuntime.requirementExtraction; - const executionPlan = deepTurnAnalysisRuntime.executionPlan; - const retrievalCalls = deepTurnAnalysisRuntime.retrievalCalls; - const retrievalResultsRaw = deepTurnAnalysisRuntime.retrievalResultsRaw; - const retrievalResults = deepTurnAnalysisRuntime.retrievalResults; - const polarityGuardResult = deepTurnAnalysisRuntime.polarityGuardResult; - const targetedEvidenceResult = deepTurnAnalysisRuntime.targetedEvidenceResult; - const evidenceGateResult = deepTurnAnalysisRuntime.evidenceGateResult; - const rbpLiveRouteAudit = deepTurnAnalysisRuntime.rbpLiveRouteAudit; - const faLiveRouteAudit = deepTurnAnalysisRuntime.faLiveRouteAudit; - const coverageEvaluation = deepTurnAnalysisRuntime.coverageEvaluation; - const groundedAnswerEligibilityGuard = deepTurnAnalysisRuntime.groundedAnswerEligibilityGuard; - const groundingCheck = deepTurnAnalysisRuntime.groundingCheck; - const questionTypeClass = deepTurnAnalysisRuntime.questionTypeClass; - const composition = deepTurnAnalysisRuntime.composition; - const deepTurnResponseRuntime = (0, assistantDeepTurnResponseRuntimeAdapter_1.runAssistantDeepTurnResponseRuntime)({ + const deepTurnResponseRuntime = (0, assistantDeepTurnResponseAttemptRuntimeAdapter_1.runAssistantDeepTurnResponseAttemptRuntime)({ featureInvestigationStateV1: config_1.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1, featureContractsV11: config_1.FEATURE_ASSISTANT_CONTRACTS_V11, featureAnswerPolicyV11: config_1.FEATURE_ASSISTANT_ANSWER_POLICY_V11, @@ -4521,30 +4499,10 @@ export class AssistantService { normalized: normalized.normalized }, normalizedQuestion: followupBinding.normalizedQuestion, - routeSummary: resolvedRouteSummary, - executionPlan, - requirementExtractionRequirements: requirementExtraction.requirements, - coverageEvaluationRequirements: coverageEvaluation.requirements, - coverageReport: coverageEvaluation.coverage, - groundingCheck, - retrievalCalls, - retrievalResultsRaw, - retrievalResults, - questionTypeClass, - companyAnchors, + deepTurnAnalysisRuntime, runtimeAnalysisContext, - businessScopeResolution, - temporalGuard, - polarityAudit: polarityGuardResult.audit, - claimAnchorAudit, - targetedEvidenceAudit: targetedEvidenceResult.audit, - evidenceAdmissibilityGateAudit: evidenceGateResult.audit, - rbpLiveRouteAudit, - faLiveRouteAudit, - groundedAnswerEligibilityGuard, followupStateUsage: followupBinding.usage, followupApplied: Boolean(followupBinding.usage?.applied), - composition, previousInvestigationState: session.investigation_state, addressRuntimeMetaForDeep, extractDroppedIntentSegments: (normalizedPayload) => extractDiscardedIntentSegments(normalizedPayload), @@ -4557,9 +4515,7 @@ export class AssistantService { getSession: (targetSessionId) => this.sessions.getSession(targetSessionId), persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState), cloneConversation: (items) => cloneItems(items), - logEvent: (payload) => (0, log_1.logJson)(payload), - runPackagingRuntime: (input) => (0, assistantDeepTurnPackagingRuntimeAdapter_1.runAssistantDeepTurnPackagingRuntime)(input), - runFinalizeDeepTurn: (input) => (0, assistantDeepTurnFinalizeRuntimeAdapter_1.finalizeAssistantDeepTurn)(input) + logEvent: (payload) => (0, log_1.logJson)(payload) }); return deepTurnResponseRuntime.response; } diff --git a/llm_normalizer/backend/tests/assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts b/llm_normalizer/backend/tests/assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts new file mode 100644 index 0000000..751b463 --- /dev/null +++ b/llm_normalizer/backend/tests/assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts @@ -0,0 +1,138 @@ +import { describe, expect, it, vi } from "vitest"; +import { runAssistantDeepTurnResponseAttemptRuntime } from "../src/services/assistantDeepTurnResponseAttemptRuntimeAdapter"; + +function buildDeepRuntime() { + return { + companyAnchors: { accounts: ["60.01"] }, + temporalGuard: { primary_period_window: { from: "2020-07-01", to: "2020-07-31" } }, + claimAnchorAudit: { claim_type: "prove_settlement_closure_state" }, + businessScopeResolution: { business_scope_resolved: ["company_specific_accounting"] }, + resolvedRouteSummary: { mode: "deterministic_v2", decisions: [] as any[] }, + requirementExtraction: { + requirements: [{ id: "R1" }], + byFragment: new Map([["F1", ["R1"]]]) + }, + executionPlan: [{ fragment_id: "F1", route: "store_canonical" }], + retrievalCalls: [{ fragment_id: "F1", route: "store_canonical" }], + retrievalResultsRaw: [{ fragment_id: "F1", route: "store_canonical", raw_result: {} }], + retrievalResults: [{ fragment_id: "F1", requirement_ids: ["R1"] }], + polarityGuardResult: { audit: { polarity: "supplier_payable" } }, + targetedEvidenceResult: { audit: { targeted_evidence_hit_rate: 1 } }, + evidenceGateResult: { audit: { admissible_evidence_count: 2 } }, + rbpLiveRouteAudit: { routed: 1 }, + faLiveRouteAudit: { routed: 1 }, + coverageEvaluation: { + requirements: [{ id: "R1" }], + coverage: { requirements_total: 1, requirements_covered: 1 } + }, + groundedAnswerEligibilityGuard: { eligible: true }, + groundingCheck: { status: "grounded", reasons: [] }, + questionTypeClass: "causal_trace", + composition: { reply_type: "factual_with_explanation", assistant_reply: "ok" } + } as any; +} + +function buildInput(overrides: Record = {}) { + return { + featureInvestigationStateV1: true, + featureContractsV11: true, + featureAnswerPolicyV11: true, + sessionId: "asst-1", + questionId: "msg-q1", + userMessage: "почему долг не закрылся", + normalized: { + trace_id: "trace-1", + prompt_version: "normalizer_v2_0_2", + schema_version: "normalized_query_v2_0_2", + normalized: { fragments: [] } + }, + normalizedQuestion: "почему долг не закрылся", + deepTurnAnalysisRuntime: buildDeepRuntime(), + runtimeAnalysisContext: { as_of_date: "2020-07-31" }, + followupStateUsage: { applied: true }, + followupApplied: true, + previousInvestigationState: null, + addressRuntimeMetaForDeep: null, + extractDroppedIntentSegments: () => [], + buildDebugRoutes: () => [], + extractExecutionState: () => [], + sanitizeReply: (value: string) => value, + persistInvestigationState: () => {}, + messageIdFactory: () => "msg-a1", + appendItem: () => {}, + getSession: () => ({ session_id: "asst-1", items: [] }), + persistSession: () => {}, + cloneConversation: () => [], + logEvent: () => {}, + ...overrides + } as any; +} + +describe("assistant deep turn response attempt runtime adapter", () => { + it("maps deep-analysis runtime output into response runtime input", () => { + const runDeepTurnResponseRuntime = vi.fn(() => ({ + response: { + ok: true, + session_id: "asst-1", + conversation: [], + debug: { trace_id: "trace-1" } + }, + debug: { trace_id: "trace-1" } + })); + + const runtime = runAssistantDeepTurnResponseAttemptRuntime( + buildInput({ + runDeepTurnResponseRuntime + }) + ); + + expect(runDeepTurnResponseRuntime).toHaveBeenCalledWith( + expect.objectContaining({ + routeSummary: expect.objectContaining({ mode: "deterministic_v2" }), + requirementExtractionRequirements: [{ id: "R1" }], + coverageEvaluationRequirements: [{ id: "R1" }], + questionTypeClass: "causal_trace", + polarityAudit: { polarity: "supplier_payable" }, + targetedEvidenceAudit: { targeted_evidence_hit_rate: 1 }, + evidenceAdmissibilityGateAudit: { admissible_evidence_count: 2 }, + composition: expect.objectContaining({ reply_type: "factual_with_explanation" }) + }) + ); + expect(runtime.response).toEqual( + expect.objectContaining({ + ok: true + }) + ); + }); + + it("forwards callbacks and state flags", () => { + const extractDroppedIntentSegments = vi.fn(() => []); + const persistInvestigationState = vi.fn(); + const runDeepTurnResponseRuntime = vi.fn(() => ({ + response: { + ok: true, + session_id: "asst-1", + conversation: [], + debug: null + }, + debug: {} + })); + + runAssistantDeepTurnResponseAttemptRuntime( + buildInput({ + followupApplied: false, + extractDroppedIntentSegments, + persistInvestigationState, + runDeepTurnResponseRuntime + }) + ); + + expect(runDeepTurnResponseRuntime).toHaveBeenCalledWith( + expect.objectContaining({ + followupApplied: false, + extractDroppedIntentSegments, + persistInvestigationState + }) + ); + }); +});