@absolutejs/voice 0.0.22-beta.439 → 0.0.22-beta.441
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 +2729 -2698
- package/dist/agent.d.ts +10 -10
- package/dist/agentSquadContract.d.ts +4 -4
- package/dist/angular/index.d.ts +22 -22
- package/dist/angular/voice-agent-squad-status.service.d.ts +1 -1
- package/dist/angular/voice-call-debugger.service.d.ts +2 -2
- package/dist/angular/voice-campaign-dialer-proof.service.d.ts +2 -2
- package/dist/angular/voice-controller.service.d.ts +1 -1
- package/dist/angular/voice-delivery-runtime.component.d.ts +2 -2
- package/dist/angular/voice-delivery-runtime.service.d.ts +2 -2
- package/dist/angular/voice-live-ops.service.d.ts +1 -1
- package/dist/angular/voice-ops-action-center.service.d.ts +1 -1
- package/dist/angular/voice-ops-status.component.d.ts +2 -2
- package/dist/angular/voice-ops-status.service.d.ts +2 -2
- package/dist/angular/voice-platform-coverage.service.d.ts +2 -2
- package/dist/angular/voice-profile-comparison.service.d.ts +2 -2
- package/dist/angular/voice-proof-trends.service.d.ts +2 -2
- package/dist/angular/voice-provider-capabilities.service.d.ts +2 -2
- package/dist/angular/voice-provider-contracts.service.d.ts +2 -2
- package/dist/angular/voice-provider-status.service.d.ts +2 -2
- package/dist/angular/voice-readiness-failures.service.d.ts +2 -2
- package/dist/angular/voice-routing-status.service.d.ts +1 -1
- package/dist/angular/voice-session-snapshot.service.d.ts +2 -2
- package/dist/angular/voice-stream.service.d.ts +1 -1
- package/dist/angular/voice-trace-timeline.service.d.ts +2 -2
- package/dist/angular/voice-turn-latency.service.d.ts +2 -2
- package/dist/angular/voice-turn-quality.service.d.ts +2 -2
- package/dist/angular/voice-workflow-status.service.d.ts +2 -2
- package/dist/assistant.d.ts +11 -11
- package/dist/assistantHealth.d.ts +6 -6
- package/dist/assistantMemory.d.ts +3 -3
- package/dist/audioConditioning.d.ts +1 -1
- package/dist/audit.d.ts +11 -11
- package/dist/auditDeliveryRoutes.d.ts +3 -3
- package/dist/auditExport.d.ts +3 -3
- package/dist/auditRoutes.d.ts +2 -2
- package/dist/auditSinks.d.ts +8 -8
- package/dist/bargeInRoutes.d.ts +3 -3
- package/dist/browserCallProfiles.d.ts +2 -2
- package/dist/browserMediaRoutes.d.ts +4 -4
- package/dist/callDebugger.d.ts +6 -6
- package/dist/campaign.d.ts +22 -22
- package/dist/campaignDialers.d.ts +14 -14
- package/dist/client/actions.d.ts +1 -1
- package/dist/client/agentSquadStatus.d.ts +3 -3
- package/dist/client/agentSquadStatusWidget.d.ts +1 -1
- package/dist/client/audioPlayer.d.ts +2 -2
- package/dist/client/bargeInMonitor.d.ts +1 -1
- package/dist/client/browserMedia.d.ts +1 -1
- package/dist/client/callDebugger.d.ts +1 -1
- package/dist/client/callDebuggerWidget.d.ts +3 -3
- package/dist/client/campaignDialerProof.d.ts +1 -1
- package/dist/client/connection.d.ts +3 -3
- package/dist/client/controller.d.ts +1 -1
- package/dist/client/createVoiceStream.d.ts +1 -1
- package/dist/client/deliveryRuntime.d.ts +4 -4
- package/dist/client/deliveryRuntimeWidget.d.ts +5 -5
- package/dist/client/duplex.d.ts +1 -1
- package/dist/client/htmx.d.ts +1 -1
- package/dist/client/index.d.ts +96 -96
- package/dist/client/index.js +41 -15
- package/dist/client/liveOps.d.ts +2 -2
- package/dist/client/liveOpsWidget.d.ts +2 -2
- package/dist/client/liveTurnLatency.d.ts +3 -3
- package/dist/client/microphone.d.ts +4 -4
- package/dist/client/opsActionCenter.d.ts +1 -1
- package/dist/client/opsActionCenterWidget.d.ts +2 -2
- package/dist/client/opsActionHistory.d.ts +1 -1
- package/dist/client/opsActionHistoryWidget.d.ts +1 -1
- package/dist/client/opsStatus.d.ts +1 -1
- package/dist/client/opsStatusWidget.d.ts +4 -4
- package/dist/client/platformCoverage.d.ts +1 -1
- package/dist/client/platformCoverageWidget.d.ts +3 -3
- package/dist/client/profileComparison.d.ts +1 -1
- package/dist/client/profileComparisonWidget.d.ts +2 -2
- package/dist/client/profileSwitchRecommendation.d.ts +1 -1
- package/dist/client/profileSwitchRecommendationWidget.d.ts +1 -1
- package/dist/client/proofTrends.d.ts +1 -1
- package/dist/client/proofTrendsWidget.d.ts +3 -3
- package/dist/client/providerCapabilities.d.ts +1 -1
- package/dist/client/providerCapabilitiesWidget.d.ts +3 -3
- package/dist/client/providerContracts.d.ts +1 -1
- package/dist/client/providerContractsWidget.d.ts +3 -3
- package/dist/client/providerSimulationControls.d.ts +2 -2
- package/dist/client/providerSimulationControlsWidget.d.ts +1 -1
- package/dist/client/providerStatus.d.ts +1 -1
- package/dist/client/providerStatusWidget.d.ts +3 -3
- package/dist/client/readinessFailures.d.ts +1 -1
- package/dist/client/readinessFailuresWidget.d.ts +4 -4
- package/dist/client/routingStatus.d.ts +1 -1
- package/dist/client/routingStatusWidget.d.ts +3 -3
- package/dist/client/sessionSnapshot.d.ts +1 -1
- package/dist/client/sessionSnapshotWidget.d.ts +2 -2
- package/dist/client/store.d.ts +1 -1
- package/dist/client/traceTimeline.d.ts +1 -1
- package/dist/client/traceTimelineWidget.d.ts +3 -3
- package/dist/client/turnLatency.d.ts +1 -1
- package/dist/client/turnLatencyWidget.d.ts +3 -3
- package/dist/client/turnQuality.d.ts +1 -1
- package/dist/client/turnQualityWidget.d.ts +3 -3
- package/dist/client/workflowStatus.d.ts +1 -1
- package/dist/competitiveCoverage.d.ts +9 -9
- package/dist/correction.d.ts +2 -2
- package/dist/dataControl.d.ts +16 -16
- package/dist/deliveryRuntime.d.ts +9 -9
- package/dist/deliverySinkRoutes.d.ts +6 -6
- package/dist/demoReadyRoutes.d.ts +8 -8
- package/dist/diagnosticsRoutes.d.ts +2 -2
- package/dist/evalRoutes.d.ts +4 -4
- package/dist/fileStore.d.ts +9 -9
- package/dist/guardrails.d.ts +9 -9
- package/dist/handoff.d.ts +6 -6
- package/dist/handoffHealth.d.ts +5 -5
- package/dist/htmx.d.ts +1 -1
- package/dist/incidentBundle.d.ts +7 -7
- package/dist/incidentTimeline.d.ts +30 -16
- package/dist/index.d.ts +215 -215
- package/dist/index.js +375 -111
- package/dist/latencySlo.d.ts +4 -4
- package/dist/liveLatency.d.ts +3 -3
- package/dist/liveOps.d.ts +11 -11
- package/dist/logger.d.ts +1 -1
- package/dist/mediaPipelineRoutes.d.ts +2 -2
- package/dist/memoryStore.d.ts +1 -1
- package/dist/modelAdapters.d.ts +9 -9
- package/dist/observabilityExport.d.ts +44 -44
- package/dist/openaiTTS.d.ts +3 -3
- package/dist/operationalStatus.d.ts +5 -5
- package/dist/operationsRecord.d.ts +12 -12
- package/dist/ops.d.ts +12 -12
- package/dist/opsActionAuditRoutes.d.ts +3 -3
- package/dist/opsConsoleRoutes.d.ts +6 -6
- package/dist/opsPresets.d.ts +2 -2
- package/dist/opsRecovery.d.ts +11 -11
- package/dist/opsRuntime.d.ts +6 -6
- package/dist/opsSinks.d.ts +13 -13
- package/dist/opsStatus.d.ts +7 -7
- package/dist/opsStatusRoutes.d.ts +2 -2
- package/dist/opsWebhook.d.ts +6 -6
- package/dist/outcomeContract.d.ts +5 -5
- package/dist/outcomeRecipes.d.ts +4 -4
- package/dist/phoneAgent.d.ts +18 -18
- package/dist/phoneAgentProductionSmoke.d.ts +8 -8
- package/dist/platformCoverage.d.ts +3 -3
- package/dist/plugin.d.ts +2 -2
- package/dist/postCallAnalysis.d.ts +6 -6
- package/dist/postgresStore.d.ts +8 -8
- package/dist/presets.d.ts +3 -3
- package/dist/productionReadiness.d.ts +62 -36
- package/dist/profileSwitchRecommendation.d.ts +15 -15
- package/dist/proofAssertions.d.ts +1 -1
- package/dist/proofPack.d.ts +12 -12
- package/dist/proofRunner.d.ts +5 -5
- package/dist/proofTrends.d.ts +17 -17
- package/dist/providerAdapters.d.ts +5 -5
- package/dist/providerCapabilities.d.ts +4 -4
- package/dist/providerDecisionTraces.d.ts +8 -8
- package/dist/providerHealth.d.ts +3 -3
- package/dist/providerOrchestration.d.ts +5 -5
- package/dist/providerRouterTraces.d.ts +7 -7
- package/dist/providerRoutingContract.d.ts +3 -3
- package/dist/providerSlo.d.ts +6 -6
- package/dist/providerStackRecommendations.d.ts +6 -6
- package/dist/qualityRoutes.d.ts +4 -4
- package/dist/queue.d.ts +16 -16
- package/dist/react/VoiceAgentSquadStatus.d.ts +1 -1
- package/dist/react/VoiceCallDebuggerLaunch.d.ts +1 -1
- package/dist/react/VoiceDeliveryRuntime.d.ts +1 -1
- package/dist/react/VoiceOpsActionCenter.d.ts +1 -1
- package/dist/react/VoiceOpsStatus.d.ts +1 -1
- package/dist/react/VoicePlatformCoverage.d.ts +1 -1
- package/dist/react/VoiceProfileComparison.d.ts +1 -1
- package/dist/react/VoiceProfileSwitchRecommendation.d.ts +1 -1
- package/dist/react/VoiceProofTrends.d.ts +1 -1
- package/dist/react/VoiceProviderCapabilities.d.ts +1 -1
- package/dist/react/VoiceProviderContracts.d.ts +1 -1
- package/dist/react/VoiceProviderSimulationControls.d.ts +1 -1
- package/dist/react/VoiceProviderStatus.d.ts +1 -1
- package/dist/react/VoiceReadinessFailures.d.ts +1 -1
- package/dist/react/VoiceRoutingStatus.d.ts +1 -1
- package/dist/react/VoiceSessionSnapshot.d.ts +1 -1
- package/dist/react/VoiceTraceTimeline.d.ts +1 -1
- package/dist/react/VoiceTurnLatency.d.ts +1 -1
- package/dist/react/VoiceTurnQuality.d.ts +1 -1
- package/dist/react/index.d.ts +43 -43
- package/dist/react/index.js +41 -15
- package/dist/react/useVoiceAgentSquadStatus.d.ts +1 -1
- package/dist/react/useVoiceCallDebugger.d.ts +1 -1
- package/dist/react/useVoiceCampaignDialerProof.d.ts +1 -1
- package/dist/react/useVoiceController.d.ts +1 -1
- package/dist/react/useVoiceDeliveryRuntime.d.ts +1 -1
- package/dist/react/useVoiceLiveOps.d.ts +1 -1
- package/dist/react/useVoiceOpsActionCenter.d.ts +1 -1
- package/dist/react/useVoiceOpsStatus.d.ts +1 -1
- package/dist/react/useVoicePlatformCoverage.d.ts +1 -1
- package/dist/react/useVoiceProfileComparison.d.ts +1 -1
- package/dist/react/useVoiceProfileSwitchRecommendation.d.ts +1 -1
- package/dist/react/useVoiceProofTrends.d.ts +1 -1
- package/dist/react/useVoiceProviderCapabilities.d.ts +1 -1
- package/dist/react/useVoiceProviderContracts.d.ts +1 -1
- package/dist/react/useVoiceProviderSimulationControls.d.ts +1 -1
- package/dist/react/useVoiceProviderStatus.d.ts +1 -1
- package/dist/react/useVoiceReadinessFailures.d.ts +1 -1
- package/dist/react/useVoiceRoutingStatus.d.ts +1 -1
- package/dist/react/useVoiceSessionSnapshot.d.ts +1 -1
- package/dist/react/useVoiceStream.d.ts +1 -1
- package/dist/react/useVoiceTraceTimeline.d.ts +1 -1
- package/dist/react/useVoiceTurnLatency.d.ts +1 -1
- package/dist/react/useVoiceTurnQuality.d.ts +1 -1
- package/dist/react/useVoiceWorkflowStatus.d.ts +1 -1
- package/dist/readinessProfiles.d.ts +22 -15
- package/dist/realtimeChannel.d.ts +6 -6
- package/dist/realtimeProviderContracts.d.ts +7 -7
- package/dist/reconnectContract.d.ts +6 -6
- package/dist/resilienceRoutes.d.ts +6 -6
- package/dist/routing.d.ts +1 -1
- package/dist/runtimeOps.d.ts +3 -3
- package/dist/s3Store.d.ts +3 -3
- package/dist/session.d.ts +1 -1
- package/dist/sessionReplay.d.ts +9 -9
- package/dist/sessionSnapshot.d.ts +8 -8
- package/dist/simulationSuite.d.ts +12 -12
- package/dist/sloCalibration.d.ts +8 -8
- package/dist/sqliteStore.d.ts +8 -8
- package/dist/store.d.ts +1 -1
- package/dist/svelte/createVoiceAgentSquadStatus.d.ts +1 -1
- package/dist/svelte/createVoiceCallDebugger.d.ts +2 -2
- package/dist/svelte/createVoiceCampaignDialerProof.d.ts +1 -1
- package/dist/svelte/createVoiceDeliveryRuntime.d.ts +1 -1
- package/dist/svelte/createVoiceLiveOps.d.ts +2 -2
- package/dist/svelte/createVoiceOpsActionCenter.d.ts +1 -1
- package/dist/svelte/createVoiceOpsStatus.d.ts +1 -1
- package/dist/svelte/createVoicePlatformCoverage.d.ts +1 -1
- package/dist/svelte/createVoiceProfileComparison.d.ts +1 -1
- package/dist/svelte/createVoiceProofTrends.d.ts +1 -1
- package/dist/svelte/createVoiceProviderCapabilities.d.ts +1 -1
- package/dist/svelte/createVoiceProviderContracts.d.ts +1 -1
- package/dist/svelte/createVoiceProviderSimulationControls.d.ts +1 -1
- package/dist/svelte/createVoiceProviderStatus.d.ts +1 -1
- package/dist/svelte/createVoiceReadinessFailures.d.ts +1 -1
- package/dist/svelte/createVoiceRoutingStatus.d.ts +1 -1
- package/dist/svelte/createVoiceSessionSnapshot.d.ts +2 -2
- package/dist/svelte/createVoiceStream.d.ts +1 -1
- package/dist/svelte/createVoiceTraceTimeline.d.ts +1 -1
- package/dist/svelte/createVoiceTurnLatency.d.ts +1 -1
- package/dist/svelte/createVoiceTurnQuality.d.ts +1 -1
- package/dist/svelte/createVoiceWorkflowStatus.d.ts +1 -1
- package/dist/svelte/index.d.ts +23 -23
- package/dist/svelte/index.js +30 -8
- package/dist/telephony/contract.d.ts +5 -5
- package/dist/telephony/matrix.d.ts +4 -4
- package/dist/telephony/plivo.d.ts +30 -30
- package/dist/telephony/response.d.ts +1 -1
- package/dist/telephony/security.d.ts +17 -17
- package/dist/telephony/telnyx.d.ts +31 -31
- package/dist/telephony/twilio.d.ts +22 -22
- package/dist/telephonyMediaRoutes.d.ts +4 -4
- package/dist/telephonyOutcome.d.ts +13 -13
- package/dist/testing/accuracy.d.ts +1 -1
- package/dist/testing/benchmark.d.ts +9 -9
- package/dist/testing/corrected.d.ts +5 -5
- package/dist/testing/duplex.d.ts +3 -3
- package/dist/testing/fixtures.d.ts +3 -3
- package/dist/testing/index.d.ts +13 -13
- package/dist/testing/index.js +49 -20
- package/dist/testing/ioProviderSimulator.d.ts +5 -5
- package/dist/testing/providerSimulator.d.ts +5 -5
- package/dist/testing/review.d.ts +4 -4
- package/dist/testing/sessionBenchmark.d.ts +3 -3
- package/dist/testing/stt.d.ts +3 -3
- package/dist/testing/telephony.d.ts +3 -3
- package/dist/testing/tts.d.ts +1 -1
- package/dist/toolContract.d.ts +10 -10
- package/dist/toolRuntime.d.ts +3 -3
- package/dist/trace.d.ts +10 -10
- package/dist/traceDeliveryRoutes.d.ts +4 -4
- package/dist/traceTimeline.d.ts +4 -4
- package/dist/turnDetection.d.ts +1 -1
- package/dist/turnLatency.d.ts +4 -4
- package/dist/turnProfiles.d.ts +2 -2
- package/dist/turnQuality.d.ts +4 -4
- package/dist/types.d.ts +92 -92
- package/dist/voiceMonitoring.d.ts +6 -6
- package/dist/vue/VoiceOpsActionCenter.d.ts +2 -2
- package/dist/vue/VoiceProviderSimulationControls.d.ts +2 -2
- package/dist/vue/index.d.ts +38 -38
- package/dist/vue/index.js +41 -15
- package/dist/vue/useVoiceAgentSquadStatus.d.ts +1 -1
- package/dist/vue/useVoiceCallDebugger.d.ts +2 -2
- package/dist/vue/useVoiceCampaignDialerProof.d.ts +2 -2
- package/dist/vue/useVoiceController.d.ts +1 -1
- package/dist/vue/useVoiceDeliveryRuntime.d.ts +2 -2
- package/dist/vue/useVoiceLiveOps.d.ts +1 -1
- package/dist/vue/useVoiceOpsActionCenter.d.ts +1 -1
- package/dist/vue/useVoiceOpsStatus.d.ts +2 -2
- package/dist/vue/useVoicePlatformCoverage.d.ts +2 -2
- package/dist/vue/useVoiceProfileComparison.d.ts +2 -2
- package/dist/vue/useVoiceProofTrends.d.ts +2 -2
- package/dist/vue/useVoiceProviderCapabilities.d.ts +2 -2
- package/dist/vue/useVoiceProviderContracts.d.ts +2 -2
- package/dist/vue/useVoiceProviderSimulationControls.d.ts +1 -1
- package/dist/vue/useVoiceProviderStatus.d.ts +2 -2
- package/dist/vue/useVoiceReadinessFailures.d.ts +30 -2
- package/dist/vue/useVoiceRoutingStatus.d.ts +1 -1
- package/dist/vue/useVoiceSessionSnapshot.d.ts +2 -2
- package/dist/vue/useVoiceStream.d.ts +1 -1
- package/dist/vue/useVoiceTraceTimeline.d.ts +2 -2
- package/dist/vue/useVoiceTurnLatency.d.ts +2 -2
- package/dist/vue/useVoiceTurnQuality.d.ts +2 -2
- package/dist/vue/useVoiceWorkflowStatus.d.ts +2 -2
- package/dist/workflowContract.d.ts +8 -8
- package/fixtures/manifest.json +356 -197
- package/package.json +260 -259
package/dist/index.js
CHANGED
|
@@ -1830,10 +1830,7 @@ var createVoiceZendeskTicketUpdateSink = (options) => {
|
|
|
1830
1830
|
}
|
|
1831
1831
|
});
|
|
1832
1832
|
},
|
|
1833
|
-
eventTypes: options.eventTypes ?? [
|
|
1834
|
-
"task.updated",
|
|
1835
|
-
"task.sla_breached"
|
|
1836
|
-
],
|
|
1833
|
+
eventTypes: options.eventTypes ?? ["task.updated", "task.sla_breached"],
|
|
1837
1834
|
id: options.id,
|
|
1838
1835
|
kind: options.kind ?? "zendesk-ticket-update"
|
|
1839
1836
|
};
|
|
@@ -1844,19 +1841,13 @@ var createVoiceZendeskTicketSyncSinks = (options) => {
|
|
|
1844
1841
|
createVoiceZendeskTicketSink({
|
|
1845
1842
|
...baseOptions,
|
|
1846
1843
|
...create,
|
|
1847
|
-
eventTypes: create?.eventTypes ?? [
|
|
1848
|
-
"review.saved",
|
|
1849
|
-
"task.created"
|
|
1850
|
-
],
|
|
1844
|
+
eventTypes: create?.eventTypes ?? ["review.saved", "task.created"],
|
|
1851
1845
|
id: createId ?? create?.id ?? options.id
|
|
1852
1846
|
}),
|
|
1853
1847
|
createVoiceZendeskTicketUpdateSink({
|
|
1854
1848
|
...baseOptions,
|
|
1855
1849
|
...update,
|
|
1856
|
-
eventTypes: update?.eventTypes ?? [
|
|
1857
|
-
"task.updated",
|
|
1858
|
-
"task.sla_breached"
|
|
1859
|
-
],
|
|
1850
|
+
eventTypes: update?.eventTypes ?? ["task.updated", "task.sla_breached"],
|
|
1860
1851
|
id: updateId ?? update?.id ?? `${options.id}:update`
|
|
1861
1852
|
})
|
|
1862
1853
|
];
|
|
@@ -1961,10 +1952,7 @@ var createVoiceHubSpotTaskUpdateSink = (options) => {
|
|
|
1961
1952
|
}
|
|
1962
1953
|
});
|
|
1963
1954
|
},
|
|
1964
|
-
eventTypes: options.eventTypes ?? [
|
|
1965
|
-
"task.updated",
|
|
1966
|
-
"task.sla_breached"
|
|
1967
|
-
],
|
|
1955
|
+
eventTypes: options.eventTypes ?? ["task.updated", "task.sla_breached"],
|
|
1968
1956
|
id: options.id,
|
|
1969
1957
|
kind: options.kind ?? "hubspot-task-update"
|
|
1970
1958
|
};
|
|
@@ -1981,10 +1969,7 @@ var createVoiceHubSpotTaskSyncSinks = (options) => {
|
|
|
1981
1969
|
createVoiceHubSpotTaskUpdateSink({
|
|
1982
1970
|
...baseOptions,
|
|
1983
1971
|
...update,
|
|
1984
|
-
eventTypes: update?.eventTypes ?? [
|
|
1985
|
-
"task.updated",
|
|
1986
|
-
"task.sla_breached"
|
|
1987
|
-
],
|
|
1972
|
+
eventTypes: update?.eventTypes ?? ["task.updated", "task.sla_breached"],
|
|
1988
1973
|
id: updateId ?? update?.id ?? `${options.id}:update`
|
|
1989
1974
|
})
|
|
1990
1975
|
];
|
|
@@ -2061,19 +2046,13 @@ var createVoiceLinearIssueSyncSinks = (options) => {
|
|
|
2061
2046
|
createVoiceLinearIssueSink({
|
|
2062
2047
|
...baseOptions,
|
|
2063
2048
|
...create,
|
|
2064
|
-
eventTypes: create?.eventTypes ?? [
|
|
2065
|
-
"review.saved",
|
|
2066
|
-
"task.created"
|
|
2067
|
-
],
|
|
2049
|
+
eventTypes: create?.eventTypes ?? ["review.saved", "task.created"],
|
|
2068
2050
|
id: createId ?? create?.id ?? options.id
|
|
2069
2051
|
}),
|
|
2070
2052
|
createVoiceLinearIssueUpdateSink({
|
|
2071
2053
|
...baseOptions,
|
|
2072
2054
|
...update,
|
|
2073
|
-
eventTypes: update?.eventTypes ?? [
|
|
2074
|
-
"task.updated",
|
|
2075
|
-
"task.sla_breached"
|
|
2076
|
-
],
|
|
2055
|
+
eventTypes: update?.eventTypes ?? ["task.updated", "task.sla_breached"],
|
|
2077
2056
|
id: updateId ?? update?.id ?? `${options.id}:update`
|
|
2078
2057
|
})
|
|
2079
2058
|
];
|
|
@@ -2136,10 +2115,7 @@ var createVoiceLinearIssueUpdateSink = (options) => {
|
|
|
2136
2115
|
}
|
|
2137
2116
|
});
|
|
2138
2117
|
},
|
|
2139
|
-
eventTypes: options.eventTypes ?? [
|
|
2140
|
-
"task.updated",
|
|
2141
|
-
"task.sla_breached"
|
|
2142
|
-
],
|
|
2118
|
+
eventTypes: options.eventTypes ?? ["task.updated", "task.sla_breached"],
|
|
2143
2119
|
id: options.id,
|
|
2144
2120
|
kind: options.kind ?? "linear-issue-update"
|
|
2145
2121
|
};
|
|
@@ -5463,7 +5439,9 @@ var recommendVoiceProfileSwitch = (options) => {
|
|
|
5463
5439
|
const recommended = candidates.slice().sort((left, right) => scoreProfile(left, observed) - scoreProfile(right, observed))[0];
|
|
5464
5440
|
const issues = [
|
|
5465
5441
|
...defaults.profiles.length === 0 ? ["No measured profile defaults are available."] : [],
|
|
5466
|
-
...!currentProfile && currentProfileId ? [
|
|
5442
|
+
...!currentProfile && currentProfileId ? [
|
|
5443
|
+
`Current profile ${currentProfileId} is not present in measured defaults.`
|
|
5444
|
+
] : [],
|
|
5467
5445
|
...!recommended ? ["No non-failing measured profile can be recommended."] : []
|
|
5468
5446
|
];
|
|
5469
5447
|
const currentOverBudget = currentProfile ? [
|
|
@@ -5994,7 +5972,9 @@ var createVoiceProfileSwitchReadinessRoutes = (options) => {
|
|
|
5994
5972
|
limit: typeof query.limit === "string" && Number.isFinite(Number(query.limit)) ? Number(query.limit) : options.limit,
|
|
5995
5973
|
sessionId: typeof query.sessionId === "string" && query.sessionId.trim() ? query.sessionId.trim() : options.sessionId
|
|
5996
5974
|
});
|
|
5997
|
-
const render = options.render ?? ((input) => renderVoiceProfileSwitchReadinessHTML(input, {
|
|
5975
|
+
const render = options.render ?? ((input) => renderVoiceProfileSwitchReadinessHTML(input, {
|
|
5976
|
+
title: options.title
|
|
5977
|
+
}));
|
|
5998
5978
|
return new Response(await render(report), {
|
|
5999
5979
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
6000
5980
|
});
|
|
@@ -7704,10 +7684,7 @@ var createVoiceCampaignRoutes = (options) => {
|
|
|
7704
7684
|
}).post(`${path}/:campaignId/recipients`, async ({ params, request }) => {
|
|
7705
7685
|
const body = await readJsonBody(request);
|
|
7706
7686
|
return runtime.addRecipients(params.campaignId, body.recipients ?? []);
|
|
7707
|
-
}).post(`${path}/:campaignId/recipients/import`, async ({ params, request }) => runtime.importRecipients(params.campaignId, await readJsonBody(request))).post(`${path}/:campaignId/enqueue`, ({ params }) => runtime.enqueue(params.campaignId)).post(`${path}/:campaignId/pause`, ({ params }) => runtime.pause(params.campaignId)).post(`${path}/:campaignId/resume`, ({ params }) => runtime.resume(params.campaignId)).post(`${path}/:campaignId/cancel`, ({ params }) => runtime.cancel(params.campaignId)).post(`${path}/:campaignId/tick`, ({ params }) => runtime.tick(params.campaignId)).post(`${path}/:campaignId/attempts/:attemptId/result`, async ({
|
|
7708
|
-
params,
|
|
7709
|
-
request
|
|
7710
|
-
}) => runtime.completeAttempt(params.campaignId, params.attemptId, await readJsonBody(request)));
|
|
7687
|
+
}).post(`${path}/:campaignId/recipients/import`, async ({ params, request }) => runtime.importRecipients(params.campaignId, await readJsonBody(request))).post(`${path}/:campaignId/enqueue`, ({ params }) => runtime.enqueue(params.campaignId)).post(`${path}/:campaignId/pause`, ({ params }) => runtime.pause(params.campaignId)).post(`${path}/:campaignId/resume`, ({ params }) => runtime.resume(params.campaignId)).post(`${path}/:campaignId/cancel`, ({ params }) => runtime.cancel(params.campaignId)).post(`${path}/:campaignId/tick`, ({ params }) => runtime.tick(params.campaignId)).post(`${path}/:campaignId/attempts/:attemptId/result`, async ({ params, request }) => runtime.completeAttempt(params.campaignId, params.attemptId, await readJsonBody(request)));
|
|
7711
7688
|
if (htmlPath) {
|
|
7712
7689
|
app.get(htmlPath, async () => {
|
|
7713
7690
|
const records = await runtime.list();
|
|
@@ -10410,8 +10387,12 @@ var redactVoiceTraceEvent = (event, options = {}) => {
|
|
|
10410
10387
|
const resolved = resolveVoiceTraceRedactionOptions(options);
|
|
10411
10388
|
return {
|
|
10412
10389
|
...event,
|
|
10413
|
-
metadata: redactTraceValue(event.metadata, resolved, [
|
|
10414
|
-
|
|
10390
|
+
metadata: redactTraceValue(event.metadata, resolved, [
|
|
10391
|
+
"metadata"
|
|
10392
|
+
]),
|
|
10393
|
+
payload: redactTraceValue(event.payload, resolved, [
|
|
10394
|
+
"payload"
|
|
10395
|
+
])
|
|
10415
10396
|
};
|
|
10416
10397
|
};
|
|
10417
10398
|
var redactVoiceTraceEvents = (events, options = {}) => events.map((event) => redactVoiceTraceEvent(event, options));
|
|
@@ -11760,7 +11741,9 @@ var createVoiceReconnectContractRoutes = (options) => {
|
|
|
11760
11741
|
requireResume: options.requireResume,
|
|
11761
11742
|
snapshots: await options.getSnapshots()
|
|
11762
11743
|
});
|
|
11763
|
-
const app = new Elysia9({
|
|
11744
|
+
const app = new Elysia9({
|
|
11745
|
+
name: options.name ?? "absolutejs-voice-reconnect-contract"
|
|
11746
|
+
}).get(path, async () => new Response(JSON.stringify(await buildReport()), {
|
|
11764
11747
|
headers: {
|
|
11765
11748
|
"content-type": "application/json; charset=utf-8",
|
|
11766
11749
|
...options.headers
|
|
@@ -12071,7 +12054,9 @@ var createVoiceRealtimeChannelRoutes = (options) => {
|
|
|
12071
12054
|
return reportOptions;
|
|
12072
12055
|
};
|
|
12073
12056
|
const report = async () => buildVoiceRealtimeChannelReport(await resolveOptions());
|
|
12074
|
-
const app = new Elysia10({
|
|
12057
|
+
const app = new Elysia10({
|
|
12058
|
+
name: options.name ?? "voice-realtime-channel"
|
|
12059
|
+
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
12075
12060
|
headers: {
|
|
12076
12061
|
"content-type": "application/json; charset=utf-8",
|
|
12077
12062
|
...headers
|
|
@@ -12115,10 +12100,7 @@ var defaultProviderEnv = {
|
|
|
12115
12100
|
"gemini-live": ["GEMINI_API_KEY"],
|
|
12116
12101
|
"openai-realtime": ["OPENAI_API_KEY"]
|
|
12117
12102
|
};
|
|
12118
|
-
var defaultRealtimeProviders = [
|
|
12119
|
-
"openai-realtime",
|
|
12120
|
-
"gemini-live"
|
|
12121
|
-
];
|
|
12103
|
+
var defaultRealtimeProviders = ["openai-realtime", "gemini-live"];
|
|
12122
12104
|
var statusRank = {
|
|
12123
12105
|
pass: 0,
|
|
12124
12106
|
warn: 1,
|
|
@@ -12397,7 +12379,10 @@ var buildVoiceDiagnosticsMarkdown = (events, options = {}) => {
|
|
|
12397
12379
|
var renderDiagnosticsIndex = (input) => {
|
|
12398
12380
|
const sessions = new Map;
|
|
12399
12381
|
for (const event of input.events) {
|
|
12400
|
-
sessions.set(event.sessionId, [
|
|
12382
|
+
sessions.set(event.sessionId, [
|
|
12383
|
+
...sessions.get(event.sessionId) ?? [],
|
|
12384
|
+
event
|
|
12385
|
+
]);
|
|
12401
12386
|
}
|
|
12402
12387
|
const rows = [...sessions.entries()].sort(([, left], [, right]) => (right.at(-1)?.at ?? 0) - (left.at(-1)?.at ?? 0)).slice(0, 50).map(([sessionId, events]) => {
|
|
12403
12388
|
const summary = summarizeVoiceTrace(events);
|
|
@@ -13982,7 +13967,10 @@ var createVoiceDemoReadyRoutes = (options) => {
|
|
|
13982
13967
|
routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
|
|
13983
13968
|
if (htmlPath !== false) {
|
|
13984
13969
|
routes.get(htmlPath, async ({ query, request }) => {
|
|
13985
|
-
const report = await buildVoiceDemoReadyReport(options, {
|
|
13970
|
+
const report = await buildVoiceDemoReadyReport(options, {
|
|
13971
|
+
query,
|
|
13972
|
+
request
|
|
13973
|
+
});
|
|
13986
13974
|
const body = await (options.render ?? renderVoiceDemoReadyHTML)(report);
|
|
13987
13975
|
return new Response(body, {
|
|
13988
13976
|
headers: {
|
|
@@ -16282,7 +16270,9 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16282
16270
|
const headers = options.headers ?? {};
|
|
16283
16271
|
const title = options.title ?? "Provider Decision Traces";
|
|
16284
16272
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
16285
|
-
const app = new Elysia23({
|
|
16273
|
+
const app = new Elysia23({
|
|
16274
|
+
name: options.name ?? "voice-provider-decisions"
|
|
16275
|
+
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
16286
16276
|
headers: {
|
|
16287
16277
|
"content-type": "application/json; charset=utf-8",
|
|
16288
16278
|
...headers
|
|
@@ -16529,7 +16519,10 @@ var summarizeProviderTraceEvidence = (events, maxProviderP95Ms) => {
|
|
|
16529
16519
|
const id = `${role}:${provider}`;
|
|
16530
16520
|
const latency = readProviderTraceLatency(payload);
|
|
16531
16521
|
if (latency !== undefined) {
|
|
16532
|
-
providerLatencies.set(id, [
|
|
16522
|
+
providerLatencies.set(id, [
|
|
16523
|
+
...providerLatencies.get(id) ?? [],
|
|
16524
|
+
latency
|
|
16525
|
+
]);
|
|
16533
16526
|
}
|
|
16534
16527
|
const existing = providerMeta.get(id);
|
|
16535
16528
|
providerMeta.set(id, {
|
|
@@ -16626,10 +16619,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
|
|
|
16626
16619
|
event
|
|
16627
16620
|
]);
|
|
16628
16621
|
}
|
|
16629
|
-
return [...eventsBySession.entries()].map(([
|
|
16630
|
-
sessionId,
|
|
16631
|
-
sessionEvents
|
|
16632
|
-
]) => {
|
|
16622
|
+
return [...eventsBySession.entries()].map(([sessionId, sessionEvents]) => {
|
|
16633
16623
|
const profileId = readTraceProfileId(sessionEvents, options);
|
|
16634
16624
|
if (!profileId) {
|
|
16635
16625
|
return;
|
|
@@ -18071,7 +18061,9 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
18071
18061
|
"",
|
|
18072
18062
|
"| Rank | Provider | Role | Status | P95 | Samples | Next move |",
|
|
18073
18063
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
18074
|
-
...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown2(provider.label ?? provider.id)} | ${escapeMarkdown2(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown2(provider.nextMove)} |`) : [
|
|
18064
|
+
...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown2(provider.label ?? provider.id)} | ${escapeMarkdown2(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown2(provider.nextMove)} |`) : [
|
|
18065
|
+
"| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"
|
|
18066
|
+
],
|
|
18075
18067
|
"",
|
|
18076
18068
|
"## Benchmark Profiles",
|
|
18077
18069
|
"",
|
|
@@ -18589,7 +18581,9 @@ var createVoiceSessionSnapshotRoutes = (options = {}) => {
|
|
|
18589
18581
|
const path = options.path ?? "/api/voice/session-snapshot/:sessionId";
|
|
18590
18582
|
const downloadPath = options.downloadPath ?? "/api/voice/session-snapshot/:sessionId/download";
|
|
18591
18583
|
const headers = options.headers ?? {};
|
|
18592
|
-
const app = new Elysia25({
|
|
18584
|
+
const app = new Elysia25({
|
|
18585
|
+
name: options.name ?? "voice-session-snapshot"
|
|
18586
|
+
}).get(path, async ({ params, request, query }) => sessionSnapshotJsonResponse(await resolveVoiceSessionSnapshot(options, {
|
|
18593
18587
|
request,
|
|
18594
18588
|
sessionId: readRouteSessionId(params),
|
|
18595
18589
|
turnId: typeof query.turnId === "string" ? query.turnId : undefined
|
|
@@ -18736,7 +18730,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
18736
18730
|
const events = options.events ?? await options.store?.list() ?? [];
|
|
18737
18731
|
const grouped = new Map;
|
|
18738
18732
|
for (const event of events) {
|
|
18739
|
-
grouped.set(event.sessionId, [
|
|
18733
|
+
grouped.set(event.sessionId, [
|
|
18734
|
+
...grouped.get(event.sessionId) ?? [],
|
|
18735
|
+
event
|
|
18736
|
+
]);
|
|
18740
18737
|
}
|
|
18741
18738
|
const sessions = [...grouped.entries()].map(([sessionId, sessionEvents]) => {
|
|
18742
18739
|
const sorted = filterVoiceTraceEvents(sessionEvents);
|
|
@@ -19034,7 +19031,10 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
19034
19031
|
const source = options.redact ? redactVoiceTraceEvents(events, options.redact) : events;
|
|
19035
19032
|
const grouped = new Map;
|
|
19036
19033
|
for (const event of filterVoiceTraceEvents(source)) {
|
|
19037
|
-
grouped.set(event.sessionId, [
|
|
19034
|
+
grouped.set(event.sessionId, [
|
|
19035
|
+
...grouped.get(event.sessionId) ?? [],
|
|
19036
|
+
event
|
|
19037
|
+
]);
|
|
19038
19038
|
}
|
|
19039
19039
|
const sessions = [...grouped.entries()].map(([sessionId, sessionEvents]) => {
|
|
19040
19040
|
const sorted = filterVoiceTraceEvents(sessionEvents);
|
|
@@ -22236,7 +22236,11 @@ var resolveVoiceTelephonyOutcome = (event, policyInput = {}) => {
|
|
|
22236
22236
|
}
|
|
22237
22237
|
if (target) {
|
|
22238
22238
|
return {
|
|
22239
|
-
...buildDecision("transfer", {
|
|
22239
|
+
...buildDecision("transfer", {
|
|
22240
|
+
event,
|
|
22241
|
+
policy,
|
|
22242
|
+
source: "explicit-target"
|
|
22243
|
+
}),
|
|
22240
22244
|
confidence: "medium"
|
|
22241
22245
|
};
|
|
22242
22246
|
}
|
|
@@ -22418,7 +22422,12 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
|
|
|
22418
22422
|
"hangupCauseCode"
|
|
22419
22423
|
]);
|
|
22420
22424
|
const from = firstString4(payload, ["From", "from", "caller_id", "callerId"]);
|
|
22421
|
-
const to = firstString4(payload, [
|
|
22425
|
+
const to = firstString4(payload, [
|
|
22426
|
+
"To",
|
|
22427
|
+
"to",
|
|
22428
|
+
"called_number",
|
|
22429
|
+
"calledNumber"
|
|
22430
|
+
]);
|
|
22422
22431
|
const target = firstString4(payload, [
|
|
22423
22432
|
"transferTarget",
|
|
22424
22433
|
"TransferTarget",
|
|
@@ -23220,7 +23229,9 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
23220
23229
|
const warnings = [
|
|
23221
23230
|
...stream.startsWith("wss://") ? [] : ["Twilio media streams should use wss:// in production."],
|
|
23222
23231
|
...signingConfigured ? [] : ["Webhook signature verification is not configured."],
|
|
23223
|
-
...verificationUrl || !signingConfigured ? [] : [
|
|
23232
|
+
...verificationUrl || !signingConfigured ? [] : [
|
|
23233
|
+
"Webhook signing is configured without an explicit verification URL."
|
|
23234
|
+
]
|
|
23224
23235
|
];
|
|
23225
23236
|
return {
|
|
23226
23237
|
generatedAt: Date.now(),
|
|
@@ -25842,7 +25853,9 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
25842
25853
|
...options.headers ?? {}
|
|
25843
25854
|
};
|
|
25844
25855
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
25845
|
-
const app = new Elysia41({
|
|
25856
|
+
const app = new Elysia41({
|
|
25857
|
+
name: options.name ?? "absolute-voice-provider-slos"
|
|
25858
|
+
});
|
|
25846
25859
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
25847
25860
|
if (markdownPath !== false) {
|
|
25848
25861
|
app.get(markdownPath, async () => {
|
|
@@ -26590,6 +26603,84 @@ var buildVoiceIncidentRecoveryOutcomeReadinessCheck = (report, options = {}) =>
|
|
|
26590
26603
|
value: `${report.improved}/${report.total} improved`
|
|
26591
26604
|
};
|
|
26592
26605
|
};
|
|
26606
|
+
var buildVoiceIncidentRecoveryTrendSLOReadinessCheck = (report, options = {}) => {
|
|
26607
|
+
const mode = options.mode ?? "latest";
|
|
26608
|
+
const minCycles = Math.max(1, options.minCycles ?? 1);
|
|
26609
|
+
const minActions = Math.max(1, options.minActions ?? 1);
|
|
26610
|
+
const minImprovementRate = options.minImprovementRate ?? 0;
|
|
26611
|
+
const maxRegressionRate = options.maxRegressionRate ?? 0;
|
|
26612
|
+
const maxFailureRate = options.maxFailureRate ?? 0;
|
|
26613
|
+
const maxUnchangedRate = options.maxUnchangedRate ?? 1;
|
|
26614
|
+
const warnWhenEmpty = options.warnWhenEmpty ?? true;
|
|
26615
|
+
const href = options.href ?? "/api/voice/incident-timeline/recovery-trends";
|
|
26616
|
+
const modeLatestCycle = report.latest;
|
|
26617
|
+
const modeAggregate = report.summary.cycles > 0;
|
|
26618
|
+
const modeTarget = mode === "aggregate" ? modeAggregate ? {
|
|
26619
|
+
failed: report.summary.failed,
|
|
26620
|
+
failureRate: report.summary.failureRate,
|
|
26621
|
+
improved: report.summary.improved,
|
|
26622
|
+
improvementRate: report.summary.improvementRate,
|
|
26623
|
+
regressed: report.summary.regressed,
|
|
26624
|
+
regressionRate: report.summary.regressionRate,
|
|
26625
|
+
total: report.summary.total,
|
|
26626
|
+
unchanged: report.summary.unchanged,
|
|
26627
|
+
unchangedRate: report.summary.unchangedRate
|
|
26628
|
+
} : undefined : modeLatestCycle;
|
|
26629
|
+
const insufficientCycles = report.cycles.length < minCycles;
|
|
26630
|
+
const empty = !modeTarget || modeTarget.total === 0;
|
|
26631
|
+
const insufficientActions = !empty && modeTarget.total < minActions;
|
|
26632
|
+
const failedRate = modeTarget?.failureRate ?? 0;
|
|
26633
|
+
const regressedRate = modeTarget?.regressionRate ?? 0;
|
|
26634
|
+
const unchangedRate = modeTarget?.unchangedRate ?? 0;
|
|
26635
|
+
const improvementRate = modeTarget?.improvementRate ?? 0;
|
|
26636
|
+
const issues = [];
|
|
26637
|
+
if (empty && warnWhenEmpty) {
|
|
26638
|
+
issues.push("No incident recovery actions found in the configured trend window.");
|
|
26639
|
+
}
|
|
26640
|
+
if (insufficientCycles) {
|
|
26641
|
+
issues.push(`Need at least ${minCycles} trend cycle(s) before enforcing trend SLOs, found ${report.cycles.length}.`);
|
|
26642
|
+
}
|
|
26643
|
+
if (insufficientActions) {
|
|
26644
|
+
issues.push(`Need at least ${minActions} recovery actions in the trend cycle, found ${modeTarget?.total ?? 0}.`);
|
|
26645
|
+
}
|
|
26646
|
+
if (improvementRate < minImprovementRate) {
|
|
26647
|
+
issues.push(`Improvement rate ${Math.round(improvementRate * 100)}% is below minimum ${Math.round(minImprovementRate * 100)}%.`);
|
|
26648
|
+
}
|
|
26649
|
+
if (regressedRate > maxRegressionRate) {
|
|
26650
|
+
issues.push(`Regression rate ${Math.round(regressedRate * 100)}% is above maximum ${Math.round(maxRegressionRate * 100)}%.`);
|
|
26651
|
+
}
|
|
26652
|
+
if (failedRate > maxFailureRate) {
|
|
26653
|
+
issues.push(`Failure rate ${Math.round(failedRate * 100)}% is above maximum ${Math.round(maxFailureRate * 100)}%.`);
|
|
26654
|
+
}
|
|
26655
|
+
if (unchangedRate > maxUnchangedRate) {
|
|
26656
|
+
issues.push(`Unchanged rate ${Math.round(unchangedRate * 100)}% is above maximum ${Math.round(maxUnchangedRate * 100)}%.`);
|
|
26657
|
+
}
|
|
26658
|
+
const fail = issues.some((issue) => issue.includes("Regression rate") || issue.includes("Failure rate"));
|
|
26659
|
+
const status = fail ? "fail" : issues.length > 0 ? "warn" : "pass";
|
|
26660
|
+
const detail = empty && warnWhenEmpty ? `${mode} trend is empty; set up recovery action execution before release.` : `${mode} trend has ${modeTarget?.total ?? 0} recovery action(s), ${Math.round(improvementRate * 100)}% improved, ${Math.round(regressedRate * 100)}% regressed, ${Math.round(failedRate * 100)}% failed, ${Math.round(unchangedRate * 100)}% unchanged.`;
|
|
26661
|
+
return {
|
|
26662
|
+
actions: status === "pass" ? [] : [
|
|
26663
|
+
{
|
|
26664
|
+
description: `Open recovery trend report and tighten recovery handling before deploy.`,
|
|
26665
|
+
href,
|
|
26666
|
+
label: `Open recovery trend report`
|
|
26667
|
+
}
|
|
26668
|
+
],
|
|
26669
|
+
detail,
|
|
26670
|
+
gateExplanation: modeTarget ? {
|
|
26671
|
+
evidenceHref: href,
|
|
26672
|
+
observed: `improvement ${Math.round(improvementRate * 100)}%, regression ${Math.round(regressedRate * 100)}%, failure ${Math.round(failedRate * 100)}%, unchanged ${Math.round(unchangedRate * 100)}%`,
|
|
26673
|
+
threshold: `cycles >= ${minCycles}, actions >= ${minActions}`,
|
|
26674
|
+
thresholdLabel: "Incident recovery trend SLO budget",
|
|
26675
|
+
unit: "rate",
|
|
26676
|
+
remediation: "Run recovery recovery actions and harden handler fallbacks, then rerun recovery trend capture."
|
|
26677
|
+
} : undefined,
|
|
26678
|
+
href,
|
|
26679
|
+
label: options.label ?? "Incident recovery trend SLO",
|
|
26680
|
+
status,
|
|
26681
|
+
value: `${Math.round(improvementRate * 100)}% improved, ${Math.round(regressedRate * 100)}% regressed`
|
|
26682
|
+
};
|
|
26683
|
+
};
|
|
26593
26684
|
var rate3 = (count, total) => total > 0 ? count / total : 0;
|
|
26594
26685
|
var toIncidentRecoveryTrendCycle = (report) => ({
|
|
26595
26686
|
checkedAt: report.checkedAt,
|
|
@@ -29333,6 +29424,15 @@ var resolveIncidentRecoveryOutcomes = async (options, input) => {
|
|
|
29333
29424
|
}
|
|
29334
29425
|
return options.incidentRecoveryOutcomes;
|
|
29335
29426
|
};
|
|
29427
|
+
var resolveIncidentRecoveryTrend = async (options, input) => {
|
|
29428
|
+
if (!options.incidentRecoveryTrend) {
|
|
29429
|
+
return;
|
|
29430
|
+
}
|
|
29431
|
+
if (typeof options.incidentRecoveryTrend === "function") {
|
|
29432
|
+
return options.incidentRecoveryTrend(input);
|
|
29433
|
+
}
|
|
29434
|
+
return options.incidentRecoveryTrend;
|
|
29435
|
+
};
|
|
29336
29436
|
var resolveObservabilityExport = async (options, input) => {
|
|
29337
29437
|
if (!options.observabilityExport) {
|
|
29338
29438
|
return;
|
|
@@ -29538,7 +29638,57 @@ var buildOperationsRecordLinks = (input) => {
|
|
|
29538
29638
|
};
|
|
29539
29639
|
};
|
|
29540
29640
|
var firstOperationsRecordHref = (links) => links[0]?.href;
|
|
29641
|
+
var applyProfileReadinessDefaults = (options) => {
|
|
29642
|
+
if (options.profile === false || options.profile === undefined) {
|
|
29643
|
+
return options;
|
|
29644
|
+
}
|
|
29645
|
+
const profileName = options.profile.name;
|
|
29646
|
+
if (profileName !== "meeting-recorder" && profileName !== "phone-agent") {
|
|
29647
|
+
return options;
|
|
29648
|
+
}
|
|
29649
|
+
const defaults = profileName === "meeting-recorder" ? {
|
|
29650
|
+
browserMediaMinActiveCandidatePairs: 1,
|
|
29651
|
+
browserMediaMinLiveAudioTracks: 1,
|
|
29652
|
+
browserMediaMinTotalStats: 3,
|
|
29653
|
+
reconnectContractsMinCount: 1,
|
|
29654
|
+
reconnectContractsMinSnapshotsPerContract: 1
|
|
29655
|
+
} : {
|
|
29656
|
+
browserMediaMinActiveCandidatePairs: 1,
|
|
29657
|
+
browserMediaMinLiveAudioTracks: 1,
|
|
29658
|
+
browserMediaMinTotalStats: 3,
|
|
29659
|
+
reconnectContractsMinCount: 1,
|
|
29660
|
+
reconnectContractsMinSnapshotsPerContract: 1,
|
|
29661
|
+
telephonyMediaMinCarriers: 1,
|
|
29662
|
+
telephonyMediaMinMediaEvents: 2
|
|
29663
|
+
};
|
|
29664
|
+
const resolvedOptions = {
|
|
29665
|
+
...options
|
|
29666
|
+
};
|
|
29667
|
+
if (resolvedOptions.browserMediaMinActiveCandidatePairs === undefined) {
|
|
29668
|
+
resolvedOptions.browserMediaMinActiveCandidatePairs = defaults.browserMediaMinActiveCandidatePairs;
|
|
29669
|
+
}
|
|
29670
|
+
if (resolvedOptions.browserMediaMinLiveAudioTracks === undefined) {
|
|
29671
|
+
resolvedOptions.browserMediaMinLiveAudioTracks = defaults.browserMediaMinLiveAudioTracks;
|
|
29672
|
+
}
|
|
29673
|
+
if (resolvedOptions.browserMediaMinTotalStats === undefined) {
|
|
29674
|
+
resolvedOptions.browserMediaMinTotalStats = defaults.browserMediaMinTotalStats;
|
|
29675
|
+
}
|
|
29676
|
+
if (resolvedOptions.reconnectContractsMinCount === undefined) {
|
|
29677
|
+
resolvedOptions.reconnectContractsMinCount = defaults.reconnectContractsMinCount;
|
|
29678
|
+
}
|
|
29679
|
+
if (resolvedOptions.reconnectContractsMinSnapshotsPerContract === undefined) {
|
|
29680
|
+
resolvedOptions.reconnectContractsMinSnapshotsPerContract = defaults.reconnectContractsMinSnapshotsPerContract;
|
|
29681
|
+
}
|
|
29682
|
+
if ("telephonyMediaMinCarriers" in defaults && resolvedOptions.telephonyMediaMinCarriers === undefined) {
|
|
29683
|
+
resolvedOptions.telephonyMediaMinCarriers = defaults.telephonyMediaMinCarriers;
|
|
29684
|
+
}
|
|
29685
|
+
if ("telephonyMediaMinMediaEvents" in defaults && resolvedOptions.telephonyMediaMinMediaEvents === undefined) {
|
|
29686
|
+
resolvedOptions.telephonyMediaMinMediaEvents = defaults.telephonyMediaMinMediaEvents;
|
|
29687
|
+
}
|
|
29688
|
+
return resolvedOptions;
|
|
29689
|
+
};
|
|
29541
29690
|
var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
29691
|
+
options = applyProfileReadinessDefaults(options);
|
|
29542
29692
|
const request = input.request ?? new Request("http://localhost/");
|
|
29543
29693
|
const query = input.query ?? {};
|
|
29544
29694
|
const time = async (label, run) => {
|
|
@@ -29592,6 +29742,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29592
29742
|
campaignReadiness,
|
|
29593
29743
|
opsRecovery,
|
|
29594
29744
|
incidentRecoveryOutcomes,
|
|
29745
|
+
incidentRecoveryTrend,
|
|
29595
29746
|
observabilityExport,
|
|
29596
29747
|
observabilityExportDeliveryHistory,
|
|
29597
29748
|
observabilityExportReplay,
|
|
@@ -29640,6 +29791,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29640
29791
|
time("campaignReadiness", () => resolveCampaignReadiness(options, { query, request })),
|
|
29641
29792
|
time("opsRecovery", () => resolveOpsRecovery(options, { query, request })),
|
|
29642
29793
|
time("incidentRecoveryOutcomes", () => resolveIncidentRecoveryOutcomes(options, { query, request })),
|
|
29794
|
+
time("incidentRecoveryTrend", () => resolveIncidentRecoveryTrend(options, { query, request })),
|
|
29643
29795
|
time("observabilityExport", () => resolveObservabilityExport(options, { query, request })),
|
|
29644
29796
|
time("observabilityExportDeliveryHistory", () => resolveObservabilityExportDeliveryHistory(options, { query, request })),
|
|
29645
29797
|
time("observabilityExportReplay", () => resolveObservabilityExportReplay(options, { query, request })),
|
|
@@ -29664,6 +29816,18 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29664
29816
|
href: options.incidentRecoveryOutcomeReadiness?.href ?? "/api/voice/incident-timeline/recovery-outcomes",
|
|
29665
29817
|
...options.incidentRecoveryOutcomeReadiness
|
|
29666
29818
|
}) : undefined;
|
|
29819
|
+
const incidentRecoveryTrendReadiness = incidentRecoveryTrend && options.incidentRecoveryTrendSLO !== false ? buildVoiceIncidentRecoveryTrendSLOReadinessCheck(incidentRecoveryTrend, {
|
|
29820
|
+
href: options.incidentRecoveryTrendSLO?.href ?? "/api/voice/incident-timeline/recovery-trends",
|
|
29821
|
+
label: options.incidentRecoveryTrendSLO?.label,
|
|
29822
|
+
maxFailureRate: options.incidentRecoveryTrendSLO?.maxFailureRate,
|
|
29823
|
+
maxRegressionRate: options.incidentRecoveryTrendSLO?.maxRegressionRate,
|
|
29824
|
+
maxUnchangedRate: options.incidentRecoveryTrendSLO?.maxUnchangedRate,
|
|
29825
|
+
minActions: options.incidentRecoveryTrendSLO?.minActions,
|
|
29826
|
+
minCycles: options.incidentRecoveryTrendSLO?.minCycles,
|
|
29827
|
+
minImprovementRate: options.incidentRecoveryTrendSLO?.minImprovementRate,
|
|
29828
|
+
warnWhenEmpty: options.incidentRecoveryTrendSLO?.warnWhenEmpty,
|
|
29829
|
+
mode: options.incidentRecoveryTrendSLO?.mode
|
|
29830
|
+
}) : undefined;
|
|
29667
29831
|
const checks = [
|
|
29668
29832
|
{
|
|
29669
29833
|
detail: quality.status === "pass" ? "Quality gates are passing." : "Quality gates need attention.",
|
|
@@ -29736,6 +29900,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29736
29900
|
}
|
|
29737
29901
|
] : [],
|
|
29738
29902
|
...incidentRecoveryOutcomeReadiness ? [incidentRecoveryOutcomeReadiness] : [],
|
|
29903
|
+
...incidentRecoveryTrendReadiness ? [incidentRecoveryTrendReadiness] : [],
|
|
29739
29904
|
{
|
|
29740
29905
|
detail: failedSessions === 0 ? sessions.length > 0 ? "Recent sessions have no recorded provider/session failures." : "No sessions have been recorded yet; run a smoke or live session for proof." : `${failedSessions} recent session(s) have failures.`,
|
|
29741
29906
|
href: firstOperationsRecordHref(operationsRecords.failedSessions) ?? options.links?.sessions ?? "/sessions",
|
|
@@ -29830,6 +29995,11 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29830
29995
|
status: mediaPipeline.status === "pass" ? "pass" : "fail",
|
|
29831
29996
|
timestampDriftMs: mediaPipeline.quality.timestampDriftMs
|
|
29832
29997
|
} : undefined;
|
|
29998
|
+
const browserMediaBreadthFailures = browserMedia ? [
|
|
29999
|
+
options.browserMediaMinActiveCandidatePairs !== undefined && typeof options.browserMediaMinActiveCandidatePairs === "number" && options.browserMediaMinActiveCandidatePairs >= 0 && browserMedia.activeCandidatePairs < options.browserMediaMinActiveCandidatePairs ? `Expected at least ${options.browserMediaMinActiveCandidatePairs} active candidate pair(s), observed ${browserMedia.activeCandidatePairs}.` : undefined,
|
|
30000
|
+
options.browserMediaMinLiveAudioTracks !== undefined && typeof options.browserMediaMinLiveAudioTracks === "number" && options.browserMediaMinLiveAudioTracks >= 0 && browserMedia.liveAudioTracks < options.browserMediaMinLiveAudioTracks ? `Expected at least ${options.browserMediaMinLiveAudioTracks} live audio track(s), observed ${browserMedia.liveAudioTracks}.` : undefined,
|
|
30001
|
+
options.browserMediaMinTotalStats !== undefined && typeof options.browserMediaMinTotalStats === "number" && options.browserMediaMinTotalStats >= 0 && browserMedia.totalStats < options.browserMediaMinTotalStats ? `Expected at least ${options.browserMediaMinTotalStats} WebRTC stats sample(s), observed ${browserMedia.totalStats}.` : undefined
|
|
30002
|
+
].filter((message) => typeof message === "string" && message.length > 0) : [];
|
|
29833
30003
|
const browserMediaSummary = browserMedia ? {
|
|
29834
30004
|
activeCandidatePairs: browserMedia.activeCandidatePairs,
|
|
29835
30005
|
bytesReceived: browserMedia.bytesReceived,
|
|
@@ -29839,18 +30009,29 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29839
30009
|
liveAudioTracks: browserMedia.liveAudioTracks,
|
|
29840
30010
|
packetLossRatio: browserMedia.packetLossRatio,
|
|
29841
30011
|
roundTripTimeMs: browserMedia.roundTripTimeMs,
|
|
29842
|
-
status: browserMedia.status === "pass" ? "pass" : "fail"
|
|
29843
|
-
} : undefined;
|
|
29844
|
-
const telephonyMediaSummary = telephonyMedia ? {
|
|
29845
|
-
audioBytes: telephonyMedia.carriers.reduce((total, carrier) => total + carrier.audioBytes, 0),
|
|
29846
|
-
carriers: telephonyMedia.carriers.length,
|
|
29847
|
-
failed: telephonyMedia.carriers.filter((carrier) => carrier.status !== "pass").length,
|
|
29848
|
-
issues: telephonyMedia.issues.length,
|
|
29849
|
-
lifecycleFailures: telephonyMedia.carriers.filter((carrier) => carrier.lifecycle.status !== "pass").length,
|
|
29850
|
-
mediaEvents: telephonyMedia.carriers.reduce((total, carrier) => total + carrier.lifecycle.mediaEvents, 0),
|
|
29851
|
-
passed: telephonyMedia.carriers.filter((carrier) => carrier.status === "pass").length,
|
|
29852
|
-
status: telephonyMedia.status === "pass" ? "pass" : "fail"
|
|
30012
|
+
status: browserMedia.status === "pass" && browserMediaBreadthFailures.length === 0 ? "pass" : "fail"
|
|
29853
30013
|
} : undefined;
|
|
30014
|
+
let telephonyMediaBreadthFailures = [];
|
|
30015
|
+
const telephonyMediaSummary = telephonyMedia ? (() => {
|
|
30016
|
+
const telephonyMediaTotalMediaEvents = telephonyMedia.carriers.reduce((total, carrier) => total + carrier.lifecycle.mediaEvents, 0);
|
|
30017
|
+
const failures = [
|
|
30018
|
+
options.telephonyMediaMinCarriers !== undefined && typeof options.telephonyMediaMinCarriers === "number" && options.telephonyMediaMinCarriers >= 0 && telephonyMedia.carriers.length < options.telephonyMediaMinCarriers ? `Expected at least ${options.telephonyMediaMinCarriers} telephony carrier(s), observed ${telephonyMedia.carriers.length}.` : undefined,
|
|
30019
|
+
options.telephonyMediaMinMediaEvents !== undefined && typeof options.telephonyMediaMinMediaEvents === "number" && options.telephonyMediaMinMediaEvents >= 0 && telephonyMediaTotalMediaEvents < options.telephonyMediaMinMediaEvents ? `Expected at least ${options.telephonyMediaMinMediaEvents} telephony media event(s), observed ${telephonyMediaTotalMediaEvents}.` : undefined
|
|
30020
|
+
].filter((message) => typeof message === "string" && message.length > 0);
|
|
30021
|
+
telephonyMediaBreadthFailures = failures;
|
|
30022
|
+
return {
|
|
30023
|
+
audioBytes: telephonyMedia.carriers.reduce((total, carrier) => total + carrier.audioBytes, 0),
|
|
30024
|
+
carriers: telephonyMedia.carriers.length,
|
|
30025
|
+
failed: telephonyMedia.carriers.filter((carrier) => carrier.status !== "pass").length,
|
|
30026
|
+
issues: telephonyMedia.issues.length,
|
|
30027
|
+
lifecycleFailures: telephonyMedia.carriers.filter((carrier) => carrier.lifecycle.status !== "pass").length,
|
|
30028
|
+
mediaEvents: telephonyMediaTotalMediaEvents,
|
|
30029
|
+
passed: telephonyMedia.carriers.filter((carrier) => carrier.status === "pass").length,
|
|
30030
|
+
status: telephonyMedia.status === "pass" && telephonyMediaBreadthFailures.length === 0 ? "pass" : "fail"
|
|
30031
|
+
};
|
|
30032
|
+
})() : undefined;
|
|
30033
|
+
const browserMediaBreadthSummary = browserMediaBreadthFailures.length > 0 ? browserMediaBreadthFailures : undefined;
|
|
30034
|
+
const telephonyMediaBreadthSummary = telephonyMediaBreadthFailures.length > 0 ? telephonyMediaBreadthFailures : undefined;
|
|
29854
30035
|
checks.push({
|
|
29855
30036
|
detail: liveLatency.total === 0 ? "No browser live-latency measurements are recorded yet." : liveLatency.status === "pass" ? `Live browser turn latency averages ${liveLatency.averageLatencyMs}ms.` : `${liveLatency.failed} failed and ${liveLatency.warnings} warned live-latency measurement(s).`,
|
|
29856
30037
|
href: firstOperationsRecordHref(operationsRecords.failingLatency) ?? options.links?.liveLatency ?? "/traces",
|
|
@@ -29921,11 +30102,17 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29921
30102
|
if (browserMedia && browserMediaSummary) {
|
|
29922
30103
|
const firstIssue = browserMedia.issues[0];
|
|
29923
30104
|
checks.push({
|
|
29924
|
-
detail: browserMediaSummary.status === "pass" ? `Browser media transport is passing with ${browserMediaSummary.activeCandidatePairs} active candidate pair(s), ${browserMediaSummary.liveAudioTracks} live audio track(s), ${String(browserMediaSummary.roundTripTimeMs ?? "n/a")}ms RTT, ${String(browserMediaSummary.jitterMs ?? "n/a")}ms jitter, and ${browserMediaSummary.packetLossRatio} packet loss ratio.` : firstIssue?.message ?? `${browserMediaSummary.issues} browser media transport issue(s) need review.`,
|
|
30105
|
+
detail: browserMediaSummary.status === "pass" ? `Browser media transport is passing with ${browserMediaSummary.activeCandidatePairs} active candidate pair(s), ${browserMediaSummary.liveAudioTracks} live audio track(s), ${String(browserMediaSummary.roundTripTimeMs ?? "n/a")}ms RTT, ${String(browserMediaSummary.jitterMs ?? "n/a")}ms jitter, and ${browserMediaSummary.packetLossRatio} packet loss ratio.` : browserMediaBreadthSummary ? browserMediaBreadthSummary.join("; ") : firstIssue?.message ?? `${browserMediaSummary.issues} browser media transport issue(s) need review.`,
|
|
29925
30106
|
href: options.links?.browserMedia ?? "/voice/browser-media",
|
|
29926
30107
|
label: "Browser media transport",
|
|
29927
30108
|
proofSource: proofSource("browserMedia", "webrtcStats"),
|
|
29928
|
-
gateExplanation: browserMediaSummary.status === "pass" ? undefined : {
|
|
30109
|
+
gateExplanation: browserMediaSummary.status === "pass" ? undefined : browserMediaBreadthSummary ? {
|
|
30110
|
+
evidenceHref: options.links?.browserMedia ?? "/voice/browser-media",
|
|
30111
|
+
observed: browserMediaBreadthSummary.join("; "),
|
|
30112
|
+
remediation: "Collect richer browser media evidence and rerun readiness so active candidate-pair, track, and stats thresholds are met.",
|
|
30113
|
+
thresholdLabel: "Browser media breadth",
|
|
30114
|
+
unit: "count"
|
|
30115
|
+
} : {
|
|
29929
30116
|
evidenceHref: options.links?.browserMedia ?? "/voice/browser-media",
|
|
29930
30117
|
observed: firstIssue?.code ?? `${browserMediaSummary.issues} issue(s)`,
|
|
29931
30118
|
remediation: "Inspect browser WebRTC media stats, fix packet loss, RTT, jitter, candidate-pair, or audio-track issues, then rerun readiness proof.",
|
|
@@ -29946,11 +30133,17 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
29946
30133
|
if (telephonyMedia && telephonyMediaSummary) {
|
|
29947
30134
|
const firstIssue = telephonyMedia.issues[0];
|
|
29948
30135
|
checks.push({
|
|
29949
|
-
detail: telephonyMediaSummary.status === "pass" ? `Telephony media serializers are passing for ${telephonyMediaSummary.passed}/${telephonyMediaSummary.carriers} carrier(s) with ${telephonyMediaSummary.audioBytes} audio byte(s), ${telephonyMediaSummary.mediaEvents} media event(s), and valid start/media/stop lifecycle sequencing.` : firstIssue ?? `${telephonyMediaSummary.issues} telephony media serializer issue(s) need review.`,
|
|
30136
|
+
detail: telephonyMediaSummary.status === "pass" ? `Telephony media serializers are passing for ${telephonyMediaSummary.passed}/${telephonyMediaSummary.carriers} carrier(s) with ${telephonyMediaSummary.audioBytes} audio byte(s), ${telephonyMediaSummary.mediaEvents} media event(s), and valid start/media/stop lifecycle sequencing.` : telephonyMediaBreadthSummary ? telephonyMediaBreadthSummary.join("; ") : firstIssue ?? `${telephonyMediaSummary.issues} telephony media serializer issue(s) need review.`,
|
|
29950
30137
|
href: firstOperationsRecordHref(operationsRecords.telephonyMedia) ?? options.links?.telephonyMedia ?? "/voice/telephony-media",
|
|
29951
30138
|
label: "Telephony media serializers",
|
|
29952
30139
|
proofSource: proofSource("telephonyMedia", "carrierMediaSerializers"),
|
|
29953
|
-
gateExplanation: telephonyMediaSummary.status === "pass" ? undefined : {
|
|
30140
|
+
gateExplanation: telephonyMediaSummary.status === "pass" ? undefined : telephonyMediaBreadthSummary ? {
|
|
30141
|
+
evidenceHref: firstOperationsRecordHref(operationsRecords.telephonyMedia) ?? options.links?.telephonyMedia ?? "/voice/telephony-media",
|
|
30142
|
+
observed: telephonyMediaBreadthSummary.join("; "),
|
|
30143
|
+
remediation: "Collect richer telephony lifecycle evidence and rerun readiness so carrier/media-event thresholds are met.",
|
|
30144
|
+
thresholdLabel: "Telephony media breadth",
|
|
30145
|
+
unit: "count"
|
|
30146
|
+
} : {
|
|
29954
30147
|
evidenceHref: firstOperationsRecordHref(operationsRecords.telephonyMedia) ?? options.links?.telephonyMedia ?? "/voice/telephony-media",
|
|
29955
30148
|
observed: firstIssue ?? `${telephonyMediaSummary.issues} issue(s)`,
|
|
29956
30149
|
remediation: "Inspect carrier media proof, fix start/media/stop sequencing, payload parsing, byte flow, or outbound envelope serialization, then rerun readiness proof.",
|
|
@@ -30037,17 +30230,31 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30037
30230
|
status: telephonyWebhookSecurity.status,
|
|
30038
30231
|
warned: telephonyWebhookSecurity.summary.warned
|
|
30039
30232
|
} : undefined;
|
|
30233
|
+
let reconnectContractBreadthFailures = [];
|
|
30040
30234
|
const reconnectContractSummary = reconnectContracts ? (() => {
|
|
30235
|
+
const reconnectContractCountMin = typeof options.reconnectContractsMinCount === "number" && options.reconnectContractsMinCount >= 0 ? options.reconnectContractsMinCount : undefined;
|
|
30236
|
+
const reconnectContractSnapshotsMin = typeof options.reconnectContractsMinSnapshotsPerContract === "number" && options.reconnectContractsMinSnapshotsPerContract >= 0 ? options.reconnectContractsMinSnapshotsPerContract : undefined;
|
|
30237
|
+
const reconnectSnapshotShortfallCount = reconnectContractSnapshotsMin === undefined ? 0 : reconnectContracts.filter((report) => typeof report.snapshotCount === "number" && report.snapshotCount < reconnectContractSnapshotsMin).length;
|
|
30238
|
+
const reconnectContractCountShortfall = reconnectContractCountMin === undefined ? 0 : Math.max(0, reconnectContractCountMin - reconnectContracts.length);
|
|
30239
|
+
reconnectContractBreadthFailures = reconnectContractCountShortfall > 0 ? [
|
|
30240
|
+
`Expected at least ${reconnectContractCountMin} reconnect contract(s), observed ${reconnectContracts.length}.`
|
|
30241
|
+
] : [];
|
|
30242
|
+
if (reconnectSnapshotShortfallCount > 0) {
|
|
30243
|
+
reconnectContractBreadthFailures.push(`${reconnectSnapshotShortfallCount} reconnect contract(s) with fewer than ${reconnectContractSnapshotsMin} snapshot(s).`);
|
|
30244
|
+
}
|
|
30041
30245
|
const failedReports = reconnectContracts.filter((report) => !report.pass || options.reconnectResumeFailAfterMs !== undefined && report.resumeLatencyP95Ms !== undefined && report.resumeLatencyP95Ms > options.reconnectResumeFailAfterMs);
|
|
30042
30246
|
const resumeLatencies = reconnectContracts.map((report) => report.resumeLatencyP95Ms).filter((value) => typeof value === "number");
|
|
30247
|
+
const reconnectContractBreadthFailureCount = reconnectContractBreadthFailures.length > 0 ? Math.min(reconnectContracts.length, reconnectContractBreadthFailures.length) : 0;
|
|
30248
|
+
const passedCount = Math.max(0, reconnectContracts.length - (failedReports.length + reconnectContractBreadthFailureCount));
|
|
30043
30249
|
return {
|
|
30044
|
-
failed: failedReports.length,
|
|
30045
|
-
passed:
|
|
30250
|
+
failed: failedReports.length + reconnectContractBreadthFailureCount,
|
|
30251
|
+
passed: passedCount,
|
|
30046
30252
|
resumeLatencyP95Ms: resumeLatencies.length > 0 ? Math.max(...resumeLatencies) : undefined,
|
|
30047
|
-
status: failedReports.length > 0 ? "fail" : reconnectContracts.length === 0 ? "warn" : "pass",
|
|
30253
|
+
status: failedReports.length > 0 || reconnectContractBreadthFailures.length > 0 ? "fail" : reconnectContracts.length === 0 ? "warn" : "pass",
|
|
30048
30254
|
total: reconnectContracts.length
|
|
30049
30255
|
};
|
|
30050
30256
|
})() : undefined;
|
|
30257
|
+
const reconnectContractBreadthSummary = reconnectContractBreadthFailures.length > 0 ? reconnectContractBreadthFailures : undefined;
|
|
30051
30258
|
const bargeInSummary = bargeInReports ? {
|
|
30052
30259
|
failed: bargeInReports.reduce((total, report) => total + report.failed, 0),
|
|
30053
30260
|
passed: bargeInReports.reduce((total, report) => total + report.passed, 0),
|
|
@@ -30077,6 +30284,19 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30077
30284
|
total: incidentRecoveryOutcomes.total,
|
|
30078
30285
|
unchanged: incidentRecoveryOutcomes.unchanged
|
|
30079
30286
|
} : undefined;
|
|
30287
|
+
const incidentRecoveryTrendSummary = incidentRecoveryTrend && incidentRecoveryTrendReadiness ? {
|
|
30288
|
+
cycles: incidentRecoveryTrend.summary.cycles,
|
|
30289
|
+
failed: incidentRecoveryTrend.summary.failed,
|
|
30290
|
+
failureRate: incidentRecoveryTrend.summary.failureRate,
|
|
30291
|
+
improved: incidentRecoveryTrend.summary.improved,
|
|
30292
|
+
improvementRate: incidentRecoveryTrend.summary.improvementRate,
|
|
30293
|
+
regressed: incidentRecoveryTrend.summary.regressed,
|
|
30294
|
+
regressionRate: incidentRecoveryTrend.summary.regressionRate,
|
|
30295
|
+
status: incidentRecoveryTrendReadiness.status,
|
|
30296
|
+
total: incidentRecoveryTrend.summary.total,
|
|
30297
|
+
unchanged: incidentRecoveryTrend.summary.unchanged,
|
|
30298
|
+
unchangedRate: incidentRecoveryTrend.summary.unchangedRate
|
|
30299
|
+
} : undefined;
|
|
30080
30300
|
const observabilityExportDeliveryHistorySummary = observabilityExportDeliveryHistory ? (() => {
|
|
30081
30301
|
const latestSuccess = observabilityExportDeliveryHistory.history.receipts.filter((receipt) => receipt.status === "pass" && receipt.summary.delivered > 0 && receipt.summary.failed === 0).sort((left, right) => right.checkedAt - left.checkedAt)[0];
|
|
30082
30302
|
const latestSuccessAgeMs = latestSuccess ? Date.now() - latestSuccess.checkedAt : undefined;
|
|
@@ -30300,11 +30520,17 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30300
30520
|
}
|
|
30301
30521
|
if (reconnectContractSummary) {
|
|
30302
30522
|
checks.push({
|
|
30303
|
-
detail: reconnectContractSummary.status === "pass" ? `${reconnectContractSummary.passed} reconnect contract(s) are passing.` : reconnectContractSummary.total === 0 ? "No reconnect contracts are configured." : options.reconnectResumeFailAfterMs !== undefined && reconnectContractSummary.resumeLatencyP95Ms !== undefined && reconnectContractSummary.resumeLatencyP95Ms > options.reconnectResumeFailAfterMs ? `Reconnect resume p95 ${reconnectContractSummary.resumeLatencyP95Ms}ms exceeded ${options.reconnectResumeFailAfterMs}ms.` : `${reconnectContractSummary.failed} reconnect contract(s) failed.`,
|
|
30523
|
+
detail: reconnectContractSummary.status === "pass" ? `${reconnectContractSummary.passed} reconnect contract(s) are passing.` : reconnectContractBreadthSummary && reconnectContractBreadthSummary.length > 0 ? reconnectContractBreadthSummary.join("; ") : reconnectContractSummary.total === 0 ? "No reconnect contracts are configured." : options.reconnectResumeFailAfterMs !== undefined && reconnectContractSummary.resumeLatencyP95Ms !== undefined && reconnectContractSummary.resumeLatencyP95Ms > options.reconnectResumeFailAfterMs ? `Reconnect resume p95 ${reconnectContractSummary.resumeLatencyP95Ms}ms exceeded ${options.reconnectResumeFailAfterMs}ms.` : `${reconnectContractSummary.failed} reconnect contract(s) failed.`,
|
|
30304
30524
|
href: options.links?.reconnectContracts ?? options.links?.sessions ?? "/sessions",
|
|
30305
30525
|
label: "Reconnect recovery contracts",
|
|
30306
30526
|
proofSource: proofSource("reconnectContracts", "reconnect"),
|
|
30307
|
-
gateExplanation: reconnectContractSummary.status === "pass" ? undefined :
|
|
30527
|
+
gateExplanation: reconnectContractSummary.status === "pass" ? undefined : reconnectContractBreadthSummary && reconnectContractBreadthSummary.length > 0 ? {
|
|
30528
|
+
evidenceHref: options.links?.reconnectContracts ?? options.links?.sessions ?? "/sessions",
|
|
30529
|
+
observed: reconnectContractBreadthSummary.join("; "),
|
|
30530
|
+
remediation: "Increase reconnect contract breadth (count and snapshot depth) before marking this gate as passing.",
|
|
30531
|
+
thresholdLabel: "Reconnect contract breadth",
|
|
30532
|
+
unit: "count"
|
|
30533
|
+
} : calibratedGateExplanation({
|
|
30308
30534
|
evidenceHref: options.links?.reconnectContracts ?? options.links?.sessions ?? "/sessions",
|
|
30309
30535
|
observed: reconnectContractSummary.resumeLatencyP95Ms,
|
|
30310
30536
|
remediation: "Inspect reconnect lifecycle traces, restore faster resume/replay-safe state, then rerun reconnect proof.",
|
|
@@ -30573,6 +30799,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30573
30799
|
handoffRetry: "/api/voice-handoffs/retry",
|
|
30574
30800
|
liveLatency: "/traces",
|
|
30575
30801
|
operationsRecords: "/voice-operations",
|
|
30802
|
+
incidentRecoveryTrends: "/voice/incident-recovery-trends",
|
|
30576
30803
|
observabilityExport: "/voice/observability-export",
|
|
30577
30804
|
observabilityExportDeliveries: "/api/voice/observability-export/deliveries",
|
|
30578
30805
|
monitoring: "/voice/monitors",
|
|
@@ -30617,6 +30844,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
30617
30844
|
},
|
|
30618
30845
|
liveLatency,
|
|
30619
30846
|
incidentRecoveryOutcomes: incidentRecoveryOutcomeSummary,
|
|
30847
|
+
incidentRecoveryTrend: incidentRecoveryTrendSummary,
|
|
30620
30848
|
mediaPipeline: mediaPipelineSummary,
|
|
30621
30849
|
monitoring: monitoringSummary,
|
|
30622
30850
|
monitoringNotifierDelivery: monitoringNotifierDeliverySummary,
|
|
@@ -31576,7 +31804,10 @@ var runVoiceSessionEvals = async (options = {}) => {
|
|
|
31576
31804
|
const events = filterVoiceTraceEvents(options.events ?? await options.store?.list() ?? []);
|
|
31577
31805
|
const grouped = new Map;
|
|
31578
31806
|
for (const event of events) {
|
|
31579
|
-
grouped.set(event.sessionId, [
|
|
31807
|
+
grouped.set(event.sessionId, [
|
|
31808
|
+
...grouped.get(event.sessionId) ?? [],
|
|
31809
|
+
event
|
|
31810
|
+
]);
|
|
31580
31811
|
}
|
|
31581
31812
|
const sessions = await Promise.all([...grouped.entries()].map(async ([sessionId, sessionEvents]) => {
|
|
31582
31813
|
const sorted = filterVoiceTraceEvents(sessionEvents);
|
|
@@ -31692,7 +31923,10 @@ var runVoiceScenarioEvals = async (options = {}) => {
|
|
|
31692
31923
|
const events = filterVoiceTraceEvents(options.events ?? await options.store?.list() ?? []);
|
|
31693
31924
|
const grouped = new Map;
|
|
31694
31925
|
for (const event of events) {
|
|
31695
|
-
grouped.set(event.sessionId, [
|
|
31926
|
+
grouped.set(event.sessionId, [
|
|
31927
|
+
...grouped.get(event.sessionId) ?? [],
|
|
31928
|
+
event
|
|
31929
|
+
]);
|
|
31696
31930
|
}
|
|
31697
31931
|
const results = scenarios.map((scenario) => {
|
|
31698
31932
|
const sessions = [...grouped.entries()].filter(([, sessionEvents]) => scenario.scenarioId ? sessionEvents.some((event) => event.scenarioId === scenario.scenarioId) : true).map(([sessionId, sessionEvents]) => evaluateScenarioSession(scenario, sessionId, filterVoiceTraceEvents(sessionEvents), resolveSessionHref3(options.operationsRecordHref, sessionId))).sort((left, right) => left.sessionId.localeCompare(right.sessionId));
|
|
@@ -31726,7 +31960,10 @@ var runVoiceScenarioEvals = async (options = {}) => {
|
|
|
31726
31960
|
total: results.length
|
|
31727
31961
|
};
|
|
31728
31962
|
};
|
|
31729
|
-
var resolveScenarioFixtures = async (options) => [
|
|
31963
|
+
var resolveScenarioFixtures = async (options) => [
|
|
31964
|
+
...options.fixtures ?? [],
|
|
31965
|
+
...await options.fixtureStore?.list() ?? []
|
|
31966
|
+
];
|
|
31730
31967
|
var runVoiceScenarioFixtureEvals = async (options = {}) => {
|
|
31731
31968
|
const fixtures = await resolveScenarioFixtures(options);
|
|
31732
31969
|
const results = await Promise.all(fixtures.map(async (fixture) => {
|
|
@@ -32689,7 +32926,9 @@ var evaluateVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
32689
32926
|
const toolNames = [
|
|
32690
32927
|
...new Set(report.contracts.map((contract) => contract.toolName))
|
|
32691
32928
|
].sort();
|
|
32692
|
-
const caseStatuses = [
|
|
32929
|
+
const caseStatuses = [
|
|
32930
|
+
...new Set(cases.map((testCase) => testCase.status))
|
|
32931
|
+
].sort();
|
|
32693
32932
|
const issueCount = report.contracts.reduce((total, contract) => total + contract.issues.length, 0);
|
|
32694
32933
|
const timedOut = cases.filter((testCase) => testCase.timedOut).length;
|
|
32695
32934
|
const missingOperationsRecordHrefs = cases.filter((testCase) => !testCase.operationsRecordHref).length;
|
|
@@ -33198,7 +33437,11 @@ var presetDefinitions = {
|
|
|
33198
33437
|
"appointment-booking": {
|
|
33199
33438
|
description: "Appointment booking should complete with enough identity, appointment, and follow-up details to act on.",
|
|
33200
33439
|
fields: [
|
|
33201
|
-
{
|
|
33440
|
+
{
|
|
33441
|
+
aliases: ["name", "customer.name"],
|
|
33442
|
+
label: "Caller name",
|
|
33443
|
+
path: "caller.name"
|
|
33444
|
+
},
|
|
33202
33445
|
{
|
|
33203
33446
|
aliases: ["phone", "customer.phone"],
|
|
33204
33447
|
label: "Caller phone",
|
|
@@ -33223,7 +33466,11 @@ var presetDefinitions = {
|
|
|
33223
33466
|
"lead-qualification": {
|
|
33224
33467
|
description: "Lead qualification should complete with contact, need, qualification, and next-step fields.",
|
|
33225
33468
|
fields: [
|
|
33226
|
-
{
|
|
33469
|
+
{
|
|
33470
|
+
aliases: ["name", "lead.name"],
|
|
33471
|
+
label: "Lead name",
|
|
33472
|
+
path: "contact.name"
|
|
33473
|
+
},
|
|
33227
33474
|
{
|
|
33228
33475
|
aliases: ["email", "lead.email"],
|
|
33229
33476
|
label: "Lead email",
|
|
@@ -33606,7 +33853,9 @@ var evaluateVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
33606
33853
|
const maxIssues = input.maxIssues ?? 0;
|
|
33607
33854
|
const maxBlockedHandoffs = input.maxBlockedHandoffs ?? Infinity;
|
|
33608
33855
|
const allHandoffs = reports.flatMap((report) => report.turns.flatMap((turn) => turn.handoffs));
|
|
33609
|
-
const contractIds = [
|
|
33856
|
+
const contractIds = [
|
|
33857
|
+
...new Set(reports.map((report) => report.contractId))
|
|
33858
|
+
].sort();
|
|
33610
33859
|
const scenarioIds = [
|
|
33611
33860
|
...new Set(reports.map((report) => report.scenarioId).filter((scenarioId) => Boolean(scenarioId)))
|
|
33612
33861
|
].sort();
|
|
@@ -33785,7 +34034,11 @@ var summarizeVoiceTurnLatency = async (options) => {
|
|
|
33785
34034
|
const stageIndex = createTraceStageIndex(traceEvents);
|
|
33786
34035
|
const warnAfterMs = options.warnAfterMs ?? DEFAULT_WARN_AFTER_MS2;
|
|
33787
34036
|
const failAfterMs = options.failAfterMs ?? DEFAULT_FAIL_AFTER_MS2;
|
|
33788
|
-
const turns = sessions.flatMap((session) => session.turns.map((turn) => summarizeTurn(session.id, turn, {
|
|
34037
|
+
const turns = sessions.flatMap((session) => session.turns.map((turn) => summarizeTurn(session.id, turn, {
|
|
34038
|
+
failAfterMs,
|
|
34039
|
+
stageIndex,
|
|
34040
|
+
warnAfterMs
|
|
34041
|
+
}))).sort((left, right) => right.committedAt - left.committedAt);
|
|
33789
34042
|
const totals = turns.map((turn) => turn.totalMs).filter((value) => typeof value === "number");
|
|
33790
34043
|
const failed = turns.filter((turn) => turn.status === "fail").length;
|
|
33791
34044
|
const warnings = turns.filter((turn) => turn.status === "warn").length;
|
|
@@ -36182,7 +36435,9 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
36182
36435
|
};
|
|
36183
36436
|
const abortController = new AbortController;
|
|
36184
36437
|
const signalAbort = () => abortController.abort();
|
|
36185
|
-
openOptions.signal?.addEventListener("abort", signalAbort, {
|
|
36438
|
+
openOptions.signal?.addEventListener("abort", signalAbort, {
|
|
36439
|
+
once: true
|
|
36440
|
+
});
|
|
36186
36441
|
let closed = false;
|
|
36187
36442
|
return {
|
|
36188
36443
|
close: async (reason) => {
|
|
@@ -36310,7 +36565,9 @@ var resolveCapabilityDefinitions = (options) => {
|
|
|
36310
36565
|
};
|
|
36311
36566
|
var summarizeVoiceProviderCapabilities = async (options) => {
|
|
36312
36567
|
const definitions = resolveCapabilityDefinitions(options);
|
|
36313
|
-
const providerNames = [
|
|
36568
|
+
const providerNames = [
|
|
36569
|
+
...new Set(definitions.map((entry) => entry.provider))
|
|
36570
|
+
];
|
|
36314
36571
|
const health = await summarizeVoiceProviderHealth({
|
|
36315
36572
|
events: options.events,
|
|
36316
36573
|
now: options.now,
|
|
@@ -36638,7 +36895,9 @@ var evaluateVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
36638
36895
|
const maxFailed = input.maxFailed ?? 0;
|
|
36639
36896
|
const maxIssues = input.maxIssues ?? 0;
|
|
36640
36897
|
const events = reports.flatMap((report) => report.events);
|
|
36641
|
-
const contractIds = [
|
|
36898
|
+
const contractIds = [
|
|
36899
|
+
...new Set(reports.map((report) => report.contractId))
|
|
36900
|
+
].sort();
|
|
36642
36901
|
const scenarioIds = [
|
|
36643
36902
|
...new Set(reports.map((report) => report.scenarioId).filter((scenarioId) => Boolean(scenarioId)))
|
|
36644
36903
|
].sort();
|
|
@@ -37354,6 +37613,11 @@ var createVoiceReadinessProfile = (profile, options = {}) => {
|
|
|
37354
37613
|
bargeInReports: options.bargeInReports,
|
|
37355
37614
|
gate: options.gate,
|
|
37356
37615
|
links: links2,
|
|
37616
|
+
browserMediaMinActiveCandidatePairs: options.browserMediaMinActiveCandidatePairs ?? 1,
|
|
37617
|
+
browserMediaMinLiveAudioTracks: options.browserMediaMinLiveAudioTracks ?? 1,
|
|
37618
|
+
browserMediaMinTotalStats: options.browserMediaMinTotalStats ?? 3,
|
|
37619
|
+
reconnectContractsMinCount: options.reconnectContractsMinCount ?? 1,
|
|
37620
|
+
reconnectContractsMinSnapshotsPerContract: options.reconnectContractsMinSnapshotsPerContract ?? 1,
|
|
37357
37621
|
profile: profileExplanation(profile, options, links2),
|
|
37358
37622
|
proofSources: options.proofSources,
|
|
37359
37623
|
providerRoutingContracts: options.providerRoutingContracts,
|
|
@@ -37387,6 +37651,13 @@ var createVoiceReadinessProfile = (profile, options = {}) => {
|
|
|
37387
37651
|
profile: profileExplanation(profile, options, links2),
|
|
37388
37652
|
proofSources: options.proofSources,
|
|
37389
37653
|
providerRoutingContracts: options.providerRoutingContracts,
|
|
37654
|
+
reconnectContractsMinCount: options.reconnectContractsMinCount ?? 1,
|
|
37655
|
+
reconnectContractsMinSnapshotsPerContract: options.reconnectContractsMinSnapshotsPerContract ?? 1,
|
|
37656
|
+
telephonyMediaMinCarriers: options.telephonyMediaMinCarriers ?? 1,
|
|
37657
|
+
telephonyMediaMinMediaEvents: options.telephonyMediaMinMediaEvents ?? 2,
|
|
37658
|
+
browserMediaMinActiveCandidatePairs: options.browserMediaMinActiveCandidatePairs ?? 1,
|
|
37659
|
+
browserMediaMinLiveAudioTracks: options.browserMediaMinLiveAudioTracks ?? 1,
|
|
37660
|
+
browserMediaMinTotalStats: options.browserMediaMinTotalStats ?? 3,
|
|
37390
37661
|
telephonyWebhookSecurity: options.telephonyWebhookSecurity,
|
|
37391
37662
|
traceDeliveries: options.traceDeliveries
|
|
37392
37663
|
});
|
|
@@ -37506,11 +37777,7 @@ var defaultProviderEnv2 = {
|
|
|
37506
37777
|
gemini: ["GEMINI_API_KEY"],
|
|
37507
37778
|
openai: ["OPENAI_API_KEY"]
|
|
37508
37779
|
};
|
|
37509
|
-
var defaultStreamingProviders = new Set([
|
|
37510
|
-
"assemblyai",
|
|
37511
|
-
"deepgram",
|
|
37512
|
-
"openai"
|
|
37513
|
-
]);
|
|
37780
|
+
var defaultStreamingProviders = new Set(["assemblyai", "deepgram", "openai"]);
|
|
37514
37781
|
var defaultProviderCapabilities = {
|
|
37515
37782
|
anthropic: ["tool calling", "JSON result shaping", "fallback routing"],
|
|
37516
37783
|
assemblyai: ["realtime STT", "turn formatting", "fallback STT"],
|
|
@@ -40535,10 +40802,7 @@ var createRiskyTurnCorrectionHandler = (options = {}) => {
|
|
|
40535
40802
|
if (averageConfidence !== undefined && averageConfidence > maxAverageConfidence) {
|
|
40536
40803
|
return;
|
|
40537
40804
|
}
|
|
40538
|
-
const result = applyRiskTieredPhraseHintCorrections(text, [
|
|
40539
|
-
...phraseHints,
|
|
40540
|
-
...lexiconToPhraseHints(lexicon)
|
|
40541
|
-
], { riskTier });
|
|
40805
|
+
const result = applyRiskTieredPhraseHintCorrections(text, [...phraseHints, ...lexiconToPhraseHints(lexicon)], { riskTier });
|
|
40542
40806
|
if (!result.changed) {
|
|
40543
40807
|
return;
|
|
40544
40808
|
}
|
|
@@ -41304,7 +41568,9 @@ var createVoiceProofPackSupportBundleSection = (input) => {
|
|
|
41304
41568
|
};
|
|
41305
41569
|
};
|
|
41306
41570
|
var buildDerivedProofPackSections = (input) => [
|
|
41307
|
-
...input.productionReadiness ? [
|
|
41571
|
+
...input.productionReadiness ? [
|
|
41572
|
+
createVoiceProofPackProductionReadinessSection(input.productionReadiness)
|
|
41573
|
+
] : [],
|
|
41308
41574
|
...input.providerSlo ? [
|
|
41309
41575
|
createVoiceProofPackProviderSloSection(input.providerSlo, {
|
|
41310
41576
|
href: input.productionReadiness?.links.providerSlo
|
|
@@ -41331,7 +41597,10 @@ var buildVoiceProofPack = (input) => {
|
|
|
41331
41597
|
if ("status" in input && "ok" in input && "summary" in input && Array.isArray(input.sections)) {
|
|
41332
41598
|
return input;
|
|
41333
41599
|
}
|
|
41334
|
-
const sections = [
|
|
41600
|
+
const sections = [
|
|
41601
|
+
...buildDerivedProofPackSections(input),
|
|
41602
|
+
...input.sections ?? []
|
|
41603
|
+
];
|
|
41335
41604
|
const summary = summarizeProofPackSections(sections);
|
|
41336
41605
|
const status = summary.fail > 0 ? "fail" : summary.warn > 0 ? "warn" : "pass";
|
|
41337
41606
|
return {
|
|
@@ -41486,13 +41755,7 @@ var renderVoiceProofPackMarkdown = (proofPack) => {
|
|
|
41486
41755
|
return `- ${item.label}${value}${href} - ${item.status ?? "pass"}${detail}`;
|
|
41487
41756
|
}).join(`
|
|
41488
41757
|
`);
|
|
41489
|
-
return [
|
|
41490
|
-
`## ${section.title}`,
|
|
41491
|
-
"",
|
|
41492
|
-
section.summary ?? "",
|
|
41493
|
-
"",
|
|
41494
|
-
evidence
|
|
41495
|
-
].filter(Boolean).join(`
|
|
41758
|
+
return [`## ${section.title}`, "", section.summary ?? "", "", evidence].filter(Boolean).join(`
|
|
41496
41759
|
`);
|
|
41497
41760
|
}).join(`
|
|
41498
41761
|
|
|
@@ -42259,6 +42522,7 @@ export {
|
|
|
42259
42522
|
buildVoiceLiveOpsControlState,
|
|
42260
42523
|
buildVoiceLatencySLOGate,
|
|
42261
42524
|
buildVoiceIncidentTimelineReport,
|
|
42525
|
+
buildVoiceIncidentRecoveryTrendSLOReadinessCheck,
|
|
42262
42526
|
buildVoiceIncidentRecoveryTrendReport,
|
|
42263
42527
|
buildVoiceIncidentRecoveryOutcomeReport,
|
|
42264
42528
|
buildVoiceIncidentRecoveryOutcomeReadinessCheck,
|