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.
65 lines
2.0 KiB
TypeScript
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,
|
|
);
|
|
}
|