Files
Jyotisha/frontend/src/lib/rectification-snapshot-messages.ts
T
jesse-ux 7f28bfecbb fix(rectification): ask tie-break questions before the range card (BUG-685/686/687)
Close leads hold delivery until unused D9/D10 style questions are asked. Tie-break POST merges the new turn into the transcript. Range copy no longer lists declined lines.
2026-09-14 18:23:54 +08:00

65 lines
2.0 KiB
TypeScript

import { parseTurnQuestion, persistedOfferFromTurn, type TurnQuestion } from "./rectification-agentic/v9/turn-question.ts";
export type SnapshotTurnMessage = {
role: "assistant" | "user";
turnId?: string;
text: string;
renderKey: string;
question?: TurnQuestion;
candidateOffer?: { resultId: string };
};
export function mergeTurnQuestions<T extends SnapshotTurnMessage>(
current: T[],
turns: readonly unknown[],
): T[] {
const byId = new Map<string, { question: TurnQuestion | null; offerResultId: string | null }>();
for (const item of turns) {
if (!item || typeof item !== "object") continue;
const turn = item as { id?: unknown; question?: unknown; offer_result_id?: unknown };
if (typeof turn.id !== "string") continue;
byId.set(turn.id, {
question: parseTurnQuestion(turn.question),
offerResultId: typeof turn.offer_result_id === "string" ? turn.offer_result_id : null,
});
}
return current.map((message) => {
if (!message.turnId || !byId.has(message.turnId)) return message;
const next = byId.get(message.turnId);
const question = next?.question ?? undefined;
return {
...message,
question: question ?? undefined,
candidateOffer: persistedOfferFromTurn(
next?.offerResultId,
message.candidateOffer,
true,
),
};
});
}
export function appendUnseenAssistantTurns<T extends SnapshotTurnMessage>(
current: T[],
extras: readonly T[],
): T[] {
const known = new Set(current.flatMap((message) => message.turnId ? [message.turnId] : []));
const incoming = extras.filter((message) => (
message.role === "assistant"
&& message.turnId
&& !known.has(message.turnId)
));
return incoming.length ? [...current, ...incoming] : current;
}
export function applySnapshotTurnsToMessages<T extends SnapshotTurnMessage>(
current: T[],
turns: readonly unknown[],
extrasFromTurns: (turns: readonly unknown[]) => T[],
): T[] {
return mergeTurnQuestions(
appendUnseenAssistantTurns(current, extrasFromTurns(turns)),
turns,
);
}