@absolutejs/voice 0.0.22-beta.5 → 0.0.22-beta.500
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4556 -603
- package/dist/agent.d.ts +79 -5
- package/dist/agentSquadContract.d.ts +98 -0
- package/dist/agentState.d.ts +12 -0
- package/dist/agentTools.d.ts +133 -0
- package/dist/aiVoiceModel.d.ts +15 -0
- package/dist/amdDetector.d.ts +25 -0
- package/dist/angular/index.d.ts +26 -2
- package/dist/angular/index.js +3703 -246
- 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-campaign-dialer-proof.service.d.ts +14 -0
- package/dist/angular/voice-controller.service.d.ts +3 -1
- 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-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 +15 -0
- 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 +12 -0
- 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-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 +6 -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 +12 -0
- package/dist/assistant.d.ts +12 -13
- package/dist/assistantHealth.d.ts +81 -0
- 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/browserCallProfiles.d.ts +120 -0
- package/dist/browserMediaRoutes.d.ts +62 -0
- package/dist/callDebugger.d.ts +66 -0
- package/dist/callQuota.d.ts +54 -0
- package/dist/callerMemory.d.ts +37 -0
- package/dist/campaign.d.ts +794 -0
- package/dist/campaignControls.d.ts +37 -0
- package/dist/campaignDialers.d.ts +111 -0
- package/dist/client/actions.d.ts +117 -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/callDebugger.d.ts +19 -0
- package/dist/client/callDebuggerWidget.d.ts +30 -0
- package/dist/client/campaignDialerProof.d.ts +23 -0
- package/dist/client/connection.d.ts +5 -1
- package/dist/client/controller.d.ts +1 -1
- 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/htmxBootstrap.js +1011 -16
- package/dist/client/index.d.ts +104 -7
- package/dist/client/index.js +10409 -10
- 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 +40 -0
- 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 +19 -0
- 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 +19 -0
- package/dist/competitiveCoverage.d.ts +141 -0
- package/dist/correction.d.ts +2 -2
- package/dist/costAccounting.d.ts +76 -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 +44 -0
- package/dist/evalRoutes.d.ts +219 -0
- package/dist/fileStore.d.ts +21 -7
- package/dist/generated/htmxBootstrapBundle.d.ts +1 -0
- package/dist/guardrails.d.ts +128 -0
- package/dist/handoff.d.ts +54 -0
- package/dist/handoffHealth.d.ts +94 -0
- package/dist/htmx.d.ts +1 -1
- package/dist/incidentBundle.d.ts +119 -0
- package/dist/incidentTimeline.d.ts +260 -0
- package/dist/index.d.ts +278 -46
- package/dist/index.js +42417 -4242
- package/dist/ivrPlan.d.ts +40 -0
- package/dist/latencySlo.d.ts +56 -0
- package/dist/liveLatency.d.ts +78 -0
- package/dist/liveOps.d.ts +190 -0
- package/dist/llmJudge.d.ts +45 -0
- package/dist/logger.d.ts +1 -1
- package/dist/mediaPipelineRoutes.d.ts +171 -0
- package/dist/mediaPipelineSurfaces.d.ts +48 -0
- package/dist/memoryStore.d.ts +1 -1
- package/dist/midCallSummary.d.ts +27 -0
- package/dist/modelAdapters.d.ts +135 -2
- package/dist/monitor.d.ts +148 -0
- package/dist/multilingualProof.d.ts +77 -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 +80 -0
- 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 +126 -0
- package/dist/otelExporter.d.ts +83 -0
- package/dist/outcomeContract.d.ts +146 -0
- package/dist/outcomeRecipes.d.ts +4 -4
- package/dist/phoneAgent.d.ts +139 -0
- package/dist/phoneAgentProductionSmoke.d.ts +115 -0
- package/dist/platformCoverage.d.ts +91 -0
- package/dist/plugin.d.ts +2 -2
- package/dist/postCallAnalysis.d.ts +98 -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/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 +48 -0
- package/dist/providerCapabilities.d.ts +92 -0
- package/dist/providerDecisionTraces.d.ts +130 -0
- package/dist/providerHealth.d.ts +79 -0
- 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/qualityRoutes.d.ts +76 -0
- package/dist/queue.d.ts +72 -11
- package/dist/ragTool.d.ts +57 -0
- package/dist/react/VoiceAgentSquadStatus.d.ts +5 -0
- package/dist/react/VoiceCallDebuggerLaunch.d.ts +6 -0
- package/dist/react/VoiceCostDashboard.d.ts +10 -0
- package/dist/react/VoiceDeliveryRuntime.d.ts +7 -0
- package/dist/react/VoiceLiveCallViewer.d.ts +9 -0
- package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
- package/dist/react/VoiceOpsStatus.d.ts +6 -0
- 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 +55 -2
- package/dist/react/index.js +12290 -15
- 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 +6 -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 +8 -0
- 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 +6 -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 +8 -0
- 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 +18 -0
- package/dist/recordingStore.d.ts +60 -0
- package/dist/redaction.d.ts +13 -0
- package/dist/resilienceRoutes.d.ts +146 -0
- package/dist/retention.d.ts +37 -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/semanticTurn.d.ts +27 -0
- package/dist/session.d.ts +1 -1
- package/dist/sessionObservability.d.ts +145 -0
- package/dist/sessionReplay.d.ts +187 -0
- 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/svelte/createVoiceAgentSquadStatus.d.ts +9 -0
- package/dist/svelte/createVoiceCallDebugger.d.ts +12 -0
- package/dist/svelte/createVoiceCampaignDialerProof.d.ts +9 -0
- package/dist/svelte/createVoiceDeliveryRuntime.d.ts +11 -0
- package/dist/svelte/createVoiceLiveOps.d.ts +13 -0
- package/dist/svelte/createVoiceOpsActionCenter.d.ts +10 -0
- package/dist/svelte/createVoiceOpsStatus.d.ts +9 -0
- 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 +10 -0
- package/dist/svelte/createVoiceReadinessFailures.d.ts +7 -0
- package/dist/svelte/createVoiceReconnectProfileEvidence.d.ts +7 -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 +8 -0
- package/dist/svelte/index.d.ts +27 -2
- package/dist/svelte/index.js +6010 -150
- 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 -11
- package/dist/testing/index.js +9117 -2592
- package/dist/testing/ioProviderSimulator.d.ts +41 -0
- package/dist/testing/providerSimulator.d.ts +44 -0
- 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/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 +366 -71
- package/dist/vapiAdapter.d.ts +160 -0
- package/dist/voiceMonitoring.d.ts +444 -0
- package/dist/vue/VoiceCallDebuggerLaunch.d.ts +68 -0
- package/dist/vue/VoiceDeliveryRuntime.d.ts +30 -0
- package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
- package/dist/vue/VoiceOpsStatus.d.ts +30 -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/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 +44 -2
- package/dist/vue/index.js +11027 -31
- 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 +9 -0
- 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 +7 -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 +9 -0
- package/dist/webhookVerification.d.ts +27 -0
- package/dist/workflowContract.d.ts +91 -0
- package/fixtures/manifest.json +356 -197
- package/package.json +265 -256
package/dist/angular/index.js
CHANGED
|
@@ -68,10 +68,277 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
|
68
68
|
}
|
|
69
69
|
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
70
70
|
};
|
|
71
|
+
var __require = import.meta.require;
|
|
71
72
|
|
|
72
|
-
// src/angular/voice-
|
|
73
|
+
// src/angular/voice-ops-status.service.ts
|
|
73
74
|
import { computed, Injectable, signal } from "@angular/core";
|
|
74
75
|
|
|
76
|
+
// src/client/opsStatus.ts
|
|
77
|
+
var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
|
|
78
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
79
|
+
const response = await fetchImpl(path);
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`Voice ops status failed: HTTP ${response.status}`);
|
|
82
|
+
}
|
|
83
|
+
return await response.json();
|
|
84
|
+
};
|
|
85
|
+
var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) => {
|
|
86
|
+
const listeners = new Set;
|
|
87
|
+
let closed = false;
|
|
88
|
+
let timer;
|
|
89
|
+
let snapshot = {
|
|
90
|
+
error: null,
|
|
91
|
+
isLoading: false
|
|
92
|
+
};
|
|
93
|
+
const emit = () => {
|
|
94
|
+
for (const listener of listeners) {
|
|
95
|
+
listener();
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const refresh = async () => {
|
|
99
|
+
if (closed) {
|
|
100
|
+
return snapshot.report;
|
|
101
|
+
}
|
|
102
|
+
snapshot = {
|
|
103
|
+
...snapshot,
|
|
104
|
+
error: null,
|
|
105
|
+
isLoading: true
|
|
106
|
+
};
|
|
107
|
+
emit();
|
|
108
|
+
try {
|
|
109
|
+
const report = await fetchVoiceOpsStatus(path, options);
|
|
110
|
+
snapshot = {
|
|
111
|
+
error: null,
|
|
112
|
+
isLoading: false,
|
|
113
|
+
report,
|
|
114
|
+
updatedAt: Date.now()
|
|
115
|
+
};
|
|
116
|
+
emit();
|
|
117
|
+
return report;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
snapshot = {
|
|
120
|
+
...snapshot,
|
|
121
|
+
error: error instanceof Error ? error.message : String(error),
|
|
122
|
+
isLoading: false
|
|
123
|
+
};
|
|
124
|
+
emit();
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const close = () => {
|
|
129
|
+
closed = true;
|
|
130
|
+
if (timer) {
|
|
131
|
+
clearInterval(timer);
|
|
132
|
+
timer = undefined;
|
|
133
|
+
}
|
|
134
|
+
listeners.clear();
|
|
135
|
+
};
|
|
136
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
137
|
+
timer = setInterval(() => {
|
|
138
|
+
refresh().catch(() => {});
|
|
139
|
+
}, options.intervalMs);
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
close,
|
|
143
|
+
getServerSnapshot: () => snapshot,
|
|
144
|
+
getSnapshot: () => snapshot,
|
|
145
|
+
refresh,
|
|
146
|
+
subscribe: (listener) => {
|
|
147
|
+
listeners.add(listener);
|
|
148
|
+
return () => {
|
|
149
|
+
listeners.delete(listener);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// src/angular/voice-ops-status.service.ts
|
|
156
|
+
var _dec = [
|
|
157
|
+
Injectable({ providedIn: "root" })
|
|
158
|
+
];
|
|
159
|
+
var _init = __decoratorStart(undefined);
|
|
160
|
+
|
|
161
|
+
class VoiceOpsStatusService {
|
|
162
|
+
connect(path = "/api/voice/ops-status", options = {}) {
|
|
163
|
+
const store = createVoiceOpsStatusStore(path, options);
|
|
164
|
+
const errorSignal = signal(null);
|
|
165
|
+
const isLoadingSignal = signal(false);
|
|
166
|
+
const reportSignal = signal(undefined);
|
|
167
|
+
const updatedAtSignal = signal(undefined);
|
|
168
|
+
const sync = () => {
|
|
169
|
+
const snapshot = store.getSnapshot();
|
|
170
|
+
errorSignal.set(snapshot.error);
|
|
171
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
172
|
+
reportSignal.set(snapshot.report);
|
|
173
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
174
|
+
};
|
|
175
|
+
const unsubscribe = store.subscribe(sync);
|
|
176
|
+
sync();
|
|
177
|
+
if (typeof window !== "undefined") {
|
|
178
|
+
store.refresh().catch(() => {});
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
close: () => {
|
|
182
|
+
unsubscribe();
|
|
183
|
+
store.close();
|
|
184
|
+
},
|
|
185
|
+
error: computed(() => errorSignal()),
|
|
186
|
+
isLoading: computed(() => isLoadingSignal()),
|
|
187
|
+
refresh: store.refresh,
|
|
188
|
+
report: computed(() => reportSignal()),
|
|
189
|
+
updatedAt: computed(() => updatedAtSignal())
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
VoiceOpsStatusService = __decorateElement(_init, 0, "VoiceOpsStatusService", _dec, VoiceOpsStatusService);
|
|
194
|
+
__runInitializers(_init, 1, VoiceOpsStatusService);
|
|
195
|
+
__decoratorMetadata(_init, VoiceOpsStatusService);
|
|
196
|
+
let _VoiceOpsStatusService = VoiceOpsStatusService;
|
|
197
|
+
// src/angular/voice-widget.service.ts
|
|
198
|
+
import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
|
|
199
|
+
|
|
200
|
+
// src/client/htmx.ts
|
|
201
|
+
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
202
|
+
var DEFAULT_QUERY_PARAM = "sessionId";
|
|
203
|
+
var resolveElement = (input) => {
|
|
204
|
+
if (typeof input !== "string") {
|
|
205
|
+
return input;
|
|
206
|
+
}
|
|
207
|
+
return document.querySelector(input);
|
|
208
|
+
};
|
|
209
|
+
var buildRoute = (element, route, queryParam, sessionId) => {
|
|
210
|
+
const baseRoute = route ?? element.getAttribute("hx-get") ?? "";
|
|
211
|
+
if (!baseRoute) {
|
|
212
|
+
return "";
|
|
213
|
+
}
|
|
214
|
+
const url = new URL(baseRoute, window.location.origin);
|
|
215
|
+
if (sessionId) {
|
|
216
|
+
url.searchParams.set(queryParam, sessionId);
|
|
217
|
+
} else {
|
|
218
|
+
url.searchParams.delete(queryParam);
|
|
219
|
+
}
|
|
220
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
221
|
+
};
|
|
222
|
+
var bindVoiceHTMX = (stream, options) => {
|
|
223
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
224
|
+
return () => {};
|
|
225
|
+
}
|
|
226
|
+
const element = resolveElement(options.element);
|
|
227
|
+
if (!element) {
|
|
228
|
+
return () => {};
|
|
229
|
+
}
|
|
230
|
+
const eventName = options.eventName ?? DEFAULT_EVENT_NAME;
|
|
231
|
+
const queryParam = options.sessionQueryParam ?? DEFAULT_QUERY_PARAM;
|
|
232
|
+
const sync = () => {
|
|
233
|
+
const htmxWindow = window;
|
|
234
|
+
const nextRoute = buildRoute(element, options.route, queryParam, stream.sessionId);
|
|
235
|
+
if (nextRoute) {
|
|
236
|
+
element.setAttribute("hx-get", nextRoute);
|
|
237
|
+
}
|
|
238
|
+
htmxWindow.htmx?.process?.(element);
|
|
239
|
+
htmxWindow.htmx?.trigger?.(element, eventName);
|
|
240
|
+
};
|
|
241
|
+
const unsubscribe = stream.subscribe(sync);
|
|
242
|
+
sync();
|
|
243
|
+
return () => {
|
|
244
|
+
unsubscribe();
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// src/client/microphone.ts
|
|
249
|
+
var clampSample = (value) => Math.max(-1, Math.min(1, value));
|
|
250
|
+
var floatTo16BitPCM = (input) => {
|
|
251
|
+
const output = new Int16Array(input.length);
|
|
252
|
+
for (let index = 0;index < input.length; index += 1) {
|
|
253
|
+
const sample = clampSample(input[index] ?? 0);
|
|
254
|
+
output[index] = sample < 0 ? sample * 32768 : sample * 32767;
|
|
255
|
+
}
|
|
256
|
+
return new Uint8Array(output.buffer);
|
|
257
|
+
};
|
|
258
|
+
var getPcmLevel = (audio) => {
|
|
259
|
+
const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
|
|
260
|
+
if (bytes.byteLength < 2) {
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
const samples = new Int16Array(bytes.buffer, bytes.byteOffset, Math.floor(bytes.byteLength / 2));
|
|
264
|
+
if (samples.length === 0) {
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
let sumSquares = 0;
|
|
268
|
+
for (const sample of samples) {
|
|
269
|
+
const normalized = sample / 32768;
|
|
270
|
+
sumSquares += normalized * normalized;
|
|
271
|
+
}
|
|
272
|
+
return Math.min(1, Math.max(0, Math.sqrt(sumSquares / samples.length) * 5.5));
|
|
273
|
+
};
|
|
274
|
+
var downsampleBuffer = (input, sourceRate, targetRate) => {
|
|
275
|
+
if (sourceRate === targetRate) {
|
|
276
|
+
return input;
|
|
277
|
+
}
|
|
278
|
+
const ratio = sourceRate / targetRate;
|
|
279
|
+
const length = Math.round(input.length / ratio);
|
|
280
|
+
const output = new Float32Array(length);
|
|
281
|
+
let offsetResult = 0;
|
|
282
|
+
let offsetBuffer = 0;
|
|
283
|
+
while (offsetResult < output.length) {
|
|
284
|
+
const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
|
|
285
|
+
let accum = 0;
|
|
286
|
+
let count = 0;
|
|
287
|
+
for (let index = offsetBuffer;index < nextOffsetBuffer && index < input.length; index += 1) {
|
|
288
|
+
accum += input[index] ?? 0;
|
|
289
|
+
count += 1;
|
|
290
|
+
}
|
|
291
|
+
output[offsetResult] = count > 0 ? accum / count : 0;
|
|
292
|
+
offsetResult += 1;
|
|
293
|
+
offsetBuffer = nextOffsetBuffer;
|
|
294
|
+
}
|
|
295
|
+
return output;
|
|
296
|
+
};
|
|
297
|
+
var createMicrophoneCapture = (options) => {
|
|
298
|
+
let audioContext = null;
|
|
299
|
+
let sourceNode = null;
|
|
300
|
+
let processorNode = null;
|
|
301
|
+
let mediaStream = null;
|
|
302
|
+
const start = async () => {
|
|
303
|
+
if (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia) {
|
|
304
|
+
throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
|
|
305
|
+
}
|
|
306
|
+
const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
|
|
307
|
+
if (!AudioContextCtor) {
|
|
308
|
+
throw new Error("Browser microphone capture requires AudioContext support.");
|
|
309
|
+
}
|
|
310
|
+
mediaStream = await navigator.mediaDevices.getUserMedia({
|
|
311
|
+
audio: {
|
|
312
|
+
channelCount: options.channelCount ?? 1
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
audioContext = new AudioContextCtor;
|
|
316
|
+
sourceNode = audioContext.createMediaStreamSource(mediaStream);
|
|
317
|
+
processorNode = audioContext.createScriptProcessor(4096, 1, 1);
|
|
318
|
+
processorNode.onaudioprocess = (event) => {
|
|
319
|
+
const channel = event.inputBuffer.getChannelData(0);
|
|
320
|
+
const downsampled = downsampleBuffer(channel, audioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
|
|
321
|
+
const pcm = floatTo16BitPCM(downsampled);
|
|
322
|
+
options.onLevel?.(getPcmLevel(pcm));
|
|
323
|
+
options.onAudio(pcm);
|
|
324
|
+
};
|
|
325
|
+
sourceNode.connect(processorNode);
|
|
326
|
+
processorNode.connect(audioContext.destination);
|
|
327
|
+
};
|
|
328
|
+
const stop = () => {
|
|
329
|
+
processorNode?.disconnect();
|
|
330
|
+
sourceNode?.disconnect();
|
|
331
|
+
mediaStream?.getTracks().forEach((track) => track.stop());
|
|
332
|
+
audioContext?.close();
|
|
333
|
+
options.onLevel?.(0);
|
|
334
|
+
audioContext = null;
|
|
335
|
+
mediaStream = null;
|
|
336
|
+
processorNode = null;
|
|
337
|
+
sourceNode = null;
|
|
338
|
+
};
|
|
339
|
+
return { start, stop };
|
|
340
|
+
};
|
|
341
|
+
|
|
75
342
|
// src/client/actions.ts
|
|
76
343
|
var normalizeErrorMessage = (value) => {
|
|
77
344
|
if (typeof value === "string" && value.trim()) {
|
|
@@ -120,6 +387,17 @@ var serverMessageToAction = (message) => {
|
|
|
120
387
|
sessionId: message.sessionId,
|
|
121
388
|
type: "complete"
|
|
122
389
|
};
|
|
390
|
+
case "connection":
|
|
391
|
+
return {
|
|
392
|
+
reconnect: message.reconnect,
|
|
393
|
+
type: "connection"
|
|
394
|
+
};
|
|
395
|
+
case "call_lifecycle":
|
|
396
|
+
return {
|
|
397
|
+
event: message.event,
|
|
398
|
+
sessionId: message.sessionId,
|
|
399
|
+
type: "call_lifecycle"
|
|
400
|
+
};
|
|
123
401
|
case "error":
|
|
124
402
|
return {
|
|
125
403
|
message: normalizeErrorMessage(message.message),
|
|
@@ -135,9 +413,22 @@ var serverMessageToAction = (message) => {
|
|
|
135
413
|
transcript: message.transcript,
|
|
136
414
|
type: "partial"
|
|
137
415
|
};
|
|
416
|
+
case "replay":
|
|
417
|
+
return {
|
|
418
|
+
assistantTexts: message.assistantTexts,
|
|
419
|
+
call: message.call,
|
|
420
|
+
partial: message.partial,
|
|
421
|
+
scenarioId: message.scenarioId,
|
|
422
|
+
sessionId: message.sessionId,
|
|
423
|
+
sessionMetadata: message.sessionMetadata,
|
|
424
|
+
status: message.status,
|
|
425
|
+
turns: message.turns,
|
|
426
|
+
type: "replay"
|
|
427
|
+
};
|
|
138
428
|
case "session":
|
|
139
429
|
return {
|
|
140
430
|
sessionId: message.sessionId,
|
|
431
|
+
sessionMetadata: message.sessionMetadata,
|
|
141
432
|
scenarioId: message.scenarioId,
|
|
142
433
|
status: message.status,
|
|
143
434
|
type: "session"
|
|
@@ -152,6 +443,84 @@ var serverMessageToAction = (message) => {
|
|
|
152
443
|
}
|
|
153
444
|
};
|
|
154
445
|
|
|
446
|
+
// src/client/browserMedia.ts
|
|
447
|
+
import {
|
|
448
|
+
buildMediaWebRTCStatsReport,
|
|
449
|
+
buildMediaWebRTCStreamContinuityReport,
|
|
450
|
+
collectMediaWebRTCStats
|
|
451
|
+
} from "@absolutejs/media";
|
|
452
|
+
var DEFAULT_BROWSER_MEDIA_PATH = "/api/voice/browser-media";
|
|
453
|
+
var DEFAULT_BROWSER_MEDIA_INTERVAL_MS = 5000;
|
|
454
|
+
var resolvePeerConnection = async (options) => options.peerConnection ?? await options.getPeerConnection?.() ?? null;
|
|
455
|
+
var postBrowserMediaReport = async (payload, options) => {
|
|
456
|
+
const requestFetch = options.fetch ?? globalThis.fetch;
|
|
457
|
+
if (!requestFetch) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
await requestFetch(options.path ?? DEFAULT_BROWSER_MEDIA_PATH, {
|
|
461
|
+
body: JSON.stringify(payload),
|
|
462
|
+
headers: {
|
|
463
|
+
"Content-Type": "application/json"
|
|
464
|
+
},
|
|
465
|
+
keepalive: true,
|
|
466
|
+
method: "POST"
|
|
467
|
+
});
|
|
468
|
+
};
|
|
469
|
+
var createVoiceBrowserMediaReporter = (options) => {
|
|
470
|
+
let interval = null;
|
|
471
|
+
let previousStats = [];
|
|
472
|
+
const reportOnce = async () => {
|
|
473
|
+
const peerConnection = await resolvePeerConnection(options);
|
|
474
|
+
if (!peerConnection) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const stats = await collectMediaWebRTCStats({ peerConnection });
|
|
478
|
+
const report = buildMediaWebRTCStatsReport({
|
|
479
|
+
...options,
|
|
480
|
+
stats
|
|
481
|
+
});
|
|
482
|
+
const continuity = options.continuity === false ? undefined : buildMediaWebRTCStreamContinuityReport({
|
|
483
|
+
...options.continuity,
|
|
484
|
+
previousStats,
|
|
485
|
+
stats
|
|
486
|
+
});
|
|
487
|
+
const payload = {
|
|
488
|
+
at: Date.now(),
|
|
489
|
+
continuity,
|
|
490
|
+
report,
|
|
491
|
+
scenarioId: options.getScenarioId?.() ?? null,
|
|
492
|
+
sessionId: options.getSessionId?.() ?? null
|
|
493
|
+
};
|
|
494
|
+
previousStats = stats;
|
|
495
|
+
options.onReport?.(payload);
|
|
496
|
+
await postBrowserMediaReport(payload, options);
|
|
497
|
+
return payload;
|
|
498
|
+
};
|
|
499
|
+
const run = () => {
|
|
500
|
+
reportOnce().catch((error) => {
|
|
501
|
+
options.onError?.(error);
|
|
502
|
+
});
|
|
503
|
+
};
|
|
504
|
+
const stop = () => {
|
|
505
|
+
if (interval) {
|
|
506
|
+
clearInterval(interval);
|
|
507
|
+
interval = null;
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
return {
|
|
511
|
+
close: stop,
|
|
512
|
+
reportOnce,
|
|
513
|
+
start: () => {
|
|
514
|
+
if (interval) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
run();
|
|
518
|
+
interval = setInterval(run, options.intervalMs ?? DEFAULT_BROWSER_MEDIA_INTERVAL_MS);
|
|
519
|
+
},
|
|
520
|
+
stop
|
|
521
|
+
};
|
|
522
|
+
};
|
|
523
|
+
|
|
155
524
|
// src/client/connection.ts
|
|
156
525
|
var WS_OPEN = 1;
|
|
157
526
|
var WS_CLOSED = 3;
|
|
@@ -163,7 +532,7 @@ var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
|
|
|
163
532
|
var noop = () => {};
|
|
164
533
|
var noopUnsubscribe = () => noop;
|
|
165
534
|
var NOOP_CONNECTION = {
|
|
166
|
-
|
|
535
|
+
callControl: noop,
|
|
167
536
|
close: noop,
|
|
168
537
|
endTurn: noop,
|
|
169
538
|
getReadyState: () => WS_CLOSED,
|
|
@@ -171,6 +540,8 @@ var NOOP_CONNECTION = {
|
|
|
171
540
|
getSessionId: () => "",
|
|
172
541
|
send: noop,
|
|
173
542
|
sendAudio: noop,
|
|
543
|
+
simulateDisconnect: noop,
|
|
544
|
+
start: () => {},
|
|
174
545
|
subscribe: noopUnsubscribe
|
|
175
546
|
};
|
|
176
547
|
var createSessionId = () => crypto.randomUUID();
|
|
@@ -192,11 +563,14 @@ var isVoiceServerMessage = (value) => {
|
|
|
192
563
|
switch (value.type) {
|
|
193
564
|
case "audio":
|
|
194
565
|
case "assistant":
|
|
566
|
+
case "call_lifecycle":
|
|
195
567
|
case "complete":
|
|
568
|
+
case "connection":
|
|
196
569
|
case "error":
|
|
197
570
|
case "final":
|
|
198
571
|
case "partial":
|
|
199
572
|
case "pong":
|
|
573
|
+
case "replay":
|
|
200
574
|
case "session":
|
|
201
575
|
case "turn":
|
|
202
576
|
return true;
|
|
@@ -233,6 +607,9 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
233
607
|
sessionId: options.sessionId ?? createSessionId(),
|
|
234
608
|
ws: null
|
|
235
609
|
};
|
|
610
|
+
const emitConnection = (reconnect) => {
|
|
611
|
+
listeners.forEach((listener) => listener(reconnect));
|
|
612
|
+
};
|
|
236
613
|
const clearTimers = () => {
|
|
237
614
|
if (state.pingInterval) {
|
|
238
615
|
clearInterval(state.pingInterval);
|
|
@@ -255,9 +632,28 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
255
632
|
}
|
|
256
633
|
};
|
|
257
634
|
const scheduleReconnect = () => {
|
|
635
|
+
const nextAttemptAt = Date.now() + RECONNECT_DELAY_MS;
|
|
258
636
|
state.reconnectAttempts += 1;
|
|
637
|
+
emitConnection({
|
|
638
|
+
reconnect: {
|
|
639
|
+
attempts: state.reconnectAttempts,
|
|
640
|
+
lastDisconnectAt: Date.now(),
|
|
641
|
+
maxAttempts: maxReconnectAttempts,
|
|
642
|
+
nextAttemptAt,
|
|
643
|
+
status: "reconnecting"
|
|
644
|
+
},
|
|
645
|
+
type: "connection"
|
|
646
|
+
});
|
|
259
647
|
state.reconnectTimeout = setTimeout(() => {
|
|
260
648
|
if (state.reconnectAttempts > maxReconnectAttempts) {
|
|
649
|
+
emitConnection({
|
|
650
|
+
reconnect: {
|
|
651
|
+
attempts: state.reconnectAttempts,
|
|
652
|
+
maxAttempts: maxReconnectAttempts,
|
|
653
|
+
status: "exhausted"
|
|
654
|
+
},
|
|
655
|
+
type: "connection"
|
|
656
|
+
});
|
|
261
657
|
return;
|
|
262
658
|
}
|
|
263
659
|
connect();
|
|
@@ -267,9 +663,21 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
267
663
|
const ws = new WebSocket(buildWsUrl(path, state.sessionId, state.scenarioId));
|
|
268
664
|
ws.binaryType = "arraybuffer";
|
|
269
665
|
ws.onopen = () => {
|
|
666
|
+
const wasReconnecting = state.reconnectAttempts > 0;
|
|
270
667
|
state.isConnected = true;
|
|
271
|
-
state.reconnectAttempts = 0;
|
|
272
668
|
flushPendingMessages();
|
|
669
|
+
if (wasReconnecting) {
|
|
670
|
+
emitConnection({
|
|
671
|
+
reconnect: {
|
|
672
|
+
attempts: state.reconnectAttempts,
|
|
673
|
+
lastResumedAt: Date.now(),
|
|
674
|
+
maxAttempts: maxReconnectAttempts,
|
|
675
|
+
status: "resumed"
|
|
676
|
+
},
|
|
677
|
+
type: "connection"
|
|
678
|
+
});
|
|
679
|
+
state.reconnectAttempts = 0;
|
|
680
|
+
}
|
|
273
681
|
listeners.forEach((listener) => listener({
|
|
274
682
|
scenarioId: state.scenarioId ?? undefined,
|
|
275
683
|
sessionId: state.sessionId,
|
|
@@ -299,6 +707,16 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
299
707
|
const reconnectable = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && state.reconnectAttempts < maxReconnectAttempts;
|
|
300
708
|
if (reconnectable) {
|
|
301
709
|
scheduleReconnect();
|
|
710
|
+
} else if (shouldReconnect && event.code !== WS_NORMAL_CLOSURE) {
|
|
711
|
+
emitConnection({
|
|
712
|
+
reconnect: {
|
|
713
|
+
attempts: state.reconnectAttempts,
|
|
714
|
+
lastDisconnectAt: Date.now(),
|
|
715
|
+
maxAttempts: maxReconnectAttempts,
|
|
716
|
+
status: "exhausted"
|
|
717
|
+
},
|
|
718
|
+
type: "connection"
|
|
719
|
+
});
|
|
302
720
|
}
|
|
303
721
|
};
|
|
304
722
|
state.ws = ws;
|
|
@@ -332,6 +750,12 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
332
750
|
const endTurn = () => {
|
|
333
751
|
send({ type: "end_turn" });
|
|
334
752
|
};
|
|
753
|
+
const callControl = (message) => {
|
|
754
|
+
send({
|
|
755
|
+
...message,
|
|
756
|
+
type: "call_control"
|
|
757
|
+
});
|
|
758
|
+
};
|
|
335
759
|
const close = () => {
|
|
336
760
|
clearTimers();
|
|
337
761
|
if (state.ws) {
|
|
@@ -341,6 +765,11 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
341
765
|
state.isConnected = false;
|
|
342
766
|
listeners.clear();
|
|
343
767
|
};
|
|
768
|
+
const simulateDisconnect = () => {
|
|
769
|
+
if (state.ws?.readyState === WS_OPEN) {
|
|
770
|
+
state.ws.close(4000, "absolutejs-voice-reconnect-proof");
|
|
771
|
+
}
|
|
772
|
+
};
|
|
344
773
|
const subscribe = (callback) => {
|
|
345
774
|
listeners.add(callback);
|
|
346
775
|
return () => {
|
|
@@ -349,7 +778,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
349
778
|
};
|
|
350
779
|
connect();
|
|
351
780
|
return {
|
|
352
|
-
|
|
781
|
+
callControl,
|
|
353
782
|
close,
|
|
354
783
|
endTurn,
|
|
355
784
|
getReadyState: () => state.ws?.readyState ?? WS_CLOSED,
|
|
@@ -357,18 +786,28 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
357
786
|
getSessionId: () => state.sessionId,
|
|
358
787
|
send,
|
|
359
788
|
sendAudio,
|
|
789
|
+
simulateDisconnect,
|
|
790
|
+
start,
|
|
360
791
|
subscribe
|
|
361
792
|
};
|
|
362
793
|
};
|
|
363
794
|
|
|
364
795
|
// src/client/store.ts
|
|
796
|
+
var createInitialReconnectState = () => ({
|
|
797
|
+
attempts: 0,
|
|
798
|
+
maxAttempts: 0,
|
|
799
|
+
status: "idle"
|
|
800
|
+
});
|
|
365
801
|
var createInitialState = () => ({
|
|
366
802
|
assistantAudio: [],
|
|
367
803
|
assistantTexts: [],
|
|
804
|
+
call: null,
|
|
368
805
|
error: null,
|
|
369
806
|
isConnected: false,
|
|
807
|
+
sessionMetadata: null,
|
|
370
808
|
scenarioId: null,
|
|
371
809
|
partial: "",
|
|
810
|
+
reconnect: createInitialReconnectState(),
|
|
372
811
|
sessionId: null,
|
|
373
812
|
status: "idle",
|
|
374
813
|
turns: []
|
|
@@ -408,10 +847,36 @@ var createVoiceStreamStore = () => {
|
|
|
408
847
|
status: "completed"
|
|
409
848
|
};
|
|
410
849
|
break;
|
|
850
|
+
case "call_lifecycle":
|
|
851
|
+
state = {
|
|
852
|
+
...state,
|
|
853
|
+
call: {
|
|
854
|
+
...state.call,
|
|
855
|
+
disposition: action.event.type === "end" ? action.event.disposition : state.call?.disposition,
|
|
856
|
+
endedAt: action.event.type === "end" ? action.event.at : state.call?.endedAt,
|
|
857
|
+
events: [...state.call?.events ?? [], action.event],
|
|
858
|
+
lastEventAt: action.event.at,
|
|
859
|
+
startedAt: state.call?.startedAt ?? action.event.at
|
|
860
|
+
},
|
|
861
|
+
sessionId: action.sessionId
|
|
862
|
+
};
|
|
863
|
+
break;
|
|
411
864
|
case "connected":
|
|
412
865
|
state = {
|
|
413
866
|
...state,
|
|
414
|
-
isConnected: true
|
|
867
|
+
isConnected: true,
|
|
868
|
+
reconnect: state.reconnect.status === "reconnecting" ? {
|
|
869
|
+
...state.reconnect,
|
|
870
|
+
lastResumedAt: Date.now(),
|
|
871
|
+
nextAttemptAt: undefined,
|
|
872
|
+
status: "resumed"
|
|
873
|
+
} : state.reconnect
|
|
874
|
+
};
|
|
875
|
+
break;
|
|
876
|
+
case "connection":
|
|
877
|
+
state = {
|
|
878
|
+
...state,
|
|
879
|
+
reconnect: action.reconnect
|
|
415
880
|
};
|
|
416
881
|
break;
|
|
417
882
|
case "disconnected":
|
|
@@ -439,6 +904,27 @@ var createVoiceStreamStore = () => {
|
|
|
439
904
|
partial: action.transcript.text
|
|
440
905
|
};
|
|
441
906
|
break;
|
|
907
|
+
case "replay":
|
|
908
|
+
state = {
|
|
909
|
+
...state,
|
|
910
|
+
assistantTexts: [...action.assistantTexts],
|
|
911
|
+
call: action.call ?? null,
|
|
912
|
+
error: null,
|
|
913
|
+
isConnected: action.status === "active",
|
|
914
|
+
partial: action.partial,
|
|
915
|
+
reconnect: state.reconnect.status === "reconnecting" ? {
|
|
916
|
+
...state.reconnect,
|
|
917
|
+
lastResumedAt: Date.now(),
|
|
918
|
+
nextAttemptAt: undefined,
|
|
919
|
+
status: "resumed"
|
|
920
|
+
} : state.reconnect,
|
|
921
|
+
scenarioId: action.scenarioId ?? state.scenarioId,
|
|
922
|
+
sessionId: action.sessionId,
|
|
923
|
+
sessionMetadata: action.sessionMetadata ?? state.sessionMetadata,
|
|
924
|
+
status: action.status,
|
|
925
|
+
turns: [...action.turns]
|
|
926
|
+
};
|
|
927
|
+
break;
|
|
442
928
|
case "session":
|
|
443
929
|
state = {
|
|
444
930
|
...state,
|
|
@@ -446,6 +932,7 @@ var createVoiceStreamStore = () => {
|
|
|
446
932
|
scenarioId: action.scenarioId ?? state.scenarioId,
|
|
447
933
|
isConnected: action.status === "active",
|
|
448
934
|
sessionId: action.sessionId,
|
|
935
|
+
sessionMetadata: action.sessionMetadata ?? state.sessionMetadata,
|
|
449
936
|
status: action.status
|
|
450
937
|
};
|
|
451
938
|
break;
|
|
@@ -476,26 +963,60 @@ var createVoiceStreamStore = () => {
|
|
|
476
963
|
var createVoiceStream = (path, options = {}) => {
|
|
477
964
|
const connection = createVoiceConnection(path, options);
|
|
478
965
|
const store = createVoiceStreamStore();
|
|
966
|
+
const browserMediaReporter = options.browserMedia && typeof window !== "undefined" ? createVoiceBrowserMediaReporter({
|
|
967
|
+
...options.browserMedia,
|
|
968
|
+
getScenarioId: () => options.browserMedia ? options.browserMedia.getScenarioId?.() ?? connection.getScenarioId() : connection.getScenarioId(),
|
|
969
|
+
getSessionId: () => options.browserMedia ? options.browserMedia.getSessionId?.() ?? connection.getSessionId() : connection.getSessionId()
|
|
970
|
+
}) : null;
|
|
479
971
|
const subscribers = new Set;
|
|
480
972
|
const start = (input) => Promise.resolve().then(() => {
|
|
481
973
|
if (!input?.sessionId && !input?.scenarioId) {
|
|
482
974
|
return;
|
|
483
975
|
}
|
|
484
976
|
connection.start(input);
|
|
977
|
+
browserMediaReporter?.start();
|
|
485
978
|
});
|
|
486
979
|
const notify = () => {
|
|
487
980
|
subscribers.forEach((subscriber) => subscriber());
|
|
488
981
|
};
|
|
489
|
-
const
|
|
982
|
+
const reportReconnect = () => {
|
|
983
|
+
if (!options.reconnectReportPath || typeof fetch === "undefined") {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
const snapshot = store.getSnapshot();
|
|
987
|
+
const body = JSON.stringify({
|
|
988
|
+
at: Date.now(),
|
|
989
|
+
reconnect: snapshot.reconnect,
|
|
990
|
+
scenarioId: snapshot.scenarioId,
|
|
991
|
+
sessionId: connection.getSessionId(),
|
|
992
|
+
turnIds: snapshot.turns.map((turn) => turn.id)
|
|
993
|
+
});
|
|
994
|
+
fetch(options.reconnectReportPath, {
|
|
995
|
+
body,
|
|
996
|
+
headers: {
|
|
997
|
+
"Content-Type": "application/json"
|
|
998
|
+
},
|
|
999
|
+
keepalive: true,
|
|
1000
|
+
method: "POST"
|
|
1001
|
+
}).catch(() => {});
|
|
1002
|
+
};
|
|
1003
|
+
const unsubscribeConnection = connection.subscribe((message) => {
|
|
490
1004
|
const action = serverMessageToAction(message);
|
|
491
1005
|
if (action) {
|
|
492
1006
|
store.dispatch(action);
|
|
1007
|
+
if (message.type === "connection") {
|
|
1008
|
+
reportReconnect();
|
|
1009
|
+
}
|
|
493
1010
|
notify();
|
|
494
1011
|
}
|
|
495
1012
|
});
|
|
496
1013
|
return {
|
|
1014
|
+
callControl(message) {
|
|
1015
|
+
connection.callControl(message);
|
|
1016
|
+
},
|
|
497
1017
|
close() {
|
|
498
1018
|
unsubscribeConnection();
|
|
1019
|
+
browserMediaReporter?.close();
|
|
499
1020
|
connection.close();
|
|
500
1021
|
store.dispatch({ type: "disconnected" });
|
|
501
1022
|
notify();
|
|
@@ -518,10 +1039,16 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
518
1039
|
get scenarioId() {
|
|
519
1040
|
return store.getSnapshot().scenarioId;
|
|
520
1041
|
},
|
|
1042
|
+
get sessionMetadata() {
|
|
1043
|
+
return store.getSnapshot().sessionMetadata;
|
|
1044
|
+
},
|
|
521
1045
|
start,
|
|
522
1046
|
get partial() {
|
|
523
1047
|
return store.getSnapshot().partial;
|
|
524
1048
|
},
|
|
1049
|
+
get reconnect() {
|
|
1050
|
+
return store.getSnapshot().reconnect;
|
|
1051
|
+
},
|
|
525
1052
|
get sessionId() {
|
|
526
1053
|
return connection.getSessionId();
|
|
527
1054
|
},
|
|
@@ -537,9 +1064,15 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
537
1064
|
get assistantAudio() {
|
|
538
1065
|
return store.getSnapshot().assistantAudio;
|
|
539
1066
|
},
|
|
1067
|
+
get call() {
|
|
1068
|
+
return store.getSnapshot().call;
|
|
1069
|
+
},
|
|
540
1070
|
sendAudio(audio) {
|
|
541
1071
|
connection.sendAudio(audio);
|
|
542
1072
|
},
|
|
1073
|
+
simulateDisconnect() {
|
|
1074
|
+
connection.simulateDisconnect();
|
|
1075
|
+
},
|
|
543
1076
|
subscribe(subscriber) {
|
|
544
1077
|
subscribers.add(subscriber);
|
|
545
1078
|
return () => {
|
|
@@ -549,202 +1082,6 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
549
1082
|
};
|
|
550
1083
|
};
|
|
551
1084
|
|
|
552
|
-
// src/angular/voice-stream.service.ts
|
|
553
|
-
var _dec = [
|
|
554
|
-
Injectable({ providedIn: "root" })
|
|
555
|
-
];
|
|
556
|
-
var _init = __decoratorStart(undefined);
|
|
557
|
-
|
|
558
|
-
class VoiceStreamService {
|
|
559
|
-
connect(path, options = {}) {
|
|
560
|
-
const stream = createVoiceStream(path, options);
|
|
561
|
-
const assistantAudioSignal = signal([]);
|
|
562
|
-
const assistantTextsSignal = signal([]);
|
|
563
|
-
const errorSignal = signal(null);
|
|
564
|
-
const isConnectedSignal = signal(false);
|
|
565
|
-
const partialSignal = signal("");
|
|
566
|
-
const sessionIdSignal = signal(stream.sessionId);
|
|
567
|
-
const statusSignal = signal(stream.status);
|
|
568
|
-
const turnsSignal = signal([]);
|
|
569
|
-
const sync = () => {
|
|
570
|
-
assistantAudioSignal.set([...stream.assistantAudio]);
|
|
571
|
-
assistantTextsSignal.set([...stream.assistantTexts]);
|
|
572
|
-
errorSignal.set(stream.error);
|
|
573
|
-
isConnectedSignal.set(stream.isConnected);
|
|
574
|
-
partialSignal.set(stream.partial);
|
|
575
|
-
sessionIdSignal.set(stream.sessionId);
|
|
576
|
-
statusSignal.set(stream.status);
|
|
577
|
-
turnsSignal.set([...stream.turns]);
|
|
578
|
-
};
|
|
579
|
-
const unsubscribe = stream.subscribe(sync);
|
|
580
|
-
sync();
|
|
581
|
-
return {
|
|
582
|
-
assistantAudio: computed(() => assistantAudioSignal()),
|
|
583
|
-
assistantTexts: computed(() => assistantTextsSignal()),
|
|
584
|
-
close: () => {
|
|
585
|
-
unsubscribe();
|
|
586
|
-
stream.close();
|
|
587
|
-
},
|
|
588
|
-
endTurn: () => stream.endTurn(),
|
|
589
|
-
error: computed(() => errorSignal()),
|
|
590
|
-
isConnected: computed(() => isConnectedSignal()),
|
|
591
|
-
partial: computed(() => partialSignal()),
|
|
592
|
-
sendAudio: (audio) => stream.sendAudio(audio),
|
|
593
|
-
sessionId: computed(() => sessionIdSignal()),
|
|
594
|
-
status: computed(() => statusSignal()),
|
|
595
|
-
turns: computed(() => turnsSignal())
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
VoiceStreamService = __decorateElement(_init, 0, "VoiceStreamService", _dec, VoiceStreamService);
|
|
600
|
-
__runInitializers(_init, 1, VoiceStreamService);
|
|
601
|
-
__decoratorMetadata(_init, VoiceStreamService);
|
|
602
|
-
let _VoiceStreamService = VoiceStreamService;
|
|
603
|
-
// src/angular/voice-controller.service.ts
|
|
604
|
-
import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
|
|
605
|
-
|
|
606
|
-
// src/client/htmx.ts
|
|
607
|
-
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
608
|
-
var DEFAULT_QUERY_PARAM = "sessionId";
|
|
609
|
-
var resolveElement = (input) => {
|
|
610
|
-
if (typeof input !== "string") {
|
|
611
|
-
return input;
|
|
612
|
-
}
|
|
613
|
-
return document.querySelector(input);
|
|
614
|
-
};
|
|
615
|
-
var buildRoute = (element, route, queryParam, sessionId) => {
|
|
616
|
-
const baseRoute = route ?? element.getAttribute("hx-get") ?? "";
|
|
617
|
-
if (!baseRoute) {
|
|
618
|
-
return "";
|
|
619
|
-
}
|
|
620
|
-
const url = new URL(baseRoute, window.location.origin);
|
|
621
|
-
if (sessionId) {
|
|
622
|
-
url.searchParams.set(queryParam, sessionId);
|
|
623
|
-
} else {
|
|
624
|
-
url.searchParams.delete(queryParam);
|
|
625
|
-
}
|
|
626
|
-
return `${url.pathname}${url.search}${url.hash}`;
|
|
627
|
-
};
|
|
628
|
-
var bindVoiceHTMX = (stream, options) => {
|
|
629
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
630
|
-
return () => {};
|
|
631
|
-
}
|
|
632
|
-
const element = resolveElement(options.element);
|
|
633
|
-
if (!element) {
|
|
634
|
-
return () => {};
|
|
635
|
-
}
|
|
636
|
-
const eventName = options.eventName ?? DEFAULT_EVENT_NAME;
|
|
637
|
-
const queryParam = options.sessionQueryParam ?? DEFAULT_QUERY_PARAM;
|
|
638
|
-
const sync = () => {
|
|
639
|
-
const htmxWindow = window;
|
|
640
|
-
const nextRoute = buildRoute(element, options.route, queryParam, stream.sessionId);
|
|
641
|
-
if (nextRoute) {
|
|
642
|
-
element.setAttribute("hx-get", nextRoute);
|
|
643
|
-
}
|
|
644
|
-
htmxWindow.htmx?.process?.(element);
|
|
645
|
-
htmxWindow.htmx?.trigger?.(element, eventName);
|
|
646
|
-
};
|
|
647
|
-
const unsubscribe = stream.subscribe(sync);
|
|
648
|
-
sync();
|
|
649
|
-
return () => {
|
|
650
|
-
unsubscribe();
|
|
651
|
-
};
|
|
652
|
-
};
|
|
653
|
-
|
|
654
|
-
// src/client/microphone.ts
|
|
655
|
-
var clampSample = (value) => Math.max(-1, Math.min(1, value));
|
|
656
|
-
var floatTo16BitPCM = (input) => {
|
|
657
|
-
const output = new Int16Array(input.length);
|
|
658
|
-
for (let index = 0;index < input.length; index += 1) {
|
|
659
|
-
const sample = clampSample(input[index] ?? 0);
|
|
660
|
-
output[index] = sample < 0 ? sample * 32768 : sample * 32767;
|
|
661
|
-
}
|
|
662
|
-
return new Uint8Array(output.buffer);
|
|
663
|
-
};
|
|
664
|
-
var getPcmLevel = (audio) => {
|
|
665
|
-
const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
|
|
666
|
-
if (bytes.byteLength < 2) {
|
|
667
|
-
return 0;
|
|
668
|
-
}
|
|
669
|
-
const samples = new Int16Array(bytes.buffer, bytes.byteOffset, Math.floor(bytes.byteLength / 2));
|
|
670
|
-
if (samples.length === 0) {
|
|
671
|
-
return 0;
|
|
672
|
-
}
|
|
673
|
-
let sumSquares = 0;
|
|
674
|
-
for (const sample of samples) {
|
|
675
|
-
const normalized = sample / 32768;
|
|
676
|
-
sumSquares += normalized * normalized;
|
|
677
|
-
}
|
|
678
|
-
return Math.min(1, Math.max(0, Math.sqrt(sumSquares / samples.length) * 5.5));
|
|
679
|
-
};
|
|
680
|
-
var downsampleBuffer = (input, sourceRate, targetRate) => {
|
|
681
|
-
if (sourceRate === targetRate) {
|
|
682
|
-
return input;
|
|
683
|
-
}
|
|
684
|
-
const ratio = sourceRate / targetRate;
|
|
685
|
-
const length = Math.round(input.length / ratio);
|
|
686
|
-
const output = new Float32Array(length);
|
|
687
|
-
let offsetResult = 0;
|
|
688
|
-
let offsetBuffer = 0;
|
|
689
|
-
while (offsetResult < output.length) {
|
|
690
|
-
const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
|
|
691
|
-
let accum = 0;
|
|
692
|
-
let count = 0;
|
|
693
|
-
for (let index = offsetBuffer;index < nextOffsetBuffer && index < input.length; index += 1) {
|
|
694
|
-
accum += input[index] ?? 0;
|
|
695
|
-
count += 1;
|
|
696
|
-
}
|
|
697
|
-
output[offsetResult] = count > 0 ? accum / count : 0;
|
|
698
|
-
offsetResult += 1;
|
|
699
|
-
offsetBuffer = nextOffsetBuffer;
|
|
700
|
-
}
|
|
701
|
-
return output;
|
|
702
|
-
};
|
|
703
|
-
var createMicrophoneCapture = (options) => {
|
|
704
|
-
let audioContext = null;
|
|
705
|
-
let sourceNode = null;
|
|
706
|
-
let processorNode = null;
|
|
707
|
-
let mediaStream = null;
|
|
708
|
-
const start = async () => {
|
|
709
|
-
if (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia) {
|
|
710
|
-
throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
|
|
711
|
-
}
|
|
712
|
-
const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
|
|
713
|
-
if (!AudioContextCtor) {
|
|
714
|
-
throw new Error("Browser microphone capture requires AudioContext support.");
|
|
715
|
-
}
|
|
716
|
-
mediaStream = await navigator.mediaDevices.getUserMedia({
|
|
717
|
-
audio: {
|
|
718
|
-
channelCount: options.channelCount ?? 1
|
|
719
|
-
}
|
|
720
|
-
});
|
|
721
|
-
audioContext = new AudioContextCtor;
|
|
722
|
-
sourceNode = audioContext.createMediaStreamSource(mediaStream);
|
|
723
|
-
processorNode = audioContext.createScriptProcessor(4096, 1, 1);
|
|
724
|
-
processorNode.onaudioprocess = (event) => {
|
|
725
|
-
const channel = event.inputBuffer.getChannelData(0);
|
|
726
|
-
const downsampled = downsampleBuffer(channel, audioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
|
|
727
|
-
const pcm = floatTo16BitPCM(downsampled);
|
|
728
|
-
options.onLevel?.(getPcmLevel(pcm));
|
|
729
|
-
options.onAudio(pcm);
|
|
730
|
-
};
|
|
731
|
-
sourceNode.connect(processorNode);
|
|
732
|
-
processorNode.connect(audioContext.destination);
|
|
733
|
-
};
|
|
734
|
-
const stop = () => {
|
|
735
|
-
processorNode?.disconnect();
|
|
736
|
-
sourceNode?.disconnect();
|
|
737
|
-
mediaStream?.getTracks().forEach((track) => track.stop());
|
|
738
|
-
audioContext?.close();
|
|
739
|
-
options.onLevel?.(0);
|
|
740
|
-
audioContext = null;
|
|
741
|
-
mediaStream = null;
|
|
742
|
-
processorNode = null;
|
|
743
|
-
sourceNode = null;
|
|
744
|
-
};
|
|
745
|
-
return { start, stop };
|
|
746
|
-
};
|
|
747
|
-
|
|
748
1085
|
// src/audioConditioning.ts
|
|
749
1086
|
var DEFAULT_TARGET_LEVEL = 0.08;
|
|
750
1087
|
var DEFAULT_MAX_GAIN = 3;
|
|
@@ -1065,12 +1402,15 @@ var resolveVoiceRuntimePreset = (name = "default") => {
|
|
|
1065
1402
|
var createInitialState2 = (stream) => ({
|
|
1066
1403
|
assistantAudio: [...stream.assistantAudio],
|
|
1067
1404
|
assistantTexts: [...stream.assistantTexts],
|
|
1405
|
+
call: stream.call,
|
|
1068
1406
|
error: stream.error,
|
|
1069
1407
|
isConnected: stream.isConnected,
|
|
1070
1408
|
isRecording: false,
|
|
1071
1409
|
partial: stream.partial,
|
|
1410
|
+
reconnect: stream.reconnect,
|
|
1072
1411
|
recordingError: null,
|
|
1073
1412
|
sessionId: stream.sessionId,
|
|
1413
|
+
sessionMetadata: stream.sessionMetadata,
|
|
1074
1414
|
scenarioId: stream.scenarioId,
|
|
1075
1415
|
status: stream.status,
|
|
1076
1416
|
turns: [...stream.turns]
|
|
@@ -1094,10 +1434,13 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1094
1434
|
...state,
|
|
1095
1435
|
assistantAudio: [...stream.assistantAudio],
|
|
1096
1436
|
assistantTexts: [...stream.assistantTexts],
|
|
1437
|
+
call: stream.call,
|
|
1097
1438
|
error: stream.error,
|
|
1098
1439
|
isConnected: stream.isConnected,
|
|
1099
1440
|
partial: stream.partial,
|
|
1441
|
+
reconnect: stream.reconnect,
|
|
1100
1442
|
sessionId: stream.sessionId,
|
|
1443
|
+
sessionMetadata: stream.sessionMetadata,
|
|
1101
1444
|
scenarioId: stream.scenarioId,
|
|
1102
1445
|
status: stream.status,
|
|
1103
1446
|
turns: [...stream.turns]
|
|
@@ -1121,7 +1464,13 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1121
1464
|
capture = createMicrophoneCapture({
|
|
1122
1465
|
channelCount: options.capture?.channelCount ?? preset.capture.channelCount,
|
|
1123
1466
|
onLevel: options.capture?.onLevel,
|
|
1124
|
-
onAudio: (audio) =>
|
|
1467
|
+
onAudio: (audio) => {
|
|
1468
|
+
if (options.capture?.onAudio) {
|
|
1469
|
+
options.capture.onAudio(audio, stream.sendAudio);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
stream.sendAudio(audio);
|
|
1473
|
+
},
|
|
1125
1474
|
sampleRateHz: options.capture?.sampleRateHz ?? preset.capture.sampleRateHz
|
|
1126
1475
|
});
|
|
1127
1476
|
return capture;
|
|
@@ -1171,6 +1520,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1171
1520
|
bindHTMX(bindingOptions) {
|
|
1172
1521
|
return bindVoiceHTMX(stream, bindingOptions);
|
|
1173
1522
|
},
|
|
1523
|
+
callControl: (message) => stream.callControl(message),
|
|
1174
1524
|
close,
|
|
1175
1525
|
endTurn: () => stream.endTurn(),
|
|
1176
1526
|
get error() {
|
|
@@ -1190,10 +1540,17 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1190
1540
|
get recordingError() {
|
|
1191
1541
|
return state.recordingError;
|
|
1192
1542
|
},
|
|
1543
|
+
get reconnect() {
|
|
1544
|
+
return state.reconnect;
|
|
1545
|
+
},
|
|
1193
1546
|
sendAudio: (audio) => stream.sendAudio(audio),
|
|
1547
|
+
simulateDisconnect: () => stream.simulateDisconnect(),
|
|
1194
1548
|
get sessionId() {
|
|
1195
1549
|
return state.sessionId;
|
|
1196
1550
|
},
|
|
1551
|
+
get sessionMetadata() {
|
|
1552
|
+
return state.sessionMetadata;
|
|
1553
|
+
},
|
|
1197
1554
|
get scenarioId() {
|
|
1198
1555
|
return state.scenarioId;
|
|
1199
1556
|
},
|
|
@@ -1223,72 +1580,3172 @@ var createVoiceController = (path, options = {}) => {
|
|
|
1223
1580
|
},
|
|
1224
1581
|
get assistantAudio() {
|
|
1225
1582
|
return state.assistantAudio;
|
|
1583
|
+
},
|
|
1584
|
+
get call() {
|
|
1585
|
+
return state.call;
|
|
1226
1586
|
}
|
|
1227
1587
|
};
|
|
1228
1588
|
};
|
|
1229
1589
|
|
|
1230
|
-
// src/
|
|
1590
|
+
// src/agentState.ts
|
|
1591
|
+
var deriveVoiceAgentUIState = (input) => {
|
|
1592
|
+
if (!input.isConnected) {
|
|
1593
|
+
return "idle";
|
|
1594
|
+
}
|
|
1595
|
+
if (input.isPlaying) {
|
|
1596
|
+
return "speaking";
|
|
1597
|
+
}
|
|
1598
|
+
if (input.isRecording && input.hasActivePartial) {
|
|
1599
|
+
return "listening";
|
|
1600
|
+
}
|
|
1601
|
+
if (input.isRecording) {
|
|
1602
|
+
return "listening";
|
|
1603
|
+
}
|
|
1604
|
+
if (input.lastTranscriptAt && !input.lastAssistantAt) {
|
|
1605
|
+
return "thinking";
|
|
1606
|
+
}
|
|
1607
|
+
if (input.lastTranscriptAt && input.lastAssistantAt && input.lastTranscriptAt > input.lastAssistantAt) {
|
|
1608
|
+
return "thinking";
|
|
1609
|
+
}
|
|
1610
|
+
return "idle";
|
|
1611
|
+
};
|
|
1612
|
+
var describeVoiceAgentUIState = (state) => {
|
|
1613
|
+
switch (state) {
|
|
1614
|
+
case "idle":
|
|
1615
|
+
return "Idle";
|
|
1616
|
+
case "listening":
|
|
1617
|
+
return "Listening";
|
|
1618
|
+
case "speaking":
|
|
1619
|
+
return "Speaking";
|
|
1620
|
+
case "thinking":
|
|
1621
|
+
return "Thinking";
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
var voiceAgentUIStateOrder = [
|
|
1625
|
+
"idle",
|
|
1626
|
+
"listening",
|
|
1627
|
+
"thinking",
|
|
1628
|
+
"speaking"
|
|
1629
|
+
];
|
|
1630
|
+
|
|
1631
|
+
// src/client/voiceWidgetView.ts
|
|
1632
|
+
var DEFAULT_VOICE_WIDGET_THEME = {
|
|
1633
|
+
accent: "#3b82f6",
|
|
1634
|
+
background: "#0f172a",
|
|
1635
|
+
errorAccent: "#ef4444",
|
|
1636
|
+
fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
|
1637
|
+
foreground: "#f8fafc",
|
|
1638
|
+
radius: 16
|
|
1639
|
+
};
|
|
1640
|
+
var DEFAULT_VOICE_WIDGET_LABELS = {
|
|
1641
|
+
callEnded: "Call ended",
|
|
1642
|
+
connecting: "Connecting\u2026",
|
|
1643
|
+
endCall: "End call",
|
|
1644
|
+
idle: "Idle",
|
|
1645
|
+
listening: "Listening",
|
|
1646
|
+
mute: "Mute",
|
|
1647
|
+
speaking: "Speaking",
|
|
1648
|
+
startCall: "Start call",
|
|
1649
|
+
thinking: "Thinking",
|
|
1650
|
+
unmute: "Unmute"
|
|
1651
|
+
};
|
|
1652
|
+
var stateLabel = (state, labels) => {
|
|
1653
|
+
switch (state) {
|
|
1654
|
+
case "listening":
|
|
1655
|
+
return labels.listening;
|
|
1656
|
+
case "speaking":
|
|
1657
|
+
return labels.speaking;
|
|
1658
|
+
case "thinking":
|
|
1659
|
+
return labels.thinking;
|
|
1660
|
+
case "idle":
|
|
1661
|
+
return labels.idle;
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
var createVoiceWidgetViewModel = (input) => {
|
|
1665
|
+
const theme = { ...DEFAULT_VOICE_WIDGET_THEME, ...input.theme };
|
|
1666
|
+
const labels = { ...DEFAULT_VOICE_WIDGET_LABELS, ...input.labels };
|
|
1667
|
+
const lastAssistantAt = input.state.assistantAudio.at(-1)?.receivedAt;
|
|
1668
|
+
const lastTranscriptAt = input.state.turns.at(-1)?.committedAt;
|
|
1669
|
+
const agentState = deriveVoiceAgentUIState({
|
|
1670
|
+
hasActivePartial: input.state.partial.length > 0,
|
|
1671
|
+
isConnected: input.state.isConnected,
|
|
1672
|
+
isPlaying: false,
|
|
1673
|
+
isRecording: input.state.isRecording,
|
|
1674
|
+
lastAssistantAt,
|
|
1675
|
+
lastTranscriptAt
|
|
1676
|
+
});
|
|
1677
|
+
const connecting = !input.state.isConnected && input.state.status !== "idle" && !input.state.error;
|
|
1678
|
+
const statusLabel = input.state.error ? "Error" : connecting ? labels.connecting : input.state.status === "completed" ? labels.callEnded : stateLabel(agentState, labels);
|
|
1679
|
+
return {
|
|
1680
|
+
agentState,
|
|
1681
|
+
classes: {
|
|
1682
|
+
container: `absolute-voice-widget absolute-voice-widget--${agentState}`,
|
|
1683
|
+
dot: `absolute-voice-widget__dot${input.state.error ? " absolute-voice-widget__dot--error" : ""}`
|
|
1684
|
+
},
|
|
1685
|
+
controls: {
|
|
1686
|
+
canEnd: input.state.isConnected,
|
|
1687
|
+
canMute: input.state.isRecording,
|
|
1688
|
+
canStart: !input.state.isRecording && input.state.status !== "completed"
|
|
1689
|
+
},
|
|
1690
|
+
errorMessage: input.state.error ?? undefined,
|
|
1691
|
+
labels,
|
|
1692
|
+
partial: input.state.partial || undefined,
|
|
1693
|
+
statusLabel,
|
|
1694
|
+
theme,
|
|
1695
|
+
title: input.title ?? "Voice"
|
|
1696
|
+
};
|
|
1697
|
+
};
|
|
1698
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1699
|
+
var resolveRadius = (radius) => typeof radius === "number" ? `${radius}px` : radius;
|
|
1700
|
+
var renderVoiceWidgetHTML = (model) => {
|
|
1701
|
+
const t = model.theme;
|
|
1702
|
+
const containerStyle = `background:${t.background};border-radius:${resolveRadius(t.radius)};color:${t.foreground};font-family:${t.fontFamily};min-width:240px;padding:20px 22px;`;
|
|
1703
|
+
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;`;
|
|
1704
|
+
const buttons = [];
|
|
1705
|
+
if (model.controls.canStart) {
|
|
1706
|
+
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>`);
|
|
1707
|
+
}
|
|
1708
|
+
if (model.controls.canMute) {
|
|
1709
|
+
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>`);
|
|
1710
|
+
}
|
|
1711
|
+
if (model.controls.canEnd) {
|
|
1712
|
+
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>`);
|
|
1713
|
+
}
|
|
1714
|
+
return `<div role="region" aria-live="polite" data-agent-state="${model.agentState}" class="${escapeHtml(model.classes.container)}" style="${containerStyle}">
|
|
1715
|
+
<div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
|
|
1716
|
+
<span aria-hidden="true" class="${escapeHtml(model.classes.dot)}" style="${dotStyle}"></span>
|
|
1717
|
+
<strong style="font-size:15px;">${escapeHtml(model.title)}</strong>
|
|
1718
|
+
<span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml(model.statusLabel)}</span>
|
|
1719
|
+
</div>
|
|
1720
|
+
${model.partial ? `<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">\u201C${escapeHtml(model.partial)}\u201D</p>` : ""}
|
|
1721
|
+
<div style="display:flex;gap:10px;">${buttons.join("")}</div>
|
|
1722
|
+
${model.errorMessage ? `<p style="color:${t.errorAccent};font-size:12px;margin-top:12px;">${escapeHtml(model.errorMessage)}</p>` : ""}
|
|
1723
|
+
</div>`;
|
|
1724
|
+
};
|
|
1725
|
+
|
|
1726
|
+
// src/angular/voice-widget.service.ts
|
|
1231
1727
|
var _dec = [
|
|
1232
1728
|
Injectable2({ providedIn: "root" })
|
|
1233
1729
|
];
|
|
1234
1730
|
var _init = __decoratorStart(undefined);
|
|
1235
1731
|
|
|
1236
|
-
class
|
|
1732
|
+
class VoiceWidgetService {
|
|
1237
1733
|
connect(path, options = {}) {
|
|
1238
1734
|
const controller = createVoiceController(path, options);
|
|
1239
|
-
const
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
const recordingErrorSignal = signal2(null);
|
|
1246
|
-
const sessionIdSignal = signal2(controller.sessionId);
|
|
1247
|
-
const statusSignal = signal2(controller.status);
|
|
1248
|
-
const turnsSignal = signal2([]);
|
|
1735
|
+
const viewModelSignal = signal2(createVoiceWidgetViewModel({
|
|
1736
|
+
labels: options.labels,
|
|
1737
|
+
state: controller.getSnapshot(),
|
|
1738
|
+
theme: options.theme,
|
|
1739
|
+
title: options.title
|
|
1740
|
+
}));
|
|
1249
1741
|
const sync = () => {
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
recordingErrorSignal.set(controller.recordingError);
|
|
1257
|
-
sessionIdSignal.set(controller.sessionId);
|
|
1258
|
-
statusSignal.set(controller.status);
|
|
1259
|
-
turnsSignal.set([...controller.turns]);
|
|
1742
|
+
viewModelSignal.set(createVoiceWidgetViewModel({
|
|
1743
|
+
labels: options.labels,
|
|
1744
|
+
state: controller.getSnapshot(),
|
|
1745
|
+
theme: options.theme,
|
|
1746
|
+
title: options.title
|
|
1747
|
+
}));
|
|
1260
1748
|
};
|
|
1261
1749
|
const unsubscribe = controller.subscribe(sync);
|
|
1262
1750
|
sync();
|
|
1263
1751
|
return {
|
|
1264
|
-
assistantAudio: computed2(() => assistantAudioSignal()),
|
|
1265
|
-
assistantTexts: computed2(() => assistantTextsSignal()),
|
|
1266
|
-
bindHTMX: controller.bindHTMX,
|
|
1267
1752
|
close: () => {
|
|
1268
1753
|
unsubscribe();
|
|
1269
1754
|
controller.close();
|
|
1270
1755
|
},
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
sendAudio: (audio) => controller.sendAudio(audio),
|
|
1278
|
-
sessionId: computed2(() => sessionIdSignal()),
|
|
1279
|
-
startRecording: () => controller.startRecording(),
|
|
1280
|
-
status: computed2(() => statusSignal()),
|
|
1281
|
-
stopRecording: () => controller.stopRecording(),
|
|
1282
|
-
toggleRecording: () => controller.toggleRecording(),
|
|
1283
|
-
turns: computed2(() => turnsSignal())
|
|
1756
|
+
endCall: () => controller.close(),
|
|
1757
|
+
getHTML: () => renderVoiceWidgetHTML(viewModelSignal()),
|
|
1758
|
+
mute: () => controller.stopRecording(),
|
|
1759
|
+
startCall: () => controller.startRecording(),
|
|
1760
|
+
unmute: () => controller.startRecording(),
|
|
1761
|
+
viewModel: computed2(() => viewModelSignal())
|
|
1284
1762
|
};
|
|
1285
1763
|
}
|
|
1286
1764
|
}
|
|
1287
|
-
|
|
1288
|
-
__runInitializers(_init, 1,
|
|
1289
|
-
__decoratorMetadata(_init,
|
|
1290
|
-
let
|
|
1765
|
+
VoiceWidgetService = __decorateElement(_init, 0, "VoiceWidgetService", _dec, VoiceWidgetService);
|
|
1766
|
+
__runInitializers(_init, 1, VoiceWidgetService);
|
|
1767
|
+
__decoratorMetadata(_init, VoiceWidgetService);
|
|
1768
|
+
let _VoiceWidgetService = VoiceWidgetService;
|
|
1769
|
+
// src/angular/voice-platform-coverage.service.ts
|
|
1770
|
+
import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
|
|
1771
|
+
|
|
1772
|
+
// src/client/platformCoverage.ts
|
|
1773
|
+
var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
|
|
1774
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1775
|
+
const response = await fetchImpl(path);
|
|
1776
|
+
if (!response.ok) {
|
|
1777
|
+
throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
|
|
1778
|
+
}
|
|
1779
|
+
return await response.json();
|
|
1780
|
+
};
|
|
1781
|
+
var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
|
|
1782
|
+
const listeners = new Set;
|
|
1783
|
+
let closed = false;
|
|
1784
|
+
let timer;
|
|
1785
|
+
let snapshot = {
|
|
1786
|
+
error: null,
|
|
1787
|
+
isLoading: false
|
|
1788
|
+
};
|
|
1789
|
+
const emit = () => {
|
|
1790
|
+
for (const listener of listeners) {
|
|
1791
|
+
listener();
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
const refresh = async () => {
|
|
1795
|
+
if (closed) {
|
|
1796
|
+
return snapshot.report;
|
|
1797
|
+
}
|
|
1798
|
+
snapshot = {
|
|
1799
|
+
...snapshot,
|
|
1800
|
+
error: null,
|
|
1801
|
+
isLoading: true
|
|
1802
|
+
};
|
|
1803
|
+
emit();
|
|
1804
|
+
try {
|
|
1805
|
+
const report = await fetchVoicePlatformCoverage(path, options);
|
|
1806
|
+
snapshot = {
|
|
1807
|
+
error: null,
|
|
1808
|
+
isLoading: false,
|
|
1809
|
+
report,
|
|
1810
|
+
updatedAt: Date.now()
|
|
1811
|
+
};
|
|
1812
|
+
emit();
|
|
1813
|
+
return report;
|
|
1814
|
+
} catch (error) {
|
|
1815
|
+
snapshot = {
|
|
1816
|
+
...snapshot,
|
|
1817
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1818
|
+
isLoading: false
|
|
1819
|
+
};
|
|
1820
|
+
emit();
|
|
1821
|
+
throw error;
|
|
1822
|
+
}
|
|
1823
|
+
};
|
|
1824
|
+
const close = () => {
|
|
1825
|
+
closed = true;
|
|
1826
|
+
if (timer) {
|
|
1827
|
+
clearInterval(timer);
|
|
1828
|
+
timer = undefined;
|
|
1829
|
+
}
|
|
1830
|
+
listeners.clear();
|
|
1831
|
+
};
|
|
1832
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
1833
|
+
timer = setInterval(() => {
|
|
1834
|
+
refresh().catch(() => {});
|
|
1835
|
+
}, options.intervalMs);
|
|
1836
|
+
}
|
|
1837
|
+
return {
|
|
1838
|
+
close,
|
|
1839
|
+
getServerSnapshot: () => snapshot,
|
|
1840
|
+
getSnapshot: () => snapshot,
|
|
1841
|
+
refresh,
|
|
1842
|
+
subscribe: (listener) => {
|
|
1843
|
+
listeners.add(listener);
|
|
1844
|
+
return () => {
|
|
1845
|
+
listeners.delete(listener);
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
};
|
|
1850
|
+
|
|
1851
|
+
// src/angular/voice-platform-coverage.service.ts
|
|
1852
|
+
var _dec = [
|
|
1853
|
+
Injectable3({ providedIn: "root" })
|
|
1854
|
+
];
|
|
1855
|
+
var _init = __decoratorStart(undefined);
|
|
1856
|
+
|
|
1857
|
+
class VoicePlatformCoverageService {
|
|
1858
|
+
connect(path = "/api/voice/platform-coverage", options = {}) {
|
|
1859
|
+
const store = createVoicePlatformCoverageStore(path, options);
|
|
1860
|
+
const errorSignal = signal3(null);
|
|
1861
|
+
const isLoadingSignal = signal3(false);
|
|
1862
|
+
const reportSignal = signal3(undefined);
|
|
1863
|
+
const updatedAtSignal = signal3(undefined);
|
|
1864
|
+
const sync = () => {
|
|
1865
|
+
const snapshot = store.getSnapshot();
|
|
1866
|
+
errorSignal.set(snapshot.error);
|
|
1867
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
1868
|
+
reportSignal.set(snapshot.report);
|
|
1869
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
1870
|
+
};
|
|
1871
|
+
const unsubscribe = store.subscribe(sync);
|
|
1872
|
+
sync();
|
|
1873
|
+
if (typeof window !== "undefined") {
|
|
1874
|
+
store.refresh().catch(() => {});
|
|
1875
|
+
}
|
|
1876
|
+
return {
|
|
1877
|
+
close: () => {
|
|
1878
|
+
unsubscribe();
|
|
1879
|
+
store.close();
|
|
1880
|
+
},
|
|
1881
|
+
error: computed3(() => errorSignal()),
|
|
1882
|
+
isLoading: computed3(() => isLoadingSignal()),
|
|
1883
|
+
refresh: store.refresh,
|
|
1884
|
+
report: computed3(() => reportSignal()),
|
|
1885
|
+
updatedAt: computed3(() => updatedAtSignal())
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
VoicePlatformCoverageService = __decorateElement(_init, 0, "VoicePlatformCoverageService", _dec, VoicePlatformCoverageService);
|
|
1890
|
+
__runInitializers(_init, 1, VoicePlatformCoverageService);
|
|
1891
|
+
__decoratorMetadata(_init, VoicePlatformCoverageService);
|
|
1892
|
+
let _VoicePlatformCoverageService = VoicePlatformCoverageService;
|
|
1893
|
+
// src/angular/voice-proof-trends.service.ts
|
|
1894
|
+
import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
|
|
1895
|
+
|
|
1896
|
+
// src/client/proofTrends.ts
|
|
1897
|
+
var fetchVoiceProofTrends = async (path = "/api/voice/proof-trends", options = {}) => {
|
|
1898
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1899
|
+
const response = await fetchImpl(path);
|
|
1900
|
+
if (!response.ok) {
|
|
1901
|
+
throw new Error(`Voice proof trends failed: HTTP ${response.status}`);
|
|
1902
|
+
}
|
|
1903
|
+
return await response.json();
|
|
1904
|
+
};
|
|
1905
|
+
var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {}) => {
|
|
1906
|
+
const listeners = new Set;
|
|
1907
|
+
let closed = false;
|
|
1908
|
+
let timer;
|
|
1909
|
+
let snapshot = {
|
|
1910
|
+
error: null,
|
|
1911
|
+
isLoading: false
|
|
1912
|
+
};
|
|
1913
|
+
const emit = () => {
|
|
1914
|
+
for (const listener of listeners) {
|
|
1915
|
+
listener();
|
|
1916
|
+
}
|
|
1917
|
+
};
|
|
1918
|
+
const refresh = async () => {
|
|
1919
|
+
if (closed) {
|
|
1920
|
+
return snapshot.report;
|
|
1921
|
+
}
|
|
1922
|
+
snapshot = {
|
|
1923
|
+
...snapshot,
|
|
1924
|
+
error: null,
|
|
1925
|
+
isLoading: true
|
|
1926
|
+
};
|
|
1927
|
+
emit();
|
|
1928
|
+
try {
|
|
1929
|
+
const report = await fetchVoiceProofTrends(path, options);
|
|
1930
|
+
snapshot = {
|
|
1931
|
+
error: null,
|
|
1932
|
+
isLoading: false,
|
|
1933
|
+
report,
|
|
1934
|
+
updatedAt: Date.now()
|
|
1935
|
+
};
|
|
1936
|
+
emit();
|
|
1937
|
+
return report;
|
|
1938
|
+
} catch (error) {
|
|
1939
|
+
snapshot = {
|
|
1940
|
+
...snapshot,
|
|
1941
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1942
|
+
isLoading: false
|
|
1943
|
+
};
|
|
1944
|
+
emit();
|
|
1945
|
+
throw error;
|
|
1946
|
+
}
|
|
1947
|
+
};
|
|
1948
|
+
const close = () => {
|
|
1949
|
+
closed = true;
|
|
1950
|
+
if (timer) {
|
|
1951
|
+
clearInterval(timer);
|
|
1952
|
+
timer = undefined;
|
|
1953
|
+
}
|
|
1954
|
+
listeners.clear();
|
|
1955
|
+
};
|
|
1956
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
1957
|
+
timer = setInterval(() => {
|
|
1958
|
+
refresh().catch(() => {});
|
|
1959
|
+
}, options.intervalMs);
|
|
1960
|
+
}
|
|
1961
|
+
return {
|
|
1962
|
+
close,
|
|
1963
|
+
getServerSnapshot: () => snapshot,
|
|
1964
|
+
getSnapshot: () => snapshot,
|
|
1965
|
+
refresh,
|
|
1966
|
+
subscribe: (listener) => {
|
|
1967
|
+
listeners.add(listener);
|
|
1968
|
+
return () => {
|
|
1969
|
+
listeners.delete(listener);
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
};
|
|
1974
|
+
|
|
1975
|
+
// src/angular/voice-proof-trends.service.ts
|
|
1976
|
+
var _dec = [
|
|
1977
|
+
Injectable4({ providedIn: "root" })
|
|
1978
|
+
];
|
|
1979
|
+
var _init = __decoratorStart(undefined);
|
|
1980
|
+
|
|
1981
|
+
class VoiceProofTrendsService {
|
|
1982
|
+
connect(path = "/api/voice/proof-trends", options = {}) {
|
|
1983
|
+
const store = createVoiceProofTrendsStore(path, options);
|
|
1984
|
+
const errorSignal = signal4(null);
|
|
1985
|
+
const isLoadingSignal = signal4(false);
|
|
1986
|
+
const reportSignal = signal4(undefined);
|
|
1987
|
+
const updatedAtSignal = signal4(undefined);
|
|
1988
|
+
const sync = () => {
|
|
1989
|
+
const snapshot = store.getSnapshot();
|
|
1990
|
+
errorSignal.set(snapshot.error);
|
|
1991
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
1992
|
+
reportSignal.set(snapshot.report);
|
|
1993
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
1994
|
+
};
|
|
1995
|
+
const unsubscribe = store.subscribe(sync);
|
|
1996
|
+
sync();
|
|
1997
|
+
if (typeof window !== "undefined") {
|
|
1998
|
+
store.refresh().catch(() => {});
|
|
1999
|
+
}
|
|
2000
|
+
return {
|
|
2001
|
+
close: () => {
|
|
2002
|
+
unsubscribe();
|
|
2003
|
+
store.close();
|
|
2004
|
+
},
|
|
2005
|
+
error: computed4(() => errorSignal()),
|
|
2006
|
+
isLoading: computed4(() => isLoadingSignal()),
|
|
2007
|
+
refresh: store.refresh,
|
|
2008
|
+
report: computed4(() => reportSignal()),
|
|
2009
|
+
updatedAt: computed4(() => updatedAtSignal())
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
VoiceProofTrendsService = __decorateElement(_init, 0, "VoiceProofTrendsService", _dec, VoiceProofTrendsService);
|
|
2014
|
+
__runInitializers(_init, 1, VoiceProofTrendsService);
|
|
2015
|
+
__decoratorMetadata(_init, VoiceProofTrendsService);
|
|
2016
|
+
let _VoiceProofTrendsService = VoiceProofTrendsService;
|
|
2017
|
+
// src/angular/voice-reconnect-profile-evidence.service.ts
|
|
2018
|
+
import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
|
|
2019
|
+
|
|
2020
|
+
// src/client/reconnectProfileEvidence.ts
|
|
2021
|
+
var fetchVoiceReconnectProfileEvidence = async (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
|
|
2022
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2023
|
+
const response = await fetchImpl(path);
|
|
2024
|
+
if (!response.ok) {
|
|
2025
|
+
throw new Error(`Voice reconnect profile evidence failed: HTTP ${response.status}`);
|
|
2026
|
+
}
|
|
2027
|
+
return await response.json();
|
|
2028
|
+
};
|
|
2029
|
+
var createVoiceReconnectProfileEvidenceStore = (path = "/api/voice/reconnect-profile-evidence", options = {}) => {
|
|
2030
|
+
const listeners = new Set;
|
|
2031
|
+
let closed = false;
|
|
2032
|
+
let timer;
|
|
2033
|
+
let snapshot = {
|
|
2034
|
+
error: null,
|
|
2035
|
+
isLoading: false
|
|
2036
|
+
};
|
|
2037
|
+
const emit = () => {
|
|
2038
|
+
for (const listener of listeners) {
|
|
2039
|
+
listener();
|
|
2040
|
+
}
|
|
2041
|
+
};
|
|
2042
|
+
const refresh = async () => {
|
|
2043
|
+
if (closed) {
|
|
2044
|
+
return snapshot.report;
|
|
2045
|
+
}
|
|
2046
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2047
|
+
emit();
|
|
2048
|
+
try {
|
|
2049
|
+
const report = await fetchVoiceReconnectProfileEvidence(path, options);
|
|
2050
|
+
snapshot = {
|
|
2051
|
+
error: null,
|
|
2052
|
+
isLoading: false,
|
|
2053
|
+
report,
|
|
2054
|
+
updatedAt: Date.now()
|
|
2055
|
+
};
|
|
2056
|
+
emit();
|
|
2057
|
+
return report;
|
|
2058
|
+
} catch (error) {
|
|
2059
|
+
snapshot = {
|
|
2060
|
+
...snapshot,
|
|
2061
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2062
|
+
isLoading: false
|
|
2063
|
+
};
|
|
2064
|
+
emit();
|
|
2065
|
+
throw error;
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
2068
|
+
const close = () => {
|
|
2069
|
+
closed = true;
|
|
2070
|
+
if (timer) {
|
|
2071
|
+
clearInterval(timer);
|
|
2072
|
+
timer = undefined;
|
|
2073
|
+
}
|
|
2074
|
+
listeners.clear();
|
|
2075
|
+
};
|
|
2076
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
2077
|
+
timer = setInterval(() => {
|
|
2078
|
+
refresh().catch(() => {});
|
|
2079
|
+
}, options.intervalMs);
|
|
2080
|
+
}
|
|
2081
|
+
return {
|
|
2082
|
+
close,
|
|
2083
|
+
getServerSnapshot: () => snapshot,
|
|
2084
|
+
getSnapshot: () => snapshot,
|
|
2085
|
+
refresh,
|
|
2086
|
+
subscribe: (listener) => {
|
|
2087
|
+
listeners.add(listener);
|
|
2088
|
+
return () => {
|
|
2089
|
+
listeners.delete(listener);
|
|
2090
|
+
};
|
|
2091
|
+
}
|
|
2092
|
+
};
|
|
2093
|
+
};
|
|
2094
|
+
|
|
2095
|
+
// src/angular/voice-reconnect-profile-evidence.service.ts
|
|
2096
|
+
var _dec = [
|
|
2097
|
+
Injectable5({ providedIn: "root" })
|
|
2098
|
+
];
|
|
2099
|
+
var _init = __decoratorStart(undefined);
|
|
2100
|
+
|
|
2101
|
+
class VoiceReconnectProfileEvidenceService {
|
|
2102
|
+
connect(path = "/api/voice/reconnect-profile-evidence", options = {}) {
|
|
2103
|
+
const store = createVoiceReconnectProfileEvidenceStore(path, options);
|
|
2104
|
+
const errorSignal = signal5(null);
|
|
2105
|
+
const isLoadingSignal = signal5(false);
|
|
2106
|
+
const reportSignal = signal5(undefined);
|
|
2107
|
+
const updatedAtSignal = signal5(undefined);
|
|
2108
|
+
const sync = () => {
|
|
2109
|
+
const snapshot = store.getSnapshot();
|
|
2110
|
+
errorSignal.set(snapshot.error);
|
|
2111
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
2112
|
+
reportSignal.set(snapshot.report);
|
|
2113
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
2114
|
+
};
|
|
2115
|
+
const unsubscribe = store.subscribe(sync);
|
|
2116
|
+
sync();
|
|
2117
|
+
if (typeof window !== "undefined") {
|
|
2118
|
+
store.refresh().catch(() => {});
|
|
2119
|
+
}
|
|
2120
|
+
return {
|
|
2121
|
+
close: () => {
|
|
2122
|
+
unsubscribe();
|
|
2123
|
+
store.close();
|
|
2124
|
+
},
|
|
2125
|
+
error: computed5(() => errorSignal()),
|
|
2126
|
+
isLoading: computed5(() => isLoadingSignal()),
|
|
2127
|
+
refresh: store.refresh,
|
|
2128
|
+
report: computed5(() => reportSignal()),
|
|
2129
|
+
updatedAt: computed5(() => updatedAtSignal())
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
VoiceReconnectProfileEvidenceService = __decorateElement(_init, 0, "VoiceReconnectProfileEvidenceService", _dec, VoiceReconnectProfileEvidenceService);
|
|
2134
|
+
__runInitializers(_init, 1, VoiceReconnectProfileEvidenceService);
|
|
2135
|
+
__decoratorMetadata(_init, VoiceReconnectProfileEvidenceService);
|
|
2136
|
+
let _VoiceReconnectProfileEvidenceService = VoiceReconnectProfileEvidenceService;
|
|
2137
|
+
// src/angular/voice-call-debugger.service.ts
|
|
2138
|
+
import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
|
|
2139
|
+
|
|
2140
|
+
// src/client/callDebugger.ts
|
|
2141
|
+
var fetchVoiceCallDebugger = async (path, options = {}) => {
|
|
2142
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2143
|
+
const response = await fetchImpl(path);
|
|
2144
|
+
if (!response.ok) {
|
|
2145
|
+
throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
|
|
2146
|
+
}
|
|
2147
|
+
return await response.json();
|
|
2148
|
+
};
|
|
2149
|
+
var createVoiceCallDebuggerStore = (path, options = {}) => {
|
|
2150
|
+
const listeners = new Set;
|
|
2151
|
+
let closed = false;
|
|
2152
|
+
let timer;
|
|
2153
|
+
let snapshot = {
|
|
2154
|
+
error: null,
|
|
2155
|
+
isLoading: false
|
|
2156
|
+
};
|
|
2157
|
+
const emit = () => {
|
|
2158
|
+
for (const listener of listeners) {
|
|
2159
|
+
listener();
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
2162
|
+
const refresh = async () => {
|
|
2163
|
+
if (closed) {
|
|
2164
|
+
return snapshot.report;
|
|
2165
|
+
}
|
|
2166
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2167
|
+
emit();
|
|
2168
|
+
try {
|
|
2169
|
+
const report = await fetchVoiceCallDebugger(path, options);
|
|
2170
|
+
snapshot = {
|
|
2171
|
+
error: null,
|
|
2172
|
+
isLoading: false,
|
|
2173
|
+
report,
|
|
2174
|
+
updatedAt: Date.now()
|
|
2175
|
+
};
|
|
2176
|
+
emit();
|
|
2177
|
+
return report;
|
|
2178
|
+
} catch (error) {
|
|
2179
|
+
snapshot = {
|
|
2180
|
+
...snapshot,
|
|
2181
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2182
|
+
isLoading: false
|
|
2183
|
+
};
|
|
2184
|
+
emit();
|
|
2185
|
+
throw error;
|
|
2186
|
+
}
|
|
2187
|
+
};
|
|
2188
|
+
const close = () => {
|
|
2189
|
+
closed = true;
|
|
2190
|
+
if (timer) {
|
|
2191
|
+
clearInterval(timer);
|
|
2192
|
+
timer = undefined;
|
|
2193
|
+
}
|
|
2194
|
+
listeners.clear();
|
|
2195
|
+
};
|
|
2196
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
2197
|
+
timer = setInterval(() => {
|
|
2198
|
+
refresh().catch(() => {});
|
|
2199
|
+
}, options.intervalMs);
|
|
2200
|
+
}
|
|
2201
|
+
return {
|
|
2202
|
+
close,
|
|
2203
|
+
getServerSnapshot: () => snapshot,
|
|
2204
|
+
getSnapshot: () => snapshot,
|
|
2205
|
+
refresh,
|
|
2206
|
+
subscribe: (listener) => {
|
|
2207
|
+
listeners.add(listener);
|
|
2208
|
+
return () => {
|
|
2209
|
+
listeners.delete(listener);
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
};
|
|
2213
|
+
};
|
|
2214
|
+
|
|
2215
|
+
// src/angular/voice-call-debugger.service.ts
|
|
2216
|
+
var _dec = [
|
|
2217
|
+
Injectable6({ providedIn: "root" })
|
|
2218
|
+
];
|
|
2219
|
+
var _init = __decoratorStart(undefined);
|
|
2220
|
+
|
|
2221
|
+
class VoiceCallDebuggerService {
|
|
2222
|
+
connect(path, options = {}) {
|
|
2223
|
+
const store = createVoiceCallDebuggerStore(path, options);
|
|
2224
|
+
const errorSignal = signal6(null);
|
|
2225
|
+
const isLoadingSignal = signal6(false);
|
|
2226
|
+
const reportSignal = signal6(undefined);
|
|
2227
|
+
const updatedAtSignal = signal6(undefined);
|
|
2228
|
+
const sync = () => {
|
|
2229
|
+
const state = store.getSnapshot();
|
|
2230
|
+
errorSignal.set(state.error);
|
|
2231
|
+
isLoadingSignal.set(state.isLoading);
|
|
2232
|
+
reportSignal.set(state.report);
|
|
2233
|
+
updatedAtSignal.set(state.updatedAt);
|
|
2234
|
+
};
|
|
2235
|
+
const unsubscribe = store.subscribe(sync);
|
|
2236
|
+
sync();
|
|
2237
|
+
store.refresh().catch(() => {});
|
|
2238
|
+
return {
|
|
2239
|
+
close: () => {
|
|
2240
|
+
unsubscribe();
|
|
2241
|
+
store.close();
|
|
2242
|
+
},
|
|
2243
|
+
error: computed6(() => errorSignal()),
|
|
2244
|
+
isLoading: computed6(() => isLoadingSignal()),
|
|
2245
|
+
refresh: store.refresh,
|
|
2246
|
+
report: computed6(() => reportSignal()),
|
|
2247
|
+
updatedAt: computed6(() => updatedAtSignal())
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
VoiceCallDebuggerService = __decorateElement(_init, 0, "VoiceCallDebuggerService", _dec, VoiceCallDebuggerService);
|
|
2252
|
+
__runInitializers(_init, 1, VoiceCallDebuggerService);
|
|
2253
|
+
__decoratorMetadata(_init, VoiceCallDebuggerService);
|
|
2254
|
+
let _VoiceCallDebuggerService = VoiceCallDebuggerService;
|
|
2255
|
+
// src/angular/voice-session-snapshot.service.ts
|
|
2256
|
+
import { computed as computed7, Injectable as Injectable7, signal as signal7 } from "@angular/core";
|
|
2257
|
+
|
|
2258
|
+
// src/client/sessionSnapshot.ts
|
|
2259
|
+
var withTurnId = (path, turnId) => {
|
|
2260
|
+
if (!turnId) {
|
|
2261
|
+
return path;
|
|
2262
|
+
}
|
|
2263
|
+
const url = new URL(path, "http://absolutejs.local");
|
|
2264
|
+
url.searchParams.set("turnId", turnId);
|
|
2265
|
+
return `${url.pathname}${url.search}`;
|
|
2266
|
+
};
|
|
2267
|
+
var fetchVoiceSessionSnapshot = async (path, options = {}) => {
|
|
2268
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2269
|
+
const response = await fetchImpl(withTurnId(path, options.turnId));
|
|
2270
|
+
if (!response.ok) {
|
|
2271
|
+
throw new Error(`Voice session snapshot failed: HTTP ${response.status}`);
|
|
2272
|
+
}
|
|
2273
|
+
return await response.json();
|
|
2274
|
+
};
|
|
2275
|
+
var createVoiceSessionSnapshotStore = (path, options = {}) => {
|
|
2276
|
+
const listeners = new Set;
|
|
2277
|
+
let closed = false;
|
|
2278
|
+
let timer;
|
|
2279
|
+
let snapshot = {
|
|
2280
|
+
error: null,
|
|
2281
|
+
isLoading: false
|
|
2282
|
+
};
|
|
2283
|
+
const emit = () => {
|
|
2284
|
+
for (const listener of listeners) {
|
|
2285
|
+
listener();
|
|
2286
|
+
}
|
|
2287
|
+
};
|
|
2288
|
+
const refresh = async () => {
|
|
2289
|
+
if (closed) {
|
|
2290
|
+
return snapshot.snapshot;
|
|
2291
|
+
}
|
|
2292
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2293
|
+
emit();
|
|
2294
|
+
try {
|
|
2295
|
+
const next = await fetchVoiceSessionSnapshot(path, options);
|
|
2296
|
+
snapshot = {
|
|
2297
|
+
error: null,
|
|
2298
|
+
isLoading: false,
|
|
2299
|
+
snapshot: next,
|
|
2300
|
+
updatedAt: Date.now()
|
|
2301
|
+
};
|
|
2302
|
+
emit();
|
|
2303
|
+
return next;
|
|
2304
|
+
} catch (error) {
|
|
2305
|
+
snapshot = {
|
|
2306
|
+
...snapshot,
|
|
2307
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2308
|
+
isLoading: false
|
|
2309
|
+
};
|
|
2310
|
+
emit();
|
|
2311
|
+
throw error;
|
|
2312
|
+
}
|
|
2313
|
+
};
|
|
2314
|
+
const download = () => {
|
|
2315
|
+
const current = snapshot.snapshot;
|
|
2316
|
+
if (current === undefined) {
|
|
2317
|
+
throw new Error("Voice session snapshot has not been loaded.");
|
|
2318
|
+
}
|
|
2319
|
+
return new Blob([JSON.stringify(current, null, 2)], {
|
|
2320
|
+
type: "application/json"
|
|
2321
|
+
});
|
|
2322
|
+
};
|
|
2323
|
+
const close = () => {
|
|
2324
|
+
closed = true;
|
|
2325
|
+
if (timer) {
|
|
2326
|
+
clearInterval(timer);
|
|
2327
|
+
timer = undefined;
|
|
2328
|
+
}
|
|
2329
|
+
listeners.clear();
|
|
2330
|
+
};
|
|
2331
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
2332
|
+
timer = setInterval(() => {
|
|
2333
|
+
refresh().catch(() => {});
|
|
2334
|
+
}, options.intervalMs);
|
|
2335
|
+
}
|
|
2336
|
+
return {
|
|
2337
|
+
close,
|
|
2338
|
+
download,
|
|
2339
|
+
getServerSnapshot: () => snapshot,
|
|
2340
|
+
getSnapshot: () => snapshot,
|
|
2341
|
+
refresh,
|
|
2342
|
+
subscribe: (listener) => {
|
|
2343
|
+
listeners.add(listener);
|
|
2344
|
+
return () => {
|
|
2345
|
+
listeners.delete(listener);
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
};
|
|
2349
|
+
};
|
|
2350
|
+
|
|
2351
|
+
// src/angular/voice-session-snapshot.service.ts
|
|
2352
|
+
var _dec = [
|
|
2353
|
+
Injectable7({ providedIn: "root" })
|
|
2354
|
+
];
|
|
2355
|
+
var _init = __decoratorStart(undefined);
|
|
2356
|
+
|
|
2357
|
+
class VoiceSessionSnapshotService {
|
|
2358
|
+
connect(path, options = {}) {
|
|
2359
|
+
const store = createVoiceSessionSnapshotStore(path, options);
|
|
2360
|
+
const errorSignal = signal7(null);
|
|
2361
|
+
const isLoadingSignal = signal7(false);
|
|
2362
|
+
const snapshotSignal = signal7(undefined);
|
|
2363
|
+
const updatedAtSignal = signal7(undefined);
|
|
2364
|
+
const sync = () => {
|
|
2365
|
+
const state = store.getSnapshot();
|
|
2366
|
+
errorSignal.set(state.error);
|
|
2367
|
+
isLoadingSignal.set(state.isLoading);
|
|
2368
|
+
snapshotSignal.set(state.snapshot);
|
|
2369
|
+
updatedAtSignal.set(state.updatedAt);
|
|
2370
|
+
};
|
|
2371
|
+
const unsubscribe = store.subscribe(sync);
|
|
2372
|
+
sync();
|
|
2373
|
+
store.refresh().catch(() => {});
|
|
2374
|
+
return {
|
|
2375
|
+
close: () => {
|
|
2376
|
+
unsubscribe();
|
|
2377
|
+
store.close();
|
|
2378
|
+
},
|
|
2379
|
+
download: store.download,
|
|
2380
|
+
error: computed7(() => errorSignal()),
|
|
2381
|
+
isLoading: computed7(() => isLoadingSignal()),
|
|
2382
|
+
refresh: store.refresh,
|
|
2383
|
+
snapshot: computed7(() => snapshotSignal()),
|
|
2384
|
+
updatedAt: computed7(() => updatedAtSignal())
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
VoiceSessionSnapshotService = __decorateElement(_init, 0, "VoiceSessionSnapshotService", _dec, VoiceSessionSnapshotService);
|
|
2389
|
+
__runInitializers(_init, 1, VoiceSessionSnapshotService);
|
|
2390
|
+
__decoratorMetadata(_init, VoiceSessionSnapshotService);
|
|
2391
|
+
let _VoiceSessionSnapshotService = VoiceSessionSnapshotService;
|
|
2392
|
+
// src/angular/voice-session-observability.service.ts
|
|
2393
|
+
import { computed as computed8, Injectable as Injectable8, signal as signal8 } from "@angular/core";
|
|
2394
|
+
|
|
2395
|
+
// src/client/sessionObservability.ts
|
|
2396
|
+
var fetchVoiceSessionObservability = async (path, options = {}) => {
|
|
2397
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2398
|
+
const response = await fetchImpl(path);
|
|
2399
|
+
if (!response.ok) {
|
|
2400
|
+
throw new Error(`Voice session observability failed: HTTP ${response.status}`);
|
|
2401
|
+
}
|
|
2402
|
+
return await response.json();
|
|
2403
|
+
};
|
|
2404
|
+
var createVoiceSessionObservabilityStore = (path, options = {}) => {
|
|
2405
|
+
const listeners = new Set;
|
|
2406
|
+
let closed = false;
|
|
2407
|
+
let timer;
|
|
2408
|
+
let snapshot = {
|
|
2409
|
+
error: null,
|
|
2410
|
+
isLoading: false,
|
|
2411
|
+
report: null
|
|
2412
|
+
};
|
|
2413
|
+
const emit = () => {
|
|
2414
|
+
for (const listener of listeners) {
|
|
2415
|
+
listener();
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
const refresh = async () => {
|
|
2419
|
+
if (closed) {
|
|
2420
|
+
return snapshot.report;
|
|
2421
|
+
}
|
|
2422
|
+
snapshot = {
|
|
2423
|
+
...snapshot,
|
|
2424
|
+
error: null,
|
|
2425
|
+
isLoading: true
|
|
2426
|
+
};
|
|
2427
|
+
emit();
|
|
2428
|
+
try {
|
|
2429
|
+
const report = await fetchVoiceSessionObservability(path, options);
|
|
2430
|
+
snapshot = {
|
|
2431
|
+
error: null,
|
|
2432
|
+
isLoading: false,
|
|
2433
|
+
report,
|
|
2434
|
+
updatedAt: Date.now()
|
|
2435
|
+
};
|
|
2436
|
+
emit();
|
|
2437
|
+
return report;
|
|
2438
|
+
} catch (error) {
|
|
2439
|
+
snapshot = {
|
|
2440
|
+
...snapshot,
|
|
2441
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2442
|
+
isLoading: false
|
|
2443
|
+
};
|
|
2444
|
+
emit();
|
|
2445
|
+
throw error;
|
|
2446
|
+
}
|
|
2447
|
+
};
|
|
2448
|
+
const close = () => {
|
|
2449
|
+
closed = true;
|
|
2450
|
+
if (timer) {
|
|
2451
|
+
clearInterval(timer);
|
|
2452
|
+
timer = undefined;
|
|
2453
|
+
}
|
|
2454
|
+
listeners.clear();
|
|
2455
|
+
};
|
|
2456
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
2457
|
+
timer = setInterval(() => {
|
|
2458
|
+
refresh().catch(() => {});
|
|
2459
|
+
}, options.intervalMs);
|
|
2460
|
+
}
|
|
2461
|
+
return {
|
|
2462
|
+
close,
|
|
2463
|
+
getServerSnapshot: () => snapshot,
|
|
2464
|
+
getSnapshot: () => snapshot,
|
|
2465
|
+
refresh,
|
|
2466
|
+
subscribe: (listener) => {
|
|
2467
|
+
listeners.add(listener);
|
|
2468
|
+
return () => {
|
|
2469
|
+
listeners.delete(listener);
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2472
|
+
};
|
|
2473
|
+
};
|
|
2474
|
+
|
|
2475
|
+
// src/angular/voice-session-observability.service.ts
|
|
2476
|
+
var _dec = [
|
|
2477
|
+
Injectable8({ providedIn: "root" })
|
|
2478
|
+
];
|
|
2479
|
+
var _init = __decoratorStart(undefined);
|
|
2480
|
+
|
|
2481
|
+
class VoiceSessionObservabilityService {
|
|
2482
|
+
connect(path = "/api/voice/session-observability/latest", options = {}) {
|
|
2483
|
+
const store = createVoiceSessionObservabilityStore(path, options);
|
|
2484
|
+
const errorSignal = signal8(null);
|
|
2485
|
+
const isLoadingSignal = signal8(false);
|
|
2486
|
+
const reportSignal = signal8(null);
|
|
2487
|
+
const updatedAtSignal = signal8(undefined);
|
|
2488
|
+
const sync = () => {
|
|
2489
|
+
const snapshot = store.getSnapshot();
|
|
2490
|
+
errorSignal.set(snapshot.error);
|
|
2491
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
2492
|
+
reportSignal.set(snapshot.report);
|
|
2493
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
2494
|
+
};
|
|
2495
|
+
const unsubscribe = store.subscribe(sync);
|
|
2496
|
+
sync();
|
|
2497
|
+
store.refresh().catch(() => {});
|
|
2498
|
+
return {
|
|
2499
|
+
close: () => {
|
|
2500
|
+
unsubscribe();
|
|
2501
|
+
store.close();
|
|
2502
|
+
},
|
|
2503
|
+
error: computed8(() => errorSignal()),
|
|
2504
|
+
isLoading: computed8(() => isLoadingSignal()),
|
|
2505
|
+
refresh: store.refresh,
|
|
2506
|
+
report: computed8(() => reportSignal()),
|
|
2507
|
+
updatedAt: computed8(() => updatedAtSignal())
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
VoiceSessionObservabilityService = __decorateElement(_init, 0, "VoiceSessionObservabilityService", _dec, VoiceSessionObservabilityService);
|
|
2512
|
+
__runInitializers(_init, 1, VoiceSessionObservabilityService);
|
|
2513
|
+
__decoratorMetadata(_init, VoiceSessionObservabilityService);
|
|
2514
|
+
let _VoiceSessionObservabilityService = VoiceSessionObservabilityService;
|
|
2515
|
+
// src/angular/voice-profile-comparison.service.ts
|
|
2516
|
+
import { computed as computed9, Injectable as Injectable9, signal as signal9 } from "@angular/core";
|
|
2517
|
+
|
|
2518
|
+
// src/client/profileComparison.ts
|
|
2519
|
+
var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
|
|
2520
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2521
|
+
const response = await fetchImpl(path);
|
|
2522
|
+
if (!response.ok) {
|
|
2523
|
+
throw new Error(`Voice profile comparison failed: HTTP ${response.status}`);
|
|
2524
|
+
}
|
|
2525
|
+
return await response.json();
|
|
2526
|
+
};
|
|
2527
|
+
var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-history", options = {}) => {
|
|
2528
|
+
const listeners = new Set;
|
|
2529
|
+
let closed = false;
|
|
2530
|
+
let timer;
|
|
2531
|
+
let snapshot = {
|
|
2532
|
+
error: null,
|
|
2533
|
+
isLoading: false
|
|
2534
|
+
};
|
|
2535
|
+
const emit = () => {
|
|
2536
|
+
for (const listener of listeners) {
|
|
2537
|
+
listener();
|
|
2538
|
+
}
|
|
2539
|
+
};
|
|
2540
|
+
const refresh = async () => {
|
|
2541
|
+
if (closed) {
|
|
2542
|
+
return snapshot.report;
|
|
2543
|
+
}
|
|
2544
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2545
|
+
emit();
|
|
2546
|
+
try {
|
|
2547
|
+
const report = await fetchVoiceProfileComparison(path, options);
|
|
2548
|
+
snapshot = {
|
|
2549
|
+
error: null,
|
|
2550
|
+
isLoading: false,
|
|
2551
|
+
report,
|
|
2552
|
+
updatedAt: Date.now()
|
|
2553
|
+
};
|
|
2554
|
+
emit();
|
|
2555
|
+
return report;
|
|
2556
|
+
} catch (error) {
|
|
2557
|
+
snapshot = {
|
|
2558
|
+
...snapshot,
|
|
2559
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2560
|
+
isLoading: false
|
|
2561
|
+
};
|
|
2562
|
+
emit();
|
|
2563
|
+
throw error;
|
|
2564
|
+
}
|
|
2565
|
+
};
|
|
2566
|
+
const close = () => {
|
|
2567
|
+
closed = true;
|
|
2568
|
+
if (timer) {
|
|
2569
|
+
clearInterval(timer);
|
|
2570
|
+
timer = undefined;
|
|
2571
|
+
}
|
|
2572
|
+
listeners.clear();
|
|
2573
|
+
};
|
|
2574
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
2575
|
+
timer = setInterval(() => {
|
|
2576
|
+
refresh().catch(() => {});
|
|
2577
|
+
}, options.intervalMs);
|
|
2578
|
+
}
|
|
2579
|
+
return {
|
|
2580
|
+
close,
|
|
2581
|
+
getServerSnapshot: () => snapshot,
|
|
2582
|
+
getSnapshot: () => snapshot,
|
|
2583
|
+
refresh,
|
|
2584
|
+
subscribe: (listener) => {
|
|
2585
|
+
listeners.add(listener);
|
|
2586
|
+
return () => {
|
|
2587
|
+
listeners.delete(listener);
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2591
|
+
};
|
|
2592
|
+
|
|
2593
|
+
// src/angular/voice-profile-comparison.service.ts
|
|
2594
|
+
var _dec = [
|
|
2595
|
+
Injectable9({ providedIn: "root" })
|
|
2596
|
+
];
|
|
2597
|
+
var _init = __decoratorStart(undefined);
|
|
2598
|
+
|
|
2599
|
+
class VoiceProfileComparisonService {
|
|
2600
|
+
connect(path = "/api/voice/real-call-profile-history", options = {}) {
|
|
2601
|
+
const store = createVoiceProfileComparisonStore(path, options);
|
|
2602
|
+
const errorSignal = signal9(null);
|
|
2603
|
+
const isLoadingSignal = signal9(false);
|
|
2604
|
+
const reportSignal = signal9(undefined);
|
|
2605
|
+
const updatedAtSignal = signal9(undefined);
|
|
2606
|
+
const sync = () => {
|
|
2607
|
+
const snapshot = store.getSnapshot();
|
|
2608
|
+
errorSignal.set(snapshot.error);
|
|
2609
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
2610
|
+
reportSignal.set(snapshot.report);
|
|
2611
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
2612
|
+
};
|
|
2613
|
+
const unsubscribe = store.subscribe(sync);
|
|
2614
|
+
sync();
|
|
2615
|
+
if (typeof window !== "undefined") {
|
|
2616
|
+
store.refresh().catch(() => {});
|
|
2617
|
+
}
|
|
2618
|
+
return {
|
|
2619
|
+
close: () => {
|
|
2620
|
+
unsubscribe();
|
|
2621
|
+
store.close();
|
|
2622
|
+
},
|
|
2623
|
+
error: computed9(() => errorSignal()),
|
|
2624
|
+
isLoading: computed9(() => isLoadingSignal()),
|
|
2625
|
+
refresh: store.refresh,
|
|
2626
|
+
report: computed9(() => reportSignal()),
|
|
2627
|
+
updatedAt: computed9(() => updatedAtSignal())
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
VoiceProfileComparisonService = __decorateElement(_init, 0, "VoiceProfileComparisonService", _dec, VoiceProfileComparisonService);
|
|
2632
|
+
__runInitializers(_init, 1, VoiceProfileComparisonService);
|
|
2633
|
+
__decoratorMetadata(_init, VoiceProfileComparisonService);
|
|
2634
|
+
let _VoiceProfileComparisonService = VoiceProfileComparisonService;
|
|
2635
|
+
// src/angular/voice-readiness-failures.service.ts
|
|
2636
|
+
import { computed as computed10, Injectable as Injectable10, signal as signal10 } from "@angular/core";
|
|
2637
|
+
|
|
2638
|
+
// src/client/readinessFailures.ts
|
|
2639
|
+
var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
|
|
2640
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2641
|
+
const response = await fetchImpl(path);
|
|
2642
|
+
if (!response.ok) {
|
|
2643
|
+
throw new Error(`Voice readiness failed: HTTP ${response.status}`);
|
|
2644
|
+
}
|
|
2645
|
+
return await response.json();
|
|
2646
|
+
};
|
|
2647
|
+
var createVoiceReadinessFailuresStore = (path = "/api/production-readiness", options = {}) => {
|
|
2648
|
+
const listeners = new Set;
|
|
2649
|
+
let closed = false;
|
|
2650
|
+
let timer;
|
|
2651
|
+
let snapshot = {
|
|
2652
|
+
error: null,
|
|
2653
|
+
isLoading: false
|
|
2654
|
+
};
|
|
2655
|
+
const emit = () => {
|
|
2656
|
+
for (const listener of listeners) {
|
|
2657
|
+
listener();
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
const refresh = async () => {
|
|
2661
|
+
if (closed) {
|
|
2662
|
+
return snapshot.report;
|
|
2663
|
+
}
|
|
2664
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2665
|
+
emit();
|
|
2666
|
+
try {
|
|
2667
|
+
const report = await fetchVoiceReadinessFailures(path, options);
|
|
2668
|
+
snapshot = {
|
|
2669
|
+
error: null,
|
|
2670
|
+
isLoading: false,
|
|
2671
|
+
report,
|
|
2672
|
+
updatedAt: Date.now()
|
|
2673
|
+
};
|
|
2674
|
+
emit();
|
|
2675
|
+
return report;
|
|
2676
|
+
} catch (error) {
|
|
2677
|
+
snapshot = {
|
|
2678
|
+
...snapshot,
|
|
2679
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2680
|
+
isLoading: false
|
|
2681
|
+
};
|
|
2682
|
+
emit();
|
|
2683
|
+
throw error;
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
const close = () => {
|
|
2687
|
+
closed = true;
|
|
2688
|
+
if (timer) {
|
|
2689
|
+
clearInterval(timer);
|
|
2690
|
+
timer = undefined;
|
|
2691
|
+
}
|
|
2692
|
+
listeners.clear();
|
|
2693
|
+
};
|
|
2694
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
2695
|
+
timer = setInterval(() => {
|
|
2696
|
+
refresh().catch(() => {});
|
|
2697
|
+
}, options.intervalMs);
|
|
2698
|
+
}
|
|
2699
|
+
return {
|
|
2700
|
+
close,
|
|
2701
|
+
getServerSnapshot: () => snapshot,
|
|
2702
|
+
getSnapshot: () => snapshot,
|
|
2703
|
+
refresh,
|
|
2704
|
+
subscribe: (listener) => {
|
|
2705
|
+
listeners.add(listener);
|
|
2706
|
+
return () => {
|
|
2707
|
+
listeners.delete(listener);
|
|
2708
|
+
};
|
|
2709
|
+
}
|
|
2710
|
+
};
|
|
2711
|
+
};
|
|
2712
|
+
|
|
2713
|
+
// src/angular/voice-readiness-failures.service.ts
|
|
2714
|
+
var _dec = [
|
|
2715
|
+
Injectable10({ providedIn: "root" })
|
|
2716
|
+
];
|
|
2717
|
+
var _init = __decoratorStart(undefined);
|
|
2718
|
+
|
|
2719
|
+
class VoiceReadinessFailuresService {
|
|
2720
|
+
connect(path = "/api/production-readiness", options = {}) {
|
|
2721
|
+
const store = createVoiceReadinessFailuresStore(path, options);
|
|
2722
|
+
const errorSignal = signal10(null);
|
|
2723
|
+
const isLoadingSignal = signal10(false);
|
|
2724
|
+
const reportSignal = signal10(undefined);
|
|
2725
|
+
const updatedAtSignal = signal10(undefined);
|
|
2726
|
+
const sync = () => {
|
|
2727
|
+
const snapshot = store.getSnapshot();
|
|
2728
|
+
errorSignal.set(snapshot.error);
|
|
2729
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
2730
|
+
reportSignal.set(snapshot.report);
|
|
2731
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
2732
|
+
};
|
|
2733
|
+
const unsubscribe = store.subscribe(sync);
|
|
2734
|
+
sync();
|
|
2735
|
+
if (typeof window !== "undefined") {
|
|
2736
|
+
store.refresh().catch(() => {});
|
|
2737
|
+
}
|
|
2738
|
+
return {
|
|
2739
|
+
close: () => {
|
|
2740
|
+
unsubscribe();
|
|
2741
|
+
store.close();
|
|
2742
|
+
},
|
|
2743
|
+
error: computed10(() => errorSignal()),
|
|
2744
|
+
explanations: computed10(() => reportSignal()?.checks.filter((check) => check.status !== "pass" && !!check.gateExplanation) ?? []),
|
|
2745
|
+
isLoading: computed10(() => isLoadingSignal()),
|
|
2746
|
+
refresh: store.refresh,
|
|
2747
|
+
report: computed10(() => reportSignal()),
|
|
2748
|
+
updatedAt: computed10(() => updatedAtSignal())
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
VoiceReadinessFailuresService = __decorateElement(_init, 0, "VoiceReadinessFailuresService", _dec, VoiceReadinessFailuresService);
|
|
2753
|
+
__runInitializers(_init, 1, VoiceReadinessFailuresService);
|
|
2754
|
+
__decoratorMetadata(_init, VoiceReadinessFailuresService);
|
|
2755
|
+
let _VoiceReadinessFailuresService = VoiceReadinessFailuresService;
|
|
2756
|
+
// src/angular/voice-ops-action-center.service.ts
|
|
2757
|
+
import { computed as computed11, Injectable as Injectable11, signal as signal11 } from "@angular/core";
|
|
2758
|
+
|
|
2759
|
+
// src/client/opsActionCenter.ts
|
|
2760
|
+
var recordVoiceOpsActionResult = async (result, options = {}) => {
|
|
2761
|
+
if (options.auditPath === false) {
|
|
2762
|
+
return;
|
|
2763
|
+
}
|
|
2764
|
+
const path = options.auditPath ?? "/api/voice/ops-actions/audit";
|
|
2765
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2766
|
+
const response = await fetchImpl(path, {
|
|
2767
|
+
body: JSON.stringify(result),
|
|
2768
|
+
headers: {
|
|
2769
|
+
"Content-Type": "application/json"
|
|
2770
|
+
},
|
|
2771
|
+
method: "POST"
|
|
2772
|
+
});
|
|
2773
|
+
if (!response.ok) {
|
|
2774
|
+
throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
|
|
2775
|
+
}
|
|
2776
|
+
};
|
|
2777
|
+
var createVoiceOpsActionCenterActions = (options = {}) => {
|
|
2778
|
+
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
2779
|
+
const actions = [];
|
|
2780
|
+
if (options.includeProductionReadiness !== false) {
|
|
2781
|
+
actions.push({
|
|
2782
|
+
description: "Refresh the production readiness report.",
|
|
2783
|
+
id: "production-readiness",
|
|
2784
|
+
label: "Refresh readiness",
|
|
2785
|
+
method: "GET",
|
|
2786
|
+
path: options.productionReadinessPath ?? "/api/production-readiness"
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
if (options.includeDeliveryRuntime !== false) {
|
|
2790
|
+
actions.push({
|
|
2791
|
+
description: "Drain pending and failed audit/trace deliveries.",
|
|
2792
|
+
id: "delivery-runtime.tick",
|
|
2793
|
+
label: "Tick delivery workers",
|
|
2794
|
+
method: "POST",
|
|
2795
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
|
|
2796
|
+
}, {
|
|
2797
|
+
description: "Move reviewed dead letters back to live delivery queues.",
|
|
2798
|
+
id: "delivery-runtime.requeue-dead-letters",
|
|
2799
|
+
label: "Requeue dead letters",
|
|
2800
|
+
method: "POST",
|
|
2801
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
if (options.includeTurnLatencyProof !== false) {
|
|
2805
|
+
actions.push({
|
|
2806
|
+
description: "Run the synthetic turn latency proof.",
|
|
2807
|
+
id: "turn-latency.proof",
|
|
2808
|
+
label: "Run latency proof",
|
|
2809
|
+
method: "POST",
|
|
2810
|
+
path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
|
|
2811
|
+
});
|
|
2812
|
+
}
|
|
2813
|
+
if (options.includeProviderSimulation !== false) {
|
|
2814
|
+
const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
|
|
2815
|
+
for (const provider of options.providers ?? []) {
|
|
2816
|
+
actions.push({
|
|
2817
|
+
description: `Simulate ${provider} provider failure.`,
|
|
2818
|
+
id: `provider.${provider}.failure`,
|
|
2819
|
+
label: `Simulate ${provider} failure`,
|
|
2820
|
+
method: "POST",
|
|
2821
|
+
path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
|
|
2822
|
+
}, {
|
|
2823
|
+
description: `Mark ${provider} provider recovered.`,
|
|
2824
|
+
id: `provider.${provider}.recovery`,
|
|
2825
|
+
label: `Recover ${provider}`,
|
|
2826
|
+
method: "POST",
|
|
2827
|
+
path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
|
|
2828
|
+
});
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
return actions;
|
|
2832
|
+
};
|
|
2833
|
+
var runVoiceOpsAction = async (action, options = {}) => {
|
|
2834
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2835
|
+
const response = await fetchImpl(action.path, {
|
|
2836
|
+
method: action.method ?? "POST"
|
|
2837
|
+
});
|
|
2838
|
+
const body = await response.json().catch(() => null);
|
|
2839
|
+
if (!response.ok) {
|
|
2840
|
+
const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
|
|
2841
|
+
throw new Error(message);
|
|
2842
|
+
}
|
|
2843
|
+
return {
|
|
2844
|
+
actionId: action.id,
|
|
2845
|
+
body,
|
|
2846
|
+
ok: response.ok,
|
|
2847
|
+
ranAt: Date.now(),
|
|
2848
|
+
status: response.status
|
|
2849
|
+
};
|
|
2850
|
+
};
|
|
2851
|
+
var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
2852
|
+
const listeners = new Set;
|
|
2853
|
+
let closed = false;
|
|
2854
|
+
let timer;
|
|
2855
|
+
let snapshot = {
|
|
2856
|
+
actions: options.actions ?? createVoiceOpsActionCenterActions(),
|
|
2857
|
+
error: null,
|
|
2858
|
+
isRunning: false
|
|
2859
|
+
};
|
|
2860
|
+
const emit = () => {
|
|
2861
|
+
for (const listener of listeners) {
|
|
2862
|
+
listener();
|
|
2863
|
+
}
|
|
2864
|
+
};
|
|
2865
|
+
const setActions = (actions) => {
|
|
2866
|
+
snapshot = { ...snapshot, actions, updatedAt: Date.now() };
|
|
2867
|
+
emit();
|
|
2868
|
+
};
|
|
2869
|
+
const run = async (actionId) => {
|
|
2870
|
+
if (closed) {
|
|
2871
|
+
return snapshot.lastResult;
|
|
2872
|
+
}
|
|
2873
|
+
const action = snapshot.actions.find((item) => item.id === actionId);
|
|
2874
|
+
if (!action) {
|
|
2875
|
+
throw new Error(`Voice ops action "${actionId}" is not configured.`);
|
|
2876
|
+
}
|
|
2877
|
+
if (action.disabled) {
|
|
2878
|
+
throw new Error(`Voice ops action "${actionId}" is disabled.`);
|
|
2879
|
+
}
|
|
2880
|
+
snapshot = {
|
|
2881
|
+
...snapshot,
|
|
2882
|
+
error: null,
|
|
2883
|
+
isRunning: true,
|
|
2884
|
+
runningActionId: action.id
|
|
2885
|
+
};
|
|
2886
|
+
emit();
|
|
2887
|
+
try {
|
|
2888
|
+
const result = await runVoiceOpsAction(action, options);
|
|
2889
|
+
await options.onActionResult?.(result);
|
|
2890
|
+
await recordVoiceOpsActionResult(result, options);
|
|
2891
|
+
snapshot = {
|
|
2892
|
+
...snapshot,
|
|
2893
|
+
error: null,
|
|
2894
|
+
isRunning: false,
|
|
2895
|
+
lastResult: result,
|
|
2896
|
+
runningActionId: undefined,
|
|
2897
|
+
updatedAt: Date.now()
|
|
2898
|
+
};
|
|
2899
|
+
emit();
|
|
2900
|
+
return result;
|
|
2901
|
+
} catch (error) {
|
|
2902
|
+
const result = {
|
|
2903
|
+
actionId: action.id,
|
|
2904
|
+
body: null,
|
|
2905
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2906
|
+
ok: false,
|
|
2907
|
+
ranAt: Date.now(),
|
|
2908
|
+
status: 0
|
|
2909
|
+
};
|
|
2910
|
+
await options.onActionResult?.(result);
|
|
2911
|
+
await recordVoiceOpsActionResult(result, options).catch(() => {});
|
|
2912
|
+
snapshot = {
|
|
2913
|
+
...snapshot,
|
|
2914
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2915
|
+
isRunning: false,
|
|
2916
|
+
runningActionId: undefined
|
|
2917
|
+
};
|
|
2918
|
+
emit();
|
|
2919
|
+
throw error;
|
|
2920
|
+
}
|
|
2921
|
+
};
|
|
2922
|
+
const close = () => {
|
|
2923
|
+
closed = true;
|
|
2924
|
+
if (timer) {
|
|
2925
|
+
clearInterval(timer);
|
|
2926
|
+
timer = undefined;
|
|
2927
|
+
}
|
|
2928
|
+
listeners.clear();
|
|
2929
|
+
};
|
|
2930
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
2931
|
+
timer = setInterval(() => {
|
|
2932
|
+
emit();
|
|
2933
|
+
}, options.intervalMs);
|
|
2934
|
+
}
|
|
2935
|
+
return {
|
|
2936
|
+
close,
|
|
2937
|
+
getServerSnapshot: () => snapshot,
|
|
2938
|
+
getSnapshot: () => snapshot,
|
|
2939
|
+
run,
|
|
2940
|
+
setActions,
|
|
2941
|
+
subscribe: (listener) => {
|
|
2942
|
+
listeners.add(listener);
|
|
2943
|
+
return () => {
|
|
2944
|
+
listeners.delete(listener);
|
|
2945
|
+
};
|
|
2946
|
+
}
|
|
2947
|
+
};
|
|
2948
|
+
};
|
|
2949
|
+
|
|
2950
|
+
// src/angular/voice-ops-action-center.service.ts
|
|
2951
|
+
var _dec = [
|
|
2952
|
+
Injectable11({ providedIn: "root" })
|
|
2953
|
+
];
|
|
2954
|
+
var _init = __decoratorStart(undefined);
|
|
2955
|
+
|
|
2956
|
+
class VoiceOpsActionCenterService {
|
|
2957
|
+
connect(options = {}) {
|
|
2958
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
2959
|
+
const actionsSignal = signal11([]);
|
|
2960
|
+
const errorSignal = signal11(null);
|
|
2961
|
+
const isRunningSignal = signal11(false);
|
|
2962
|
+
const lastResultSignal = signal11(undefined);
|
|
2963
|
+
const runningActionIdSignal = signal11(undefined);
|
|
2964
|
+
const sync = () => {
|
|
2965
|
+
const snapshot = store.getSnapshot();
|
|
2966
|
+
actionsSignal.set(snapshot.actions);
|
|
2967
|
+
errorSignal.set(snapshot.error);
|
|
2968
|
+
isRunningSignal.set(snapshot.isRunning);
|
|
2969
|
+
lastResultSignal.set(snapshot.lastResult);
|
|
2970
|
+
runningActionIdSignal.set(snapshot.runningActionId);
|
|
2971
|
+
};
|
|
2972
|
+
const unsubscribe = store.subscribe(sync);
|
|
2973
|
+
sync();
|
|
2974
|
+
return {
|
|
2975
|
+
actions: computed11(() => actionsSignal()),
|
|
2976
|
+
close: () => {
|
|
2977
|
+
unsubscribe();
|
|
2978
|
+
store.close();
|
|
2979
|
+
},
|
|
2980
|
+
error: computed11(() => errorSignal()),
|
|
2981
|
+
isRunning: computed11(() => isRunningSignal()),
|
|
2982
|
+
lastResult: computed11(() => lastResultSignal()),
|
|
2983
|
+
run: store.run,
|
|
2984
|
+
runningActionId: computed11(() => runningActionIdSignal()),
|
|
2985
|
+
setActions: store.setActions
|
|
2986
|
+
};
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
VoiceOpsActionCenterService = __decorateElement(_init, 0, "VoiceOpsActionCenterService", _dec, VoiceOpsActionCenterService);
|
|
2990
|
+
__runInitializers(_init, 1, VoiceOpsActionCenterService);
|
|
2991
|
+
__decoratorMetadata(_init, VoiceOpsActionCenterService);
|
|
2992
|
+
let _VoiceOpsActionCenterService = VoiceOpsActionCenterService;
|
|
2993
|
+
// src/angular/voice-live-ops.service.ts
|
|
2994
|
+
import { computed as computed12, Injectable as Injectable12, signal as signal12 } from "@angular/core";
|
|
2995
|
+
|
|
2996
|
+
// src/client/liveOps.ts
|
|
2997
|
+
var postVoiceLiveOpsAction = async (input, options = {}) => {
|
|
2998
|
+
if (!input.sessionId) {
|
|
2999
|
+
throw new Error("Start a voice session before running live ops actions.");
|
|
3000
|
+
}
|
|
3001
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3002
|
+
const response = await fetchImpl(options.actionPath ?? "/api/voice/live-ops/action", {
|
|
3003
|
+
body: JSON.stringify(input),
|
|
3004
|
+
headers: {
|
|
3005
|
+
"Content-Type": "application/json"
|
|
3006
|
+
},
|
|
3007
|
+
method: "POST"
|
|
3008
|
+
});
|
|
3009
|
+
const payload = await response.json().catch(() => null);
|
|
3010
|
+
if (!response.ok || !payload?.ok) {
|
|
3011
|
+
const message = payload && typeof payload === "object" && "error" in payload ? String(payload.error) : `Voice live ops action failed: HTTP ${response.status}`;
|
|
3012
|
+
throw new Error(message);
|
|
3013
|
+
}
|
|
3014
|
+
return payload;
|
|
3015
|
+
};
|
|
3016
|
+
var createVoiceLiveOpsStore = (options = {}) => {
|
|
3017
|
+
const listeners = new Set;
|
|
3018
|
+
let closed = false;
|
|
3019
|
+
let snapshot = {
|
|
3020
|
+
error: null,
|
|
3021
|
+
isRunning: false
|
|
3022
|
+
};
|
|
3023
|
+
const emit = () => {
|
|
3024
|
+
for (const listener of listeners) {
|
|
3025
|
+
listener();
|
|
3026
|
+
}
|
|
3027
|
+
};
|
|
3028
|
+
const run = async (input) => {
|
|
3029
|
+
if (closed) {
|
|
3030
|
+
return snapshot.lastResult;
|
|
3031
|
+
}
|
|
3032
|
+
snapshot = {
|
|
3033
|
+
...snapshot,
|
|
3034
|
+
error: null,
|
|
3035
|
+
isRunning: true,
|
|
3036
|
+
runningAction: input.action
|
|
3037
|
+
};
|
|
3038
|
+
emit();
|
|
3039
|
+
try {
|
|
3040
|
+
const result = await postVoiceLiveOpsAction(input, options);
|
|
3041
|
+
await options.onControl?.(result);
|
|
3042
|
+
snapshot = {
|
|
3043
|
+
...snapshot,
|
|
3044
|
+
error: null,
|
|
3045
|
+
isRunning: false,
|
|
3046
|
+
lastResult: result,
|
|
3047
|
+
runningAction: undefined,
|
|
3048
|
+
updatedAt: Date.now()
|
|
3049
|
+
};
|
|
3050
|
+
emit();
|
|
3051
|
+
return result;
|
|
3052
|
+
} catch (error) {
|
|
3053
|
+
snapshot = {
|
|
3054
|
+
...snapshot,
|
|
3055
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3056
|
+
isRunning: false,
|
|
3057
|
+
runningAction: undefined,
|
|
3058
|
+
updatedAt: Date.now()
|
|
3059
|
+
};
|
|
3060
|
+
emit();
|
|
3061
|
+
throw error;
|
|
3062
|
+
}
|
|
3063
|
+
};
|
|
3064
|
+
const close = () => {
|
|
3065
|
+
closed = true;
|
|
3066
|
+
listeners.clear();
|
|
3067
|
+
};
|
|
3068
|
+
return {
|
|
3069
|
+
close,
|
|
3070
|
+
getServerSnapshot: () => snapshot,
|
|
3071
|
+
getSnapshot: () => snapshot,
|
|
3072
|
+
run,
|
|
3073
|
+
subscribe: (listener) => {
|
|
3074
|
+
listeners.add(listener);
|
|
3075
|
+
return () => {
|
|
3076
|
+
listeners.delete(listener);
|
|
3077
|
+
};
|
|
3078
|
+
}
|
|
3079
|
+
};
|
|
3080
|
+
};
|
|
3081
|
+
|
|
3082
|
+
// src/angular/voice-live-ops.service.ts
|
|
3083
|
+
var _dec = [
|
|
3084
|
+
Injectable12({ providedIn: "root" })
|
|
3085
|
+
];
|
|
3086
|
+
var _init = __decoratorStart(undefined);
|
|
3087
|
+
|
|
3088
|
+
class VoiceLiveOpsService {
|
|
3089
|
+
connect(options = {}) {
|
|
3090
|
+
const store = createVoiceLiveOpsStore(options);
|
|
3091
|
+
const errorSignal = signal12(null);
|
|
3092
|
+
const isRunningSignal = signal12(false);
|
|
3093
|
+
const lastResultSignal = signal12(undefined);
|
|
3094
|
+
const runningActionSignal = signal12(undefined);
|
|
3095
|
+
const sync = () => {
|
|
3096
|
+
const snapshot = store.getSnapshot();
|
|
3097
|
+
errorSignal.set(snapshot.error);
|
|
3098
|
+
isRunningSignal.set(snapshot.isRunning);
|
|
3099
|
+
lastResultSignal.set(snapshot.lastResult);
|
|
3100
|
+
runningActionSignal.set(snapshot.runningAction);
|
|
3101
|
+
};
|
|
3102
|
+
const unsubscribe = store.subscribe(sync);
|
|
3103
|
+
sync();
|
|
3104
|
+
return {
|
|
3105
|
+
close: () => {
|
|
3106
|
+
unsubscribe();
|
|
3107
|
+
store.close();
|
|
3108
|
+
},
|
|
3109
|
+
error: computed12(() => errorSignal()),
|
|
3110
|
+
isRunning: computed12(() => isRunningSignal()),
|
|
3111
|
+
lastResult: computed12(() => lastResultSignal()),
|
|
3112
|
+
run: store.run,
|
|
3113
|
+
runningAction: computed12(() => runningActionSignal())
|
|
3114
|
+
};
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
VoiceLiveOpsService = __decorateElement(_init, 0, "VoiceLiveOpsService", _dec, VoiceLiveOpsService);
|
|
3118
|
+
__runInitializers(_init, 1, VoiceLiveOpsService);
|
|
3119
|
+
__decoratorMetadata(_init, VoiceLiveOpsService);
|
|
3120
|
+
let _VoiceLiveOpsService = VoiceLiveOpsService;
|
|
3121
|
+
// src/angular/voice-delivery-runtime.service.ts
|
|
3122
|
+
import { computed as computed13, Injectable as Injectable13, signal as signal13 } from "@angular/core";
|
|
3123
|
+
|
|
3124
|
+
// src/client/deliveryRuntime.ts
|
|
3125
|
+
var getDefaultActionPath = (path, action, options) => {
|
|
3126
|
+
if (action === "tick") {
|
|
3127
|
+
return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
|
|
3128
|
+
}
|
|
3129
|
+
return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
|
|
3130
|
+
};
|
|
3131
|
+
var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
3132
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3133
|
+
const response = await fetchImpl(path);
|
|
3134
|
+
if (!response.ok) {
|
|
3135
|
+
throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
|
|
3136
|
+
}
|
|
3137
|
+
return await response.json();
|
|
3138
|
+
};
|
|
3139
|
+
var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
3140
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3141
|
+
const response = await fetchImpl(getDefaultActionPath(path, action, options), {
|
|
3142
|
+
method: "POST"
|
|
3143
|
+
});
|
|
3144
|
+
if (!response.ok) {
|
|
3145
|
+
throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
|
|
3146
|
+
}
|
|
3147
|
+
const body = await response.json();
|
|
3148
|
+
return {
|
|
3149
|
+
action,
|
|
3150
|
+
result: body.result,
|
|
3151
|
+
summary: body.summary,
|
|
3152
|
+
updatedAt: Date.now()
|
|
3153
|
+
};
|
|
3154
|
+
};
|
|
3155
|
+
var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
3156
|
+
const listeners = new Set;
|
|
3157
|
+
let closed = false;
|
|
3158
|
+
let timer;
|
|
3159
|
+
let snapshot = {
|
|
3160
|
+
actionError: null,
|
|
3161
|
+
actionStatus: "idle",
|
|
3162
|
+
error: null,
|
|
3163
|
+
isLoading: false
|
|
3164
|
+
};
|
|
3165
|
+
const emit = () => {
|
|
3166
|
+
for (const listener of listeners) {
|
|
3167
|
+
listener();
|
|
3168
|
+
}
|
|
3169
|
+
};
|
|
3170
|
+
const refresh = async () => {
|
|
3171
|
+
if (closed) {
|
|
3172
|
+
return snapshot.report;
|
|
3173
|
+
}
|
|
3174
|
+
snapshot = {
|
|
3175
|
+
...snapshot,
|
|
3176
|
+
error: null,
|
|
3177
|
+
isLoading: true
|
|
3178
|
+
};
|
|
3179
|
+
emit();
|
|
3180
|
+
try {
|
|
3181
|
+
const report = await fetchVoiceDeliveryRuntime(path, options);
|
|
3182
|
+
snapshot = {
|
|
3183
|
+
...snapshot,
|
|
3184
|
+
error: null,
|
|
3185
|
+
isLoading: false,
|
|
3186
|
+
report,
|
|
3187
|
+
updatedAt: Date.now()
|
|
3188
|
+
};
|
|
3189
|
+
emit();
|
|
3190
|
+
return report;
|
|
3191
|
+
} catch (error) {
|
|
3192
|
+
snapshot = {
|
|
3193
|
+
...snapshot,
|
|
3194
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3195
|
+
isLoading: false
|
|
3196
|
+
};
|
|
3197
|
+
emit();
|
|
3198
|
+
throw error;
|
|
3199
|
+
}
|
|
3200
|
+
};
|
|
3201
|
+
const runAction = async (action) => {
|
|
3202
|
+
if (closed) {
|
|
3203
|
+
return snapshot.lastAction;
|
|
3204
|
+
}
|
|
3205
|
+
snapshot = {
|
|
3206
|
+
...snapshot,
|
|
3207
|
+
actionError: null,
|
|
3208
|
+
actionStatus: "running"
|
|
3209
|
+
};
|
|
3210
|
+
emit();
|
|
3211
|
+
try {
|
|
3212
|
+
const result = await runVoiceDeliveryRuntimeAction(action, path, options);
|
|
3213
|
+
snapshot = {
|
|
3214
|
+
...snapshot,
|
|
3215
|
+
actionError: null,
|
|
3216
|
+
actionStatus: "completed",
|
|
3217
|
+
lastAction: result
|
|
3218
|
+
};
|
|
3219
|
+
emit();
|
|
3220
|
+
await refresh();
|
|
3221
|
+
return result;
|
|
3222
|
+
} catch (error) {
|
|
3223
|
+
snapshot = {
|
|
3224
|
+
...snapshot,
|
|
3225
|
+
actionError: error instanceof Error ? error.message : String(error),
|
|
3226
|
+
actionStatus: "failed"
|
|
3227
|
+
};
|
|
3228
|
+
emit();
|
|
3229
|
+
throw error;
|
|
3230
|
+
}
|
|
3231
|
+
};
|
|
3232
|
+
const close = () => {
|
|
3233
|
+
closed = true;
|
|
3234
|
+
if (timer) {
|
|
3235
|
+
clearInterval(timer);
|
|
3236
|
+
timer = undefined;
|
|
3237
|
+
}
|
|
3238
|
+
listeners.clear();
|
|
3239
|
+
};
|
|
3240
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
3241
|
+
timer = setInterval(() => {
|
|
3242
|
+
refresh().catch(() => {});
|
|
3243
|
+
}, options.intervalMs);
|
|
3244
|
+
}
|
|
3245
|
+
return {
|
|
3246
|
+
close,
|
|
3247
|
+
getServerSnapshot: () => snapshot,
|
|
3248
|
+
getSnapshot: () => snapshot,
|
|
3249
|
+
requeueDeadLetters: () => runAction("requeue-dead-letters"),
|
|
3250
|
+
refresh,
|
|
3251
|
+
tick: () => runAction("tick"),
|
|
3252
|
+
subscribe: (listener) => {
|
|
3253
|
+
listeners.add(listener);
|
|
3254
|
+
return () => {
|
|
3255
|
+
listeners.delete(listener);
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3258
|
+
};
|
|
3259
|
+
};
|
|
3260
|
+
|
|
3261
|
+
// src/angular/voice-delivery-runtime.service.ts
|
|
3262
|
+
var _dec = [
|
|
3263
|
+
Injectable13({ providedIn: "root" })
|
|
3264
|
+
];
|
|
3265
|
+
var _init = __decoratorStart(undefined);
|
|
3266
|
+
|
|
3267
|
+
class VoiceDeliveryRuntimeService {
|
|
3268
|
+
connect(path = "/api/voice-delivery-runtime", options = {}) {
|
|
3269
|
+
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
3270
|
+
const actionErrorSignal = signal13(null);
|
|
3271
|
+
const actionStatusSignal = signal13("idle");
|
|
3272
|
+
const errorSignal = signal13(null);
|
|
3273
|
+
const isLoadingSignal = signal13(false);
|
|
3274
|
+
const reportSignal = signal13(undefined);
|
|
3275
|
+
const updatedAtSignal = signal13(undefined);
|
|
3276
|
+
const sync = () => {
|
|
3277
|
+
const snapshot = store.getSnapshot();
|
|
3278
|
+
actionErrorSignal.set(snapshot.actionError);
|
|
3279
|
+
actionStatusSignal.set(snapshot.actionStatus);
|
|
3280
|
+
errorSignal.set(snapshot.error);
|
|
3281
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
3282
|
+
reportSignal.set(snapshot.report);
|
|
3283
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
3284
|
+
};
|
|
3285
|
+
const unsubscribe = store.subscribe(sync);
|
|
3286
|
+
sync();
|
|
3287
|
+
if (typeof window !== "undefined") {
|
|
3288
|
+
store.refresh().catch(() => {});
|
|
3289
|
+
}
|
|
3290
|
+
return {
|
|
3291
|
+
close: () => {
|
|
3292
|
+
unsubscribe();
|
|
3293
|
+
store.close();
|
|
3294
|
+
},
|
|
3295
|
+
error: computed13(() => errorSignal()),
|
|
3296
|
+
actionError: computed13(() => actionErrorSignal()),
|
|
3297
|
+
actionStatus: computed13(() => actionStatusSignal()),
|
|
3298
|
+
isLoading: computed13(() => isLoadingSignal()),
|
|
3299
|
+
requeueDeadLetters: store.requeueDeadLetters,
|
|
3300
|
+
refresh: store.refresh,
|
|
3301
|
+
report: computed13(() => reportSignal()),
|
|
3302
|
+
tick: store.tick,
|
|
3303
|
+
updatedAt: computed13(() => updatedAtSignal())
|
|
3304
|
+
};
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
VoiceDeliveryRuntimeService = __decorateElement(_init, 0, "VoiceDeliveryRuntimeService", _dec, VoiceDeliveryRuntimeService);
|
|
3308
|
+
__runInitializers(_init, 1, VoiceDeliveryRuntimeService);
|
|
3309
|
+
__decoratorMetadata(_init, VoiceDeliveryRuntimeService);
|
|
3310
|
+
let _VoiceDeliveryRuntimeService = VoiceDeliveryRuntimeService;
|
|
3311
|
+
// src/angular/voice-campaign-dialer-proof.service.ts
|
|
3312
|
+
import { computed as computed14, Injectable as Injectable14, signal as signal14 } from "@angular/core";
|
|
3313
|
+
|
|
3314
|
+
// src/client/campaignDialerProof.ts
|
|
3315
|
+
var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
3316
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3317
|
+
const response = await fetchImpl(path);
|
|
3318
|
+
if (!response.ok) {
|
|
3319
|
+
throw new Error(`Voice campaign dialer proof status failed: HTTP ${response.status}`);
|
|
3320
|
+
}
|
|
3321
|
+
return await response.json();
|
|
3322
|
+
};
|
|
3323
|
+
var runVoiceCampaignDialerProofAction = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
3324
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3325
|
+
const response = await fetchImpl(path, { method: "POST" });
|
|
3326
|
+
if (!response.ok) {
|
|
3327
|
+
throw new Error(`Voice campaign dialer proof failed: HTTP ${response.status}`);
|
|
3328
|
+
}
|
|
3329
|
+
return await response.json();
|
|
3330
|
+
};
|
|
3331
|
+
var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
3332
|
+
const listeners = new Set;
|
|
3333
|
+
let closed = false;
|
|
3334
|
+
let timer;
|
|
3335
|
+
let snapshot = {
|
|
3336
|
+
error: null,
|
|
3337
|
+
isLoading: false
|
|
3338
|
+
};
|
|
3339
|
+
const emit = () => {
|
|
3340
|
+
for (const listener of listeners) {
|
|
3341
|
+
listener();
|
|
3342
|
+
}
|
|
3343
|
+
};
|
|
3344
|
+
const refresh = async () => {
|
|
3345
|
+
if (closed) {
|
|
3346
|
+
return snapshot.status;
|
|
3347
|
+
}
|
|
3348
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3349
|
+
emit();
|
|
3350
|
+
try {
|
|
3351
|
+
const status = await fetchVoiceCampaignDialerProofStatus(path, options);
|
|
3352
|
+
snapshot = {
|
|
3353
|
+
...snapshot,
|
|
3354
|
+
error: null,
|
|
3355
|
+
isLoading: false,
|
|
3356
|
+
status,
|
|
3357
|
+
updatedAt: Date.now()
|
|
3358
|
+
};
|
|
3359
|
+
emit();
|
|
3360
|
+
return status;
|
|
3361
|
+
} catch (error) {
|
|
3362
|
+
snapshot = {
|
|
3363
|
+
...snapshot,
|
|
3364
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3365
|
+
isLoading: false
|
|
3366
|
+
};
|
|
3367
|
+
emit();
|
|
3368
|
+
throw error;
|
|
3369
|
+
}
|
|
3370
|
+
};
|
|
3371
|
+
const runProof = async () => {
|
|
3372
|
+
const runPath = options.runPath ?? snapshot.status?.runPath ?? path;
|
|
3373
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3374
|
+
emit();
|
|
3375
|
+
try {
|
|
3376
|
+
const report = await runVoiceCampaignDialerProofAction(runPath, options);
|
|
3377
|
+
snapshot = {
|
|
3378
|
+
...snapshot,
|
|
3379
|
+
error: null,
|
|
3380
|
+
isLoading: false,
|
|
3381
|
+
report,
|
|
3382
|
+
status: {
|
|
3383
|
+
generatedAt: Date.now(),
|
|
3384
|
+
mode: report.mode,
|
|
3385
|
+
ok: report.ok,
|
|
3386
|
+
providers: report.providers.map((provider) => provider.provider),
|
|
3387
|
+
runPath,
|
|
3388
|
+
safe: true
|
|
3389
|
+
},
|
|
3390
|
+
updatedAt: Date.now()
|
|
3391
|
+
};
|
|
3392
|
+
emit();
|
|
3393
|
+
return report;
|
|
3394
|
+
} catch (error) {
|
|
3395
|
+
snapshot = {
|
|
3396
|
+
...snapshot,
|
|
3397
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3398
|
+
isLoading: false
|
|
3399
|
+
};
|
|
3400
|
+
emit();
|
|
3401
|
+
throw error;
|
|
3402
|
+
}
|
|
3403
|
+
};
|
|
3404
|
+
const close = () => {
|
|
3405
|
+
closed = true;
|
|
3406
|
+
if (timer) {
|
|
3407
|
+
clearInterval(timer);
|
|
3408
|
+
timer = undefined;
|
|
3409
|
+
}
|
|
3410
|
+
listeners.clear();
|
|
3411
|
+
};
|
|
3412
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3413
|
+
timer = setInterval(() => {
|
|
3414
|
+
refresh().catch(() => {});
|
|
3415
|
+
}, options.intervalMs);
|
|
3416
|
+
}
|
|
3417
|
+
return {
|
|
3418
|
+
close,
|
|
3419
|
+
getServerSnapshot: () => snapshot,
|
|
3420
|
+
getSnapshot: () => snapshot,
|
|
3421
|
+
refresh,
|
|
3422
|
+
runProof,
|
|
3423
|
+
subscribe: (listener) => {
|
|
3424
|
+
listeners.add(listener);
|
|
3425
|
+
return () => {
|
|
3426
|
+
listeners.delete(listener);
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
};
|
|
3430
|
+
};
|
|
3431
|
+
|
|
3432
|
+
// src/angular/voice-campaign-dialer-proof.service.ts
|
|
3433
|
+
var _dec = [
|
|
3434
|
+
Injectable14({ providedIn: "root" })
|
|
3435
|
+
];
|
|
3436
|
+
var _init = __decoratorStart(undefined);
|
|
3437
|
+
|
|
3438
|
+
class VoiceCampaignDialerProofService {
|
|
3439
|
+
connect(path = "/api/voice/campaigns/dialer-proof", options = {}) {
|
|
3440
|
+
const store = createVoiceCampaignDialerProofStore(path, options);
|
|
3441
|
+
const errorSignal = signal14(null);
|
|
3442
|
+
const isLoadingSignal = signal14(false);
|
|
3443
|
+
const reportSignal = signal14(undefined);
|
|
3444
|
+
const statusSignal = signal14(undefined);
|
|
3445
|
+
const updatedAtSignal = signal14(undefined);
|
|
3446
|
+
const sync = () => {
|
|
3447
|
+
const snapshot = store.getSnapshot();
|
|
3448
|
+
errorSignal.set(snapshot.error);
|
|
3449
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
3450
|
+
reportSignal.set(snapshot.report);
|
|
3451
|
+
statusSignal.set(snapshot.status);
|
|
3452
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
3453
|
+
};
|
|
3454
|
+
const unsubscribe = store.subscribe(sync);
|
|
3455
|
+
sync();
|
|
3456
|
+
store.refresh().catch(() => {});
|
|
3457
|
+
return {
|
|
3458
|
+
close: () => {
|
|
3459
|
+
unsubscribe();
|
|
3460
|
+
store.close();
|
|
3461
|
+
},
|
|
3462
|
+
error: computed14(() => errorSignal()),
|
|
3463
|
+
isLoading: computed14(() => isLoadingSignal()),
|
|
3464
|
+
refresh: store.refresh,
|
|
3465
|
+
report: computed14(() => reportSignal()),
|
|
3466
|
+
runProof: store.runProof,
|
|
3467
|
+
status: computed14(() => statusSignal()),
|
|
3468
|
+
updatedAt: computed14(() => updatedAtSignal())
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
VoiceCampaignDialerProofService = __decorateElement(_init, 0, "VoiceCampaignDialerProofService", _dec, VoiceCampaignDialerProofService);
|
|
3473
|
+
__runInitializers(_init, 1, VoiceCampaignDialerProofService);
|
|
3474
|
+
__decoratorMetadata(_init, VoiceCampaignDialerProofService);
|
|
3475
|
+
let _VoiceCampaignDialerProofService = VoiceCampaignDialerProofService;
|
|
3476
|
+
// src/angular/voice-stream.service.ts
|
|
3477
|
+
import { computed as computed15, Injectable as Injectable15, signal as signal15 } from "@angular/core";
|
|
3478
|
+
var _dec = [
|
|
3479
|
+
Injectable15({ providedIn: "root" })
|
|
3480
|
+
];
|
|
3481
|
+
var _init = __decoratorStart(undefined);
|
|
3482
|
+
|
|
3483
|
+
class VoiceStreamService {
|
|
3484
|
+
connect(path, options = {}) {
|
|
3485
|
+
const stream = createVoiceStream(path, options);
|
|
3486
|
+
const assistantAudioSignal = signal15([]);
|
|
3487
|
+
const assistantTextsSignal = signal15([]);
|
|
3488
|
+
const callSignal = signal15(null);
|
|
3489
|
+
const errorSignal = signal15(null);
|
|
3490
|
+
const isConnectedSignal = signal15(false);
|
|
3491
|
+
const partialSignal = signal15("");
|
|
3492
|
+
const reconnectSignal = signal15(stream.reconnect);
|
|
3493
|
+
const sessionIdSignal = signal15(stream.sessionId);
|
|
3494
|
+
const sessionMetadataSignal = signal15(stream.sessionMetadata);
|
|
3495
|
+
const statusSignal = signal15(stream.status);
|
|
3496
|
+
const turnsSignal = signal15([]);
|
|
3497
|
+
const sync = () => {
|
|
3498
|
+
assistantAudioSignal.set([...stream.assistantAudio]);
|
|
3499
|
+
assistantTextsSignal.set([...stream.assistantTexts]);
|
|
3500
|
+
callSignal.set(stream.call);
|
|
3501
|
+
errorSignal.set(stream.error);
|
|
3502
|
+
isConnectedSignal.set(stream.isConnected);
|
|
3503
|
+
partialSignal.set(stream.partial);
|
|
3504
|
+
reconnectSignal.set(stream.reconnect);
|
|
3505
|
+
sessionIdSignal.set(stream.sessionId);
|
|
3506
|
+
sessionMetadataSignal.set(stream.sessionMetadata);
|
|
3507
|
+
statusSignal.set(stream.status);
|
|
3508
|
+
turnsSignal.set([...stream.turns]);
|
|
3509
|
+
};
|
|
3510
|
+
const unsubscribe = stream.subscribe(sync);
|
|
3511
|
+
sync();
|
|
3512
|
+
return {
|
|
3513
|
+
assistantAudio: computed15(() => assistantAudioSignal()),
|
|
3514
|
+
assistantTexts: computed15(() => assistantTextsSignal()),
|
|
3515
|
+
call: computed15(() => callSignal()),
|
|
3516
|
+
callControl: (message) => stream.callControl(message),
|
|
3517
|
+
close: () => {
|
|
3518
|
+
unsubscribe();
|
|
3519
|
+
stream.close();
|
|
3520
|
+
},
|
|
3521
|
+
endTurn: () => stream.endTurn(),
|
|
3522
|
+
error: computed15(() => errorSignal()),
|
|
3523
|
+
isConnected: computed15(() => isConnectedSignal()),
|
|
3524
|
+
partial: computed15(() => partialSignal()),
|
|
3525
|
+
reconnect: computed15(() => reconnectSignal()),
|
|
3526
|
+
sendAudio: (audio) => stream.sendAudio(audio),
|
|
3527
|
+
simulateDisconnect: () => stream.simulateDisconnect(),
|
|
3528
|
+
sessionId: computed15(() => sessionIdSignal()),
|
|
3529
|
+
sessionMetadata: computed15(() => sessionMetadataSignal()),
|
|
3530
|
+
status: computed15(() => statusSignal()),
|
|
3531
|
+
turns: computed15(() => turnsSignal())
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
VoiceStreamService = __decorateElement(_init, 0, "VoiceStreamService", _dec, VoiceStreamService);
|
|
3536
|
+
__runInitializers(_init, 1, VoiceStreamService);
|
|
3537
|
+
__decoratorMetadata(_init, VoiceStreamService);
|
|
3538
|
+
let _VoiceStreamService = VoiceStreamService;
|
|
3539
|
+
// src/angular/voice-controller.service.ts
|
|
3540
|
+
import { computed as computed16, Injectable as Injectable16, signal as signal16 } from "@angular/core";
|
|
3541
|
+
var _dec = [
|
|
3542
|
+
Injectable16({ providedIn: "root" })
|
|
3543
|
+
];
|
|
3544
|
+
var _init = __decoratorStart(undefined);
|
|
3545
|
+
|
|
3546
|
+
class VoiceControllerService {
|
|
3547
|
+
connect(path, options = {}) {
|
|
3548
|
+
const controller = createVoiceController(path, options);
|
|
3549
|
+
const assistantAudioSignal = signal16([]);
|
|
3550
|
+
const assistantTextsSignal = signal16([]);
|
|
3551
|
+
const errorSignal = signal16(null);
|
|
3552
|
+
const isConnectedSignal = signal16(false);
|
|
3553
|
+
const isRecordingSignal = signal16(false);
|
|
3554
|
+
const partialSignal = signal16("");
|
|
3555
|
+
const reconnectSignal = signal16(controller.reconnect);
|
|
3556
|
+
const recordingErrorSignal = signal16(null);
|
|
3557
|
+
const sessionIdSignal = signal16(controller.sessionId);
|
|
3558
|
+
const statusSignal = signal16(controller.status);
|
|
3559
|
+
const turnsSignal = signal16([]);
|
|
3560
|
+
const sync = () => {
|
|
3561
|
+
assistantAudioSignal.set([...controller.assistantAudio]);
|
|
3562
|
+
assistantTextsSignal.set([...controller.assistantTexts]);
|
|
3563
|
+
errorSignal.set(controller.error);
|
|
3564
|
+
isConnectedSignal.set(controller.isConnected);
|
|
3565
|
+
isRecordingSignal.set(controller.isRecording);
|
|
3566
|
+
partialSignal.set(controller.partial);
|
|
3567
|
+
reconnectSignal.set(controller.reconnect);
|
|
3568
|
+
recordingErrorSignal.set(controller.recordingError);
|
|
3569
|
+
sessionIdSignal.set(controller.sessionId);
|
|
3570
|
+
statusSignal.set(controller.status);
|
|
3571
|
+
turnsSignal.set([...controller.turns]);
|
|
3572
|
+
};
|
|
3573
|
+
const unsubscribe = controller.subscribe(sync);
|
|
3574
|
+
sync();
|
|
3575
|
+
return {
|
|
3576
|
+
assistantAudio: computed16(() => assistantAudioSignal()),
|
|
3577
|
+
assistantTexts: computed16(() => assistantTextsSignal()),
|
|
3578
|
+
bindHTMX: controller.bindHTMX,
|
|
3579
|
+
close: () => {
|
|
3580
|
+
unsubscribe();
|
|
3581
|
+
controller.close();
|
|
3582
|
+
},
|
|
3583
|
+
endTurn: () => controller.endTurn(),
|
|
3584
|
+
error: computed16(() => errorSignal()),
|
|
3585
|
+
isConnected: computed16(() => isConnectedSignal()),
|
|
3586
|
+
isRecording: computed16(() => isRecordingSignal()),
|
|
3587
|
+
partial: computed16(() => partialSignal()),
|
|
3588
|
+
reconnect: computed16(() => reconnectSignal()),
|
|
3589
|
+
recordingError: computed16(() => recordingErrorSignal()),
|
|
3590
|
+
sendAudio: (audio) => controller.sendAudio(audio),
|
|
3591
|
+
simulateDisconnect: () => controller.simulateDisconnect(),
|
|
3592
|
+
sessionId: computed16(() => sessionIdSignal()),
|
|
3593
|
+
startRecording: () => controller.startRecording(),
|
|
3594
|
+
status: computed16(() => statusSignal()),
|
|
3595
|
+
stopRecording: () => controller.stopRecording(),
|
|
3596
|
+
toggleRecording: () => controller.toggleRecording(),
|
|
3597
|
+
turns: computed16(() => turnsSignal())
|
|
3598
|
+
};
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
VoiceControllerService = __decorateElement(_init, 0, "VoiceControllerService", _dec, VoiceControllerService);
|
|
3602
|
+
__runInitializers(_init, 1, VoiceControllerService);
|
|
3603
|
+
__decoratorMetadata(_init, VoiceControllerService);
|
|
3604
|
+
let _VoiceControllerService = VoiceControllerService;
|
|
3605
|
+
// src/angular/voice-provider-capabilities.service.ts
|
|
3606
|
+
import { computed as computed17, Injectable as Injectable17, signal as signal17 } from "@angular/core";
|
|
3607
|
+
|
|
3608
|
+
// src/client/providerCapabilities.ts
|
|
3609
|
+
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
3610
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3611
|
+
const response = await fetchImpl(path);
|
|
3612
|
+
if (!response.ok) {
|
|
3613
|
+
throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
|
|
3614
|
+
}
|
|
3615
|
+
return await response.json();
|
|
3616
|
+
};
|
|
3617
|
+
var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
|
|
3618
|
+
const listeners = new Set;
|
|
3619
|
+
let closed = false;
|
|
3620
|
+
let timer;
|
|
3621
|
+
let snapshot = {
|
|
3622
|
+
error: null,
|
|
3623
|
+
isLoading: false
|
|
3624
|
+
};
|
|
3625
|
+
const emit = () => {
|
|
3626
|
+
for (const listener of listeners) {
|
|
3627
|
+
listener();
|
|
3628
|
+
}
|
|
3629
|
+
};
|
|
3630
|
+
const refresh = async () => {
|
|
3631
|
+
if (closed) {
|
|
3632
|
+
return snapshot.report;
|
|
3633
|
+
}
|
|
3634
|
+
snapshot = {
|
|
3635
|
+
...snapshot,
|
|
3636
|
+
error: null,
|
|
3637
|
+
isLoading: true
|
|
3638
|
+
};
|
|
3639
|
+
emit();
|
|
3640
|
+
try {
|
|
3641
|
+
const report = await fetchVoiceProviderCapabilities(path, options);
|
|
3642
|
+
snapshot = {
|
|
3643
|
+
error: null,
|
|
3644
|
+
isLoading: false,
|
|
3645
|
+
report,
|
|
3646
|
+
updatedAt: Date.now()
|
|
3647
|
+
};
|
|
3648
|
+
emit();
|
|
3649
|
+
return report;
|
|
3650
|
+
} catch (error) {
|
|
3651
|
+
snapshot = {
|
|
3652
|
+
...snapshot,
|
|
3653
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3654
|
+
isLoading: false
|
|
3655
|
+
};
|
|
3656
|
+
emit();
|
|
3657
|
+
throw error;
|
|
3658
|
+
}
|
|
3659
|
+
};
|
|
3660
|
+
const close = () => {
|
|
3661
|
+
closed = true;
|
|
3662
|
+
if (timer) {
|
|
3663
|
+
clearInterval(timer);
|
|
3664
|
+
timer = undefined;
|
|
3665
|
+
}
|
|
3666
|
+
listeners.clear();
|
|
3667
|
+
};
|
|
3668
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3669
|
+
timer = setInterval(() => {
|
|
3670
|
+
refresh().catch(() => {});
|
|
3671
|
+
}, options.intervalMs);
|
|
3672
|
+
}
|
|
3673
|
+
return {
|
|
3674
|
+
close,
|
|
3675
|
+
getServerSnapshot: () => snapshot,
|
|
3676
|
+
getSnapshot: () => snapshot,
|
|
3677
|
+
refresh,
|
|
3678
|
+
subscribe: (listener) => {
|
|
3679
|
+
listeners.add(listener);
|
|
3680
|
+
return () => {
|
|
3681
|
+
listeners.delete(listener);
|
|
3682
|
+
};
|
|
3683
|
+
}
|
|
3684
|
+
};
|
|
3685
|
+
};
|
|
3686
|
+
|
|
3687
|
+
// src/angular/voice-provider-capabilities.service.ts
|
|
3688
|
+
var _dec = [
|
|
3689
|
+
Injectable17({ providedIn: "root" })
|
|
3690
|
+
];
|
|
3691
|
+
var _init = __decoratorStart(undefined);
|
|
3692
|
+
|
|
3693
|
+
class VoiceProviderCapabilitiesService {
|
|
3694
|
+
connect(path = "/api/provider-capabilities", options = {}) {
|
|
3695
|
+
const store = createVoiceProviderCapabilitiesStore(path, options);
|
|
3696
|
+
const errorSignal = signal17(null);
|
|
3697
|
+
const isLoadingSignal = signal17(false);
|
|
3698
|
+
const reportSignal = signal17(undefined);
|
|
3699
|
+
const updatedAtSignal = signal17(undefined);
|
|
3700
|
+
const sync = () => {
|
|
3701
|
+
const snapshot = store.getSnapshot();
|
|
3702
|
+
errorSignal.set(snapshot.error);
|
|
3703
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
3704
|
+
reportSignal.set(snapshot.report);
|
|
3705
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
3706
|
+
};
|
|
3707
|
+
const unsubscribe = store.subscribe(sync);
|
|
3708
|
+
sync();
|
|
3709
|
+
store.refresh().catch(() => {});
|
|
3710
|
+
return {
|
|
3711
|
+
close: () => {
|
|
3712
|
+
unsubscribe();
|
|
3713
|
+
store.close();
|
|
3714
|
+
},
|
|
3715
|
+
error: computed17(() => errorSignal()),
|
|
3716
|
+
isLoading: computed17(() => isLoadingSignal()),
|
|
3717
|
+
refresh: store.refresh,
|
|
3718
|
+
report: computed17(() => reportSignal()),
|
|
3719
|
+
updatedAt: computed17(() => updatedAtSignal())
|
|
3720
|
+
};
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
VoiceProviderCapabilitiesService = __decorateElement(_init, 0, "VoiceProviderCapabilitiesService", _dec, VoiceProviderCapabilitiesService);
|
|
3724
|
+
__runInitializers(_init, 1, VoiceProviderCapabilitiesService);
|
|
3725
|
+
__decoratorMetadata(_init, VoiceProviderCapabilitiesService);
|
|
3726
|
+
let _VoiceProviderCapabilitiesService = VoiceProviderCapabilitiesService;
|
|
3727
|
+
// src/angular/voice-provider-contracts.service.ts
|
|
3728
|
+
import { computed as computed18, Injectable as Injectable18, signal as signal18 } from "@angular/core";
|
|
3729
|
+
|
|
3730
|
+
// src/client/providerContracts.ts
|
|
3731
|
+
var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
|
|
3732
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3733
|
+
const response = await fetchImpl(path);
|
|
3734
|
+
if (!response.ok) {
|
|
3735
|
+
throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
|
|
3736
|
+
}
|
|
3737
|
+
return await response.json();
|
|
3738
|
+
};
|
|
3739
|
+
var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
|
|
3740
|
+
const listeners = new Set;
|
|
3741
|
+
let closed = false;
|
|
3742
|
+
let timer;
|
|
3743
|
+
let snapshot = {
|
|
3744
|
+
error: null,
|
|
3745
|
+
isLoading: false
|
|
3746
|
+
};
|
|
3747
|
+
const emit = () => {
|
|
3748
|
+
for (const listener of listeners) {
|
|
3749
|
+
listener();
|
|
3750
|
+
}
|
|
3751
|
+
};
|
|
3752
|
+
const refresh = async () => {
|
|
3753
|
+
if (closed) {
|
|
3754
|
+
return snapshot.report;
|
|
3755
|
+
}
|
|
3756
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3757
|
+
emit();
|
|
3758
|
+
try {
|
|
3759
|
+
const report = await fetchVoiceProviderContracts(path, options);
|
|
3760
|
+
snapshot = {
|
|
3761
|
+
error: null,
|
|
3762
|
+
isLoading: false,
|
|
3763
|
+
report,
|
|
3764
|
+
updatedAt: Date.now()
|
|
3765
|
+
};
|
|
3766
|
+
emit();
|
|
3767
|
+
return report;
|
|
3768
|
+
} catch (error) {
|
|
3769
|
+
snapshot = {
|
|
3770
|
+
...snapshot,
|
|
3771
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3772
|
+
isLoading: false
|
|
3773
|
+
};
|
|
3774
|
+
emit();
|
|
3775
|
+
throw error;
|
|
3776
|
+
}
|
|
3777
|
+
};
|
|
3778
|
+
const close = () => {
|
|
3779
|
+
closed = true;
|
|
3780
|
+
if (timer) {
|
|
3781
|
+
clearInterval(timer);
|
|
3782
|
+
timer = undefined;
|
|
3783
|
+
}
|
|
3784
|
+
listeners.clear();
|
|
3785
|
+
};
|
|
3786
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3787
|
+
timer = setInterval(() => {
|
|
3788
|
+
refresh().catch(() => {});
|
|
3789
|
+
}, options.intervalMs);
|
|
3790
|
+
}
|
|
3791
|
+
return {
|
|
3792
|
+
close,
|
|
3793
|
+
getServerSnapshot: () => snapshot,
|
|
3794
|
+
getSnapshot: () => snapshot,
|
|
3795
|
+
refresh,
|
|
3796
|
+
subscribe: (listener) => {
|
|
3797
|
+
listeners.add(listener);
|
|
3798
|
+
return () => {
|
|
3799
|
+
listeners.delete(listener);
|
|
3800
|
+
};
|
|
3801
|
+
}
|
|
3802
|
+
};
|
|
3803
|
+
};
|
|
3804
|
+
|
|
3805
|
+
// src/angular/voice-provider-contracts.service.ts
|
|
3806
|
+
var _dec = [
|
|
3807
|
+
Injectable18({ providedIn: "root" })
|
|
3808
|
+
];
|
|
3809
|
+
var _init = __decoratorStart(undefined);
|
|
3810
|
+
|
|
3811
|
+
class VoiceProviderContractsService {
|
|
3812
|
+
connect(path = "/api/provider-contracts", options = {}) {
|
|
3813
|
+
const store = createVoiceProviderContractsStore(path, options);
|
|
3814
|
+
const errorSignal = signal18(null);
|
|
3815
|
+
const isLoadingSignal = signal18(false);
|
|
3816
|
+
const reportSignal = signal18(undefined);
|
|
3817
|
+
const updatedAtSignal = signal18(undefined);
|
|
3818
|
+
const sync = () => {
|
|
3819
|
+
const snapshot = store.getSnapshot();
|
|
3820
|
+
errorSignal.set(snapshot.error);
|
|
3821
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
3822
|
+
reportSignal.set(snapshot.report);
|
|
3823
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
3824
|
+
};
|
|
3825
|
+
const unsubscribe = store.subscribe(sync);
|
|
3826
|
+
sync();
|
|
3827
|
+
store.refresh().catch(() => {});
|
|
3828
|
+
return {
|
|
3829
|
+
close: () => {
|
|
3830
|
+
unsubscribe();
|
|
3831
|
+
store.close();
|
|
3832
|
+
},
|
|
3833
|
+
error: computed18(() => errorSignal()),
|
|
3834
|
+
isLoading: computed18(() => isLoadingSignal()),
|
|
3835
|
+
refresh: store.refresh,
|
|
3836
|
+
report: computed18(() => reportSignal()),
|
|
3837
|
+
updatedAt: computed18(() => updatedAtSignal())
|
|
3838
|
+
};
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
VoiceProviderContractsService = __decorateElement(_init, 0, "VoiceProviderContractsService", _dec, VoiceProviderContractsService);
|
|
3842
|
+
__runInitializers(_init, 1, VoiceProviderContractsService);
|
|
3843
|
+
__decoratorMetadata(_init, VoiceProviderContractsService);
|
|
3844
|
+
let _VoiceProviderContractsService = VoiceProviderContractsService;
|
|
3845
|
+
// src/angular/voice-provider-status.service.ts
|
|
3846
|
+
import { computed as computed19, Injectable as Injectable19, signal as signal19 } from "@angular/core";
|
|
3847
|
+
|
|
3848
|
+
// src/client/providerStatus.ts
|
|
3849
|
+
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
3850
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3851
|
+
const response = await fetchImpl(path);
|
|
3852
|
+
if (!response.ok) {
|
|
3853
|
+
throw new Error(`Voice provider status failed: HTTP ${response.status}`);
|
|
3854
|
+
}
|
|
3855
|
+
return await response.json();
|
|
3856
|
+
};
|
|
3857
|
+
var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {}) => {
|
|
3858
|
+
const listeners = new Set;
|
|
3859
|
+
let closed = false;
|
|
3860
|
+
let timer;
|
|
3861
|
+
let snapshot = {
|
|
3862
|
+
error: null,
|
|
3863
|
+
isLoading: false,
|
|
3864
|
+
providers: []
|
|
3865
|
+
};
|
|
3866
|
+
const emit = () => {
|
|
3867
|
+
for (const listener of listeners) {
|
|
3868
|
+
listener();
|
|
3869
|
+
}
|
|
3870
|
+
};
|
|
3871
|
+
const refresh = async () => {
|
|
3872
|
+
if (closed) {
|
|
3873
|
+
return snapshot.providers;
|
|
3874
|
+
}
|
|
3875
|
+
snapshot = {
|
|
3876
|
+
...snapshot,
|
|
3877
|
+
error: null,
|
|
3878
|
+
isLoading: true
|
|
3879
|
+
};
|
|
3880
|
+
emit();
|
|
3881
|
+
try {
|
|
3882
|
+
const providers = await fetchVoiceProviderStatus(path, options);
|
|
3883
|
+
snapshot = {
|
|
3884
|
+
error: null,
|
|
3885
|
+
isLoading: false,
|
|
3886
|
+
providers,
|
|
3887
|
+
updatedAt: Date.now()
|
|
3888
|
+
};
|
|
3889
|
+
emit();
|
|
3890
|
+
return providers;
|
|
3891
|
+
} catch (error) {
|
|
3892
|
+
snapshot = {
|
|
3893
|
+
...snapshot,
|
|
3894
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3895
|
+
isLoading: false
|
|
3896
|
+
};
|
|
3897
|
+
emit();
|
|
3898
|
+
throw error;
|
|
3899
|
+
}
|
|
3900
|
+
};
|
|
3901
|
+
const close = () => {
|
|
3902
|
+
closed = true;
|
|
3903
|
+
if (timer) {
|
|
3904
|
+
clearInterval(timer);
|
|
3905
|
+
timer = undefined;
|
|
3906
|
+
}
|
|
3907
|
+
listeners.clear();
|
|
3908
|
+
};
|
|
3909
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3910
|
+
timer = setInterval(() => {
|
|
3911
|
+
refresh().catch(() => {});
|
|
3912
|
+
}, options.intervalMs);
|
|
3913
|
+
}
|
|
3914
|
+
return {
|
|
3915
|
+
close,
|
|
3916
|
+
getServerSnapshot: () => snapshot,
|
|
3917
|
+
getSnapshot: () => snapshot,
|
|
3918
|
+
refresh,
|
|
3919
|
+
subscribe: (listener) => {
|
|
3920
|
+
listeners.add(listener);
|
|
3921
|
+
return () => {
|
|
3922
|
+
listeners.delete(listener);
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
};
|
|
3927
|
+
|
|
3928
|
+
// src/angular/voice-provider-status.service.ts
|
|
3929
|
+
var _dec = [
|
|
3930
|
+
Injectable19({ providedIn: "root" })
|
|
3931
|
+
];
|
|
3932
|
+
var _init = __decoratorStart(undefined);
|
|
3933
|
+
|
|
3934
|
+
class VoiceProviderStatusService {
|
|
3935
|
+
connect(path = "/api/provider-status", options = {}) {
|
|
3936
|
+
const store = createVoiceProviderStatusStore(path, options);
|
|
3937
|
+
const errorSignal = signal19(null);
|
|
3938
|
+
const isLoadingSignal = signal19(false);
|
|
3939
|
+
const providersSignal = signal19([]);
|
|
3940
|
+
const updatedAtSignal = signal19(undefined);
|
|
3941
|
+
const sync = () => {
|
|
3942
|
+
const snapshot = store.getSnapshot();
|
|
3943
|
+
errorSignal.set(snapshot.error);
|
|
3944
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
3945
|
+
providersSignal.set([...snapshot.providers]);
|
|
3946
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
3947
|
+
};
|
|
3948
|
+
const unsubscribe = store.subscribe(sync);
|
|
3949
|
+
sync();
|
|
3950
|
+
store.refresh().catch(() => {});
|
|
3951
|
+
return {
|
|
3952
|
+
close: () => {
|
|
3953
|
+
unsubscribe();
|
|
3954
|
+
store.close();
|
|
3955
|
+
},
|
|
3956
|
+
error: computed19(() => errorSignal()),
|
|
3957
|
+
isLoading: computed19(() => isLoadingSignal()),
|
|
3958
|
+
providers: computed19(() => providersSignal()),
|
|
3959
|
+
refresh: store.refresh,
|
|
3960
|
+
updatedAt: computed19(() => updatedAtSignal())
|
|
3961
|
+
};
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
VoiceProviderStatusService = __decorateElement(_init, 0, "VoiceProviderStatusService", _dec, VoiceProviderStatusService);
|
|
3965
|
+
__runInitializers(_init, 1, VoiceProviderStatusService);
|
|
3966
|
+
__decoratorMetadata(_init, VoiceProviderStatusService);
|
|
3967
|
+
let _VoiceProviderStatusService = VoiceProviderStatusService;
|
|
3968
|
+
// src/angular/voice-routing-status.service.ts
|
|
3969
|
+
import { Injectable as Injectable20, signal as signal20 } from "@angular/core";
|
|
3970
|
+
|
|
3971
|
+
// src/client/routingStatus.ts
|
|
3972
|
+
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
3973
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3974
|
+
const response = await fetchImpl(path);
|
|
3975
|
+
if (!response.ok) {
|
|
3976
|
+
throw new Error(`Voice routing status failed: HTTP ${response.status}`);
|
|
3977
|
+
}
|
|
3978
|
+
return await response.json();
|
|
3979
|
+
};
|
|
3980
|
+
var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {}) => {
|
|
3981
|
+
const listeners = new Set;
|
|
3982
|
+
let closed = false;
|
|
3983
|
+
let timer;
|
|
3984
|
+
let snapshot = {
|
|
3985
|
+
decision: null,
|
|
3986
|
+
error: null,
|
|
3987
|
+
isLoading: false
|
|
3988
|
+
};
|
|
3989
|
+
const emit = () => {
|
|
3990
|
+
for (const listener of listeners) {
|
|
3991
|
+
listener();
|
|
3992
|
+
}
|
|
3993
|
+
};
|
|
3994
|
+
const refresh = async () => {
|
|
3995
|
+
if (closed) {
|
|
3996
|
+
return snapshot.decision;
|
|
3997
|
+
}
|
|
3998
|
+
snapshot = {
|
|
3999
|
+
...snapshot,
|
|
4000
|
+
error: null,
|
|
4001
|
+
isLoading: true
|
|
4002
|
+
};
|
|
4003
|
+
emit();
|
|
4004
|
+
try {
|
|
4005
|
+
const decision = await fetchVoiceRoutingStatus(path, options);
|
|
4006
|
+
snapshot = {
|
|
4007
|
+
decision,
|
|
4008
|
+
error: null,
|
|
4009
|
+
isLoading: false,
|
|
4010
|
+
updatedAt: Date.now()
|
|
4011
|
+
};
|
|
4012
|
+
emit();
|
|
4013
|
+
return decision;
|
|
4014
|
+
} catch (error) {
|
|
4015
|
+
snapshot = {
|
|
4016
|
+
...snapshot,
|
|
4017
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4018
|
+
isLoading: false
|
|
4019
|
+
};
|
|
4020
|
+
emit();
|
|
4021
|
+
throw error;
|
|
4022
|
+
}
|
|
4023
|
+
};
|
|
4024
|
+
const close = () => {
|
|
4025
|
+
closed = true;
|
|
4026
|
+
if (timer) {
|
|
4027
|
+
clearInterval(timer);
|
|
4028
|
+
timer = undefined;
|
|
4029
|
+
}
|
|
4030
|
+
listeners.clear();
|
|
4031
|
+
};
|
|
4032
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
4033
|
+
timer = setInterval(() => {
|
|
4034
|
+
refresh().catch(() => {});
|
|
4035
|
+
}, options.intervalMs);
|
|
4036
|
+
}
|
|
4037
|
+
return {
|
|
4038
|
+
close,
|
|
4039
|
+
getServerSnapshot: () => snapshot,
|
|
4040
|
+
getSnapshot: () => snapshot,
|
|
4041
|
+
refresh,
|
|
4042
|
+
subscribe: (listener) => {
|
|
4043
|
+
listeners.add(listener);
|
|
4044
|
+
return () => {
|
|
4045
|
+
listeners.delete(listener);
|
|
4046
|
+
};
|
|
4047
|
+
}
|
|
4048
|
+
};
|
|
4049
|
+
};
|
|
4050
|
+
|
|
4051
|
+
// src/angular/voice-routing-status.service.ts
|
|
4052
|
+
var _dec = [
|
|
4053
|
+
Injectable20({ providedIn: "root" })
|
|
4054
|
+
];
|
|
4055
|
+
var _init = __decoratorStart(undefined);
|
|
4056
|
+
|
|
4057
|
+
class VoiceRoutingStatusService {
|
|
4058
|
+
connect(path = "/api/routing/latest", options = {}) {
|
|
4059
|
+
const store = createVoiceRoutingStatusStore(path, options);
|
|
4060
|
+
const decisionSignal = signal20(null);
|
|
4061
|
+
const errorSignal = signal20(null);
|
|
4062
|
+
const isLoadingSignal = signal20(false);
|
|
4063
|
+
const updatedAtSignal = signal20(undefined);
|
|
4064
|
+
const sync = () => {
|
|
4065
|
+
const snapshot = store.getSnapshot();
|
|
4066
|
+
decisionSignal.set(snapshot.decision);
|
|
4067
|
+
errorSignal.set(snapshot.error);
|
|
4068
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
4069
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
4070
|
+
};
|
|
4071
|
+
const unsubscribe = store.subscribe(sync);
|
|
4072
|
+
sync();
|
|
4073
|
+
store.refresh().catch(() => {});
|
|
4074
|
+
return {
|
|
4075
|
+
close: () => {
|
|
4076
|
+
unsubscribe();
|
|
4077
|
+
store.close();
|
|
4078
|
+
},
|
|
4079
|
+
decision: decisionSignal.asReadonly(),
|
|
4080
|
+
error: errorSignal.asReadonly(),
|
|
4081
|
+
isLoading: isLoadingSignal.asReadonly(),
|
|
4082
|
+
refresh: store.refresh,
|
|
4083
|
+
updatedAt: updatedAtSignal.asReadonly()
|
|
4084
|
+
};
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
VoiceRoutingStatusService = __decorateElement(_init, 0, "VoiceRoutingStatusService", _dec, VoiceRoutingStatusService);
|
|
4088
|
+
__runInitializers(_init, 1, VoiceRoutingStatusService);
|
|
4089
|
+
__decoratorMetadata(_init, VoiceRoutingStatusService);
|
|
4090
|
+
let _VoiceRoutingStatusService = VoiceRoutingStatusService;
|
|
4091
|
+
// src/angular/voice-trace-timeline.service.ts
|
|
4092
|
+
import { computed as computed20, Injectable as Injectable21, signal as signal21 } from "@angular/core";
|
|
4093
|
+
|
|
4094
|
+
// src/client/traceTimeline.ts
|
|
4095
|
+
var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
|
|
4096
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
4097
|
+
const response = await fetchImpl(path);
|
|
4098
|
+
if (!response.ok) {
|
|
4099
|
+
throw new Error(`Voice trace timeline failed: HTTP ${response.status}`);
|
|
4100
|
+
}
|
|
4101
|
+
return await response.json();
|
|
4102
|
+
};
|
|
4103
|
+
var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) => {
|
|
4104
|
+
const listeners = new Set;
|
|
4105
|
+
let closed = false;
|
|
4106
|
+
let timer;
|
|
4107
|
+
let snapshot = {
|
|
4108
|
+
error: null,
|
|
4109
|
+
isLoading: false,
|
|
4110
|
+
report: null
|
|
4111
|
+
};
|
|
4112
|
+
const emit = () => {
|
|
4113
|
+
for (const listener of listeners) {
|
|
4114
|
+
listener();
|
|
4115
|
+
}
|
|
4116
|
+
};
|
|
4117
|
+
const refresh = async () => {
|
|
4118
|
+
if (closed) {
|
|
4119
|
+
return snapshot.report;
|
|
4120
|
+
}
|
|
4121
|
+
snapshot = {
|
|
4122
|
+
...snapshot,
|
|
4123
|
+
error: null,
|
|
4124
|
+
isLoading: true
|
|
4125
|
+
};
|
|
4126
|
+
emit();
|
|
4127
|
+
try {
|
|
4128
|
+
const report = await fetchVoiceTraceTimeline(path, options);
|
|
4129
|
+
snapshot = {
|
|
4130
|
+
error: null,
|
|
4131
|
+
isLoading: false,
|
|
4132
|
+
report,
|
|
4133
|
+
updatedAt: Date.now()
|
|
4134
|
+
};
|
|
4135
|
+
emit();
|
|
4136
|
+
return report;
|
|
4137
|
+
} catch (error) {
|
|
4138
|
+
snapshot = {
|
|
4139
|
+
...snapshot,
|
|
4140
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4141
|
+
isLoading: false
|
|
4142
|
+
};
|
|
4143
|
+
emit();
|
|
4144
|
+
throw error;
|
|
4145
|
+
}
|
|
4146
|
+
};
|
|
4147
|
+
const close = () => {
|
|
4148
|
+
closed = true;
|
|
4149
|
+
if (timer) {
|
|
4150
|
+
clearInterval(timer);
|
|
4151
|
+
timer = undefined;
|
|
4152
|
+
}
|
|
4153
|
+
listeners.clear();
|
|
4154
|
+
};
|
|
4155
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
4156
|
+
timer = setInterval(() => {
|
|
4157
|
+
refresh().catch(() => {});
|
|
4158
|
+
}, options.intervalMs);
|
|
4159
|
+
}
|
|
4160
|
+
return {
|
|
4161
|
+
close,
|
|
4162
|
+
getServerSnapshot: () => snapshot,
|
|
4163
|
+
getSnapshot: () => snapshot,
|
|
4164
|
+
refresh,
|
|
4165
|
+
subscribe: (listener) => {
|
|
4166
|
+
listeners.add(listener);
|
|
4167
|
+
return () => {
|
|
4168
|
+
listeners.delete(listener);
|
|
4169
|
+
};
|
|
4170
|
+
}
|
|
4171
|
+
};
|
|
4172
|
+
};
|
|
4173
|
+
|
|
4174
|
+
// src/angular/voice-trace-timeline.service.ts
|
|
4175
|
+
var _dec = [
|
|
4176
|
+
Injectable21({ providedIn: "root" })
|
|
4177
|
+
];
|
|
4178
|
+
var _init = __decoratorStart(undefined);
|
|
4179
|
+
|
|
4180
|
+
class VoiceTraceTimelineService {
|
|
4181
|
+
connect(path = "/api/voice-traces", options = {}) {
|
|
4182
|
+
const store = createVoiceTraceTimelineStore(path, options);
|
|
4183
|
+
const errorSignal = signal21(null);
|
|
4184
|
+
const isLoadingSignal = signal21(false);
|
|
4185
|
+
const reportSignal = signal21(null);
|
|
4186
|
+
const updatedAtSignal = signal21(undefined);
|
|
4187
|
+
const sync = () => {
|
|
4188
|
+
const snapshot = store.getSnapshot();
|
|
4189
|
+
errorSignal.set(snapshot.error);
|
|
4190
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
4191
|
+
reportSignal.set(snapshot.report);
|
|
4192
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
4193
|
+
};
|
|
4194
|
+
const unsubscribe = store.subscribe(sync);
|
|
4195
|
+
sync();
|
|
4196
|
+
store.refresh().catch(() => {});
|
|
4197
|
+
return {
|
|
4198
|
+
close: () => {
|
|
4199
|
+
unsubscribe();
|
|
4200
|
+
store.close();
|
|
4201
|
+
},
|
|
4202
|
+
error: computed20(() => errorSignal()),
|
|
4203
|
+
isLoading: computed20(() => isLoadingSignal()),
|
|
4204
|
+
refresh: store.refresh,
|
|
4205
|
+
report: computed20(() => reportSignal()),
|
|
4206
|
+
updatedAt: computed20(() => updatedAtSignal())
|
|
4207
|
+
};
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
VoiceTraceTimelineService = __decorateElement(_init, 0, "VoiceTraceTimelineService", _dec, VoiceTraceTimelineService);
|
|
4211
|
+
__runInitializers(_init, 1, VoiceTraceTimelineService);
|
|
4212
|
+
__decoratorMetadata(_init, VoiceTraceTimelineService);
|
|
4213
|
+
let _VoiceTraceTimelineService = VoiceTraceTimelineService;
|
|
4214
|
+
// src/angular/voice-agent-squad-status.service.ts
|
|
4215
|
+
import { computed as computed21, Injectable as Injectable22, signal as signal22 } from "@angular/core";
|
|
4216
|
+
|
|
4217
|
+
// src/client/agentSquadStatus.ts
|
|
4218
|
+
var getString = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
4219
|
+
var getPayloadString = (event, key) => getString(event.payload?.[key]);
|
|
4220
|
+
var eventStatus = (event) => {
|
|
4221
|
+
const status = getPayloadString(event, "status");
|
|
4222
|
+
if (status === "blocked")
|
|
4223
|
+
return "blocked";
|
|
4224
|
+
if (status === "unknown-target")
|
|
4225
|
+
return "unknown-target";
|
|
4226
|
+
if (status === "allowed")
|
|
4227
|
+
return "handoff";
|
|
4228
|
+
return event.type === "agent.result" ? "active" : "handoff";
|
|
4229
|
+
};
|
|
4230
|
+
var deriveSessionSpecialist = (session) => {
|
|
4231
|
+
const events = [...session.events].sort((left, right) => left.at - right.at);
|
|
4232
|
+
const agentEvents = events.filter((event) => event.type === "agent.handoff" || event.type === "agent.context" || event.type === "agent.result" || event.type === "agent.model");
|
|
4233
|
+
const latest = agentEvents.at(-1);
|
|
4234
|
+
if (!latest) {
|
|
4235
|
+
return {
|
|
4236
|
+
lastEventAt: session.lastEventAt,
|
|
4237
|
+
sessionId: session.sessionId,
|
|
4238
|
+
status: "idle"
|
|
4239
|
+
};
|
|
4240
|
+
}
|
|
4241
|
+
const handoffEvents = events.filter((event) => event.type === "agent.handoff");
|
|
4242
|
+
const lastHandoff = handoffEvents.at(-1);
|
|
4243
|
+
const latestAgentId = getPayloadString(latest, "agentId");
|
|
4244
|
+
const handoffStatus = lastHandoff ? eventStatus(lastHandoff) : undefined;
|
|
4245
|
+
const currentTarget = handoffStatus === "blocked" || handoffStatus === "unknown-target" ? getPayloadString(lastHandoff, "fromAgentId") ?? latestAgentId : getPayloadString(lastHandoff ?? latest, "targetAgentId") ?? latestAgentId;
|
|
4246
|
+
return {
|
|
4247
|
+
fromAgentId: getPayloadString(lastHandoff ?? latest, "fromAgentId"),
|
|
4248
|
+
lastEventAt: latest.at,
|
|
4249
|
+
reason: getPayloadString(lastHandoff ?? latest, "reason") ?? getPayloadString(latest, "handoffTarget"),
|
|
4250
|
+
sessionId: session.sessionId,
|
|
4251
|
+
status: lastHandoff ? eventStatus(lastHandoff) : "active",
|
|
4252
|
+
summary: getPayloadString(lastHandoff ?? latest, "summary"),
|
|
4253
|
+
targetAgentId: currentTarget,
|
|
4254
|
+
turnId: latest.turnId
|
|
4255
|
+
};
|
|
4256
|
+
};
|
|
4257
|
+
var buildVoiceAgentSquadStatusReport = (timeline, options = {}) => {
|
|
4258
|
+
const sessions = (timeline?.sessions ?? []).filter((session) => !options.sessionId || session.sessionId === options.sessionId).map(deriveSessionSpecialist).sort((left, right) => (right.lastEventAt ?? 0) - (left.lastEventAt ?? 0));
|
|
4259
|
+
const active = sessions.filter((session) => session.status !== "idle");
|
|
4260
|
+
return {
|
|
4261
|
+
active,
|
|
4262
|
+
checkedAt: timeline?.checkedAt,
|
|
4263
|
+
current: active[0] ?? sessions[0],
|
|
4264
|
+
sessionCount: sessions.length,
|
|
4265
|
+
sessions
|
|
4266
|
+
};
|
|
4267
|
+
};
|
|
4268
|
+
var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}) => {
|
|
4269
|
+
const timelineStore = createVoiceTraceTimelineStore(path, options);
|
|
4270
|
+
const getReport = () => buildVoiceAgentSquadStatusReport(timelineStore.getSnapshot().report, {
|
|
4271
|
+
sessionId: options.sessionId
|
|
4272
|
+
});
|
|
4273
|
+
const getSnapshot = () => {
|
|
4274
|
+
const snapshot = timelineStore.getSnapshot();
|
|
4275
|
+
return {
|
|
4276
|
+
error: snapshot.error,
|
|
4277
|
+
isLoading: snapshot.isLoading,
|
|
4278
|
+
report: getReport(),
|
|
4279
|
+
updatedAt: snapshot.updatedAt
|
|
4280
|
+
};
|
|
4281
|
+
};
|
|
4282
|
+
return {
|
|
4283
|
+
close: timelineStore.close,
|
|
4284
|
+
getServerSnapshot: getSnapshot,
|
|
4285
|
+
getSnapshot,
|
|
4286
|
+
refresh: timelineStore.refresh,
|
|
4287
|
+
subscribe: timelineStore.subscribe
|
|
4288
|
+
};
|
|
4289
|
+
};
|
|
4290
|
+
|
|
4291
|
+
// src/angular/voice-agent-squad-status.service.ts
|
|
4292
|
+
var _dec = [
|
|
4293
|
+
Injectable22({ providedIn: "root" })
|
|
4294
|
+
];
|
|
4295
|
+
var _init = __decoratorStart(undefined);
|
|
4296
|
+
|
|
4297
|
+
class VoiceAgentSquadStatusService {
|
|
4298
|
+
connect(path = "/api/voice-traces", options = {}) {
|
|
4299
|
+
const store = createVoiceAgentSquadStatusStore(path, options);
|
|
4300
|
+
const errorSignal = signal22(null);
|
|
4301
|
+
const isLoadingSignal = signal22(false);
|
|
4302
|
+
const reportSignal = signal22(undefined);
|
|
4303
|
+
const updatedAtSignal = signal22(undefined);
|
|
4304
|
+
const sync = () => {
|
|
4305
|
+
const snapshot = store.getSnapshot();
|
|
4306
|
+
errorSignal.set(snapshot.error);
|
|
4307
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
4308
|
+
reportSignal.set(snapshot.report);
|
|
4309
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
4310
|
+
};
|
|
4311
|
+
const unsubscribe = store.subscribe(sync);
|
|
4312
|
+
sync();
|
|
4313
|
+
store.refresh().catch(() => {});
|
|
4314
|
+
return {
|
|
4315
|
+
close: () => {
|
|
4316
|
+
unsubscribe();
|
|
4317
|
+
store.close();
|
|
4318
|
+
},
|
|
4319
|
+
current: computed21(() => reportSignal()?.current),
|
|
4320
|
+
error: computed21(() => errorSignal()),
|
|
4321
|
+
isLoading: computed21(() => isLoadingSignal()),
|
|
4322
|
+
refresh: store.refresh,
|
|
4323
|
+
report: computed21(() => reportSignal()),
|
|
4324
|
+
updatedAt: computed21(() => updatedAtSignal())
|
|
4325
|
+
};
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
VoiceAgentSquadStatusService = __decorateElement(_init, 0, "VoiceAgentSquadStatusService", _dec, VoiceAgentSquadStatusService);
|
|
4329
|
+
__runInitializers(_init, 1, VoiceAgentSquadStatusService);
|
|
4330
|
+
__decoratorMetadata(_init, VoiceAgentSquadStatusService);
|
|
4331
|
+
let _VoiceAgentSquadStatusService = VoiceAgentSquadStatusService;
|
|
4332
|
+
// src/angular/voice-turn-latency.service.ts
|
|
4333
|
+
import { computed as computed22, Injectable as Injectable23, signal as signal23 } from "@angular/core";
|
|
4334
|
+
|
|
4335
|
+
// src/client/turnLatency.ts
|
|
4336
|
+
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
4337
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
4338
|
+
const response = await fetchImpl(path);
|
|
4339
|
+
if (!response.ok) {
|
|
4340
|
+
throw new Error(`Voice turn latency failed: HTTP ${response.status}`);
|
|
4341
|
+
}
|
|
4342
|
+
return await response.json();
|
|
4343
|
+
};
|
|
4344
|
+
var runVoiceTurnLatencyProof = async (path, options = {}) => {
|
|
4345
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
4346
|
+
const response = await fetchImpl(path, { method: "POST" });
|
|
4347
|
+
if (!response.ok) {
|
|
4348
|
+
throw new Error(`Voice turn latency proof failed: HTTP ${response.status}`);
|
|
4349
|
+
}
|
|
4350
|
+
return response.json();
|
|
4351
|
+
};
|
|
4352
|
+
var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) => {
|
|
4353
|
+
const listeners = new Set;
|
|
4354
|
+
let closed = false;
|
|
4355
|
+
let timer;
|
|
4356
|
+
let snapshot = {
|
|
4357
|
+
error: null,
|
|
4358
|
+
isLoading: false
|
|
4359
|
+
};
|
|
4360
|
+
const emit = () => {
|
|
4361
|
+
for (const listener of listeners) {
|
|
4362
|
+
listener();
|
|
4363
|
+
}
|
|
4364
|
+
};
|
|
4365
|
+
const refresh = async () => {
|
|
4366
|
+
if (closed) {
|
|
4367
|
+
return snapshot.report;
|
|
4368
|
+
}
|
|
4369
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
4370
|
+
emit();
|
|
4371
|
+
try {
|
|
4372
|
+
const report = await fetchVoiceTurnLatency(path, options);
|
|
4373
|
+
snapshot = {
|
|
4374
|
+
error: null,
|
|
4375
|
+
isLoading: false,
|
|
4376
|
+
report,
|
|
4377
|
+
updatedAt: Date.now()
|
|
4378
|
+
};
|
|
4379
|
+
emit();
|
|
4380
|
+
return report;
|
|
4381
|
+
} catch (error) {
|
|
4382
|
+
snapshot = {
|
|
4383
|
+
...snapshot,
|
|
4384
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4385
|
+
isLoading: false
|
|
4386
|
+
};
|
|
4387
|
+
emit();
|
|
4388
|
+
throw error;
|
|
4389
|
+
}
|
|
4390
|
+
};
|
|
4391
|
+
const runProof = async () => {
|
|
4392
|
+
if (!options.proofPath) {
|
|
4393
|
+
throw new Error("Voice turn latency proof path is not configured.");
|
|
4394
|
+
}
|
|
4395
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
4396
|
+
emit();
|
|
4397
|
+
try {
|
|
4398
|
+
await runVoiceTurnLatencyProof(options.proofPath, options);
|
|
4399
|
+
return await refresh();
|
|
4400
|
+
} catch (error) {
|
|
4401
|
+
snapshot = {
|
|
4402
|
+
...snapshot,
|
|
4403
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4404
|
+
isLoading: false
|
|
4405
|
+
};
|
|
4406
|
+
emit();
|
|
4407
|
+
throw error;
|
|
4408
|
+
}
|
|
4409
|
+
};
|
|
4410
|
+
const close = () => {
|
|
4411
|
+
closed = true;
|
|
4412
|
+
if (timer) {
|
|
4413
|
+
clearInterval(timer);
|
|
4414
|
+
timer = undefined;
|
|
4415
|
+
}
|
|
4416
|
+
listeners.clear();
|
|
4417
|
+
};
|
|
4418
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
4419
|
+
timer = setInterval(() => {
|
|
4420
|
+
refresh().catch(() => {});
|
|
4421
|
+
}, options.intervalMs);
|
|
4422
|
+
}
|
|
4423
|
+
return {
|
|
4424
|
+
close,
|
|
4425
|
+
getServerSnapshot: () => snapshot,
|
|
4426
|
+
getSnapshot: () => snapshot,
|
|
4427
|
+
refresh,
|
|
4428
|
+
runProof,
|
|
4429
|
+
subscribe: (listener) => {
|
|
4430
|
+
listeners.add(listener);
|
|
4431
|
+
return () => {
|
|
4432
|
+
listeners.delete(listener);
|
|
4433
|
+
};
|
|
4434
|
+
}
|
|
4435
|
+
};
|
|
4436
|
+
};
|
|
4437
|
+
|
|
4438
|
+
// src/angular/voice-turn-latency.service.ts
|
|
4439
|
+
var _dec = [
|
|
4440
|
+
Injectable23({ providedIn: "root" })
|
|
4441
|
+
];
|
|
4442
|
+
var _init = __decoratorStart(undefined);
|
|
4443
|
+
|
|
4444
|
+
class VoiceTurnLatencyService {
|
|
4445
|
+
connect(path = "/api/turn-latency", options = {}) {
|
|
4446
|
+
const store = createVoiceTurnLatencyStore(path, options);
|
|
4447
|
+
const errorSignal = signal23(null);
|
|
4448
|
+
const isLoadingSignal = signal23(false);
|
|
4449
|
+
const reportSignal = signal23(undefined);
|
|
4450
|
+
const updatedAtSignal = signal23(undefined);
|
|
4451
|
+
const sync = () => {
|
|
4452
|
+
const snapshot = store.getSnapshot();
|
|
4453
|
+
errorSignal.set(snapshot.error);
|
|
4454
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
4455
|
+
reportSignal.set(snapshot.report);
|
|
4456
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
4457
|
+
};
|
|
4458
|
+
const unsubscribe = store.subscribe(sync);
|
|
4459
|
+
sync();
|
|
4460
|
+
store.refresh().catch(() => {});
|
|
4461
|
+
return {
|
|
4462
|
+
close: () => {
|
|
4463
|
+
unsubscribe();
|
|
4464
|
+
store.close();
|
|
4465
|
+
},
|
|
4466
|
+
error: computed22(() => errorSignal()),
|
|
4467
|
+
isLoading: computed22(() => isLoadingSignal()),
|
|
4468
|
+
refresh: store.refresh,
|
|
4469
|
+
report: computed22(() => reportSignal()),
|
|
4470
|
+
runProof: store.runProof,
|
|
4471
|
+
updatedAt: computed22(() => updatedAtSignal())
|
|
4472
|
+
};
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
VoiceTurnLatencyService = __decorateElement(_init, 0, "VoiceTurnLatencyService", _dec, VoiceTurnLatencyService);
|
|
4476
|
+
__runInitializers(_init, 1, VoiceTurnLatencyService);
|
|
4477
|
+
__decoratorMetadata(_init, VoiceTurnLatencyService);
|
|
4478
|
+
let _VoiceTurnLatencyService = VoiceTurnLatencyService;
|
|
4479
|
+
// src/angular/voice-turn-quality.service.ts
|
|
4480
|
+
import { computed as computed23, Injectable as Injectable24, signal as signal24 } from "@angular/core";
|
|
4481
|
+
|
|
4482
|
+
// src/client/turnQuality.ts
|
|
4483
|
+
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
4484
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
4485
|
+
const response = await fetchImpl(path);
|
|
4486
|
+
if (!response.ok) {
|
|
4487
|
+
throw new Error(`Voice turn quality failed: HTTP ${response.status}`);
|
|
4488
|
+
}
|
|
4489
|
+
return await response.json();
|
|
4490
|
+
};
|
|
4491
|
+
var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) => {
|
|
4492
|
+
const listeners = new Set;
|
|
4493
|
+
let closed = false;
|
|
4494
|
+
let timer;
|
|
4495
|
+
let snapshot = {
|
|
4496
|
+
error: null,
|
|
4497
|
+
isLoading: false
|
|
4498
|
+
};
|
|
4499
|
+
const emit = () => {
|
|
4500
|
+
for (const listener of listeners) {
|
|
4501
|
+
listener();
|
|
4502
|
+
}
|
|
4503
|
+
};
|
|
4504
|
+
const refresh = async () => {
|
|
4505
|
+
if (closed) {
|
|
4506
|
+
return snapshot.report;
|
|
4507
|
+
}
|
|
4508
|
+
snapshot = {
|
|
4509
|
+
...snapshot,
|
|
4510
|
+
error: null,
|
|
4511
|
+
isLoading: true
|
|
4512
|
+
};
|
|
4513
|
+
emit();
|
|
4514
|
+
try {
|
|
4515
|
+
const report = await fetchVoiceTurnQuality(path, options);
|
|
4516
|
+
snapshot = {
|
|
4517
|
+
error: null,
|
|
4518
|
+
isLoading: false,
|
|
4519
|
+
report,
|
|
4520
|
+
updatedAt: Date.now()
|
|
4521
|
+
};
|
|
4522
|
+
emit();
|
|
4523
|
+
return report;
|
|
4524
|
+
} catch (error) {
|
|
4525
|
+
snapshot = {
|
|
4526
|
+
...snapshot,
|
|
4527
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4528
|
+
isLoading: false
|
|
4529
|
+
};
|
|
4530
|
+
emit();
|
|
4531
|
+
throw error;
|
|
4532
|
+
}
|
|
4533
|
+
};
|
|
4534
|
+
const close = () => {
|
|
4535
|
+
closed = true;
|
|
4536
|
+
if (timer) {
|
|
4537
|
+
clearInterval(timer);
|
|
4538
|
+
timer = undefined;
|
|
4539
|
+
}
|
|
4540
|
+
listeners.clear();
|
|
4541
|
+
};
|
|
4542
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
4543
|
+
timer = setInterval(() => {
|
|
4544
|
+
refresh().catch(() => {});
|
|
4545
|
+
}, options.intervalMs);
|
|
4546
|
+
}
|
|
4547
|
+
return {
|
|
4548
|
+
close,
|
|
4549
|
+
getServerSnapshot: () => snapshot,
|
|
4550
|
+
getSnapshot: () => snapshot,
|
|
4551
|
+
refresh,
|
|
4552
|
+
subscribe: (listener) => {
|
|
4553
|
+
listeners.add(listener);
|
|
4554
|
+
return () => {
|
|
4555
|
+
listeners.delete(listener);
|
|
4556
|
+
};
|
|
4557
|
+
}
|
|
4558
|
+
};
|
|
4559
|
+
};
|
|
4560
|
+
|
|
4561
|
+
// src/angular/voice-turn-quality.service.ts
|
|
4562
|
+
var _dec = [
|
|
4563
|
+
Injectable24({ providedIn: "root" })
|
|
4564
|
+
];
|
|
4565
|
+
var _init = __decoratorStart(undefined);
|
|
4566
|
+
|
|
4567
|
+
class VoiceTurnQualityService {
|
|
4568
|
+
connect(path = "/api/turn-quality", options = {}) {
|
|
4569
|
+
const store = createVoiceTurnQualityStore(path, options);
|
|
4570
|
+
const errorSignal = signal24(null);
|
|
4571
|
+
const isLoadingSignal = signal24(false);
|
|
4572
|
+
const reportSignal = signal24(undefined);
|
|
4573
|
+
const updatedAtSignal = signal24(undefined);
|
|
4574
|
+
const sync = () => {
|
|
4575
|
+
const snapshot = store.getSnapshot();
|
|
4576
|
+
errorSignal.set(snapshot.error);
|
|
4577
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
4578
|
+
reportSignal.set(snapshot.report);
|
|
4579
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
4580
|
+
};
|
|
4581
|
+
const unsubscribe = store.subscribe(sync);
|
|
4582
|
+
sync();
|
|
4583
|
+
store.refresh().catch(() => {});
|
|
4584
|
+
return {
|
|
4585
|
+
close: () => {
|
|
4586
|
+
unsubscribe();
|
|
4587
|
+
store.close();
|
|
4588
|
+
},
|
|
4589
|
+
error: computed23(() => errorSignal()),
|
|
4590
|
+
isLoading: computed23(() => isLoadingSignal()),
|
|
4591
|
+
refresh: store.refresh,
|
|
4592
|
+
report: computed23(() => reportSignal()),
|
|
4593
|
+
updatedAt: computed23(() => updatedAtSignal())
|
|
4594
|
+
};
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
VoiceTurnQualityService = __decorateElement(_init, 0, "VoiceTurnQualityService", _dec, VoiceTurnQualityService);
|
|
4598
|
+
__runInitializers(_init, 1, VoiceTurnQualityService);
|
|
4599
|
+
__decoratorMetadata(_init, VoiceTurnQualityService);
|
|
4600
|
+
let _VoiceTurnQualityService = VoiceTurnQualityService;
|
|
4601
|
+
// src/angular/voice-workflow-status.service.ts
|
|
4602
|
+
import { computed as computed24, Injectable as Injectable25, signal as signal25 } from "@angular/core";
|
|
4603
|
+
|
|
4604
|
+
// src/client/workflowStatus.ts
|
|
4605
|
+
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
4606
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
4607
|
+
const response = await fetchImpl(path);
|
|
4608
|
+
if (!response.ok) {
|
|
4609
|
+
throw new Error(`Voice workflow status failed: HTTP ${response.status}`);
|
|
4610
|
+
}
|
|
4611
|
+
return await response.json();
|
|
4612
|
+
};
|
|
4613
|
+
var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options = {}) => {
|
|
4614
|
+
const listeners = new Set;
|
|
4615
|
+
let closed = false;
|
|
4616
|
+
let timer;
|
|
4617
|
+
let snapshot = {
|
|
4618
|
+
error: null,
|
|
4619
|
+
isLoading: false
|
|
4620
|
+
};
|
|
4621
|
+
const emit = () => {
|
|
4622
|
+
for (const listener of listeners) {
|
|
4623
|
+
listener();
|
|
4624
|
+
}
|
|
4625
|
+
};
|
|
4626
|
+
const refresh = async () => {
|
|
4627
|
+
if (closed) {
|
|
4628
|
+
return snapshot.report;
|
|
4629
|
+
}
|
|
4630
|
+
snapshot = {
|
|
4631
|
+
...snapshot,
|
|
4632
|
+
error: null,
|
|
4633
|
+
isLoading: true
|
|
4634
|
+
};
|
|
4635
|
+
emit();
|
|
4636
|
+
try {
|
|
4637
|
+
const report = await fetchVoiceWorkflowStatus(path, options);
|
|
4638
|
+
snapshot = {
|
|
4639
|
+
error: null,
|
|
4640
|
+
isLoading: false,
|
|
4641
|
+
report,
|
|
4642
|
+
updatedAt: Date.now()
|
|
4643
|
+
};
|
|
4644
|
+
emit();
|
|
4645
|
+
return report;
|
|
4646
|
+
} catch (error) {
|
|
4647
|
+
snapshot = {
|
|
4648
|
+
...snapshot,
|
|
4649
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4650
|
+
isLoading: false
|
|
4651
|
+
};
|
|
4652
|
+
emit();
|
|
4653
|
+
throw error;
|
|
4654
|
+
}
|
|
4655
|
+
};
|
|
4656
|
+
const close = () => {
|
|
4657
|
+
closed = true;
|
|
4658
|
+
if (timer) {
|
|
4659
|
+
clearInterval(timer);
|
|
4660
|
+
timer = undefined;
|
|
4661
|
+
}
|
|
4662
|
+
listeners.clear();
|
|
4663
|
+
};
|
|
4664
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
4665
|
+
timer = setInterval(() => {
|
|
4666
|
+
refresh().catch(() => {});
|
|
4667
|
+
}, options.intervalMs);
|
|
4668
|
+
}
|
|
4669
|
+
return {
|
|
4670
|
+
close,
|
|
4671
|
+
getServerSnapshot: () => snapshot,
|
|
4672
|
+
getSnapshot: () => snapshot,
|
|
4673
|
+
refresh,
|
|
4674
|
+
subscribe: (listener) => {
|
|
4675
|
+
listeners.add(listener);
|
|
4676
|
+
return () => {
|
|
4677
|
+
listeners.delete(listener);
|
|
4678
|
+
};
|
|
4679
|
+
}
|
|
4680
|
+
};
|
|
4681
|
+
};
|
|
4682
|
+
|
|
4683
|
+
// src/angular/voice-workflow-status.service.ts
|
|
4684
|
+
var _dec = [
|
|
4685
|
+
Injectable25({ providedIn: "root" })
|
|
4686
|
+
];
|
|
4687
|
+
var _init = __decoratorStart(undefined);
|
|
4688
|
+
|
|
4689
|
+
class VoiceWorkflowStatusService {
|
|
4690
|
+
connect(path = "/evals/scenarios/json", options = {}) {
|
|
4691
|
+
const store = createVoiceWorkflowStatusStore(path, options);
|
|
4692
|
+
const errorSignal = signal25(null);
|
|
4693
|
+
const isLoadingSignal = signal25(false);
|
|
4694
|
+
const reportSignal = signal25(undefined);
|
|
4695
|
+
const updatedAtSignal = signal25(undefined);
|
|
4696
|
+
const sync = () => {
|
|
4697
|
+
const snapshot = store.getSnapshot();
|
|
4698
|
+
errorSignal.set(snapshot.error);
|
|
4699
|
+
isLoadingSignal.set(snapshot.isLoading);
|
|
4700
|
+
reportSignal.set(snapshot.report);
|
|
4701
|
+
updatedAtSignal.set(snapshot.updatedAt);
|
|
4702
|
+
};
|
|
4703
|
+
const unsubscribe = store.subscribe(sync);
|
|
4704
|
+
sync();
|
|
4705
|
+
if (typeof window !== "undefined") {
|
|
4706
|
+
store.refresh().catch(() => {});
|
|
4707
|
+
}
|
|
4708
|
+
return {
|
|
4709
|
+
close: () => {
|
|
4710
|
+
unsubscribe();
|
|
4711
|
+
store.close();
|
|
4712
|
+
},
|
|
4713
|
+
error: computed24(() => errorSignal()),
|
|
4714
|
+
isLoading: computed24(() => isLoadingSignal()),
|
|
4715
|
+
refresh: store.refresh,
|
|
4716
|
+
report: computed24(() => reportSignal()),
|
|
4717
|
+
updatedAt: computed24(() => updatedAtSignal())
|
|
4718
|
+
};
|
|
4719
|
+
}
|
|
4720
|
+
}
|
|
4721
|
+
VoiceWorkflowStatusService = __decorateElement(_init, 0, "VoiceWorkflowStatusService", _dec, VoiceWorkflowStatusService);
|
|
4722
|
+
__runInitializers(_init, 1, VoiceWorkflowStatusService);
|
|
4723
|
+
__decoratorMetadata(_init, VoiceWorkflowStatusService);
|
|
4724
|
+
let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
|
|
1291
4725
|
export {
|
|
4726
|
+
VoiceWorkflowStatusService,
|
|
4727
|
+
VoiceWidgetService,
|
|
4728
|
+
VoiceTurnQualityService,
|
|
4729
|
+
VoiceTurnLatencyService,
|
|
4730
|
+
VoiceTraceTimelineService,
|
|
1292
4731
|
VoiceStreamService,
|
|
1293
|
-
|
|
4732
|
+
VoiceSessionSnapshotService,
|
|
4733
|
+
VoiceSessionObservabilityService,
|
|
4734
|
+
VoiceRoutingStatusService,
|
|
4735
|
+
VoiceReconnectProfileEvidenceService,
|
|
4736
|
+
VoiceReadinessFailuresService,
|
|
4737
|
+
VoiceProviderStatusService,
|
|
4738
|
+
VoiceProviderContractsService,
|
|
4739
|
+
VoiceProviderCapabilitiesService,
|
|
4740
|
+
VoiceProofTrendsService,
|
|
4741
|
+
VoiceProfileComparisonService,
|
|
4742
|
+
VoicePlatformCoverageService,
|
|
4743
|
+
VoiceOpsStatusService,
|
|
4744
|
+
VoiceOpsActionCenterService,
|
|
4745
|
+
VoiceLiveOpsService,
|
|
4746
|
+
VoiceDeliveryRuntimeService,
|
|
4747
|
+
VoiceControllerService,
|
|
4748
|
+
VoiceCampaignDialerProofService,
|
|
4749
|
+
VoiceCallDebuggerService,
|
|
4750
|
+
VoiceAgentSquadStatusService
|
|
1294
4751
|
};
|