{"version":3,"file":"historyFormatter-CQRpnE54.cjs","sources":["../../lib/vowel/utils/historyFormatter.ts"],"sourcesContent":["/**\n * @fileoverview History Formatter - Converts conversation transcripts to system prompt format\n * \n * This utility formats conversation history for injection into system prompts,\n * enabling \"informal\" state restoration without server-side protocol changes.\n * \n * @module @vowel.to/client/utils\n * @author vowel.to\n * @license Proprietary\n */\n\nimport type { VoiceSessionState } from \"../managers/StateManager\";\n\n/**\n * Format conversation history for system prompt injection\n * \n * Converts transcript array into a structured text block that can be\n * prepended to system instructions, giving the AI context about\n * previous conversation turns.\n * \n * @param transcripts - Array of conversation transcripts\n * @param options - Formatting options\n * @param options.maxTurns - Maximum number of turns to include (default: all)\n * @param options.includeTimestamps - Include timestamps in output (default: false)\n * @returns Formatted history string for system prompt\n * \n * @example\n * ```ts\n * const history = formatHistoryForPrompt(state.transcripts);\n * const instructions = `${history}\\n\\n${baseInstructions}`;\n * ```\n */\nexport function formatHistoryForPrompt(\n  transcripts: VoiceSessionState['transcripts'],\n  options?: {\n    maxTurns?: number;\n    includeTimestamps?: boolean;\n  }\n): string {\n  if (!transcripts || transcripts.length === 0) {\n    return '';\n  }\n\n  const maxTurns = options?.maxTurns;\n  const includeTimestamps = options?.includeTimestamps ?? false;\n\n  // Take only the last N turns (or all if maxTurns not specified)\n  const recentTranscripts = maxTurns ? transcripts.slice(-maxTurns) : transcripts;\n\n  // Build formatted history\n  const lines: string[] = [\n    '<PREVIOUS_CONVERSATION>',\n    'The following is a summary of the conversation so far. Continue naturally from this context:',\n    '',\n  ];\n\n  for (const transcript of recentTranscripts) {\n    const role = transcript.role === 'user' ? 'User' : 'Assistant';\n    const timestamp = includeTimestamps\n      ? ` (${transcript.timestamp.toLocaleTimeString()})`\n      : '';\n    \n    lines.push(`${role}${timestamp}: ${transcript.text}`);\n  }\n\n  lines.push('</PREVIOUS_CONVERSATION>');\n  lines.push('');\n\n  return lines.join('\\n');\n}\n\n/**\n * Truncate conversation history to fit within token limits\n * \n * Estimates token count and removes oldest turns until within limit.\n * Uses rough heuristic: 1 token ≈ 4 characters.\n * \n * @param transcripts - Array of conversation transcripts\n * @param maxTokens - Maximum tokens to allow (default: 32000)\n * @returns Truncated transcript array\n * \n * @example\n * ```ts\n * const truncated = truncateHistory(state.transcripts, 32000);\n * ```\n */\nexport function truncateHistory(\n  transcripts: VoiceSessionState['transcripts'],\n  maxTokens: number = 32000\n): VoiceSessionState['transcripts'] {\n  if (!transcripts || transcripts.length === 0) {\n    return [];\n  }\n\n  // Estimate tokens (rough: 1 token ≈ 4 characters)\n  const estimateTokens = (text: string): number => {\n    return Math.ceil(text.length / 4);\n  };\n\n  let totalTokens = 0;\n  const result: typeof transcripts = [];\n\n  // Work backwards from most recent\n  for (let i = transcripts.length - 1; i >= 0; i--) {\n    const transcript = transcripts[i];\n    const tokens = estimateTokens(transcript.text);\n\n    if (totalTokens + tokens > maxTokens) {\n      break; // Would exceed limit\n    }\n\n    result.unshift(transcript); // Add to front\n    totalTokens += tokens;\n  }\n\n  console.log(`📊 [HistoryFormatter] Truncated ${transcripts.length} turns to ${result.length} turns (${totalTokens} estimated tokens)`);\n\n  return result;\n}\n\n"],"names":[],"mappings":";;;;AAgCO,SAAS,sBAAA,CACd,aACA,OAAA,EAIQ;AACR,EAAA,IAAI,CAAC,WAAA,IAAe,WAAA,CAAY,MAAA,KAAW,CAAA,EAAG;AAC5C,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,WAAW,OAAA,EAAS,QAAA;AAC1B,EAAA,MAAM,iBAAA,GAAoB,SAAS,iBAAA,IAAqB,KAAA;AAGxD,EAAA,MAAM,oBAAoB,QAAA,GAAW,WAAA,CAAY,KAAA,CAAM,CAAC,QAAQ,CAAA,GAAI,WAAA;AAGpE,EAAA,MAAM,KAAA,GAAkB;AAAA,IACtB,yBAAA;AAAA,IACA,8FAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,KAAA,MAAW,cAAc,iBAAA,EAAmB;AAC1C,IAAA,MAAM,IAAA,GAAO,UAAA,CAAW,IAAA,KAAS,MAAA,GAAS,MAAA,GAAS,WAAA;AACnD,IAAA,MAAM,YAAY,iBAAA,GACd,CAAA,EAAA,EAAK,WAAW,SAAA,CAAU,kBAAA,EAAoB,CAAA,CAAA,CAAA,GAC9C,EAAA;AAEJ,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,IAAI,CAAA,EAAG,SAAS,CAAA,EAAA,EAAK,UAAA,CAAW,IAAI,CAAA,CAAE,CAAA;AAAA,EACtD;AAEA,EAAA,KAAA,CAAM,KAAK,0BAA0B,CAAA;AACrC,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAiBO,SAAS,eAAA,CACd,WAAA,EACA,SAAA,GAAoB,IAAA,EACc;AAClC,EAAA,IAAI,CAAC,WAAA,IAAe,WAAA,CAAY,MAAA,KAAW,CAAA,EAAG;AAC5C,IAAA,OAAO,EAAC;AAAA,EACV;AAGA,EAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,KAAyB;AAC/C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAAA,EAClC,CAAA;AAEA,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,MAAM,SAA6B,EAAC;AAGpC,EAAA,KAAA,IAAS,IAAI,WAAA,CAAY,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAChD,IAAA,MAAM,UAAA,GAAa,YAAY,CAAC,CAAA;AAChC,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,UAAA,CAAW,IAAI,CAAA;AAE7C,IAAA,IAAI,WAAA,GAAc,SAAS,SAAA,EAAW;AACpC,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,QAAQ,UAAU,CAAA;AACzB,IAAA,WAAA,IAAe,MAAA;AAAA,EACjB;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAI,mCAAmC,WAAA,CAAY,MAAM,aAAa,MAAA,CAAO,MAAM,CAAA,QAAA,EAAW,WAAW,CAAA,kBAAA,CAAoB,CAAA;AAErI,EAAA,OAAO,MAAA;AACT;;;;;"}