import { nanoid } from "nanoid"; import type { AssistantConversationItem, AssistantDebugPayload, AssistantMessageResponsePayload, AssistantReplyType } from "../types/assistant"; import type { CommitAssistantTurnAndLogOutput } from "./assistantTurnCommitRuntimeAdapter"; import { commitAssistantTurnAndLog } from "./assistantTurnCommitRuntimeAdapter"; export interface LivingModeDecisionForFinalize { mode?: string | null; reason?: string | null; } export interface FinalizeAssistantLivingChatTurnInput { sessionId: string; userMessage: string; assistantReply: string; replyType: AssistantReplyType; debug: AssistantDebugPayload | Record; modeDecision?: LivingModeDecisionForFinalize | null; appendItem: Parameters[0]["appendItem"]; getSession: Parameters[0]["getSession"]; persistSession: Parameters[0]["persistSession"]; cloneConversation: Parameters[0]["cloneConversation"]; logEvent: Parameters[0]["logEvent"]; messageIdFactory?: () => string; nowIso?: () => string; commitFn?: typeof commitAssistantTurnAndLog; } export interface FinalizeAssistantLivingChatTurnOutput { assistantItem: AssistantConversationItem; commitResult: CommitAssistantTurnAndLogOutput; response: AssistantMessageResponsePayload; } function toTraceId(debug: AssistantDebugPayload | Record): string | null { const value = (debug as Record | null | undefined)?.trace_id; if (typeof value !== "string") { return null; } const trimmed = value.trim(); return trimmed.length > 0 ? trimmed : null; } export function finalizeAssistantLivingChatTurn( input: FinalizeAssistantLivingChatTurnInput ): FinalizeAssistantLivingChatTurnOutput { const nowIso = input.nowIso ?? (() => new Date().toISOString()); const messageIdFactory = input.messageIdFactory ?? (() => `msg-${nanoid(10)}`); const commitSafe = input.commitFn ?? commitAssistantTurnAndLog; const assistantItem: AssistantConversationItem = { message_id: messageIdFactory(), session_id: input.sessionId, role: "assistant", text: input.assistantReply, reply_type: input.replyType, created_at: nowIso(), trace_id: toTraceId(input.debug), debug: input.debug as AssistantDebugPayload }; const logDetails = { session_id: input.sessionId, message_id: assistantItem.message_id, user_message: input.userMessage, living_router_mode: input.modeDecision?.mode ?? "chat", living_router_reason: input.modeDecision?.reason ?? "living_chat_signal_detected", assistant_reply: assistantItem.text, reply_type: assistantItem.reply_type, trace_id: assistantItem.trace_id }; const commitResult = commitSafe({ sessionId: input.sessionId, assistantItem, eventType: "assistant_message_chat", logDetails, appendItem: input.appendItem, getSession: input.getSession, persistSession: input.persistSession, cloneConversation: input.cloneConversation, logEvent: input.logEvent }); const response: AssistantMessageResponsePayload = { ok: true, session_id: input.sessionId, assistant_reply: assistantItem.text, reply_type: assistantItem.reply_type as AssistantReplyType, conversation_item: assistantItem, debug: input.debug as AssistantDebugPayload, conversation: commitResult.conversation }; return { assistantItem, commitResult, response }; }