import { describe, expect, it, vi } from "vitest"; import { runAssistantAddressRuntime } from "../src/services/assistantAddressRuntimeAdapter"; describe("assistant address runtime adapter", () => { it("returns unhandled when address feature is disabled", async () => { const result = await runAssistantAddressRuntime({ featureAssistantAddressQueryV1: false, sessionId: "asst-1", userMessage: "question", sessionItems: [], llmProvider: "openai", useMock: false, featureAddressLlmPredecomposeV1: true, runAddressLlmPreDecompose: async () => ({}), buildAddressLlmPredecomposeContractV1: () => ({}), sanitizeAddressMessageForFallback: (value) => value, toNonEmptyString: () => null, resolveAddressFollowupCarryoverContext: () => null, resolveAssistantOrchestrationDecision: () => ({}), buildAddressDialogContinuationContractV2: () => ({}), runtimeAnalysisContextAsOfDate: null, payloadContextPeriodHint: null, compactWhitespace: (value) => value.trim(), runAddressLaneAttempt: async () => null, isRetryableAddressLimitedResult: () => false, finalizeAddressLaneResponse: () => ({ ok: true }), tryHandleLivingChat: async () => null, logEvent: () => {}, nowIso: () => "2026-04-10T00:00:00.000Z" }); expect(result).toEqual({ handled: false, response: null, addressRuntimeMetaForDeep: null }); }); it("returns early when tool-gate chat fallback handles", async () => { const runAddressOrchestrationRuntime = vi.fn(async () => ({ addressPreDecompose: {}, addressInputMessage: "canon", carryover: null, orchestrationDecision: { runAddressLane: false }, addressRuntimeMeta: { attempted: true }, livingModeDecision: { mode: "chat", reason: "x" } })); const runAddressToolGateRuntime = vi.fn(async () => ({ handled: true, response: { ok: "chat" } })); const runAddressLaneRuntime = vi.fn(async () => ({ handled: false, selection: null, retryAudit: { attempted: false, reason: null, initial_limited_category: null, retry_message: null, retry_used_followup_context: false, retry_result_category: null } })); const result = await runAssistantAddressRuntime({ featureAssistantAddressQueryV1: true, sessionId: "asst-2", userMessage: "question", sessionItems: [], llmProvider: "openai", useMock: false, featureAddressLlmPredecomposeV1: true, runAddressLlmPreDecompose: async () => ({}), buildAddressLlmPredecomposeContractV1: () => ({}), sanitizeAddressMessageForFallback: (value) => value, toNonEmptyString: () => null, resolveAddressFollowupCarryoverContext: () => null, resolveAssistantOrchestrationDecision: () => ({}), buildAddressDialogContinuationContractV2: () => ({}), runtimeAnalysisContextAsOfDate: null, payloadContextPeriodHint: null, compactWhitespace: (value) => value.trim(), runAddressLaneAttempt: async () => null, isRetryableAddressLimitedResult: () => false, finalizeAddressLaneResponse: () => ({ ok: true }), tryHandleLivingChat: async () => ({ ok: true }), logEvent: () => {}, nowIso: () => "2026-04-10T00:00:00.000Z", runAddressOrchestrationRuntime, runAddressToolGateRuntime, runAddressLaneRuntime }); expect(result.handled).toBe(true); expect(result.response).toEqual({ ok: "chat" }); expect(result.addressRuntimeMetaForDeep).toEqual({ attempted: true }); expect(runAddressLaneRuntime).not.toHaveBeenCalled(); }); it("finalizes address lane when lane runtime resolves handled selection", async () => { const runAddressLaneAttempt = vi.fn(async () => ({ handled: true })); const finalizeAddressLaneResponse = vi.fn(() => ({ ok: "address" })); const runAddressLaneRuntime = vi.fn(async (input) => { await input.runAddressLaneAttempt("canon", null); return { handled: true, selection: { addressLane: { handled: true }, messageUsed: "canon", carryMeta: null }, retryAudit: { attempted: true, reason: "limited_result_retry_with_raw_message", initial_limited_category: "missing_anchor", retry_message: "raw", retry_used_followup_context: false, retry_result_category: null } }; }); const result = await runAssistantAddressRuntime({ featureAssistantAddressQueryV1: true, sessionId: "asst-3", userMessage: "raw question", sessionItems: [], llmProvider: "openai", useMock: false, featureAddressLlmPredecomposeV1: true, runAddressLlmPreDecompose: async () => ({}), buildAddressLlmPredecomposeContractV1: () => ({}), sanitizeAddressMessageForFallback: (value) => value, toNonEmptyString: (value) => (typeof value === "string" && value.trim() ? value.trim() : null), resolveAddressFollowupCarryoverContext: () => ({ followupContext: { intent: "x" } }), resolveAssistantOrchestrationDecision: () => ({}), buildAddressDialogContinuationContractV2: () => ({}), runtimeAnalysisContextAsOfDate: null, payloadContextPeriodHint: "2020-07-31", compactWhitespace: (value) => value.replace(/\s+/g, " ").trim(), runAddressLaneAttempt, isRetryableAddressLimitedResult: () => false, finalizeAddressLaneResponse, tryHandleLivingChat: async () => null, logEvent: () => {}, nowIso: () => "2026-04-10T00:00:00.000Z", runAddressOrchestrationRuntime: async () => ({ addressPreDecompose: {}, addressInputMessage: "canon", carryover: { followupContext: { intent: "x" } }, orchestrationDecision: { runAddressLane: true }, addressRuntimeMeta: { attempted: true }, livingModeDecision: { mode: "deep_analysis", reason: "x" } }), runAddressToolGateRuntime: async () => ({ handled: false, response: null }), runAddressLaneRuntime }); expect(runAddressLaneAttempt).toHaveBeenCalledWith("canon", null, "2020-07-31"); expect(finalizeAddressLaneResponse).toHaveBeenCalledWith( { handled: true }, "canon", null, expect.objectContaining({ attempted: true, addressRetryAudit: expect.objectContaining({ attempted: true }) }) ); expect(result).toEqual({ handled: true, response: { ok: "address" }, addressRuntimeMetaForDeep: { attempted: true } }); }); });