import type { AssistantMessageRequestPayload } from "../types/assistant"; import type { NormalizeRequestPayload, NormalizeResponsePayload } from "../types/normalizer"; import type { InvestigationStateWithProblemUnits } from "../types/stage2ProblemUnits"; import type { AssistantFollowupUsage } from "./assistantFollowupUsage"; import { toRouteHintSummary } from "./routeHintAdapter"; export interface AssistantDeepTurnFollowupBinding { normalizedQuestion: string; mergedContext: NormalizeRequestPayload["context"] | undefined; usage: AssistantFollowupUsage | null; } export interface BuildAssistantDeepTurnNormalizationRuntimeInput { userMessage: string; payload: AssistantMessageRequestPayload; featureInvestigationStateV1: boolean; featureStateFollowupBindingV1: boolean; sessionInvestigationState: InvestigationStateWithProblemUnits | null | undefined; buildFollowupStateBinding: (input: { userMessage: string; payloadContext: NormalizeRequestPayload["context"] | undefined; investigationState: InvestigationStateWithProblemUnits; }) => AssistantDeepTurnFollowupBinding; normalize: (payload: NormalizeRequestPayload) => Promise; } export interface BuildAssistantDeepTurnNormalizationRuntimeOutput { followupBinding: AssistantDeepTurnFollowupBinding; normalizePayload: NormalizeRequestPayload; normalized: NormalizeResponsePayload; } function resolveDeepTurnNormalizerPromptVersion(promptVersion: NormalizeRequestPayload["promptVersion"]): string { const normalized = String(promptVersion ?? "").trim().toLowerCase(); if ( normalized === "normalizer_v2_0_2" || normalized === "normalizer_v2_0_1" || normalized === "normalizer_v2" || normalized === "normalizer_v1" ) { return String(promptVersion); } return "normalizer_v2_0_2"; } function canSynthesizeRouteSummary(normalized: NormalizeResponsePayload["normalized"]): boolean { if (!normalized || typeof normalized !== "object") { return false; } const source = normalized as unknown as Record; return Array.isArray(source.fragments); } export async function buildAssistantDeepTurnNormalizationRuntime( input: BuildAssistantDeepTurnNormalizationRuntimeInput ): Promise { const investigationState = input.sessionInvestigationState; const canUseFollowupBinding = input.featureInvestigationStateV1 && input.featureStateFollowupBindingV1 && investigationState !== null && investigationState !== undefined; const followupBinding = canUseFollowupBinding ? input.buildFollowupStateBinding({ userMessage: input.userMessage, payloadContext: input.payload.context, investigationState }) : { normalizedQuestion: input.userMessage, mergedContext: input.payload.context, usage: null }; const normalizePayload: NormalizeRequestPayload = { llmProvider: input.payload.llmProvider, apiKey: input.payload.apiKey, model: input.payload.model, baseUrl: input.payload.baseUrl, temperature: input.payload.temperature, maxOutputTokens: input.payload.maxOutputTokens, promptVersion: resolveDeepTurnNormalizerPromptVersion(input.payload.promptVersion), schemaVersion: "v2_0_2", systemPrompt: input.payload.systemPrompt, developerPrompt: input.payload.developerPrompt, domainPrompt: input.payload.domainPrompt, fewShotExamples: input.payload.fewShotExamples, userQuestion: followupBinding.normalizedQuestion, context: followupBinding.mergedContext, useMock: Boolean(input.payload.useMock) }; const normalized = await input.normalize(normalizePayload); const normalizedPayload = normalized.normalized; const synthesizedRouteSummary = normalized.route_hint_summary ?? (normalizedPayload && canSynthesizeRouteSummary(normalizedPayload) ? toRouteHintSummary(normalizedPayload) : null); const normalizedWithRouteSummary: NormalizeResponsePayload = synthesizedRouteSummary === normalized.route_hint_summary ? normalized : { ...normalized, route_hint_summary: synthesizedRouteSummary }; return { followupBinding, normalizePayload, normalized: normalizedWithRouteSummary }; }