@absolutejs/voice 0.0.22-beta.53 → 0.0.22-beta.530

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 (480) hide show
  1. package/README.md +4518 -951
  2. package/dist/agent.d.ts +79 -5
  3. package/dist/agentPerformanceReport.d.ts +40 -0
  4. package/dist/agentSquadContract.d.ts +98 -0
  5. package/dist/agentState.d.ts +12 -0
  6. package/dist/agentTools.d.ts +133 -0
  7. package/dist/aiScorecard.d.ts +32 -0
  8. package/dist/aiVoiceModel.d.ts +15 -0
  9. package/dist/amdDetector.d.ts +25 -0
  10. package/dist/angular/index.d.ts +36 -6
  11. package/dist/angular/index.js +3995 -577
  12. package/dist/angular/voice-agent-squad-status.service.d.ts +12 -0
  13. package/dist/angular/voice-call-debugger.service.d.ts +12 -0
  14. package/dist/angular/voice-call-player.service.d.ts +19 -0
  15. package/dist/angular/voice-campaign-dialer-proof.service.d.ts +14 -0
  16. package/dist/angular/voice-controller.service.d.ts +3 -1
  17. package/dist/angular/voice-cost-dashboard.service.d.ts +15 -0
  18. package/dist/angular/voice-delivery-runtime.component.d.ts +17 -0
  19. package/dist/angular/voice-delivery-runtime.service.d.ts +16 -0
  20. package/dist/angular/voice-live-agent-console.service.d.ts +16 -0
  21. package/dist/angular/voice-live-call-viewer.service.d.ts +16 -0
  22. package/dist/angular/voice-live-ops.service.d.ts +11 -0
  23. package/dist/angular/voice-ops-action-center.service.d.ts +13 -0
  24. package/dist/angular/voice-ops-status.component.d.ts +2 -2
  25. package/dist/angular/voice-ops-status.service.d.ts +12 -0
  26. package/dist/angular/voice-platform-coverage.service.d.ts +12 -0
  27. package/dist/angular/voice-profile-comparison.service.d.ts +12 -0
  28. package/dist/angular/voice-proof-trends.service.d.ts +12 -0
  29. package/dist/angular/voice-provider-capabilities.service.d.ts +12 -0
  30. package/dist/angular/voice-provider-contracts.service.d.ts +12 -0
  31. package/dist/angular/voice-provider-status.service.d.ts +2 -2
  32. package/dist/angular/voice-readiness-failures.service.d.ts +13 -0
  33. package/dist/angular/voice-reconnect-profile-evidence.service.d.ts +12 -0
  34. package/dist/angular/voice-replay-timeline.service.d.ts +13 -0
  35. package/dist/angular/voice-routing-status.service.d.ts +11 -0
  36. package/dist/angular/voice-session-observability.service.d.ts +12 -0
  37. package/dist/angular/voice-session-snapshot.service.d.ts +13 -0
  38. package/dist/angular/voice-stream.service.d.ts +4 -1
  39. package/dist/angular/voice-trace-timeline.service.d.ts +12 -0
  40. package/dist/angular/voice-turn-latency.service.d.ts +13 -0
  41. package/dist/angular/voice-turn-quality.service.d.ts +12 -0
  42. package/dist/angular/voice-widget.service.d.ts +18 -0
  43. package/dist/angular/voice-workflow-status.service.d.ts +2 -2
  44. package/dist/assistant.d.ts +12 -13
  45. package/dist/assistantExperiment.d.ts +41 -0
  46. package/dist/assistantHealth.d.ts +6 -6
  47. package/dist/assistantMemory.d.ts +3 -3
  48. package/dist/assistantMode.d.ts +22 -0
  49. package/dist/audioConditioning.d.ts +1 -1
  50. package/dist/audit.d.ts +131 -0
  51. package/dist/auditDeliveryRoutes.d.ts +85 -0
  52. package/dist/auditExport.d.ts +34 -0
  53. package/dist/auditRoutes.d.ts +66 -0
  54. package/dist/auditSinks.d.ts +151 -0
  55. package/dist/backchannel.d.ts +18 -0
  56. package/dist/bargeInRoutes.d.ts +56 -0
  57. package/dist/bookingFlow.d.ts +43 -0
  58. package/dist/browserCallProfiles.d.ts +120 -0
  59. package/dist/browserMediaRoutes.d.ts +62 -0
  60. package/dist/calendarAdapter.d.ts +47 -0
  61. package/dist/calendarSlots.d.ts +35 -0
  62. package/dist/callDebugger.d.ts +66 -0
  63. package/dist/callDisposition.d.ts +38 -0
  64. package/dist/callQuota.d.ts +54 -0
  65. package/dist/callScorecard.d.ts +53 -0
  66. package/dist/callerCRMLinker.d.ts +29 -0
  67. package/dist/callerMemory.d.ts +37 -0
  68. package/dist/callingWindow.d.ts +26 -0
  69. package/dist/campaign.d.ts +794 -0
  70. package/dist/campaignControls.d.ts +37 -0
  71. package/dist/campaignDialers.d.ts +111 -0
  72. package/dist/campaignTemplate.d.ts +16 -0
  73. package/dist/client/actions.d.ts +95 -1
  74. package/dist/client/agentSquadStatus.d.ts +37 -0
  75. package/dist/client/agentSquadStatusWidget.d.ts +24 -0
  76. package/dist/client/audioPlayer.d.ts +2 -2
  77. package/dist/client/bargeInMonitor.d.ts +7 -0
  78. package/dist/client/browserMedia.d.ts +8 -0
  79. package/dist/client/browserNoiseSuppression.d.ts +42 -0
  80. package/dist/client/browserVoiceSupport.d.ts +22 -0
  81. package/dist/client/callDebugger.d.ts +19 -0
  82. package/dist/client/callDebuggerWidget.d.ts +30 -0
  83. package/dist/client/callPlayer.d.ts +41 -0
  84. package/dist/client/campaignDialerProof.d.ts +23 -0
  85. package/dist/client/connection.d.ts +4 -3
  86. package/dist/client/controller.d.ts +1 -1
  87. package/dist/client/conversationAnalytics.d.ts +29 -0
  88. package/dist/client/costDashboard.d.ts +27 -0
  89. package/dist/client/createVoiceStream.d.ts +1 -1
  90. package/dist/client/deliveryRuntime.d.ts +34 -0
  91. package/dist/client/deliveryRuntimeWidget.d.ts +37 -0
  92. package/dist/client/duplex.d.ts +2 -2
  93. package/dist/client/htmx.d.ts +1 -1
  94. package/dist/client/htmxAttributes.d.ts +28 -0
  95. package/dist/client/htmxBootstrap.js +971 -15
  96. package/dist/client/htmxDashboardRenderers.d.ts +72 -0
  97. package/dist/client/index.d.ts +104 -15
  98. package/dist/client/index.js +10142 -139
  99. package/dist/client/liveAgentConsole.d.ts +28 -0
  100. package/dist/client/liveCallViewer.d.ts +42 -0
  101. package/dist/client/liveOps.d.ts +22 -0
  102. package/dist/client/liveOpsWidget.d.ts +23 -0
  103. package/dist/client/liveTurnLatency.d.ts +41 -0
  104. package/dist/client/microphone.d.ts +4 -4
  105. package/dist/client/opsActionCenter.d.ts +54 -0
  106. package/dist/client/opsActionCenterWidget.d.ts +29 -0
  107. package/dist/client/opsActionHistory.d.ts +19 -0
  108. package/dist/client/opsActionHistoryWidget.d.ts +11 -0
  109. package/dist/client/opsStatus.d.ts +19 -0
  110. package/dist/client/opsStatusWidget.d.ts +9 -9
  111. package/dist/client/platformCoverage.d.ts +19 -0
  112. package/dist/client/platformCoverageWidget.d.ts +37 -0
  113. package/dist/client/profileComparison.d.ts +19 -0
  114. package/dist/client/profileComparisonWidget.d.ts +41 -0
  115. package/dist/client/profileSwitchRecommendation.d.ts +19 -0
  116. package/dist/client/profileSwitchRecommendationWidget.d.ts +12 -0
  117. package/dist/client/proofTrends.d.ts +19 -0
  118. package/dist/client/proofTrendsWidget.d.ts +37 -0
  119. package/dist/client/providerCapabilities.d.ts +19 -0
  120. package/dist/client/providerCapabilitiesWidget.d.ts +32 -0
  121. package/dist/client/providerContracts.d.ts +19 -0
  122. package/dist/client/providerContractsWidget.d.ts +37 -0
  123. package/dist/client/providerSimulationControls.d.ts +33 -0
  124. package/dist/client/providerSimulationControlsWidget.d.ts +20 -0
  125. package/dist/client/providerStatus.d.ts +1 -1
  126. package/dist/client/providerStatusWidget.d.ts +32 -0
  127. package/dist/client/readinessFailures.d.ts +19 -0
  128. package/dist/client/readinessFailuresWidget.d.ts +42 -0
  129. package/dist/client/reconnectProfileEvidence.d.ts +19 -0
  130. package/dist/client/reconnectProfileEvidenceWidget.d.ts +39 -0
  131. package/dist/client/replayTimeline.d.ts +26 -0
  132. package/dist/client/routingStatus.d.ts +19 -0
  133. package/dist/client/routingStatusWidget.d.ts +32 -0
  134. package/dist/client/sessionObservability.d.ts +19 -0
  135. package/dist/client/sessionObservabilityWidget.d.ts +31 -0
  136. package/dist/client/sessionSnapshot.d.ts +21 -0
  137. package/dist/client/sessionSnapshotWidget.d.ts +33 -0
  138. package/dist/client/store.d.ts +1 -1
  139. package/dist/client/traceTimeline.d.ts +19 -0
  140. package/dist/client/traceTimelineWidget.d.ts +36 -0
  141. package/dist/client/turnLatency.d.ts +22 -0
  142. package/dist/client/turnLatencyWidget.d.ts +33 -0
  143. package/dist/client/turnQuality.d.ts +19 -0
  144. package/dist/client/turnQualityWidget.d.ts +32 -0
  145. package/dist/client/voiceWidgetView.d.ts +50 -0
  146. package/dist/client/workflowStatus.d.ts +1 -1
  147. package/dist/competitiveCoverage.d.ts +141 -0
  148. package/dist/conversationSimulator.d.ts +73 -0
  149. package/dist/correction.d.ts +2 -2
  150. package/dist/costAccounting.d.ts +76 -0
  151. package/dist/costPredictor.d.ts +74 -0
  152. package/dist/crmCallLogger.d.ts +37 -0
  153. package/dist/crmContract.d.ts +70 -0
  154. package/dist/dataControl.d.ts +180 -0
  155. package/dist/defineVoiceAssistant.d.ts +68 -0
  156. package/dist/deliveryRuntime.d.ts +158 -0
  157. package/dist/deliverySinkRoutes.d.ts +117 -0
  158. package/dist/demoReadyRoutes.d.ts +98 -0
  159. package/dist/diagnosticsRoutes.d.ts +2 -2
  160. package/dist/dncRegistry.d.ts +38 -0
  161. package/dist/dtmfCollector.d.ts +37 -0
  162. package/dist/embed/index.d.ts +38 -0
  163. package/dist/embed/index.js +1710 -0
  164. package/dist/embed/voice-widget.js +10 -0
  165. package/dist/evalRoutes.d.ts +10 -4
  166. package/dist/fileStore.d.ts +21 -7
  167. package/dist/guardrails.d.ts +128 -0
  168. package/dist/handoff.d.ts +6 -6
  169. package/dist/handoffHealth.d.ts +5 -5
  170. package/dist/holdAudio.d.ts +23 -0
  171. package/dist/htmx.d.ts +1 -1
  172. package/dist/htmxDashboardRoutes.d.ts +249 -0
  173. package/dist/iceServers.d.ts +34 -0
  174. package/dist/incidentBundle.d.ts +119 -0
  175. package/dist/incidentTimeline.d.ts +260 -0
  176. package/dist/index.d.ts +369 -74
  177. package/dist/index.js +44682 -6184
  178. package/dist/internal/html.d.ts +6 -0
  179. package/dist/internal/status.d.ts +9 -0
  180. package/dist/ivrPlan.d.ts +40 -0
  181. package/dist/latencySlo.d.ts +56 -0
  182. package/dist/liveCoach.d.ts +43 -0
  183. package/dist/liveLatency.d.ts +78 -0
  184. package/dist/liveOps.d.ts +190 -0
  185. package/dist/llmJudge.d.ts +45 -0
  186. package/dist/logger.d.ts +1 -1
  187. package/dist/mcpToolset.d.ts +58 -0
  188. package/dist/mediaPipelineRoutes.d.ts +171 -0
  189. package/dist/mediaPipelineSurfaces.d.ts +48 -0
  190. package/dist/memoryStore.d.ts +1 -1
  191. package/dist/midCallSummary.d.ts +27 -0
  192. package/dist/modelAdapters.d.ts +59 -7
  193. package/dist/monitor.d.ts +148 -0
  194. package/dist/multilingualProof.d.ts +77 -0
  195. package/dist/noShowPredictor.d.ts +46 -0
  196. package/dist/oauth2TokenSource.d.ts +21 -0
  197. package/dist/observabilityExport.d.ts +501 -0
  198. package/dist/openaiTTS.d.ts +18 -0
  199. package/dist/operationalStatus.d.ts +87 -0
  200. package/dist/operationsRecord.d.ts +370 -0
  201. package/dist/ops.d.ts +12 -12
  202. package/dist/opsActionAuditRoutes.d.ts +99 -0
  203. package/dist/opsConsoleRoutes.d.ts +8 -5
  204. package/dist/opsPresets.d.ts +2 -2
  205. package/dist/opsRecovery.d.ts +137 -0
  206. package/dist/opsRuntime.d.ts +6 -6
  207. package/dist/opsSinks.d.ts +13 -13
  208. package/dist/opsStatus.d.ts +76 -0
  209. package/dist/opsStatusRoutes.d.ts +33 -0
  210. package/dist/opsWebhook.d.ts +6 -6
  211. package/dist/otelExporter.d.ts +83 -0
  212. package/dist/outcomeContract.d.ts +146 -0
  213. package/dist/outcomeRecipes.d.ts +4 -4
  214. package/dist/pathway.d.ts +94 -0
  215. package/dist/pathwayCompiler.d.ts +31 -0
  216. package/dist/pathwayGenerator.d.ts +27 -0
  217. package/dist/pathwayRuntime.d.ts +57 -0
  218. package/dist/pathwaySlotCollector.d.ts +29 -0
  219. package/dist/pathwayVisualizer.d.ts +8 -0
  220. package/dist/phoneAgent.d.ts +139 -0
  221. package/dist/phoneAgentProductionSmoke.d.ts +115 -0
  222. package/dist/phoneProvisioning.d.ts +29 -0
  223. package/dist/platformCoverage.d.ts +91 -0
  224. package/dist/plugin.d.ts +2 -2
  225. package/dist/postCallAnalysis.d.ts +98 -0
  226. package/dist/postCallSurvey.d.ts +41 -0
  227. package/dist/postgresStore.d.ts +17 -6
  228. package/dist/presets.d.ts +3 -3
  229. package/dist/productionReadiness.d.ts +756 -0
  230. package/dist/profileSwitchRecommendation.d.ts +350 -0
  231. package/dist/promptInjectionGuard.d.ts +30 -0
  232. package/dist/proofAssertions.d.ts +32 -0
  233. package/dist/proofPack.d.ts +211 -0
  234. package/dist/proofRunner.d.ts +79 -0
  235. package/dist/proofTrends.d.ts +966 -0
  236. package/dist/providerAdapters.d.ts +16 -5
  237. package/dist/providerCapabilities.d.ts +92 -0
  238. package/dist/providerDecisionTraces.d.ts +130 -0
  239. package/dist/providerHealth.d.ts +13 -3
  240. package/dist/providerOrchestration.d.ts +109 -0
  241. package/dist/providerRouterTraces.d.ts +35 -0
  242. package/dist/providerRoutingContract.d.ts +71 -0
  243. package/dist/providerSlo.d.ts +142 -0
  244. package/dist/providerStackRecommendations.d.ts +187 -0
  245. package/dist/qualityDriftDetector.d.ts +44 -0
  246. package/dist/qualityRoutes.d.ts +4 -4
  247. package/dist/queue.d.ts +23 -14
  248. package/dist/ragTool.d.ts +52 -0
  249. package/dist/react/VoiceAgentSquadStatus.d.ts +5 -0
  250. package/dist/react/VoiceCallDebuggerLaunch.d.ts +6 -0
  251. package/dist/react/VoiceCallPlayer.d.ts +11 -0
  252. package/dist/react/VoiceCostDashboard.d.ts +10 -0
  253. package/dist/react/VoiceDeliveryRuntime.d.ts +7 -0
  254. package/dist/react/VoiceLiveAgentConsole.d.ts +11 -0
  255. package/dist/react/VoiceLiveCallViewer.d.ts +9 -0
  256. package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
  257. package/dist/react/VoiceOpsStatus.d.ts +1 -1
  258. package/dist/react/VoicePlatformCoverage.d.ts +6 -0
  259. package/dist/react/VoiceProfileComparison.d.ts +6 -0
  260. package/dist/react/VoiceProfileSwitchRecommendation.d.ts +6 -0
  261. package/dist/react/VoiceProofTrends.d.ts +6 -0
  262. package/dist/react/VoiceProviderCapabilities.d.ts +6 -0
  263. package/dist/react/VoiceProviderContracts.d.ts +6 -0
  264. package/dist/react/VoiceProviderSimulationControls.d.ts +5 -0
  265. package/dist/react/VoiceProviderStatus.d.ts +6 -0
  266. package/dist/react/VoiceReadinessFailures.d.ts +6 -0
  267. package/dist/react/VoiceReconnectProfileEvidence.d.ts +6 -0
  268. package/dist/react/VoiceReplayTimeline.d.ts +6 -0
  269. package/dist/react/VoiceRoutingStatus.d.ts +6 -0
  270. package/dist/react/VoiceSessionObservability.d.ts +6 -0
  271. package/dist/react/VoiceSessionSnapshot.d.ts +6 -0
  272. package/dist/react/VoiceTraceTimeline.d.ts +6 -0
  273. package/dist/react/VoiceTurnLatency.d.ts +6 -0
  274. package/dist/react/VoiceTurnQuality.d.ts +6 -0
  275. package/dist/react/VoiceWidget.d.ts +13 -0
  276. package/dist/react/index.d.ts +59 -6
  277. package/dist/react/index.js +12684 -322
  278. package/dist/react/useVoiceAgentSquadStatus.d.ts +8 -0
  279. package/dist/react/useVoiceCallDebugger.d.ts +8 -0
  280. package/dist/react/useVoiceCampaignDialerProof.d.ts +10 -0
  281. package/dist/react/useVoiceController.d.ts +4 -1
  282. package/dist/react/useVoiceDeliveryRuntime.d.ts +13 -0
  283. package/dist/react/useVoiceLiveOps.d.ts +9 -0
  284. package/dist/react/useVoiceOpsActionCenter.d.ts +11 -0
  285. package/dist/react/useVoiceOpsStatus.d.ts +8 -0
  286. package/dist/react/useVoicePlatformCoverage.d.ts +8 -0
  287. package/dist/react/useVoiceProfileComparison.d.ts +8 -0
  288. package/dist/react/useVoiceProfileSwitchRecommendation.d.ts +8 -0
  289. package/dist/react/useVoiceProofTrends.d.ts +8 -0
  290. package/dist/react/useVoiceProviderCapabilities.d.ts +8 -0
  291. package/dist/react/useVoiceProviderContracts.d.ts +8 -0
  292. package/dist/react/useVoiceProviderSimulationControls.d.ts +10 -0
  293. package/dist/react/useVoiceProviderStatus.d.ts +1 -1
  294. package/dist/react/useVoiceReadinessFailures.d.ts +8 -0
  295. package/dist/react/useVoiceReconnectProfileEvidence.d.ts +8 -0
  296. package/dist/react/useVoiceRoutingStatus.d.ts +8 -0
  297. package/dist/react/useVoiceSessionObservability.d.ts +8 -0
  298. package/dist/react/useVoiceSessionSnapshot.d.ts +9 -0
  299. package/dist/react/useVoiceStream.d.ts +4 -1
  300. package/dist/react/useVoiceTraceTimeline.d.ts +8 -0
  301. package/dist/react/useVoiceTurnLatency.d.ts +9 -0
  302. package/dist/react/useVoiceTurnQuality.d.ts +8 -0
  303. package/dist/react/useVoiceWorkflowStatus.d.ts +1 -1
  304. package/dist/readinessProfiles.d.ts +45 -0
  305. package/dist/realtimeChannel.d.ts +136 -0
  306. package/dist/realtimeProviderContracts.d.ts +133 -0
  307. package/dist/reconnectContract.d.ts +176 -0
  308. package/dist/recordingRedaction.d.ts +47 -0
  309. package/dist/recordingStore.d.ts +60 -0
  310. package/dist/redaction.d.ts +13 -0
  311. package/dist/reminderScheduler.d.ts +43 -0
  312. package/dist/resilienceRoutes.d.ts +45 -5
  313. package/dist/retention.d.ts +37 -0
  314. package/dist/retryPolicy.d.ts +38 -0
  315. package/dist/routeAuth.d.ts +58 -0
  316. package/dist/routing.d.ts +1 -1
  317. package/dist/runtimeOps.d.ts +3 -3
  318. package/dist/s3Store.d.ts +18 -3
  319. package/dist/scorecardCalibration.d.ts +31 -0
  320. package/dist/semanticTurn.d.ts +27 -0
  321. package/dist/session.d.ts +1 -1
  322. package/dist/sessionObservability.d.ts +145 -0
  323. package/dist/sessionReplay.d.ts +19 -7
  324. package/dist/sessionSnapshot.d.ts +109 -0
  325. package/dist/simulationSuite.d.ts +143 -0
  326. package/dist/sloCalibration.d.ts +185 -0
  327. package/dist/sqliteStore.d.ts +17 -6
  328. package/dist/store.d.ts +1 -1
  329. package/dist/supervisorPermissions.d.ts +33 -0
  330. package/dist/supervisorPresence.d.ts +49 -0
  331. package/dist/svelte/createVoiceAgentSquadStatus.d.ts +9 -0
  332. package/dist/svelte/createVoiceCallDebugger.d.ts +12 -0
  333. package/dist/svelte/createVoiceCallPlayer.d.ts +33 -0
  334. package/dist/svelte/createVoiceCampaignDialerProof.d.ts +9 -0
  335. package/dist/svelte/createVoiceCostDashboard.d.ts +13 -0
  336. package/dist/svelte/createVoiceDeliveryRuntime.d.ts +11 -0
  337. package/dist/svelte/createVoiceLiveAgentConsole.d.ts +23 -0
  338. package/dist/svelte/createVoiceLiveCallViewer.d.ts +26 -0
  339. package/dist/svelte/createVoiceLiveOps.d.ts +13 -0
  340. package/dist/svelte/createVoiceOpsActionCenter.d.ts +10 -0
  341. package/dist/svelte/createVoiceOpsStatus.d.ts +3 -3
  342. package/dist/svelte/createVoicePlatformCoverage.d.ts +7 -0
  343. package/dist/svelte/createVoiceProfileComparison.d.ts +7 -0
  344. package/dist/svelte/createVoiceProofTrends.d.ts +7 -0
  345. package/dist/svelte/createVoiceProviderCapabilities.d.ts +10 -0
  346. package/dist/svelte/createVoiceProviderContracts.d.ts +10 -0
  347. package/dist/svelte/createVoiceProviderSimulationControls.d.ts +11 -0
  348. package/dist/svelte/createVoiceProviderStatus.d.ts +4 -2
  349. package/dist/svelte/createVoiceReadinessFailures.d.ts +7 -0
  350. package/dist/svelte/createVoiceReconnectProfileEvidence.d.ts +7 -0
  351. package/dist/svelte/createVoiceReplayTimeline.d.ts +13 -0
  352. package/dist/svelte/createVoiceRoutingStatus.d.ts +10 -0
  353. package/dist/svelte/createVoiceSessionObservability.d.ts +10 -0
  354. package/dist/svelte/createVoiceSessionSnapshot.d.ts +13 -0
  355. package/dist/svelte/createVoiceStream.d.ts +1 -1
  356. package/dist/svelte/createVoiceTraceTimeline.d.ts +10 -0
  357. package/dist/svelte/createVoiceTurnLatency.d.ts +11 -0
  358. package/dist/svelte/createVoiceTurnQuality.d.ts +10 -0
  359. package/dist/svelte/createVoiceWidget.d.ts +19 -0
  360. package/dist/svelte/createVoiceWorkflowStatus.d.ts +1 -1
  361. package/dist/svelte/index.d.ts +37 -6
  362. package/dist/svelte/index.js +6834 -729
  363. package/dist/telephony/contract.d.ts +61 -0
  364. package/dist/telephony/matrix.d.ts +97 -0
  365. package/dist/telephony/plivo.d.ts +303 -0
  366. package/dist/telephony/response.d.ts +1 -1
  367. package/dist/telephony/security.d.ts +182 -0
  368. package/dist/telephony/telnyx.d.ts +291 -0
  369. package/dist/telephony/twilio.d.ts +147 -13
  370. package/dist/telephonyMediaRoutes.d.ts +72 -0
  371. package/dist/telephonyOutcome.d.ts +273 -0
  372. package/dist/testing/accuracy.d.ts +1 -1
  373. package/dist/testing/benchmark.d.ts +9 -9
  374. package/dist/testing/corrected.d.ts +5 -5
  375. package/dist/testing/duplex.d.ts +3 -3
  376. package/dist/testing/fixtures.d.ts +3 -3
  377. package/dist/testing/index.d.ts +13 -13
  378. package/dist/testing/index.js +5260 -158
  379. package/dist/testing/ioProviderSimulator.d.ts +5 -5
  380. package/dist/testing/providerSimulator.d.ts +5 -5
  381. package/dist/testing/review.d.ts +4 -4
  382. package/dist/testing/sessionBenchmark.d.ts +3 -3
  383. package/dist/testing/stt.d.ts +3 -3
  384. package/dist/testing/telephony.d.ts +25 -0
  385. package/dist/testing/tts.d.ts +1 -1
  386. package/dist/toolContract.d.ts +161 -0
  387. package/dist/toolRuntime.d.ts +50 -0
  388. package/dist/trace.d.ts +46 -7
  389. package/dist/traceDeliveryRoutes.d.ts +86 -0
  390. package/dist/traceTimeline.d.ts +97 -0
  391. package/dist/transcriptAnnotator.d.ts +41 -0
  392. package/dist/turnDetection.d.ts +1 -1
  393. package/dist/turnLatency.d.ts +95 -0
  394. package/dist/turnProfiles.d.ts +2 -2
  395. package/dist/turnQuality.d.ts +94 -0
  396. package/dist/types.d.ts +408 -80
  397. package/dist/vapiAdapter.d.ts +160 -0
  398. package/dist/variableAnalytics.d.ts +47 -0
  399. package/dist/voiceConfiguration.d.ts +8 -0
  400. package/dist/voiceMonitoring.d.ts +444 -0
  401. package/dist/vue/VoiceCallDebuggerLaunch.d.ts +68 -0
  402. package/dist/vue/VoiceCallPlayer.d.ts +40 -0
  403. package/dist/vue/VoiceCostDashboard.d.ts +57 -0
  404. package/dist/vue/VoiceDeliveryRuntime.d.ts +30 -0
  405. package/dist/vue/VoiceLiveAgentConsole.d.ts +50 -0
  406. package/dist/vue/VoiceLiveCallViewer.d.ts +35 -0
  407. package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
  408. package/dist/vue/VoicePlatformCoverage.d.ts +23 -0
  409. package/dist/vue/VoiceProofTrends.d.ts +21 -0
  410. package/dist/vue/VoiceProviderCapabilities.d.ts +51 -0
  411. package/dist/vue/VoiceProviderContracts.d.ts +21 -0
  412. package/dist/vue/VoiceProviderSimulationControls.d.ts +88 -0
  413. package/dist/vue/VoiceProviderStatus.d.ts +51 -0
  414. package/dist/vue/VoiceReadinessFailures.d.ts +21 -0
  415. package/dist/vue/VoiceReconnectProfileEvidence.d.ts +21 -0
  416. package/dist/vue/VoiceReplayTimeline.d.ts +17 -0
  417. package/dist/vue/VoiceRoutingStatus.d.ts +51 -0
  418. package/dist/vue/VoiceSessionObservability.d.ts +23 -0
  419. package/dist/vue/VoiceSessionSnapshot.d.ts +68 -0
  420. package/dist/vue/VoiceTurnLatency.d.ts +69 -0
  421. package/dist/vue/VoiceTurnQuality.d.ts +51 -0
  422. package/dist/vue/VoiceWidget.d.ts +77 -0
  423. package/dist/vue/index.d.ts +49 -6
  424. package/dist/vue/index.js +11965 -407
  425. package/dist/vue/useVoiceAgentSquadStatus.d.ts +9 -0
  426. package/dist/vue/useVoiceCallDebugger.d.ts +10 -0
  427. package/dist/vue/useVoiceCampaignDialerProof.d.ts +11 -0
  428. package/dist/vue/useVoiceController.d.ts +4 -2
  429. package/dist/vue/useVoiceDeliveryRuntime.d.ts +13 -0
  430. package/dist/vue/useVoiceLiveOps.d.ts +9 -0
  431. package/dist/vue/useVoiceOpsActionCenter.d.ts +11 -0
  432. package/dist/vue/useVoiceOpsStatus.d.ts +9 -0
  433. package/dist/vue/useVoicePlatformCoverage.d.ts +9 -0
  434. package/dist/vue/useVoiceProfileComparison.d.ts +9 -0
  435. package/dist/vue/useVoiceProofTrends.d.ts +9 -0
  436. package/dist/vue/useVoiceProviderCapabilities.d.ts +9 -0
  437. package/dist/vue/useVoiceProviderContracts.d.ts +9 -0
  438. package/dist/vue/useVoiceProviderSimulationControls.d.ts +24 -0
  439. package/dist/vue/useVoiceProviderStatus.d.ts +3 -3
  440. package/dist/vue/useVoiceReadinessFailures.d.ts +959 -0
  441. package/dist/vue/useVoiceReconnectProfileEvidence.d.ts +9 -0
  442. package/dist/vue/useVoiceRoutingStatus.d.ts +8 -0
  443. package/dist/vue/useVoiceSessionObservability.d.ts +9 -0
  444. package/dist/vue/useVoiceSessionSnapshot.d.ts +10 -0
  445. package/dist/vue/useVoiceStream.d.ts +5 -2
  446. package/dist/vue/useVoiceTraceTimeline.d.ts +9 -0
  447. package/dist/vue/useVoiceTurnLatency.d.ts +10 -0
  448. package/dist/vue/useVoiceTurnQuality.d.ts +9 -0
  449. package/dist/vue/useVoiceWorkflowStatus.d.ts +3 -3
  450. package/dist/webhookFanout.d.ts +48 -0
  451. package/dist/webhookVerification.d.ts +27 -0
  452. package/dist/whisperChannel.d.ts +50 -0
  453. package/dist/workflowContract.d.ts +8 -8
  454. package/dist/zeroDataRetention.d.ts +41 -0
  455. package/package.json +129 -256
  456. package/dist/angular/voice-app-kit-status.service.d.ts +0 -12
  457. package/dist/appKit.d.ts +0 -92
  458. package/dist/client/appKitStatus.d.ts +0 -19
  459. package/dist/react/useVoiceAppKitStatus.d.ts +0 -8
  460. package/dist/svelte/createVoiceAppKitStatus.d.ts +0 -8
  461. package/dist/vue/useVoiceAppKitStatus.d.ts +0 -9
  462. package/fixtures/README.md +0 -57
  463. package/fixtures/manifest.json +0 -199
  464. package/fixtures/pcm/dialogue-three-clean.pcm +0 -0
  465. package/fixtures/pcm/dialogue-three-mixed.pcm +0 -0
  466. package/fixtures/pcm/dialogue-two-clean.pcm +0 -0
  467. package/fixtures/pcm/dialogue-two-noisy.pcm +0 -0
  468. package/fixtures/pcm/multiturn-three-mixed.pcm +0 -0
  469. package/fixtures/pcm/multiturn-two-clean.pcm +0 -0
  470. package/fixtures/pcm/quietly-alone-clean.pcm +0 -0
  471. package/fixtures/pcm/rainstorms-noisy.pcm +0 -0
  472. package/fixtures/pcm/stella-bulgaria-bulgarian20.pcm +0 -0
  473. package/fixtures/pcm/stella-ghana-english507.pcm +0 -0
  474. package/fixtures/pcm/stella-india-english37.pcm +0 -0
  475. package/fixtures/pcm/stella-jamaica-jamaican-creole-english1.pcm +0 -0
  476. package/fixtures/pcm/stella-liberia-liberian-pidgin-english2.pcm +0 -0
  477. package/fixtures/pcm/stella-pakistan-english519.pcm +0 -0
  478. package/fixtures/pcm/stella-sierra-leone-krio5.pcm +0 -0
  479. package/fixtures/pcm/stella-singapore-english655.pcm +0 -0
  480. package/fixtures/pcm/traveled-back-route-clean.pcm +0 -0
@@ -10,6 +10,19 @@ var __name = (target, name) => {
10
10
  });
11
11
  return target;
12
12
  };
13
+ var __returnValue = (v) => v;
14
+ function __exportSetter(name, newValue) {
15
+ this[name] = __returnValue.bind(null, newValue);
16
+ }
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, {
20
+ get: all[name],
21
+ enumerable: true,
22
+ configurable: true,
23
+ set: __exportSetter.bind(all, name)
24
+ });
25
+ };
13
26
  var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
14
27
  var __typeError = (msg) => {
15
28
  throw TypeError(msg);
@@ -68,20 +81,21 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
68
81
  }
69
82
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
70
83
  };
84
+ var __require = import.meta.require;
71
85
 
72
- // src/angular/voice-ops-status.component.ts
73
- import { Component, Input, signal } from "@angular/core";
86
+ // src/angular/voice-ops-status.service.ts
87
+ import { computed, Injectable, signal } from "@angular/core";
74
88
 
75
- // src/client/appKitStatus.ts
76
- var fetchVoiceAppKitStatus = async (path = "/app-kit/status", options = {}) => {
89
+ // src/client/opsStatus.ts
90
+ var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
77
91
  const fetchImpl = options.fetch ?? globalThis.fetch;
78
92
  const response = await fetchImpl(path);
79
93
  if (!response.ok) {
80
- throw new Error(`Voice app kit status failed: HTTP ${response.status}`);
94
+ throw new Error(`Voice ops status failed: HTTP ${response.status}`);
81
95
  }
82
96
  return await response.json();
83
97
  };
84
- var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
98
+ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) => {
85
99
  const listeners = new Set;
86
100
  let closed = false;
87
101
  let timer;
@@ -105,7 +119,7 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
105
119
  };
106
120
  emit();
107
121
  try {
108
- const report = await fetchVoiceAppKitStatus(path, options);
122
+ const report = await fetchVoiceOpsStatus(path, options);
109
123
  snapshot = {
110
124
  error: null,
111
125
  isLoading: false,
@@ -151,281 +165,19 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
151
165
  };
152
166
  };
153
167
 
154
- // src/client/opsStatusWidget.ts
155
- var DEFAULT_TITLE = "Voice Ops Status";
156
- var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from the AbsoluteJS voice app kit.";
157
- var SURFACE_LABELS = {
158
- handoffs: "Handoffs",
159
- providers: "Providers",
160
- quality: "Quality",
161
- sessions: "Sessions",
162
- workflows: "Workflows"
163
- };
164
- var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
165
- var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
166
- var surfaceDetail = (surface) => {
167
- const total = readNumber(surface, "total");
168
- const failed = readNumber(surface, "failed");
169
- const degraded = readNumber(surface, "degraded");
170
- const source = surface && typeof surface === "object" && "source" in surface && typeof surface.source === "string" ? ` from ${surface.source}` : "";
171
- if (degraded > 0) {
172
- return `${degraded} degraded of ${total}`;
173
- }
174
- if (failed > 0) {
175
- return `${failed} failing of ${total}${source}`;
176
- }
177
- return total > 0 ? `${total} passing${source}` : `No failures${source}`;
178
- };
179
- var getVoiceOpsStatusLabel = (report, error) => {
180
- if (error) {
181
- return "Unavailable";
182
- }
183
- if (!report) {
184
- return "Checking";
185
- }
186
- return report.status === "pass" ? "Passing" : "Needs attention";
187
- };
188
- var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
189
- const report = snapshot.report;
190
- const surfaces = Object.entries(report?.surfaces ?? {}).map(([id, surface]) => {
191
- const failed = readNumber(surface, "failed") || readNumber(surface, "degraded");
192
- const total = readNumber(surface, "total");
193
- const status = surface && typeof surface === "object" && "status" in surface ? surface.status ?? "pass" : "pass";
194
- return {
195
- detail: surfaceDetail(surface),
196
- failed,
197
- id,
198
- label: SURFACE_LABELS[id] ?? id,
199
- status,
200
- total
201
- };
202
- });
203
- return {
204
- description: options.description ?? DEFAULT_DESCRIPTION,
205
- error: snapshot.error,
206
- isLoading: snapshot.isLoading,
207
- label: getVoiceOpsStatusLabel(report, snapshot.error),
208
- links: options.includeLinks === false ? [] : report?.links ?? [],
209
- passed: report?.passed ?? 0,
210
- status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
211
- surfaces,
212
- title: options.title ?? DEFAULT_TITLE,
213
- total: report?.total ?? 0,
214
- updatedAt: snapshot.updatedAt
215
- };
216
- };
217
- var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
218
- const model = createVoiceOpsStatusViewModel(snapshot, options);
219
- const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
220
- <span>${escapeHtml(surface.label)}</span>
221
- <strong>${escapeHtml(surface.detail)}</strong>
222
- </li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
223
- const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</nav>` : "";
224
- return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml(model.status)}">
225
- <header class="absolute-voice-ops-status__header">
226
- <span class="absolute-voice-ops-status__eyebrow">${escapeHtml(model.title)}</span>
227
- <strong class="absolute-voice-ops-status__label">${escapeHtml(model.label)}</strong>
228
- </header>
229
- <p class="absolute-voice-ops-status__description">${escapeHtml(model.description)}</p>
230
- <div class="absolute-voice-ops-status__summary">
231
- <span>${model.passed} passing</span>
232
- <span>${Math.max(model.total - model.passed, 0)} failing</span>
233
- <span>${model.total} checks</span>
234
- </div>
235
- <ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
236
- ${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml(model.error)}</p>` : ""}
237
- ${links}
238
- </section>`;
239
- };
240
- 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}`;
241
- var mountVoiceOpsStatus = (element, path = "/app-kit/status", options = {}) => {
242
- const store = createVoiceAppKitStatusStore(path, options);
243
- const render = () => {
244
- element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
245
- };
246
- const unsubscribe = store.subscribe(render);
247
- render();
248
- store.refresh().catch(() => {});
249
- return {
250
- close: () => {
251
- unsubscribe();
252
- store.close();
253
- },
254
- refresh: store.refresh
255
- };
256
- };
257
- var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
258
- if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
259
- return;
260
- }
261
- customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
262
- mounted;
263
- connectedCallback() {
264
- const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
265
- this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/app-kit/status", {
266
- description: this.getAttribute("description") ?? undefined,
267
- includeLinks: this.getAttribute("include-links") !== "false",
268
- intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
269
- title: this.getAttribute("title") ?? undefined
270
- });
271
- }
272
- disconnectedCallback() {
273
- this.mounted?.close();
274
- this.mounted = undefined;
275
- }
276
- });
277
- };
278
-
279
- // src/angular/voice-ops-status.component.ts
280
- var _dec = [
281
- Component({
282
- selector: "absolute-voice-ops-status",
283
- standalone: true,
284
- template: `
285
- <section
286
- class="absolute-voice-ops-status"
287
- [class.absolute-voice-ops-status--pass]="model().status === 'pass'"
288
- [class.absolute-voice-ops-status--fail]="model().status === 'fail'"
289
- [class.absolute-voice-ops-status--loading]="model().status === 'loading'"
290
- [class.absolute-voice-ops-status--error]="model().status === 'error'"
291
- >
292
- <header class="absolute-voice-ops-status__header">
293
- <span class="absolute-voice-ops-status__eyebrow">{{
294
- model().title
295
- }}</span>
296
- <strong class="absolute-voice-ops-status__label">{{
297
- model().label
298
- }}</strong>
299
- </header>
300
- <p class="absolute-voice-ops-status__description">
301
- {{ model().description }}
302
- </p>
303
- <div class="absolute-voice-ops-status__summary">
304
- <span>{{ model().passed }} passing</span>
305
- <span>{{ model().total - model().passed }} failing</span>
306
- <span>{{ model().total }} checks</span>
307
- </div>
308
- <ul class="absolute-voice-ops-status__surfaces">
309
- @if (model().surfaces.length > 0) {
310
- @for (surface of model().surfaces; track surface.id) {
311
- <li
312
- class="absolute-voice-ops-status__surface"
313
- [class.absolute-voice-ops-status__surface--pass]="
314
- surface.status === 'pass'
315
- "
316
- [class.absolute-voice-ops-status__surface--fail]="
317
- surface.status === 'fail'
318
- "
319
- >
320
- <span>{{ surface.label }}</span>
321
- <strong>{{ surface.detail }}</strong>
322
- </li>
323
- }
324
- } @else {
325
- <li class="absolute-voice-ops-status__surface">
326
- <span>Status</span>
327
- <strong>Waiting for first check</strong>
328
- </li>
329
- }
330
- </ul>
331
- @if (model().error) {
332
- <p class="absolute-voice-ops-status__error">{{ model().error }}</p>
333
- }
334
- @if (model().links.length > 0) {
335
- <nav class="absolute-voice-ops-status__links">
336
- @for (link of model().links.slice(0, 4); track link.href) {
337
- <a [href]="link.href">{{ link.label }}</a>
338
- }
339
- </nav>
340
- }
341
- </section>
342
- `
343
- })
344
- ];
345
- var _dec2 = [
346
- Input()
347
- ];
348
- var _dec3 = [
349
- Input()
350
- ];
351
- var _dec4 = [
352
- Input()
353
- ];
354
- var _dec5 = [
355
- Input()
356
- ];
357
- var _dec6 = [
358
- Input()
359
- ];
360
- var _init = __decoratorStart(undefined);
361
-
362
- class VoiceOpsStatusComponent {
363
- constructor() {
364
- this.description = __runInitializers(_init, 8, this);
365
- __runInitializers(_init, 11, this);
366
- this.includeLinks = __runInitializers(_init, 12, this, true);
367
- __runInitializers(_init, 15, this);
368
- this.intervalMs = __runInitializers(_init, 16, this);
369
- __runInitializers(_init, 19, this);
370
- this.path = __runInitializers(_init, 20, this, "/app-kit/status");
371
- __runInitializers(_init, 23, this);
372
- this.title = __runInitializers(_init, 24, this);
373
- __runInitializers(_init, 27, this);
374
- }
375
- cleanup = () => {};
376
- store;
377
- model = signal(createVoiceOpsStatusViewModel({
378
- error: null,
379
- isLoading: true
380
- }));
381
- ngOnInit() {
382
- const options = this.options();
383
- this.store = createVoiceAppKitStatusStore(this.path, options);
384
- const sync = () => {
385
- this.model.set(createVoiceOpsStatusViewModel(this.store.getSnapshot(), options));
386
- };
387
- this.cleanup = this.store.subscribe(sync);
388
- sync();
389
- if (typeof window !== "undefined") {
390
- this.store.refresh().catch(() => {});
391
- }
392
- }
393
- ngOnDestroy() {
394
- this.cleanup();
395
- this.store?.close();
396
- }
397
- options() {
398
- return {
399
- description: this.description,
400
- includeLinks: this.includeLinks,
401
- intervalMs: this.intervalMs,
402
- title: this.title
403
- };
404
- }
405
- }
406
- __decorateElement(_init, 5, "description", _dec2, VoiceOpsStatusComponent);
407
- __decorateElement(_init, 5, "includeLinks", _dec3, VoiceOpsStatusComponent);
408
- __decorateElement(_init, 5, "intervalMs", _dec4, VoiceOpsStatusComponent);
409
- __decorateElement(_init, 5, "path", _dec5, VoiceOpsStatusComponent);
410
- __decorateElement(_init, 5, "title", _dec6, VoiceOpsStatusComponent);
411
- VoiceOpsStatusComponent = __decorateElement(_init, 0, "VoiceOpsStatusComponent", _dec, VoiceOpsStatusComponent);
412
- __runInitializers(_init, 1, VoiceOpsStatusComponent);
413
- __decoratorMetadata(_init, VoiceOpsStatusComponent);
414
- let _VoiceOpsStatusComponent = VoiceOpsStatusComponent;
415
- // src/angular/voice-app-kit-status.service.ts
416
- import { computed, Injectable, signal as signal2 } from "@angular/core";
168
+ // src/angular/voice-ops-status.service.ts
417
169
  var _dec = [
418
170
  Injectable({ providedIn: "root" })
419
171
  ];
420
172
  var _init = __decoratorStart(undefined);
421
173
 
422
- class VoiceAppKitStatusService {
423
- connect(path = "/app-kit/status", options = {}) {
424
- const store = createVoiceAppKitStatusStore(path, options);
425
- const errorSignal = signal2(null);
426
- const isLoadingSignal = signal2(false);
427
- const reportSignal = signal2(undefined);
428
- const updatedAtSignal = signal2(undefined);
174
+ class VoiceOpsStatusService {
175
+ connect(path = "/api/voice/ops-status", options = {}) {
176
+ const store = createVoiceOpsStatusStore(path, options);
177
+ const errorSignal = signal(null);
178
+ const isLoadingSignal = signal(false);
179
+ const reportSignal = signal(undefined);
180
+ const updatedAtSignal = signal(undefined);
429
181
  const sync = () => {
430
182
  const snapshot = store.getSnapshot();
431
183
  errorSignal.set(snapshot.error);
@@ -451,12 +203,154 @@ class VoiceAppKitStatusService {
451
203
  };
452
204
  }
453
205
  }
454
- VoiceAppKitStatusService = __decorateElement(_init, 0, "VoiceAppKitStatusService", _dec, VoiceAppKitStatusService);
455
- __runInitializers(_init, 1, VoiceAppKitStatusService);
456
- __decoratorMetadata(_init, VoiceAppKitStatusService);
457
- let _VoiceAppKitStatusService = VoiceAppKitStatusService;
458
- // src/angular/voice-stream.service.ts
459
- import { computed as computed2, Injectable as Injectable2, signal as signal3 } from "@angular/core";
206
+ VoiceOpsStatusService = __decorateElement(_init, 0, "VoiceOpsStatusService", _dec, VoiceOpsStatusService);
207
+ __runInitializers(_init, 1, VoiceOpsStatusService);
208
+ __decoratorMetadata(_init, VoiceOpsStatusService);
209
+ let _VoiceOpsStatusService = VoiceOpsStatusService;
210
+ // src/angular/voice-widget.service.ts
211
+ import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
212
+
213
+ // src/client/htmx.ts
214
+ var DEFAULT_EVENT_NAME = "voice-refresh";
215
+ var DEFAULT_QUERY_PARAM = "sessionId";
216
+ var resolveElement = (input) => {
217
+ if (typeof input !== "string") {
218
+ return input;
219
+ }
220
+ return document.querySelector(input);
221
+ };
222
+ var buildRoute = (element, route, queryParam, sessionId) => {
223
+ const baseRoute = route ?? element.getAttribute("hx-get") ?? "";
224
+ if (!baseRoute) {
225
+ return "";
226
+ }
227
+ const url = new URL(baseRoute, window.location.origin);
228
+ if (sessionId) {
229
+ url.searchParams.set(queryParam, sessionId);
230
+ } else {
231
+ url.searchParams.delete(queryParam);
232
+ }
233
+ return `${url.pathname}${url.search}${url.hash}`;
234
+ };
235
+ var bindVoiceHTMX = (stream, options) => {
236
+ if (typeof window === "undefined" || typeof document === "undefined") {
237
+ return () => {};
238
+ }
239
+ const element = resolveElement(options.element);
240
+ if (!element) {
241
+ return () => {};
242
+ }
243
+ const eventName = options.eventName ?? DEFAULT_EVENT_NAME;
244
+ const queryParam = options.sessionQueryParam ?? DEFAULT_QUERY_PARAM;
245
+ const sync = () => {
246
+ const htmxWindow = window;
247
+ const nextRoute = buildRoute(element, options.route, queryParam, stream.sessionId);
248
+ if (nextRoute) {
249
+ element.setAttribute("hx-get", nextRoute);
250
+ }
251
+ htmxWindow.htmx?.process?.(element);
252
+ htmxWindow.htmx?.trigger?.(element, eventName);
253
+ };
254
+ const unsubscribe = stream.subscribe(sync);
255
+ sync();
256
+ return () => {
257
+ unsubscribe();
258
+ };
259
+ };
260
+
261
+ // src/client/microphone.ts
262
+ var clampSample = (value) => Math.max(-1, Math.min(1, value));
263
+ var floatTo16BitPCM = (input) => {
264
+ const output = new Int16Array(input.length);
265
+ for (let index = 0;index < input.length; index += 1) {
266
+ const sample = clampSample(input[index] ?? 0);
267
+ output[index] = sample < 0 ? sample * 32768 : sample * 32767;
268
+ }
269
+ return new Uint8Array(output.buffer);
270
+ };
271
+ var getPcmLevel = (audio) => {
272
+ const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
273
+ if (bytes.byteLength < 2) {
274
+ return 0;
275
+ }
276
+ const samples = new Int16Array(bytes.buffer, bytes.byteOffset, Math.floor(bytes.byteLength / 2));
277
+ if (samples.length === 0) {
278
+ return 0;
279
+ }
280
+ let sumSquares = 0;
281
+ for (const sample of samples) {
282
+ const normalized = sample / 32768;
283
+ sumSquares += normalized * normalized;
284
+ }
285
+ return Math.min(1, Math.max(0, Math.sqrt(sumSquares / samples.length) * 5.5));
286
+ };
287
+ var downsampleBuffer = (input, sourceRate, targetRate) => {
288
+ if (sourceRate === targetRate) {
289
+ return input;
290
+ }
291
+ const ratio = sourceRate / targetRate;
292
+ const length = Math.round(input.length / ratio);
293
+ const output = new Float32Array(length);
294
+ let offsetResult = 0;
295
+ let offsetBuffer = 0;
296
+ while (offsetResult < output.length) {
297
+ const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
298
+ let accum = 0;
299
+ let count = 0;
300
+ for (let index = offsetBuffer;index < nextOffsetBuffer && index < input.length; index += 1) {
301
+ accum += input[index] ?? 0;
302
+ count += 1;
303
+ }
304
+ output[offsetResult] = count > 0 ? accum / count : 0;
305
+ offsetResult += 1;
306
+ offsetBuffer = nextOffsetBuffer;
307
+ }
308
+ return output;
309
+ };
310
+ var createMicrophoneCapture = (options) => {
311
+ let audioContext = null;
312
+ let sourceNode = null;
313
+ let processorNode = null;
314
+ let mediaStream = null;
315
+ const start = async () => {
316
+ if (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia) {
317
+ throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
318
+ }
319
+ const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
320
+ if (!AudioContextCtor) {
321
+ throw new Error("Browser microphone capture requires AudioContext support.");
322
+ }
323
+ mediaStream = await navigator.mediaDevices.getUserMedia({
324
+ audio: {
325
+ channelCount: options.channelCount ?? 1
326
+ }
327
+ });
328
+ audioContext = new AudioContextCtor;
329
+ sourceNode = audioContext.createMediaStreamSource(mediaStream);
330
+ processorNode = audioContext.createScriptProcessor(4096, 1, 1);
331
+ processorNode.onaudioprocess = (event) => {
332
+ const channel = event.inputBuffer.getChannelData(0);
333
+ const downsampled = downsampleBuffer(channel, audioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
334
+ const pcm = floatTo16BitPCM(downsampled);
335
+ options.onLevel?.(getPcmLevel(pcm));
336
+ options.onAudio(pcm);
337
+ };
338
+ sourceNode.connect(processorNode);
339
+ processorNode.connect(audioContext.destination);
340
+ };
341
+ const stop = () => {
342
+ processorNode?.disconnect();
343
+ sourceNode?.disconnect();
344
+ mediaStream?.getTracks().forEach((track) => track.stop());
345
+ audioContext?.close();
346
+ options.onLevel?.(0);
347
+ audioContext = null;
348
+ mediaStream = null;
349
+ processorNode = null;
350
+ sourceNode = null;
351
+ };
352
+ return { start, stop };
353
+ };
460
354
 
461
355
  // src/client/actions.ts
462
356
  var normalizeErrorMessage = (value) => {
@@ -506,6 +400,11 @@ var serverMessageToAction = (message) => {
506
400
  sessionId: message.sessionId,
507
401
  type: "complete"
508
402
  };
403
+ case "connection":
404
+ return {
405
+ reconnect: message.reconnect,
406
+ type: "connection"
407
+ };
509
408
  case "call_lifecycle":
510
409
  return {
511
410
  event: message.event,
@@ -527,9 +426,22 @@ var serverMessageToAction = (message) => {
527
426
  transcript: message.transcript,
528
427
  type: "partial"
529
428
  };
429
+ case "replay":
430
+ return {
431
+ assistantTexts: message.assistantTexts,
432
+ call: message.call,
433
+ partial: message.partial,
434
+ scenarioId: message.scenarioId,
435
+ sessionId: message.sessionId,
436
+ sessionMetadata: message.sessionMetadata,
437
+ status: message.status,
438
+ turns: message.turns,
439
+ type: "replay"
440
+ };
530
441
  case "session":
531
442
  return {
532
443
  sessionId: message.sessionId,
444
+ sessionMetadata: message.sessionMetadata,
533
445
  scenarioId: message.scenarioId,
534
446
  status: message.status,
535
447
  type: "session"
@@ -544,6 +456,84 @@ var serverMessageToAction = (message) => {
544
456
  }
545
457
  };
546
458
 
459
+ // src/client/browserMedia.ts
460
+ import {
461
+ buildMediaWebRTCStatsReport,
462
+ buildMediaWebRTCStreamContinuityReport,
463
+ collectMediaWebRTCStats
464
+ } from "@absolutejs/media";
465
+ var DEFAULT_BROWSER_MEDIA_PATH = "/api/voice/browser-media";
466
+ var DEFAULT_BROWSER_MEDIA_INTERVAL_MS = 5000;
467
+ var resolvePeerConnection = async (options) => options.peerConnection ?? await options.getPeerConnection?.() ?? null;
468
+ var postBrowserMediaReport = async (payload, options) => {
469
+ const requestFetch = options.fetch ?? globalThis.fetch;
470
+ if (!requestFetch) {
471
+ return;
472
+ }
473
+ await requestFetch(options.path ?? DEFAULT_BROWSER_MEDIA_PATH, {
474
+ body: JSON.stringify(payload),
475
+ headers: {
476
+ "Content-Type": "application/json"
477
+ },
478
+ keepalive: true,
479
+ method: "POST"
480
+ });
481
+ };
482
+ var createVoiceBrowserMediaReporter = (options) => {
483
+ let interval = null;
484
+ let previousStats = [];
485
+ const reportOnce = async () => {
486
+ const peerConnection = await resolvePeerConnection(options);
487
+ if (!peerConnection) {
488
+ return;
489
+ }
490
+ const stats = await collectMediaWebRTCStats({ peerConnection });
491
+ const report = buildMediaWebRTCStatsReport({
492
+ ...options,
493
+ stats
494
+ });
495
+ const continuity = options.continuity === false ? undefined : buildMediaWebRTCStreamContinuityReport({
496
+ ...options.continuity,
497
+ previousStats,
498
+ stats
499
+ });
500
+ const payload = {
501
+ at: Date.now(),
502
+ continuity,
503
+ report,
504
+ scenarioId: options.getScenarioId?.() ?? null,
505
+ sessionId: options.getSessionId?.() ?? null
506
+ };
507
+ previousStats = stats;
508
+ options.onReport?.(payload);
509
+ await postBrowserMediaReport(payload, options);
510
+ return payload;
511
+ };
512
+ const run = () => {
513
+ reportOnce().catch((error) => {
514
+ options.onError?.(error);
515
+ });
516
+ };
517
+ const stop = () => {
518
+ if (interval) {
519
+ clearInterval(interval);
520
+ interval = null;
521
+ }
522
+ };
523
+ return {
524
+ close: stop,
525
+ reportOnce,
526
+ start: () => {
527
+ if (interval) {
528
+ return;
529
+ }
530
+ run();
531
+ interval = setInterval(run, options.intervalMs ?? DEFAULT_BROWSER_MEDIA_INTERVAL_MS);
532
+ },
533
+ stop
534
+ };
535
+ };
536
+
547
537
  // src/client/connection.ts
548
538
  var WS_OPEN = 1;
549
539
  var WS_CLOSED = 3;
@@ -563,6 +553,7 @@ var NOOP_CONNECTION = {
563
553
  getSessionId: () => "",
564
554
  send: noop,
565
555
  sendAudio: noop,
556
+ simulateDisconnect: noop,
566
557
  start: () => {},
567
558
  subscribe: noopUnsubscribe
568
559
  };
@@ -587,10 +578,12 @@ var isVoiceServerMessage = (value) => {
587
578
  case "assistant":
588
579
  case "call_lifecycle":
589
580
  case "complete":
581
+ case "connection":
590
582
  case "error":
591
583
  case "final":
592
584
  case "partial":
593
585
  case "pong":
586
+ case "replay":
594
587
  case "session":
595
588
  case "turn":
596
589
  return true;
@@ -627,6 +620,9 @@ var createVoiceConnection = (path, options = {}) => {
627
620
  sessionId: options.sessionId ?? createSessionId(),
628
621
  ws: null
629
622
  };
623
+ const emitConnection = (reconnect) => {
624
+ listeners.forEach((listener) => listener(reconnect));
625
+ };
630
626
  const clearTimers = () => {
631
627
  if (state.pingInterval) {
632
628
  clearInterval(state.pingInterval);
@@ -649,9 +645,28 @@ var createVoiceConnection = (path, options = {}) => {
649
645
  }
650
646
  };
651
647
  const scheduleReconnect = () => {
648
+ const nextAttemptAt = Date.now() + RECONNECT_DELAY_MS;
652
649
  state.reconnectAttempts += 1;
650
+ emitConnection({
651
+ reconnect: {
652
+ attempts: state.reconnectAttempts,
653
+ lastDisconnectAt: Date.now(),
654
+ maxAttempts: maxReconnectAttempts,
655
+ nextAttemptAt,
656
+ status: "reconnecting"
657
+ },
658
+ type: "connection"
659
+ });
653
660
  state.reconnectTimeout = setTimeout(() => {
654
661
  if (state.reconnectAttempts > maxReconnectAttempts) {
662
+ emitConnection({
663
+ reconnect: {
664
+ attempts: state.reconnectAttempts,
665
+ maxAttempts: maxReconnectAttempts,
666
+ status: "exhausted"
667
+ },
668
+ type: "connection"
669
+ });
655
670
  return;
656
671
  }
657
672
  connect();
@@ -661,9 +676,21 @@ var createVoiceConnection = (path, options = {}) => {
661
676
  const ws = new WebSocket(buildWsUrl(path, state.sessionId, state.scenarioId));
662
677
  ws.binaryType = "arraybuffer";
663
678
  ws.onopen = () => {
679
+ const wasReconnecting = state.reconnectAttempts > 0;
664
680
  state.isConnected = true;
665
- state.reconnectAttempts = 0;
666
681
  flushPendingMessages();
682
+ if (wasReconnecting) {
683
+ emitConnection({
684
+ reconnect: {
685
+ attempts: state.reconnectAttempts,
686
+ lastResumedAt: Date.now(),
687
+ maxAttempts: maxReconnectAttempts,
688
+ status: "resumed"
689
+ },
690
+ type: "connection"
691
+ });
692
+ state.reconnectAttempts = 0;
693
+ }
667
694
  listeners.forEach((listener) => listener({
668
695
  scenarioId: state.scenarioId ?? undefined,
669
696
  sessionId: state.sessionId,
@@ -693,6 +720,16 @@ var createVoiceConnection = (path, options = {}) => {
693
720
  const reconnectable = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && state.reconnectAttempts < maxReconnectAttempts;
694
721
  if (reconnectable) {
695
722
  scheduleReconnect();
723
+ } else if (shouldReconnect && event.code !== WS_NORMAL_CLOSURE) {
724
+ emitConnection({
725
+ reconnect: {
726
+ attempts: state.reconnectAttempts,
727
+ lastDisconnectAt: Date.now(),
728
+ maxAttempts: maxReconnectAttempts,
729
+ status: "exhausted"
730
+ },
731
+ type: "connection"
732
+ });
696
733
  }
697
734
  };
698
735
  state.ws = ws;
@@ -741,6 +778,11 @@ var createVoiceConnection = (path, options = {}) => {
741
778
  state.isConnected = false;
742
779
  listeners.clear();
743
780
  };
781
+ const simulateDisconnect = () => {
782
+ if (state.ws?.readyState === WS_OPEN) {
783
+ state.ws.close(4000, "absolutejs-voice-reconnect-proof");
784
+ }
785
+ };
744
786
  const subscribe = (callback) => {
745
787
  listeners.add(callback);
746
788
  return () => {
@@ -757,20 +799,28 @@ var createVoiceConnection = (path, options = {}) => {
757
799
  getSessionId: () => state.sessionId,
758
800
  send,
759
801
  sendAudio,
802
+ simulateDisconnect,
760
803
  start,
761
804
  subscribe
762
805
  };
763
806
  };
764
807
 
765
808
  // src/client/store.ts
809
+ var createInitialReconnectState = () => ({
810
+ attempts: 0,
811
+ maxAttempts: 0,
812
+ status: "idle"
813
+ });
766
814
  var createInitialState = () => ({
767
815
  assistantAudio: [],
768
816
  assistantTexts: [],
769
817
  call: null,
770
818
  error: null,
771
819
  isConnected: false,
820
+ sessionMetadata: null,
772
821
  scenarioId: null,
773
822
  partial: "",
823
+ reconnect: createInitialReconnectState(),
774
824
  sessionId: null,
775
825
  status: "idle",
776
826
  turns: []
@@ -827,7 +877,19 @@ var createVoiceStreamStore = () => {
827
877
  case "connected":
828
878
  state = {
829
879
  ...state,
830
- isConnected: true
880
+ isConnected: true,
881
+ reconnect: state.reconnect.status === "reconnecting" ? {
882
+ ...state.reconnect,
883
+ lastResumedAt: Date.now(),
884
+ nextAttemptAt: undefined,
885
+ status: "resumed"
886
+ } : state.reconnect
887
+ };
888
+ break;
889
+ case "connection":
890
+ state = {
891
+ ...state,
892
+ reconnect: action.reconnect
831
893
  };
832
894
  break;
833
895
  case "disconnected":
@@ -855,6 +917,27 @@ var createVoiceStreamStore = () => {
855
917
  partial: action.transcript.text
856
918
  };
857
919
  break;
920
+ case "replay":
921
+ state = {
922
+ ...state,
923
+ assistantTexts: [...action.assistantTexts],
924
+ call: action.call ?? null,
925
+ error: null,
926
+ isConnected: action.status === "active",
927
+ partial: action.partial,
928
+ reconnect: state.reconnect.status === "reconnecting" ? {
929
+ ...state.reconnect,
930
+ lastResumedAt: Date.now(),
931
+ nextAttemptAt: undefined,
932
+ status: "resumed"
933
+ } : state.reconnect,
934
+ scenarioId: action.scenarioId ?? state.scenarioId,
935
+ sessionId: action.sessionId,
936
+ sessionMetadata: action.sessionMetadata ?? state.sessionMetadata,
937
+ status: action.status,
938
+ turns: [...action.turns]
939
+ };
940
+ break;
858
941
  case "session":
859
942
  state = {
860
943
  ...state,
@@ -862,6 +945,7 @@ var createVoiceStreamStore = () => {
862
945
  scenarioId: action.scenarioId ?? state.scenarioId,
863
946
  isConnected: action.status === "active",
864
947
  sessionId: action.sessionId,
948
+ sessionMetadata: action.sessionMetadata ?? state.sessionMetadata,
865
949
  status: action.status
866
950
  };
867
951
  break;
@@ -892,20 +976,50 @@ var createVoiceStreamStore = () => {
892
976
  var createVoiceStream = (path, options = {}) => {
893
977
  const connection = createVoiceConnection(path, options);
894
978
  const store = createVoiceStreamStore();
979
+ const browserMediaReporter = options.browserMedia && typeof window !== "undefined" ? createVoiceBrowserMediaReporter({
980
+ ...options.browserMedia,
981
+ getScenarioId: () => options.browserMedia ? options.browserMedia.getScenarioId?.() ?? connection.getScenarioId() : connection.getScenarioId(),
982
+ getSessionId: () => options.browserMedia ? options.browserMedia.getSessionId?.() ?? connection.getSessionId() : connection.getSessionId()
983
+ }) : null;
895
984
  const subscribers = new Set;
896
985
  const start = (input) => Promise.resolve().then(() => {
897
986
  if (!input?.sessionId && !input?.scenarioId) {
898
987
  return;
899
988
  }
900
989
  connection.start(input);
990
+ browserMediaReporter?.start();
901
991
  });
902
992
  const notify = () => {
903
993
  subscribers.forEach((subscriber) => subscriber());
904
994
  };
995
+ const reportReconnect = () => {
996
+ if (!options.reconnectReportPath || typeof fetch === "undefined") {
997
+ return;
998
+ }
999
+ const snapshot = store.getSnapshot();
1000
+ const body = JSON.stringify({
1001
+ at: Date.now(),
1002
+ reconnect: snapshot.reconnect,
1003
+ scenarioId: snapshot.scenarioId,
1004
+ sessionId: connection.getSessionId(),
1005
+ turnIds: snapshot.turns.map((turn) => turn.id)
1006
+ });
1007
+ fetch(options.reconnectReportPath, {
1008
+ body,
1009
+ headers: {
1010
+ "Content-Type": "application/json"
1011
+ },
1012
+ keepalive: true,
1013
+ method: "POST"
1014
+ }).catch(() => {});
1015
+ };
905
1016
  const unsubscribeConnection = connection.subscribe((message) => {
906
1017
  const action = serverMessageToAction(message);
907
1018
  if (action) {
908
1019
  store.dispatch(action);
1020
+ if (message.type === "connection") {
1021
+ reportReconnect();
1022
+ }
909
1023
  notify();
910
1024
  }
911
1025
  });
@@ -915,6 +1029,7 @@ var createVoiceStream = (path, options = {}) => {
915
1029
  },
916
1030
  close() {
917
1031
  unsubscribeConnection();
1032
+ browserMediaReporter?.close();
918
1033
  connection.close();
919
1034
  store.dispatch({ type: "disconnected" });
920
1035
  notify();
@@ -937,10 +1052,16 @@ var createVoiceStream = (path, options = {}) => {
937
1052
  get scenarioId() {
938
1053
  return store.getSnapshot().scenarioId;
939
1054
  },
1055
+ get sessionMetadata() {
1056
+ return store.getSnapshot().sessionMetadata;
1057
+ },
940
1058
  start,
941
1059
  get partial() {
942
1060
  return store.getSnapshot().partial;
943
1061
  },
1062
+ get reconnect() {
1063
+ return store.getSnapshot().reconnect;
1064
+ },
944
1065
  get sessionId() {
945
1066
  return connection.getSessionId();
946
1067
  },
@@ -962,6 +1083,9 @@ var createVoiceStream = (path, options = {}) => {
962
1083
  sendAudio(audio) {
963
1084
  connection.sendAudio(audio);
964
1085
  },
1086
+ simulateDisconnect() {
1087
+ connection.simulateDisconnect();
1088
+ },
965
1089
  subscribe(subscriber) {
966
1090
  subscribers.add(subscriber);
967
1091
  return () => {
@@ -971,206 +1095,6 @@ var createVoiceStream = (path, options = {}) => {
971
1095
  };
972
1096
  };
973
1097
 
974
- // src/angular/voice-stream.service.ts
975
- var _dec = [
976
- Injectable2({ providedIn: "root" })
977
- ];
978
- var _init = __decoratorStart(undefined);
979
-
980
- class VoiceStreamService {
981
- connect(path, options = {}) {
982
- const stream = createVoiceStream(path, options);
983
- const assistantAudioSignal = signal3([]);
984
- const assistantTextsSignal = signal3([]);
985
- const callSignal = signal3(null);
986
- const errorSignal = signal3(null);
987
- const isConnectedSignal = signal3(false);
988
- const partialSignal = signal3("");
989
- const sessionIdSignal = signal3(stream.sessionId);
990
- const statusSignal = signal3(stream.status);
991
- const turnsSignal = signal3([]);
992
- const sync = () => {
993
- assistantAudioSignal.set([...stream.assistantAudio]);
994
- assistantTextsSignal.set([...stream.assistantTexts]);
995
- callSignal.set(stream.call);
996
- errorSignal.set(stream.error);
997
- isConnectedSignal.set(stream.isConnected);
998
- partialSignal.set(stream.partial);
999
- sessionIdSignal.set(stream.sessionId);
1000
- statusSignal.set(stream.status);
1001
- turnsSignal.set([...stream.turns]);
1002
- };
1003
- const unsubscribe = stream.subscribe(sync);
1004
- sync();
1005
- return {
1006
- assistantAudio: computed2(() => assistantAudioSignal()),
1007
- assistantTexts: computed2(() => assistantTextsSignal()),
1008
- call: computed2(() => callSignal()),
1009
- callControl: (message) => stream.callControl(message),
1010
- close: () => {
1011
- unsubscribe();
1012
- stream.close();
1013
- },
1014
- endTurn: () => stream.endTurn(),
1015
- error: computed2(() => errorSignal()),
1016
- isConnected: computed2(() => isConnectedSignal()),
1017
- partial: computed2(() => partialSignal()),
1018
- sendAudio: (audio) => stream.sendAudio(audio),
1019
- sessionId: computed2(() => sessionIdSignal()),
1020
- status: computed2(() => statusSignal()),
1021
- turns: computed2(() => turnsSignal())
1022
- };
1023
- }
1024
- }
1025
- VoiceStreamService = __decorateElement(_init, 0, "VoiceStreamService", _dec, VoiceStreamService);
1026
- __runInitializers(_init, 1, VoiceStreamService);
1027
- __decoratorMetadata(_init, VoiceStreamService);
1028
- let _VoiceStreamService = VoiceStreamService;
1029
- // src/angular/voice-controller.service.ts
1030
- import { computed as computed3, Injectable as Injectable3, signal as signal4 } from "@angular/core";
1031
-
1032
- // src/client/htmx.ts
1033
- var DEFAULT_EVENT_NAME = "voice-refresh";
1034
- var DEFAULT_QUERY_PARAM = "sessionId";
1035
- var resolveElement = (input) => {
1036
- if (typeof input !== "string") {
1037
- return input;
1038
- }
1039
- return document.querySelector(input);
1040
- };
1041
- var buildRoute = (element, route, queryParam, sessionId) => {
1042
- const baseRoute = route ?? element.getAttribute("hx-get") ?? "";
1043
- if (!baseRoute) {
1044
- return "";
1045
- }
1046
- const url = new URL(baseRoute, window.location.origin);
1047
- if (sessionId) {
1048
- url.searchParams.set(queryParam, sessionId);
1049
- } else {
1050
- url.searchParams.delete(queryParam);
1051
- }
1052
- return `${url.pathname}${url.search}${url.hash}`;
1053
- };
1054
- var bindVoiceHTMX = (stream, options) => {
1055
- if (typeof window === "undefined" || typeof document === "undefined") {
1056
- return () => {};
1057
- }
1058
- const element = resolveElement(options.element);
1059
- if (!element) {
1060
- return () => {};
1061
- }
1062
- const eventName = options.eventName ?? DEFAULT_EVENT_NAME;
1063
- const queryParam = options.sessionQueryParam ?? DEFAULT_QUERY_PARAM;
1064
- const sync = () => {
1065
- const htmxWindow = window;
1066
- const nextRoute = buildRoute(element, options.route, queryParam, stream.sessionId);
1067
- if (nextRoute) {
1068
- element.setAttribute("hx-get", nextRoute);
1069
- }
1070
- htmxWindow.htmx?.process?.(element);
1071
- htmxWindow.htmx?.trigger?.(element, eventName);
1072
- };
1073
- const unsubscribe = stream.subscribe(sync);
1074
- sync();
1075
- return () => {
1076
- unsubscribe();
1077
- };
1078
- };
1079
-
1080
- // src/client/microphone.ts
1081
- var clampSample = (value) => Math.max(-1, Math.min(1, value));
1082
- var floatTo16BitPCM = (input) => {
1083
- const output = new Int16Array(input.length);
1084
- for (let index = 0;index < input.length; index += 1) {
1085
- const sample = clampSample(input[index] ?? 0);
1086
- output[index] = sample < 0 ? sample * 32768 : sample * 32767;
1087
- }
1088
- return new Uint8Array(output.buffer);
1089
- };
1090
- var getPcmLevel = (audio) => {
1091
- const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
1092
- if (bytes.byteLength < 2) {
1093
- return 0;
1094
- }
1095
- const samples = new Int16Array(bytes.buffer, bytes.byteOffset, Math.floor(bytes.byteLength / 2));
1096
- if (samples.length === 0) {
1097
- return 0;
1098
- }
1099
- let sumSquares = 0;
1100
- for (const sample of samples) {
1101
- const normalized = sample / 32768;
1102
- sumSquares += normalized * normalized;
1103
- }
1104
- return Math.min(1, Math.max(0, Math.sqrt(sumSquares / samples.length) * 5.5));
1105
- };
1106
- var downsampleBuffer = (input, sourceRate, targetRate) => {
1107
- if (sourceRate === targetRate) {
1108
- return input;
1109
- }
1110
- const ratio = sourceRate / targetRate;
1111
- const length = Math.round(input.length / ratio);
1112
- const output = new Float32Array(length);
1113
- let offsetResult = 0;
1114
- let offsetBuffer = 0;
1115
- while (offsetResult < output.length) {
1116
- const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
1117
- let accum = 0;
1118
- let count = 0;
1119
- for (let index = offsetBuffer;index < nextOffsetBuffer && index < input.length; index += 1) {
1120
- accum += input[index] ?? 0;
1121
- count += 1;
1122
- }
1123
- output[offsetResult] = count > 0 ? accum / count : 0;
1124
- offsetResult += 1;
1125
- offsetBuffer = nextOffsetBuffer;
1126
- }
1127
- return output;
1128
- };
1129
- var createMicrophoneCapture = (options) => {
1130
- let audioContext = null;
1131
- let sourceNode = null;
1132
- let processorNode = null;
1133
- let mediaStream = null;
1134
- const start = async () => {
1135
- if (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia) {
1136
- throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
1137
- }
1138
- const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
1139
- if (!AudioContextCtor) {
1140
- throw new Error("Browser microphone capture requires AudioContext support.");
1141
- }
1142
- mediaStream = await navigator.mediaDevices.getUserMedia({
1143
- audio: {
1144
- channelCount: options.channelCount ?? 1
1145
- }
1146
- });
1147
- audioContext = new AudioContextCtor;
1148
- sourceNode = audioContext.createMediaStreamSource(mediaStream);
1149
- processorNode = audioContext.createScriptProcessor(4096, 1, 1);
1150
- processorNode.onaudioprocess = (event) => {
1151
- const channel = event.inputBuffer.getChannelData(0);
1152
- const downsampled = downsampleBuffer(channel, audioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
1153
- const pcm = floatTo16BitPCM(downsampled);
1154
- options.onLevel?.(getPcmLevel(pcm));
1155
- options.onAudio(pcm);
1156
- };
1157
- sourceNode.connect(processorNode);
1158
- processorNode.connect(audioContext.destination);
1159
- };
1160
- const stop = () => {
1161
- processorNode?.disconnect();
1162
- sourceNode?.disconnect();
1163
- mediaStream?.getTracks().forEach((track) => track.stop());
1164
- audioContext?.close();
1165
- options.onLevel?.(0);
1166
- audioContext = null;
1167
- mediaStream = null;
1168
- processorNode = null;
1169
- sourceNode = null;
1170
- };
1171
- return { start, stop };
1172
- };
1173
-
1174
1098
  // src/audioConditioning.ts
1175
1099
  var DEFAULT_TARGET_LEVEL = 0.08;
1176
1100
  var DEFAULT_MAX_GAIN = 3;
@@ -1496,8 +1420,10 @@ var createInitialState2 = (stream) => ({
1496
1420
  isConnected: stream.isConnected,
1497
1421
  isRecording: false,
1498
1422
  partial: stream.partial,
1423
+ reconnect: stream.reconnect,
1499
1424
  recordingError: null,
1500
1425
  sessionId: stream.sessionId,
1426
+ sessionMetadata: stream.sessionMetadata,
1501
1427
  scenarioId: stream.scenarioId,
1502
1428
  status: stream.status,
1503
1429
  turns: [...stream.turns]
@@ -1525,7 +1451,9 @@ var createVoiceController = (path, options = {}) => {
1525
1451
  error: stream.error,
1526
1452
  isConnected: stream.isConnected,
1527
1453
  partial: stream.partial,
1454
+ reconnect: stream.reconnect,
1528
1455
  sessionId: stream.sessionId,
1456
+ sessionMetadata: stream.sessionMetadata,
1529
1457
  scenarioId: stream.scenarioId,
1530
1458
  status: stream.status,
1531
1459
  turns: [...stream.turns]
@@ -1549,7 +1477,13 @@ var createVoiceController = (path, options = {}) => {
1549
1477
  capture = createMicrophoneCapture({
1550
1478
  channelCount: options.capture?.channelCount ?? preset.capture.channelCount,
1551
1479
  onLevel: options.capture?.onLevel,
1552
- onAudio: (audio) => stream.sendAudio(audio),
1480
+ onAudio: (audio) => {
1481
+ if (options.capture?.onAudio) {
1482
+ options.capture.onAudio(audio, stream.sendAudio);
1483
+ return;
1484
+ }
1485
+ stream.sendAudio(audio);
1486
+ },
1553
1487
  sampleRateHz: options.capture?.sampleRateHz ?? preset.capture.sampleRateHz
1554
1488
  });
1555
1489
  return capture;
@@ -1619,10 +1553,17 @@ var createVoiceController = (path, options = {}) => {
1619
1553
  get recordingError() {
1620
1554
  return state.recordingError;
1621
1555
  },
1556
+ get reconnect() {
1557
+ return state.reconnect;
1558
+ },
1622
1559
  sendAudio: (audio) => stream.sendAudio(audio),
1560
+ simulateDisconnect: () => stream.simulateDisconnect(),
1623
1561
  get sessionId() {
1624
1562
  return state.sessionId;
1625
1563
  },
1564
+ get sessionMetadata() {
1565
+ return state.sessionMetadata;
1566
+ },
1626
1567
  get scenarioId() {
1627
1568
  return state.scenarioId;
1628
1569
  },
@@ -1659,85 +1600,2905 @@ var createVoiceController = (path, options = {}) => {
1659
1600
  };
1660
1601
  };
1661
1602
 
1662
- // src/angular/voice-controller.service.ts
1603
+ // src/internal/html.ts
1604
+ var escapeHtml = (value) => String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1605
+
1606
+ // src/agentState.ts
1607
+ var deriveVoiceAgentUIState = (input) => {
1608
+ if (!input.isConnected) {
1609
+ return "idle";
1610
+ }
1611
+ if (input.isPlaying) {
1612
+ return "speaking";
1613
+ }
1614
+ if (input.isRecording && input.hasActivePartial) {
1615
+ return "listening";
1616
+ }
1617
+ if (input.isRecording) {
1618
+ return "listening";
1619
+ }
1620
+ if (input.lastTranscriptAt && !input.lastAssistantAt) {
1621
+ return "thinking";
1622
+ }
1623
+ if (input.lastTranscriptAt && input.lastAssistantAt && input.lastTranscriptAt > input.lastAssistantAt) {
1624
+ return "thinking";
1625
+ }
1626
+ return "idle";
1627
+ };
1628
+ var describeVoiceAgentUIState = (state) => {
1629
+ switch (state) {
1630
+ case "idle":
1631
+ return "Idle";
1632
+ case "listening":
1633
+ return "Listening";
1634
+ case "speaking":
1635
+ return "Speaking";
1636
+ case "thinking":
1637
+ return "Thinking";
1638
+ }
1639
+ };
1640
+ var voiceAgentUIStateOrder = [
1641
+ "idle",
1642
+ "listening",
1643
+ "thinking",
1644
+ "speaking"
1645
+ ];
1646
+
1647
+ // src/client/voiceWidgetView.ts
1648
+ var DEFAULT_VOICE_WIDGET_THEME = {
1649
+ accent: "#3b82f6",
1650
+ background: "#0f172a",
1651
+ errorAccent: "#ef4444",
1652
+ fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
1653
+ foreground: "#f8fafc",
1654
+ radius: 16
1655
+ };
1656
+ var DEFAULT_VOICE_WIDGET_LABELS = {
1657
+ callEnded: "Call ended",
1658
+ connecting: "Connecting\u2026",
1659
+ endCall: "End call",
1660
+ idle: "Idle",
1661
+ listening: "Listening",
1662
+ mute: "Mute",
1663
+ speaking: "Speaking",
1664
+ startCall: "Start call",
1665
+ thinking: "Thinking",
1666
+ unmute: "Unmute"
1667
+ };
1668
+ var stateLabel = (state, labels) => {
1669
+ switch (state) {
1670
+ case "listening":
1671
+ return labels.listening;
1672
+ case "speaking":
1673
+ return labels.speaking;
1674
+ case "thinking":
1675
+ return labels.thinking;
1676
+ case "idle":
1677
+ return labels.idle;
1678
+ }
1679
+ };
1680
+ var createVoiceWidgetViewModel = (input) => {
1681
+ const theme = { ...DEFAULT_VOICE_WIDGET_THEME, ...input.theme };
1682
+ const labels = { ...DEFAULT_VOICE_WIDGET_LABELS, ...input.labels };
1683
+ const lastAssistantAt = input.state.assistantAudio.at(-1)?.receivedAt;
1684
+ const lastTranscriptAt = input.state.turns.at(-1)?.committedAt;
1685
+ const agentState = deriveVoiceAgentUIState({
1686
+ hasActivePartial: input.state.partial.length > 0,
1687
+ isConnected: input.state.isConnected,
1688
+ isPlaying: false,
1689
+ isRecording: input.state.isRecording,
1690
+ lastAssistantAt,
1691
+ lastTranscriptAt
1692
+ });
1693
+ const connecting = !input.state.isConnected && input.state.status !== "idle" && !input.state.error;
1694
+ const statusLabel = input.state.error ? "Error" : connecting ? labels.connecting : input.state.status === "completed" ? labels.callEnded : stateLabel(agentState, labels);
1695
+ return {
1696
+ agentState,
1697
+ classes: {
1698
+ container: `absolute-voice-widget absolute-voice-widget--${agentState}`,
1699
+ dot: `absolute-voice-widget__dot${input.state.error ? " absolute-voice-widget__dot--error" : ""}`
1700
+ },
1701
+ controls: {
1702
+ canEnd: input.state.isConnected,
1703
+ canMute: input.state.isRecording,
1704
+ canStart: !input.state.isRecording && input.state.status !== "completed"
1705
+ },
1706
+ errorMessage: input.state.error ?? undefined,
1707
+ labels,
1708
+ partial: input.state.partial || undefined,
1709
+ statusLabel,
1710
+ theme,
1711
+ title: input.title ?? "Voice"
1712
+ };
1713
+ };
1714
+ var resolveRadius = (radius) => typeof radius === "number" ? `${radius}px` : radius;
1715
+ var renderVoiceWidgetHTML = (model) => {
1716
+ const t = model.theme;
1717
+ const containerStyle = `background:${t.background};border-radius:${resolveRadius(t.radius)};color:${t.foreground};font-family:${t.fontFamily};min-width:240px;padding:20px 22px;`;
1718
+ const dotStyle = `background:${model.errorMessage ? t.errorAccent : model.agentState === "idle" ? "rgba(148,163,184,0.6)" : t.accent};border-radius:50%;height:10px;width:10px;`;
1719
+ const buttons = [];
1720
+ if (model.controls.canStart) {
1721
+ buttons.push(`<button type="button" data-action="start" style="background:${t.accent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.startCall)}</button>`);
1722
+ }
1723
+ if (model.controls.canMute) {
1724
+ buttons.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.mute)}</button>`);
1725
+ }
1726
+ if (model.controls.canEnd) {
1727
+ buttons.push(`<button type="button" data-action="end" style="background:${t.errorAccent};border:none;border-radius:12px;color:${t.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${escapeHtml(model.labels.endCall)}</button>`);
1728
+ }
1729
+ return `<div role="region" aria-live="polite" data-agent-state="${model.agentState}" class="${escapeHtml(model.classes.container)}" style="${containerStyle}">
1730
+ <div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
1731
+ <span aria-hidden="true" class="${escapeHtml(model.classes.dot)}" style="${dotStyle}"></span>
1732
+ <strong style="font-size:15px;">${escapeHtml(model.title)}</strong>
1733
+ <span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml(model.statusLabel)}</span>
1734
+ </div>
1735
+ ${model.partial ? `<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">\u201C${escapeHtml(model.partial)}\u201D</p>` : ""}
1736
+ <div style="display:flex;gap:10px;">${buttons.join("")}</div>
1737
+ ${model.errorMessage ? `<p style="color:${t.errorAccent};font-size:12px;margin-top:12px;">${escapeHtml(model.errorMessage)}</p>` : ""}
1738
+ </div>`;
1739
+ };
1740
+
1741
+ // src/angular/voice-widget.service.ts
1663
1742
  var _dec = [
1664
- Injectable3({ providedIn: "root" })
1743
+ Injectable2({ providedIn: "root" })
1665
1744
  ];
1666
1745
  var _init = __decoratorStart(undefined);
1667
1746
 
1668
- class VoiceControllerService {
1747
+ class VoiceWidgetService {
1669
1748
  connect(path, options = {}) {
1670
1749
  const controller = createVoiceController(path, options);
1671
- const assistantAudioSignal = signal4([]);
1672
- const assistantTextsSignal = signal4([]);
1673
- const errorSignal = signal4(null);
1674
- const isConnectedSignal = signal4(false);
1675
- const isRecordingSignal = signal4(false);
1676
- const partialSignal = signal4("");
1677
- const recordingErrorSignal = signal4(null);
1678
- const sessionIdSignal = signal4(controller.sessionId);
1679
- const statusSignal = signal4(controller.status);
1680
- const turnsSignal = signal4([]);
1750
+ const viewModelSignal = signal2(createVoiceWidgetViewModel({
1751
+ labels: options.labels,
1752
+ state: controller.getSnapshot(),
1753
+ theme: options.theme,
1754
+ title: options.title
1755
+ }));
1681
1756
  const sync = () => {
1682
- assistantAudioSignal.set([...controller.assistantAudio]);
1683
- assistantTextsSignal.set([...controller.assistantTexts]);
1684
- errorSignal.set(controller.error);
1685
- isConnectedSignal.set(controller.isConnected);
1686
- isRecordingSignal.set(controller.isRecording);
1687
- partialSignal.set(controller.partial);
1688
- recordingErrorSignal.set(controller.recordingError);
1689
- sessionIdSignal.set(controller.sessionId);
1690
- statusSignal.set(controller.status);
1691
- turnsSignal.set([...controller.turns]);
1757
+ viewModelSignal.set(createVoiceWidgetViewModel({
1758
+ labels: options.labels,
1759
+ state: controller.getSnapshot(),
1760
+ theme: options.theme,
1761
+ title: options.title
1762
+ }));
1692
1763
  };
1693
1764
  const unsubscribe = controller.subscribe(sync);
1694
1765
  sync();
1695
1766
  return {
1696
- assistantAudio: computed3(() => assistantAudioSignal()),
1697
- assistantTexts: computed3(() => assistantTextsSignal()),
1698
- bindHTMX: controller.bindHTMX,
1699
1767
  close: () => {
1700
1768
  unsubscribe();
1701
1769
  controller.close();
1702
1770
  },
1703
- endTurn: () => controller.endTurn(),
1704
- error: computed3(() => errorSignal()),
1705
- isConnected: computed3(() => isConnectedSignal()),
1706
- isRecording: computed3(() => isRecordingSignal()),
1707
- partial: computed3(() => partialSignal()),
1708
- recordingError: computed3(() => recordingErrorSignal()),
1709
- sendAudio: (audio) => controller.sendAudio(audio),
1710
- sessionId: computed3(() => sessionIdSignal()),
1711
- startRecording: () => controller.startRecording(),
1712
- status: computed3(() => statusSignal()),
1713
- stopRecording: () => controller.stopRecording(),
1714
- toggleRecording: () => controller.toggleRecording(),
1715
- turns: computed3(() => turnsSignal())
1771
+ endCall: () => controller.close(),
1772
+ getHTML: () => renderVoiceWidgetHTML(viewModelSignal()),
1773
+ mute: () => controller.stopRecording(),
1774
+ startCall: () => controller.startRecording(),
1775
+ unmute: () => controller.startRecording(),
1776
+ viewModel: computed2(() => viewModelSignal())
1716
1777
  };
1717
1778
  }
1718
1779
  }
1719
- VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _dec, VoiceControllerService);
1720
- __runInitializers(_init, 1, VoiceControllerService);
1721
- __decoratorMetadata(_init, VoiceControllerService);
1722
- let _VoiceControllerService = VoiceControllerService;
1723
- // src/angular/voice-provider-status.service.ts
1724
- import { computed as computed4, Injectable as Injectable4, signal as signal5 } from "@angular/core";
1780
+ VoiceWidgetService = __decorateElement(_init, 0, "VoiceWidgetService", _dec, VoiceWidgetService);
1781
+ __runInitializers(_init, 1, VoiceWidgetService);
1782
+ __decoratorMetadata(_init, VoiceWidgetService);
1783
+ let _VoiceWidgetService = VoiceWidgetService;
1784
+ // src/angular/voice-call-player.service.ts
1785
+ import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
1725
1786
 
1726
- // src/client/providerStatus.ts
1727
- var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
1728
- const fetchImpl = options.fetch ?? globalThis.fetch;
1729
- const response = await fetchImpl(path);
1730
- if (!response.ok) {
1731
- throw new Error(`Voice provider status failed: HTTP ${response.status}`);
1787
+ // src/client/callPlayer.ts
1788
+ var cloneState = (state) => ({
1789
+ ...state
1790
+ });
1791
+ var normalizeTranscriptTimes = (transcripts, baseEpoch) => {
1792
+ if (typeof baseEpoch !== "number") {
1793
+ return transcripts;
1732
1794
  }
1733
- return await response.json();
1795
+ return transcripts.map((transcript) => {
1796
+ const adjusted = { ...transcript };
1797
+ if (typeof adjusted.startedAtMs === "number" && adjusted.startedAtMs >= baseEpoch) {
1798
+ adjusted.startedAtMs = adjusted.startedAtMs - baseEpoch;
1799
+ }
1800
+ if (typeof adjusted.endedAtMs === "number" && adjusted.endedAtMs >= baseEpoch) {
1801
+ adjusted.endedAtMs = adjusted.endedAtMs - baseEpoch;
1802
+ }
1803
+ return adjusted;
1804
+ });
1734
1805
  };
1735
- var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
1806
+ var findActiveTranscript = (transcripts, positionMs) => {
1807
+ let candidate;
1808
+ for (let index = 0;index < transcripts.length; index += 1) {
1809
+ const transcript = transcripts[index];
1810
+ if (typeof transcript.startedAtMs !== "number")
1811
+ continue;
1812
+ if (transcript.startedAtMs > positionMs)
1813
+ break;
1814
+ if (typeof transcript.endedAtMs === "number" && transcript.endedAtMs < positionMs) {
1815
+ continue;
1816
+ }
1817
+ candidate = { id: transcript.id, index };
1818
+ }
1819
+ return candidate ?? {};
1820
+ };
1821
+ var createVoiceCallPlayer = (options = {}) => {
1822
+ let transcripts = normalizeTranscriptTimes(options.transcripts ?? [], options.recordingStartedAtEpochMs);
1823
+ let state = {
1824
+ audioUrl: options.audioUrl,
1825
+ buffered: 0,
1826
+ currentTimeMs: 0,
1827
+ durationMs: 0,
1828
+ isPlaying: false,
1829
+ isReady: false,
1830
+ playbackRate: options.initialPlaybackRate ?? 1
1831
+ };
1736
1832
  const listeners = new Set;
1737
- let closed = false;
1738
- let timer;
1739
- let snapshot = {
1740
- error: null,
1833
+ const notify = () => {
1834
+ for (const listener of listeners)
1835
+ listener();
1836
+ };
1837
+ const update = (next) => {
1838
+ state = { ...state, ...next };
1839
+ notify();
1840
+ };
1841
+ const refreshActive = () => {
1842
+ const { id, index } = findActiveTranscript(transcripts, state.currentTimeMs);
1843
+ if (id !== state.activeTranscriptId || index !== state.activeTranscriptIndex) {
1844
+ state = {
1845
+ ...state,
1846
+ activeTranscriptId: id,
1847
+ activeTranscriptIndex: index
1848
+ };
1849
+ notify();
1850
+ }
1851
+ };
1852
+ return {
1853
+ getState: () => cloneState(state),
1854
+ pause: () => {
1855
+ if (!state.isPlaying)
1856
+ return;
1857
+ update({ isPlaying: false });
1858
+ },
1859
+ play: async () => {
1860
+ update({ isPlaying: true });
1861
+ },
1862
+ reset: () => {
1863
+ state = {
1864
+ audioUrl: state.audioUrl,
1865
+ buffered: 0,
1866
+ currentTimeMs: 0,
1867
+ durationMs: 0,
1868
+ isPlaying: false,
1869
+ isReady: false,
1870
+ playbackRate: 1
1871
+ };
1872
+ notify();
1873
+ },
1874
+ seekMs: (positionMs) => {
1875
+ const clamped = Math.max(0, Math.min(state.durationMs || Number.POSITIVE_INFINITY, positionMs));
1876
+ update({ currentTimeMs: clamped });
1877
+ refreshActive();
1878
+ },
1879
+ seekToTranscript: (transcriptId) => {
1880
+ const found = transcripts.find((t) => t.id === transcriptId);
1881
+ if (!found || typeof found.startedAtMs !== "number") {
1882
+ return;
1883
+ }
1884
+ update({ currentTimeMs: Math.max(0, found.startedAtMs) });
1885
+ refreshActive();
1886
+ },
1887
+ setAudioUrl: (url) => {
1888
+ update({ audioUrl: url, isReady: false });
1889
+ },
1890
+ setBuffered: (seconds) => {
1891
+ update({ buffered: Math.max(0, seconds) });
1892
+ },
1893
+ setDuration: (durationMs) => {
1894
+ update({ durationMs: Math.max(0, durationMs) });
1895
+ },
1896
+ setError: (error) => {
1897
+ update({ error });
1898
+ },
1899
+ setPlaybackRate: (rate) => {
1900
+ update({ playbackRate: Math.max(0.25, Math.min(4, rate)) });
1901
+ },
1902
+ setPlaying: (playing) => {
1903
+ if (playing === state.isPlaying)
1904
+ return;
1905
+ update({ isPlaying: playing });
1906
+ },
1907
+ setReady: (ready) => {
1908
+ update({ isReady: ready });
1909
+ },
1910
+ setTime: (positionMs) => {
1911
+ const next = Math.max(0, positionMs);
1912
+ if (next === state.currentTimeMs)
1913
+ return;
1914
+ update({ currentTimeMs: next });
1915
+ refreshActive();
1916
+ },
1917
+ setTranscripts: (next) => {
1918
+ transcripts = normalizeTranscriptTimes(next, options.recordingStartedAtEpochMs);
1919
+ refreshActive();
1920
+ },
1921
+ subscribe: (listener) => {
1922
+ listeners.add(listener);
1923
+ return () => {
1924
+ listeners.delete(listener);
1925
+ };
1926
+ },
1927
+ transcripts: () => transcripts
1928
+ };
1929
+ };
1930
+ var formatVoiceCallPlayerTimestamp = (ms) => {
1931
+ const seconds = Math.max(0, Math.floor(ms / 1000));
1932
+ const minutes = Math.floor(seconds / 60);
1933
+ const remaining = seconds % 60;
1934
+ return `${String(minutes).padStart(2, "0")}:${String(remaining).padStart(2, "0")}`;
1935
+ };
1936
+
1937
+ // src/angular/voice-call-player.service.ts
1938
+ var _dec = [
1939
+ Injectable3({ providedIn: "root" })
1940
+ ];
1941
+ var _init = __decoratorStart(undefined);
1942
+
1943
+ class VoiceCallPlayerService {
1944
+ build(options = {}) {
1945
+ const player = createVoiceCallPlayer(options);
1946
+ const stateSignal = signal3(player.getState());
1947
+ const unsubscribe = player.subscribe(() => {
1948
+ stateSignal.set(player.getState());
1949
+ });
1950
+ return {
1951
+ formatTimestamp: formatVoiceCallPlayerTimestamp,
1952
+ pause: () => player.pause(),
1953
+ play: () => player.play(),
1954
+ seekMs: (ms) => player.seekMs(ms),
1955
+ seekToTranscript: (id) => player.seekToTranscript(id),
1956
+ setPlaybackRate: (rate) => player.setPlaybackRate(rate),
1957
+ setTime: (ms) => player.setTime(ms),
1958
+ state: computed3(() => stateSignal()),
1959
+ stop: () => unsubscribe(),
1960
+ title: options.title ?? "Call replay",
1961
+ transcripts: () => player.transcripts()
1962
+ };
1963
+ }
1964
+ }
1965
+ VoiceCallPlayerService = __decorateElement(_init, 0, "VoiceCallPlayerService", _dec, VoiceCallPlayerService);
1966
+ __runInitializers(_init, 1, VoiceCallPlayerService);
1967
+ __decoratorMetadata(_init, VoiceCallPlayerService);
1968
+ let _VoiceCallPlayerService = VoiceCallPlayerService;
1969
+ // src/angular/voice-cost-dashboard.service.ts
1970
+ import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
1971
+
1972
+ // src/client/costDashboard.ts
1973
+ var padTwo = (value) => String(value).padStart(2, "0");
1974
+ var formatBucketKey = (epochMs, bucketBy) => {
1975
+ const date = new Date(epochMs);
1976
+ const y = date.getUTCFullYear();
1977
+ const m = padTwo(date.getUTCMonth() + 1);
1978
+ const d = padTwo(date.getUTCDate());
1979
+ const h = padTwo(date.getUTCHours());
1980
+ if (bucketBy === "month")
1981
+ return `${y}-${m}`;
1982
+ if (bucketBy === "day")
1983
+ return `${y}-${m}-${d}`;
1984
+ return `${y}-${m}-${d}T${h}`;
1985
+ };
1986
+ var isCostBreakdown = (value) => Boolean(value) && typeof value === "object" && typeof value.totalUsd === "number";
1987
+ var emptyBucket = (bucketKey) => ({
1988
+ bucketKey,
1989
+ callCount: 0,
1990
+ llmUsd: 0,
1991
+ sttUsd: 0,
1992
+ telephonyMinutes: 0,
1993
+ telephonyUsd: 0,
1994
+ totalUsd: 0,
1995
+ ttsUsd: 0
1996
+ });
1997
+ var accumulate = (bucket, payload) => {
1998
+ bucket.callCount += 1;
1999
+ bucket.llmUsd += payload.llm.usd;
2000
+ bucket.sttUsd += payload.stt.usd;
2001
+ bucket.ttsUsd += payload.tts.usd;
2002
+ bucket.telephonyUsd += payload.telephony.usd;
2003
+ bucket.telephonyMinutes += payload.telephony.minutes;
2004
+ bucket.totalUsd += payload.totalUsd;
2005
+ };
2006
+ var roundCurrency = (bucket) => {
2007
+ bucket.llmUsd = Math.round(bucket.llmUsd * 1e6) / 1e6;
2008
+ bucket.sttUsd = Math.round(bucket.sttUsd * 1e6) / 1e6;
2009
+ bucket.ttsUsd = Math.round(bucket.ttsUsd * 1e6) / 1e6;
2010
+ bucket.telephonyUsd = Math.round(bucket.telephonyUsd * 1e6) / 1e6;
2011
+ bucket.totalUsd = Math.round(bucket.totalUsd * 1e6) / 1e6;
2012
+ };
2013
+ var buildVoiceCostDashboardReport = (options) => {
2014
+ const bucketBy = options.bucketBy ?? "day";
2015
+ const fromMs = options.fromMs ?? Number.NEGATIVE_INFINITY;
2016
+ const toMs = options.toMs ?? Number.POSITIVE_INFINITY;
2017
+ const buckets = new Map;
2018
+ const grandTotal = emptyBucket("total");
2019
+ let minMs = Number.POSITIVE_INFINITY;
2020
+ let maxMs = Number.NEGATIVE_INFINITY;
2021
+ for (const event of options.events) {
2022
+ if (event.type !== "cost.ready")
2023
+ continue;
2024
+ if (event.at < fromMs || event.at > toMs)
2025
+ continue;
2026
+ if (!isCostBreakdown(event.payload))
2027
+ continue;
2028
+ minMs = Math.min(minMs, event.at);
2029
+ maxMs = Math.max(maxMs, event.at);
2030
+ const bucketKey = formatBucketKey(event.at, bucketBy);
2031
+ let bucket = buckets.get(bucketKey);
2032
+ if (!bucket) {
2033
+ bucket = emptyBucket(bucketKey);
2034
+ buckets.set(bucketKey, bucket);
2035
+ }
2036
+ accumulate(bucket, event.payload);
2037
+ accumulate(grandTotal, event.payload);
2038
+ }
2039
+ for (const bucket of buckets.values()) {
2040
+ roundCurrency(bucket);
2041
+ }
2042
+ roundCurrency(grandTotal);
2043
+ return {
2044
+ buckets: Array.from(buckets.values()).sort((a, b) => a.bucketKey.localeCompare(b.bucketKey)),
2045
+ generatedAt: Date.now(),
2046
+ grandTotal,
2047
+ windowEndMs: Number.isFinite(maxMs) ? maxMs : 0,
2048
+ windowStartMs: Number.isFinite(minMs) ? minMs : 0
2049
+ };
2050
+ };
2051
+
2052
+ // src/angular/voice-cost-dashboard.service.ts
2053
+ var _dec = [
2054
+ Injectable4({ providedIn: "root" })
2055
+ ];
2056
+ var _init = __decoratorStart(undefined);
2057
+
2058
+ class VoiceCostDashboardService {
2059
+ build(options) {
2060
+ const events = signal4(options.events);
2061
+ const filters = signal4({
2062
+ bucketBy: options.bucketBy,
2063
+ fromMs: options.fromMs,
2064
+ toMs: options.toMs
2065
+ });
2066
+ const report = computed4(() => {
2067
+ const f = filters();
2068
+ return buildVoiceCostDashboardReport({
2069
+ bucketBy: f.bucketBy,
2070
+ events: events(),
2071
+ fromMs: f.fromMs,
2072
+ toMs: f.toMs
2073
+ });
2074
+ });
2075
+ return {
2076
+ currency: options.currency ?? "USD",
2077
+ report,
2078
+ setEvents: (next) => events.set(next),
2079
+ setFilters: (next) => filters.update((current) => ({
2080
+ ...current,
2081
+ bucketBy: next.bucketBy ?? current.bucketBy,
2082
+ fromMs: next.fromMs ?? current.fromMs,
2083
+ toMs: next.toMs ?? current.toMs
2084
+ })),
2085
+ title: options.title ?? "Voice cost dashboard"
2086
+ };
2087
+ }
2088
+ }
2089
+ VoiceCostDashboardService = __decorateElement(_init, 0, "VoiceCostDashboardService", _dec, VoiceCostDashboardService);
2090
+ __runInitializers(_init, 1, VoiceCostDashboardService);
2091
+ __decoratorMetadata(_init, VoiceCostDashboardService);
2092
+ let _VoiceCostDashboardService = VoiceCostDashboardService;
2093
+ // src/angular/voice-live-agent-console.service.ts
2094
+ import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
2095
+
2096
+ // src/client/liveCallViewer.ts
2097
+ var EVENT_BUFFER_LIMIT = 200;
2098
+ var createLiveCallViewer = (options) => {
2099
+ const bufferLimit = options.bufferLimit ?? EVENT_BUFFER_LIMIT;
2100
+ const subscribers = new Set;
2101
+ let state = {
2102
+ agentState: "idle",
2103
+ callDurationMs: 0,
2104
+ events: [],
2105
+ isConnected: true,
2106
+ isLiveListening: true,
2107
+ partialTranscript: "",
2108
+ sessionId: options.sessionId
2109
+ };
2110
+ const startedAt = options.startedAt ?? Date.now();
2111
+ const notify = () => {
2112
+ for (const subscriber of subscribers)
2113
+ subscriber();
2114
+ };
2115
+ const update = (next) => {
2116
+ state = { ...state, ...next };
2117
+ state.callDurationMs = Math.max(0, Date.now() - startedAt);
2118
+ state.agentState = deriveVoiceAgentUIState({
2119
+ hasActivePartial: state.partialTranscript.length > 0,
2120
+ isConnected: state.isConnected,
2121
+ isPlaying: false,
2122
+ isRecording: state.isLiveListening,
2123
+ lastAssistantAt: state.lastAssistantAt,
2124
+ lastTranscriptAt: state.lastTranscriptAt
2125
+ });
2126
+ notify();
2127
+ };
2128
+ const pushEvent = (event) => {
2129
+ const next = state.events.concat(event);
2130
+ if (next.length > bufferLimit) {
2131
+ next.splice(0, next.length - bufferLimit);
2132
+ }
2133
+ update({ events: next });
2134
+ };
2135
+ return {
2136
+ applyControl: (control) => {
2137
+ pushEvent({
2138
+ at: Date.now(),
2139
+ detail: control.reason,
2140
+ kind: "lifecycle",
2141
+ title: `control:${control.type}`
2142
+ });
2143
+ },
2144
+ applyEvent: pushEvent,
2145
+ applyMonitorEvent: ({ payload, type }) => {
2146
+ pushEvent({
2147
+ at: Date.now(),
2148
+ detail: JSON.stringify(payload).slice(0, 240),
2149
+ kind: type === "call.lifecycle" ? "lifecycle" : "lifecycle",
2150
+ title: type
2151
+ });
2152
+ },
2153
+ getState: () => state,
2154
+ noteAgentAudio: (at) => {
2155
+ const ts = at ?? Date.now();
2156
+ update({ lastAssistantAt: ts });
2157
+ pushEvent({
2158
+ at: ts,
2159
+ kind: "agent_audio",
2160
+ title: "Agent audio frame"
2161
+ });
2162
+ },
2163
+ notePartial: (text, at) => {
2164
+ update({ partialTranscript: text });
2165
+ if (text) {
2166
+ pushEvent({
2167
+ at: at ?? Date.now(),
2168
+ detail: text,
2169
+ kind: "transcript",
2170
+ title: "Partial"
2171
+ });
2172
+ }
2173
+ },
2174
+ noteTranscript: (text, at) => {
2175
+ const ts = at ?? Date.now();
2176
+ update({ lastTranscriptAt: ts, partialTranscript: "" });
2177
+ pushEvent({
2178
+ at: ts,
2179
+ detail: text,
2180
+ kind: "transcript",
2181
+ title: "Final transcript"
2182
+ });
2183
+ },
2184
+ reset: (sessionId, startedAtOverride) => {
2185
+ state = {
2186
+ agentState: "idle",
2187
+ callDurationMs: 0,
2188
+ events: [],
2189
+ isConnected: true,
2190
+ isLiveListening: true,
2191
+ partialTranscript: "",
2192
+ sessionId
2193
+ };
2194
+ if (typeof startedAtOverride === "number") {}
2195
+ notify();
2196
+ },
2197
+ subscribe: (subscriber) => {
2198
+ subscribers.add(subscriber);
2199
+ return () => subscribers.delete(subscriber);
2200
+ }
2201
+ };
2202
+ };
2203
+
2204
+ // src/client/liveAgentConsole.ts
2205
+ var createLiveAgentConsole = (options) => {
2206
+ const viewer = createLiveCallViewer(options);
2207
+ const recentLimit = Math.max(1, options.recentLimit ?? 12);
2208
+ let caller;
2209
+ let hasTakeover = false;
2210
+ let takeoverAt;
2211
+ let takeoverReason;
2212
+ const subscribers = new Set;
2213
+ const buildState = () => {
2214
+ const view = viewer.getState();
2215
+ return {
2216
+ caller,
2217
+ hasTakeover,
2218
+ recentTimeline: view.events.slice(-recentLimit),
2219
+ takeoverAt,
2220
+ takeoverReason,
2221
+ view
2222
+ };
2223
+ };
2224
+ const notify = () => {
2225
+ for (const subscriber of subscribers)
2226
+ subscriber();
2227
+ };
2228
+ const unsubscribeViewer = viewer.subscribe(() => {
2229
+ notify();
2230
+ });
2231
+ if (options.resolveCaller) {
2232
+ Promise.resolve(options.resolveCaller()).then((snapshot) => {
2233
+ caller = snapshot;
2234
+ notify();
2235
+ });
2236
+ }
2237
+ return {
2238
+ getState: buildState,
2239
+ noteAgentAudio: (at) => viewer.noteAgentAudio(at),
2240
+ notePartial: (text, at) => viewer.notePartial(text, at),
2241
+ noteTranscript: (text, at) => viewer.noteTranscript(text, at),
2242
+ releaseTakeover: () => {
2243
+ if (!hasTakeover)
2244
+ return;
2245
+ hasTakeover = false;
2246
+ takeoverAt = undefined;
2247
+ takeoverReason = undefined;
2248
+ viewer.applyControl({ reason: "released", type: "takeover.release" });
2249
+ notify();
2250
+ },
2251
+ setCaller: (snapshot) => {
2252
+ caller = snapshot;
2253
+ notify();
2254
+ },
2255
+ subscribe: (listener) => {
2256
+ subscribers.add(listener);
2257
+ return () => {
2258
+ subscribers.delete(listener);
2259
+ if (subscribers.size === 0)
2260
+ unsubscribeViewer();
2261
+ };
2262
+ },
2263
+ takeover: (reason) => {
2264
+ if (hasTakeover)
2265
+ return;
2266
+ hasTakeover = true;
2267
+ takeoverAt = Date.now();
2268
+ takeoverReason = reason;
2269
+ viewer.applyControl({ reason, type: "takeover.engaged" });
2270
+ notify();
2271
+ },
2272
+ viewer
2273
+ };
2274
+ };
2275
+
2276
+ // src/angular/voice-live-agent-console.service.ts
2277
+ var _dec = [
2278
+ Injectable5({ providedIn: "root" })
2279
+ ];
2280
+ var _init = __decoratorStart(undefined);
2281
+
2282
+ class VoiceLiveAgentConsoleService {
2283
+ build(options) {
2284
+ const console = createLiveAgentConsole(options);
2285
+ const stateSignal = signal5(console.getState());
2286
+ const unsubscribe = console.subscribe(() => {
2287
+ stateSignal.set(console.getState());
2288
+ });
2289
+ return {
2290
+ releaseTakeover: () => console.releaseTakeover(),
2291
+ setCaller: (caller) => console.setCaller(caller),
2292
+ state: computed5(() => stateSignal()),
2293
+ stop: () => unsubscribe(),
2294
+ takeover: (reason) => console.takeover(reason),
2295
+ takeoverButtonLabel: options.takeoverButtonLabel ?? "Take over",
2296
+ title: options.title ?? "Live agent console"
2297
+ };
2298
+ }
2299
+ }
2300
+ VoiceLiveAgentConsoleService = __decorateElement(_init, 0, "VoiceLiveAgentConsoleService", _dec, VoiceLiveAgentConsoleService);
2301
+ __runInitializers(_init, 1, VoiceLiveAgentConsoleService);
2302
+ __decoratorMetadata(_init, VoiceLiveAgentConsoleService);
2303
+ let _VoiceLiveAgentConsoleService = VoiceLiveAgentConsoleService;
2304
+ // src/angular/voice-live-call-viewer.service.ts
2305
+ import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
2306
+ var _dec = [
2307
+ Injectable6({ providedIn: "root" })
2308
+ ];
2309
+ var _init = __decoratorStart(undefined);
2310
+
2311
+ class VoiceLiveCallViewerService {
2312
+ build(options) {
2313
+ const viewer = options.viewer ?? createLiveCallViewer(options);
2314
+ const stateSignal = signal6(viewer.getState());
2315
+ const unsubscribe = viewer.subscribe(() => {
2316
+ stateSignal.set(viewer.getState());
2317
+ });
2318
+ return {
2319
+ noteAgentAudio: (at) => viewer.noteAgentAudio(at),
2320
+ notePartial: (text, at) => viewer.notePartial(text, at),
2321
+ noteTranscript: (text, at) => viewer.noteTranscript(text, at),
2322
+ reset: (sessionId, startedAt) => viewer.reset(sessionId, startedAt),
2323
+ state: computed6(() => stateSignal()),
2324
+ stop: () => unsubscribe(),
2325
+ title: options.title ?? "Live call"
2326
+ };
2327
+ }
2328
+ }
2329
+ VoiceLiveCallViewerService = __decorateElement(_init, 0, "VoiceLiveCallViewerService", _dec, VoiceLiveCallViewerService);
2330
+ __runInitializers(_init, 1, VoiceLiveCallViewerService);
2331
+ __decoratorMetadata(_init, VoiceLiveCallViewerService);
2332
+ let _VoiceLiveCallViewerService = VoiceLiveCallViewerService;
2333
+ // src/angular/voice-replay-timeline.service.ts
2334
+ import { computed as computed7, Injectable as Injectable7, signal as signal7 } from "@angular/core";
2335
+
2336
+ // src/client/replayTimeline.ts
2337
+ var categorize = (entry) => {
2338
+ const event = entry.event.toLowerCase();
2339
+ if (event.startsWith("stt.") || event.includes("user"))
2340
+ return "user";
2341
+ if (event.startsWith("tts.") || event.includes("assistant") || event.includes("agent"))
2342
+ return "agent";
2343
+ if (event.startsWith("tool.") || event.includes("tool"))
2344
+ return "tool";
2345
+ return "lifecycle";
2346
+ };
2347
+ var buildReplayTimelineReport = (input) => {
2348
+ const events = [];
2349
+ let summaryAgentTurns = 0;
2350
+ let summaryUserTurns = 0;
2351
+ let summaryToolCalls = 0;
2352
+ for (const entry of input.artifact.timeline ?? []) {
2353
+ const category = categorize(entry);
2354
+ if (category === "user")
2355
+ summaryUserTurns += 1;
2356
+ if (category === "agent")
2357
+ summaryAgentTurns += 1;
2358
+ if (category === "tool")
2359
+ summaryToolCalls += 1;
2360
+ events.push({
2361
+ at: entry.atMs,
2362
+ category,
2363
+ detail: entry.text ?? entry.reason,
2364
+ durationMs: entry.chunkDurationMs,
2365
+ label: entry.event
2366
+ });
2367
+ }
2368
+ events.sort((a, b) => a.at - b.at);
2369
+ const first = events[0]?.at ?? 0;
2370
+ const last = events.at(-1)?.at ?? first;
2371
+ return {
2372
+ duration: last - first,
2373
+ events,
2374
+ metadata: {
2375
+ artifactId: input.artifact.id ?? "",
2376
+ title: input.artifact.title
2377
+ },
2378
+ startedAt: first,
2379
+ summary: {
2380
+ agentTurns: summaryAgentTurns,
2381
+ toolCalls: summaryToolCalls,
2382
+ userTurns: summaryUserTurns
2383
+ }
2384
+ };
2385
+ };
2386
+
2387
+ // src/angular/voice-replay-timeline.service.ts
2388
+ var _dec = [
2389
+ Injectable7({ providedIn: "root" })
2390
+ ];
2391
+ var _init = __decoratorStart(undefined);
2392
+
2393
+ class VoiceReplayTimelineService {
2394
+ build(options) {
2395
+ const artifact = signal7(options.artifact);
2396
+ const report = computed7(() => buildReplayTimelineReport({ artifact: artifact() }));
2397
+ return {
2398
+ report,
2399
+ setArtifact: (next) => artifact.set(next),
2400
+ title: options.title
2401
+ };
2402
+ }
2403
+ }
2404
+ VoiceReplayTimelineService = __decorateElement(_init, 0, "VoiceReplayTimelineService", _dec, VoiceReplayTimelineService);
2405
+ __runInitializers(_init, 1, VoiceReplayTimelineService);
2406
+ __decoratorMetadata(_init, VoiceReplayTimelineService);
2407
+ let _VoiceReplayTimelineService = VoiceReplayTimelineService;
2408
+ // src/angular/voice-platform-coverage.service.ts
2409
+ import { computed as computed8, Injectable as Injectable8, signal as signal8 } from "@angular/core";
2410
+
2411
+ // src/client/platformCoverage.ts
2412
+ var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
2413
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2414
+ const response = await fetchImpl(path);
2415
+ if (!response.ok) {
2416
+ throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
2417
+ }
2418
+ return await response.json();
2419
+ };
2420
+ var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
2421
+ const listeners = new Set;
2422
+ let closed = false;
2423
+ let timer;
2424
+ let snapshot = {
2425
+ error: null,
2426
+ isLoading: false
2427
+ };
2428
+ const emit = () => {
2429
+ for (const listener of listeners) {
2430
+ listener();
2431
+ }
2432
+ };
2433
+ const refresh = async () => {
2434
+ if (closed) {
2435
+ return snapshot.report;
2436
+ }
2437
+ snapshot = {
2438
+ ...snapshot,
2439
+ error: null,
2440
+ isLoading: true
2441
+ };
2442
+ emit();
2443
+ try {
2444
+ const report = await fetchVoicePlatformCoverage(path, options);
2445
+ snapshot = {
2446
+ error: null,
2447
+ isLoading: false,
2448
+ report,
2449
+ updatedAt: Date.now()
2450
+ };
2451
+ emit();
2452
+ return report;
2453
+ } catch (error) {
2454
+ snapshot = {
2455
+ ...snapshot,
2456
+ error: error instanceof Error ? error.message : String(error),
2457
+ isLoading: false
2458
+ };
2459
+ emit();
2460
+ throw error;
2461
+ }
2462
+ };
2463
+ const close = () => {
2464
+ closed = true;
2465
+ if (timer) {
2466
+ clearInterval(timer);
2467
+ timer = undefined;
2468
+ }
2469
+ listeners.clear();
2470
+ };
2471
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2472
+ timer = setInterval(() => {
2473
+ refresh().catch(() => {});
2474
+ }, options.intervalMs);
2475
+ }
2476
+ return {
2477
+ close,
2478
+ getServerSnapshot: () => snapshot,
2479
+ getSnapshot: () => snapshot,
2480
+ refresh,
2481
+ subscribe: (listener) => {
2482
+ listeners.add(listener);
2483
+ return () => {
2484
+ listeners.delete(listener);
2485
+ };
2486
+ }
2487
+ };
2488
+ };
2489
+
2490
+ // src/angular/voice-platform-coverage.service.ts
2491
+ var _dec = [
2492
+ Injectable8({ providedIn: "root" })
2493
+ ];
2494
+ var _init = __decoratorStart(undefined);
2495
+
2496
+ class VoicePlatformCoverageService {
2497
+ connect(path = "/api/voice/platform-coverage", options = {}) {
2498
+ const store = createVoicePlatformCoverageStore(path, options);
2499
+ const errorSignal = signal8(null);
2500
+ const isLoadingSignal = signal8(false);
2501
+ const reportSignal = signal8(undefined);
2502
+ const updatedAtSignal = signal8(undefined);
2503
+ const sync = () => {
2504
+ const snapshot = store.getSnapshot();
2505
+ errorSignal.set(snapshot.error);
2506
+ isLoadingSignal.set(snapshot.isLoading);
2507
+ reportSignal.set(snapshot.report);
2508
+ updatedAtSignal.set(snapshot.updatedAt);
2509
+ };
2510
+ const unsubscribe = store.subscribe(sync);
2511
+ sync();
2512
+ if (typeof window !== "undefined") {
2513
+ store.refresh().catch(() => {});
2514
+ }
2515
+ return {
2516
+ close: () => {
2517
+ unsubscribe();
2518
+ store.close();
2519
+ },
2520
+ error: computed8(() => errorSignal()),
2521
+ isLoading: computed8(() => isLoadingSignal()),
2522
+ refresh: store.refresh,
2523
+ report: computed8(() => reportSignal()),
2524
+ updatedAt: computed8(() => updatedAtSignal())
2525
+ };
2526
+ }
2527
+ }
2528
+ VoicePlatformCoverageService = __decorateElement(_init, 0, "VoicePlatformCoverageService", _dec, VoicePlatformCoverageService);
2529
+ __runInitializers(_init, 1, VoicePlatformCoverageService);
2530
+ __decoratorMetadata(_init, VoicePlatformCoverageService);
2531
+ let _VoicePlatformCoverageService = VoicePlatformCoverageService;
2532
+ // src/angular/voice-proof-trends.service.ts
2533
+ import { computed as computed9, Injectable as Injectable9, signal as signal9 } from "@angular/core";
2534
+
2535
+ // src/client/proofTrends.ts
2536
+ var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
2537
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2538
+ const response = await fetchImpl(path);
2539
+ if (!response.ok) {
2540
+ throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
2541
+ }
2542
+ return await response.json();
2543
+ };
2544
+ var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {}) => {
2545
+ const listeners = new Set;
2546
+ let closed = false;
2547
+ let timer;
2548
+ let snapshot = {
2549
+ error: null,
2550
+ isLoading: false
2551
+ };
2552
+ const emit = () => {
2553
+ for (const listener of listeners) {
2554
+ listener();
2555
+ }
2556
+ };
2557
+ const refresh = async () => {
2558
+ if (closed) {
2559
+ return snapshot.report;
2560
+ }
2561
+ snapshot = {
2562
+ ...snapshot,
2563
+ error: null,
2564
+ isLoading: true
2565
+ };
2566
+ emit();
2567
+ try {
2568
+ const report = await fetchVoiceProofTrends(path, options);
2569
+ snapshot = {
2570
+ error: null,
2571
+ isLoading: false,
2572
+ report,
2573
+ updatedAt: Date.now()
2574
+ };
2575
+ emit();
2576
+ return report;
2577
+ } catch (error) {
2578
+ snapshot = {
2579
+ ...snapshot,
2580
+ error: error instanceof Error ? error.message : String(error),
2581
+ isLoading: false
2582
+ };
2583
+ emit();
2584
+ throw error;
2585
+ }
2586
+ };
2587
+ const close = () => {
2588
+ closed = true;
2589
+ if (timer) {
2590
+ clearInterval(timer);
2591
+ timer = undefined;
2592
+ }
2593
+ listeners.clear();
2594
+ };
2595
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2596
+ timer = setInterval(() => {
2597
+ refresh().catch(() => {});
2598
+ }, options.intervalMs);
2599
+ }
2600
+ return {
2601
+ close,
2602
+ getServerSnapshot: () => snapshot,
2603
+ getSnapshot: () => snapshot,
2604
+ refresh,
2605
+ subscribe: (listener) => {
2606
+ listeners.add(listener);
2607
+ return () => {
2608
+ listeners.delete(listener);
2609
+ };
2610
+ }
2611
+ };
2612
+ };
2613
+
2614
+ // src/angular/voice-proof-trends.service.ts
2615
+ var _dec = [
2616
+ Injectable9({ providedIn: "root" })
2617
+ ];
2618
+ var _init = __decoratorStart(undefined);
2619
+
2620
+ class VoiceProofTrendsService {
2621
+ connect(path = "/api/voice/proof-trends", options = {}) {
2622
+ const store = createVoiceProofTrendsStore(path, options);
2623
+ const errorSignal = signal9(null);
2624
+ const isLoadingSignal = signal9(false);
2625
+ const reportSignal = signal9(undefined);
2626
+ const updatedAtSignal = signal9(undefined);
2627
+ const sync = () => {
2628
+ const snapshot = store.getSnapshot();
2629
+ errorSignal.set(snapshot.error);
2630
+ isLoadingSignal.set(snapshot.isLoading);
2631
+ reportSignal.set(snapshot.report);
2632
+ updatedAtSignal.set(snapshot.updatedAt);
2633
+ };
2634
+ const unsubscribe = store.subscribe(sync);
2635
+ sync();
2636
+ if (typeof window !== "undefined") {
2637
+ store.refresh().catch(() => {});
2638
+ }
2639
+ return {
2640
+ close: () => {
2641
+ unsubscribe();
2642
+ store.close();
2643
+ },
2644
+ error: computed9(() => errorSignal()),
2645
+ isLoading: computed9(() => isLoadingSignal()),
2646
+ refresh: store.refresh,
2647
+ report: computed9(() => reportSignal()),
2648
+ updatedAt: computed9(() => updatedAtSignal())
2649
+ };
2650
+ }
2651
+ }
2652
+ VoiceProofTrendsService = __decorateElement(_init, 0, "VoiceProofTrendsService", _dec, VoiceProofTrendsService);
2653
+ __runInitializers(_init, 1, VoiceProofTrendsService);
2654
+ __decoratorMetadata(_init, VoiceProofTrendsService);
2655
+ let _VoiceProofTrendsService = VoiceProofTrendsService;
2656
+ // src/angular/voice-reconnect-profile-evidence.service.ts
2657
+ import { computed as computed10, Injectable as Injectable10, signal as signal10 } from "@angular/core";
2658
+
2659
+ // src/client/reconnectProfileEvidence.ts
2660
+ var fetchVoiceReconnectProfileEvidence = async (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
2661
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2662
+ const response = await fetchImpl(path);
2663
+ if (!response.ok) {
2664
+ throw new Error(`Voice reconnect profile evidence failed: HTTP ${response.status}`);
2665
+ }
2666
+ return await response.json();
2667
+ };
2668
+ var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
2669
+ const listeners = new Set;
2670
+ let closed = false;
2671
+ let timer;
2672
+ let snapshot = {
2673
+ error: null,
2674
+ isLoading: false
2675
+ };
2676
+ const emit = () => {
2677
+ for (const listener of listeners) {
2678
+ listener();
2679
+ }
2680
+ };
2681
+ const refresh = async () => {
2682
+ if (closed) {
2683
+ return snapshot.report;
2684
+ }
2685
+ snapshot = { ...snapshot, error: null, isLoading: true };
2686
+ emit();
2687
+ try {
2688
+ const report = await fetchVoiceReconnectProfileEvidence(path, options);
2689
+ snapshot = {
2690
+ error: null,
2691
+ isLoading: false,
2692
+ report,
2693
+ updatedAt: Date.now()
2694
+ };
2695
+ emit();
2696
+ return report;
2697
+ } catch (error) {
2698
+ snapshot = {
2699
+ ...snapshot,
2700
+ error: error instanceof Error ? error.message : String(error),
2701
+ isLoading: false
2702
+ };
2703
+ emit();
2704
+ throw error;
2705
+ }
2706
+ };
2707
+ const close = () => {
2708
+ closed = true;
2709
+ if (timer) {
2710
+ clearInterval(timer);
2711
+ timer = undefined;
2712
+ }
2713
+ listeners.clear();
2714
+ };
2715
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
2716
+ timer = setInterval(() => {
2717
+ refresh().catch(() => {});
2718
+ }, options.intervalMs);
2719
+ }
2720
+ return {
2721
+ close,
2722
+ getServerSnapshot: () => snapshot,
2723
+ getSnapshot: () => snapshot,
2724
+ refresh,
2725
+ subscribe: (listener) => {
2726
+ listeners.add(listener);
2727
+ return () => {
2728
+ listeners.delete(listener);
2729
+ };
2730
+ }
2731
+ };
2732
+ };
2733
+
2734
+ // src/angular/voice-reconnect-profile-evidence.service.ts
2735
+ var _dec = [
2736
+ Injectable10({ providedIn: "root" })
2737
+ ];
2738
+ var _init = __decoratorStart(undefined);
2739
+
2740
+ class VoiceReconnectProfileEvidenceService {
2741
+ connect(path = "/api/voice/reconnect-profile-evidence", options = {}) {
2742
+ const store = createVoiceReconnectProfileEvidenceStore(path, options);
2743
+ const errorSignal = signal10(null);
2744
+ const isLoadingSignal = signal10(false);
2745
+ const reportSignal = signal10(undefined);
2746
+ const updatedAtSignal = signal10(undefined);
2747
+ const sync = () => {
2748
+ const snapshot = store.getSnapshot();
2749
+ errorSignal.set(snapshot.error);
2750
+ isLoadingSignal.set(snapshot.isLoading);
2751
+ reportSignal.set(snapshot.report);
2752
+ updatedAtSignal.set(snapshot.updatedAt);
2753
+ };
2754
+ const unsubscribe = store.subscribe(sync);
2755
+ sync();
2756
+ if (typeof window !== "undefined") {
2757
+ store.refresh().catch(() => {});
2758
+ }
2759
+ return {
2760
+ close: () => {
2761
+ unsubscribe();
2762
+ store.close();
2763
+ },
2764
+ error: computed10(() => errorSignal()),
2765
+ isLoading: computed10(() => isLoadingSignal()),
2766
+ refresh: store.refresh,
2767
+ report: computed10(() => reportSignal()),
2768
+ updatedAt: computed10(() => updatedAtSignal())
2769
+ };
2770
+ }
2771
+ }
2772
+ VoiceReconnectProfileEvidenceService = __decorateElement(_init, 0, "VoiceReconnectProfileEvidenceService", _dec, VoiceReconnectProfileEvidenceService);
2773
+ __runInitializers(_init, 1, VoiceReconnectProfileEvidenceService);
2774
+ __decoratorMetadata(_init, VoiceReconnectProfileEvidenceService);
2775
+ let _VoiceReconnectProfileEvidenceService = VoiceReconnectProfileEvidenceService;
2776
+ // src/angular/voice-call-debugger.service.ts
2777
+ import { computed as computed11, Injectable as Injectable11, signal as signal11 } from "@angular/core";
2778
+
2779
+ // src/client/callDebugger.ts
2780
+ var fetchVoiceCallDebugger = async (path, options = {}) => {
2781
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2782
+ const response = await fetchImpl(path);
2783
+ if (!response.ok) {
2784
+ throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
2785
+ }
2786
+ return await response.json();
2787
+ };
2788
+ var createVoiceCallDebuggerStore = (path, options = {}) => {
2789
+ const listeners = new Set;
2790
+ let closed = false;
2791
+ let timer;
2792
+ let snapshot = {
2793
+ error: null,
2794
+ isLoading: false
2795
+ };
2796
+ const emit = () => {
2797
+ for (const listener of listeners) {
2798
+ listener();
2799
+ }
2800
+ };
2801
+ const refresh = async () => {
2802
+ if (closed) {
2803
+ return snapshot.report;
2804
+ }
2805
+ snapshot = { ...snapshot, error: null, isLoading: true };
2806
+ emit();
2807
+ try {
2808
+ const report = await fetchVoiceCallDebugger(path, options);
2809
+ snapshot = {
2810
+ error: null,
2811
+ isLoading: false,
2812
+ report,
2813
+ updatedAt: Date.now()
2814
+ };
2815
+ emit();
2816
+ return report;
2817
+ } catch (error) {
2818
+ snapshot = {
2819
+ ...snapshot,
2820
+ error: error instanceof Error ? error.message : String(error),
2821
+ isLoading: false
2822
+ };
2823
+ emit();
2824
+ throw error;
2825
+ }
2826
+ };
2827
+ const close = () => {
2828
+ closed = true;
2829
+ if (timer) {
2830
+ clearInterval(timer);
2831
+ timer = undefined;
2832
+ }
2833
+ listeners.clear();
2834
+ };
2835
+ if (options.intervalMs && options.intervalMs > 0) {
2836
+ timer = setInterval(() => {
2837
+ refresh().catch(() => {});
2838
+ }, options.intervalMs);
2839
+ }
2840
+ return {
2841
+ close,
2842
+ getServerSnapshot: () => snapshot,
2843
+ getSnapshot: () => snapshot,
2844
+ refresh,
2845
+ subscribe: (listener) => {
2846
+ listeners.add(listener);
2847
+ return () => {
2848
+ listeners.delete(listener);
2849
+ };
2850
+ }
2851
+ };
2852
+ };
2853
+
2854
+ // src/angular/voice-call-debugger.service.ts
2855
+ var _dec = [
2856
+ Injectable11({ providedIn: "root" })
2857
+ ];
2858
+ var _init = __decoratorStart(undefined);
2859
+
2860
+ class VoiceCallDebuggerService {
2861
+ connect(path, options = {}) {
2862
+ const store = createVoiceCallDebuggerStore(path, options);
2863
+ const errorSignal = signal11(null);
2864
+ const isLoadingSignal = signal11(false);
2865
+ const reportSignal = signal11(undefined);
2866
+ const updatedAtSignal = signal11(undefined);
2867
+ const sync = () => {
2868
+ const state = store.getSnapshot();
2869
+ errorSignal.set(state.error);
2870
+ isLoadingSignal.set(state.isLoading);
2871
+ reportSignal.set(state.report);
2872
+ updatedAtSignal.set(state.updatedAt);
2873
+ };
2874
+ const unsubscribe = store.subscribe(sync);
2875
+ sync();
2876
+ store.refresh().catch(() => {});
2877
+ return {
2878
+ close: () => {
2879
+ unsubscribe();
2880
+ store.close();
2881
+ },
2882
+ error: computed11(() => errorSignal()),
2883
+ isLoading: computed11(() => isLoadingSignal()),
2884
+ refresh: store.refresh,
2885
+ report: computed11(() => reportSignal()),
2886
+ updatedAt: computed11(() => updatedAtSignal())
2887
+ };
2888
+ }
2889
+ }
2890
+ VoiceCallDebuggerService = __decorateElement(_init, 0, "VoiceCallDebuggerService", _dec, VoiceCallDebuggerService);
2891
+ __runInitializers(_init, 1, VoiceCallDebuggerService);
2892
+ __decoratorMetadata(_init, VoiceCallDebuggerService);
2893
+ let _VoiceCallDebuggerService = VoiceCallDebuggerService;
2894
+ // src/angular/voice-session-snapshot.service.ts
2895
+ import { computed as computed12, Injectable as Injectable12, signal as signal12 } from "@angular/core";
2896
+
2897
+ // src/client/sessionSnapshot.ts
2898
+ var withTurnId = (path, turnId) => {
2899
+ if (!turnId) {
2900
+ return path;
2901
+ }
2902
+ const url = new URL(path, "http://absolutejs.local");
2903
+ url.searchParams.set("turnId", turnId);
2904
+ return `${url.pathname}${url.search}`;
2905
+ };
2906
+ var fetchVoiceSessionSnapshot = async (path, options = {}) => {
2907
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2908
+ const response = await fetchImpl(withTurnId(path, options.turnId));
2909
+ if (!response.ok) {
2910
+ throw new Error(`Voice session snapshot failed: HTTP ${response.status}`);
2911
+ }
2912
+ return await response.json();
2913
+ };
2914
+ var createVoiceSessionSnapshotStore = (path, options = {}) => {
2915
+ const listeners = new Set;
2916
+ let closed = false;
2917
+ let timer;
2918
+ let snapshot = {
2919
+ error: null,
2920
+ isLoading: false
2921
+ };
2922
+ const emit = () => {
2923
+ for (const listener of listeners) {
2924
+ listener();
2925
+ }
2926
+ };
2927
+ const refresh = async () => {
2928
+ if (closed) {
2929
+ return snapshot.snapshot;
2930
+ }
2931
+ snapshot = { ...snapshot, error: null, isLoading: true };
2932
+ emit();
2933
+ try {
2934
+ const next = await fetchVoiceSessionSnapshot(path, options);
2935
+ snapshot = {
2936
+ error: null,
2937
+ isLoading: false,
2938
+ snapshot: next,
2939
+ updatedAt: Date.now()
2940
+ };
2941
+ emit();
2942
+ return next;
2943
+ } catch (error) {
2944
+ snapshot = {
2945
+ ...snapshot,
2946
+ error: error instanceof Error ? error.message : String(error),
2947
+ isLoading: false
2948
+ };
2949
+ emit();
2950
+ throw error;
2951
+ }
2952
+ };
2953
+ const download = () => {
2954
+ const current = snapshot.snapshot;
2955
+ if (current === undefined) {
2956
+ throw new Error("Voice session snapshot has not been loaded.");
2957
+ }
2958
+ return new Blob([JSON.stringify(current, null, 2)], {
2959
+ type: "application/json"
2960
+ });
2961
+ };
2962
+ const close = () => {
2963
+ closed = true;
2964
+ if (timer) {
2965
+ clearInterval(timer);
2966
+ timer = undefined;
2967
+ }
2968
+ listeners.clear();
2969
+ };
2970
+ if (options.intervalMs && options.intervalMs > 0) {
2971
+ timer = setInterval(() => {
2972
+ refresh().catch(() => {});
2973
+ }, options.intervalMs);
2974
+ }
2975
+ return {
2976
+ close,
2977
+ download,
2978
+ getServerSnapshot: () => snapshot,
2979
+ getSnapshot: () => snapshot,
2980
+ refresh,
2981
+ subscribe: (listener) => {
2982
+ listeners.add(listener);
2983
+ return () => {
2984
+ listeners.delete(listener);
2985
+ };
2986
+ }
2987
+ };
2988
+ };
2989
+
2990
+ // src/angular/voice-session-snapshot.service.ts
2991
+ var _dec = [
2992
+ Injectable12({ providedIn: "root" })
2993
+ ];
2994
+ var _init = __decoratorStart(undefined);
2995
+
2996
+ class VoiceSessionSnapshotService {
2997
+ connect(path, options = {}) {
2998
+ const store = createVoiceSessionSnapshotStore(path, options);
2999
+ const errorSignal = signal12(null);
3000
+ const isLoadingSignal = signal12(false);
3001
+ const snapshotSignal = signal12(undefined);
3002
+ const updatedAtSignal = signal12(undefined);
3003
+ const sync = () => {
3004
+ const state = store.getSnapshot();
3005
+ errorSignal.set(state.error);
3006
+ isLoadingSignal.set(state.isLoading);
3007
+ snapshotSignal.set(state.snapshot);
3008
+ updatedAtSignal.set(state.updatedAt);
3009
+ };
3010
+ const unsubscribe = store.subscribe(sync);
3011
+ sync();
3012
+ store.refresh().catch(() => {});
3013
+ return {
3014
+ close: () => {
3015
+ unsubscribe();
3016
+ store.close();
3017
+ },
3018
+ download: store.download,
3019
+ error: computed12(() => errorSignal()),
3020
+ isLoading: computed12(() => isLoadingSignal()),
3021
+ refresh: store.refresh,
3022
+ snapshot: computed12(() => snapshotSignal()),
3023
+ updatedAt: computed12(() => updatedAtSignal())
3024
+ };
3025
+ }
3026
+ }
3027
+ VoiceSessionSnapshotService = __decorateElement(_init, 0, "VoiceSessionSnapshotService", _dec, VoiceSessionSnapshotService);
3028
+ __runInitializers(_init, 1, VoiceSessionSnapshotService);
3029
+ __decoratorMetadata(_init, VoiceSessionSnapshotService);
3030
+ let _VoiceSessionSnapshotService = VoiceSessionSnapshotService;
3031
+ // src/angular/voice-session-observability.service.ts
3032
+ import { computed as computed13, Injectable as Injectable13, signal as signal13 } from "@angular/core";
3033
+
3034
+ // src/client/sessionObservability.ts
3035
+ var fetchVoiceSessionObservability = async (path, options = {}) => {
3036
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3037
+ const response = await fetchImpl(path);
3038
+ if (!response.ok) {
3039
+ throw new Error(`Voice session observability failed: HTTP ${response.status}`);
3040
+ }
3041
+ return await response.json();
3042
+ };
3043
+ var createVoiceSessionObservabilityStore = (path, options = {}) => {
3044
+ const listeners = new Set;
3045
+ let closed = false;
3046
+ let timer;
3047
+ let snapshot = {
3048
+ error: null,
3049
+ isLoading: false,
3050
+ report: null
3051
+ };
3052
+ const emit = () => {
3053
+ for (const listener of listeners) {
3054
+ listener();
3055
+ }
3056
+ };
3057
+ const refresh = async () => {
3058
+ if (closed) {
3059
+ return snapshot.report;
3060
+ }
3061
+ snapshot = {
3062
+ ...snapshot,
3063
+ error: null,
3064
+ isLoading: true
3065
+ };
3066
+ emit();
3067
+ try {
3068
+ const report = await fetchVoiceSessionObservability(path, options);
3069
+ snapshot = {
3070
+ error: null,
3071
+ isLoading: false,
3072
+ report,
3073
+ updatedAt: Date.now()
3074
+ };
3075
+ emit();
3076
+ return report;
3077
+ } catch (error) {
3078
+ snapshot = {
3079
+ ...snapshot,
3080
+ error: error instanceof Error ? error.message : String(error),
3081
+ isLoading: false
3082
+ };
3083
+ emit();
3084
+ throw error;
3085
+ }
3086
+ };
3087
+ const close = () => {
3088
+ closed = true;
3089
+ if (timer) {
3090
+ clearInterval(timer);
3091
+ timer = undefined;
3092
+ }
3093
+ listeners.clear();
3094
+ };
3095
+ if (options.intervalMs && options.intervalMs > 0) {
3096
+ timer = setInterval(() => {
3097
+ refresh().catch(() => {});
3098
+ }, options.intervalMs);
3099
+ }
3100
+ return {
3101
+ close,
3102
+ getServerSnapshot: () => snapshot,
3103
+ getSnapshot: () => snapshot,
3104
+ refresh,
3105
+ subscribe: (listener) => {
3106
+ listeners.add(listener);
3107
+ return () => {
3108
+ listeners.delete(listener);
3109
+ };
3110
+ }
3111
+ };
3112
+ };
3113
+
3114
+ // src/angular/voice-session-observability.service.ts
3115
+ var _dec = [
3116
+ Injectable13({ providedIn: "root" })
3117
+ ];
3118
+ var _init = __decoratorStart(undefined);
3119
+
3120
+ class VoiceSessionObservabilityService {
3121
+ connect(path = "/api/voice/session-observability/latest", options = {}) {
3122
+ const store = createVoiceSessionObservabilityStore(path, options);
3123
+ const errorSignal = signal13(null);
3124
+ const isLoadingSignal = signal13(false);
3125
+ const reportSignal = signal13(null);
3126
+ const updatedAtSignal = signal13(undefined);
3127
+ const sync = () => {
3128
+ const snapshot = store.getSnapshot();
3129
+ errorSignal.set(snapshot.error);
3130
+ isLoadingSignal.set(snapshot.isLoading);
3131
+ reportSignal.set(snapshot.report);
3132
+ updatedAtSignal.set(snapshot.updatedAt);
3133
+ };
3134
+ const unsubscribe = store.subscribe(sync);
3135
+ sync();
3136
+ store.refresh().catch(() => {});
3137
+ return {
3138
+ close: () => {
3139
+ unsubscribe();
3140
+ store.close();
3141
+ },
3142
+ error: computed13(() => errorSignal()),
3143
+ isLoading: computed13(() => isLoadingSignal()),
3144
+ refresh: store.refresh,
3145
+ report: computed13(() => reportSignal()),
3146
+ updatedAt: computed13(() => updatedAtSignal())
3147
+ };
3148
+ }
3149
+ }
3150
+ VoiceSessionObservabilityService = __decorateElement(_init, 0, "VoiceSessionObservabilityService", _dec, VoiceSessionObservabilityService);
3151
+ __runInitializers(_init, 1, VoiceSessionObservabilityService);
3152
+ __decoratorMetadata(_init, VoiceSessionObservabilityService);
3153
+ let _VoiceSessionObservabilityService = VoiceSessionObservabilityService;
3154
+ // src/angular/voice-profile-comparison.service.ts
3155
+ import { computed as computed14, Injectable as Injectable14, signal as signal14 } from "@angular/core";
3156
+
3157
+ // src/client/profileComparison.ts
3158
+ var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
3159
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3160
+ const response = await fetchImpl(path);
3161
+ if (!response.ok) {
3162
+ throw new Error(`Voice profile comparison failed: HTTP ${response.status}`);
3163
+ }
3164
+ return await response.json();
3165
+ };
3166
+ var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-history", options = {}) => {
3167
+ const listeners = new Set;
3168
+ let closed = false;
3169
+ let timer;
3170
+ let snapshot = {
3171
+ error: null,
3172
+ isLoading: false
3173
+ };
3174
+ const emit = () => {
3175
+ for (const listener of listeners) {
3176
+ listener();
3177
+ }
3178
+ };
3179
+ const refresh = async () => {
3180
+ if (closed) {
3181
+ return snapshot.report;
3182
+ }
3183
+ snapshot = { ...snapshot, error: null, isLoading: true };
3184
+ emit();
3185
+ try {
3186
+ const report = await fetchVoiceProfileComparison(path, options);
3187
+ snapshot = {
3188
+ error: null,
3189
+ isLoading: false,
3190
+ report,
3191
+ updatedAt: Date.now()
3192
+ };
3193
+ emit();
3194
+ return report;
3195
+ } catch (error) {
3196
+ snapshot = {
3197
+ ...snapshot,
3198
+ error: error instanceof Error ? error.message : String(error),
3199
+ isLoading: false
3200
+ };
3201
+ emit();
3202
+ throw error;
3203
+ }
3204
+ };
3205
+ const close = () => {
3206
+ closed = true;
3207
+ if (timer) {
3208
+ clearInterval(timer);
3209
+ timer = undefined;
3210
+ }
3211
+ listeners.clear();
3212
+ };
3213
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
3214
+ timer = setInterval(() => {
3215
+ refresh().catch(() => {});
3216
+ }, options.intervalMs);
3217
+ }
3218
+ return {
3219
+ close,
3220
+ getServerSnapshot: () => snapshot,
3221
+ getSnapshot: () => snapshot,
3222
+ refresh,
3223
+ subscribe: (listener) => {
3224
+ listeners.add(listener);
3225
+ return () => {
3226
+ listeners.delete(listener);
3227
+ };
3228
+ }
3229
+ };
3230
+ };
3231
+
3232
+ // src/angular/voice-profile-comparison.service.ts
3233
+ var _dec = [
3234
+ Injectable14({ providedIn: "root" })
3235
+ ];
3236
+ var _init = __decoratorStart(undefined);
3237
+
3238
+ class VoiceProfileComparisonService {
3239
+ connect(path = "/api/voice/real-call-profile-history", options = {}) {
3240
+ const store = createVoiceProfileComparisonStore(path, options);
3241
+ const errorSignal = signal14(null);
3242
+ const isLoadingSignal = signal14(false);
3243
+ const reportSignal = signal14(undefined);
3244
+ const updatedAtSignal = signal14(undefined);
3245
+ const sync = () => {
3246
+ const snapshot = store.getSnapshot();
3247
+ errorSignal.set(snapshot.error);
3248
+ isLoadingSignal.set(snapshot.isLoading);
3249
+ reportSignal.set(snapshot.report);
3250
+ updatedAtSignal.set(snapshot.updatedAt);
3251
+ };
3252
+ const unsubscribe = store.subscribe(sync);
3253
+ sync();
3254
+ if (typeof window !== "undefined") {
3255
+ store.refresh().catch(() => {});
3256
+ }
3257
+ return {
3258
+ close: () => {
3259
+ unsubscribe();
3260
+ store.close();
3261
+ },
3262
+ error: computed14(() => errorSignal()),
3263
+ isLoading: computed14(() => isLoadingSignal()),
3264
+ refresh: store.refresh,
3265
+ report: computed14(() => reportSignal()),
3266
+ updatedAt: computed14(() => updatedAtSignal())
3267
+ };
3268
+ }
3269
+ }
3270
+ VoiceProfileComparisonService = __decorateElement(_init, 0, "VoiceProfileComparisonService", _dec, VoiceProfileComparisonService);
3271
+ __runInitializers(_init, 1, VoiceProfileComparisonService);
3272
+ __decoratorMetadata(_init, VoiceProfileComparisonService);
3273
+ let _VoiceProfileComparisonService = VoiceProfileComparisonService;
3274
+ // src/angular/voice-readiness-failures.service.ts
3275
+ import { computed as computed15, Injectable as Injectable15, signal as signal15 } from "@angular/core";
3276
+
3277
+ // src/client/readinessFailures.ts
3278
+ var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
3279
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3280
+ const response = await fetchImpl(path);
3281
+ if (!response.ok) {
3282
+ throw new Error(`Voice readiness failed: HTTP ${response.status}`);
3283
+ }
3284
+ return await response.json();
3285
+ };
3286
+ var createVoiceReadinessFailuresStore = (path = "/api/production-readiness", options = {}) => {
3287
+ const listeners = new Set;
3288
+ let closed = false;
3289
+ let timer;
3290
+ let snapshot = {
3291
+ error: null,
3292
+ isLoading: false
3293
+ };
3294
+ const emit = () => {
3295
+ for (const listener of listeners) {
3296
+ listener();
3297
+ }
3298
+ };
3299
+ const refresh = async () => {
3300
+ if (closed) {
3301
+ return snapshot.report;
3302
+ }
3303
+ snapshot = { ...snapshot, error: null, isLoading: true };
3304
+ emit();
3305
+ try {
3306
+ const report = await fetchVoiceReadinessFailures(path, options);
3307
+ snapshot = {
3308
+ error: null,
3309
+ isLoading: false,
3310
+ report,
3311
+ updatedAt: Date.now()
3312
+ };
3313
+ emit();
3314
+ return report;
3315
+ } catch (error) {
3316
+ snapshot = {
3317
+ ...snapshot,
3318
+ error: error instanceof Error ? error.message : String(error),
3319
+ isLoading: false
3320
+ };
3321
+ emit();
3322
+ throw error;
3323
+ }
3324
+ };
3325
+ const close = () => {
3326
+ closed = true;
3327
+ if (timer) {
3328
+ clearInterval(timer);
3329
+ timer = undefined;
3330
+ }
3331
+ listeners.clear();
3332
+ };
3333
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
3334
+ timer = setInterval(() => {
3335
+ refresh().catch(() => {});
3336
+ }, options.intervalMs);
3337
+ }
3338
+ return {
3339
+ close,
3340
+ getServerSnapshot: () => snapshot,
3341
+ getSnapshot: () => snapshot,
3342
+ refresh,
3343
+ subscribe: (listener) => {
3344
+ listeners.add(listener);
3345
+ return () => {
3346
+ listeners.delete(listener);
3347
+ };
3348
+ }
3349
+ };
3350
+ };
3351
+
3352
+ // src/angular/voice-readiness-failures.service.ts
3353
+ var _dec = [
3354
+ Injectable15({ providedIn: "root" })
3355
+ ];
3356
+ var _init = __decoratorStart(undefined);
3357
+
3358
+ class VoiceReadinessFailuresService {
3359
+ connect(path = "/api/production-readiness", options = {}) {
3360
+ const store = createVoiceReadinessFailuresStore(path, options);
3361
+ const errorSignal = signal15(null);
3362
+ const isLoadingSignal = signal15(false);
3363
+ const reportSignal = signal15(undefined);
3364
+ const updatedAtSignal = signal15(undefined);
3365
+ const sync = () => {
3366
+ const snapshot = store.getSnapshot();
3367
+ errorSignal.set(snapshot.error);
3368
+ isLoadingSignal.set(snapshot.isLoading);
3369
+ reportSignal.set(snapshot.report);
3370
+ updatedAtSignal.set(snapshot.updatedAt);
3371
+ };
3372
+ const unsubscribe = store.subscribe(sync);
3373
+ sync();
3374
+ if (typeof window !== "undefined") {
3375
+ store.refresh().catch(() => {});
3376
+ }
3377
+ return {
3378
+ close: () => {
3379
+ unsubscribe();
3380
+ store.close();
3381
+ },
3382
+ error: computed15(() => errorSignal()),
3383
+ explanations: computed15(() => reportSignal()?.checks.filter((check) => check.status !== "pass" && !!check.gateExplanation) ?? []),
3384
+ isLoading: computed15(() => isLoadingSignal()),
3385
+ refresh: store.refresh,
3386
+ report: computed15(() => reportSignal()),
3387
+ updatedAt: computed15(() => updatedAtSignal())
3388
+ };
3389
+ }
3390
+ }
3391
+ VoiceReadinessFailuresService = __decorateElement(_init, 0, "VoiceReadinessFailuresService", _dec, VoiceReadinessFailuresService);
3392
+ __runInitializers(_init, 1, VoiceReadinessFailuresService);
3393
+ __decoratorMetadata(_init, VoiceReadinessFailuresService);
3394
+ let _VoiceReadinessFailuresService = VoiceReadinessFailuresService;
3395
+ // src/angular/voice-ops-action-center.service.ts
3396
+ import { computed as computed16, Injectable as Injectable16, signal as signal16 } from "@angular/core";
3397
+
3398
+ // src/client/opsActionCenter.ts
3399
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
3400
+ if (options.auditPath === false) {
3401
+ return;
3402
+ }
3403
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
3404
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3405
+ const response = await fetchImpl(path, {
3406
+ body: JSON.stringify(result),
3407
+ headers: {
3408
+ "Content-Type": "application/json"
3409
+ },
3410
+ method: "POST"
3411
+ });
3412
+ if (!response.ok) {
3413
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
3414
+ }
3415
+ };
3416
+ var createVoiceOpsActionCenterActions = (options = {}) => {
3417
+ const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
3418
+ const actions = [];
3419
+ if (options.includeProductionReadiness !== false) {
3420
+ actions.push({
3421
+ description: "Refresh the production readiness report.",
3422
+ id: "production-readiness",
3423
+ label: "Refresh readiness",
3424
+ method: "GET",
3425
+ path: options.productionReadinessPath ?? "/api/production-readiness"
3426
+ });
3427
+ }
3428
+ if (options.includeDeliveryRuntime !== false) {
3429
+ actions.push({
3430
+ description: "Drain pending and failed audit/trace deliveries.",
3431
+ id: "delivery-runtime.tick",
3432
+ label: "Tick delivery workers",
3433
+ method: "POST",
3434
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
3435
+ }, {
3436
+ description: "Move reviewed dead letters back to live delivery queues.",
3437
+ id: "delivery-runtime.requeue-dead-letters",
3438
+ label: "Requeue dead letters",
3439
+ method: "POST",
3440
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
3441
+ });
3442
+ }
3443
+ if (options.includeTurnLatencyProof !== false) {
3444
+ actions.push({
3445
+ description: "Run the synthetic turn latency proof.",
3446
+ id: "turn-latency.proof",
3447
+ label: "Run latency proof",
3448
+ method: "POST",
3449
+ path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
3450
+ });
3451
+ }
3452
+ if (options.includeProviderSimulation !== false) {
3453
+ const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
3454
+ for (const provider of options.providers ?? []) {
3455
+ actions.push({
3456
+ description: `Simulate ${provider} provider failure.`,
3457
+ id: `provider.${provider}.failure`,
3458
+ label: `Simulate ${provider} failure`,
3459
+ method: "POST",
3460
+ path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
3461
+ }, {
3462
+ description: `Mark ${provider} provider recovered.`,
3463
+ id: `provider.${provider}.recovery`,
3464
+ label: `Recover ${provider}`,
3465
+ method: "POST",
3466
+ path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
3467
+ });
3468
+ }
3469
+ }
3470
+ return actions;
3471
+ };
3472
+ var runVoiceOpsAction = async (action, options = {}) => {
3473
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3474
+ const response = await fetchImpl(action.path, {
3475
+ method: action.method ?? "POST"
3476
+ });
3477
+ const body = await response.json().catch(() => null);
3478
+ if (!response.ok) {
3479
+ const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
3480
+ throw new Error(message);
3481
+ }
3482
+ return {
3483
+ actionId: action.id,
3484
+ body,
3485
+ ok: response.ok,
3486
+ ranAt: Date.now(),
3487
+ status: response.status
3488
+ };
3489
+ };
3490
+ var createVoiceOpsActionCenterStore = (options = {}) => {
3491
+ const listeners = new Set;
3492
+ let closed = false;
3493
+ let timer;
3494
+ let snapshot = {
3495
+ actions: options.actions ?? createVoiceOpsActionCenterActions(),
3496
+ error: null,
3497
+ isRunning: false
3498
+ };
3499
+ const emit = () => {
3500
+ for (const listener of listeners) {
3501
+ listener();
3502
+ }
3503
+ };
3504
+ const setActions = (actions) => {
3505
+ snapshot = { ...snapshot, actions, updatedAt: Date.now() };
3506
+ emit();
3507
+ };
3508
+ const run = async (actionId) => {
3509
+ if (closed) {
3510
+ return snapshot.lastResult;
3511
+ }
3512
+ const action = snapshot.actions.find((item) => item.id === actionId);
3513
+ if (!action) {
3514
+ throw new Error(`Voice ops action "${actionId}" is not configured.`);
3515
+ }
3516
+ if (action.disabled) {
3517
+ throw new Error(`Voice ops action "${actionId}" is disabled.`);
3518
+ }
3519
+ snapshot = {
3520
+ ...snapshot,
3521
+ error: null,
3522
+ isRunning: true,
3523
+ runningActionId: action.id
3524
+ };
3525
+ emit();
3526
+ try {
3527
+ const result = await runVoiceOpsAction(action, options);
3528
+ await options.onActionResult?.(result);
3529
+ await recordVoiceOpsActionResult(result, options);
3530
+ snapshot = {
3531
+ ...snapshot,
3532
+ error: null,
3533
+ isRunning: false,
3534
+ lastResult: result,
3535
+ runningActionId: undefined,
3536
+ updatedAt: Date.now()
3537
+ };
3538
+ emit();
3539
+ return result;
3540
+ } catch (error) {
3541
+ const result = {
3542
+ actionId: action.id,
3543
+ body: null,
3544
+ error: error instanceof Error ? error.message : String(error),
3545
+ ok: false,
3546
+ ranAt: Date.now(),
3547
+ status: 0
3548
+ };
3549
+ await options.onActionResult?.(result);
3550
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
3551
+ snapshot = {
3552
+ ...snapshot,
3553
+ error: error instanceof Error ? error.message : String(error),
3554
+ isRunning: false,
3555
+ runningActionId: undefined
3556
+ };
3557
+ emit();
3558
+ throw error;
3559
+ }
3560
+ };
3561
+ const close = () => {
3562
+ closed = true;
3563
+ if (timer) {
3564
+ clearInterval(timer);
3565
+ timer = undefined;
3566
+ }
3567
+ listeners.clear();
3568
+ };
3569
+ if (options.intervalMs && options.intervalMs > 0) {
3570
+ timer = setInterval(() => {
3571
+ emit();
3572
+ }, options.intervalMs);
3573
+ }
3574
+ return {
3575
+ close,
3576
+ getServerSnapshot: () => snapshot,
3577
+ getSnapshot: () => snapshot,
3578
+ run,
3579
+ setActions,
3580
+ subscribe: (listener) => {
3581
+ listeners.add(listener);
3582
+ return () => {
3583
+ listeners.delete(listener);
3584
+ };
3585
+ }
3586
+ };
3587
+ };
3588
+
3589
+ // src/angular/voice-ops-action-center.service.ts
3590
+ var _dec = [
3591
+ Injectable16({ providedIn: "root" })
3592
+ ];
3593
+ var _init = __decoratorStart(undefined);
3594
+
3595
+ class VoiceOpsActionCenterService {
3596
+ connect(options = {}) {
3597
+ const store = createVoiceOpsActionCenterStore(options);
3598
+ const actionsSignal = signal16([]);
3599
+ const errorSignal = signal16(null);
3600
+ const isRunningSignal = signal16(false);
3601
+ const lastResultSignal = signal16(undefined);
3602
+ const runningActionIdSignal = signal16(undefined);
3603
+ const sync = () => {
3604
+ const snapshot = store.getSnapshot();
3605
+ actionsSignal.set(snapshot.actions);
3606
+ errorSignal.set(snapshot.error);
3607
+ isRunningSignal.set(snapshot.isRunning);
3608
+ lastResultSignal.set(snapshot.lastResult);
3609
+ runningActionIdSignal.set(snapshot.runningActionId);
3610
+ };
3611
+ const unsubscribe = store.subscribe(sync);
3612
+ sync();
3613
+ return {
3614
+ actions: computed16(() => actionsSignal()),
3615
+ close: () => {
3616
+ unsubscribe();
3617
+ store.close();
3618
+ },
3619
+ error: computed16(() => errorSignal()),
3620
+ isRunning: computed16(() => isRunningSignal()),
3621
+ lastResult: computed16(() => lastResultSignal()),
3622
+ run: store.run,
3623
+ runningActionId: computed16(() => runningActionIdSignal()),
3624
+ setActions: store.setActions
3625
+ };
3626
+ }
3627
+ }
3628
+ VoiceOpsActionCenterService = __decorateElement(_init, 0, "VoiceOpsActionCenterService", _dec, VoiceOpsActionCenterService);
3629
+ __runInitializers(_init, 1, VoiceOpsActionCenterService);
3630
+ __decoratorMetadata(_init, VoiceOpsActionCenterService);
3631
+ let _VoiceOpsActionCenterService = VoiceOpsActionCenterService;
3632
+ // src/angular/voice-live-ops.service.ts
3633
+ import { computed as computed17, Injectable as Injectable17, signal as signal17 } from "@angular/core";
3634
+
3635
+ // src/client/liveOps.ts
3636
+ var postVoiceLiveOpsAction = async (input, options = {}) => {
3637
+ if (!input.sessionId) {
3638
+ throw new Error("Start a voice session before running live ops actions.");
3639
+ }
3640
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3641
+ const response = await fetchImpl(options.actionPath ?? "/api/voice/live-ops/action", {
3642
+ body: JSON.stringify(input),
3643
+ headers: {
3644
+ "Content-Type": "application/json"
3645
+ },
3646
+ method: "POST"
3647
+ });
3648
+ const payload = await response.json().catch(() => null);
3649
+ if (!response.ok || !payload?.ok) {
3650
+ const message = payload && typeof payload === "object" && "error" in payload ? String(payload.error) : `Voice live ops action failed: HTTP ${response.status}`;
3651
+ throw new Error(message);
3652
+ }
3653
+ return payload;
3654
+ };
3655
+ var createVoiceLiveOpsStore = (options = {}) => {
3656
+ const listeners = new Set;
3657
+ let closed = false;
3658
+ let snapshot = {
3659
+ error: null,
3660
+ isRunning: false
3661
+ };
3662
+ const emit = () => {
3663
+ for (const listener of listeners) {
3664
+ listener();
3665
+ }
3666
+ };
3667
+ const run = async (input) => {
3668
+ if (closed) {
3669
+ return snapshot.lastResult;
3670
+ }
3671
+ snapshot = {
3672
+ ...snapshot,
3673
+ error: null,
3674
+ isRunning: true,
3675
+ runningAction: input.action
3676
+ };
3677
+ emit();
3678
+ try {
3679
+ const result = await postVoiceLiveOpsAction(input, options);
3680
+ await options.onControl?.(result);
3681
+ snapshot = {
3682
+ ...snapshot,
3683
+ error: null,
3684
+ isRunning: false,
3685
+ lastResult: result,
3686
+ runningAction: undefined,
3687
+ updatedAt: Date.now()
3688
+ };
3689
+ emit();
3690
+ return result;
3691
+ } catch (error) {
3692
+ snapshot = {
3693
+ ...snapshot,
3694
+ error: error instanceof Error ? error.message : String(error),
3695
+ isRunning: false,
3696
+ runningAction: undefined,
3697
+ updatedAt: Date.now()
3698
+ };
3699
+ emit();
3700
+ throw error;
3701
+ }
3702
+ };
3703
+ const close = () => {
3704
+ closed = true;
3705
+ listeners.clear();
3706
+ };
3707
+ return {
3708
+ close,
3709
+ getServerSnapshot: () => snapshot,
3710
+ getSnapshot: () => snapshot,
3711
+ run,
3712
+ subscribe: (listener) => {
3713
+ listeners.add(listener);
3714
+ return () => {
3715
+ listeners.delete(listener);
3716
+ };
3717
+ }
3718
+ };
3719
+ };
3720
+
3721
+ // src/angular/voice-live-ops.service.ts
3722
+ var _dec = [
3723
+ Injectable17({ providedIn: "root" })
3724
+ ];
3725
+ var _init = __decoratorStart(undefined);
3726
+
3727
+ class VoiceLiveOpsService {
3728
+ connect(options = {}) {
3729
+ const store = createVoiceLiveOpsStore(options);
3730
+ const errorSignal = signal17(null);
3731
+ const isRunningSignal = signal17(false);
3732
+ const lastResultSignal = signal17(undefined);
3733
+ const runningActionSignal = signal17(undefined);
3734
+ const sync = () => {
3735
+ const snapshot = store.getSnapshot();
3736
+ errorSignal.set(snapshot.error);
3737
+ isRunningSignal.set(snapshot.isRunning);
3738
+ lastResultSignal.set(snapshot.lastResult);
3739
+ runningActionSignal.set(snapshot.runningAction);
3740
+ };
3741
+ const unsubscribe = store.subscribe(sync);
3742
+ sync();
3743
+ return {
3744
+ close: () => {
3745
+ unsubscribe();
3746
+ store.close();
3747
+ },
3748
+ error: computed17(() => errorSignal()),
3749
+ isRunning: computed17(() => isRunningSignal()),
3750
+ lastResult: computed17(() => lastResultSignal()),
3751
+ run: store.run,
3752
+ runningAction: computed17(() => runningActionSignal())
3753
+ };
3754
+ }
3755
+ }
3756
+ VoiceLiveOpsService = __decorateElement(_init, 0, "VoiceLiveOpsService", _dec, VoiceLiveOpsService);
3757
+ __runInitializers(_init, 1, VoiceLiveOpsService);
3758
+ __decoratorMetadata(_init, VoiceLiveOpsService);
3759
+ let _VoiceLiveOpsService = VoiceLiveOpsService;
3760
+ // src/angular/voice-delivery-runtime.service.ts
3761
+ import { computed as computed18, Injectable as Injectable18, signal as signal18 } from "@angular/core";
3762
+
3763
+ // src/client/deliveryRuntime.ts
3764
+ var getDefaultActionPath = (path, action, options) => {
3765
+ if (action === "tick") {
3766
+ return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
3767
+ }
3768
+ return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
3769
+ };
3770
+ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
3771
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3772
+ const response = await fetchImpl(path);
3773
+ if (!response.ok) {
3774
+ throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
3775
+ }
3776
+ return await response.json();
3777
+ };
3778
+ var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
3779
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3780
+ const response = await fetchImpl(getDefaultActionPath(path, action, options), {
3781
+ method: "POST"
3782
+ });
3783
+ if (!response.ok) {
3784
+ throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
3785
+ }
3786
+ const body = await response.json();
3787
+ return {
3788
+ action,
3789
+ result: body.result,
3790
+ summary: body.summary,
3791
+ updatedAt: Date.now()
3792
+ };
3793
+ };
3794
+ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
3795
+ const listeners = new Set;
3796
+ let closed = false;
3797
+ let timer;
3798
+ let snapshot = {
3799
+ actionError: null,
3800
+ actionStatus: "idle",
3801
+ error: null,
3802
+ isLoading: false
3803
+ };
3804
+ const emit = () => {
3805
+ for (const listener of listeners) {
3806
+ listener();
3807
+ }
3808
+ };
3809
+ const refresh = async () => {
3810
+ if (closed) {
3811
+ return snapshot.report;
3812
+ }
3813
+ snapshot = {
3814
+ ...snapshot,
3815
+ error: null,
3816
+ isLoading: true
3817
+ };
3818
+ emit();
3819
+ try {
3820
+ const report = await fetchVoiceDeliveryRuntime(path, options);
3821
+ snapshot = {
3822
+ ...snapshot,
3823
+ error: null,
3824
+ isLoading: false,
3825
+ report,
3826
+ updatedAt: Date.now()
3827
+ };
3828
+ emit();
3829
+ return report;
3830
+ } catch (error) {
3831
+ snapshot = {
3832
+ ...snapshot,
3833
+ error: error instanceof Error ? error.message : String(error),
3834
+ isLoading: false
3835
+ };
3836
+ emit();
3837
+ throw error;
3838
+ }
3839
+ };
3840
+ const runAction = async (action) => {
3841
+ if (closed) {
3842
+ return snapshot.lastAction;
3843
+ }
3844
+ snapshot = {
3845
+ ...snapshot,
3846
+ actionError: null,
3847
+ actionStatus: "running"
3848
+ };
3849
+ emit();
3850
+ try {
3851
+ const result = await runVoiceDeliveryRuntimeAction(action, path, options);
3852
+ snapshot = {
3853
+ ...snapshot,
3854
+ actionError: null,
3855
+ actionStatus: "completed",
3856
+ lastAction: result
3857
+ };
3858
+ emit();
3859
+ await refresh();
3860
+ return result;
3861
+ } catch (error) {
3862
+ snapshot = {
3863
+ ...snapshot,
3864
+ actionError: error instanceof Error ? error.message : String(error),
3865
+ actionStatus: "failed"
3866
+ };
3867
+ emit();
3868
+ throw error;
3869
+ }
3870
+ };
3871
+ const close = () => {
3872
+ closed = true;
3873
+ if (timer) {
3874
+ clearInterval(timer);
3875
+ timer = undefined;
3876
+ }
3877
+ listeners.clear();
3878
+ };
3879
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
3880
+ timer = setInterval(() => {
3881
+ refresh().catch(() => {});
3882
+ }, options.intervalMs);
3883
+ }
3884
+ return {
3885
+ close,
3886
+ getServerSnapshot: () => snapshot,
3887
+ getSnapshot: () => snapshot,
3888
+ requeueDeadLetters: () => runAction("requeue-dead-letters"),
3889
+ refresh,
3890
+ tick: () => runAction("tick"),
3891
+ subscribe: (listener) => {
3892
+ listeners.add(listener);
3893
+ return () => {
3894
+ listeners.delete(listener);
3895
+ };
3896
+ }
3897
+ };
3898
+ };
3899
+
3900
+ // src/angular/voice-delivery-runtime.service.ts
3901
+ var _dec = [
3902
+ Injectable18({ providedIn: "root" })
3903
+ ];
3904
+ var _init = __decoratorStart(undefined);
3905
+
3906
+ class VoiceDeliveryRuntimeService {
3907
+ connect(path = "/api/voice-delivery-runtime", options = {}) {
3908
+ const store = createVoiceDeliveryRuntimeStore(path, options);
3909
+ const actionErrorSignal = signal18(null);
3910
+ const actionStatusSignal = signal18("idle");
3911
+ const errorSignal = signal18(null);
3912
+ const isLoadingSignal = signal18(false);
3913
+ const reportSignal = signal18(undefined);
3914
+ const updatedAtSignal = signal18(undefined);
3915
+ const sync = () => {
3916
+ const snapshot = store.getSnapshot();
3917
+ actionErrorSignal.set(snapshot.actionError);
3918
+ actionStatusSignal.set(snapshot.actionStatus);
3919
+ errorSignal.set(snapshot.error);
3920
+ isLoadingSignal.set(snapshot.isLoading);
3921
+ reportSignal.set(snapshot.report);
3922
+ updatedAtSignal.set(snapshot.updatedAt);
3923
+ };
3924
+ const unsubscribe = store.subscribe(sync);
3925
+ sync();
3926
+ if (typeof window !== "undefined") {
3927
+ store.refresh().catch(() => {});
3928
+ }
3929
+ return {
3930
+ close: () => {
3931
+ unsubscribe();
3932
+ store.close();
3933
+ },
3934
+ error: computed18(() => errorSignal()),
3935
+ actionError: computed18(() => actionErrorSignal()),
3936
+ actionStatus: computed18(() => actionStatusSignal()),
3937
+ isLoading: computed18(() => isLoadingSignal()),
3938
+ requeueDeadLetters: store.requeueDeadLetters,
3939
+ refresh: store.refresh,
3940
+ report: computed18(() => reportSignal()),
3941
+ tick: store.tick,
3942
+ updatedAt: computed18(() => updatedAtSignal())
3943
+ };
3944
+ }
3945
+ }
3946
+ VoiceDeliveryRuntimeService = __decorateElement(_init, 0, "VoiceDeliveryRuntimeService", _dec, VoiceDeliveryRuntimeService);
3947
+ __runInitializers(_init, 1, VoiceDeliveryRuntimeService);
3948
+ __decoratorMetadata(_init, VoiceDeliveryRuntimeService);
3949
+ let _VoiceDeliveryRuntimeService = VoiceDeliveryRuntimeService;
3950
+ // src/angular/voice-campaign-dialer-proof.service.ts
3951
+ import { computed as computed19, Injectable as Injectable19, signal as signal19 } from "@angular/core";
3952
+
3953
+ // src/client/campaignDialerProof.ts
3954
+ var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3955
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3956
+ const response = await fetchImpl(path);
3957
+ if (!response.ok) {
3958
+ throw new Error(`Voice campaign dialer proof status failed: HTTP ${response.status}`);
3959
+ }
3960
+ return await response.json();
3961
+ };
3962
+ var runVoiceCampaignDialerProofAction = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3963
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3964
+ const response = await fetchImpl(path, { method: "POST" });
3965
+ if (!response.ok) {
3966
+ throw new Error(`Voice campaign dialer proof failed: HTTP ${response.status}`);
3967
+ }
3968
+ return await response.json();
3969
+ };
3970
+ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
3971
+ const listeners = new Set;
3972
+ let closed = false;
3973
+ let timer;
3974
+ let snapshot = {
3975
+ error: null,
3976
+ isLoading: false
3977
+ };
3978
+ const emit = () => {
3979
+ for (const listener of listeners) {
3980
+ listener();
3981
+ }
3982
+ };
3983
+ const refresh = async () => {
3984
+ if (closed) {
3985
+ return snapshot.status;
3986
+ }
3987
+ snapshot = { ...snapshot, error: null, isLoading: true };
3988
+ emit();
3989
+ try {
3990
+ const status = await fetchVoiceCampaignDialerProofStatus(path, options);
3991
+ snapshot = {
3992
+ ...snapshot,
3993
+ error: null,
3994
+ isLoading: false,
3995
+ status,
3996
+ updatedAt: Date.now()
3997
+ };
3998
+ emit();
3999
+ return status;
4000
+ } catch (error) {
4001
+ snapshot = {
4002
+ ...snapshot,
4003
+ error: error instanceof Error ? error.message : String(error),
4004
+ isLoading: false
4005
+ };
4006
+ emit();
4007
+ throw error;
4008
+ }
4009
+ };
4010
+ const runProof = async () => {
4011
+ const runPath = options.runPath ?? snapshot.status?.runPath ?? path;
4012
+ snapshot = { ...snapshot, error: null, isLoading: true };
4013
+ emit();
4014
+ try {
4015
+ const report = await runVoiceCampaignDialerProofAction(runPath, options);
4016
+ snapshot = {
4017
+ ...snapshot,
4018
+ error: null,
4019
+ isLoading: false,
4020
+ report,
4021
+ status: {
4022
+ generatedAt: Date.now(),
4023
+ mode: report.mode,
4024
+ ok: report.ok,
4025
+ providers: report.providers.map((provider) => provider.provider),
4026
+ runPath,
4027
+ safe: true
4028
+ },
4029
+ updatedAt: Date.now()
4030
+ };
4031
+ emit();
4032
+ return report;
4033
+ } catch (error) {
4034
+ snapshot = {
4035
+ ...snapshot,
4036
+ error: error instanceof Error ? error.message : String(error),
4037
+ isLoading: false
4038
+ };
4039
+ emit();
4040
+ throw error;
4041
+ }
4042
+ };
4043
+ const close = () => {
4044
+ closed = true;
4045
+ if (timer) {
4046
+ clearInterval(timer);
4047
+ timer = undefined;
4048
+ }
4049
+ listeners.clear();
4050
+ };
4051
+ if (options.intervalMs && options.intervalMs > 0) {
4052
+ timer = setInterval(() => {
4053
+ refresh().catch(() => {});
4054
+ }, options.intervalMs);
4055
+ }
4056
+ return {
4057
+ close,
4058
+ getServerSnapshot: () => snapshot,
4059
+ getSnapshot: () => snapshot,
4060
+ refresh,
4061
+ runProof,
4062
+ subscribe: (listener) => {
4063
+ listeners.add(listener);
4064
+ return () => {
4065
+ listeners.delete(listener);
4066
+ };
4067
+ }
4068
+ };
4069
+ };
4070
+
4071
+ // src/angular/voice-campaign-dialer-proof.service.ts
4072
+ var _dec = [
4073
+ Injectable19({ providedIn: "root" })
4074
+ ];
4075
+ var _init = __decoratorStart(undefined);
4076
+
4077
+ class VoiceCampaignDialerProofService {
4078
+ connect(path = "/api/voice/campaigns/dialer-proof", options = {}) {
4079
+ const store = createVoiceCampaignDialerProofStore(path, options);
4080
+ const errorSignal = signal19(null);
4081
+ const isLoadingSignal = signal19(false);
4082
+ const reportSignal = signal19(undefined);
4083
+ const statusSignal = signal19(undefined);
4084
+ const updatedAtSignal = signal19(undefined);
4085
+ const sync = () => {
4086
+ const snapshot = store.getSnapshot();
4087
+ errorSignal.set(snapshot.error);
4088
+ isLoadingSignal.set(snapshot.isLoading);
4089
+ reportSignal.set(snapshot.report);
4090
+ statusSignal.set(snapshot.status);
4091
+ updatedAtSignal.set(snapshot.updatedAt);
4092
+ };
4093
+ const unsubscribe = store.subscribe(sync);
4094
+ sync();
4095
+ store.refresh().catch(() => {});
4096
+ return {
4097
+ close: () => {
4098
+ unsubscribe();
4099
+ store.close();
4100
+ },
4101
+ error: computed19(() => errorSignal()),
4102
+ isLoading: computed19(() => isLoadingSignal()),
4103
+ refresh: store.refresh,
4104
+ report: computed19(() => reportSignal()),
4105
+ runProof: store.runProof,
4106
+ status: computed19(() => statusSignal()),
4107
+ updatedAt: computed19(() => updatedAtSignal())
4108
+ };
4109
+ }
4110
+ }
4111
+ VoiceCampaignDialerProofService = __decorateElement(_init, 0, "VoiceCampaignDialerProofService", _dec, VoiceCampaignDialerProofService);
4112
+ __runInitializers(_init, 1, VoiceCampaignDialerProofService);
4113
+ __decoratorMetadata(_init, VoiceCampaignDialerProofService);
4114
+ let _VoiceCampaignDialerProofService = VoiceCampaignDialerProofService;
4115
+ // src/angular/voice-stream.service.ts
4116
+ import { computed as computed20, Injectable as Injectable20, signal as signal20 } from "@angular/core";
4117
+ var _dec = [
4118
+ Injectable20({ providedIn: "root" })
4119
+ ];
4120
+ var _init = __decoratorStart(undefined);
4121
+
4122
+ class VoiceStreamService {
4123
+ connect(path, options = {}) {
4124
+ const stream = createVoiceStream(path, options);
4125
+ const assistantAudioSignal = signal20([]);
4126
+ const assistantTextsSignal = signal20([]);
4127
+ const callSignal = signal20(null);
4128
+ const errorSignal = signal20(null);
4129
+ const isConnectedSignal = signal20(false);
4130
+ const partialSignal = signal20("");
4131
+ const reconnectSignal = signal20(stream.reconnect);
4132
+ const sessionIdSignal = signal20(stream.sessionId);
4133
+ const sessionMetadataSignal = signal20(stream.sessionMetadata);
4134
+ const statusSignal = signal20(stream.status);
4135
+ const turnsSignal = signal20([]);
4136
+ const sync = () => {
4137
+ assistantAudioSignal.set([...stream.assistantAudio]);
4138
+ assistantTextsSignal.set([...stream.assistantTexts]);
4139
+ callSignal.set(stream.call);
4140
+ errorSignal.set(stream.error);
4141
+ isConnectedSignal.set(stream.isConnected);
4142
+ partialSignal.set(stream.partial);
4143
+ reconnectSignal.set(stream.reconnect);
4144
+ sessionIdSignal.set(stream.sessionId);
4145
+ sessionMetadataSignal.set(stream.sessionMetadata);
4146
+ statusSignal.set(stream.status);
4147
+ turnsSignal.set([...stream.turns]);
4148
+ };
4149
+ const unsubscribe = stream.subscribe(sync);
4150
+ sync();
4151
+ return {
4152
+ assistantAudio: computed20(() => assistantAudioSignal()),
4153
+ assistantTexts: computed20(() => assistantTextsSignal()),
4154
+ call: computed20(() => callSignal()),
4155
+ callControl: (message) => stream.callControl(message),
4156
+ close: () => {
4157
+ unsubscribe();
4158
+ stream.close();
4159
+ },
4160
+ endTurn: () => stream.endTurn(),
4161
+ error: computed20(() => errorSignal()),
4162
+ isConnected: computed20(() => isConnectedSignal()),
4163
+ partial: computed20(() => partialSignal()),
4164
+ reconnect: computed20(() => reconnectSignal()),
4165
+ sendAudio: (audio) => stream.sendAudio(audio),
4166
+ simulateDisconnect: () => stream.simulateDisconnect(),
4167
+ sessionId: computed20(() => sessionIdSignal()),
4168
+ sessionMetadata: computed20(() => sessionMetadataSignal()),
4169
+ status: computed20(() => statusSignal()),
4170
+ turns: computed20(() => turnsSignal())
4171
+ };
4172
+ }
4173
+ }
4174
+ VoiceStreamService = __decorateElement(_init, 0, "VoiceStreamService", _dec, VoiceStreamService);
4175
+ __runInitializers(_init, 1, VoiceStreamService);
4176
+ __decoratorMetadata(_init, VoiceStreamService);
4177
+ let _VoiceStreamService = VoiceStreamService;
4178
+ // src/angular/voice-controller.service.ts
4179
+ import { computed as computed21, Injectable as Injectable21, signal as signal21 } from "@angular/core";
4180
+ var _dec = [
4181
+ Injectable21({ providedIn: "root" })
4182
+ ];
4183
+ var _init = __decoratorStart(undefined);
4184
+
4185
+ class VoiceControllerService {
4186
+ connect(path, options = {}) {
4187
+ const controller = createVoiceController(path, options);
4188
+ const assistantAudioSignal = signal21([]);
4189
+ const assistantTextsSignal = signal21([]);
4190
+ const errorSignal = signal21(null);
4191
+ const isConnectedSignal = signal21(false);
4192
+ const isRecordingSignal = signal21(false);
4193
+ const partialSignal = signal21("");
4194
+ const reconnectSignal = signal21(controller.reconnect);
4195
+ const recordingErrorSignal = signal21(null);
4196
+ const sessionIdSignal = signal21(controller.sessionId);
4197
+ const statusSignal = signal21(controller.status);
4198
+ const turnsSignal = signal21([]);
4199
+ const sync = () => {
4200
+ assistantAudioSignal.set([...controller.assistantAudio]);
4201
+ assistantTextsSignal.set([...controller.assistantTexts]);
4202
+ errorSignal.set(controller.error);
4203
+ isConnectedSignal.set(controller.isConnected);
4204
+ isRecordingSignal.set(controller.isRecording);
4205
+ partialSignal.set(controller.partial);
4206
+ reconnectSignal.set(controller.reconnect);
4207
+ recordingErrorSignal.set(controller.recordingError);
4208
+ sessionIdSignal.set(controller.sessionId);
4209
+ statusSignal.set(controller.status);
4210
+ turnsSignal.set([...controller.turns]);
4211
+ };
4212
+ const unsubscribe = controller.subscribe(sync);
4213
+ sync();
4214
+ return {
4215
+ assistantAudio: computed21(() => assistantAudioSignal()),
4216
+ assistantTexts: computed21(() => assistantTextsSignal()),
4217
+ bindHTMX: controller.bindHTMX,
4218
+ close: () => {
4219
+ unsubscribe();
4220
+ controller.close();
4221
+ },
4222
+ endTurn: () => controller.endTurn(),
4223
+ error: computed21(() => errorSignal()),
4224
+ isConnected: computed21(() => isConnectedSignal()),
4225
+ isRecording: computed21(() => isRecordingSignal()),
4226
+ partial: computed21(() => partialSignal()),
4227
+ reconnect: computed21(() => reconnectSignal()),
4228
+ recordingError: computed21(() => recordingErrorSignal()),
4229
+ sendAudio: (audio) => controller.sendAudio(audio),
4230
+ simulateDisconnect: () => controller.simulateDisconnect(),
4231
+ sessionId: computed21(() => sessionIdSignal()),
4232
+ startRecording: () => controller.startRecording(),
4233
+ status: computed21(() => statusSignal()),
4234
+ stopRecording: () => controller.stopRecording(),
4235
+ toggleRecording: () => controller.toggleRecording(),
4236
+ turns: computed21(() => turnsSignal())
4237
+ };
4238
+ }
4239
+ }
4240
+ VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _dec, VoiceControllerService);
4241
+ __runInitializers(_init, 1, VoiceControllerService);
4242
+ __decoratorMetadata(_init, VoiceControllerService);
4243
+ let _VoiceControllerService = VoiceControllerService;
4244
+ // src/angular/voice-provider-capabilities.service.ts
4245
+ import { computed as computed22, Injectable as Injectable22, signal as signal22 } from "@angular/core";
4246
+
4247
+ // src/client/providerCapabilities.ts
4248
+ var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
4249
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4250
+ const response = await fetchImpl(path);
4251
+ if (!response.ok) {
4252
+ throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
4253
+ }
4254
+ return await response.json();
4255
+ };
4256
+ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
4257
+ const listeners = new Set;
4258
+ let closed = false;
4259
+ let timer;
4260
+ let snapshot = {
4261
+ error: null,
4262
+ isLoading: false
4263
+ };
4264
+ const emit = () => {
4265
+ for (const listener of listeners) {
4266
+ listener();
4267
+ }
4268
+ };
4269
+ const refresh = async () => {
4270
+ if (closed) {
4271
+ return snapshot.report;
4272
+ }
4273
+ snapshot = {
4274
+ ...snapshot,
4275
+ error: null,
4276
+ isLoading: true
4277
+ };
4278
+ emit();
4279
+ try {
4280
+ const report = await fetchVoiceProviderCapabilities(path, options);
4281
+ snapshot = {
4282
+ error: null,
4283
+ isLoading: false,
4284
+ report,
4285
+ updatedAt: Date.now()
4286
+ };
4287
+ emit();
4288
+ return report;
4289
+ } catch (error) {
4290
+ snapshot = {
4291
+ ...snapshot,
4292
+ error: error instanceof Error ? error.message : String(error),
4293
+ isLoading: false
4294
+ };
4295
+ emit();
4296
+ throw error;
4297
+ }
4298
+ };
4299
+ const close = () => {
4300
+ closed = true;
4301
+ if (timer) {
4302
+ clearInterval(timer);
4303
+ timer = undefined;
4304
+ }
4305
+ listeners.clear();
4306
+ };
4307
+ if (options.intervalMs && options.intervalMs > 0) {
4308
+ timer = setInterval(() => {
4309
+ refresh().catch(() => {});
4310
+ }, options.intervalMs);
4311
+ }
4312
+ return {
4313
+ close,
4314
+ getServerSnapshot: () => snapshot,
4315
+ getSnapshot: () => snapshot,
4316
+ refresh,
4317
+ subscribe: (listener) => {
4318
+ listeners.add(listener);
4319
+ return () => {
4320
+ listeners.delete(listener);
4321
+ };
4322
+ }
4323
+ };
4324
+ };
4325
+
4326
+ // src/angular/voice-provider-capabilities.service.ts
4327
+ var _dec = [
4328
+ Injectable22({ providedIn: "root" })
4329
+ ];
4330
+ var _init = __decoratorStart(undefined);
4331
+
4332
+ class VoiceProviderCapabilitiesService {
4333
+ connect(path = "/api/provider-capabilities", options = {}) {
4334
+ const store = createVoiceProviderCapabilitiesStore(path, options);
4335
+ const errorSignal = signal22(null);
4336
+ const isLoadingSignal = signal22(false);
4337
+ const reportSignal = signal22(undefined);
4338
+ const updatedAtSignal = signal22(undefined);
4339
+ const sync = () => {
4340
+ const snapshot = store.getSnapshot();
4341
+ errorSignal.set(snapshot.error);
4342
+ isLoadingSignal.set(snapshot.isLoading);
4343
+ reportSignal.set(snapshot.report);
4344
+ updatedAtSignal.set(snapshot.updatedAt);
4345
+ };
4346
+ const unsubscribe = store.subscribe(sync);
4347
+ sync();
4348
+ store.refresh().catch(() => {});
4349
+ return {
4350
+ close: () => {
4351
+ unsubscribe();
4352
+ store.close();
4353
+ },
4354
+ error: computed22(() => errorSignal()),
4355
+ isLoading: computed22(() => isLoadingSignal()),
4356
+ refresh: store.refresh,
4357
+ report: computed22(() => reportSignal()),
4358
+ updatedAt: computed22(() => updatedAtSignal())
4359
+ };
4360
+ }
4361
+ }
4362
+ VoiceProviderCapabilitiesService = __decorateElement(_init, 0, "VoiceProviderCapabilitiesService", _dec, VoiceProviderCapabilitiesService);
4363
+ __runInitializers(_init, 1, VoiceProviderCapabilitiesService);
4364
+ __decoratorMetadata(_init, VoiceProviderCapabilitiesService);
4365
+ let _VoiceProviderCapabilitiesService = VoiceProviderCapabilitiesService;
4366
+ // src/angular/voice-provider-contracts.service.ts
4367
+ import { computed as computed23, Injectable as Injectable23, signal as signal23 } from "@angular/core";
4368
+
4369
+ // src/client/providerContracts.ts
4370
+ var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
4371
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4372
+ const response = await fetchImpl(path);
4373
+ if (!response.ok) {
4374
+ throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
4375
+ }
4376
+ return await response.json();
4377
+ };
4378
+ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
4379
+ const listeners = new Set;
4380
+ let closed = false;
4381
+ let timer;
4382
+ let snapshot = {
4383
+ error: null,
4384
+ isLoading: false
4385
+ };
4386
+ const emit = () => {
4387
+ for (const listener of listeners) {
4388
+ listener();
4389
+ }
4390
+ };
4391
+ const refresh = async () => {
4392
+ if (closed) {
4393
+ return snapshot.report;
4394
+ }
4395
+ snapshot = { ...snapshot, error: null, isLoading: true };
4396
+ emit();
4397
+ try {
4398
+ const report = await fetchVoiceProviderContracts(path, options);
4399
+ snapshot = {
4400
+ error: null,
4401
+ isLoading: false,
4402
+ report,
4403
+ updatedAt: Date.now()
4404
+ };
4405
+ emit();
4406
+ return report;
4407
+ } catch (error) {
4408
+ snapshot = {
4409
+ ...snapshot,
4410
+ error: error instanceof Error ? error.message : String(error),
4411
+ isLoading: false
4412
+ };
4413
+ emit();
4414
+ throw error;
4415
+ }
4416
+ };
4417
+ const close = () => {
4418
+ closed = true;
4419
+ if (timer) {
4420
+ clearInterval(timer);
4421
+ timer = undefined;
4422
+ }
4423
+ listeners.clear();
4424
+ };
4425
+ if (options.intervalMs && options.intervalMs > 0) {
4426
+ timer = setInterval(() => {
4427
+ refresh().catch(() => {});
4428
+ }, options.intervalMs);
4429
+ }
4430
+ return {
4431
+ close,
4432
+ getServerSnapshot: () => snapshot,
4433
+ getSnapshot: () => snapshot,
4434
+ refresh,
4435
+ subscribe: (listener) => {
4436
+ listeners.add(listener);
4437
+ return () => {
4438
+ listeners.delete(listener);
4439
+ };
4440
+ }
4441
+ };
4442
+ };
4443
+
4444
+ // src/angular/voice-provider-contracts.service.ts
4445
+ var _dec = [
4446
+ Injectable23({ providedIn: "root" })
4447
+ ];
4448
+ var _init = __decoratorStart(undefined);
4449
+
4450
+ class VoiceProviderContractsService {
4451
+ connect(path = "/api/provider-contracts", options = {}) {
4452
+ const store = createVoiceProviderContractsStore(path, options);
4453
+ const errorSignal = signal23(null);
4454
+ const isLoadingSignal = signal23(false);
4455
+ const reportSignal = signal23(undefined);
4456
+ const updatedAtSignal = signal23(undefined);
4457
+ const sync = () => {
4458
+ const snapshot = store.getSnapshot();
4459
+ errorSignal.set(snapshot.error);
4460
+ isLoadingSignal.set(snapshot.isLoading);
4461
+ reportSignal.set(snapshot.report);
4462
+ updatedAtSignal.set(snapshot.updatedAt);
4463
+ };
4464
+ const unsubscribe = store.subscribe(sync);
4465
+ sync();
4466
+ store.refresh().catch(() => {});
4467
+ return {
4468
+ close: () => {
4469
+ unsubscribe();
4470
+ store.close();
4471
+ },
4472
+ error: computed23(() => errorSignal()),
4473
+ isLoading: computed23(() => isLoadingSignal()),
4474
+ refresh: store.refresh,
4475
+ report: computed23(() => reportSignal()),
4476
+ updatedAt: computed23(() => updatedAtSignal())
4477
+ };
4478
+ }
4479
+ }
4480
+ VoiceProviderContractsService = __decorateElement(_init, 0, "VoiceProviderContractsService", _dec, VoiceProviderContractsService);
4481
+ __runInitializers(_init, 1, VoiceProviderContractsService);
4482
+ __decoratorMetadata(_init, VoiceProviderContractsService);
4483
+ let _VoiceProviderContractsService = VoiceProviderContractsService;
4484
+ // src/angular/voice-provider-status.service.ts
4485
+ import { computed as computed24, Injectable as Injectable24, signal as signal24 } from "@angular/core";
4486
+
4487
+ // src/client/providerStatus.ts
4488
+ var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
4489
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4490
+ const response = await fetchImpl(path);
4491
+ if (!response.ok) {
4492
+ throw new Error(`Voice provider status failed: HTTP ${response.status}`);
4493
+ }
4494
+ return await response.json();
4495
+ };
4496
+ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
4497
+ const listeners = new Set;
4498
+ let closed = false;
4499
+ let timer;
4500
+ let snapshot = {
4501
+ error: null,
1741
4502
  isLoading: false,
1742
4503
  providers: []
1743
4504
  };
@@ -1748,7 +4509,640 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1748
4509
  };
1749
4510
  const refresh = async () => {
1750
4511
  if (closed) {
1751
- return snapshot.providers;
4512
+ return snapshot.providers;
4513
+ }
4514
+ snapshot = {
4515
+ ...snapshot,
4516
+ error: null,
4517
+ isLoading: true
4518
+ };
4519
+ emit();
4520
+ try {
4521
+ const providers = await fetchVoiceProviderStatus(path, options);
4522
+ snapshot = {
4523
+ error: null,
4524
+ isLoading: false,
4525
+ providers,
4526
+ updatedAt: Date.now()
4527
+ };
4528
+ emit();
4529
+ return providers;
4530
+ } catch (error) {
4531
+ snapshot = {
4532
+ ...snapshot,
4533
+ error: error instanceof Error ? error.message : String(error),
4534
+ isLoading: false
4535
+ };
4536
+ emit();
4537
+ throw error;
4538
+ }
4539
+ };
4540
+ const close = () => {
4541
+ closed = true;
4542
+ if (timer) {
4543
+ clearInterval(timer);
4544
+ timer = undefined;
4545
+ }
4546
+ listeners.clear();
4547
+ };
4548
+ if (options.intervalMs && options.intervalMs > 0) {
4549
+ timer = setInterval(() => {
4550
+ refresh().catch(() => {});
4551
+ }, options.intervalMs);
4552
+ }
4553
+ return {
4554
+ close,
4555
+ getServerSnapshot: () => snapshot,
4556
+ getSnapshot: () => snapshot,
4557
+ refresh,
4558
+ subscribe: (listener) => {
4559
+ listeners.add(listener);
4560
+ return () => {
4561
+ listeners.delete(listener);
4562
+ };
4563
+ }
4564
+ };
4565
+ };
4566
+
4567
+ // src/angular/voice-provider-status.service.ts
4568
+ var _dec = [
4569
+ Injectable24({ providedIn: "root" })
4570
+ ];
4571
+ var _init = __decoratorStart(undefined);
4572
+
4573
+ class VoiceProviderStatusService {
4574
+ connect(path = "/api/provider-status", options = {}) {
4575
+ const store = createVoiceProviderStatusStore(path, options);
4576
+ const errorSignal = signal24(null);
4577
+ const isLoadingSignal = signal24(false);
4578
+ const providersSignal = signal24([]);
4579
+ const updatedAtSignal = signal24(undefined);
4580
+ const sync = () => {
4581
+ const snapshot = store.getSnapshot();
4582
+ errorSignal.set(snapshot.error);
4583
+ isLoadingSignal.set(snapshot.isLoading);
4584
+ providersSignal.set([...snapshot.providers]);
4585
+ updatedAtSignal.set(snapshot.updatedAt);
4586
+ };
4587
+ const unsubscribe = store.subscribe(sync);
4588
+ sync();
4589
+ store.refresh().catch(() => {});
4590
+ return {
4591
+ close: () => {
4592
+ unsubscribe();
4593
+ store.close();
4594
+ },
4595
+ error: computed24(() => errorSignal()),
4596
+ isLoading: computed24(() => isLoadingSignal()),
4597
+ providers: computed24(() => providersSignal()),
4598
+ refresh: store.refresh,
4599
+ updatedAt: computed24(() => updatedAtSignal())
4600
+ };
4601
+ }
4602
+ }
4603
+ VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
4604
+ __runInitializers(_init, 1, VoiceProviderStatusService);
4605
+ __decoratorMetadata(_init, VoiceProviderStatusService);
4606
+ let _VoiceProviderStatusService = VoiceProviderStatusService;
4607
+ // src/angular/voice-routing-status.service.ts
4608
+ import { Injectable as Injectable25, signal as signal25 } from "@angular/core";
4609
+
4610
+ // src/client/routingStatus.ts
4611
+ var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
4612
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4613
+ const response = await fetchImpl(path);
4614
+ if (!response.ok) {
4615
+ throw new Error(`Voice routing status failed: HTTP ${response.status}`);
4616
+ }
4617
+ return await response.json();
4618
+ };
4619
+ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {}) => {
4620
+ const listeners = new Set;
4621
+ let closed = false;
4622
+ let timer;
4623
+ let snapshot = {
4624
+ decision: null,
4625
+ error: null,
4626
+ isLoading: false
4627
+ };
4628
+ const emit = () => {
4629
+ for (const listener of listeners) {
4630
+ listener();
4631
+ }
4632
+ };
4633
+ const refresh = async () => {
4634
+ if (closed) {
4635
+ return snapshot.decision;
4636
+ }
4637
+ snapshot = {
4638
+ ...snapshot,
4639
+ error: null,
4640
+ isLoading: true
4641
+ };
4642
+ emit();
4643
+ try {
4644
+ const decision = await fetchVoiceRoutingStatus(path, options);
4645
+ snapshot = {
4646
+ decision,
4647
+ error: null,
4648
+ isLoading: false,
4649
+ updatedAt: Date.now()
4650
+ };
4651
+ emit();
4652
+ return decision;
4653
+ } catch (error) {
4654
+ snapshot = {
4655
+ ...snapshot,
4656
+ error: error instanceof Error ? error.message : String(error),
4657
+ isLoading: false
4658
+ };
4659
+ emit();
4660
+ throw error;
4661
+ }
4662
+ };
4663
+ const close = () => {
4664
+ closed = true;
4665
+ if (timer) {
4666
+ clearInterval(timer);
4667
+ timer = undefined;
4668
+ }
4669
+ listeners.clear();
4670
+ };
4671
+ if (options.intervalMs && options.intervalMs > 0) {
4672
+ timer = setInterval(() => {
4673
+ refresh().catch(() => {});
4674
+ }, options.intervalMs);
4675
+ }
4676
+ return {
4677
+ close,
4678
+ getServerSnapshot: () => snapshot,
4679
+ getSnapshot: () => snapshot,
4680
+ refresh,
4681
+ subscribe: (listener) => {
4682
+ listeners.add(listener);
4683
+ return () => {
4684
+ listeners.delete(listener);
4685
+ };
4686
+ }
4687
+ };
4688
+ };
4689
+
4690
+ // src/angular/voice-routing-status.service.ts
4691
+ var _dec = [
4692
+ Injectable25({ providedIn: "root" })
4693
+ ];
4694
+ var _init = __decoratorStart(undefined);
4695
+
4696
+ class VoiceRoutingStatusService {
4697
+ connect(path = "/api/routing/latest", options = {}) {
4698
+ const store = createVoiceRoutingStatusStore(path, options);
4699
+ const decisionSignal = signal25(null);
4700
+ const errorSignal = signal25(null);
4701
+ const isLoadingSignal = signal25(false);
4702
+ const updatedAtSignal = signal25(undefined);
4703
+ const sync = () => {
4704
+ const snapshot = store.getSnapshot();
4705
+ decisionSignal.set(snapshot.decision);
4706
+ errorSignal.set(snapshot.error);
4707
+ isLoadingSignal.set(snapshot.isLoading);
4708
+ updatedAtSignal.set(snapshot.updatedAt);
4709
+ };
4710
+ const unsubscribe = store.subscribe(sync);
4711
+ sync();
4712
+ store.refresh().catch(() => {});
4713
+ return {
4714
+ close: () => {
4715
+ unsubscribe();
4716
+ store.close();
4717
+ },
4718
+ decision: decisionSignal.asReadonly(),
4719
+ error: errorSignal.asReadonly(),
4720
+ isLoading: isLoadingSignal.asReadonly(),
4721
+ refresh: store.refresh,
4722
+ updatedAt: updatedAtSignal.asReadonly()
4723
+ };
4724
+ }
4725
+ }
4726
+ VoiceRoutingStatusService = __decorateElement(_init, 0, "VoiceRoutingStatusService", _dec, VoiceRoutingStatusService);
4727
+ __runInitializers(_init, 1, VoiceRoutingStatusService);
4728
+ __decoratorMetadata(_init, VoiceRoutingStatusService);
4729
+ let _VoiceRoutingStatusService = VoiceRoutingStatusService;
4730
+ // src/angular/voice-trace-timeline.service.ts
4731
+ import { computed as computed25, Injectable as Injectable26, signal as signal26 } from "@angular/core";
4732
+
4733
+ // src/client/traceTimeline.ts
4734
+ var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
4735
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4736
+ const response = await fetchImpl(path);
4737
+ if (!response.ok) {
4738
+ throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
4739
+ }
4740
+ return await response.json();
4741
+ };
4742
+ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
4743
+ const listeners = new Set;
4744
+ let closed = false;
4745
+ let timer;
4746
+ let snapshot = {
4747
+ error: null,
4748
+ isLoading: false,
4749
+ report: null
4750
+ };
4751
+ const emit = () => {
4752
+ for (const listener of listeners) {
4753
+ listener();
4754
+ }
4755
+ };
4756
+ const refresh = async () => {
4757
+ if (closed) {
4758
+ return snapshot.report;
4759
+ }
4760
+ snapshot = {
4761
+ ...snapshot,
4762
+ error: null,
4763
+ isLoading: true
4764
+ };
4765
+ emit();
4766
+ try {
4767
+ const report = await fetchVoiceTraceTimeline(path, options);
4768
+ snapshot = {
4769
+ error: null,
4770
+ isLoading: false,
4771
+ report,
4772
+ updatedAt: Date.now()
4773
+ };
4774
+ emit();
4775
+ return report;
4776
+ } catch (error) {
4777
+ snapshot = {
4778
+ ...snapshot,
4779
+ error: error instanceof Error ? error.message : String(error),
4780
+ isLoading: false
4781
+ };
4782
+ emit();
4783
+ throw error;
4784
+ }
4785
+ };
4786
+ const close = () => {
4787
+ closed = true;
4788
+ if (timer) {
4789
+ clearInterval(timer);
4790
+ timer = undefined;
4791
+ }
4792
+ listeners.clear();
4793
+ };
4794
+ if (options.intervalMs && options.intervalMs > 0) {
4795
+ timer = setInterval(() => {
4796
+ refresh().catch(() => {});
4797
+ }, options.intervalMs);
4798
+ }
4799
+ return {
4800
+ close,
4801
+ getServerSnapshot: () => snapshot,
4802
+ getSnapshot: () => snapshot,
4803
+ refresh,
4804
+ subscribe: (listener) => {
4805
+ listeners.add(listener);
4806
+ return () => {
4807
+ listeners.delete(listener);
4808
+ };
4809
+ }
4810
+ };
4811
+ };
4812
+
4813
+ // src/angular/voice-trace-timeline.service.ts
4814
+ var _dec = [
4815
+ Injectable26({ providedIn: "root" })
4816
+ ];
4817
+ var _init = __decoratorStart(undefined);
4818
+
4819
+ class VoiceTraceTimelineService {
4820
+ connect(path = "/api/voice-traces", options = {}) {
4821
+ const store = createVoiceTraceTimelineStore(path, options);
4822
+ const errorSignal = signal26(null);
4823
+ const isLoadingSignal = signal26(false);
4824
+ const reportSignal = signal26(null);
4825
+ const updatedAtSignal = signal26(undefined);
4826
+ const sync = () => {
4827
+ const snapshot = store.getSnapshot();
4828
+ errorSignal.set(snapshot.error);
4829
+ isLoadingSignal.set(snapshot.isLoading);
4830
+ reportSignal.set(snapshot.report);
4831
+ updatedAtSignal.set(snapshot.updatedAt);
4832
+ };
4833
+ const unsubscribe = store.subscribe(sync);
4834
+ sync();
4835
+ store.refresh().catch(() => {});
4836
+ return {
4837
+ close: () => {
4838
+ unsubscribe();
4839
+ store.close();
4840
+ },
4841
+ error: computed25(() => errorSignal()),
4842
+ isLoading: computed25(() => isLoadingSignal()),
4843
+ refresh: store.refresh,
4844
+ report: computed25(() => reportSignal()),
4845
+ updatedAt: computed25(() => updatedAtSignal())
4846
+ };
4847
+ }
4848
+ }
4849
+ VoiceTraceTimelineService = __decorateElement(_init, 0, "VoiceTraceTimelineService", _dec, VoiceTraceTimelineService);
4850
+ __runInitializers(_init, 1, VoiceTraceTimelineService);
4851
+ __decoratorMetadata(_init, VoiceTraceTimelineService);
4852
+ let _VoiceTraceTimelineService = VoiceTraceTimelineService;
4853
+ // src/angular/voice-agent-squad-status.service.ts
4854
+ import { computed as computed26, Injectable as Injectable27, signal as signal27 } from "@angular/core";
4855
+
4856
+ // src/client/agentSquadStatus.ts
4857
+ var getString = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
4858
+ var getPayloadString = (event, key) => getString(event.payload?.[key]);
4859
+ var eventStatus = (event) => {
4860
+ const status = getPayloadString(event, "status");
4861
+ if (status === "blocked")
4862
+ return "blocked";
4863
+ if (status === "unknown-target")
4864
+ return "unknown-target";
4865
+ if (status === "allowed")
4866
+ return "handoff";
4867
+ return event.type === "agent.result" ? "active" : "handoff";
4868
+ };
4869
+ var deriveSessionSpecialist = (session) => {
4870
+ const events = [...session.events].sort((left, right) => left.at - right.at);
4871
+ const agentEvents = events.filter((event) => event.type === "agent.handoff" || event.type === "agent.context" || event.type === "agent.result" || event.type === "agent.model");
4872
+ const latest = agentEvents.at(-1);
4873
+ if (!latest) {
4874
+ return {
4875
+ lastEventAt: session.lastEventAt,
4876
+ sessionId: session.sessionId,
4877
+ status: "idle"
4878
+ };
4879
+ }
4880
+ const handoffEvents = events.filter((event) => event.type === "agent.handoff");
4881
+ const lastHandoff = handoffEvents.at(-1);
4882
+ const latestAgentId = getPayloadString(latest, "agentId");
4883
+ const handoffStatus = lastHandoff ? eventStatus(lastHandoff) : undefined;
4884
+ const currentTarget = handoffStatus === "blocked" || handoffStatus === "unknown-target" ? getPayloadString(lastHandoff, "fromAgentId") ?? latestAgentId : getPayloadString(lastHandoff ?? latest, "targetAgentId") ?? latestAgentId;
4885
+ return {
4886
+ fromAgentId: getPayloadString(lastHandoff ?? latest, "fromAgentId"),
4887
+ lastEventAt: latest.at,
4888
+ reason: getPayloadString(lastHandoff ?? latest, "reason") ?? getPayloadString(latest, "handoffTarget"),
4889
+ sessionId: session.sessionId,
4890
+ status: lastHandoff ? eventStatus(lastHandoff) : "active",
4891
+ summary: getPayloadString(lastHandoff ?? latest, "summary"),
4892
+ targetAgentId: currentTarget,
4893
+ turnId: latest.turnId
4894
+ };
4895
+ };
4896
+ var buildVoiceAgentSquadStatusReport = (timeline, options = {}) => {
4897
+ const sessions = (timeline?.sessions ?? []).filter((session) => !options.sessionId || session.sessionId === options.sessionId).map(deriveSessionSpecialist).sort((left, right) => (right.lastEventAt ?? 0) - (left.lastEventAt ?? 0));
4898
+ const active = sessions.filter((session) => session.status !== "idle");
4899
+ return {
4900
+ active,
4901
+ checkedAt: timeline?.checkedAt,
4902
+ current: active[0] ?? sessions[0],
4903
+ sessionCount: sessions.length,
4904
+ sessions
4905
+ };
4906
+ };
4907
+ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}) => {
4908
+ const timelineStore = createVoiceTraceTimelineStore(path, options);
4909
+ const getReport = () => buildVoiceAgentSquadStatusReport(timelineStore.getSnapshot().report, {
4910
+ sessionId: options.sessionId
4911
+ });
4912
+ const getSnapshot = () => {
4913
+ const snapshot = timelineStore.getSnapshot();
4914
+ return {
4915
+ error: snapshot.error,
4916
+ isLoading: snapshot.isLoading,
4917
+ report: getReport(),
4918
+ updatedAt: snapshot.updatedAt
4919
+ };
4920
+ };
4921
+ return {
4922
+ close: timelineStore.close,
4923
+ getServerSnapshot: getSnapshot,
4924
+ getSnapshot,
4925
+ refresh: timelineStore.refresh,
4926
+ subscribe: timelineStore.subscribe
4927
+ };
4928
+ };
4929
+
4930
+ // src/angular/voice-agent-squad-status.service.ts
4931
+ var _dec = [
4932
+ Injectable27({ providedIn: "root" })
4933
+ ];
4934
+ var _init = __decoratorStart(undefined);
4935
+
4936
+ class VoiceAgentSquadStatusService {
4937
+ connect(path = "/api/voice-traces", options = {}) {
4938
+ const store = createVoiceAgentSquadStatusStore(path, options);
4939
+ const errorSignal = signal27(null);
4940
+ const isLoadingSignal = signal27(false);
4941
+ const reportSignal = signal27(undefined);
4942
+ const updatedAtSignal = signal27(undefined);
4943
+ const sync = () => {
4944
+ const snapshot = store.getSnapshot();
4945
+ errorSignal.set(snapshot.error);
4946
+ isLoadingSignal.set(snapshot.isLoading);
4947
+ reportSignal.set(snapshot.report);
4948
+ updatedAtSignal.set(snapshot.updatedAt);
4949
+ };
4950
+ const unsubscribe = store.subscribe(sync);
4951
+ sync();
4952
+ store.refresh().catch(() => {});
4953
+ return {
4954
+ close: () => {
4955
+ unsubscribe();
4956
+ store.close();
4957
+ },
4958
+ current: computed26(() => reportSignal()?.current),
4959
+ error: computed26(() => errorSignal()),
4960
+ isLoading: computed26(() => isLoadingSignal()),
4961
+ refresh: store.refresh,
4962
+ report: computed26(() => reportSignal()),
4963
+ updatedAt: computed26(() => updatedAtSignal())
4964
+ };
4965
+ }
4966
+ }
4967
+ VoiceAgentSquadStatusService = __decorateElement(_init, 0, "VoiceAgentSquadStatusService", _dec, VoiceAgentSquadStatusService);
4968
+ __runInitializers(_init, 1, VoiceAgentSquadStatusService);
4969
+ __decoratorMetadata(_init, VoiceAgentSquadStatusService);
4970
+ let _VoiceAgentSquadStatusService = VoiceAgentSquadStatusService;
4971
+ // src/angular/voice-turn-latency.service.ts
4972
+ import { computed as computed27, Injectable as Injectable28, signal as signal28 } from "@angular/core";
4973
+
4974
+ // src/client/turnLatency.ts
4975
+ var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
4976
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4977
+ const response = await fetchImpl(path);
4978
+ if (!response.ok) {
4979
+ throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
4980
+ }
4981
+ return await response.json();
4982
+ };
4983
+ var runVoiceTurnLatencyProof = async (path, options = {}) => {
4984
+ const fetchImpl = options.fetch ?? globalThis.fetch;
4985
+ const response = await fetchImpl(path, { method: "POST" });
4986
+ if (!response.ok) {
4987
+ throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
4988
+ }
4989
+ return response.json();
4990
+ };
4991
+ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
4992
+ const listeners = new Set;
4993
+ let closed = false;
4994
+ let timer;
4995
+ let snapshot = {
4996
+ error: null,
4997
+ isLoading: false
4998
+ };
4999
+ const emit = () => {
5000
+ for (const listener of listeners) {
5001
+ listener();
5002
+ }
5003
+ };
5004
+ const refresh = async () => {
5005
+ if (closed) {
5006
+ return snapshot.report;
5007
+ }
5008
+ snapshot = { ...snapshot, error: null, isLoading: true };
5009
+ emit();
5010
+ try {
5011
+ const report = await fetchVoiceTurnLatency(path, options);
5012
+ snapshot = {
5013
+ error: null,
5014
+ isLoading: false,
5015
+ report,
5016
+ updatedAt: Date.now()
5017
+ };
5018
+ emit();
5019
+ return report;
5020
+ } catch (error) {
5021
+ snapshot = {
5022
+ ...snapshot,
5023
+ error: error instanceof Error ? error.message : String(error),
5024
+ isLoading: false
5025
+ };
5026
+ emit();
5027
+ throw error;
5028
+ }
5029
+ };
5030
+ const runProof = async () => {
5031
+ if (!options.proofPath) {
5032
+ throw new Error("Voice turn latency proof path is not configured.");
5033
+ }
5034
+ snapshot = { ...snapshot, error: null, isLoading: true };
5035
+ emit();
5036
+ try {
5037
+ await runVoiceTurnLatencyProof(options.proofPath, options);
5038
+ return await refresh();
5039
+ } catch (error) {
5040
+ snapshot = {
5041
+ ...snapshot,
5042
+ error: error instanceof Error ? error.message : String(error),
5043
+ isLoading: false
5044
+ };
5045
+ emit();
5046
+ throw error;
5047
+ }
5048
+ };
5049
+ const close = () => {
5050
+ closed = true;
5051
+ if (timer) {
5052
+ clearInterval(timer);
5053
+ timer = undefined;
5054
+ }
5055
+ listeners.clear();
5056
+ };
5057
+ if (options.intervalMs && options.intervalMs > 0) {
5058
+ timer = setInterval(() => {
5059
+ refresh().catch(() => {});
5060
+ }, options.intervalMs);
5061
+ }
5062
+ return {
5063
+ close,
5064
+ getServerSnapshot: () => snapshot,
5065
+ getSnapshot: () => snapshot,
5066
+ refresh,
5067
+ runProof,
5068
+ subscribe: (listener) => {
5069
+ listeners.add(listener);
5070
+ return () => {
5071
+ listeners.delete(listener);
5072
+ };
5073
+ }
5074
+ };
5075
+ };
5076
+
5077
+ // src/angular/voice-turn-latency.service.ts
5078
+ var _dec = [
5079
+ Injectable28({ providedIn: "root" })
5080
+ ];
5081
+ var _init = __decoratorStart(undefined);
5082
+
5083
+ class VoiceTurnLatencyService {
5084
+ connect(path = "/api/turn-latency", options = {}) {
5085
+ const store = createVoiceTurnLatencyStore(path, options);
5086
+ const errorSignal = signal28(null);
5087
+ const isLoadingSignal = signal28(false);
5088
+ const reportSignal = signal28(undefined);
5089
+ const updatedAtSignal = signal28(undefined);
5090
+ const sync = () => {
5091
+ const snapshot = store.getSnapshot();
5092
+ errorSignal.set(snapshot.error);
5093
+ isLoadingSignal.set(snapshot.isLoading);
5094
+ reportSignal.set(snapshot.report);
5095
+ updatedAtSignal.set(snapshot.updatedAt);
5096
+ };
5097
+ const unsubscribe = store.subscribe(sync);
5098
+ sync();
5099
+ store.refresh().catch(() => {});
5100
+ return {
5101
+ close: () => {
5102
+ unsubscribe();
5103
+ store.close();
5104
+ },
5105
+ error: computed27(() => errorSignal()),
5106
+ isLoading: computed27(() => isLoadingSignal()),
5107
+ refresh: store.refresh,
5108
+ report: computed27(() => reportSignal()),
5109
+ runProof: store.runProof,
5110
+ updatedAt: computed27(() => updatedAtSignal())
5111
+ };
5112
+ }
5113
+ }
5114
+ VoiceTurnLatencyService = __decorateElement(_init, 0, "VoiceTurnLatencyService", _dec, VoiceTurnLatencyService);
5115
+ __runInitializers(_init, 1, VoiceTurnLatencyService);
5116
+ __decoratorMetadata(_init, VoiceTurnLatencyService);
5117
+ let _VoiceTurnLatencyService = VoiceTurnLatencyService;
5118
+ // src/angular/voice-turn-quality.service.ts
5119
+ import { computed as computed28, Injectable as Injectable29, signal as signal29 } from "@angular/core";
5120
+
5121
+ // src/client/turnQuality.ts
5122
+ var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
5123
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5124
+ const response = await fetchImpl(path);
5125
+ if (!response.ok) {
5126
+ throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
5127
+ }
5128
+ return await response.json();
5129
+ };
5130
+ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
5131
+ const listeners = new Set;
5132
+ let closed = false;
5133
+ let timer;
5134
+ let snapshot = {
5135
+ error: null,
5136
+ isLoading: false
5137
+ };
5138
+ const emit = () => {
5139
+ for (const listener of listeners) {
5140
+ listener();
5141
+ }
5142
+ };
5143
+ const refresh = async () => {
5144
+ if (closed) {
5145
+ return snapshot.report;
1752
5146
  }
1753
5147
  snapshot = {
1754
5148
  ...snapshot,
@@ -1757,15 +5151,15 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1757
5151
  };
1758
5152
  emit();
1759
5153
  try {
1760
- const providers = await fetchVoiceProviderStatus(path, options);
5154
+ const report = await fetchVoiceTurnQuality(path, options);
1761
5155
  snapshot = {
1762
5156
  error: null,
1763
5157
  isLoading: false,
1764
- providers,
5158
+ report,
1765
5159
  updatedAt: Date.now()
1766
5160
  };
1767
5161
  emit();
1768
- return providers;
5162
+ return report;
1769
5163
  } catch (error) {
1770
5164
  snapshot = {
1771
5165
  ...snapshot,
@@ -1803,24 +5197,24 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
1803
5197
  };
1804
5198
  };
1805
5199
 
1806
- // src/angular/voice-provider-status.service.ts
5200
+ // src/angular/voice-turn-quality.service.ts
1807
5201
  var _dec = [
1808
- Injectable4({ providedIn: "root" })
5202
+ Injectable29({ providedIn: "root" })
1809
5203
  ];
1810
5204
  var _init = __decoratorStart(undefined);
1811
5205
 
1812
- class VoiceProviderStatusService {
1813
- connect(path = "/api/provider-status", options = {}) {
1814
- const store = createVoiceProviderStatusStore(path, options);
1815
- const errorSignal = signal5(null);
1816
- const isLoadingSignal = signal5(false);
1817
- const providersSignal = signal5([]);
1818
- const updatedAtSignal = signal5(undefined);
5206
+ class VoiceTurnQualityService {
5207
+ connect(path = "/api/turn-quality", options = {}) {
5208
+ const store = createVoiceTurnQualityStore(path, options);
5209
+ const errorSignal = signal29(null);
5210
+ const isLoadingSignal = signal29(false);
5211
+ const reportSignal = signal29(undefined);
5212
+ const updatedAtSignal = signal29(undefined);
1819
5213
  const sync = () => {
1820
5214
  const snapshot = store.getSnapshot();
1821
5215
  errorSignal.set(snapshot.error);
1822
5216
  isLoadingSignal.set(snapshot.isLoading);
1823
- providersSignal.set([...snapshot.providers]);
5217
+ reportSignal.set(snapshot.report);
1824
5218
  updatedAtSignal.set(snapshot.updatedAt);
1825
5219
  };
1826
5220
  const unsubscribe = store.subscribe(sync);
@@ -1831,20 +5225,20 @@ class VoiceProviderStatusService {
1831
5225
  unsubscribe();
1832
5226
  store.close();
1833
5227
  },
1834
- error: computed4(() => errorSignal()),
1835
- isLoading: computed4(() => isLoadingSignal()),
1836
- providers: computed4(() => providersSignal()),
5228
+ error: computed28(() => errorSignal()),
5229
+ isLoading: computed28(() => isLoadingSignal()),
1837
5230
  refresh: store.refresh,
1838
- updatedAt: computed4(() => updatedAtSignal())
5231
+ report: computed28(() => reportSignal()),
5232
+ updatedAt: computed28(() => updatedAtSignal())
1839
5233
  };
1840
5234
  }
1841
5235
  }
1842
- VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
1843
- __runInitializers(_init, 1, VoiceProviderStatusService);
1844
- __decoratorMetadata(_init, VoiceProviderStatusService);
1845
- let _VoiceProviderStatusService = VoiceProviderStatusService;
5236
+ VoiceTurnQualityService = __decorateElement(_init, 0, "VoiceTurnQualityService", _dec, VoiceTurnQualityService);
5237
+ __runInitializers(_init, 1, VoiceTurnQualityService);
5238
+ __decoratorMetadata(_init, VoiceTurnQualityService);
5239
+ let _VoiceTurnQualityService = VoiceTurnQualityService;
1846
5240
  // src/angular/voice-workflow-status.service.ts
1847
- import { computed as computed5, Injectable as Injectable5, signal as signal6 } from "@angular/core";
5241
+ import { computed as computed29, Injectable as Injectable30, signal as signal30 } from "@angular/core";
1848
5242
 
1849
5243
  // src/client/workflowStatus.ts
1850
5244
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -1927,17 +5321,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
1927
5321
 
1928
5322
  // src/angular/voice-workflow-status.service.ts
1929
5323
  var _dec = [
1930
- Injectable5({ providedIn: "root" })
5324
+ Injectable30({ providedIn: "root" })
1931
5325
  ];
1932
5326
  var _init = __decoratorStart(undefined);
1933
5327
 
1934
5328
  class VoiceWorkflowStatusService {
1935
5329
  connect(path = "/evals/scenarios/json", options = {}) {
1936
5330
  const store = createVoiceWorkflowStatusStore(path, options);
1937
- const errorSignal = signal6(null);
1938
- const isLoadingSignal = signal6(false);
1939
- const reportSignal = signal6(undefined);
1940
- const updatedAtSignal = signal6(undefined);
5331
+ const errorSignal = signal30(null);
5332
+ const isLoadingSignal = signal30(false);
5333
+ const reportSignal = signal30(undefined);
5334
+ const updatedAtSignal = signal30(undefined);
1941
5335
  const sync = () => {
1942
5336
  const snapshot = store.getSnapshot();
1943
5337
  errorSignal.set(snapshot.error);
@@ -1955,11 +5349,11 @@ class VoiceWorkflowStatusService {
1955
5349
  unsubscribe();
1956
5350
  store.close();
1957
5351
  },
1958
- error: computed5(() => errorSignal()),
1959
- isLoading: computed5(() => isLoadingSignal()),
5352
+ error: computed29(() => errorSignal()),
5353
+ isLoading: computed29(() => isLoadingSignal()),
1960
5354
  refresh: store.refresh,
1961
- report: computed5(() => reportSignal()),
1962
- updatedAt: computed5(() => updatedAtSignal())
5355
+ report: computed29(() => reportSignal()),
5356
+ updatedAt: computed29(() => updatedAtSignal())
1963
5357
  };
1964
5358
  }
1965
5359
  }
@@ -1969,9 +5363,33 @@ __decoratorMetadata(_init, VoiceWorkflowStatusService);
1969
5363
  let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
1970
5364
  export {
1971
5365
  VoiceWorkflowStatusService,
5366
+ VoiceWidgetService,
5367
+ VoiceTurnQualityService,
5368
+ VoiceTurnLatencyService,
5369
+ VoiceTraceTimelineService,
1972
5370
  VoiceStreamService,
5371
+ VoiceSessionSnapshotService,
5372
+ VoiceSessionObservabilityService,
5373
+ VoiceRoutingStatusService,
5374
+ VoiceReplayTimelineService,
5375
+ VoiceReconnectProfileEvidenceService,
5376
+ VoiceReadinessFailuresService,
1973
5377
  VoiceProviderStatusService,
1974
- VoiceOpsStatusComponent,
5378
+ VoiceProviderContractsService,
5379
+ VoiceProviderCapabilitiesService,
5380
+ VoiceProofTrendsService,
5381
+ VoiceProfileComparisonService,
5382
+ VoicePlatformCoverageService,
5383
+ VoiceOpsStatusService,
5384
+ VoiceOpsActionCenterService,
5385
+ VoiceLiveOpsService,
5386
+ VoiceLiveCallViewerService,
5387
+ VoiceLiveAgentConsoleService,
5388
+ VoiceDeliveryRuntimeService,
5389
+ VoiceCostDashboardService,
1975
5390
  VoiceControllerService,
1976
- VoiceAppKitStatusService
5391
+ VoiceCampaignDialerProofService,
5392
+ VoiceCallPlayerService,
5393
+ VoiceCallDebuggerService,
5394
+ VoiceAgentSquadStatusService
1977
5395
  };