{"version":3,"file":"turn-metrics-CtVHHdJj.cjs","names":[],"sources":["../src/turn-metrics.ts"],"sourcesContent":["/** A speech segment boundary, separate from its text. Safe to import in server code. */\nexport const VOICE_TEXT_FLUSH = Object.freeze({ type: 'voice-text-flush' as const });\nexport type VoiceReplyChunk = string | typeof VOICE_TEXT_FLUSH;\n\nexport type VoiceOutcome = 'completed' | 'interrupted' | 'cancelled' | 'failed';\n\nexport interface VoiceTurnIdentity {\n  /** The triggering user message ID, or a generated ID for speech without user input. */\n  turnId: string;\n  /** Unique for each generation, including speculative attempts and retries. */\n  attemptId: string;\n}\n\nexport interface VoiceToolTiming {\n  toolCallId: string;\n  toolName: string;\n  /** Observed at the bridge, relative to generation start. Not server execution time. */\n  startedAtMs: number;\n  durationMs?: number;\n}\n\nexport interface VoiceGenerationMetrics extends VoiceTurnIdentity {\n  version: 1;\n  phase: 'generation';\n  outcome: VoiceOutcome;\n  /** Unix epoch milliseconds, for trace correlation. Durations use a monotonic clock. */\n  startedAt: number;\n  durationMs: number;\n  /** First text sent toward TTS; can include tool-feedback filler. */\n  firstTextMs?: number;\n  tools: VoiceToolTiming[];\n}\n\nexport interface VoiceSpeechMetrics {\n  version: 1;\n  phase: 'speech';\n  turnId: string;\n  attemptId?: string;\n  speechId: string;\n  outcome: VoiceOutcome;\n  measurement: 'server-playout';\n  /** Epoch milliseconds. Absent when LiveKit has no aligned timing. */\n  speechStartedAt?: number;\n  speechEndedAt?: number;\n  /** User speech end to first output audio. Includes filler; not browser receipt. */\n  firstAudioMs?: number;\n  /** User speech end to completed output. Omitted for interrupted/cancelled/failed speech. */\n  completionMs?: number;\n}\n\nexport type VoiceTurnMetrics = VoiceGenerationMetrics | VoiceSpeechMetrics;\nexport type VoiceTurnMetricsHook = (metrics: VoiceTurnMetrics) => void | Promise<void>;\n\nexport interface VoiceSpeechResult extends VoiceSpeechMetrics {\n  /** LiveKit's committed playback transcript, potentially partial or estimated. Not proof of hearing. */\n  playedText?: string;\n  transcriptSource: 'livekit' | 'unavailable';\n}\nexport type VoiceSpeechCompleteHook = (result: VoiceSpeechResult) => void | Promise<void>;\n\n/** Observer failures must never break speech or delay the audio path. */\nexport function notifyVoiceObserver<T>(hook: ((value: T) => void | Promise<void>) | undefined, value: T): void {\n  if (!hook) return;\n  void Promise.resolve()\n    .then(() => hook(value))\n    .catch(error => {\n      console.warn('@mastra/livekit: voice observer threw', error);\n    });\n}\n\nexport const VOICE_TURN_METADATA = 'mastra.voice.turn';\nexport const VOICE_FLUSH_METADATA = 'mastra.voice.flush';\n\n/** Internal per-attempt clock; never mixes durations from different machines. */\nexport function createGenerationMetrics(identity: VoiceTurnIdentity, hook?: VoiceTurnMetricsHook) {\n  const start = performance.now();\n  const startedAt = Date.now();\n  let firstTextMs: number | undefined;\n  let ended = false;\n  const tools: VoiceToolTiming[] = [];\n  return {\n    text() {\n      firstTextMs ??= performance.now() - start;\n    },\n    toolStart(tool: { toolCallId: string; toolName: string }) {\n      tools.push({ ...tool, startedAtMs: performance.now() - start });\n    },\n    toolEnd(id: string) {\n      const tool = tools.find(t => t.toolCallId === id && t.durationMs === undefined);\n      if (tool) tool.durationMs = performance.now() - start - tool.startedAtMs;\n    },\n    end(outcome: VoiceOutcome) {\n      if (ended) return;\n      ended = true;\n      notifyVoiceObserver(hook, {\n        version: 1,\n        phase: 'generation',\n        ...identity,\n        startedAt,\n        durationMs: performance.now() - start,\n        firstTextMs,\n        outcome,\n        tools: tools.map(tool => ({ ...tool })),\n      });\n    },\n  };\n}\n"],"mappings":";;AACA,MAAa,mBAAmB,OAAO,OAAO,EAAE,MAAM,mBAA4B,CAAC;;AA4DnF,SAAgB,oBAAuB,MAAwD,OAAgB;CAC7G,IAAI,CAAC,MAAM;CACX,QAAa,QAAQ,CAAC,CACnB,WAAW,KAAK,KAAK,CAAC,CAAC,CACvB,OAAM,UAAS;EACd,QAAQ,KAAK,yCAAyC,KAAK;CAC7D,CAAC;AACL;AAEA,MAAa,sBAAsB;AACnC,MAAa,uBAAuB;;AAGpC,SAAgB,wBAAwB,UAA6B,MAA6B;CAChG,MAAM,QAAQ,YAAY,IAAI;CAC9B,MAAM,YAAY,KAAK,IAAI;CAC3B,IAAI;CACJ,IAAI,QAAQ;CACZ,MAAM,QAA2B,CAAC;CAClC,OAAO;EACL,OAAO;GACL,gBAAgB,YAAY,IAAI,IAAI;EACtC;EACA,UAAU,MAAgD;GACxD,MAAM,KAAK;IAAE,GAAG;IAAM,aAAa,YAAY,IAAI,IAAI;GAAM,CAAC;EAChE;EACA,QAAQ,IAAY;GAClB,MAAM,OAAO,MAAM,MAAK,MAAK,EAAE,eAAe,MAAM,EAAE,eAAe,KAAA,CAAS;GAC9E,IAAI,MAAM,KAAK,aAAa,YAAY,IAAI,IAAI,QAAQ,KAAK;EAC/D;EACA,IAAI,SAAuB;GACzB,IAAI,OAAO;GACX,QAAQ;GACR,oBAAoB,MAAM;IACxB,SAAS;IACT,OAAO;IACP,GAAG;IACH;IACA,YAAY,YAAY,IAAI,IAAI;IAChC;IACA;IACA,OAAO,MAAM,KAAI,UAAS,EAAE,GAAG,KAAK,EAAE;GACxC,CAAC;EACH;CACF;AACF"}