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