@absolutejs/voice 0.0.22-beta.534 → 0.0.22-beta.536

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/dist/angular/index.js +347 -347
  2. package/dist/angular/voice-cost-dashboard.service.d.ts +1 -1
  3. package/dist/angular/voice-replay-timeline.service.d.ts +1 -1
  4. package/dist/client/agentSquadStatusWidget.d.ts +3 -3
  5. package/dist/client/browserVoiceSupport.d.ts +1 -1
  6. package/dist/client/callDebugger.d.ts +2 -2
  7. package/dist/client/callDebuggerWidget.d.ts +3 -3
  8. package/dist/client/campaignDialerProof.d.ts +4 -4
  9. package/dist/client/deliveryRuntime.d.ts +4 -4
  10. package/dist/client/deliveryRuntimeWidget.d.ts +3 -3
  11. package/dist/client/htmxAttributes.d.ts +1 -5
  12. package/dist/client/htmxBootstrap.js +82 -82
  13. package/dist/client/htmxDashboardRenderers.d.ts +17 -17
  14. package/dist/client/index.js +2478 -2484
  15. package/dist/client/liveOps.d.ts +2 -2
  16. package/dist/client/liveOpsWidget.d.ts +3 -3
  17. package/dist/client/opsActionCenter.d.ts +3 -3
  18. package/dist/client/opsActionCenterWidget.d.ts +3 -3
  19. package/dist/client/opsActionHistory.d.ts +2 -2
  20. package/dist/client/opsActionHistoryWidget.d.ts +2 -2
  21. package/dist/client/opsStatus.d.ts +2 -2
  22. package/dist/client/opsStatusWidget.d.ts +4 -4
  23. package/dist/client/platformCoverage.d.ts +2 -2
  24. package/dist/client/platformCoverageWidget.d.ts +3 -3
  25. package/dist/client/profileComparison.d.ts +2 -2
  26. package/dist/client/profileComparisonWidget.d.ts +3 -3
  27. package/dist/client/profileSwitchRecommendation.d.ts +2 -2
  28. package/dist/client/profileSwitchRecommendationWidget.d.ts +3 -3
  29. package/dist/client/proofTrends.d.ts +2 -2
  30. package/dist/client/proofTrendsWidget.d.ts +3 -3
  31. package/dist/client/providerCapabilities.d.ts +2 -2
  32. package/dist/client/providerCapabilitiesWidget.d.ts +3 -3
  33. package/dist/client/providerContracts.d.ts +2 -2
  34. package/dist/client/providerContractsWidget.d.ts +3 -3
  35. package/dist/client/providerSimulationControls.d.ts +1 -1
  36. package/dist/client/providerSimulationControlsWidget.d.ts +4 -4
  37. package/dist/client/providerStatus.d.ts +2 -2
  38. package/dist/client/providerStatusWidget.d.ts +3 -3
  39. package/dist/client/readinessFailures.d.ts +2 -2
  40. package/dist/client/readinessFailuresWidget.d.ts +3 -3
  41. package/dist/client/reconnectProfileEvidence.d.ts +2 -2
  42. package/dist/client/reconnectProfileEvidenceWidget.d.ts +3 -3
  43. package/dist/client/routingStatus.d.ts +2 -2
  44. package/dist/client/routingStatusWidget.d.ts +3 -3
  45. package/dist/client/sessionObservability.d.ts +2 -2
  46. package/dist/client/sessionObservabilityWidget.d.ts +3 -3
  47. package/dist/client/sessionSnapshot.d.ts +2 -2
  48. package/dist/client/sessionSnapshotWidget.d.ts +2 -2
  49. package/dist/client/traceTimeline.d.ts +2 -2
  50. package/dist/client/traceTimelineWidget.d.ts +3 -3
  51. package/dist/client/turnLatency.d.ts +4 -4
  52. package/dist/client/turnLatencyWidget.d.ts +3 -3
  53. package/dist/client/turnQuality.d.ts +2 -2
  54. package/dist/client/turnQualityWidget.d.ts +3 -3
  55. package/dist/client/workflowStatus.d.ts +2 -2
  56. package/dist/core/agent.d.ts +1 -1
  57. package/dist/core/agentSquadContract.d.ts +2 -2
  58. package/dist/core/agentState.d.ts +1 -1
  59. package/dist/core/aiScorecard.d.ts +1 -1
  60. package/dist/core/assistant.d.ts +1 -1
  61. package/dist/core/assistantHealth.d.ts +3 -3
  62. package/dist/core/assistantMemory.d.ts +7 -7
  63. package/dist/core/audioConditioning.d.ts +1 -1
  64. package/dist/core/audit.d.ts +6 -6
  65. package/dist/core/auditDeliveryRoutes.d.ts +7 -7
  66. package/dist/core/auditExport.d.ts +10 -10
  67. package/dist/core/auditRoutes.d.ts +5 -5
  68. package/dist/core/auditSinks.d.ts +7 -7
  69. package/dist/core/bargeInRoutes.d.ts +6 -6
  70. package/dist/core/bookingFlow.d.ts +1 -1
  71. package/dist/core/browserCallProfiles.d.ts +3 -3
  72. package/dist/core/browserMediaRoutes.d.ts +5 -5
  73. package/dist/core/callDebugger.d.ts +1 -1
  74. package/dist/core/callDisposition.d.ts +1 -1
  75. package/dist/core/callScorecard.d.ts +1 -1
  76. package/dist/core/campaign.d.ts +5 -5
  77. package/dist/core/campaignControls.d.ts +1 -1
  78. package/dist/core/campaignDialers.d.ts +4 -4
  79. package/dist/core/campaignTemplate.d.ts +1 -1
  80. package/dist/core/competitiveCoverage.d.ts +2 -2
  81. package/dist/core/conversationSimulator.d.ts +1 -1
  82. package/dist/core/correction.d.ts +1 -1
  83. package/dist/core/dataControl.d.ts +5 -5
  84. package/dist/core/deliveryRuntime.d.ts +7 -7
  85. package/dist/core/deliverySinkRoutes.d.ts +7 -7
  86. package/dist/core/demoReadyRoutes.d.ts +1 -1
  87. package/dist/core/dncRegistry.d.ts +1 -1
  88. package/dist/core/dtmfCollector.d.ts +1 -1
  89. package/dist/core/evalRoutes.d.ts +16 -16
  90. package/dist/core/fileStore.d.ts +18 -18
  91. package/dist/core/guardrails.d.ts +2 -2
  92. package/dist/core/handoff.d.ts +4 -4
  93. package/dist/core/handoffHealth.d.ts +4 -4
  94. package/dist/core/htmx.d.ts +1 -1
  95. package/dist/core/incidentBundle.d.ts +1 -1
  96. package/dist/core/incidentTimeline.d.ts +11 -11
  97. package/dist/core/latencySlo.d.ts +1 -1
  98. package/dist/core/liveCoach.d.ts +1 -1
  99. package/dist/core/liveLatency.d.ts +3 -3
  100. package/dist/core/liveOps.d.ts +6 -6
  101. package/dist/core/mediaPipelineRoutes.d.ts +4 -4
  102. package/dist/core/monitor.d.ts +1 -1
  103. package/dist/core/multilingualProof.d.ts +1 -1
  104. package/dist/core/observabilityExport.d.ts +15 -15
  105. package/dist/core/operationalStatus.d.ts +3 -3
  106. package/dist/core/operationsRecord.d.ts +8 -8
  107. package/dist/core/ops.d.ts +58 -58
  108. package/dist/core/opsActionAuditRoutes.d.ts +10 -10
  109. package/dist/core/opsConsoleRoutes.d.ts +3 -3
  110. package/dist/core/opsRecovery.d.ts +4 -4
  111. package/dist/core/opsSinks.d.ts +6 -6
  112. package/dist/core/opsStatusRoutes.d.ts +3 -3
  113. package/dist/core/opsWebhook.d.ts +9 -9
  114. package/dist/core/otelExporter.d.ts +1 -1
  115. package/dist/core/outcomeContract.d.ts +6 -6
  116. package/dist/core/pathway.d.ts +2 -2
  117. package/dist/core/pathwayRuntime.d.ts +2 -2
  118. package/dist/core/phoneAgent.d.ts +2 -2
  119. package/dist/core/phoneAgentProductionSmoke.d.ts +7 -7
  120. package/dist/core/platformCoverage.d.ts +1 -1
  121. package/dist/core/postCallSurvey.d.ts +1 -1
  122. package/dist/core/postgresStore.d.ts +8 -8
  123. package/dist/core/productionReadiness.d.ts +9 -9
  124. package/dist/core/profileSwitchRecommendation.d.ts +9 -9
  125. package/dist/core/proofAssertions.d.ts +1 -1
  126. package/dist/core/proofPack.d.ts +12 -12
  127. package/dist/core/proofRunner.d.ts +2 -2
  128. package/dist/core/proofTrends.d.ts +26 -26
  129. package/dist/core/providerCapabilities.d.ts +5 -5
  130. package/dist/core/providerDecisionTraces.d.ts +4 -4
  131. package/dist/core/providerHealth.d.ts +3 -3
  132. package/dist/core/providerOrchestration.d.ts +4 -4
  133. package/dist/core/providerRouterTraces.d.ts +2 -2
  134. package/dist/core/providerRoutingContract.d.ts +2 -2
  135. package/dist/core/providerSlo.d.ts +5 -5
  136. package/dist/core/providerStackRecommendations.d.ts +8 -8
  137. package/dist/core/qualityRoutes.d.ts +3 -3
  138. package/dist/core/queue.d.ts +26 -26
  139. package/dist/core/realtimeChannel.d.ts +5 -5
  140. package/dist/core/realtimeProviderContracts.d.ts +3 -3
  141. package/dist/core/reconnectContract.d.ts +16 -16
  142. package/dist/core/recordingStore.d.ts +2 -2
  143. package/dist/core/reminderScheduler.d.ts +1 -1
  144. package/dist/core/resilienceRoutes.d.ts +1 -1
  145. package/dist/core/routing.d.ts +1 -1
  146. package/dist/core/sessionObservability.d.ts +2 -2
  147. package/dist/core/sessionReplay.d.ts +12 -12
  148. package/dist/core/sessionSnapshot.d.ts +1 -1
  149. package/dist/core/simulationSuite.d.ts +4 -4
  150. package/dist/core/sloCalibration.d.ts +12 -12
  151. package/dist/core/sqliteStore.d.ts +8 -8
  152. package/dist/core/telephonyMediaRoutes.d.ts +4 -4
  153. package/dist/core/telephonyOutcome.d.ts +2 -2
  154. package/dist/core/toolContract.d.ts +10 -10
  155. package/dist/core/toolRuntime.d.ts +1 -1
  156. package/dist/core/trace.d.ts +18 -18
  157. package/dist/core/traceDeliveryRoutes.d.ts +7 -7
  158. package/dist/core/traceTimeline.d.ts +3 -3
  159. package/dist/core/turnLatency.d.ts +4 -4
  160. package/dist/core/turnQuality.d.ts +5 -5
  161. package/dist/core/types.d.ts +7 -2
  162. package/dist/core/voiceMonitoring.d.ts +11 -11
  163. package/dist/core/webhookVerification.d.ts +4 -4
  164. package/dist/core/whisperChannel.d.ts +4 -4
  165. package/dist/core/workflowContract.d.ts +13 -13
  166. package/dist/core/zeroDataRetention.d.ts +3 -13
  167. package/dist/drizzle/assistantMemory.d.ts +95 -0
  168. package/dist/drizzle/eval.d.ts +61 -0
  169. package/dist/drizzle/handoff.d.ts +62 -0
  170. package/dist/drizzle/incidentBundle.d.ts +61 -0
  171. package/dist/drizzle/index.d.ts +1088 -0
  172. package/dist/drizzle/index.js +3064 -0
  173. package/dist/drizzle/observabilityExport.d.ts +61 -0
  174. package/dist/drizzle/proofTrends.d.ts +126 -0
  175. package/dist/drizzle/runtimeStorage.d.ts +1315 -0
  176. package/dist/drizzle/shared.d.ts +76 -0
  177. package/dist/embed/index.js +72 -72
  178. package/dist/embed/voice-widget.js +2 -2
  179. package/dist/index.js +7034 -7101
  180. package/dist/react/index.js +2148 -2150
  181. package/dist/svelte/createVoiceAgentSquadStatus.d.ts +2 -2
  182. package/dist/svelte/createVoiceCallDebugger.d.ts +1 -1
  183. package/dist/svelte/createVoiceCallPlayer.d.ts +8 -8
  184. package/dist/svelte/createVoiceCampaignDialerProof.d.ts +2 -2
  185. package/dist/svelte/createVoiceCostDashboard.d.ts +4 -4
  186. package/dist/svelte/createVoiceDeliveryRuntime.d.ts +3 -3
  187. package/dist/svelte/createVoiceLiveAgentConsole.d.ts +4 -4
  188. package/dist/svelte/createVoiceLiveOps.d.ts +4 -4
  189. package/dist/svelte/createVoiceOpsActionCenter.d.ts +2 -2
  190. package/dist/svelte/createVoiceOpsStatus.d.ts +2 -2
  191. package/dist/svelte/createVoiceProviderCapabilities.d.ts +1 -1
  192. package/dist/svelte/createVoiceProviderContracts.d.ts +1 -1
  193. package/dist/svelte/createVoiceProviderSimulationControls.d.ts +1 -1
  194. package/dist/svelte/createVoiceProviderStatus.d.ts +1 -1
  195. package/dist/svelte/createVoiceReplayTimeline.d.ts +1 -1
  196. package/dist/svelte/createVoiceRoutingStatus.d.ts +1 -1
  197. package/dist/svelte/createVoiceSessionObservability.d.ts +1 -1
  198. package/dist/svelte/createVoiceSessionSnapshot.d.ts +1 -1
  199. package/dist/svelte/createVoiceTraceTimeline.d.ts +1 -1
  200. package/dist/svelte/createVoiceTurnLatency.d.ts +2 -2
  201. package/dist/svelte/createVoiceTurnQuality.d.ts +1 -1
  202. package/dist/svelte/createVoiceWidget.d.ts +2 -2
  203. package/dist/svelte/createVoiceWorkflowStatus.d.ts +1 -1
  204. package/dist/svelte/index.js +1518 -1522
  205. package/dist/telephony/matrix.d.ts +3 -3
  206. package/dist/telephony/plivo.d.ts +2 -2
  207. package/dist/telephony/security.d.ts +3 -3
  208. package/dist/telephony/telnyx.d.ts +1 -1
  209. package/dist/telephony/twilio.d.ts +2 -2
  210. package/dist/testing/benchmark.d.ts +6 -6
  211. package/dist/testing/corrected.d.ts +4 -4
  212. package/dist/testing/duplex.d.ts +2 -2
  213. package/dist/testing/fixtures.d.ts +1 -1
  214. package/dist/testing/index.js +1382 -1388
  215. package/dist/testing/review.d.ts +4 -4
  216. package/dist/testing/sessionBenchmark.d.ts +10 -10
  217. package/dist/testing/telephony.d.ts +3 -3
  218. package/dist/testing/tts.d.ts +1 -1
  219. package/dist/vue/VoiceCostDashboard.d.ts +2 -2
  220. package/dist/vue/index.js +2110 -2112
  221. package/dist/vue/useVoiceController.d.ts +5 -5
  222. package/dist/vue/useVoiceDeliveryRuntime.d.ts +1 -1
  223. package/dist/vue/useVoiceStream.d.ts +5 -5
  224. package/package.json +28 -6
@@ -84,22 +84,6 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
84
84
  var __require = import.meta.require;
85
85
 
86
86
  // src/client/campaignDialerProof.ts
87
- var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
88
- const fetchImpl = options.fetch ?? globalThis.fetch;
89
- const response = await fetchImpl(path);
90
- if (!response.ok) {
91
- throw new Error(`Voice campaign dialer proof status failed: HTTP ${response.status}`);
92
- }
93
- return await response.json();
94
- };
95
- var runVoiceCampaignDialerProofAction = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
96
- const fetchImpl = options.fetch ?? globalThis.fetch;
97
- const response = await fetchImpl(path, { method: "POST" });
98
- if (!response.ok) {
99
- throw new Error(`Voice campaign dialer proof failed: HTTP ${response.status}`);
100
- }
101
- return await response.json();
102
- };
103
87
  var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
104
88
  const listeners = new Set;
105
89
  let closed = false;
@@ -188,10 +172,10 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
188
172
  }
189
173
  return {
190
174
  close,
191
- getServerSnapshot: () => snapshot,
192
- getSnapshot: () => snapshot,
193
175
  refresh,
194
176
  runProof,
177
+ getServerSnapshot: () => snapshot,
178
+ getSnapshot: () => snapshot,
195
179
  subscribe: (listener) => {
196
180
  listeners.add(listener);
197
181
  return () => {
@@ -200,6 +184,22 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
200
184
  }
201
185
  };
202
186
  };
187
+ var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
188
+ const fetchImpl = options.fetch ?? globalThis.fetch;
189
+ const response = await fetchImpl(path);
190
+ if (!response.ok) {
191
+ throw new Error(`Voice campaign dialer proof status failed: HTTP ${response.status}`);
192
+ }
193
+ return await response.json();
194
+ };
195
+ var runVoiceCampaignDialerProofAction = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
196
+ const fetchImpl = options.fetch ?? globalThis.fetch;
197
+ const response = await fetchImpl(path, { method: "POST" });
198
+ if (!response.ok) {
199
+ throw new Error(`Voice campaign dialer proof failed: HTTP ${response.status}`);
200
+ }
201
+ return await response.json();
202
+ };
203
203
 
204
204
  // src/svelte/createVoiceCampaignDialerProof.ts
205
205
  var createVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => createVoiceCampaignDialerProofStore(path, options);
@@ -357,6 +357,21 @@ var formatVoiceCallPlayerTimestamp = (ms) => {
357
357
  };
358
358
 
359
359
  // src/svelte/createVoiceCallPlayer.ts
360
+ var createVoiceCallPlayer2 = (options = {}) => {
361
+ const player = createVoiceCallPlayer(options);
362
+ return {
363
+ ...player,
364
+ getHTML: () => renderVoiceCallPlayerHTML(player.getState(), {
365
+ title: options.title,
366
+ transcripts: player.transcripts().map((t) => ({
367
+ id: t.id,
368
+ startedAtMs: t.startedAtMs,
369
+ text: t.text
370
+ }))
371
+ }),
372
+ title: options.title
373
+ };
374
+ };
360
375
  var renderVoiceCallPlayerHTML = (state, options = {}) => {
361
376
  const title = options.title ?? "Call replay";
362
377
  const transcripts = options.transcripts ?? [];
@@ -377,21 +392,6 @@ var renderVoiceCallPlayerHTML = (state, options = {}) => {
377
392
  <ol style="display:flex;flex-direction:column;gap:6px;list-style:none;margin:0;max-height:280px;overflow-y:auto;padding:0;">${items}</ol>
378
393
  </section>`;
379
394
  };
380
- var createVoiceCallPlayer2 = (options = {}) => {
381
- const player = createVoiceCallPlayer(options);
382
- return {
383
- ...player,
384
- getHTML: () => renderVoiceCallPlayerHTML(player.getState(), {
385
- title: options.title,
386
- transcripts: player.transcripts().map((t) => ({
387
- id: t.id,
388
- startedAtMs: t.startedAtMs,
389
- text: t.text
390
- }))
391
- }),
392
- title: options.title
393
- };
394
- };
395
395
  // src/client/htmx.ts
396
396
  var DEFAULT_EVENT_NAME = "voice-refresh";
397
397
  var DEFAULT_QUERY_PARAM = "sessionId";
@@ -705,14 +705,14 @@ var createVoiceBrowserMediaReporter = (options) => {
705
705
  return {
706
706
  close: stop,
707
707
  reportOnce,
708
+ stop,
708
709
  start: () => {
709
710
  if (interval) {
710
711
  return;
711
712
  }
712
713
  run();
713
714
  interval = setInterval(run, options.intervalMs ?? DEFAULT_BROWSER_MEDIA_INTERVAL_MS);
714
- },
715
- stop
715
+ }
716
716
  };
717
717
  };
718
718
 
@@ -730,14 +730,14 @@ var NOOP_CONNECTION = {
730
730
  callControl: noop,
731
731
  close: noop,
732
732
  endTurn: noop,
733
- getReadyState: () => WS_CLOSED,
734
- getScenarioId: () => "",
735
- getSessionId: () => "",
736
733
  send: noop,
737
734
  sendAudio: noop,
738
735
  simulateDisconnect: noop,
739
- start: () => {},
740
- subscribe: noopUnsubscribe
736
+ subscribe: noopUnsubscribe,
737
+ getReadyState: () => WS_CLOSED,
738
+ getScenarioId: () => "",
739
+ getSessionId: () => "",
740
+ start: () => {}
741
741
  };
742
742
  var createSessionId = () => crypto.randomUUID();
743
743
  var buildWsUrl = (path, sessionId, scenarioId) => {
@@ -934,9 +934,9 @@ var createVoiceConnection = (path, options = {}) => {
934
934
  state.scenarioId = input.scenarioId;
935
935
  }
936
936
  send({
937
- type: "start",
937
+ scenarioId: state.scenarioId ?? undefined,
938
938
  sessionId: state.sessionId,
939
- scenarioId: state.scenarioId ?? undefined
939
+ type: "start"
940
940
  });
941
941
  };
942
942
  const sendAudio = (audio) => {
@@ -976,14 +976,14 @@ var createVoiceConnection = (path, options = {}) => {
976
976
  callControl,
977
977
  close,
978
978
  endTurn,
979
- getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
980
- getScenarioId: () => state.scenarioId ?? "",
981
- getSessionId: () => state.sessionId,
982
979
  send,
983
980
  sendAudio,
984
981
  simulateDisconnect,
985
982
  start,
986
- subscribe
983
+ subscribe,
984
+ getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
985
+ getScenarioId: () => state.scenarioId ?? "",
986
+ getSessionId: () => state.sessionId
987
987
  };
988
988
  };
989
989
 
@@ -999,11 +999,11 @@ var createInitialState = () => ({
999
999
  call: null,
1000
1000
  error: null,
1001
1001
  isConnected: false,
1002
- sessionMetadata: null,
1003
- scenarioId: null,
1004
1002
  partial: "",
1005
1003
  reconnect: createInitialReconnectState(),
1004
+ scenarioId: null,
1006
1005
  sessionId: null,
1006
+ sessionMetadata: null,
1007
1007
  status: "idle",
1008
1008
  turns: []
1009
1009
  });
@@ -1206,6 +1206,16 @@ var createVoiceStream = (path, options = {}) => {
1206
1206
  }
1207
1207
  });
1208
1208
  return {
1209
+ start,
1210
+ get assistantAudio() {
1211
+ return store.getSnapshot().assistantAudio;
1212
+ },
1213
+ get assistantTexts() {
1214
+ return store.getSnapshot().assistantTexts;
1215
+ },
1216
+ get call() {
1217
+ return store.getSnapshot().call;
1218
+ },
1209
1219
  callControl(message) {
1210
1220
  connection.callControl(message);
1211
1221
  },
@@ -1231,48 +1241,38 @@ var createVoiceStream = (path, options = {}) => {
1231
1241
  get isConnected() {
1232
1242
  return store.getSnapshot().isConnected;
1233
1243
  },
1234
- get scenarioId() {
1235
- return store.getSnapshot().scenarioId;
1236
- },
1237
- get sessionMetadata() {
1238
- return store.getSnapshot().sessionMetadata;
1239
- },
1240
- start,
1241
1244
  get partial() {
1242
1245
  return store.getSnapshot().partial;
1243
1246
  },
1244
1247
  get reconnect() {
1245
1248
  return store.getSnapshot().reconnect;
1246
1249
  },
1247
- get sessionId() {
1248
- return connection.getSessionId();
1249
- },
1250
- get status() {
1251
- return store.getSnapshot().status;
1252
- },
1253
- get turns() {
1254
- return store.getSnapshot().turns;
1255
- },
1256
- get assistantTexts() {
1257
- return store.getSnapshot().assistantTexts;
1258
- },
1259
- get assistantAudio() {
1260
- return store.getSnapshot().assistantAudio;
1261
- },
1262
- get call() {
1263
- return store.getSnapshot().call;
1250
+ get scenarioId() {
1251
+ return store.getSnapshot().scenarioId;
1264
1252
  },
1265
1253
  sendAudio(audio) {
1266
1254
  connection.sendAudio(audio);
1267
1255
  },
1256
+ get sessionId() {
1257
+ return connection.getSessionId();
1258
+ },
1259
+ get sessionMetadata() {
1260
+ return store.getSnapshot().sessionMetadata;
1261
+ },
1268
1262
  simulateDisconnect() {
1269
1263
  connection.simulateDisconnect();
1270
1264
  },
1265
+ get status() {
1266
+ return store.getSnapshot().status;
1267
+ },
1271
1268
  subscribe(subscriber) {
1272
1269
  subscribers.add(subscriber);
1273
1270
  return () => {
1274
1271
  subscribers.delete(subscriber);
1275
1272
  };
1273
+ },
1274
+ get turns() {
1275
+ return store.getSnapshot().turns;
1276
1276
  }
1277
1277
  };
1278
1278
  };
@@ -1299,18 +1299,6 @@ var computeRms = (samples) => {
1299
1299
  }
1300
1300
  return Math.sqrt(sumSquares / samples.length);
1301
1301
  };
1302
- var resolveAudioConditioningConfig = (config) => {
1303
- if (!config || config.enabled === false) {
1304
- return;
1305
- }
1306
- return {
1307
- enabled: true,
1308
- maxGain: config.maxGain ?? DEFAULT_MAX_GAIN,
1309
- noiseGateAttenuation: config.noiseGateAttenuation ?? DEFAULT_NOISE_GATE_ATTENUATION,
1310
- noiseGateThreshold: config.noiseGateThreshold ?? DEFAULT_NOISE_GATE_THRESHOLD,
1311
- targetLevel: config.targetLevel ?? DEFAULT_TARGET_LEVEL
1312
- };
1313
- };
1314
1302
  var conditionAudioChunk = (audio, config) => {
1315
1303
  if (!config) {
1316
1304
  return audio;
@@ -1331,6 +1319,18 @@ var conditionAudioChunk = (audio, config) => {
1331
1319
  }
1332
1320
  return new Uint8Array(output.buffer);
1333
1321
  };
1322
+ var resolveAudioConditioningConfig = (config) => {
1323
+ if (!config || config.enabled === false) {
1324
+ return;
1325
+ }
1326
+ return {
1327
+ enabled: true,
1328
+ maxGain: config.maxGain ?? DEFAULT_MAX_GAIN,
1329
+ noiseGateAttenuation: config.noiseGateAttenuation ?? DEFAULT_NOISE_GATE_ATTENUATION,
1330
+ noiseGateThreshold: config.noiseGateThreshold ?? DEFAULT_NOISE_GATE_THRESHOLD,
1331
+ targetLevel: config.targetLevel ?? DEFAULT_TARGET_LEVEL
1332
+ };
1333
+ };
1334
1334
 
1335
1335
  // src/core/turnProfiles.ts
1336
1336
  var TURN_PROFILE_DEFAULTS = {
@@ -1354,12 +1354,12 @@ var TURN_PROFILE_DEFAULTS = {
1354
1354
  }
1355
1355
  };
1356
1356
  var QUALITY_PROFILE_DEFAULTS = {
1357
- general: {},
1358
1357
  "accent-heavy": {
1359
1358
  silenceMs: 1200,
1360
1359
  speechThreshold: 0.01,
1361
1360
  transcriptStabilityMs: 1200
1362
1361
  },
1362
+ general: {},
1363
1363
  "noisy-room": {
1364
1364
  silenceMs: 2000,
1365
1365
  speechThreshold: 0.02,
@@ -1408,8 +1408,8 @@ var PRESET_INPUTS = {
1408
1408
  },
1409
1409
  sttLifecycle: "continuous",
1410
1410
  turnDetection: {
1411
- qualityProfile: "short-command",
1412
- profile: "balanced"
1411
+ profile: "balanced",
1412
+ qualityProfile: "short-command"
1413
1413
  }
1414
1414
  },
1415
1415
  default: {
@@ -1424,8 +1424,8 @@ var PRESET_INPUTS = {
1424
1424
  },
1425
1425
  sttLifecycle: "continuous",
1426
1426
  turnDetection: {
1427
- qualityProfile: "general",
1428
- profile: "fast"
1427
+ profile: "fast",
1428
+ qualityProfile: "general"
1429
1429
  }
1430
1430
  },
1431
1431
  dictation: {
@@ -1447,8 +1447,8 @@ var PRESET_INPUTS = {
1447
1447
  },
1448
1448
  sttLifecycle: "continuous",
1449
1449
  turnDetection: {
1450
- qualityProfile: "accent-heavy",
1451
- profile: "long-form"
1450
+ profile: "long-form",
1451
+ qualityProfile: "accent-heavy"
1452
1452
  }
1453
1453
  },
1454
1454
  "guided-intake": {
@@ -1470,8 +1470,8 @@ var PRESET_INPUTS = {
1470
1470
  },
1471
1471
  sttLifecycle: "turn-scoped",
1472
1472
  turnDetection: {
1473
- qualityProfile: "accent-heavy",
1474
- profile: "long-form"
1473
+ profile: "long-form",
1474
+ qualityProfile: "accent-heavy"
1475
1475
  }
1476
1476
  },
1477
1477
  "noisy-room": {
@@ -1493,8 +1493,8 @@ var PRESET_INPUTS = {
1493
1493
  },
1494
1494
  sttLifecycle: "continuous",
1495
1495
  turnDetection: {
1496
- qualityProfile: "noisy-room",
1497
1496
  profile: "long-form",
1497
+ qualityProfile: "noisy-room",
1498
1498
  silenceMs: 2100,
1499
1499
  speechThreshold: 0.02,
1500
1500
  transcriptStabilityMs: 1650
@@ -1519,8 +1519,8 @@ var PRESET_INPUTS = {
1519
1519
  },
1520
1520
  sttLifecycle: "continuous",
1521
1521
  turnDetection: {
1522
- qualityProfile: "noisy-room",
1523
1522
  profile: "long-form",
1523
+ qualityProfile: "noisy-room",
1524
1524
  silenceMs: 660,
1525
1525
  speechThreshold: 0.012,
1526
1526
  transcriptStabilityMs: 300
@@ -1545,8 +1545,8 @@ var PRESET_INPUTS = {
1545
1545
  },
1546
1546
  sttLifecycle: "continuous",
1547
1547
  turnDetection: {
1548
- qualityProfile: "noisy-room",
1549
1548
  profile: "long-form",
1549
+ qualityProfile: "noisy-room",
1550
1550
  silenceMs: 620,
1551
1551
  speechThreshold: 0.012,
1552
1552
  transcriptStabilityMs: 280
@@ -1571,8 +1571,8 @@ var PRESET_INPUTS = {
1571
1571
  },
1572
1572
  sttLifecycle: "continuous",
1573
1573
  turnDetection: {
1574
- qualityProfile: "noisy-room",
1575
- profile: "long-form"
1574
+ profile: "long-form",
1575
+ qualityProfile: "noisy-room"
1576
1576
  }
1577
1577
  }
1578
1578
  };
@@ -1712,11 +1712,22 @@ var createVoiceController = (path, options = {}) => {
1712
1712
  stream.close();
1713
1713
  };
1714
1714
  return {
1715
+ close,
1716
+ startRecording,
1717
+ stopRecording,
1718
+ get assistantAudio() {
1719
+ return state.assistantAudio;
1720
+ },
1721
+ get assistantTexts() {
1722
+ return state.assistantTexts;
1723
+ },
1715
1724
  bindHTMX(bindingOptions) {
1716
1725
  return bindVoiceHTMX(stream, bindingOptions);
1717
1726
  },
1727
+ get call() {
1728
+ return state.call;
1729
+ },
1718
1730
  callControl: (message) => stream.callControl(message),
1719
- close,
1720
1731
  endTurn: () => stream.endTurn(),
1721
1732
  get error() {
1722
1733
  return state.error;
@@ -1732,28 +1743,26 @@ var createVoiceController = (path, options = {}) => {
1732
1743
  get partial() {
1733
1744
  return state.partial;
1734
1745
  },
1746
+ get reconnect() {
1747
+ return state.reconnect;
1748
+ },
1735
1749
  get recordingError() {
1736
1750
  return state.recordingError;
1737
1751
  },
1738
- get reconnect() {
1739
- return state.reconnect;
1752
+ get scenarioId() {
1753
+ return state.scenarioId;
1740
1754
  },
1741
1755
  sendAudio: (audio) => stream.sendAudio(audio),
1742
- simulateDisconnect: () => stream.simulateDisconnect(),
1743
1756
  get sessionId() {
1744
1757
  return state.sessionId;
1745
1758
  },
1746
1759
  get sessionMetadata() {
1747
1760
  return state.sessionMetadata;
1748
1761
  },
1749
- get scenarioId() {
1750
- return state.scenarioId;
1751
- },
1752
- startRecording,
1762
+ simulateDisconnect: () => stream.simulateDisconnect(),
1753
1763
  get status() {
1754
1764
  return state.status;
1755
1765
  },
1756
- stopRecording,
1757
1766
  subscribe: (subscriber) => {
1758
1767
  subscribers.add(subscriber);
1759
1768
  return () => {
@@ -1769,20 +1778,17 @@ var createVoiceController = (path, options = {}) => {
1769
1778
  },
1770
1779
  get turns() {
1771
1780
  return state.turns;
1772
- },
1773
- get assistantTexts() {
1774
- return state.assistantTexts;
1775
- },
1776
- get assistantAudio() {
1777
- return state.assistantAudio;
1778
- },
1779
- get call() {
1780
- return state.call;
1781
1781
  }
1782
1782
  };
1783
1783
  };
1784
1784
 
1785
1785
  // src/core/agentState.ts
1786
+ var voiceAgentUIStateOrder = [
1787
+ "idle",
1788
+ "listening",
1789
+ "thinking",
1790
+ "speaking"
1791
+ ];
1786
1792
  var deriveVoiceAgentUIState = (input) => {
1787
1793
  if (!input.isConnected) {
1788
1794
  return "idle";
@@ -1816,12 +1822,6 @@ var describeVoiceAgentUIState = (state) => {
1816
1822
  return "Thinking";
1817
1823
  }
1818
1824
  };
1819
- var voiceAgentUIStateOrder = [
1820
- "idle",
1821
- "listening",
1822
- "thinking",
1823
- "speaking"
1824
- ];
1825
1825
 
1826
1826
  // src/client/voiceWidgetView.ts
1827
1827
  var DEFAULT_VOICE_WIDGET_THEME = {
@@ -1927,14 +1927,14 @@ var createVoiceWidget = (path, options = {}) => {
1927
1927
  title: options.title
1928
1928
  });
1929
1929
  return {
1930
+ getViewModel: buildModel,
1931
+ subscribe: controller.subscribe,
1930
1932
  close: () => controller.close(),
1931
1933
  endCall: () => controller.close(),
1932
1934
  getHTML: () => renderVoiceWidgetHTML(buildModel()),
1933
1935
  getSnapshot: () => controller.getSnapshot(),
1934
- getViewModel: buildModel,
1935
1936
  mute: () => controller.stopRecording(),
1936
1937
  startCall: () => controller.startRecording(),
1937
- subscribe: controller.subscribe,
1938
1938
  unmute: () => controller.startRecording()
1939
1939
  };
1940
1940
  };
@@ -2027,6 +2027,16 @@ var formatUsd = (value, currency = "USD") => new Intl.NumberFormat("en-US", {
2027
2027
  style: "currency"
2028
2028
  }).format(value);
2029
2029
  var formatInteger = (value) => new Intl.NumberFormat("en-US").format(value);
2030
+ var createVoiceCostDashboard = (options) => {
2031
+ const buildReport = () => buildVoiceCostDashboardReport(options);
2032
+ return {
2033
+ getReport: buildReport,
2034
+ getHTML: () => renderVoiceCostDashboardHTML(buildReport(), {
2035
+ currency: options.currency,
2036
+ title: options.title
2037
+ })
2038
+ };
2039
+ };
2030
2040
  var renderVoiceCostDashboardHTML = (report, options = {}) => {
2031
2041
  const currency = options.currency ?? "USD";
2032
2042
  const title = options.title ?? "Voice cost dashboard";
@@ -2060,16 +2070,6 @@ var renderVoiceCostDashboardHTML = (report, options = {}) => {
2060
2070
  </table>
2061
2071
  </section>`;
2062
2072
  };
2063
- var createVoiceCostDashboard = (options) => {
2064
- const buildReport = () => buildVoiceCostDashboardReport(options);
2065
- return {
2066
- getHTML: () => renderVoiceCostDashboardHTML(buildReport(), {
2067
- currency: options.currency,
2068
- title: options.title
2069
- }),
2070
- getReport: buildReport
2071
- };
2072
- };
2073
2073
  // src/client/liveCallViewer.ts
2074
2074
  var EVENT_BUFFER_LIMIT = 200;
2075
2075
  var createLiveCallViewer = (options) => {
@@ -2110,6 +2110,7 @@ var createLiveCallViewer = (options) => {
2110
2110
  update({ events: next });
2111
2111
  };
2112
2112
  return {
2113
+ applyEvent: pushEvent,
2113
2114
  applyControl: (control) => {
2114
2115
  pushEvent({
2115
2116
  at: Date.now(),
@@ -2118,7 +2119,6 @@ var createLiveCallViewer = (options) => {
2118
2119
  title: `control:${control.type}`
2119
2120
  });
2120
2121
  },
2121
- applyEvent: pushEvent,
2122
2122
  applyMonitorEvent: ({ payload, type }) => {
2123
2123
  pushEvent({
2124
2124
  at: Date.now(),
@@ -2213,6 +2213,7 @@ var createLiveAgentConsole = (options) => {
2213
2213
  }
2214
2214
  return {
2215
2215
  getState: buildState,
2216
+ viewer,
2216
2217
  noteAgentAudio: (at) => viewer.noteAgentAudio(at),
2217
2218
  notePartial: (text, at) => viewer.notePartial(text, at),
2218
2219
  noteTranscript: (text, at) => viewer.noteTranscript(text, at),
@@ -2245,12 +2246,23 @@ var createLiveAgentConsole = (options) => {
2245
2246
  takeoverReason = reason;
2246
2247
  viewer.applyControl({ reason, type: "takeover.engaged" });
2247
2248
  notify();
2248
- },
2249
- viewer
2249
+ }
2250
2250
  };
2251
2251
  };
2252
2252
 
2253
2253
  // src/svelte/createVoiceLiveAgentConsole.ts
2254
+ var createVoiceLiveAgentConsole = (options) => {
2255
+ const console = createLiveAgentConsole(options);
2256
+ return {
2257
+ ...console,
2258
+ getHTML: () => renderVoiceLiveAgentConsoleHTML(console.getState(), {
2259
+ takeoverButtonLabel: options.takeoverButtonLabel,
2260
+ title: options.title
2261
+ }),
2262
+ takeoverButtonLabel: options.takeoverButtonLabel ?? "Take over",
2263
+ title: options.title ?? "Live agent console"
2264
+ };
2265
+ };
2254
2266
  var renderVoiceLiveAgentConsoleHTML = (state, options = {}) => {
2255
2267
  const title = options.title ?? "Live agent console";
2256
2268
  const buttonLabel = options.takeoverButtonLabel ?? "Take over";
@@ -2274,18 +2286,6 @@ var renderVoiceLiveAgentConsoleHTML = (state, options = {}) => {
2274
2286
  <ol style="display:flex;flex-direction:column;gap:6px;list-style:none;margin:0;max-height:260px;overflow-y:auto;padding:0;">${items}</ol>
2275
2287
  </section>`;
2276
2288
  };
2277
- var createVoiceLiveAgentConsole = (options) => {
2278
- const console = createLiveAgentConsole(options);
2279
- return {
2280
- ...console,
2281
- getHTML: () => renderVoiceLiveAgentConsoleHTML(console.getState(), {
2282
- takeoverButtonLabel: options.takeoverButtonLabel,
2283
- title: options.title
2284
- }),
2285
- takeoverButtonLabel: options.takeoverButtonLabel ?? "Take over",
2286
- title: options.title ?? "Live agent console"
2287
- };
2288
- };
2289
2289
  // src/svelte/createVoiceLiveCallViewer.ts
2290
2290
  var escape2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2291
2291
  var CATEGORY_COLOR = {
@@ -2412,8 +2412,8 @@ var renderVoiceReplayTimelineHTML = (report, options = {}) => {
2412
2412
  var createVoiceReplayTimeline = (options) => {
2413
2413
  const buildReport = () => buildReplayTimelineReport({ artifact: options.artifact });
2414
2414
  return {
2415
- getHTML: () => renderVoiceReplayTimelineHTML(buildReport(), { title: options.title }),
2416
- getReport: buildReport
2415
+ getReport: buildReport,
2416
+ getHTML: () => renderVoiceReplayTimelineHTML(buildReport(), { title: options.title })
2417
2417
  };
2418
2418
  };
2419
2419
  // src/client/deliveryRuntime.ts
@@ -2423,30 +2423,6 @@ var getDefaultActionPath = (path, action, options) => {
2423
2423
  }
2424
2424
  return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
2425
2425
  };
2426
- var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
2427
- const fetchImpl = options.fetch ?? globalThis.fetch;
2428
- const response = await fetchImpl(path);
2429
- if (!response.ok) {
2430
- throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
2431
- }
2432
- return await response.json();
2433
- };
2434
- var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
2435
- const fetchImpl = options.fetch ?? globalThis.fetch;
2436
- const response = await fetchImpl(getDefaultActionPath(path, action, options), {
2437
- method: "POST"
2438
- });
2439
- if (!response.ok) {
2440
- throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
2441
- }
2442
- const body = await response.json();
2443
- return {
2444
- action,
2445
- result: body.result,
2446
- summary: body.summary,
2447
- updatedAt: Date.now()
2448
- };
2449
- };
2450
2426
  var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
2451
2427
  const listeners = new Set;
2452
2428
  let closed = false;
@@ -2539,17 +2515,41 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
2539
2515
  }
2540
2516
  return {
2541
2517
  close,
2518
+ refresh,
2542
2519
  getServerSnapshot: () => snapshot,
2543
2520
  getSnapshot: () => snapshot,
2544
2521
  requeueDeadLetters: () => runAction("requeue-dead-letters"),
2545
- refresh,
2546
- tick: () => runAction("tick"),
2547
2522
  subscribe: (listener) => {
2548
2523
  listeners.add(listener);
2549
2524
  return () => {
2550
2525
  listeners.delete(listener);
2551
2526
  };
2552
- }
2527
+ },
2528
+ tick: () => runAction("tick")
2529
+ };
2530
+ };
2531
+ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
2532
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2533
+ const response = await fetchImpl(path);
2534
+ if (!response.ok) {
2535
+ throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
2536
+ }
2537
+ return await response.json();
2538
+ };
2539
+ var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
2540
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2541
+ const response = await fetchImpl(getDefaultActionPath(path, action, options), {
2542
+ method: "POST"
2543
+ });
2544
+ if (!response.ok) {
2545
+ throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
2546
+ }
2547
+ const body = await response.json();
2548
+ return {
2549
+ action,
2550
+ result: body.result,
2551
+ summary: body.summary,
2552
+ updatedAt: Date.now()
2553
2553
  };
2554
2554
  };
2555
2555
 
@@ -2582,7 +2582,7 @@ var createSurface = (id, summary) => {
2582
2582
  };
2583
2583
  };
2584
2584
  var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
2585
- const report = snapshot.report;
2585
+ const { report } = snapshot;
2586
2586
  const surfaces = [
2587
2587
  createSurface("audit", report?.summary.audit),
2588
2588
  createSurface("trace", report?.summary.trace)
@@ -2602,29 +2602,25 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
2602
2602
  updatedAt: snapshot.updatedAt
2603
2603
  };
2604
2604
  };
2605
- var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
2606
- const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
2607
- const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml(surface.status)}">
2608
- <span>${escapeHtml(surface.label)}</span>
2609
- <strong>${escapeHtml(surface.detail)}</strong>
2610
- <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
2611
- </li>`).join("");
2612
- const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
2613
- <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
2614
- <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
2615
- </div>`;
2616
- const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.actionError)}</p>` : "";
2617
- return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml(model.status)}">
2618
- <header class="absolute-voice-delivery-runtime__header">
2619
- <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml(model.title)}</span>
2620
- <strong class="absolute-voice-delivery-runtime__label">${escapeHtml(model.label)}</strong>
2621
- </header>
2622
- <p class="absolute-voice-delivery-runtime__description">${escapeHtml(model.description)}</p>
2623
- <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
2624
- ${actions}
2625
- ${actionError}
2626
- ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.error)}</p>` : ""}
2627
- </section>`;
2605
+ var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runtime") => {
2606
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2607
+ return;
2608
+ }
2609
+ customElements.define(tagName, class AbsoluteVoiceDeliveryRuntimeElement extends HTMLElement {
2610
+ mounted;
2611
+ connectedCallback() {
2612
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
2613
+ this.mounted = mountVoiceDeliveryRuntime(this, this.getAttribute("path") ?? "/api/voice-delivery-runtime", {
2614
+ description: this.getAttribute("description") ?? undefined,
2615
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
2616
+ title: this.getAttribute("title") ?? undefined
2617
+ });
2618
+ }
2619
+ disconnectedCallback() {
2620
+ this.mounted?.close();
2621
+ this.mounted = undefined;
2622
+ }
2623
+ });
2628
2624
  };
2629
2625
  var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
2630
2626
  var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
@@ -2634,7 +2630,7 @@ var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime",
2634
2630
  };
2635
2631
  const unsubscribe = store.subscribe(render);
2636
2632
  const handleClick = (event) => {
2637
- const target = event.target;
2633
+ const { target } = event;
2638
2634
  if (!(target instanceof Element)) {
2639
2635
  return;
2640
2636
  }
@@ -2651,33 +2647,37 @@ var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime",
2651
2647
  render();
2652
2648
  store.refresh().catch(() => {});
2653
2649
  return {
2650
+ refresh: store.refresh,
2654
2651
  close: () => {
2655
2652
  element.removeEventListener?.("click", handleClick);
2656
2653
  unsubscribe();
2657
2654
  store.close();
2658
- },
2659
- refresh: store.refresh
2655
+ }
2660
2656
  };
2661
2657
  };
2662
- var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runtime") => {
2663
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2664
- return;
2665
- }
2666
- customElements.define(tagName, class AbsoluteVoiceDeliveryRuntimeElement extends HTMLElement {
2667
- mounted;
2668
- connectedCallback() {
2669
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
2670
- this.mounted = mountVoiceDeliveryRuntime(this, this.getAttribute("path") ?? "/api/voice-delivery-runtime", {
2671
- description: this.getAttribute("description") ?? undefined,
2672
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
2673
- title: this.getAttribute("title") ?? undefined
2674
- });
2675
- }
2676
- disconnectedCallback() {
2677
- this.mounted?.close();
2678
- this.mounted = undefined;
2679
- }
2680
- });
2658
+ var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
2659
+ const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
2660
+ const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml(surface.status)}">
2661
+ <span>${escapeHtml(surface.label)}</span>
2662
+ <strong>${escapeHtml(surface.detail)}</strong>
2663
+ <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
2664
+ </li>`).join("");
2665
+ const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
2666
+ <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
2667
+ <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
2668
+ </div>`;
2669
+ const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.actionError)}</p>` : "";
2670
+ return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml(model.status)}">
2671
+ <header class="absolute-voice-delivery-runtime__header">
2672
+ <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml(model.title)}</span>
2673
+ <strong class="absolute-voice-delivery-runtime__label">${escapeHtml(model.label)}</strong>
2674
+ </header>
2675
+ <p class="absolute-voice-delivery-runtime__description">${escapeHtml(model.description)}</p>
2676
+ <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
2677
+ ${actions}
2678
+ ${actionError}
2679
+ ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.error)}</p>` : ""}
2680
+ </section>`;
2681
2681
  };
2682
2682
 
2683
2683
  // src/svelte/createVoiceDeliveryRuntime.ts
@@ -2685,13 +2685,13 @@ var createVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options
2685
2685
  const store = createVoiceDeliveryRuntimeStore(path, options);
2686
2686
  return {
2687
2687
  close: store.close,
2688
- getHTML: () => renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options),
2689
2688
  getSnapshot: store.getSnapshot,
2690
- getViewModel: () => createVoiceDeliveryRuntimeViewModel(store.getSnapshot(), options),
2691
- requeueDeadLetters: store.requeueDeadLetters,
2692
2689
  refresh: store.refresh,
2690
+ requeueDeadLetters: store.requeueDeadLetters,
2693
2691
  subscribe: store.subscribe,
2694
- tick: store.tick
2692
+ tick: store.tick,
2693
+ getHTML: () => renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options),
2694
+ getViewModel: () => createVoiceDeliveryRuntimeViewModel(store.getSnapshot(), options)
2695
2695
  };
2696
2696
  };
2697
2697
  // src/client/opsActionCenter.ts
@@ -2768,24 +2768,6 @@ var createVoiceOpsActionCenterActions = (options = {}) => {
2768
2768
  }
2769
2769
  return actions;
2770
2770
  };
2771
- var runVoiceOpsAction = async (action, options = {}) => {
2772
- const fetchImpl = options.fetch ?? globalThis.fetch;
2773
- const response = await fetchImpl(action.path, {
2774
- method: action.method ?? "POST"
2775
- });
2776
- const body = await response.json().catch(() => null);
2777
- if (!response.ok) {
2778
- const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
2779
- throw new Error(message);
2780
- }
2781
- return {
2782
- actionId: action.id,
2783
- body,
2784
- ok: response.ok,
2785
- ranAt: Date.now(),
2786
- status: response.status
2787
- };
2788
- };
2789
2771
  var createVoiceOpsActionCenterStore = (options = {}) => {
2790
2772
  const listeners = new Set;
2791
2773
  let closed = false;
@@ -2872,10 +2854,10 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
2872
2854
  }
2873
2855
  return {
2874
2856
  close,
2875
- getServerSnapshot: () => snapshot,
2876
- getSnapshot: () => snapshot,
2877
2857
  run,
2878
2858
  setActions,
2859
+ getServerSnapshot: () => snapshot,
2860
+ getSnapshot: () => snapshot,
2879
2861
  subscribe: (listener) => {
2880
2862
  listeners.add(listener);
2881
2863
  return () => {
@@ -2884,6 +2866,24 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
2884
2866
  }
2885
2867
  };
2886
2868
  };
2869
+ var runVoiceOpsAction = async (action, options = {}) => {
2870
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2871
+ const response = await fetchImpl(action.path, {
2872
+ method: action.method ?? "POST"
2873
+ });
2874
+ const body = await response.json().catch(() => null);
2875
+ if (!response.ok) {
2876
+ const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
2877
+ throw new Error(message);
2878
+ }
2879
+ return {
2880
+ actionId: action.id,
2881
+ body,
2882
+ ok: response.ok,
2883
+ ranAt: Date.now(),
2884
+ status: response.status
2885
+ };
2886
+ };
2887
2887
 
2888
2888
  // src/client/opsActionCenterWidget.ts
2889
2889
  var DEFAULT_TITLE2 = "Voice Ops Action Center";
@@ -2907,21 +2907,24 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
2907
2907
  title: options.title ?? DEFAULT_TITLE2
2908
2908
  };
2909
2909
  };
2910
- var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
2911
- const model = createVoiceOpsActionCenterViewModel(snapshot, options);
2912
- const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml(action.id)}"${action.disabled ? " disabled" : ""}>
2913
- ${escapeHtml(action.isRunning ? "Working..." : action.label)}
2914
- </button>`).join("");
2915
- return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml(model.status)}">
2916
- <header class="absolute-voice-ops-action-center__header">
2917
- <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml(model.title)}</span>
2918
- <strong class="absolute-voice-ops-action-center__label">${escapeHtml(model.label)}</strong>
2919
- </header>
2920
- <p class="absolute-voice-ops-action-center__description">${escapeHtml(model.description)}</p>
2921
- <div class="absolute-voice-ops-action-center__actions">${actions}</div>
2922
- <p class="absolute-voice-ops-action-center__result">${escapeHtml(model.lastResultLabel)}</p>
2923
- ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml(model.error)}</p>` : ""}
2924
- </section>`;
2910
+ var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
2911
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2912
+ return;
2913
+ }
2914
+ customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
2915
+ mounted;
2916
+ connectedCallback() {
2917
+ this.mounted = mountVoiceOpsActionCenter(this, {
2918
+ ...options,
2919
+ description: this.getAttribute("description") ?? options.description,
2920
+ title: this.getAttribute("title") ?? options.title
2921
+ });
2922
+ }
2923
+ disconnectedCallback() {
2924
+ this.mounted?.close();
2925
+ this.mounted = undefined;
2926
+ }
2927
+ });
2925
2928
  };
2926
2929
  var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
2927
2930
  var mountVoiceOpsActionCenter = (element, options = {}) => {
@@ -2931,7 +2934,7 @@ var mountVoiceOpsActionCenter = (element, options = {}) => {
2931
2934
  };
2932
2935
  const unsubscribe = store.subscribe(render);
2933
2936
  const handleClick = (event) => {
2934
- const target = event.target;
2937
+ const { target } = event;
2935
2938
  if (!(target instanceof Element)) {
2936
2939
  return;
2937
2940
  }
@@ -2944,67 +2947,45 @@ var mountVoiceOpsActionCenter = (element, options = {}) => {
2944
2947
  element.addEventListener?.("click", handleClick);
2945
2948
  render();
2946
2949
  return {
2950
+ run: store.run,
2947
2951
  close: () => {
2948
2952
  element.removeEventListener?.("click", handleClick);
2949
2953
  unsubscribe();
2950
2954
  store.close();
2951
- },
2952
- run: store.run
2953
- };
2954
- };
2955
- var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
2956
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2957
- return;
2958
- }
2959
- customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
2960
- mounted;
2961
- connectedCallback() {
2962
- this.mounted = mountVoiceOpsActionCenter(this, {
2963
- ...options,
2964
- description: this.getAttribute("description") ?? options.description,
2965
- title: this.getAttribute("title") ?? options.title
2966
- });
2967
- }
2968
- disconnectedCallback() {
2969
- this.mounted?.close();
2970
- this.mounted = undefined;
2971
2955
  }
2972
- });
2973
- };
2974
-
2975
- // src/svelte/createVoiceOpsActionCenter.ts
2976
- var createVoiceOpsActionCenter = (options = {}) => {
2977
- const store = createVoiceOpsActionCenterStore(options);
2978
- return {
2979
- close: store.close,
2980
- getHTML: () => renderVoiceOpsActionCenterHTML(store.getSnapshot(), options),
2981
- getSnapshot: store.getSnapshot,
2982
- getViewModel: () => createVoiceOpsActionCenterViewModel(store.getSnapshot(), options),
2983
- run: store.run,
2984
- setActions: store.setActions,
2985
- subscribe: store.subscribe
2986
2956
  };
2987
2957
  };
2988
- // src/client/liveOps.ts
2989
- var postVoiceLiveOpsAction = async (input, options = {}) => {
2990
- if (!input.sessionId) {
2991
- throw new Error("Start a voice session before running live ops actions.");
2992
- }
2993
- const fetchImpl = options.fetch ?? globalThis.fetch;
2994
- const response = await fetchImpl(options.actionPath ?? "/api/voice/live-ops/action", {
2995
- body: JSON.stringify(input),
2996
- headers: {
2997
- "Content-Type": "application/json"
2998
- },
2999
- method: "POST"
3000
- });
3001
- const payload = await response.json().catch(() => null);
3002
- if (!response.ok || !payload?.ok) {
3003
- const message = payload && typeof payload === "object" && "error" in payload ? String(payload.error) : `Voice live ops action failed: HTTP ${response.status}`;
3004
- throw new Error(message);
3005
- }
3006
- return payload;
2958
+ var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
2959
+ const model = createVoiceOpsActionCenterViewModel(snapshot, options);
2960
+ const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml(action.id)}"${action.disabled ? " disabled" : ""}>
2961
+ ${escapeHtml(action.isRunning ? "Working..." : action.label)}
2962
+ </button>`).join("");
2963
+ return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml(model.status)}">
2964
+ <header class="absolute-voice-ops-action-center__header">
2965
+ <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml(model.title)}</span>
2966
+ <strong class="absolute-voice-ops-action-center__label">${escapeHtml(model.label)}</strong>
2967
+ </header>
2968
+ <p class="absolute-voice-ops-action-center__description">${escapeHtml(model.description)}</p>
2969
+ <div class="absolute-voice-ops-action-center__actions">${actions}</div>
2970
+ <p class="absolute-voice-ops-action-center__result">${escapeHtml(model.lastResultLabel)}</p>
2971
+ ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml(model.error)}</p>` : ""}
2972
+ </section>`;
2973
+ };
2974
+
2975
+ // src/svelte/createVoiceOpsActionCenter.ts
2976
+ var createVoiceOpsActionCenter = (options = {}) => {
2977
+ const store = createVoiceOpsActionCenterStore(options);
2978
+ return {
2979
+ close: store.close,
2980
+ getSnapshot: store.getSnapshot,
2981
+ run: store.run,
2982
+ setActions: store.setActions,
2983
+ subscribe: store.subscribe,
2984
+ getHTML: () => renderVoiceOpsActionCenterHTML(store.getSnapshot(), options),
2985
+ getViewModel: () => createVoiceOpsActionCenterViewModel(store.getSnapshot(), options)
2986
+ };
3007
2987
  };
2988
+ // src/client/liveOps.ts
3008
2989
  var createVoiceLiveOpsStore = (options = {}) => {
3009
2990
  const listeners = new Set;
3010
2991
  let closed = false;
@@ -3059,9 +3040,9 @@ var createVoiceLiveOpsStore = (options = {}) => {
3059
3040
  };
3060
3041
  return {
3061
3042
  close,
3043
+ run,
3062
3044
  getServerSnapshot: () => snapshot,
3063
3045
  getSnapshot: () => snapshot,
3064
- run,
3065
3046
  subscribe: (listener) => {
3066
3047
  listeners.add(listener);
3067
3048
  return () => {
@@ -3070,6 +3051,25 @@ var createVoiceLiveOpsStore = (options = {}) => {
3070
3051
  }
3071
3052
  };
3072
3053
  };
3054
+ var postVoiceLiveOpsAction = async (input, options = {}) => {
3055
+ if (!input.sessionId) {
3056
+ throw new Error("Start a voice session before running live ops actions.");
3057
+ }
3058
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3059
+ const response = await fetchImpl(options.actionPath ?? "/api/voice/live-ops/action", {
3060
+ body: JSON.stringify(input),
3061
+ headers: {
3062
+ "Content-Type": "application/json"
3063
+ },
3064
+ method: "POST"
3065
+ });
3066
+ const payload = await response.json().catch(() => null);
3067
+ if (!response.ok || !payload?.ok) {
3068
+ const message = payload && typeof payload === "object" && "error" in payload ? String(payload.error) : `Voice live ops action failed: HTTP ${response.status}`;
3069
+ throw new Error(message);
3070
+ }
3071
+ return payload;
3072
+ };
3073
3073
 
3074
3074
  // src/internal/evidence.ts
3075
3075
  var assertVoiceEvidence = (failureMessage, assertion) => {
@@ -3097,44 +3097,25 @@ var createVoiceAuditEvent = (event) => ({
3097
3097
  at: event.at ?? Date.now(),
3098
3098
  id: event.id ?? crypto.randomUUID()
3099
3099
  });
3100
- var filterVoiceAuditEvents = (events, filter = {}) => {
3101
- const sorted = events.filter((event) => {
3102
- if (!includes(filter.type, event.type)) {
3103
- return false;
3104
- }
3105
- if (!includes(filter.outcome, event.outcome)) {
3106
- return false;
3107
- }
3108
- if (filter.actorId && event.actor?.id !== filter.actorId) {
3109
- return false;
3110
- }
3111
- if (filter.resourceId && event.resource?.id !== filter.resourceId) {
3112
- return false;
3113
- }
3114
- if (filter.resourceType && event.resource?.type !== filter.resourceType) {
3115
- return false;
3116
- }
3117
- if (filter.sessionId && event.sessionId !== filter.sessionId) {
3118
- return false;
3119
- }
3120
- if (filter.traceId && event.traceId !== filter.traceId) {
3121
- return false;
3122
- }
3123
- if (typeof filter.after === "number" && event.at <= filter.after) {
3124
- return false;
3125
- }
3126
- if (typeof filter.afterOrAt === "number" && event.at < filter.afterOrAt) {
3127
- return false;
3128
- }
3129
- if (typeof filter.before === "number" && event.at >= filter.before) {
3130
- return false;
3131
- }
3132
- if (typeof filter.beforeOrAt === "number" && event.at > filter.beforeOrAt) {
3133
- return false;
3134
- }
3135
- return true;
3136
- }).sort((left, right) => left.at - right.at || left.id.localeCompare(right.id));
3137
- return typeof filter.limit === "number" && filter.limit >= 0 ? sorted.slice(0, filter.limit) : sorted;
3100
+ var createVoiceAuditLogger = (store) => ({
3101
+ handoff: (input) => recordVoiceHandoffAuditEvent({ ...input, store }),
3102
+ operatorAction: (input) => recordVoiceOperatorAuditEvent({ ...input, store }),
3103
+ providerCall: (input) => recordVoiceProviderAuditEvent({ ...input, store }),
3104
+ record: (event) => recordVoiceAuditEvent(store, event),
3105
+ retention: (input) => recordVoiceRetentionAuditEvent({ ...input, store }),
3106
+ toolCall: (input) => recordVoiceToolAuditEvent({ ...input, store })
3107
+ });
3108
+ var createVoiceMemoryAuditEventStore = () => {
3109
+ const events = new Map;
3110
+ return {
3111
+ append: (event) => {
3112
+ const stored = createVoiceAuditEvent(event);
3113
+ events.set(stored.id, stored);
3114
+ return stored;
3115
+ },
3116
+ get: (id) => events.get(id),
3117
+ list: (filter) => filterVoiceAuditEvents([...events.values()], filter)
3118
+ };
3138
3119
  };
3139
3120
  var createVoiceScopedAuditEventStore = (store, scope) => {
3140
3121
  const upstreamFilter = (filter = {}) => {
@@ -3173,77 +3154,96 @@ var createVoiceScopedAuditEventStore = (store, scope) => {
3173
3154
  list: async (filter) => filterVoiceAuditEvents(await store.list(upstreamFilter(filter)), scopedFilter(filter))
3174
3155
  };
3175
3156
  };
3176
- var createVoiceMemoryAuditEventStore = () => {
3177
- const events = new Map;
3178
- return {
3179
- append: (event) => {
3180
- const stored = createVoiceAuditEvent(event);
3181
- events.set(stored.id, stored);
3182
- return stored;
3183
- },
3184
- get: (id) => events.get(id),
3185
- list: (filter) => filterVoiceAuditEvents([...events.values()], filter)
3186
- };
3157
+ var filterVoiceAuditEvents = (events, filter = {}) => {
3158
+ const sorted = events.filter((event) => {
3159
+ if (!includes(filter.type, event.type)) {
3160
+ return false;
3161
+ }
3162
+ if (!includes(filter.outcome, event.outcome)) {
3163
+ return false;
3164
+ }
3165
+ if (filter.actorId && event.actor?.id !== filter.actorId) {
3166
+ return false;
3167
+ }
3168
+ if (filter.resourceId && event.resource?.id !== filter.resourceId) {
3169
+ return false;
3170
+ }
3171
+ if (filter.resourceType && event.resource?.type !== filter.resourceType) {
3172
+ return false;
3173
+ }
3174
+ if (filter.sessionId && event.sessionId !== filter.sessionId) {
3175
+ return false;
3176
+ }
3177
+ if (filter.traceId && event.traceId !== filter.traceId) {
3178
+ return false;
3179
+ }
3180
+ if (typeof filter.after === "number" && event.at <= filter.after) {
3181
+ return false;
3182
+ }
3183
+ if (typeof filter.afterOrAt === "number" && event.at < filter.afterOrAt) {
3184
+ return false;
3185
+ }
3186
+ if (typeof filter.before === "number" && event.at >= filter.before) {
3187
+ return false;
3188
+ }
3189
+ if (typeof filter.beforeOrAt === "number" && event.at > filter.beforeOrAt) {
3190
+ return false;
3191
+ }
3192
+ return true;
3193
+ }).sort((left, right) => left.at - right.at || left.id.localeCompare(right.id));
3194
+ return typeof filter.limit === "number" && filter.limit >= 0 ? sorted.slice(0, filter.limit) : sorted;
3187
3195
  };
3188
3196
  var recordVoiceAuditEvent = (store, event) => store.append(createVoiceAuditEvent(event));
3189
- var recordVoiceProviderAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3190
- action: `${input.kind}.provider.call`,
3197
+ var recordVoiceHandoffAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3198
+ action: "handoff",
3191
3199
  actor: input.actor,
3192
3200
  metadata: input.metadata,
3193
3201
  outcome: input.outcome,
3194
3202
  payload: {
3195
- cost: input.cost,
3196
- elapsedMs: input.elapsedMs,
3197
- error: input.error,
3198
- kind: input.kind,
3199
- model: input.model,
3200
- provider: input.provider
3203
+ fromAgentId: input.fromAgentId,
3204
+ reason: input.reason,
3205
+ target: input.target,
3206
+ toAgentId: input.toAgentId
3201
3207
  },
3202
3208
  resource: {
3203
- id: input.provider,
3204
- type: "provider"
3209
+ id: input.toAgentId ?? input.target,
3210
+ type: "handoff"
3205
3211
  },
3206
3212
  sessionId: input.sessionId,
3207
3213
  traceId: input.traceId,
3208
- type: "provider.call"
3214
+ type: "handoff"
3209
3215
  });
3210
- var recordVoiceToolAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3211
- action: "tool.call",
3216
+ var recordVoiceOperatorAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3217
+ action: input.action,
3212
3218
  actor: input.actor,
3213
3219
  metadata: input.metadata,
3214
- outcome: input.outcome,
3215
- payload: {
3216
- elapsedMs: input.elapsedMs,
3217
- error: input.error,
3218
- toolCallId: input.toolCallId,
3219
- toolName: input.toolName
3220
- },
3221
- resource: {
3222
- id: input.toolName,
3223
- type: "tool"
3224
- },
3220
+ outcome: input.outcome ?? "success",
3221
+ payload: input.payload,
3222
+ resource: input.resource,
3225
3223
  sessionId: input.sessionId,
3226
3224
  traceId: input.traceId,
3227
- type: "tool.call"
3225
+ type: "operator.action"
3228
3226
  });
3229
- var recordVoiceHandoffAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3230
- action: "handoff",
3227
+ var recordVoiceProviderAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3228
+ action: `${input.kind}.provider.call`,
3231
3229
  actor: input.actor,
3232
3230
  metadata: input.metadata,
3233
3231
  outcome: input.outcome,
3234
3232
  payload: {
3235
- fromAgentId: input.fromAgentId,
3236
- reason: input.reason,
3237
- target: input.target,
3238
- toAgentId: input.toAgentId
3233
+ cost: input.cost,
3234
+ elapsedMs: input.elapsedMs,
3235
+ error: input.error,
3236
+ kind: input.kind,
3237
+ model: input.model,
3238
+ provider: input.provider
3239
3239
  },
3240
3240
  resource: {
3241
- id: input.toAgentId ?? input.target,
3242
- type: "handoff"
3241
+ id: input.provider,
3242
+ type: "provider"
3243
3243
  },
3244
3244
  sessionId: input.sessionId,
3245
3245
  traceId: input.traceId,
3246
- type: "handoff"
3246
+ type: "provider.call"
3247
3247
  });
3248
3248
  var recordVoiceRetentionAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3249
3249
  action: input.dryRun ? "retention.plan" : "retention.apply",
@@ -3263,34 +3263,27 @@ var recordVoiceRetentionAuditEvent = (input) => recordVoiceAuditEvent(input.stor
3263
3263
  },
3264
3264
  type: "retention.policy"
3265
3265
  });
3266
- var recordVoiceOperatorAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3267
- action: input.action,
3266
+ var recordVoiceToolAuditEvent = (input) => recordVoiceAuditEvent(input.store, {
3267
+ action: "tool.call",
3268
3268
  actor: input.actor,
3269
3269
  metadata: input.metadata,
3270
- outcome: input.outcome ?? "success",
3271
- payload: input.payload,
3272
- resource: input.resource,
3270
+ outcome: input.outcome,
3271
+ payload: {
3272
+ elapsedMs: input.elapsedMs,
3273
+ error: input.error,
3274
+ toolCallId: input.toolCallId,
3275
+ toolName: input.toolName
3276
+ },
3277
+ resource: {
3278
+ id: input.toolName,
3279
+ type: "tool"
3280
+ },
3273
3281
  sessionId: input.sessionId,
3274
3282
  traceId: input.traceId,
3275
- type: "operator.action"
3276
- });
3277
- var createVoiceAuditLogger = (store) => ({
3278
- handoff: (input) => recordVoiceHandoffAuditEvent({ ...input, store }),
3279
- operatorAction: (input) => recordVoiceOperatorAuditEvent({ ...input, store }),
3280
- providerCall: (input) => recordVoiceProviderAuditEvent({ ...input, store }),
3281
- record: (event) => recordVoiceAuditEvent(store, event),
3282
- retention: (input) => recordVoiceRetentionAuditEvent({ ...input, store }),
3283
- toolCall: (input) => recordVoiceToolAuditEvent({ ...input, store })
3283
+ type: "tool.call"
3284
3284
  });
3285
3285
 
3286
3286
  // src/core/trace.ts
3287
- var createVoiceTraceEventId = (event) => [
3288
- event.sessionId,
3289
- event.turnId ?? "session",
3290
- event.type,
3291
- String(event.at ?? Date.now()),
3292
- crypto.randomUUID()
3293
- ].map(encodeURIComponent).join(":");
3294
3287
  var createVoiceTraceEvent = (event) => ({
3295
3288
  ...event,
3296
3289
  at: event.at,
@@ -3301,6 +3294,13 @@ var createVoiceTraceEvent = (event) => ({
3301
3294
  type: event.type
3302
3295
  })
3303
3296
  });
3297
+ var createVoiceTraceEventId = (event) => [
3298
+ event.sessionId,
3299
+ event.turnId ?? "session",
3300
+ event.type,
3301
+ String(event.at ?? Date.now()),
3302
+ crypto.randomUUID()
3303
+ ].map(encodeURIComponent).join(":");
3304
3304
  var createVoiceTraceSinkDeliveryId = (events) => {
3305
3305
  const firstEvent = events[0];
3306
3306
  return [
@@ -3345,9 +3345,24 @@ var matchesTraceFilter = (event, filter) => {
3345
3345
  }
3346
3346
  return true;
3347
3347
  };
3348
- var filterVoiceTraceEvents = (events, filter = {}) => {
3349
- const sorted = events.filter((event) => matchesTraceFilter(event, filter)).sort((left, right) => left.at - right.at || left.id.localeCompare(right.id));
3350
- return typeof filter.limit === "number" && filter.limit >= 0 ? sorted.slice(0, filter.limit) : sorted;
3348
+ var createVoiceProofTraceStore = (options = {}) => {
3349
+ const proofStore = options.proofStore ?? createVoiceMemoryTraceEventStore();
3350
+ const scopedProofStore = options.scope ? createVoiceScopedTraceEventStore(proofStore, options.scope) : proofStore;
3351
+ return {
3352
+ append: async (event) => {
3353
+ const stored = await proofStore.append(event);
3354
+ await options.mirrorStore?.append(stored);
3355
+ return stored;
3356
+ },
3357
+ get: async (id) => await proofStore.get(id) ?? await options.mirrorStore?.get(id),
3358
+ list: (filter) => scopedProofStore.list(filter),
3359
+ remove: async (id) => {
3360
+ await Promise.all([
3361
+ proofStore.remove(id),
3362
+ options.mirrorStore?.remove(id) ?? Promise.resolve()
3363
+ ]);
3364
+ }
3365
+ };
3351
3366
  };
3352
3367
  var createVoiceScopedTraceEventStore = (store, scope) => {
3353
3368
  const upstreamFilter = (filter = {}) => {
@@ -3381,24 +3396,9 @@ var createVoiceScopedTraceEventStore = (store, scope) => {
3381
3396
  remove: (id) => store.remove(id)
3382
3397
  };
3383
3398
  };
3384
- var createVoiceProofTraceStore = (options = {}) => {
3385
- const proofStore = options.proofStore ?? createVoiceMemoryTraceEventStore();
3386
- const scopedProofStore = options.scope ? createVoiceScopedTraceEventStore(proofStore, options.scope) : proofStore;
3387
- return {
3388
- append: async (event) => {
3389
- const stored = await proofStore.append(event);
3390
- await options.mirrorStore?.append(stored);
3391
- return stored;
3392
- },
3393
- get: async (id) => await proofStore.get(id) ?? await options.mirrorStore?.get(id),
3394
- list: (filter) => scopedProofStore.list(filter),
3395
- remove: async (id) => {
3396
- await Promise.all([
3397
- proofStore.remove(id),
3398
- options.mirrorStore?.remove(id) ?? Promise.resolve()
3399
- ]);
3400
- }
3401
- };
3399
+ var filterVoiceTraceEvents = (events, filter = {}) => {
3400
+ const sorted = events.filter((event) => matchesTraceFilter(event, filter)).sort((left, right) => left.at - right.at || left.id.localeCompare(right.id));
3401
+ return typeof filter.limit === "number" && filter.limit >= 0 ? sorted.slice(0, filter.limit) : sorted;
3402
3402
  };
3403
3403
  var isPruneTimeMatch = (event, options) => {
3404
3404
  if (typeof options.before === "number" && event.at >= options.before) {
@@ -3409,14 +3409,6 @@ var isPruneTimeMatch = (event, options) => {
3409
3409
  }
3410
3410
  return true;
3411
3411
  };
3412
- var selectVoiceTraceEventsForPrune = (events, options = {}) => {
3413
- let candidates = filterVoiceTraceEvents(events, options.filter).filter((event) => isPruneTimeMatch(event, options));
3414
- if (typeof options.keepNewest === "number" && options.keepNewest >= 0) {
3415
- const newestIds = new Set([...candidates].sort((left, right) => right.at - left.at || right.id.localeCompare(left.id)).slice(0, options.keepNewest).map((event) => event.id));
3416
- candidates = candidates.filter((event) => !newestIds.has(event.id));
3417
- }
3418
- return typeof options.limit === "number" && options.limit >= 0 ? candidates.slice(0, options.limit) : candidates;
3419
- };
3420
3412
  var pruneVoiceTraceEvents = async (options) => {
3421
3413
  const events = await options.store.list(options.filter);
3422
3414
  const deleted = selectVoiceTraceEventsForPrune(events, options);
@@ -3430,6 +3422,14 @@ var pruneVoiceTraceEvents = async (options) => {
3430
3422
  scannedCount: events.length
3431
3423
  };
3432
3424
  };
3425
+ var selectVoiceTraceEventsForPrune = (events, options = {}) => {
3426
+ let candidates = filterVoiceTraceEvents(events, options.filter).filter((event) => isPruneTimeMatch(event, options));
3427
+ if (typeof options.keepNewest === "number" && options.keepNewest >= 0) {
3428
+ const newestIds = new Set([...candidates].sort((left, right) => right.at - left.at || right.id.localeCompare(left.id)).slice(0, options.keepNewest).map((event) => event.id));
3429
+ candidates = candidates.filter((event) => !newestIds.has(event.id));
3430
+ }
3431
+ return typeof options.limit === "number" && options.limit >= 0 ? candidates.slice(0, options.limit) : candidates;
3432
+ };
3433
3433
  var sleep = async (delayMs) => {
3434
3434
  if (delayMs <= 0) {
3435
3435
  return;
@@ -3465,7 +3465,7 @@ var createVoiceTraceS3ObjectKey = (prefix, events) => {
3465
3465
  return `${prefix}/${safeSessionId}/${Date.now()}-${safeEventId}.json`;
3466
3466
  };
3467
3467
  var resolveVoiceS3DeliveredTo = (options, key) => {
3468
- const bucket = options.bucket;
3468
+ const { bucket } = options;
3469
3469
  return bucket ? `s3://${bucket}/${key}` : `s3://${key}`;
3470
3470
  };
3471
3471
  var aggregateVoiceTraceSinkDeliveryStatus = (deliveries) => {
@@ -3479,6 +3479,9 @@ var aggregateVoiceTraceSinkDeliveryStatus = (deliveries) => {
3479
3479
  return "delivered";
3480
3480
  };
3481
3481
  var createVoiceTraceHTTPSink = (options) => ({
3482
+ eventTypes: options.eventTypes,
3483
+ id: options.id,
3484
+ kind: options.kind ?? "http",
3482
3485
  deliver: async ({ events }) => {
3483
3486
  const fetchImpl = options.fetch ?? globalThis.fetch;
3484
3487
  if (typeof fetchImpl !== "function") {
@@ -3568,15 +3571,15 @@ var createVoiceTraceHTTPSink = (options) => ({
3568
3571
  eventCount: events.length,
3569
3572
  status: "failed"
3570
3573
  };
3571
- },
3572
- eventTypes: options.eventTypes,
3573
- id: options.id,
3574
- kind: options.kind ?? "http"
3574
+ }
3575
3575
  });
3576
3576
  var createVoiceTraceS3Sink = (options) => {
3577
3577
  const client = options.client ?? new Bun.S3Client(options);
3578
3578
  const keyPrefix = normalizeVoiceTraceS3KeyPrefix(options.keyPrefix);
3579
3579
  return {
3580
+ eventTypes: options.eventTypes,
3581
+ id: options.id,
3582
+ kind: options.kind ?? "s3",
3580
3583
  deliver: async ({ events }) => {
3581
3584
  const key = createVoiceTraceS3ObjectKey(keyPrefix, events);
3582
3585
  const payload = options.body ? await options.body({ events, key }) : {
@@ -3607,10 +3610,41 @@ var createVoiceTraceS3Sink = (options) => {
3607
3610
  status: "failed"
3608
3611
  };
3609
3612
  }
3613
+ }
3614
+ };
3615
+ };
3616
+ var createVoiceTraceSinkStore = (options) => {
3617
+ const deliver = async (event) => {
3618
+ const result = await deliverVoiceTraceEventsToSinks({
3619
+ events: [event],
3620
+ redact: options.redact,
3621
+ sinks: options.sinks
3622
+ });
3623
+ await options.onDelivery?.(result);
3624
+ };
3625
+ return {
3626
+ append: async (event) => {
3627
+ const stored = await options.store.append(event);
3628
+ if (options.deliveryQueue) {
3629
+ const delivery2 = createVoiceTraceSinkDeliveryRecord({
3630
+ events: [stored]
3631
+ });
3632
+ await options.deliveryQueue.set(delivery2.id, delivery2);
3633
+ return stored;
3634
+ }
3635
+ const delivery = deliver(stored);
3636
+ if (options.awaitDelivery) {
3637
+ await delivery;
3638
+ } else {
3639
+ delivery.catch((error) => {
3640
+ options.onError?.(error);
3641
+ });
3642
+ }
3643
+ return stored;
3610
3644
  },
3611
- eventTypes: options.eventTypes,
3612
- id: options.id,
3613
- kind: options.kind ?? "s3"
3645
+ get: (id) => options.store.get(id),
3646
+ list: (filter) => options.store.list(filter),
3647
+ remove: (id) => options.store.remove(id)
3614
3648
  };
3615
3649
  };
3616
3650
  var deliverVoiceTraceEventsToSinks = async (input) => {
@@ -3646,41 +3680,34 @@ var deliverVoiceTraceEventsToSinks = async (input) => {
3646
3680
  status: aggregateVoiceTraceSinkDeliveryStatus(sinkDeliveries)
3647
3681
  };
3648
3682
  };
3649
- var createVoiceTraceSinkStore = (options) => {
3650
- const deliver = async (event) => {
3651
- const result = await deliverVoiceTraceEventsToSinks({
3652
- events: [event],
3653
- redact: options.redact,
3654
- sinks: options.sinks
3655
- });
3656
- await options.onDelivery?.(result);
3683
+ var normalizeVoiceProfileTraceTaggerProfile = (profile) => typeof profile === "string" ? { id: profile } : profile?.id ? profile : undefined;
3684
+ var createVoiceMemoryTraceEventStore = () => {
3685
+ const events = new Map;
3686
+ const append = async (event) => {
3687
+ const stored = createVoiceTraceEvent(event);
3688
+ events.set(stored.id, stored);
3689
+ return stored;
3690
+ };
3691
+ const get = async (id) => events.get(id);
3692
+ const list = async (filter) => filterVoiceTraceEvents([...events.values()], filter);
3693
+ const remove = async (id) => {
3694
+ events.delete(id);
3657
3695
  };
3696
+ return { append, get, list, remove };
3697
+ };
3698
+ var createVoiceMemoryTraceSinkDeliveryStore = () => {
3699
+ const deliveries = new Map;
3658
3700
  return {
3659
- append: async (event) => {
3660
- const stored = await options.store.append(event);
3661
- if (options.deliveryQueue) {
3662
- const delivery2 = createVoiceTraceSinkDeliveryRecord({
3663
- events: [stored]
3664
- });
3665
- await options.deliveryQueue.set(delivery2.id, delivery2);
3666
- return stored;
3667
- }
3668
- const delivery = deliver(stored);
3669
- if (options.awaitDelivery) {
3670
- await delivery;
3671
- } else {
3672
- delivery.catch((error) => {
3673
- options.onError?.(error);
3674
- });
3675
- }
3676
- return stored;
3701
+ get: async (id) => deliveries.get(id),
3702
+ list: async () => [...deliveries.values()].sort((left, right) => left.createdAt - right.createdAt || left.id.localeCompare(right.id)),
3703
+ remove: async (id) => {
3704
+ deliveries.delete(id);
3677
3705
  },
3678
- get: (id) => options.store.get(id),
3679
- list: (filter) => options.store.list(filter),
3680
- remove: (id) => options.store.remove(id)
3706
+ set: async (id, delivery) => {
3707
+ deliveries.set(id, delivery);
3708
+ }
3681
3709
  };
3682
3710
  };
3683
- var normalizeVoiceProfileTraceTaggerProfile = (profile) => typeof profile === "string" ? { id: profile } : profile?.id ? profile : undefined;
3684
3711
  var createVoiceProfileTraceTagger = (options) => {
3685
3712
  const profiles = new Map((options.profiles ?? []).map((profile) => [profile.id, profile]));
3686
3713
  const defaultProfile = normalizeVoiceProfileTraceTaggerProfile(options.defaultProfile);
@@ -3720,33 +3747,6 @@ var createVoiceProfileTraceTagger = (options) => {
3720
3747
  remove: (id) => options.store.remove(id)
3721
3748
  };
3722
3749
  };
3723
- var createVoiceMemoryTraceSinkDeliveryStore = () => {
3724
- const deliveries = new Map;
3725
- return {
3726
- get: async (id) => deliveries.get(id),
3727
- list: async () => [...deliveries.values()].sort((left, right) => left.createdAt - right.createdAt || left.id.localeCompare(right.id)),
3728
- remove: async (id) => {
3729
- deliveries.delete(id);
3730
- },
3731
- set: async (id, delivery) => {
3732
- deliveries.set(id, delivery);
3733
- }
3734
- };
3735
- };
3736
- var createVoiceMemoryTraceEventStore = () => {
3737
- const events = new Map;
3738
- const append = async (event) => {
3739
- const stored = createVoiceTraceEvent(event);
3740
- events.set(stored.id, stored);
3741
- return stored;
3742
- };
3743
- const get = async (id) => events.get(id);
3744
- const list = async (filter) => filterVoiceTraceEvents([...events.values()], filter);
3745
- const remove = async (id) => {
3746
- events.delete(id);
3747
- };
3748
- return { append, get, list, remove };
3749
- };
3750
3750
  var exportVoiceTrace = async (input) => {
3751
3751
  const events = await input.store.list(input.filter);
3752
3752
  return {
@@ -3857,53 +3857,6 @@ var redactTraceValue = (value, options, path) => {
3857
3857
  }
3858
3858
  return value;
3859
3859
  };
3860
- var redactVoiceTraceEvent = (event, options = {}) => {
3861
- const resolved = resolveVoiceTraceRedactionOptions(options);
3862
- return {
3863
- ...event,
3864
- metadata: redactTraceValue(event.metadata, resolved, [
3865
- "metadata"
3866
- ]),
3867
- payload: redactTraceValue(event.payload, resolved, [
3868
- "payload"
3869
- ])
3870
- };
3871
- };
3872
- var redactVoiceTraceEvents = (events, options = {}) => events.map((event) => redactVoiceTraceEvent(event, options));
3873
- var summarizeVoiceTrace = (events) => {
3874
- const sorted = filterVoiceTraceEvents(events);
3875
- const firstEvent = sorted[0];
3876
- const lastEvent = sorted.at(-1);
3877
- const lifecycleEvents = sorted.filter((event) => event.type === "call.lifecycle");
3878
- const startEvent = lifecycleEvents.find((event) => event.payload.type === "start");
3879
- const endEvent = lifecycleEvents.toReversed().find((event) => event.payload.type === "end");
3880
- const costEvents = sorted.filter((event) => event.type === "turn.cost");
3881
- const toolEvents = sorted.filter((event) => event.type === "agent.tool");
3882
- const startedAt = startEvent?.at ?? firstEvent?.at;
3883
- const endedAt = endEvent?.at ?? lastEvent?.at;
3884
- const failed = sorted.some((event) => event.type === "session.error") || endEvent?.payload.disposition === "failed";
3885
- return {
3886
- assistantReplyCount: sorted.filter((event) => event.type === "turn.assistant").length,
3887
- callDurationMs: startedAt !== undefined && endedAt !== undefined ? Math.max(0, endedAt - startedAt) : undefined,
3888
- cost: {
3889
- estimatedRelativeCostUnits: costEvents.reduce((total, event) => total + toNumber(event.payload.estimatedRelativeCostUnits), 0),
3890
- totalBillableAudioMs: costEvents.reduce((total, event) => total + toNumber(event.payload.totalBillableAudioMs), 0)
3891
- },
3892
- endedAt,
3893
- errorCount: sorted.filter((event) => event.type === "session.error").length,
3894
- eventCount: sorted.length,
3895
- failed,
3896
- handoffCount: sorted.filter((event) => event.type === "agent.handoff").length,
3897
- modelCallCount: sorted.filter((event) => event.type === "agent.model").length,
3898
- sessionId: firstEvent?.sessionId,
3899
- startedAt,
3900
- toolCallCount: toolEvents.length,
3901
- toolErrorCount: toolEvents.filter((event) => event.payload.status === "error").length,
3902
- traceId: firstEvent?.traceId,
3903
- transcriptCount: sorted.filter((event) => event.type === "turn.transcript").length,
3904
- turnCount: sorted.filter((event) => event.type === "turn.committed").length
3905
- };
3906
- };
3907
3860
  var evaluateVoiceTrace = (events, options = {}) => {
3908
3861
  const summary = summarizeVoiceTrace(events);
3909
3862
  const issues = [];
@@ -3973,12 +3926,59 @@ var evaluateVoiceTrace = (events, options = {}) => {
3973
3926
  summary
3974
3927
  };
3975
3928
  };
3976
- var renderTraceEventMarkdown = (event, startedAt) => {
3977
- const offset = startedAt === undefined ? `${event.at}` : `+${Math.max(0, event.at - startedAt)}ms`;
3978
- const label = `- ${offset} [${event.type}]`;
3979
- switch (event.type) {
3980
- case "turn.transcript":
3981
- return `${label} ${event.payload.isFinal ? "final" : "partial"} "${formatTraceValue(event.payload.text)}"`;
3929
+ var redactVoiceTraceEvent = (event, options = {}) => {
3930
+ const resolved = resolveVoiceTraceRedactionOptions(options);
3931
+ return {
3932
+ ...event,
3933
+ metadata: redactTraceValue(event.metadata, resolved, [
3934
+ "metadata"
3935
+ ]),
3936
+ payload: redactTraceValue(event.payload, resolved, [
3937
+ "payload"
3938
+ ])
3939
+ };
3940
+ };
3941
+ var redactVoiceTraceEvents = (events, options = {}) => events.map((event) => redactVoiceTraceEvent(event, options));
3942
+ var summarizeVoiceTrace = (events) => {
3943
+ const sorted = filterVoiceTraceEvents(events);
3944
+ const firstEvent = sorted[0];
3945
+ const lastEvent = sorted.at(-1);
3946
+ const lifecycleEvents = sorted.filter((event) => event.type === "call.lifecycle");
3947
+ const startEvent = lifecycleEvents.find((event) => event.payload.type === "start");
3948
+ const endEvent = lifecycleEvents.toReversed().find((event) => event.payload.type === "end");
3949
+ const costEvents = sorted.filter((event) => event.type === "turn.cost");
3950
+ const toolEvents = sorted.filter((event) => event.type === "agent.tool");
3951
+ const startedAt = startEvent?.at ?? firstEvent?.at;
3952
+ const endedAt = endEvent?.at ?? lastEvent?.at;
3953
+ const failed = sorted.some((event) => event.type === "session.error") || endEvent?.payload.disposition === "failed";
3954
+ return {
3955
+ assistantReplyCount: sorted.filter((event) => event.type === "turn.assistant").length,
3956
+ callDurationMs: startedAt !== undefined && endedAt !== undefined ? Math.max(0, endedAt - startedAt) : undefined,
3957
+ cost: {
3958
+ estimatedRelativeCostUnits: costEvents.reduce((total, event) => total + toNumber(event.payload.estimatedRelativeCostUnits), 0),
3959
+ totalBillableAudioMs: costEvents.reduce((total, event) => total + toNumber(event.payload.totalBillableAudioMs), 0)
3960
+ },
3961
+ endedAt,
3962
+ errorCount: sorted.filter((event) => event.type === "session.error").length,
3963
+ eventCount: sorted.length,
3964
+ failed,
3965
+ handoffCount: sorted.filter((event) => event.type === "agent.handoff").length,
3966
+ modelCallCount: sorted.filter((event) => event.type === "agent.model").length,
3967
+ sessionId: firstEvent?.sessionId,
3968
+ startedAt,
3969
+ toolCallCount: toolEvents.length,
3970
+ toolErrorCount: toolEvents.filter((event) => event.payload.status === "error").length,
3971
+ traceId: firstEvent?.traceId,
3972
+ transcriptCount: sorted.filter((event) => event.type === "turn.transcript").length,
3973
+ turnCount: sorted.filter((event) => event.type === "turn.committed").length
3974
+ };
3975
+ };
3976
+ var renderTraceEventMarkdown = (event, startedAt) => {
3977
+ const offset = startedAt === undefined ? `${event.at}` : `+${Math.max(0, event.at - startedAt)}ms`;
3978
+ const label = `- ${offset} [${event.type}]`;
3979
+ switch (event.type) {
3980
+ case "turn.transcript":
3981
+ return `${label} ${event.payload.isFinal ? "final" : "partial"} "${formatTraceValue(event.payload.text)}"`;
3982
3982
  case "turn.committed":
3983
3983
  return `${label} committed "${formatTraceValue(event.payload.text)}"`;
3984
3984
  case "turn.assistant":
@@ -3997,40 +3997,12 @@ var renderTraceEventMarkdown = (event, startedAt) => {
3997
3997
  return `${label} ${formatTraceValue(event.payload)}`;
3998
3998
  }
3999
3999
  };
4000
- var renderVoiceTraceMarkdown = (events, options = {}) => {
4001
- const sorted = filterVoiceTraceEvents(options.redact ? redactVoiceTraceEvents(events, options.redact) : events);
4002
- const summary = summarizeVoiceTrace(sorted);
4003
- const evaluation = evaluateVoiceTrace(sorted, options.evaluation);
4004
- const lines = [
4005
- `# ${options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim()}`,
4006
- "",
4007
- `Pass: ${evaluation.pass ? "yes" : "no"}`,
4008
- `Session: ${summary.sessionId ?? "unknown"}`,
4009
- `Events: ${summary.eventCount}`,
4010
- `Turns: ${summary.turnCount}`,
4011
- `Transcripts: ${summary.transcriptCount}`,
4012
- `Assistant replies: ${summary.assistantReplyCount}`,
4013
- `Model calls: ${summary.modelCallCount}`,
4014
- `Tool calls: ${summary.toolCallCount}`,
4015
- `Handoffs: ${summary.handoffCount}`,
4016
- `Errors: ${summary.errorCount}`,
4017
- `Estimated cost units: ${summary.cost.estimatedRelativeCostUnits}`,
4018
- ""
4019
- ];
4020
- if (evaluation.issues.length > 0) {
4021
- lines.push("## Issues", "");
4022
- for (const issue of evaluation.issues) {
4023
- lines.push(`- [${issue.severity}] ${issue.code}: ${issue.message}`);
4024
- }
4025
- lines.push("");
4026
- }
4027
- lines.push("## Timeline", "");
4028
- for (const event of sorted) {
4029
- lines.push(renderTraceEventMarkdown(event, summary.startedAt));
4030
- }
4031
- return lines.join(`
4032
- `);
4033
- };
4000
+ var buildVoiceTraceReplay = (events, options = {}) => ({
4001
+ evaluation: evaluateVoiceTrace(options.redact ? redactVoiceTraceEvents(events, options.redact) : events, options.evaluation),
4002
+ html: renderVoiceTraceHTML(events, options),
4003
+ markdown: renderVoiceTraceMarkdown(events, options),
4004
+ summary: summarizeVoiceTrace(options.redact ? redactVoiceTraceEvents(events, options.redact) : events)
4005
+ });
4034
4006
  var renderVoiceTraceHTML = (events, options = {}) => {
4035
4007
  const markdown = renderVoiceTraceMarkdown(events, options);
4036
4008
  const renderEvents = options.redact ? redactVoiceTraceEvents(events, options.redact) : events;
@@ -4087,12 +4059,40 @@ var renderVoiceTraceHTML = (events, options = {}) => {
4087
4059
  ].join(`
4088
4060
  `);
4089
4061
  };
4090
- var buildVoiceTraceReplay = (events, options = {}) => ({
4091
- evaluation: evaluateVoiceTrace(options.redact ? redactVoiceTraceEvents(events, options.redact) : events, options.evaluation),
4092
- html: renderVoiceTraceHTML(events, options),
4093
- markdown: renderVoiceTraceMarkdown(events, options),
4094
- summary: summarizeVoiceTrace(options.redact ? redactVoiceTraceEvents(events, options.redact) : events)
4095
- });
4062
+ var renderVoiceTraceMarkdown = (events, options = {}) => {
4063
+ const sorted = filterVoiceTraceEvents(options.redact ? redactVoiceTraceEvents(events, options.redact) : events);
4064
+ const summary = summarizeVoiceTrace(sorted);
4065
+ const evaluation = evaluateVoiceTrace(sorted, options.evaluation);
4066
+ const lines = [
4067
+ `# ${options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim()}`,
4068
+ "",
4069
+ `Pass: ${evaluation.pass ? "yes" : "no"}`,
4070
+ `Session: ${summary.sessionId ?? "unknown"}`,
4071
+ `Events: ${summary.eventCount}`,
4072
+ `Turns: ${summary.turnCount}`,
4073
+ `Transcripts: ${summary.transcriptCount}`,
4074
+ `Assistant replies: ${summary.assistantReplyCount}`,
4075
+ `Model calls: ${summary.modelCallCount}`,
4076
+ `Tool calls: ${summary.toolCallCount}`,
4077
+ `Handoffs: ${summary.handoffCount}`,
4078
+ `Errors: ${summary.errorCount}`,
4079
+ `Estimated cost units: ${summary.cost.estimatedRelativeCostUnits}`,
4080
+ ""
4081
+ ];
4082
+ if (evaluation.issues.length > 0) {
4083
+ lines.push("## Issues", "");
4084
+ for (const issue of evaluation.issues) {
4085
+ lines.push(`- [${issue.severity}] ${issue.code}: ${issue.message}`);
4086
+ }
4087
+ lines.push("");
4088
+ }
4089
+ lines.push("## Timeline", "");
4090
+ for (const event of sorted) {
4091
+ lines.push(renderTraceEventMarkdown(event, summary.startedAt));
4092
+ }
4093
+ return lines.join(`
4094
+ `);
4095
+ };
4096
4096
 
4097
4097
  // src/core/liveOps.ts
4098
4098
  var VOICE_LIVE_OPS_ACTIONS = [
@@ -4116,12 +4116,171 @@ var findMissing = (values, required) => {
4116
4116
  const valueSet = new Set(values);
4117
4117
  return required.filter((value) => !valueSet.has(value));
4118
4118
  };
4119
+ var assertVoiceLiveOpsControlEvidence = (input = {}) => assertVoiceEvidence("Voice live-ops control evidence assertion failed", evaluateVoiceLiveOpsControlEvidence(input));
4120
+ var assertVoiceLiveOpsEvidence = (input = {}) => assertVoiceEvidence("Voice live-ops evidence assertion failed", evaluateVoiceLiveOpsEvidence(input));
4121
+ var buildVoiceLiveOpsControlState = (input) => ({
4122
+ assistantPaused: input.action === "pause-assistant" || input.action === "operator-takeover" || input.action === "force-handoff" ? true : input.action === "resume-assistant" ? false : input.previous?.assistantPaused ?? false,
4123
+ handoffTarget: input.action === "force-handoff" ? input.tag : input.previous?.handoffTarget,
4124
+ injectedInstruction: input.action === "inject-instruction" ? input.detail : input.previous?.injectedInstruction,
4125
+ lastAction: input.action,
4126
+ lastUpdatedAt: input.at ?? Date.now(),
4127
+ operator: input.assignee,
4128
+ operatorTakeover: input.action === "operator-takeover" ? true : input.action === "resume-assistant" ? false : input.previous?.operatorTakeover ?? false,
4129
+ status: getVoiceLiveOpsControlStatus(input.action),
4130
+ tag: input.tag
4131
+ });
4132
+ var createVoiceLiveOpsController = (options = {}) => {
4133
+ const store = options.store ?? createVoiceMemoryLiveOpsControlStore();
4134
+ const perform = async (input) => {
4135
+ if (!input.sessionId) {
4136
+ throw new Error("Voice live ops action requires sessionId.");
4137
+ }
4138
+ if (!isVoiceLiveOpsAction(input.action)) {
4139
+ throw new Error("Voice live ops action is not supported.");
4140
+ }
4141
+ const at = Date.now();
4142
+ const assignee = input.assignee ?? options.defaultAssignee ?? "operator";
4143
+ const tag = input.tag ?? options.defaultTag ?? "live-ops";
4144
+ const detail = input.detail ?? options.defaultDetail ?? input.action;
4145
+ const previous = await store.get(input.sessionId);
4146
+ const control = buildVoiceLiveOpsControlState({
4147
+ ...input,
4148
+ assignee,
4149
+ at,
4150
+ detail,
4151
+ previous,
4152
+ tag
4153
+ });
4154
+ await store.set(input.sessionId, control);
4155
+ const traceId = `voice-live-ops:${input.sessionId}:${input.action}:${at}`;
4156
+ await Promise.all([
4157
+ options.audit?.append(createVoiceAuditEvent({
4158
+ action: `voice.live_ops.${input.action}`,
4159
+ actor: {
4160
+ id: assignee,
4161
+ kind: "operator",
4162
+ name: assignee
4163
+ },
4164
+ at,
4165
+ metadata: {
4166
+ source: "voice-live-ops",
4167
+ tag
4168
+ },
4169
+ outcome: "success",
4170
+ payload: {
4171
+ action: input.action,
4172
+ assignee,
4173
+ control,
4174
+ detail,
4175
+ tag
4176
+ },
4177
+ resource: {
4178
+ id: input.sessionId,
4179
+ type: "voice.session"
4180
+ },
4181
+ sessionId: input.sessionId,
4182
+ traceId,
4183
+ type: "operator.action"
4184
+ })),
4185
+ options.trace?.append(createVoiceTraceEvent({
4186
+ at,
4187
+ metadata: {
4188
+ source: "voice-live-ops",
4189
+ tag
4190
+ },
4191
+ payload: {
4192
+ action: input.action,
4193
+ assignee,
4194
+ control,
4195
+ detail,
4196
+ status: "success",
4197
+ tag
4198
+ },
4199
+ sessionId: input.sessionId,
4200
+ traceId,
4201
+ type: "operator.action"
4202
+ }))
4203
+ ]);
4204
+ const result = {
4205
+ action: input.action,
4206
+ control,
4207
+ ok: true,
4208
+ sessionId: input.sessionId
4209
+ };
4210
+ await options.onAction?.({
4211
+ ...result,
4212
+ assignee,
4213
+ detail,
4214
+ tag
4215
+ });
4216
+ return result;
4217
+ };
4218
+ return {
4219
+ perform,
4220
+ store,
4221
+ get: (sessionId) => store.get(sessionId)
4222
+ };
4223
+ };
4224
+ var createVoiceMemoryLiveOpsControlStore = () => {
4225
+ const states = new Map;
4226
+ return {
4227
+ get: (sessionId) => states.get(sessionId),
4228
+ set: (sessionId, state) => {
4229
+ states.set(sessionId, state);
4230
+ }
4231
+ };
4232
+ };
4233
+ var evaluateVoiceLiveOpsControlEvidence = (input = {}) => {
4234
+ const issues = [];
4235
+ const results = (input.results ?? []).filter((result) => Boolean(result));
4236
+ const controls = results.map((result) => result.control).filter((control) => Boolean(control));
4237
+ const finalControl = input.finalControl ?? controls.at(-1);
4238
+ const actions = uniqueSorted(results.map((result) => result.action).filter((action) => isVoiceLiveOpsAction(action)));
4239
+ const statuses = uniqueSorted(controls.map((control) => control.status));
4240
+ const failedActions = results.filter((result) => result.ok === false).length;
4241
+ if (results.length === 0) {
4242
+ issues.push("Expected live-ops control action result(s) to be present.");
4243
+ }
4244
+ if (input.minSnapshots !== undefined && controls.length < input.minSnapshots) {
4245
+ issues.push(`Expected at least ${String(input.minSnapshots)} live-ops control snapshot(s), found ${String(controls.length)}.`);
4246
+ }
4247
+ if (input.maxFailedActions !== undefined && failedActions > input.maxFailedActions) {
4248
+ issues.push(`Expected at most ${String(input.maxFailedActions)} failed live-ops control action(s), found ${String(failedActions)}.`);
4249
+ }
4250
+ for (const action of findMissing(actions, input.requiredActions)) {
4251
+ issues.push(`Missing live-ops control action: ${action}.`);
4252
+ }
4253
+ for (const status of findMissing(statuses, input.requiredStatuses)) {
4254
+ issues.push(`Missing live-ops control status: ${status}.`);
4255
+ }
4256
+ if (!finalControl) {
4257
+ issues.push("Expected final live-ops control state to be present.");
4258
+ } else {
4259
+ if (input.requireFinalAssistantPaused !== undefined && finalControl.assistantPaused !== input.requireFinalAssistantPaused) {
4260
+ issues.push(`Expected final live-ops assistantPaused ${String(input.requireFinalAssistantPaused)}, found ${String(finalControl.assistantPaused)}.`);
4261
+ }
4262
+ if (input.requireFinalOperatorTakeover !== undefined && finalControl.operatorTakeover !== input.requireFinalOperatorTakeover) {
4263
+ issues.push(`Expected final live-ops operatorTakeover ${String(input.requireFinalOperatorTakeover)}, found ${String(finalControl.operatorTakeover)}.`);
4264
+ }
4265
+ }
4266
+ return {
4267
+ actionCount: results.length,
4268
+ actions,
4269
+ failedActions,
4270
+ finalControl: finalControl ?? undefined,
4271
+ finalStatus: finalControl?.status,
4272
+ issues,
4273
+ ok: issues.length === 0,
4274
+ snapshots: controls.length,
4275
+ statuses
4276
+ };
4277
+ };
4119
4278
  var evaluateVoiceLiveOpsEvidence = (input = {}) => {
4120
4279
  const issues = [];
4121
- const actionHistory = input.actionHistory;
4122
- const opsRecovery = input.opsRecovery;
4123
- const opsStatus = input.opsStatus;
4124
- const operationsRecord = input.operationsRecord;
4280
+ const { actionHistory } = input;
4281
+ const { opsRecovery } = input;
4282
+ const { opsStatus } = input;
4283
+ const { operationsRecord } = input;
4125
4284
  const historyActions = uniqueSorted(actionHistory?.entries.map((entry) => entry.actionId) ?? []);
4126
4285
  const interventionActions = uniqueSorted(opsRecovery?.interventions.events.map((event) => event.action).filter((action) => Boolean(action)) ?? []);
4127
4286
  const requireActionHistory = input.requireActionHistory ?? true;
@@ -4179,79 +4338,19 @@ var evaluateVoiceLiveOpsEvidence = (input = {}) => {
4179
4338
  issues.push(`Expected at least ${String(input.minOperationsRecordTasks)} operations-record task(s), found ${String(operationsRecord.tasks?.total ?? 0)}.`);
4180
4339
  }
4181
4340
  return {
4182
- actionHistoryFailed: actionHistory?.failed,
4183
- actionHistoryTotal: actionHistory?.total,
4184
- historyActions,
4185
- interventionActions,
4186
- interventions: opsRecovery?.interventions.total,
4187
- issues,
4188
- ok: issues.length === 0,
4189
- operationsRecordHandoffs: operationsRecord?.handoffs.length,
4190
- operationsRecordStatus: operationsRecord?.status,
4191
- operationsRecordTasks: operationsRecord?.tasks?.total,
4192
- opsRecoveryIssues: opsRecovery?.issues.length,
4193
- opsRecoveryStatus: opsRecovery?.status,
4194
- opsStatus: opsStatus?.status
4195
- };
4196
- };
4197
- var assertVoiceLiveOpsEvidence = (input = {}) => {
4198
- return assertVoiceEvidence("Voice live-ops evidence assertion failed", evaluateVoiceLiveOpsEvidence(input));
4199
- };
4200
- var evaluateVoiceLiveOpsControlEvidence = (input = {}) => {
4201
- const issues = [];
4202
- const results = (input.results ?? []).filter((result) => Boolean(result));
4203
- const controls = results.map((result) => result.control).filter((control) => Boolean(control));
4204
- const finalControl = input.finalControl ?? controls.at(-1);
4205
- const actions = uniqueSorted(results.map((result) => result.action).filter((action) => isVoiceLiveOpsAction(action)));
4206
- const statuses = uniqueSorted(controls.map((control) => control.status));
4207
- const failedActions = results.filter((result) => result.ok === false).length;
4208
- if (results.length === 0) {
4209
- issues.push("Expected live-ops control action result(s) to be present.");
4210
- }
4211
- if (input.minSnapshots !== undefined && controls.length < input.minSnapshots) {
4212
- issues.push(`Expected at least ${String(input.minSnapshots)} live-ops control snapshot(s), found ${String(controls.length)}.`);
4213
- }
4214
- if (input.maxFailedActions !== undefined && failedActions > input.maxFailedActions) {
4215
- issues.push(`Expected at most ${String(input.maxFailedActions)} failed live-ops control action(s), found ${String(failedActions)}.`);
4216
- }
4217
- for (const action of findMissing(actions, input.requiredActions)) {
4218
- issues.push(`Missing live-ops control action: ${action}.`);
4219
- }
4220
- for (const status of findMissing(statuses, input.requiredStatuses)) {
4221
- issues.push(`Missing live-ops control status: ${status}.`);
4222
- }
4223
- if (!finalControl) {
4224
- issues.push("Expected final live-ops control state to be present.");
4225
- } else {
4226
- if (input.requireFinalAssistantPaused !== undefined && finalControl.assistantPaused !== input.requireFinalAssistantPaused) {
4227
- issues.push(`Expected final live-ops assistantPaused ${String(input.requireFinalAssistantPaused)}, found ${String(finalControl.assistantPaused)}.`);
4228
- }
4229
- if (input.requireFinalOperatorTakeover !== undefined && finalControl.operatorTakeover !== input.requireFinalOperatorTakeover) {
4230
- issues.push(`Expected final live-ops operatorTakeover ${String(input.requireFinalOperatorTakeover)}, found ${String(finalControl.operatorTakeover)}.`);
4231
- }
4232
- }
4233
- return {
4234
- actionCount: results.length,
4235
- actions,
4236
- failedActions,
4237
- finalControl: finalControl ?? undefined,
4238
- finalStatus: finalControl?.status,
4239
- issues,
4240
- ok: issues.length === 0,
4241
- snapshots: controls.length,
4242
- statuses
4243
- };
4244
- };
4245
- var assertVoiceLiveOpsControlEvidence = (input = {}) => {
4246
- return assertVoiceEvidence("Voice live-ops control evidence assertion failed", evaluateVoiceLiveOpsControlEvidence(input));
4247
- };
4248
- var createVoiceMemoryLiveOpsControlStore = () => {
4249
- const states = new Map;
4250
- return {
4251
- get: (sessionId) => states.get(sessionId),
4252
- set: (sessionId, state) => {
4253
- states.set(sessionId, state);
4254
- }
4341
+ actionHistoryFailed: actionHistory?.failed,
4342
+ actionHistoryTotal: actionHistory?.total,
4343
+ historyActions,
4344
+ interventionActions,
4345
+ interventions: opsRecovery?.interventions.total,
4346
+ issues,
4347
+ ok: issues.length === 0,
4348
+ operationsRecordHandoffs: operationsRecord?.handoffs.length,
4349
+ operationsRecordStatus: operationsRecord?.status,
4350
+ operationsRecordTasks: operationsRecord?.tasks?.total,
4351
+ opsRecoveryIssues: opsRecovery?.issues.length,
4352
+ opsRecoveryStatus: opsRecovery?.status,
4353
+ opsStatus: opsStatus?.status
4255
4354
  };
4256
4355
  };
4257
4356
  var getVoiceLiveOpsControlStatus = (action) => {
@@ -4270,116 +4369,13 @@ var getVoiceLiveOpsControlStatus = (action) => {
4270
4369
  return "recorded";
4271
4370
  }
4272
4371
  };
4273
- var buildVoiceLiveOpsControlState = (input) => ({
4274
- assistantPaused: input.action === "pause-assistant" || input.action === "operator-takeover" || input.action === "force-handoff" ? true : input.action === "resume-assistant" ? false : input.previous?.assistantPaused ?? false,
4275
- handoffTarget: input.action === "force-handoff" ? input.tag : input.previous?.handoffTarget,
4276
- injectedInstruction: input.action === "inject-instruction" ? input.detail : input.previous?.injectedInstruction,
4277
- lastAction: input.action,
4278
- lastUpdatedAt: input.at ?? Date.now(),
4279
- operator: input.assignee,
4280
- operatorTakeover: input.action === "operator-takeover" ? true : input.action === "resume-assistant" ? false : input.previous?.operatorTakeover ?? false,
4281
- status: getVoiceLiveOpsControlStatus(input.action),
4282
- tag: input.tag
4283
- });
4284
- var createVoiceLiveOpsController = (options = {}) => {
4285
- const store = options.store ?? createVoiceMemoryLiveOpsControlStore();
4286
- const perform = async (input) => {
4287
- if (!input.sessionId) {
4288
- throw new Error("Voice live ops action requires sessionId.");
4289
- }
4290
- if (!isVoiceLiveOpsAction(input.action)) {
4291
- throw new Error("Voice live ops action is not supported.");
4292
- }
4293
- const at = Date.now();
4294
- const assignee = input.assignee ?? options.defaultAssignee ?? "operator";
4295
- const tag = input.tag ?? options.defaultTag ?? "live-ops";
4296
- const detail = input.detail ?? options.defaultDetail ?? input.action;
4297
- const previous = await store.get(input.sessionId);
4298
- const control = buildVoiceLiveOpsControlState({
4299
- ...input,
4300
- assignee,
4301
- at,
4302
- detail,
4303
- previous,
4304
- tag
4305
- });
4306
- await store.set(input.sessionId, control);
4307
- const traceId = `voice-live-ops:${input.sessionId}:${input.action}:${at}`;
4308
- await Promise.all([
4309
- options.audit?.append(createVoiceAuditEvent({
4310
- action: `voice.live_ops.${input.action}`,
4311
- actor: {
4312
- id: assignee,
4313
- kind: "operator",
4314
- name: assignee
4315
- },
4316
- at,
4317
- metadata: {
4318
- source: "voice-live-ops",
4319
- tag
4320
- },
4321
- outcome: "success",
4322
- payload: {
4323
- action: input.action,
4324
- assignee,
4325
- control,
4326
- detail,
4327
- tag
4328
- },
4329
- resource: {
4330
- id: input.sessionId,
4331
- type: "voice.session"
4332
- },
4333
- sessionId: input.sessionId,
4334
- traceId,
4335
- type: "operator.action"
4336
- })),
4337
- options.trace?.append(createVoiceTraceEvent({
4338
- at,
4339
- metadata: {
4340
- source: "voice-live-ops",
4341
- tag
4342
- },
4343
- payload: {
4344
- action: input.action,
4345
- assignee,
4346
- control,
4347
- detail,
4348
- status: "success",
4349
- tag
4350
- },
4351
- sessionId: input.sessionId,
4352
- traceId,
4353
- type: "operator.action"
4354
- }))
4355
- ]);
4356
- const result = {
4357
- action: input.action,
4358
- control,
4359
- ok: true,
4360
- sessionId: input.sessionId
4361
- };
4362
- await options.onAction?.({
4363
- ...result,
4364
- assignee,
4365
- detail,
4366
- tag
4367
- });
4368
- return result;
4369
- };
4370
- return {
4371
- get: (sessionId) => store.get(sessionId),
4372
- perform,
4373
- store
4374
- };
4375
- };
4376
4372
  var readVoiceLiveOpsActionInput = async (request) => {
4377
4373
  const body = await request.json().catch(() => null);
4378
4374
  if (!body || typeof body !== "object") {
4379
4375
  throw new Error("Voice live ops action requires a JSON body.");
4380
4376
  }
4381
4377
  const record = body;
4382
- const action = record.action;
4378
+ const { action } = record;
4383
4379
  const sessionId = toStringValue(record.sessionId);
4384
4380
  if (!sessionId || !isVoiceLiveOpsAction(action)) {
4385
4381
  throw new Error("Voice live ops action requires valid sessionId and action.");
@@ -4409,7 +4405,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
4409
4405
  };
4410
4406
  }
4411
4407
  }).get(controlPath, async ({ params }) => {
4412
- const sessionId = params.sessionId;
4408
+ const { sessionId } = params;
4413
4409
  return {
4414
4410
  control: await controller.get(sessionId),
4415
4411
  ok: true,
@@ -4437,23 +4433,25 @@ var createVoiceLiveOpsInput = (action, input) => ({
4437
4433
  sessionId: input.sessionId ?? "",
4438
4434
  tag: input.tag
4439
4435
  });
4440
- var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
4441
- const sessionId = options.getSessionId?.() ?? "";
4442
- const disabled = snapshot.isRunning || !sessionId;
4443
- const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml(action)}"${disabled ? " disabled" : ""}>${escapeHtml(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
4444
- const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml(snapshot.lastResult.action)}. Control: ${escapeHtml(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
4445
- return `<section class="absolute-voice-live-ops">
4446
- <header class="absolute-voice-live-ops__header">
4447
- <span>${escapeHtml(options.title ?? "Live Ops")}</span>
4448
- <strong>${escapeHtml(sessionId || "No active session")}</strong>
4449
- </header>
4450
- <p class="absolute-voice-live-ops__description">${escapeHtml(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
4451
- <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml(options.defaultAssignee ?? "operator")}" /></label>
4452
- <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml(options.defaultTag ?? "live-ops")}" /></label>
4453
- <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
4454
- <div class="absolute-voice-live-ops__actions">${actions}</div>
4455
- ${result}
4456
- </section>`;
4436
+ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options = {}) => {
4437
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
4438
+ return;
4439
+ }
4440
+ customElements.define(tagName, class AbsoluteVoiceLiveOpsElement extends HTMLElement {
4441
+ mounted;
4442
+ connectedCallback() {
4443
+ this.mounted = mountVoiceLiveOps(this, {
4444
+ ...options,
4445
+ description: this.getAttribute("description") ?? options.description,
4446
+ getSessionId: options.getSessionId ?? (() => this.getAttribute("session-id") ?? undefined),
4447
+ title: this.getAttribute("title") ?? options.title
4448
+ });
4449
+ }
4450
+ disconnectedCallback() {
4451
+ this.mounted?.close();
4452
+ this.mounted = undefined;
4453
+ }
4454
+ });
4457
4455
  };
4458
4456
  var getVoiceLiveOpsCSS = () => `.absolute-voice-live-ops{border:1px solid #f59e0b66;border-radius:20px;background:#111827;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-live-ops__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-live-ops__header span{color:#fbbf24;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-live-ops__header strong{font-size:18px;overflow-wrap:anywhere}.absolute-voice-live-ops__description,.absolute-voice-live-ops__result{color:#cbd5e1}.absolute-voice-live-ops label{display:grid;gap:6px;margin-top:12px}.absolute-voice-live-ops label span{color:#94a3b8;font-size:13px}.absolute-voice-live-ops input{background:#020617;border:1px solid #f59e0b66;border-radius:12px;color:#f8fafc;font:inherit;padding:10px 12px}.absolute-voice-live-ops__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-live-ops__actions button{background:#f59e0b;border:0;border-radius:999px;color:#111827;cursor:pointer;font:inherit;font-weight:900;padding:8px 12px}.absolute-voice-live-ops__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-live-ops__error{color:#fecaca;font-weight:800}`;
4459
4457
  var mountVoiceLiveOps = (element, options = {}) => {
@@ -4486,7 +4484,7 @@ var mountVoiceLiveOps = (element, options = {}) => {
4486
4484
  const unsubscribe = store.subscribe(render);
4487
4485
  const handleInput = () => syncInputs();
4488
4486
  const handleClick = (event) => {
4489
- const target = event.target;
4487
+ const { target } = event;
4490
4488
  if (!(target instanceof Element)) {
4491
4489
  return;
4492
4490
  }
@@ -4507,34 +4505,32 @@ var mountVoiceLiveOps = (element, options = {}) => {
4507
4505
  element.addEventListener?.("input", handleInput);
4508
4506
  render();
4509
4507
  return {
4508
+ run: store.run,
4510
4509
  close: () => {
4511
4510
  element.removeEventListener?.("click", handleClick);
4512
4511
  element.removeEventListener?.("input", handleInput);
4513
4512
  unsubscribe();
4514
4513
  store.close();
4515
- },
4516
- run: store.run
4514
+ }
4517
4515
  };
4518
4516
  };
4519
- var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options = {}) => {
4520
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
4521
- return;
4522
- }
4523
- customElements.define(tagName, class AbsoluteVoiceLiveOpsElement extends HTMLElement {
4524
- mounted;
4525
- connectedCallback() {
4526
- this.mounted = mountVoiceLiveOps(this, {
4527
- ...options,
4528
- description: this.getAttribute("description") ?? options.description,
4529
- getSessionId: options.getSessionId ?? (() => this.getAttribute("session-id") ?? undefined),
4530
- title: this.getAttribute("title") ?? options.title
4531
- });
4532
- }
4533
- disconnectedCallback() {
4534
- this.mounted?.close();
4535
- this.mounted = undefined;
4536
- }
4537
- });
4517
+ var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
4518
+ const sessionId = options.getSessionId?.() ?? "";
4519
+ const disabled = snapshot.isRunning || !sessionId;
4520
+ const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml(action)}"${disabled ? " disabled" : ""}>${escapeHtml(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
4521
+ const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml(snapshot.lastResult.action)}. Control: ${escapeHtml(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
4522
+ return `<section class="absolute-voice-live-ops">
4523
+ <header class="absolute-voice-live-ops__header">
4524
+ <span>${escapeHtml(options.title ?? "Live Ops")}</span>
4525
+ <strong>${escapeHtml(sessionId || "No active session")}</strong>
4526
+ </header>
4527
+ <p class="absolute-voice-live-ops__description">${escapeHtml(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
4528
+ <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml(options.defaultAssignee ?? "operator")}" /></label>
4529
+ <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml(options.defaultTag ?? "live-ops")}" /></label>
4530
+ <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
4531
+ <div class="absolute-voice-live-ops__actions">${actions}</div>
4532
+ ${result}
4533
+ </section>`;
4538
4534
  };
4539
4535
 
4540
4536
  // src/svelte/createVoiceLiveOps.ts
@@ -4542,22 +4538,14 @@ var createVoiceLiveOps = (options = {}) => {
4542
4538
  const store = createVoiceLiveOpsStore(options);
4543
4539
  return {
4544
4540
  close: store.close,
4545
- getHTML: () => renderVoiceLiveOpsHTML(store.getSnapshot(), options),
4546
4541
  getSnapshot: store.getSnapshot,
4547
- mount: (element) => mountVoiceLiveOps(element, options),
4548
4542
  run: store.run,
4549
- subscribe: store.subscribe
4543
+ subscribe: store.subscribe,
4544
+ getHTML: () => renderVoiceLiveOpsHTML(store.getSnapshot(), options),
4545
+ mount: (element) => mountVoiceLiveOps(element, options)
4550
4546
  };
4551
4547
  };
4552
4548
  // src/client/opsStatus.ts
4553
- var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
4554
- const fetchImpl = options.fetch ?? globalThis.fetch;
4555
- const response = await fetchImpl(path);
4556
- if (!response.ok) {
4557
- throw new Error(`Voice ops status failed: HTTP ${response.status}`);
4558
- }
4559
- return await response.json();
4560
- };
4561
4549
  var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) => {
4562
4550
  const listeners = new Set;
4563
4551
  let closed = false;
@@ -4616,9 +4604,9 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
4616
4604
  }
4617
4605
  return {
4618
4606
  close,
4607
+ refresh,
4619
4608
  getServerSnapshot: () => snapshot,
4620
4609
  getSnapshot: () => snapshot,
4621
- refresh,
4622
4610
  subscribe: (listener) => {
4623
4611
  listeners.add(listener);
4624
4612
  return () => {
@@ -4627,6 +4615,14 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
4627
4615
  }
4628
4616
  };
4629
4617
  };
4618
+ var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
4619
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4620
+ const response = await fetchImpl(path);
4621
+ if (!response.ok) {
4622
+ throw new Error(`Voice ops status failed: HTTP ${response.status}`);
4623
+ }
4624
+ return await response.json();
4625
+ };
4630
4626
 
4631
4627
  // src/client/opsStatusWidget.ts
4632
4628
  var DEFAULT_TITLE3 = "Voice Ops Status";
@@ -4652,17 +4648,8 @@ var surfaceDetail = (surface) => {
4652
4648
  }
4653
4649
  return total > 0 ? `${total} passing${source}` : `No failures${source}`;
4654
4650
  };
4655
- var getVoiceOpsStatusLabel = (report, error) => {
4656
- if (error) {
4657
- return "Unavailable";
4658
- }
4659
- if (!report) {
4660
- return "Checking";
4661
- }
4662
- return report.status === "pass" ? "Passing" : "Needs attention";
4663
- };
4664
4651
  var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
4665
- const report = snapshot.report;
4652
+ const { report } = snapshot;
4666
4653
  const surfaces = Object.entries(report?.surfaces ?? {}).map(([id, surface]) => {
4667
4654
  const failed = readNumber(surface, "failed") || readNumber(surface, "degraded");
4668
4655
  const total = readNumber(surface, "total");
@@ -4690,6 +4677,53 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
4690
4677
  updatedAt: snapshot.updatedAt
4691
4678
  };
4692
4679
  };
4680
+ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
4681
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
4682
+ return;
4683
+ }
4684
+ customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
4685
+ mounted;
4686
+ connectedCallback() {
4687
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
4688
+ this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/api/voice/ops-status", {
4689
+ description: this.getAttribute("description") ?? undefined,
4690
+ includeLinks: this.getAttribute("include-links") !== "false",
4691
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
4692
+ title: this.getAttribute("title") ?? undefined
4693
+ });
4694
+ }
4695
+ disconnectedCallback() {
4696
+ this.mounted?.close();
4697
+ this.mounted = undefined;
4698
+ }
4699
+ });
4700
+ };
4701
+ var getVoiceOpsStatusCSS = () => `.absolute-voice-ops-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-ops-status--fail,.absolute-voice-ops-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-status__label{font-size:28px;line-height:1}.absolute-voice-ops-status__description{color:#514733;margin:12px 0 0}.absolute-voice-ops-status__summary,.absolute-voice-ops-status__links{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-status__summary span,.absolute-voice-ops-status__links a{border:1px solid #e6ddca;border-radius:999px;color:inherit;padding:6px 10px;text-decoration:none}.absolute-voice-ops-status__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-ops-status__surface{align-items:center;background:#fff;border:1px solid #eee4d2;border-radius:14px;display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.absolute-voice-ops-status__surface--fail{border-color:#f2a7a7}.absolute-voice-ops-status__surface span{color:#655944}.absolute-voice-ops-status__error{color:#9f1239;font-weight:700}`;
4702
+ var getVoiceOpsStatusLabel = (report, error) => {
4703
+ if (error) {
4704
+ return "Unavailable";
4705
+ }
4706
+ if (!report) {
4707
+ return "Checking";
4708
+ }
4709
+ return report.status === "pass" ? "Passing" : "Needs attention";
4710
+ };
4711
+ var mountVoiceOpsStatus = (element, path = "/api/voice/ops-status", options = {}) => {
4712
+ const store = createVoiceOpsStatusStore(path, options);
4713
+ const render = () => {
4714
+ element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
4715
+ };
4716
+ const unsubscribe = store.subscribe(render);
4717
+ render();
4718
+ store.refresh().catch(() => {});
4719
+ return {
4720
+ refresh: store.refresh,
4721
+ close: () => {
4722
+ unsubscribe();
4723
+ store.close();
4724
+ }
4725
+ };
4726
+ };
4693
4727
  var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
4694
4728
  const model = createVoiceOpsStatusViewModel(snapshot, options);
4695
4729
  const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
@@ -4713,66 +4747,20 @@ var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
4713
4747
  ${links}
4714
4748
  </section>`;
4715
4749
  };
4716
- var getVoiceOpsStatusCSS = () => `.absolute-voice-ops-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-ops-status--fail,.absolute-voice-ops-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-status__label{font-size:28px;line-height:1}.absolute-voice-ops-status__description{color:#514733;margin:12px 0 0}.absolute-voice-ops-status__summary,.absolute-voice-ops-status__links{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-status__summary span,.absolute-voice-ops-status__links a{border:1px solid #e6ddca;border-radius:999px;color:inherit;padding:6px 10px;text-decoration:none}.absolute-voice-ops-status__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-ops-status__surface{align-items:center;background:#fff;border:1px solid #eee4d2;border-radius:14px;display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.absolute-voice-ops-status__surface--fail{border-color:#f2a7a7}.absolute-voice-ops-status__surface span{color:#655944}.absolute-voice-ops-status__error{color:#9f1239;font-weight:700}`;
4717
- var mountVoiceOpsStatus = (element, path = "/api/voice/ops-status", options = {}) => {
4718
- const store = createVoiceOpsStatusStore(path, options);
4719
- const render = () => {
4720
- element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
4721
- };
4722
- const unsubscribe = store.subscribe(render);
4723
- render();
4724
- store.refresh().catch(() => {});
4725
- return {
4726
- close: () => {
4727
- unsubscribe();
4728
- store.close();
4729
- },
4730
- refresh: store.refresh
4731
- };
4732
- };
4733
- var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
4734
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
4735
- return;
4736
- }
4737
- customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
4738
- mounted;
4739
- connectedCallback() {
4740
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
4741
- this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/api/voice/ops-status", {
4742
- description: this.getAttribute("description") ?? undefined,
4743
- includeLinks: this.getAttribute("include-links") !== "false",
4744
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
4745
- title: this.getAttribute("title") ?? undefined
4746
- });
4747
- }
4748
- disconnectedCallback() {
4749
- this.mounted?.close();
4750
- this.mounted = undefined;
4751
- }
4752
- });
4753
- };
4754
4750
 
4755
4751
  // src/svelte/createVoiceOpsStatus.ts
4756
4752
  var createVoiceOpsStatus = (path = "/api/voice/ops-status", options = {}) => {
4757
4753
  const store = createVoiceOpsStatusStore(path, options);
4758
4754
  return {
4759
4755
  close: store.close,
4760
- getHTML: () => renderVoiceOpsStatusHTML(store.getSnapshot(), options),
4761
4756
  getSnapshot: store.getSnapshot,
4762
- getViewModel: () => createVoiceOpsStatusViewModel(store.getSnapshot(), options),
4763
4757
  refresh: store.refresh,
4764
- subscribe: store.subscribe
4758
+ subscribe: store.subscribe,
4759
+ getHTML: () => renderVoiceOpsStatusHTML(store.getSnapshot(), options),
4760
+ getViewModel: () => createVoiceOpsStatusViewModel(store.getSnapshot(), options)
4765
4761
  };
4766
4762
  };
4767
4763
  // src/client/platformCoverage.ts
4768
- var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
4769
- const fetchImpl = options.fetch ?? globalThis.fetch;
4770
- const response = await fetchImpl(path);
4771
- if (!response.ok) {
4772
- throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
4773
- }
4774
- return await response.json();
4775
- };
4776
4764
  var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
4777
4765
  const listeners = new Set;
4778
4766
  let closed = false;
@@ -4831,9 +4819,9 @@ var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", o
4831
4819
  }
4832
4820
  return {
4833
4821
  close,
4822
+ refresh,
4834
4823
  getServerSnapshot: () => snapshot,
4835
4824
  getSnapshot: () => snapshot,
4836
- refresh,
4837
4825
  subscribe: (listener) => {
4838
4826
  listeners.add(listener);
4839
4827
  return () => {
@@ -4842,6 +4830,14 @@ var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", o
4842
4830
  }
4843
4831
  };
4844
4832
  };
4833
+ var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
4834
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4835
+ const response = await fetchImpl(path);
4836
+ if (!response.ok) {
4837
+ throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
4838
+ }
4839
+ return await response.json();
4840
+ };
4845
4841
 
4846
4842
  // src/svelte/createVoicePlatformCoverage.ts
4847
4843
  var createVoicePlatformCoverage = (path = "/api/voice/platform-coverage", options = {}) => {
@@ -4854,14 +4850,6 @@ var createVoicePlatformCoverage = (path = "/api/voice/platform-coverage", option
4854
4850
  };
4855
4851
  };
4856
4852
  // src/client/proofTrends.ts
4857
- var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
4858
- const fetchImpl = options.fetch ?? globalThis.fetch;
4859
- const response = await fetchImpl(path);
4860
- if (!response.ok) {
4861
- throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
4862
- }
4863
- return await response.json();
4864
- };
4865
4853
  var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {}) => {
4866
4854
  const listeners = new Set;
4867
4855
  let closed = false;
@@ -4920,9 +4908,9 @@ var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {
4920
4908
  }
4921
4909
  return {
4922
4910
  close,
4911
+ refresh,
4923
4912
  getServerSnapshot: () => snapshot,
4924
4913
  getSnapshot: () => snapshot,
4925
- refresh,
4926
4914
  subscribe: (listener) => {
4927
4915
  listeners.add(listener);
4928
4916
  return () => {
@@ -4931,6 +4919,14 @@ var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {
4931
4919
  }
4932
4920
  };
4933
4921
  };
4922
+ var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
4923
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4924
+ const response = await fetchImpl(path);
4925
+ if (!response.ok) {
4926
+ throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
4927
+ }
4928
+ return await response.json();
4929
+ };
4934
4930
 
4935
4931
  // src/svelte/createVoiceProofTrends.ts
4936
4932
  var createVoiceProofTrends = (path = "/api/voice/proof-trends", options = {}) => {
@@ -4943,14 +4939,6 @@ var createVoiceProofTrends = (path = "/api/voice/proof-trends", options = {}) =>
4943
4939
  };
4944
4940
  };
4945
4941
  // src/client/reconnectProfileEvidence.ts
4946
- var fetchVoiceReconnectProfileEvidence = async (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
4947
- const fetchImpl = options.fetch ?? globalThis.fetch;
4948
- const response = await fetchImpl(path);
4949
- if (!response.ok) {
4950
- throw new Error(`Voice reconnect profile evidence failed: HTTP ${response.status}`);
4951
- }
4952
- return await response.json();
4953
- };
4954
4942
  var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
4955
4943
  const listeners = new Set;
4956
4944
  let closed = false;
@@ -5005,9 +4993,9 @@ var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-pro
5005
4993
  }
5006
4994
  return {
5007
4995
  close,
4996
+ refresh,
5008
4997
  getServerSnapshot: () => snapshot,
5009
4998
  getSnapshot: () => snapshot,
5010
- refresh,
5011
4999
  subscribe: (listener) => {
5012
5000
  listeners.add(listener);
5013
5001
  return () => {
@@ -5016,6 +5004,14 @@ var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-pro
5016
5004
  }
5017
5005
  };
5018
5006
  };
5007
+ var fetchVoiceReconnectProfileEvidence = async (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
5008
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5009
+ const response = await fetchImpl(path);
5010
+ if (!response.ok) {
5011
+ throw new Error(`Voice reconnect profile evidence failed: HTTP ${response.status}`);
5012
+ }
5013
+ return await response.json();
5014
+ };
5019
5015
 
5020
5016
  // src/svelte/createVoiceReconnectProfileEvidence.ts
5021
5017
  var createVoiceReconnectProfileEvidence = (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
@@ -5028,14 +5024,6 @@ var createVoiceReconnectProfileEvidence = (path = "/api/voice/reconnect-profile-
5028
5024
  };
5029
5025
  };
5030
5026
  // src/client/callDebugger.ts
5031
- var fetchVoiceCallDebugger = async (path, options = {}) => {
5032
- const fetchImpl = options.fetch ?? globalThis.fetch;
5033
- const response = await fetchImpl(path);
5034
- if (!response.ok) {
5035
- throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
5036
- }
5037
- return await response.json();
5038
- };
5039
5027
  var createVoiceCallDebuggerStore = (path, options = {}) => {
5040
5028
  const listeners = new Set;
5041
5029
  let closed = false;
@@ -5090,9 +5078,9 @@ var createVoiceCallDebuggerStore = (path, options = {}) => {
5090
5078
  }
5091
5079
  return {
5092
5080
  close,
5081
+ refresh,
5093
5082
  getServerSnapshot: () => snapshot,
5094
5083
  getSnapshot: () => snapshot,
5095
- refresh,
5096
5084
  subscribe: (listener) => {
5097
5085
  listeners.add(listener);
5098
5086
  return () => {
@@ -5101,6 +5089,14 @@ var createVoiceCallDebuggerStore = (path, options = {}) => {
5101
5089
  }
5102
5090
  };
5103
5091
  };
5092
+ var fetchVoiceCallDebugger = async (path, options = {}) => {
5093
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5094
+ const response = await fetchImpl(path);
5095
+ if (!response.ok) {
5096
+ throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
5097
+ }
5098
+ return await response.json();
5099
+ };
5104
5100
 
5105
5101
  // src/client/callDebuggerWidget.ts
5106
5102
  var DEFAULT_TITLE4 = "Call Debugger";
@@ -5119,7 +5115,7 @@ var resolveHref = (path, state, options) => {
5119
5115
  return options.href ?? defaultHref(path, state.report);
5120
5116
  };
5121
5117
  var createVoiceCallDebuggerLaunchViewModel = (path, state, options = {}) => {
5122
- const report = state.report;
5118
+ const { report } = state;
5123
5119
  const href = resolveHref(path, state, options);
5124
5120
  return {
5125
5121
  description: options.description ?? DEFAULT_DESCRIPTION4,
@@ -5155,39 +5151,6 @@ var createVoiceCallDebuggerLaunchViewModel = (path, state, options = {}) => {
5155
5151
  updatedAt: state.updatedAt
5156
5152
  };
5157
5153
  };
5158
- var renderVoiceCallDebuggerLaunchHTML = (path, state, options = {}) => {
5159
- const model = createVoiceCallDebuggerLaunchViewModel(path, state, options);
5160
- const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
5161
- <dt>${escapeHtml(row.label)}</dt>
5162
- <dd>${escapeHtml(row.value)}</dd>
5163
- </div>`).join("")}</dl>` : '<p class="absolute-voice-call-debugger-launch__empty">Load a call debugger report to see the latest support artifact.</p>';
5164
- return `<section class="absolute-voice-call-debugger-launch absolute-voice-call-debugger-launch--${escapeHtml(model.status)}">
5165
- <header class="absolute-voice-call-debugger-launch__header">
5166
- <span class="absolute-voice-call-debugger-launch__eyebrow">${escapeHtml(model.title)}</span>
5167
- <strong class="absolute-voice-call-debugger-launch__label">${escapeHtml(model.label)}</strong>
5168
- </header>
5169
- <p class="absolute-voice-call-debugger-launch__description">${escapeHtml(model.description)}</p>
5170
- <a class="absolute-voice-call-debugger-launch__link" href="${escapeHtml(model.href)}">${escapeHtml(options.linkLabel ?? DEFAULT_LINK_LABEL)}</a>
5171
- ${rows}
5172
- ${model.error ? `<p class="absolute-voice-call-debugger-launch__error">${escapeHtml(model.error)}</p>` : ""}
5173
- </section>`;
5174
- };
5175
- var mountVoiceCallDebuggerLaunch = (element, path, options = {}) => {
5176
- const store = createVoiceCallDebuggerStore(path, options);
5177
- const render = () => {
5178
- element.innerHTML = renderVoiceCallDebuggerLaunchHTML(path, store.getSnapshot(), options);
5179
- };
5180
- const unsubscribe = store.subscribe(render);
5181
- render();
5182
- store.refresh().catch(() => {});
5183
- return {
5184
- close: () => {
5185
- unsubscribe();
5186
- store.close();
5187
- },
5188
- refresh: store.refresh
5189
- };
5190
- };
5191
5154
  var defineVoiceCallDebuggerLaunchElement = (tagName = "absolute-voice-call-debugger-launch") => {
5192
5155
  if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
5193
5156
  return;
@@ -5210,6 +5173,39 @@ var defineVoiceCallDebuggerLaunchElement = (tagName = "absolute-voice-call-debug
5210
5173
  }
5211
5174
  });
5212
5175
  };
5176
+ var mountVoiceCallDebuggerLaunch = (element, path, options = {}) => {
5177
+ const store = createVoiceCallDebuggerStore(path, options);
5178
+ const render = () => {
5179
+ element.innerHTML = renderVoiceCallDebuggerLaunchHTML(path, store.getSnapshot(), options);
5180
+ };
5181
+ const unsubscribe = store.subscribe(render);
5182
+ render();
5183
+ store.refresh().catch(() => {});
5184
+ return {
5185
+ refresh: store.refresh,
5186
+ close: () => {
5187
+ unsubscribe();
5188
+ store.close();
5189
+ }
5190
+ };
5191
+ };
5192
+ var renderVoiceCallDebuggerLaunchHTML = (path, state, options = {}) => {
5193
+ const model = createVoiceCallDebuggerLaunchViewModel(path, state, options);
5194
+ const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
5195
+ <dt>${escapeHtml(row.label)}</dt>
5196
+ <dd>${escapeHtml(row.value)}</dd>
5197
+ </div>`).join("")}</dl>` : '<p class="absolute-voice-call-debugger-launch__empty">Load a call debugger report to see the latest support artifact.</p>';
5198
+ return `<section class="absolute-voice-call-debugger-launch absolute-voice-call-debugger-launch--${escapeHtml(model.status)}">
5199
+ <header class="absolute-voice-call-debugger-launch__header">
5200
+ <span class="absolute-voice-call-debugger-launch__eyebrow">${escapeHtml(model.title)}</span>
5201
+ <strong class="absolute-voice-call-debugger-launch__label">${escapeHtml(model.label)}</strong>
5202
+ </header>
5203
+ <p class="absolute-voice-call-debugger-launch__description">${escapeHtml(model.description)}</p>
5204
+ <a class="absolute-voice-call-debugger-launch__link" href="${escapeHtml(model.href)}">${escapeHtml(options.linkLabel ?? DEFAULT_LINK_LABEL)}</a>
5205
+ ${rows}
5206
+ ${model.error ? `<p class="absolute-voice-call-debugger-launch__error">${escapeHtml(model.error)}</p>` : ""}
5207
+ </section>`;
5208
+ };
5213
5209
 
5214
5210
  // src/svelte/createVoiceCallDebugger.ts
5215
5211
  var createVoiceCallDebugger = (path, options = {}) => {
@@ -5229,14 +5225,6 @@ var withTurnId = (path, turnId) => {
5229
5225
  url.searchParams.set("turnId", turnId);
5230
5226
  return `${url.pathname}${url.search}`;
5231
5227
  };
5232
- var fetchVoiceSessionSnapshot = async (path, options = {}) => {
5233
- const fetchImpl = options.fetch ?? globalThis.fetch;
5234
- const response = await fetchImpl(withTurnId(path, options.turnId));
5235
- if (!response.ok) {
5236
- throw new Error(`Voice session snapshot failed: HTTP ${response.status}`);
5237
- }
5238
- return await response.json();
5239
- };
5240
5228
  var createVoiceSessionSnapshotStore = (path, options = {}) => {
5241
5229
  const listeners = new Set;
5242
5230
  let closed = false;
@@ -5301,9 +5289,9 @@ var createVoiceSessionSnapshotStore = (path, options = {}) => {
5301
5289
  return {
5302
5290
  close,
5303
5291
  download,
5292
+ refresh,
5304
5293
  getServerSnapshot: () => snapshot,
5305
5294
  getSnapshot: () => snapshot,
5306
- refresh,
5307
5295
  subscribe: (listener) => {
5308
5296
  listeners.add(listener);
5309
5297
  return () => {
@@ -5312,6 +5300,14 @@ var createVoiceSessionSnapshotStore = (path, options = {}) => {
5312
5300
  }
5313
5301
  };
5314
5302
  };
5303
+ var fetchVoiceSessionSnapshot = async (path, options = {}) => {
5304
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5305
+ const response = await fetchImpl(withTurnId(path, options.turnId));
5306
+ if (!response.ok) {
5307
+ throw new Error(`Voice session snapshot failed: HTTP ${response.status}`);
5308
+ }
5309
+ return await response.json();
5310
+ };
5315
5311
 
5316
5312
  // src/client/sessionSnapshotWidget.ts
5317
5313
  var DEFAULT_TITLE5 = "Session Snapshot";
@@ -5319,7 +5315,7 @@ var DEFAULT_DESCRIPTION5 = "Portable call artifact with media graph, provider ro
5319
5315
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
5320
5316
  var formatStatus = (status) => status ?? "n/a";
5321
5317
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
5322
- const snapshot = state.snapshot;
5318
+ const { snapshot } = state;
5323
5319
  const failedProofs = snapshot?.proofSummary.failed ?? 0;
5324
5320
  const mediaWarnings = snapshot?.media.filter((media) => media.report.status !== "pass").length ?? 0;
5325
5321
  const timingWarnings = snapshot?.media.reduce((total, media) => total + media.report.timing.overBudgetFrames, 0) ?? 0;
@@ -5396,32 +5392,6 @@ var downloadBlob = (blob, filename) => {
5396
5392
  anchor.click();
5397
5393
  URL.revokeObjectURL(href);
5398
5394
  };
5399
- var mountVoiceSessionSnapshot = (element, path, options = {}) => {
5400
- const store = createVoiceSessionSnapshotStore(path, options);
5401
- const render = () => {
5402
- element.innerHTML = renderVoiceSessionSnapshotHTML(store.getSnapshot(), options);
5403
- };
5404
- const handleClick = (event) => {
5405
- const target = event.target;
5406
- if (target instanceof Element && target.closest("[data-absolute-voice-session-snapshot-download]")) {
5407
- const sessionId = store.getSnapshot().snapshot?.sessionId ?? "session";
5408
- downloadBlob(store.download(), `voice-session-${sessionId}.snapshot.json`);
5409
- }
5410
- };
5411
- const unsubscribe = store.subscribe(render);
5412
- element.addEventListener("click", handleClick);
5413
- render();
5414
- store.refresh().catch(() => {});
5415
- return {
5416
- close: () => {
5417
- element.removeEventListener("click", handleClick);
5418
- unsubscribe();
5419
- store.close();
5420
- },
5421
- download: store.download,
5422
- refresh: store.refresh
5423
- };
5424
- };
5425
5395
  var defineVoiceSessionSnapshotElement = (tagName = "absolute-voice-session-snapshot") => {
5426
5396
  if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
5427
5397
  return;
@@ -5444,6 +5414,32 @@ var defineVoiceSessionSnapshotElement = (tagName = "absolute-voice-session-snaps
5444
5414
  }
5445
5415
  });
5446
5416
  };
5417
+ var mountVoiceSessionSnapshot = (element, path, options = {}) => {
5418
+ const store = createVoiceSessionSnapshotStore(path, options);
5419
+ const render = () => {
5420
+ element.innerHTML = renderVoiceSessionSnapshotHTML(store.getSnapshot(), options);
5421
+ };
5422
+ const handleClick = (event) => {
5423
+ const { target } = event;
5424
+ if (target instanceof Element && target.closest("[data-absolute-voice-session-snapshot-download]")) {
5425
+ const sessionId = store.getSnapshot().snapshot?.sessionId ?? "session";
5426
+ downloadBlob(store.download(), `voice-session-${sessionId}.snapshot.json`);
5427
+ }
5428
+ };
5429
+ const unsubscribe = store.subscribe(render);
5430
+ element.addEventListener("click", handleClick);
5431
+ render();
5432
+ store.refresh().catch(() => {});
5433
+ return {
5434
+ download: store.download,
5435
+ refresh: store.refresh,
5436
+ close: () => {
5437
+ element.removeEventListener("click", handleClick);
5438
+ unsubscribe();
5439
+ store.close();
5440
+ }
5441
+ };
5442
+ };
5447
5443
 
5448
5444
  // src/svelte/createVoiceSessionSnapshot.ts
5449
5445
  var createVoiceSessionSnapshot = (path, options = {}) => {
@@ -5455,14 +5451,6 @@ var createVoiceSessionSnapshot = (path, options = {}) => {
5455
5451
  };
5456
5452
  };
5457
5453
  // src/client/sessionObservability.ts
5458
- var fetchVoiceSessionObservability = async (path, options = {}) => {
5459
- const fetchImpl = options.fetch ?? globalThis.fetch;
5460
- const response = await fetchImpl(path);
5461
- if (!response.ok) {
5462
- throw new Error(`Voice session observability failed: HTTP ${response.status}`);
5463
- }
5464
- return await response.json();
5465
- };
5466
5454
  var createVoiceSessionObservabilityStore = (path, options = {}) => {
5467
5455
  const listeners = new Set;
5468
5456
  let closed = false;
@@ -5522,9 +5510,9 @@ var createVoiceSessionObservabilityStore = (path, options = {}) => {
5522
5510
  }
5523
5511
  return {
5524
5512
  close,
5513
+ refresh,
5525
5514
  getServerSnapshot: () => snapshot,
5526
5515
  getSnapshot: () => snapshot,
5527
- refresh,
5528
5516
  subscribe: (listener) => {
5529
5517
  listeners.add(listener);
5530
5518
  return () => {
@@ -5533,13 +5521,21 @@ var createVoiceSessionObservabilityStore = (path, options = {}) => {
5533
5521
  }
5534
5522
  };
5535
5523
  };
5524
+ var fetchVoiceSessionObservability = async (path, options = {}) => {
5525
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5526
+ const response = await fetchImpl(path);
5527
+ if (!response.ok) {
5528
+ throw new Error(`Voice session observability failed: HTTP ${response.status}`);
5529
+ }
5530
+ return await response.json();
5531
+ };
5536
5532
 
5537
5533
  // src/client/sessionObservabilityWidget.ts
5538
5534
  var DEFAULT_TITLE6 = "Session Observability";
5539
5535
  var DEFAULT_DESCRIPTION6 = "One support/debug report for a voice call across traces, provider recovery, tools, handoffs, guardrails, turn waterfalls, and incident handoff.";
5540
5536
  var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
5541
5537
  var createVoiceSessionObservabilityViewModel = (snapshot, options = {}) => {
5542
- const report = snapshot.report;
5538
+ const { report } = snapshot;
5543
5539
  const turns = (report?.turns ?? []).slice(0, options.maxTurns ?? 3).map((turn) => ({
5544
5540
  ...turn,
5545
5541
  durationLabel: formatMs(turn.durationMs),
@@ -5559,38 +5555,6 @@ var createVoiceSessionObservabilityViewModel = (snapshot, options = {}) => {
5559
5555
  };
5560
5556
  };
5561
5557
  var renderLinks = (links) => links.length ? `<p class="absolute-voice-session-observability__actions">${links.map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</p>` : "";
5562
- var renderVoiceSessionObservabilityHTML = (snapshot, options = {}) => {
5563
- const model = createVoiceSessionObservabilityViewModel(snapshot, options);
5564
- const turns = model.turns.length ? `<div class="absolute-voice-session-observability__turns">${model.turns.map((turn) => `<article class="absolute-voice-session-observability__turn"><header><strong>${escapeHtml(turn.turnId)}</strong><span>${escapeHtml(turn.durationLabel)}</span></header><p>${escapeHtml(turn.label)}</p></article>`).join("")}</div>` : '<p class="absolute-voice-session-observability__empty">Open a voice session to see turn waterfalls.</p>';
5565
- return `<section class="absolute-voice-session-observability absolute-voice-session-observability--${escapeHtml(model.status)}">
5566
- <header class="absolute-voice-session-observability__header">
5567
- <span class="absolute-voice-session-observability__eyebrow">${escapeHtml(model.title)}</span>
5568
- <strong class="absolute-voice-session-observability__label">${escapeHtml(model.label)}</strong>
5569
- </header>
5570
- <p class="absolute-voice-session-observability__description">${escapeHtml(model.description)}</p>
5571
- ${model.sessionId ? `<p class="absolute-voice-session-observability__session">${escapeHtml(model.sessionId)}</p>` : ""}
5572
- ${renderLinks(model.links)}
5573
- ${turns}
5574
- ${model.error ? `<p class="absolute-voice-session-observability__error">${escapeHtml(model.error)}</p>` : ""}
5575
- </section>`;
5576
- };
5577
- var getVoiceSessionObservabilityCSS = () => `.absolute-voice-session-observability{border:1px solid #c8d9bf;border-radius:20px;background:#fbfff3;color:#18220d;padding:18px;box-shadow:0 18px 40px rgba(24,34,13,.12);font-family:inherit}.absolute-voice-session-observability--error,.absolute-voice-session-observability--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-session-observability--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-session-observability__header,.absolute-voice-session-observability__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-session-observability__eyebrow{color:#4d7c0f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-session-observability__label{font-size:24px;line-height:1}.absolute-voice-session-observability__description,.absolute-voice-session-observability__turn p,.absolute-voice-session-observability__empty,.absolute-voice-session-observability__session{color:#4b5f3e}.absolute-voice-session-observability__actions{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0}.absolute-voice-session-observability__actions a{color:#3f6212;font-weight:800}.absolute-voice-session-observability__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-session-observability__turn{background:#fff;border:1px solid #dcebcf;border-radius:16px;padding:14px}.absolute-voice-session-observability__turn p{margin:10px 0 0}.absolute-voice-session-observability__empty{margin:14px 0 0}.absolute-voice-session-observability__error{color:#9f1239;font-weight:700}`;
5578
- var mountVoiceSessionObservability = (element, path, options = {}) => {
5579
- const store = createVoiceSessionObservabilityStore(path, options);
5580
- const render = () => {
5581
- element.innerHTML = renderVoiceSessionObservabilityHTML(store.getSnapshot(), options);
5582
- };
5583
- const unsubscribe = store.subscribe(render);
5584
- render();
5585
- store.refresh().catch(() => {});
5586
- return {
5587
- close: () => {
5588
- unsubscribe();
5589
- store.close();
5590
- },
5591
- refresh: store.refresh
5592
- };
5593
- };
5594
5558
  var defineVoiceSessionObservabilityElement = (tagName = "absolute-voice-session-observability") => {
5595
5559
  if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
5596
5560
  return;
@@ -5613,6 +5577,38 @@ var defineVoiceSessionObservabilityElement = (tagName = "absolute-voice-session-
5613
5577
  }
5614
5578
  });
5615
5579
  };
5580
+ var getVoiceSessionObservabilityCSS = () => `.absolute-voice-session-observability{border:1px solid #c8d9bf;border-radius:20px;background:#fbfff3;color:#18220d;padding:18px;box-shadow:0 18px 40px rgba(24,34,13,.12);font-family:inherit}.absolute-voice-session-observability--error,.absolute-voice-session-observability--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-session-observability--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-session-observability__header,.absolute-voice-session-observability__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-session-observability__eyebrow{color:#4d7c0f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-session-observability__label{font-size:24px;line-height:1}.absolute-voice-session-observability__description,.absolute-voice-session-observability__turn p,.absolute-voice-session-observability__empty,.absolute-voice-session-observability__session{color:#4b5f3e}.absolute-voice-session-observability__actions{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0}.absolute-voice-session-observability__actions a{color:#3f6212;font-weight:800}.absolute-voice-session-observability__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-session-observability__turn{background:#fff;border:1px solid #dcebcf;border-radius:16px;padding:14px}.absolute-voice-session-observability__turn p{margin:10px 0 0}.absolute-voice-session-observability__empty{margin:14px 0 0}.absolute-voice-session-observability__error{color:#9f1239;font-weight:700}`;
5581
+ var mountVoiceSessionObservability = (element, path, options = {}) => {
5582
+ const store = createVoiceSessionObservabilityStore(path, options);
5583
+ const render = () => {
5584
+ element.innerHTML = renderVoiceSessionObservabilityHTML(store.getSnapshot(), options);
5585
+ };
5586
+ const unsubscribe = store.subscribe(render);
5587
+ render();
5588
+ store.refresh().catch(() => {});
5589
+ return {
5590
+ refresh: store.refresh,
5591
+ close: () => {
5592
+ unsubscribe();
5593
+ store.close();
5594
+ }
5595
+ };
5596
+ };
5597
+ var renderVoiceSessionObservabilityHTML = (snapshot, options = {}) => {
5598
+ const model = createVoiceSessionObservabilityViewModel(snapshot, options);
5599
+ const turns = model.turns.length ? `<div class="absolute-voice-session-observability__turns">${model.turns.map((turn) => `<article class="absolute-voice-session-observability__turn"><header><strong>${escapeHtml(turn.turnId)}</strong><span>${escapeHtml(turn.durationLabel)}</span></header><p>${escapeHtml(turn.label)}</p></article>`).join("")}</div>` : '<p class="absolute-voice-session-observability__empty">Open a voice session to see turn waterfalls.</p>';
5600
+ return `<section class="absolute-voice-session-observability absolute-voice-session-observability--${escapeHtml(model.status)}">
5601
+ <header class="absolute-voice-session-observability__header">
5602
+ <span class="absolute-voice-session-observability__eyebrow">${escapeHtml(model.title)}</span>
5603
+ <strong class="absolute-voice-session-observability__label">${escapeHtml(model.label)}</strong>
5604
+ </header>
5605
+ <p class="absolute-voice-session-observability__description">${escapeHtml(model.description)}</p>
5606
+ ${model.sessionId ? `<p class="absolute-voice-session-observability__session">${escapeHtml(model.sessionId)}</p>` : ""}
5607
+ ${renderLinks(model.links)}
5608
+ ${turns}
5609
+ ${model.error ? `<p class="absolute-voice-session-observability__error">${escapeHtml(model.error)}</p>` : ""}
5610
+ </section>`;
5611
+ };
5616
5612
 
5617
5613
  // src/svelte/createVoiceSessionObservability.ts
5618
5614
  var createVoiceSessionObservability = (path = "/api/voice/session-observability/latest", options = {}) => {
@@ -5624,14 +5620,6 @@ var createVoiceSessionObservability = (path = "/api/voice/session-observability/
5624
5620
  };
5625
5621
  };
5626
5622
  // src/client/profileComparison.ts
5627
- var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
5628
- const fetchImpl = options.fetch ?? globalThis.fetch;
5629
- const response = await fetchImpl(path);
5630
- if (!response.ok) {
5631
- throw new Error(`Voice profile comparison failed: HTTP ${response.status}`);
5632
- }
5633
- return await response.json();
5634
- };
5635
5623
  var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-history", options = {}) => {
5636
5624
  const listeners = new Set;
5637
5625
  let closed = false;
@@ -5686,9 +5674,9 @@ var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-hi
5686
5674
  }
5687
5675
  return {
5688
5676
  close,
5677
+ refresh,
5689
5678
  getServerSnapshot: () => snapshot,
5690
5679
  getSnapshot: () => snapshot,
5691
- refresh,
5692
5680
  subscribe: (listener) => {
5693
5681
  listeners.add(listener);
5694
5682
  return () => {
@@ -5697,6 +5685,14 @@ var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-hi
5697
5685
  }
5698
5686
  };
5699
5687
  };
5688
+ var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
5689
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5690
+ const response = await fetchImpl(path);
5691
+ if (!response.ok) {
5692
+ throw new Error(`Voice profile comparison failed: HTTP ${response.status}`);
5693
+ }
5694
+ return await response.json();
5695
+ };
5700
5696
 
5701
5697
  // src/svelte/createVoiceProfileComparison.ts
5702
5698
  var createVoiceProfileComparison = (path = "/api/voice/real-call-profile-history", options = {}) => {
@@ -5709,14 +5705,6 @@ var createVoiceProfileComparison = (path = "/api/voice/real-call-profile-history
5709
5705
  };
5710
5706
  };
5711
5707
  // src/client/readinessFailures.ts
5712
- var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
5713
- const fetchImpl = options.fetch ?? globalThis.fetch;
5714
- const response = await fetchImpl(path);
5715
- if (!response.ok) {
5716
- throw new Error(`Voice readiness failed: HTTP ${response.status}`);
5717
- }
5718
- return await response.json();
5719
- };
5720
5708
  var createVoiceReadinessFailuresStore = (path = "/api/production-readiness", options = {}) => {
5721
5709
  const listeners = new Set;
5722
5710
  let closed = false;
@@ -5771,9 +5759,9 @@ var createVoiceReadinessFailuresStore = (path = "/api/production-readiness", opt
5771
5759
  }
5772
5760
  return {
5773
5761
  close,
5762
+ refresh,
5774
5763
  getServerSnapshot: () => snapshot,
5775
5764
  getSnapshot: () => snapshot,
5776
- refresh,
5777
5765
  subscribe: (listener) => {
5778
5766
  listeners.add(listener);
5779
5767
  return () => {
@@ -5782,6 +5770,14 @@ var createVoiceReadinessFailuresStore = (path = "/api/production-readiness", opt
5782
5770
  }
5783
5771
  };
5784
5772
  };
5773
+ var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
5774
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5775
+ const response = await fetchImpl(path);
5776
+ if (!response.ok) {
5777
+ throw new Error(`Voice readiness failed: HTTP ${response.status}`);
5778
+ }
5779
+ return await response.json();
5780
+ };
5785
5781
 
5786
5782
  // src/svelte/createVoiceReadinessFailures.ts
5787
5783
  var createVoiceReadinessFailures = (path = "/api/production-readiness", options = {}) => {
@@ -5860,9 +5856,9 @@ var createVoiceProviderSimulationControlsStore = (options) => {
5860
5856
  };
5861
5857
  return {
5862
5858
  close,
5859
+ run,
5863
5860
  getServerSnapshot: () => snapshot,
5864
5861
  getSnapshot: () => snapshot,
5865
- run,
5866
5862
  subscribe: (listener) => {
5867
5863
  listeners.add(listener);
5868
5864
  return () => {
@@ -5874,41 +5870,9 @@ var createVoiceProviderSimulationControlsStore = (options) => {
5874
5870
 
5875
5871
  // src/client/providerSimulationControlsWidget.ts
5876
5872
  var formatKind = (kind) => (kind ?? "stt").toUpperCase();
5877
- var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
5878
- const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
5879
- const fallbackReady = !options.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === options.fallbackRequiredProvider);
5880
- const failureProviders = (options.failureProviders ? options.failureProviders.map((provider) => ({ provider })) : configuredProviders).filter((provider) => configuredProviders.some((entry) => entry.provider === provider.provider));
5881
- return {
5882
- canSimulateFailure: configuredProviders.length > 0 && fallbackReady,
5883
- description: options.failureMessage ?? `Simulate ${formatKind(options.kind)} provider failure and recovery without changing credentials.`,
5884
- error: snapshot.error,
5885
- failureProviders,
5886
- isRunning: snapshot.isRunning,
5887
- label: snapshot.isRunning ? `Running ${snapshot.mode ?? "simulation"}` : snapshot.lastResult ? `${snapshot.lastResult.provider} ${snapshot.lastResult.mode} simulated` : configuredProviders.length ? `${configuredProviders.length} configured` : "No configured providers",
5888
- providers: configuredProviders,
5889
- resultText: snapshot.lastResult ? JSON.stringify(snapshot.lastResult, null, 2) : null,
5890
- title: options.title ?? `${formatKind(options.kind)} Failure Simulation`
5891
- };
5892
- };
5893
- var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
5894
- const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
5895
- const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml(provider.provider)} ${escapeHtml(formatKind(options.kind))} failure</button>`).join("");
5896
- const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml(provider.provider)} recovered</button>`).join("");
5897
- return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
5898
- <header class="absolute-voice-provider-simulation__header">
5899
- <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml(model.title)}</span>
5900
- <strong class="absolute-voice-provider-simulation__label">${escapeHtml(model.label)}</strong>
5901
- </header>
5902
- <p class="absolute-voice-provider-simulation__description">${escapeHtml(model.description)}</p>
5903
- ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
5904
- <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
5905
- ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml(snapshot.error)}</p>` : ""}
5906
- ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml(model.resultText)}</pre>` : ""}
5907
- </section>`;
5908
- };
5909
5873
  var bindVoiceProviderSimulationControls = (element, store) => {
5910
5874
  const onClick = (event) => {
5911
- const target = event.target;
5875
+ const { target } = event;
5912
5876
  if (!(target instanceof HTMLElement)) {
5913
5877
  return;
5914
5878
  }
@@ -5924,21 +5888,20 @@ var bindVoiceProviderSimulationControls = (element, store) => {
5924
5888
  element.addEventListener("click", onClick);
5925
5889
  return () => element.removeEventListener("click", onClick);
5926
5890
  };
5927
- var mountVoiceProviderSimulationControls = (element, options) => {
5928
- const store = createVoiceProviderSimulationControlsStore(options);
5929
- const render = () => {
5930
- element.innerHTML = renderVoiceProviderSimulationControlsHTML(store.getSnapshot(), options);
5931
- };
5932
- const unsubscribeStore = store.subscribe(render);
5933
- const unsubscribeDom = bindVoiceProviderSimulationControls(element, store);
5934
- render();
5891
+ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
5892
+ const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
5893
+ const fallbackReady = !options.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === options.fallbackRequiredProvider);
5894
+ const failureProviders = (options.failureProviders ? options.failureProviders.map((provider) => ({ provider })) : configuredProviders).filter((provider) => configuredProviders.some((entry) => entry.provider === provider.provider));
5935
5895
  return {
5936
- close: () => {
5937
- unsubscribeDom();
5938
- unsubscribeStore();
5939
- store.close();
5940
- },
5941
- run: store.run
5896
+ canSimulateFailure: configuredProviders.length > 0 && fallbackReady,
5897
+ description: options.failureMessage ?? `Simulate ${formatKind(options.kind)} provider failure and recovery without changing credentials.`,
5898
+ error: snapshot.error,
5899
+ failureProviders,
5900
+ isRunning: snapshot.isRunning,
5901
+ label: snapshot.isRunning ? `Running ${snapshot.mode ?? "simulation"}` : snapshot.lastResult ? `${snapshot.lastResult.provider} ${snapshot.lastResult.mode} simulated` : configuredProviders.length ? `${configuredProviders.length} configured` : "No configured providers",
5902
+ providers: configuredProviders,
5903
+ resultText: snapshot.lastResult ? JSON.stringify(snapshot.lastResult, null, 2) : null,
5904
+ title: options.title ?? `${formatKind(options.kind)} Failure Simulation`
5942
5905
  };
5943
5906
  };
5944
5907
  var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-provider-simulation") => {
@@ -5967,6 +5930,39 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
5967
5930
  }
5968
5931
  });
5969
5932
  };
5933
+ var mountVoiceProviderSimulationControls = (element, options) => {
5934
+ const store = createVoiceProviderSimulationControlsStore(options);
5935
+ const render = () => {
5936
+ element.innerHTML = renderVoiceProviderSimulationControlsHTML(store.getSnapshot(), options);
5937
+ };
5938
+ const unsubscribeStore = store.subscribe(render);
5939
+ const unsubscribeDom = bindVoiceProviderSimulationControls(element, store);
5940
+ render();
5941
+ return {
5942
+ run: store.run,
5943
+ close: () => {
5944
+ unsubscribeDom();
5945
+ unsubscribeStore();
5946
+ store.close();
5947
+ }
5948
+ };
5949
+ };
5950
+ var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
5951
+ const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
5952
+ const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml(provider.provider)} ${escapeHtml(formatKind(options.kind))} failure</button>`).join("");
5953
+ const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml(provider.provider)} recovered</button>`).join("");
5954
+ return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
5955
+ <header class="absolute-voice-provider-simulation__header">
5956
+ <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml(model.title)}</span>
5957
+ <strong class="absolute-voice-provider-simulation__label">${escapeHtml(model.label)}</strong>
5958
+ </header>
5959
+ <p class="absolute-voice-provider-simulation__description">${escapeHtml(model.description)}</p>
5960
+ ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
5961
+ <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
5962
+ ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml(snapshot.error)}</p>` : ""}
5963
+ ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml(model.resultText)}</pre>` : ""}
5964
+ </section>`;
5965
+ };
5970
5966
 
5971
5967
  // src/svelte/createVoiceProviderSimulationControls.ts
5972
5968
  var createVoiceProviderSimulationControls = (options) => {
@@ -5979,14 +5975,6 @@ var createVoiceProviderSimulationControls = (options) => {
5979
5975
  };
5980
5976
  };
5981
5977
  // src/client/providerCapabilities.ts
5982
- var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
5983
- const fetchImpl = options.fetch ?? globalThis.fetch;
5984
- const response = await fetchImpl(path);
5985
- if (!response.ok) {
5986
- throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
5987
- }
5988
- return await response.json();
5989
- };
5990
5978
  var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
5991
5979
  const listeners = new Set;
5992
5980
  let closed = false;
@@ -6045,9 +6033,9 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
6045
6033
  }
6046
6034
  return {
6047
6035
  close,
6036
+ refresh,
6048
6037
  getServerSnapshot: () => snapshot,
6049
6038
  getSnapshot: () => snapshot,
6050
- refresh,
6051
6039
  subscribe: (listener) => {
6052
6040
  listeners.add(listener);
6053
6041
  return () => {
@@ -6056,6 +6044,14 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
6056
6044
  }
6057
6045
  };
6058
6046
  };
6047
+ var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
6048
+ const fetchImpl = options.fetch ?? globalThis.fetch;
6049
+ const response = await fetchImpl(path);
6050
+ if (!response.ok) {
6051
+ throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
6052
+ }
6053
+ return await response.json();
6054
+ };
6059
6055
 
6060
6056
  // src/client/providerCapabilitiesWidget.ts
6061
6057
  var DEFAULT_TITLE7 = "Provider Capabilities";
@@ -6102,14 +6098,51 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
6102
6098
  const warningCount = capabilities.filter((capability) => isWarningStatus(capability.status)).length;
6103
6099
  const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
6104
6100
  return {
6105
- capabilities,
6106
- description: options.description ?? DEFAULT_DESCRIPTION7,
6107
- error: snapshot.error,
6108
- isLoading: snapshot.isLoading,
6109
- label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
6110
- status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
6111
- title: options.title ?? DEFAULT_TITLE7,
6112
- updatedAt: snapshot.updatedAt
6101
+ capabilities,
6102
+ description: options.description ?? DEFAULT_DESCRIPTION7,
6103
+ error: snapshot.error,
6104
+ isLoading: snapshot.isLoading,
6105
+ label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
6106
+ status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
6107
+ title: options.title ?? DEFAULT_TITLE7,
6108
+ updatedAt: snapshot.updatedAt
6109
+ };
6110
+ };
6111
+ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider-capabilities") => {
6112
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6113
+ return;
6114
+ }
6115
+ customElements.define(tagName, class AbsoluteVoiceProviderCapabilitiesElement extends HTMLElement {
6116
+ mounted;
6117
+ connectedCallback() {
6118
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6119
+ this.mounted = mountVoiceProviderCapabilities(this, this.getAttribute("path") ?? "/api/provider-capabilities", {
6120
+ description: this.getAttribute("description") ?? undefined,
6121
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6122
+ title: this.getAttribute("title") ?? undefined
6123
+ });
6124
+ }
6125
+ disconnectedCallback() {
6126
+ this.mounted?.close();
6127
+ this.mounted = undefined;
6128
+ }
6129
+ });
6130
+ };
6131
+ var getVoiceProviderCapabilitiesCSS = () => `.absolute-voice-provider-capabilities{border:1px solid #bfd7ea;border-radius:20px;background:#f6fbff;color:#08131f;padding:18px;box-shadow:0 18px 40px rgba(14,51,78,.12);font-family:inherit}.absolute-voice-provider-capabilities--error,.absolute-voice-provider-capabilities--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-capabilities__header,.absolute-voice-provider-capabilities__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-capabilities__eyebrow{color:#255f85;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-capabilities__label{font-size:24px;line-height:1}.absolute-voice-provider-capabilities__description,.absolute-voice-provider-capabilities__provider p,.absolute-voice-provider-capabilities__provider dt,.absolute-voice-provider-capabilities__empty{color:#405467}.absolute-voice-provider-capabilities__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-capabilities__provider{background:#fff;border:1px solid #d7e7f3;border-radius:16px;padding:14px}.absolute-voice-provider-capabilities__provider--selected,.absolute-voice-provider-capabilities__provider--healthy{border-color:#86efac}.absolute-voice-provider-capabilities__provider--degraded,.absolute-voice-provider-capabilities__provider--rate-limited,.absolute-voice-provider-capabilities__provider--suppressed,.absolute-voice-provider-capabilities__provider--unconfigured{border-color:#f2a7a7}.absolute-voice-provider-capabilities__provider p{margin:10px 0}.absolute-voice-provider-capabilities__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-capabilities__provider div{background:#f6fbff;border:1px solid #d7e7f3;border-radius:12px;padding:8px}.absolute-voice-provider-capabilities__provider dt{font-size:12px}.absolute-voice-provider-capabilities__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-capabilities__empty{margin:14px 0 0}.absolute-voice-provider-capabilities__error{color:#9f1239;font-weight:700}`;
6132
+ var mountVoiceProviderCapabilities = (element, path = "/api/provider-capabilities", options = {}) => {
6133
+ const store = createVoiceProviderCapabilitiesStore(path, options);
6134
+ const render = () => {
6135
+ element.innerHTML = renderVoiceProviderCapabilitiesHTML(store.getSnapshot(), options);
6136
+ };
6137
+ const unsubscribe = store.subscribe(render);
6138
+ render();
6139
+ store.refresh().catch(() => {});
6140
+ return {
6141
+ refresh: store.refresh,
6142
+ close: () => {
6143
+ unsubscribe();
6144
+ store.close();
6145
+ }
6113
6146
  };
6114
6147
  };
6115
6148
  var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
@@ -6135,43 +6168,6 @@ var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
6135
6168
  ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml(model.error)}</p>` : ""}
6136
6169
  </section>`;
6137
6170
  };
6138
- var getVoiceProviderCapabilitiesCSS = () => `.absolute-voice-provider-capabilities{border:1px solid #bfd7ea;border-radius:20px;background:#f6fbff;color:#08131f;padding:18px;box-shadow:0 18px 40px rgba(14,51,78,.12);font-family:inherit}.absolute-voice-provider-capabilities--error,.absolute-voice-provider-capabilities--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-capabilities__header,.absolute-voice-provider-capabilities__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-capabilities__eyebrow{color:#255f85;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-capabilities__label{font-size:24px;line-height:1}.absolute-voice-provider-capabilities__description,.absolute-voice-provider-capabilities__provider p,.absolute-voice-provider-capabilities__provider dt,.absolute-voice-provider-capabilities__empty{color:#405467}.absolute-voice-provider-capabilities__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-capabilities__provider{background:#fff;border:1px solid #d7e7f3;border-radius:16px;padding:14px}.absolute-voice-provider-capabilities__provider--selected,.absolute-voice-provider-capabilities__provider--healthy{border-color:#86efac}.absolute-voice-provider-capabilities__provider--degraded,.absolute-voice-provider-capabilities__provider--rate-limited,.absolute-voice-provider-capabilities__provider--suppressed,.absolute-voice-provider-capabilities__provider--unconfigured{border-color:#f2a7a7}.absolute-voice-provider-capabilities__provider p{margin:10px 0}.absolute-voice-provider-capabilities__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-capabilities__provider div{background:#f6fbff;border:1px solid #d7e7f3;border-radius:12px;padding:8px}.absolute-voice-provider-capabilities__provider dt{font-size:12px}.absolute-voice-provider-capabilities__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-capabilities__empty{margin:14px 0 0}.absolute-voice-provider-capabilities__error{color:#9f1239;font-weight:700}`;
6139
- var mountVoiceProviderCapabilities = (element, path = "/api/provider-capabilities", options = {}) => {
6140
- const store = createVoiceProviderCapabilitiesStore(path, options);
6141
- const render = () => {
6142
- element.innerHTML = renderVoiceProviderCapabilitiesHTML(store.getSnapshot(), options);
6143
- };
6144
- const unsubscribe = store.subscribe(render);
6145
- render();
6146
- store.refresh().catch(() => {});
6147
- return {
6148
- close: () => {
6149
- unsubscribe();
6150
- store.close();
6151
- },
6152
- refresh: store.refresh
6153
- };
6154
- };
6155
- var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider-capabilities") => {
6156
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6157
- return;
6158
- }
6159
- customElements.define(tagName, class AbsoluteVoiceProviderCapabilitiesElement extends HTMLElement {
6160
- mounted;
6161
- connectedCallback() {
6162
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6163
- this.mounted = mountVoiceProviderCapabilities(this, this.getAttribute("path") ?? "/api/provider-capabilities", {
6164
- description: this.getAttribute("description") ?? undefined,
6165
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6166
- title: this.getAttribute("title") ?? undefined
6167
- });
6168
- }
6169
- disconnectedCallback() {
6170
- this.mounted?.close();
6171
- this.mounted = undefined;
6172
- }
6173
- });
6174
- };
6175
6171
 
6176
6172
  // src/svelte/createVoiceProviderCapabilities.ts
6177
6173
  var createVoiceProviderCapabilities = (path = "/api/provider-capabilities", options = {}) => {
@@ -6183,14 +6179,6 @@ var createVoiceProviderCapabilities = (path = "/api/provider-capabilities", opti
6183
6179
  };
6184
6180
  };
6185
6181
  // src/client/providerContracts.ts
6186
- var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
6187
- const fetchImpl = options.fetch ?? globalThis.fetch;
6188
- const response = await fetchImpl(path);
6189
- if (!response.ok) {
6190
- throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
6191
- }
6192
- return await response.json();
6193
- };
6194
6182
  var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
6195
6183
  const listeners = new Set;
6196
6184
  let closed = false;
@@ -6245,9 +6233,9 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
6245
6233
  }
6246
6234
  return {
6247
6235
  close,
6236
+ refresh,
6248
6237
  getServerSnapshot: () => snapshot,
6249
6238
  getSnapshot: () => snapshot,
6250
- refresh,
6251
6239
  subscribe: (listener) => {
6252
6240
  listeners.add(listener);
6253
6241
  return () => {
@@ -6256,6 +6244,14 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
6256
6244
  }
6257
6245
  };
6258
6246
  };
6247
+ var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
6248
+ const fetchImpl = options.fetch ?? globalThis.fetch;
6249
+ const response = await fetchImpl(path);
6250
+ if (!response.ok) {
6251
+ throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
6252
+ }
6253
+ return await response.json();
6254
+ };
6259
6255
 
6260
6256
  // src/client/providerContractsWidget.ts
6261
6257
  var DEFAULT_TITLE8 = "Provider Contracts";
@@ -6301,6 +6297,43 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
6301
6297
  updatedAt: snapshot.updatedAt
6302
6298
  };
6303
6299
  };
6300
+ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-contracts") => {
6301
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6302
+ return;
6303
+ }
6304
+ customElements.define(tagName, class AbsoluteVoiceProviderContractsElement extends HTMLElement {
6305
+ mounted;
6306
+ connectedCallback() {
6307
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6308
+ this.mounted = mountVoiceProviderContracts(this, this.getAttribute("path") ?? "/api/provider-contracts", {
6309
+ description: this.getAttribute("description") ?? undefined,
6310
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6311
+ title: this.getAttribute("title") ?? undefined
6312
+ });
6313
+ }
6314
+ disconnectedCallback() {
6315
+ this.mounted?.close();
6316
+ this.mounted = undefined;
6317
+ }
6318
+ });
6319
+ };
6320
+ var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
6321
+ var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
6322
+ const store = createVoiceProviderContractsStore(path, options);
6323
+ const render = () => {
6324
+ element.innerHTML = renderVoiceProviderContractsHTML(store.getSnapshot(), options);
6325
+ };
6326
+ const unsubscribe = store.subscribe(render);
6327
+ render();
6328
+ store.refresh().catch(() => {});
6329
+ return {
6330
+ refresh: store.refresh,
6331
+ close: () => {
6332
+ unsubscribe();
6333
+ store.close();
6334
+ }
6335
+ };
6336
+ };
6304
6337
  var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
6305
6338
  const model = createVoiceProviderContractsViewModel(snapshot, options);
6306
6339
  const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml(row.status)}">
@@ -6325,43 +6358,6 @@ var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
6325
6358
  ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml(model.error)}</p>` : ""}
6326
6359
  </section>`;
6327
6360
  };
6328
- var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
6329
- var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
6330
- const store = createVoiceProviderContractsStore(path, options);
6331
- const render = () => {
6332
- element.innerHTML = renderVoiceProviderContractsHTML(store.getSnapshot(), options);
6333
- };
6334
- const unsubscribe = store.subscribe(render);
6335
- render();
6336
- store.refresh().catch(() => {});
6337
- return {
6338
- close: () => {
6339
- unsubscribe();
6340
- store.close();
6341
- },
6342
- refresh: store.refresh
6343
- };
6344
- };
6345
- var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-contracts") => {
6346
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6347
- return;
6348
- }
6349
- customElements.define(tagName, class AbsoluteVoiceProviderContractsElement extends HTMLElement {
6350
- mounted;
6351
- connectedCallback() {
6352
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6353
- this.mounted = mountVoiceProviderContracts(this, this.getAttribute("path") ?? "/api/provider-contracts", {
6354
- description: this.getAttribute("description") ?? undefined,
6355
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6356
- title: this.getAttribute("title") ?? undefined
6357
- });
6358
- }
6359
- disconnectedCallback() {
6360
- this.mounted?.close();
6361
- this.mounted = undefined;
6362
- }
6363
- });
6364
- };
6365
6361
 
6366
6362
  // src/svelte/createVoiceProviderContracts.ts
6367
6363
  var createVoiceProviderContracts = (path = "/api/provider-contracts", options = {}) => {
@@ -6375,14 +6371,6 @@ var createVoiceProviderContracts = (path = "/api/provider-contracts", options =
6375
6371
  // src/svelte/createVoiceStream.ts
6376
6372
  var createVoiceStream2 = (path, options = {}) => createVoiceStream(path, options);
6377
6373
  // src/client/providerStatus.ts
6378
- var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
6379
- const fetchImpl = options.fetch ?? globalThis.fetch;
6380
- const response = await fetchImpl(path);
6381
- if (!response.ok) {
6382
- throw new Error(`Voice provider status failed: HTTP ${response.status}`);
6383
- }
6384
- return await response.json();
6385
- };
6386
6374
  var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
6387
6375
  const listeners = new Set;
6388
6376
  let closed = false;
@@ -6442,9 +6430,9 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
6442
6430
  }
6443
6431
  return {
6444
6432
  close,
6433
+ refresh,
6445
6434
  getServerSnapshot: () => snapshot,
6446
6435
  getSnapshot: () => snapshot,
6447
- refresh,
6448
6436
  subscribe: (listener) => {
6449
6437
  listeners.add(listener);
6450
6438
  return () => {
@@ -6453,6 +6441,14 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
6453
6441
  }
6454
6442
  };
6455
6443
  };
6444
+ var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
6445
+ const fetchImpl = options.fetch ?? globalThis.fetch;
6446
+ const response = await fetchImpl(path);
6447
+ if (!response.ok) {
6448
+ throw new Error(`Voice provider status failed: HTTP ${response.status}`);
6449
+ }
6450
+ return await response.json();
6451
+ };
6456
6452
 
6457
6453
  // src/client/providerStatusWidget.ts
6458
6454
  var DEFAULT_TITLE9 = "Voice Providers";
@@ -6510,6 +6506,43 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
6510
6506
  updatedAt: snapshot.updatedAt
6511
6507
  };
6512
6508
  };
6509
+ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-status") => {
6510
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6511
+ return;
6512
+ }
6513
+ customElements.define(tagName, class AbsoluteVoiceProviderStatusElement extends HTMLElement {
6514
+ mounted;
6515
+ connectedCallback() {
6516
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6517
+ this.mounted = mountVoiceProviderStatus(this, this.getAttribute("path") ?? "/api/provider-status", {
6518
+ description: this.getAttribute("description") ?? undefined,
6519
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6520
+ title: this.getAttribute("title") ?? undefined
6521
+ });
6522
+ }
6523
+ disconnectedCallback() {
6524
+ this.mounted?.close();
6525
+ this.mounted = undefined;
6526
+ }
6527
+ });
6528
+ };
6529
+ var getVoiceProviderStatusCSS = () => `.absolute-voice-provider-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-provider-status--error,.absolute-voice-provider-status--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-status__header,.absolute-voice-provider-status__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-status__label{font-size:24px;line-height:1}.absolute-voice-provider-status__description,.absolute-voice-provider-status__provider p,.absolute-voice-provider-status__provider dt,.absolute-voice-provider-status__empty{color:#514733}.absolute-voice-provider-status__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-status__provider{background:#fff;border:1px solid #eee4d2;border-radius:16px;padding:14px}.absolute-voice-provider-status__provider--degraded,.absolute-voice-provider-status__provider--rate-limited,.absolute-voice-provider-status__provider--suppressed{border-color:#f2a7a7}.absolute-voice-provider-status__provider--recoverable{border-color:#fbbf24}.absolute-voice-provider-status__provider p{margin:10px 0}.absolute-voice-provider-status__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-status__provider div{background:#fffaf0;border:1px solid #eee4d2;border-radius:12px;padding:8px}.absolute-voice-provider-status__provider dt{font-size:12px}.absolute-voice-provider-status__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-status__empty{margin:14px 0 0}.absolute-voice-provider-status__error{color:#9f1239;font-weight:700}`;
6530
+ var mountVoiceProviderStatus = (element, path = "/api/provider-status", options = {}) => {
6531
+ const store = createVoiceProviderStatusStore(path, options);
6532
+ const render = () => {
6533
+ element.innerHTML = renderVoiceProviderStatusHTML(store.getSnapshot(), options);
6534
+ };
6535
+ const unsubscribe = store.subscribe(render);
6536
+ render();
6537
+ store.refresh().catch(() => {});
6538
+ return {
6539
+ refresh: store.refresh,
6540
+ close: () => {
6541
+ unsubscribe();
6542
+ store.close();
6543
+ }
6544
+ };
6545
+ };
6513
6546
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
6514
6547
  const model = createVoiceProviderStatusViewModel(snapshot, options);
6515
6548
  const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml(provider.status)}">
@@ -6533,62 +6566,17 @@ var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
6533
6566
  ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml(model.error)}</p>` : ""}
6534
6567
  </section>`;
6535
6568
  };
6536
- var getVoiceProviderStatusCSS = () => `.absolute-voice-provider-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-provider-status--error,.absolute-voice-provider-status--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-status__header,.absolute-voice-provider-status__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-status__label{font-size:24px;line-height:1}.absolute-voice-provider-status__description,.absolute-voice-provider-status__provider p,.absolute-voice-provider-status__provider dt,.absolute-voice-provider-status__empty{color:#514733}.absolute-voice-provider-status__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-status__provider{background:#fff;border:1px solid #eee4d2;border-radius:16px;padding:14px}.absolute-voice-provider-status__provider--degraded,.absolute-voice-provider-status__provider--rate-limited,.absolute-voice-provider-status__provider--suppressed{border-color:#f2a7a7}.absolute-voice-provider-status__provider--recoverable{border-color:#fbbf24}.absolute-voice-provider-status__provider p{margin:10px 0}.absolute-voice-provider-status__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-status__provider div{background:#fffaf0;border:1px solid #eee4d2;border-radius:12px;padding:8px}.absolute-voice-provider-status__provider dt{font-size:12px}.absolute-voice-provider-status__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-status__empty{margin:14px 0 0}.absolute-voice-provider-status__error{color:#9f1239;font-weight:700}`;
6537
- var mountVoiceProviderStatus = (element, path = "/api/provider-status", options = {}) => {
6538
- const store = createVoiceProviderStatusStore(path, options);
6539
- const render = () => {
6540
- element.innerHTML = renderVoiceProviderStatusHTML(store.getSnapshot(), options);
6541
- };
6542
- const unsubscribe = store.subscribe(render);
6543
- render();
6544
- store.refresh().catch(() => {});
6545
- return {
6546
- close: () => {
6547
- unsubscribe();
6548
- store.close();
6549
- },
6550
- refresh: store.refresh
6551
- };
6552
- };
6553
- var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-status") => {
6554
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6555
- return;
6556
- }
6557
- customElements.define(tagName, class AbsoluteVoiceProviderStatusElement extends HTMLElement {
6558
- mounted;
6559
- connectedCallback() {
6560
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6561
- this.mounted = mountVoiceProviderStatus(this, this.getAttribute("path") ?? "/api/provider-status", {
6562
- description: this.getAttribute("description") ?? undefined,
6563
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6564
- title: this.getAttribute("title") ?? undefined
6565
- });
6566
- }
6567
- disconnectedCallback() {
6568
- this.mounted?.close();
6569
- this.mounted = undefined;
6570
- }
6571
- });
6572
- };
6573
6569
 
6574
6570
  // src/svelte/createVoiceProviderStatus.ts
6575
6571
  var createVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
6576
6572
  const store = createVoiceProviderStatusStore(path, options);
6577
6573
  return {
6578
- ...store,
6579
- getHTML: () => renderVoiceProviderStatusHTML(store.getSnapshot(), options),
6580
- getViewModel: () => createVoiceProviderStatusViewModel(store.getSnapshot(), options)
6581
- };
6582
- };
6583
- // src/client/routingStatus.ts
6584
- var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
6585
- const fetchImpl = options.fetch ?? globalThis.fetch;
6586
- const response = await fetchImpl(path);
6587
- if (!response.ok) {
6588
- throw new Error(`Voice routing status failed: HTTP ${response.status}`);
6589
- }
6590
- return await response.json();
6574
+ ...store,
6575
+ getHTML: () => renderVoiceProviderStatusHTML(store.getSnapshot(), options),
6576
+ getViewModel: () => createVoiceProviderStatusViewModel(store.getSnapshot(), options)
6577
+ };
6591
6578
  };
6579
+ // src/client/routingStatus.ts
6592
6580
  var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {}) => {
6593
6581
  const listeners = new Set;
6594
6582
  let closed = false;
@@ -6648,9 +6636,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
6648
6636
  }
6649
6637
  return {
6650
6638
  close,
6639
+ refresh,
6651
6640
  getServerSnapshot: () => snapshot,
6652
6641
  getSnapshot: () => snapshot,
6653
- refresh,
6654
6642
  subscribe: (listener) => {
6655
6643
  listeners.add(listener);
6656
6644
  return () => {
@@ -6659,6 +6647,14 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
6659
6647
  }
6660
6648
  };
6661
6649
  };
6650
+ var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
6651
+ const fetchImpl = options.fetch ?? globalThis.fetch;
6652
+ const response = await fetchImpl(path);
6653
+ if (!response.ok) {
6654
+ throw new Error(`Voice routing status failed: HTTP ${response.status}`);
6655
+ }
6656
+ return await response.json();
6657
+ };
6662
6658
 
6663
6659
  // src/client/routingStatusWidget.ts
6664
6660
  var DEFAULT_TITLE10 = "Voice Routing";
@@ -6679,7 +6675,7 @@ var formatFallbackPath = (decision) => {
6679
6675
  return `${provider} primary`;
6680
6676
  };
6681
6677
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6682
- const decision = snapshot.decision;
6678
+ const { decision } = snapshot;
6683
6679
  const activeStack = decision ? [
6684
6680
  {
6685
6681
  label: "Profile",
@@ -6741,6 +6737,43 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6741
6737
  updatedAt: snapshot.updatedAt
6742
6738
  };
6743
6739
  };
6740
+ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status") => {
6741
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6742
+ return;
6743
+ }
6744
+ customElements.define(tagName, class AbsoluteVoiceRoutingStatusElement extends HTMLElement {
6745
+ mounted;
6746
+ connectedCallback() {
6747
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6748
+ this.mounted = mountVoiceRoutingStatus(this, this.getAttribute("path") ?? "/api/routing/latest", {
6749
+ description: this.getAttribute("description") ?? undefined,
6750
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6751
+ title: this.getAttribute("title") ?? undefined
6752
+ });
6753
+ }
6754
+ disconnectedCallback() {
6755
+ this.mounted?.close();
6756
+ this.mounted = undefined;
6757
+ }
6758
+ });
6759
+ };
6760
+ var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
6761
+ var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
6762
+ const store = createVoiceRoutingStatusStore(path, options);
6763
+ const render = () => {
6764
+ element.innerHTML = renderVoiceRoutingStatusHTML(store.getSnapshot(), options);
6765
+ };
6766
+ const unsubscribe = store.subscribe(render);
6767
+ render();
6768
+ store.refresh().catch(() => {});
6769
+ return {
6770
+ refresh: store.refresh,
6771
+ close: () => {
6772
+ unsubscribe();
6773
+ store.close();
6774
+ }
6775
+ };
6776
+ };
6744
6777
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
6745
6778
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
6746
6779
  const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
@@ -6762,43 +6795,6 @@ var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
6762
6795
  ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml(model.error)}</p>` : ""}
6763
6796
  </section>`;
6764
6797
  };
6765
- var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
6766
- var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
6767
- const store = createVoiceRoutingStatusStore(path, options);
6768
- const render = () => {
6769
- element.innerHTML = renderVoiceRoutingStatusHTML(store.getSnapshot(), options);
6770
- };
6771
- const unsubscribe = store.subscribe(render);
6772
- render();
6773
- store.refresh().catch(() => {});
6774
- return {
6775
- close: () => {
6776
- unsubscribe();
6777
- store.close();
6778
- },
6779
- refresh: store.refresh
6780
- };
6781
- };
6782
- var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status") => {
6783
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6784
- return;
6785
- }
6786
- customElements.define(tagName, class AbsoluteVoiceRoutingStatusElement extends HTMLElement {
6787
- mounted;
6788
- connectedCallback() {
6789
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6790
- this.mounted = mountVoiceRoutingStatus(this, this.getAttribute("path") ?? "/api/routing/latest", {
6791
- description: this.getAttribute("description") ?? undefined,
6792
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6793
- title: this.getAttribute("title") ?? undefined
6794
- });
6795
- }
6796
- disconnectedCallback() {
6797
- this.mounted?.close();
6798
- this.mounted = undefined;
6799
- }
6800
- });
6801
- };
6802
6798
 
6803
6799
  // src/svelte/createVoiceRoutingStatus.ts
6804
6800
  var createVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
@@ -6810,14 +6806,6 @@ var createVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
6810
6806
  };
6811
6807
  };
6812
6808
  // src/client/traceTimeline.ts
6813
- var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
6814
- const fetchImpl = options.fetch ?? globalThis.fetch;
6815
- const response = await fetchImpl(path);
6816
- if (!response.ok) {
6817
- throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
6818
- }
6819
- return await response.json();
6820
- };
6821
6809
  var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
6822
6810
  const listeners = new Set;
6823
6811
  let closed = false;
@@ -6877,9 +6865,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
6877
6865
  }
6878
6866
  return {
6879
6867
  close,
6868
+ refresh,
6880
6869
  getServerSnapshot: () => snapshot,
6881
6870
  getSnapshot: () => snapshot,
6882
- refresh,
6883
6871
  subscribe: (listener) => {
6884
6872
  listeners.add(listener);
6885
6873
  return () => {
@@ -6888,6 +6876,14 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
6888
6876
  }
6889
6877
  };
6890
6878
  };
6879
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
6880
+ const fetchImpl = options.fetch ?? globalThis.fetch;
6881
+ const response = await fetchImpl(path);
6882
+ if (!response.ok) {
6883
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
6884
+ }
6885
+ return await response.json();
6886
+ };
6891
6887
 
6892
6888
  // src/client/traceTimelineWidget.ts
6893
6889
  var DEFAULT_TITLE11 = "Voice Traces";
@@ -6917,6 +6913,48 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
6917
6913
  updatedAt: snapshot.updatedAt
6918
6914
  };
6919
6915
  };
6916
+ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline") => {
6917
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6918
+ return;
6919
+ }
6920
+ customElements.define(tagName, class AbsoluteVoiceTraceTimelineElement extends HTMLElement {
6921
+ mounted;
6922
+ connectedCallback() {
6923
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6924
+ const limit = Number(this.getAttribute("limit") ?? 3);
6925
+ this.mounted = mountVoiceTraceTimeline(this, this.getAttribute("path") ?? "/api/voice-traces", {
6926
+ description: this.getAttribute("description") ?? undefined,
6927
+ detailBasePath: this.getAttribute("detail-base-path") ?? undefined,
6928
+ incidentBundleBasePath: this.getAttribute("incident-bundle-base-path") ?? undefined,
6929
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6930
+ limit: Number.isFinite(limit) ? limit : 3,
6931
+ operationsRecordBasePath: this.getAttribute("operations-record-base-path") ?? undefined,
6932
+ title: this.getAttribute("title") ?? undefined
6933
+ });
6934
+ }
6935
+ disconnectedCallback() {
6936
+ this.mounted?.close();
6937
+ this.mounted = undefined;
6938
+ }
6939
+ });
6940
+ };
6941
+ var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__actions{display:flex;flex-wrap:wrap;gap:10px}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
6942
+ var mountVoiceTraceTimeline = (element, path = "/api/voice-traces", options = {}) => {
6943
+ const store = createVoiceTraceTimelineStore(path, options);
6944
+ const render = () => {
6945
+ element.innerHTML = renderVoiceTraceTimelineWidgetHTML(store.getSnapshot(), options);
6946
+ };
6947
+ const unsubscribe = store.subscribe(render);
6948
+ render();
6949
+ store.refresh().catch(() => {});
6950
+ return {
6951
+ refresh: store.refresh,
6952
+ close: () => {
6953
+ unsubscribe();
6954
+ store.close();
6955
+ }
6956
+ };
6957
+ };
6920
6958
  var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
6921
6959
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
6922
6960
  const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
@@ -6944,48 +6982,6 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
6944
6982
  ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml(model.error)}</p>` : ""}
6945
6983
  </section>`;
6946
6984
  };
6947
- var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__actions{display:flex;flex-wrap:wrap;gap:10px}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
6948
- var mountVoiceTraceTimeline = (element, path = "/api/voice-traces", options = {}) => {
6949
- const store = createVoiceTraceTimelineStore(path, options);
6950
- const render = () => {
6951
- element.innerHTML = renderVoiceTraceTimelineWidgetHTML(store.getSnapshot(), options);
6952
- };
6953
- const unsubscribe = store.subscribe(render);
6954
- render();
6955
- store.refresh().catch(() => {});
6956
- return {
6957
- close: () => {
6958
- unsubscribe();
6959
- store.close();
6960
- },
6961
- refresh: store.refresh
6962
- };
6963
- };
6964
- var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline") => {
6965
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
6966
- return;
6967
- }
6968
- customElements.define(tagName, class AbsoluteVoiceTraceTimelineElement extends HTMLElement {
6969
- mounted;
6970
- connectedCallback() {
6971
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
6972
- const limit = Number(this.getAttribute("limit") ?? 3);
6973
- this.mounted = mountVoiceTraceTimeline(this, this.getAttribute("path") ?? "/api/voice-traces", {
6974
- description: this.getAttribute("description") ?? undefined,
6975
- detailBasePath: this.getAttribute("detail-base-path") ?? undefined,
6976
- incidentBundleBasePath: this.getAttribute("incident-bundle-base-path") ?? undefined,
6977
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
6978
- limit: Number.isFinite(limit) ? limit : 3,
6979
- operationsRecordBasePath: this.getAttribute("operations-record-base-path") ?? undefined,
6980
- title: this.getAttribute("title") ?? undefined
6981
- });
6982
- }
6983
- disconnectedCallback() {
6984
- this.mounted?.close();
6985
- this.mounted = undefined;
6986
- }
6987
- });
6988
- };
6989
6985
 
6990
6986
  // src/svelte/createVoiceTraceTimeline.ts
6991
6987
  var createVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
@@ -7095,50 +7091,6 @@ var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
7095
7091
  title: options.title ?? DEFAULT_TITLE12,
7096
7092
  updatedAt: snapshot.updatedAt
7097
7093
  });
7098
- var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
7099
- const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
7100
- const current = model.current;
7101
- const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
7102
- <span>${escapeHtml(session.sessionId)}</span>
7103
- <strong>${escapeHtml(session.targetAgentId ?? "none")}</strong>
7104
- <em>${escapeHtml(session.status)}</em>
7105
- ${session.summary || session.reason ? `<p>${escapeHtml(session.summary ?? session.reason ?? "")}</p>` : ""}
7106
- </li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
7107
- return `<section class="absolute-voice-agent-squad-status">
7108
- <header>
7109
- <span>${escapeHtml(model.title)}</span>
7110
- <strong>${escapeHtml(model.label)}</strong>
7111
- </header>
7112
- <p>${escapeHtml(model.description)}</p>
7113
- <div>
7114
- <span>Session</span><strong>${escapeHtml(current?.sessionId ?? "n/a")}</strong>
7115
- <span>From</span><strong>${escapeHtml(current?.fromAgentId ?? "n/a")}</strong>
7116
- <span>Status</span><strong>${escapeHtml(current?.status ?? "idle")}</strong>
7117
- </div>
7118
- <ul>${rows}</ul>
7119
- ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml(model.error)}</p>` : ""}
7120
- </section>`;
7121
- };
7122
- var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
7123
- var mountVoiceAgentSquadStatus = (element, path = "/api/voice-traces", options = {}) => {
7124
- if (!element) {
7125
- throw new Error("mountVoiceAgentSquadStatus requires an element.");
7126
- }
7127
- const store = createVoiceAgentSquadStatusStore(path, options);
7128
- const render = () => {
7129
- element.innerHTML = `<style>${getVoiceAgentSquadStatusCSS()}</style>${renderVoiceAgentSquadStatusHTML(store.getSnapshot(), options)}`;
7130
- };
7131
- const unsubscribe = store.subscribe(render);
7132
- render();
7133
- store.refresh().catch(() => {});
7134
- return {
7135
- close: () => {
7136
- unsubscribe();
7137
- store.close();
7138
- },
7139
- refresh: store.refresh
7140
- };
7141
- };
7142
7094
  var defineVoiceAgentSquadStatusElement = (tagName = "absolute-voice-agent-squad-status", options = {}) => {
7143
7095
  if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
7144
7096
  return;
@@ -7159,36 +7111,64 @@ var defineVoiceAgentSquadStatusElement = (tagName = "absolute-voice-agent-squad-
7159
7111
  }
7160
7112
  });
7161
7113
  };
7114
+ var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
7115
+ var mountVoiceAgentSquadStatus = (element, path = "/api/voice-traces", options = {}) => {
7116
+ if (!element) {
7117
+ throw new Error("mountVoiceAgentSquadStatus requires an element.");
7118
+ }
7119
+ const store = createVoiceAgentSquadStatusStore(path, options);
7120
+ const render = () => {
7121
+ element.innerHTML = `<style>${getVoiceAgentSquadStatusCSS()}</style>${renderVoiceAgentSquadStatusHTML(store.getSnapshot(), options)}`;
7122
+ };
7123
+ const unsubscribe = store.subscribe(render);
7124
+ render();
7125
+ store.refresh().catch(() => {});
7126
+ return {
7127
+ refresh: store.refresh,
7128
+ close: () => {
7129
+ unsubscribe();
7130
+ store.close();
7131
+ }
7132
+ };
7133
+ };
7134
+ var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
7135
+ const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
7136
+ const { current } = model;
7137
+ const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
7138
+ <span>${escapeHtml(session.sessionId)}</span>
7139
+ <strong>${escapeHtml(session.targetAgentId ?? "none")}</strong>
7140
+ <em>${escapeHtml(session.status)}</em>
7141
+ ${session.summary || session.reason ? `<p>${escapeHtml(session.summary ?? session.reason ?? "")}</p>` : ""}
7142
+ </li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
7143
+ return `<section class="absolute-voice-agent-squad-status">
7144
+ <header>
7145
+ <span>${escapeHtml(model.title)}</span>
7146
+ <strong>${escapeHtml(model.label)}</strong>
7147
+ </header>
7148
+ <p>${escapeHtml(model.description)}</p>
7149
+ <div>
7150
+ <span>Session</span><strong>${escapeHtml(current?.sessionId ?? "n/a")}</strong>
7151
+ <span>From</span><strong>${escapeHtml(current?.fromAgentId ?? "n/a")}</strong>
7152
+ <span>Status</span><strong>${escapeHtml(current?.status ?? "idle")}</strong>
7153
+ </div>
7154
+ <ul>${rows}</ul>
7155
+ ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml(model.error)}</p>` : ""}
7156
+ </section>`;
7157
+ };
7162
7158
 
7163
7159
  // src/svelte/createVoiceAgentSquadStatus.ts
7164
7160
  var createVoiceAgentSquadStatus = (path = "/api/voice-traces", options = {}) => {
7165
7161
  const store = createVoiceAgentSquadStatusStore(path, options);
7166
7162
  return {
7167
7163
  close: store.close,
7168
- getHTML: () => renderVoiceAgentSquadStatusHTML(store.getSnapshot(), options),
7169
7164
  getSnapshot: store.getSnapshot,
7170
- getViewModel: () => createVoiceAgentSquadStatusViewModel(store.getSnapshot(), options),
7171
7165
  refresh: store.refresh,
7172
- subscribe: store.subscribe
7166
+ subscribe: store.subscribe,
7167
+ getHTML: () => renderVoiceAgentSquadStatusHTML(store.getSnapshot(), options),
7168
+ getViewModel: () => createVoiceAgentSquadStatusViewModel(store.getSnapshot(), options)
7173
7169
  };
7174
7170
  };
7175
7171
  // src/client/turnLatency.ts
7176
- var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
7177
- const fetchImpl = options.fetch ?? globalThis.fetch;
7178
- const response = await fetchImpl(path);
7179
- if (!response.ok) {
7180
- throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
7181
- }
7182
- return await response.json();
7183
- };
7184
- var runVoiceTurnLatencyProof = async (path, options = {}) => {
7185
- const fetchImpl = options.fetch ?? globalThis.fetch;
7186
- const response = await fetchImpl(path, { method: "POST" });
7187
- if (!response.ok) {
7188
- throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
7189
- }
7190
- return response.json();
7191
- };
7192
7172
  var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
7193
7173
  const listeners = new Set;
7194
7174
  let closed = false;
@@ -7262,10 +7242,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
7262
7242
  }
7263
7243
  return {
7264
7244
  close,
7265
- getServerSnapshot: () => snapshot,
7266
- getSnapshot: () => snapshot,
7267
7245
  refresh,
7268
7246
  runProof,
7247
+ getServerSnapshot: () => snapshot,
7248
+ getSnapshot: () => snapshot,
7269
7249
  subscribe: (listener) => {
7270
7250
  listeners.add(listener);
7271
7251
  return () => {
@@ -7274,6 +7254,22 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
7274
7254
  }
7275
7255
  };
7276
7256
  };
7257
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
7258
+ const fetchImpl = options.fetch ?? globalThis.fetch;
7259
+ const response = await fetchImpl(path);
7260
+ if (!response.ok) {
7261
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
7262
+ }
7263
+ return await response.json();
7264
+ };
7265
+ var runVoiceTurnLatencyProof = async (path, options = {}) => {
7266
+ const fetchImpl = options.fetch ?? globalThis.fetch;
7267
+ const response = await fetchImpl(path, { method: "POST" });
7268
+ if (!response.ok) {
7269
+ throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
7270
+ }
7271
+ return response.json();
7272
+ };
7277
7273
 
7278
7274
  // src/client/turnLatencyWidget.ts
7279
7275
  var DEFAULT_TITLE13 = "Turn Latency";
@@ -7304,28 +7300,27 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
7304
7300
  updatedAt: snapshot.updatedAt
7305
7301
  };
7306
7302
  };
7307
- var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
7308
- const model = createVoiceTurnLatencyViewModel(snapshot, options);
7309
- const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml(turn.status)}">
7310
- <header>
7311
- <strong>${escapeHtml(turn.label)}</strong>
7312
- <span>${escapeHtml(turn.status)}</span>
7313
- </header>
7314
- <dl>${turn.rows.map((row) => `<div>
7315
- <dt>${escapeHtml(row.label)}</dt>
7316
- <dd>${escapeHtml(row.value)}</dd>
7317
- </div>`).join("")}</dl>
7318
- </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
7319
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml(model.status)}">
7320
- <header class="absolute-voice-turn-latency__header">
7321
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml(model.title)}</span>
7322
- <strong class="absolute-voice-turn-latency__label">${escapeHtml(model.label)}</strong>
7323
- </header>
7324
- <p class="absolute-voice-turn-latency__description">${escapeHtml(model.description)}</p>
7325
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
7326
- ${turns}
7327
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml(model.error)}</p>` : ""}
7328
- </section>`;
7303
+ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") => {
7304
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
7305
+ return;
7306
+ }
7307
+ customElements.define(tagName, class AbsoluteVoiceTurnLatencyElement extends HTMLElement {
7308
+ mounted;
7309
+ connectedCallback() {
7310
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
7311
+ this.mounted = mountVoiceTurnLatency(this, this.getAttribute("path") ?? "/api/turn-latency", {
7312
+ description: this.getAttribute("description") ?? undefined,
7313
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
7314
+ proofLabel: this.getAttribute("proof-label") ?? undefined,
7315
+ proofPath: this.getAttribute("proof-path") ?? undefined,
7316
+ title: this.getAttribute("title") ?? undefined
7317
+ });
7318
+ }
7319
+ disconnectedCallback() {
7320
+ this.mounted?.close();
7321
+ this.mounted = undefined;
7322
+ }
7323
+ });
7329
7324
  };
7330
7325
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
7331
7326
  const store = createVoiceTurnLatencyStore(path, options);
@@ -7333,7 +7328,7 @@ var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {})
7333
7328
  element.innerHTML = renderVoiceTurnLatencyHTML(store.getSnapshot(), options);
7334
7329
  };
7335
7330
  const handleClick = (event) => {
7336
- const target = event.target;
7331
+ const { target } = event;
7337
7332
  if (target instanceof Element && target.closest("[data-absolute-voice-turn-latency-proof]")) {
7338
7333
  store.runProof().catch(() => {});
7339
7334
  }
@@ -7343,35 +7338,36 @@ var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {})
7343
7338
  render();
7344
7339
  store.refresh().catch(() => {});
7345
7340
  return {
7341
+ refresh: store.refresh,
7346
7342
  close: () => {
7347
7343
  element.removeEventListener("click", handleClick);
7348
7344
  unsubscribe();
7349
7345
  store.close();
7350
- },
7351
- refresh: store.refresh
7346
+ }
7352
7347
  };
7353
7348
  };
7354
- var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") => {
7355
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
7356
- return;
7357
- }
7358
- customElements.define(tagName, class AbsoluteVoiceTurnLatencyElement extends HTMLElement {
7359
- mounted;
7360
- connectedCallback() {
7361
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
7362
- this.mounted = mountVoiceTurnLatency(this, this.getAttribute("path") ?? "/api/turn-latency", {
7363
- description: this.getAttribute("description") ?? undefined,
7364
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
7365
- proofLabel: this.getAttribute("proof-label") ?? undefined,
7366
- proofPath: this.getAttribute("proof-path") ?? undefined,
7367
- title: this.getAttribute("title") ?? undefined
7368
- });
7369
- }
7370
- disconnectedCallback() {
7371
- this.mounted?.close();
7372
- this.mounted = undefined;
7373
- }
7374
- });
7349
+ var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
7350
+ const model = createVoiceTurnLatencyViewModel(snapshot, options);
7351
+ const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml(turn.status)}">
7352
+ <header>
7353
+ <strong>${escapeHtml(turn.label)}</strong>
7354
+ <span>${escapeHtml(turn.status)}</span>
7355
+ </header>
7356
+ <dl>${turn.rows.map((row) => `<div>
7357
+ <dt>${escapeHtml(row.label)}</dt>
7358
+ <dd>${escapeHtml(row.value)}</dd>
7359
+ </div>`).join("")}</dl>
7360
+ </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
7361
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml(model.status)}">
7362
+ <header class="absolute-voice-turn-latency__header">
7363
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml(model.title)}</span>
7364
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml(model.label)}</strong>
7365
+ </header>
7366
+ <p class="absolute-voice-turn-latency__description">${escapeHtml(model.description)}</p>
7367
+ ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
7368
+ ${turns}
7369
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml(model.error)}</p>` : ""}
7370
+ </section>`;
7375
7371
  };
7376
7372
 
7377
7373
  // src/svelte/createVoiceTurnLatency.ts
@@ -7384,14 +7380,6 @@ var createVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
7384
7380
  };
7385
7381
  };
7386
7382
  // src/client/turnQuality.ts
7387
- var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
7388
- const fetchImpl = options.fetch ?? globalThis.fetch;
7389
- const response = await fetchImpl(path);
7390
- if (!response.ok) {
7391
- throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
7392
- }
7393
- return await response.json();
7394
- };
7395
7383
  var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
7396
7384
  const listeners = new Set;
7397
7385
  let closed = false;
@@ -7450,9 +7438,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
7450
7438
  }
7451
7439
  return {
7452
7440
  close,
7441
+ refresh,
7453
7442
  getServerSnapshot: () => snapshot,
7454
7443
  getSnapshot: () => snapshot,
7455
- refresh,
7456
7444
  subscribe: (listener) => {
7457
7445
  listeners.add(listener);
7458
7446
  return () => {
@@ -7461,6 +7449,14 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
7461
7449
  }
7462
7450
  };
7463
7451
  };
7452
+ var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
7453
+ const fetchImpl = options.fetch ?? globalThis.fetch;
7454
+ const response = await fetchImpl(path);
7455
+ if (!response.ok) {
7456
+ throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
7457
+ }
7458
+ return await response.json();
7459
+ };
7464
7460
 
7465
7461
  // src/client/turnQualityWidget.ts
7466
7462
  var DEFAULT_TITLE14 = "Turn Quality";
@@ -7518,6 +7514,43 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
7518
7514
  updatedAt: snapshot.updatedAt
7519
7515
  };
7520
7516
  };
7517
+ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") => {
7518
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
7519
+ return;
7520
+ }
7521
+ customElements.define(tagName, class AbsoluteVoiceTurnQualityElement extends HTMLElement {
7522
+ mounted;
7523
+ connectedCallback() {
7524
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
7525
+ this.mounted = mountVoiceTurnQuality(this, this.getAttribute("path") ?? "/api/turn-quality", {
7526
+ description: this.getAttribute("description") ?? undefined,
7527
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
7528
+ title: this.getAttribute("title") ?? undefined
7529
+ });
7530
+ }
7531
+ disconnectedCallback() {
7532
+ this.mounted?.close();
7533
+ this.mounted = undefined;
7534
+ }
7535
+ });
7536
+ };
7537
+ var getVoiceTurnQualityCSS = () => `.absolute-voice-turn-quality{border:1px solid #e4d1a3;border-radius:20px;background:#fff9eb;color:#17120a;padding:18px;box-shadow:0 18px 40px rgba(73,48,14,.12);font-family:inherit}.absolute-voice-turn-quality--error,.absolute-voice-turn-quality--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-turn-quality__header,.absolute-voice-turn-quality__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-turn-quality__eyebrow{color:#8a5a0a;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-turn-quality__label{font-size:24px;line-height:1}.absolute-voice-turn-quality__description,.absolute-voice-turn-quality__turn p,.absolute-voice-turn-quality__turn dt,.absolute-voice-turn-quality__empty{color:#5a4930}.absolute-voice-turn-quality__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-turn-quality__turn{background:#fff;border:1px solid #f0dfba;border-radius:16px;padding:14px}.absolute-voice-turn-quality__turn--pass{border-color:#86efac}.absolute-voice-turn-quality__turn--warn,.absolute-voice-turn-quality__turn--unknown{border-color:#fbbf24}.absolute-voice-turn-quality__turn--fail{border-color:#f2a7a7}.absolute-voice-turn-quality__turn p{margin:10px 0}.absolute-voice-turn-quality__turn dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-turn-quality__turn div{background:#fff9eb;border:1px solid #f0dfba;border-radius:12px;padding:8px}.absolute-voice-turn-quality__turn dt{font-size:12px}.absolute-voice-turn-quality__turn dd{font-weight:800;margin:4px 0 0}.absolute-voice-turn-quality__empty{margin:14px 0 0}.absolute-voice-turn-quality__error{color:#9f1239;font-weight:700}`;
7538
+ var mountVoiceTurnQuality = (element, path = "/api/turn-quality", options = {}) => {
7539
+ const store = createVoiceTurnQualityStore(path, options);
7540
+ const render = () => {
7541
+ element.innerHTML = renderVoiceTurnQualityHTML(store.getSnapshot(), options);
7542
+ };
7543
+ const unsubscribe = store.subscribe(render);
7544
+ render();
7545
+ store.refresh().catch(() => {});
7546
+ return {
7547
+ refresh: store.refresh,
7548
+ close: () => {
7549
+ unsubscribe();
7550
+ store.close();
7551
+ }
7552
+ };
7553
+ };
7521
7554
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
7522
7555
  const model = createVoiceTurnQualityViewModel(snapshot, options);
7523
7556
  const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml(turn.status)}">
@@ -7541,43 +7574,6 @@ var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
7541
7574
  ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml(model.error)}</p>` : ""}
7542
7575
  </section>`;
7543
7576
  };
7544
- var getVoiceTurnQualityCSS = () => `.absolute-voice-turn-quality{border:1px solid #e4d1a3;border-radius:20px;background:#fff9eb;color:#17120a;padding:18px;box-shadow:0 18px 40px rgba(73,48,14,.12);font-family:inherit}.absolute-voice-turn-quality--error,.absolute-voice-turn-quality--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-turn-quality__header,.absolute-voice-turn-quality__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-turn-quality__eyebrow{color:#8a5a0a;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-turn-quality__label{font-size:24px;line-height:1}.absolute-voice-turn-quality__description,.absolute-voice-turn-quality__turn p,.absolute-voice-turn-quality__turn dt,.absolute-voice-turn-quality__empty{color:#5a4930}.absolute-voice-turn-quality__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-turn-quality__turn{background:#fff;border:1px solid #f0dfba;border-radius:16px;padding:14px}.absolute-voice-turn-quality__turn--pass{border-color:#86efac}.absolute-voice-turn-quality__turn--warn,.absolute-voice-turn-quality__turn--unknown{border-color:#fbbf24}.absolute-voice-turn-quality__turn--fail{border-color:#f2a7a7}.absolute-voice-turn-quality__turn p{margin:10px 0}.absolute-voice-turn-quality__turn dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-turn-quality__turn div{background:#fff9eb;border:1px solid #f0dfba;border-radius:12px;padding:8px}.absolute-voice-turn-quality__turn dt{font-size:12px}.absolute-voice-turn-quality__turn dd{font-weight:800;margin:4px 0 0}.absolute-voice-turn-quality__empty{margin:14px 0 0}.absolute-voice-turn-quality__error{color:#9f1239;font-weight:700}`;
7545
- var mountVoiceTurnQuality = (element, path = "/api/turn-quality", options = {}) => {
7546
- const store = createVoiceTurnQualityStore(path, options);
7547
- const render = () => {
7548
- element.innerHTML = renderVoiceTurnQualityHTML(store.getSnapshot(), options);
7549
- };
7550
- const unsubscribe = store.subscribe(render);
7551
- render();
7552
- store.refresh().catch(() => {});
7553
- return {
7554
- close: () => {
7555
- unsubscribe();
7556
- store.close();
7557
- },
7558
- refresh: store.refresh
7559
- };
7560
- };
7561
- var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") => {
7562
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
7563
- return;
7564
- }
7565
- customElements.define(tagName, class AbsoluteVoiceTurnQualityElement extends HTMLElement {
7566
- mounted;
7567
- connectedCallback() {
7568
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
7569
- this.mounted = mountVoiceTurnQuality(this, this.getAttribute("path") ?? "/api/turn-quality", {
7570
- description: this.getAttribute("description") ?? undefined,
7571
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
7572
- title: this.getAttribute("title") ?? undefined
7573
- });
7574
- }
7575
- disconnectedCallback() {
7576
- this.mounted?.close();
7577
- this.mounted = undefined;
7578
- }
7579
- });
7580
- };
7581
7577
 
7582
7578
  // src/svelte/createVoiceTurnQuality.ts
7583
7579
  var createVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
@@ -7589,14 +7585,6 @@ var createVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
7589
7585
  };
7590
7586
  };
7591
7587
  // src/client/workflowStatus.ts
7592
- var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
7593
- const fetchImpl = options.fetch ?? globalThis.fetch;
7594
- const response = await fetchImpl(path);
7595
- if (!response.ok) {
7596
- throw new Error(`Voice workflow status failed: HTTP ${response.status}`);
7597
- }
7598
- return await response.json();
7599
- };
7600
7588
  var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options = {}) => {
7601
7589
  const listeners = new Set;
7602
7590
  let closed = false;
@@ -7655,9 +7643,9 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
7655
7643
  }
7656
7644
  return {
7657
7645
  close,
7646
+ refresh,
7658
7647
  getServerSnapshot: () => snapshot,
7659
7648
  getSnapshot: () => snapshot,
7660
- refresh,
7661
7649
  subscribe: (listener) => {
7662
7650
  listeners.add(listener);
7663
7651
  return () => {
@@ -7666,6 +7654,14 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
7666
7654
  }
7667
7655
  };
7668
7656
  };
7657
+ var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
7658
+ const fetchImpl = options.fetch ?? globalThis.fetch;
7659
+ const response = await fetchImpl(path);
7660
+ if (!response.ok) {
7661
+ throw new Error(`Voice workflow status failed: HTTP ${response.status}`);
7662
+ }
7663
+ return await response.json();
7664
+ };
7669
7665
 
7670
7666
  // src/svelte/createVoiceWorkflowStatus.ts
7671
7667
  var createVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => createVoiceWorkflowStatusStore(path, options);