Files
next-tjwater-agent/tests/sessions/interactionDeliveryReconciliation.test.ts
T

37 lines
2.7 KiB
TypeScript

import { expect, it, mock } from "bun:test";
import type { InteractionRequest } from "../../src/chat/interaction-request-contract.js";
import { reconcileInteractionDelivery } from "../../src/sessions/interaction-delivery-reconciliation.js";
import { InteractionRequestError } from "../../src/sessions/interaction-request-store.js";
const context = { actorKey: "actor", projectKey: "project", sessionId: "session" };
const record = { interaction_id: "question", status: "answered", delivery: { native_message_id: "native", revision: 2, status: "blocked", response_id: "response" } } as InteractionRequest;
it("recovers a lost acknowledgement only from consumed input and completed output without inference", async () => {
const recovered = { ...record, delivery: { ...record.delivery!, revision: 3, status: "delivered" as const } };
const updateDelivery = mock(async () => recovered);
const store = { updateDelivery } as never;
const runtime = { agentMessageState: mock(async () => "delivered" as const), readInteractionResult: mock(async () => "complete result") };
expect(await reconcileInteractionDelivery(context, record, store, runtime)).toEqual(recovered);
expect(updateDelivery).toHaveBeenCalledWith(context, "question", { expected_revision: 2, status: "delivered", response_id: "response" });
});
it("retains waiting, running, incomplete and unavailable native state", async () => {
const updateDelivery = mock(async () => record);
const store = { updateDelivery } as never;
const complete = { agentMessageState: async () => "delivered" as const, readInteractionResult: async () => "result" };
for (const runtime of [
{ ...complete, agentMessageState: async () => "enqueued" as const },
{ ...complete, agentMessageState: async () => "missing" as const },
{ ...complete, readInteractionResult: async () => { throw new Error("partial output"); } },
{ ...complete, agentMessageState: async () => { throw new Error("offline"); } }
]) expect(await reconcileInteractionDelivery(context, record, store, runtime)).toEqual(record);
expect(await reconcileInteractionDelivery(context, record, store, complete, true)).toEqual(record);
expect(updateDelivery).not.toHaveBeenCalled();
});
it("keeps concurrent cancellation instead of overwriting a newer delivery revision", async () => {
const cancelled = { ...record, delivery: { ...record.delivery!, revision: 3, status: "cancelled" as const } };
const store = { updateDelivery: async () => { throw new InteractionRequestError("revision_conflict"); }, get: async () => cancelled } as never;
expect(await reconcileInteractionDelivery(context, record, store, { agentMessageState: async () => "delivered", readInteractionResult: async () => "result" })).toEqual(cancelled);
});