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