@absolutejs/voice 0.0.22-beta.100 → 0.0.22-beta.102
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/dist/client/index.js +18 -0
- package/dist/client/liveTurnLatency.d.ts +3 -0
- package/dist/index.js +34 -0
- package/dist/productionReadiness.d.ts +10 -0
- package/dist/trace.d.ts +1 -1
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -1758,6 +1758,23 @@ var createVoiceLiveTurnLatencyMonitor = (options = {}) => {
|
|
|
1758
1758
|
listener();
|
|
1759
1759
|
}
|
|
1760
1760
|
};
|
|
1761
|
+
const reportCompletedEvent = async (event) => {
|
|
1762
|
+
await options.onComplete?.(event);
|
|
1763
|
+
if (!options.reportPath) {
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1767
|
+
const response = await fetchImpl(options.reportPath, {
|
|
1768
|
+
body: JSON.stringify(event),
|
|
1769
|
+
headers: {
|
|
1770
|
+
"content-type": "application/json"
|
|
1771
|
+
},
|
|
1772
|
+
method: "POST"
|
|
1773
|
+
});
|
|
1774
|
+
if (!response.ok) {
|
|
1775
|
+
throw new Error(`Voice live turn latency report failed: HTTP ${response.status}`);
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1761
1778
|
const completePending = (input) => {
|
|
1762
1779
|
if (!pending) {
|
|
1763
1780
|
return;
|
|
@@ -1773,6 +1790,7 @@ var createVoiceLiveTurnLatencyMonitor = (options = {}) => {
|
|
|
1773
1790
|
status
|
|
1774
1791
|
};
|
|
1775
1792
|
events = [pending, ...events].slice(0, maxEvents);
|
|
1793
|
+
reportCompletedEvent(pending).catch(() => {});
|
|
1776
1794
|
pending = undefined;
|
|
1777
1795
|
emit();
|
|
1778
1796
|
};
|
|
@@ -26,7 +26,10 @@ export type VoiceLiveTurnLatencySnapshot = {
|
|
|
26
26
|
export type VoiceLiveTurnLatencyMonitorOptions = {
|
|
27
27
|
clock?: () => number;
|
|
28
28
|
failAfterMs?: number;
|
|
29
|
+
fetch?: typeof fetch;
|
|
29
30
|
maxEvents?: number;
|
|
31
|
+
onComplete?: (event: VoiceLiveTurnLatencyEvent) => Promise<void> | void;
|
|
32
|
+
reportPath?: string;
|
|
30
33
|
speechThreshold?: number;
|
|
31
34
|
warnAfterMs?: number;
|
|
32
35
|
};
|
package/dist/index.js
CHANGED
|
@@ -9744,12 +9744,28 @@ var resolveCarriers = async (options, input) => {
|
|
|
9744
9744
|
providers: [...providers]
|
|
9745
9745
|
});
|
|
9746
9746
|
};
|
|
9747
|
+
var summarizeLiveLatency = (events, options) => {
|
|
9748
|
+
const warnAfterMs = options.liveLatencyWarnAfterMs ?? 1800;
|
|
9749
|
+
const failAfterMs = options.liveLatencyFailAfterMs ?? 3200;
|
|
9750
|
+
const latencies = events.filter((event) => event.type === "client.live_latency").map((event) => typeof event.payload.latencyMs === "number" ? event.payload.latencyMs : typeof event.payload.elapsedMs === "number" ? event.payload.elapsedMs : undefined).filter((value) => typeof value === "number");
|
|
9751
|
+
const failed = latencies.filter((value) => value > failAfterMs).length;
|
|
9752
|
+
const warnings = latencies.filter((value) => value > warnAfterMs && value <= failAfterMs).length;
|
|
9753
|
+
const averageLatencyMs = latencies.length > 0 ? Math.round(latencies.reduce((total, value) => total + value, 0) / latencies.length) : undefined;
|
|
9754
|
+
return {
|
|
9755
|
+
averageLatencyMs,
|
|
9756
|
+
failed,
|
|
9757
|
+
status: latencies.length === 0 ? "warn" : failed > 0 ? "fail" : warnings > 0 ? "warn" : "pass",
|
|
9758
|
+
total: latencies.length,
|
|
9759
|
+
warnings
|
|
9760
|
+
};
|
|
9761
|
+
};
|
|
9747
9762
|
var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
9748
9763
|
const request = input.request ?? new Request("http://localhost/");
|
|
9749
9764
|
const query = input.query ?? {};
|
|
9750
9765
|
const events = await options.store.list();
|
|
9751
9766
|
const routingEvents = listVoiceRoutingEvents(events);
|
|
9752
9767
|
const routingSessions = summarizeVoiceRoutingSessions(routingEvents);
|
|
9768
|
+
const liveLatency = summarizeLiveLatency(events, options);
|
|
9753
9769
|
const [quality, providers, sessions, handoffs, carriers] = await Promise.all([
|
|
9754
9770
|
evaluateVoiceQuality({ events }),
|
|
9755
9771
|
Promise.all([
|
|
@@ -9856,6 +9872,20 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9856
9872
|
]
|
|
9857
9873
|
}
|
|
9858
9874
|
];
|
|
9875
|
+
checks.push({
|
|
9876
|
+
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).`,
|
|
9877
|
+
href: options.links?.liveLatency ?? "/traces",
|
|
9878
|
+
label: "Live latency proof",
|
|
9879
|
+
status: liveLatency.status,
|
|
9880
|
+
value: liveLatency.averageLatencyMs === undefined ? `${liveLatency.total} samples` : `${liveLatency.averageLatencyMs}ms avg`,
|
|
9881
|
+
actions: liveLatency.status === "pass" ? [] : [
|
|
9882
|
+
{
|
|
9883
|
+
description: "Run a live browser voice turn and inspect the persisted latency trace.",
|
|
9884
|
+
href: options.links?.liveLatency ?? "/traces",
|
|
9885
|
+
label: "Open live latency traces"
|
|
9886
|
+
}
|
|
9887
|
+
]
|
|
9888
|
+
});
|
|
9859
9889
|
const carrierSummary = carriers ? {
|
|
9860
9890
|
failing: carriers.summary.failing,
|
|
9861
9891
|
providers: carriers.summary.providers,
|
|
@@ -9886,6 +9916,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9886
9916
|
carriers: "/carriers",
|
|
9887
9917
|
handoffs: "/handoffs",
|
|
9888
9918
|
handoffRetry: "/api/voice-handoffs/retry",
|
|
9919
|
+
liveLatency: "/traces",
|
|
9889
9920
|
quality: "/quality",
|
|
9890
9921
|
resilience: "/resilience",
|
|
9891
9922
|
sessions: "/sessions",
|
|
@@ -9898,6 +9929,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9898
9929
|
failed: handoffs.failed,
|
|
9899
9930
|
total: handoffs.total
|
|
9900
9931
|
},
|
|
9932
|
+
liveLatency,
|
|
9901
9933
|
providers: {
|
|
9902
9934
|
degraded: degradedProviders,
|
|
9903
9935
|
total: providers.length
|
|
@@ -10017,6 +10049,8 @@ var timelineLabel = (event) => {
|
|
|
10017
10049
|
return `Guardrail ${eventStatus(event) ?? "check"}`;
|
|
10018
10050
|
case "call.handoff":
|
|
10019
10051
|
return `Call handoff ${eventStatus(event) ?? ""}`.trim();
|
|
10052
|
+
case "client.live_latency":
|
|
10053
|
+
return `Live latency${eventElapsedMs(event) !== undefined ? ` ${eventElapsedMs(event)}ms` : ""}`;
|
|
10020
10054
|
case "session.error":
|
|
10021
10055
|
return `Error${getString9(event.payload.error) ? `: ${getString9(event.payload.error)}` : ""}`;
|
|
10022
10056
|
case "turn.cost":
|
|
@@ -23,6 +23,7 @@ export type VoiceProductionReadinessReport = {
|
|
|
23
23
|
carriers?: string;
|
|
24
24
|
handoffs?: string;
|
|
25
25
|
handoffRetry?: string;
|
|
26
|
+
liveLatency?: string;
|
|
26
27
|
quality?: string;
|
|
27
28
|
resilience?: string;
|
|
28
29
|
sessions?: string;
|
|
@@ -40,6 +41,13 @@ export type VoiceProductionReadinessReport = {
|
|
|
40
41
|
failed: number;
|
|
41
42
|
total: number;
|
|
42
43
|
};
|
|
44
|
+
liveLatency: {
|
|
45
|
+
averageLatencyMs?: number;
|
|
46
|
+
failed: number;
|
|
47
|
+
status: VoiceProductionReadinessStatus;
|
|
48
|
+
total: number;
|
|
49
|
+
warnings: number;
|
|
50
|
+
};
|
|
43
51
|
providers: {
|
|
44
52
|
degraded: number;
|
|
45
53
|
total: number;
|
|
@@ -73,6 +81,8 @@ export type VoiceProductionReadinessRoutesOptions = {
|
|
|
73
81
|
sttProviders?: readonly string[];
|
|
74
82
|
title?: string;
|
|
75
83
|
ttsProviders?: readonly string[];
|
|
84
|
+
liveLatencyWarnAfterMs?: number;
|
|
85
|
+
liveLatencyFailAfterMs?: number;
|
|
76
86
|
};
|
|
77
87
|
export declare const buildVoiceProductionReadinessReport: (options: VoiceProductionReadinessRoutesOptions, input?: {
|
|
78
88
|
query?: Record<string, unknown>;
|
package/dist/trace.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn_latency.stage' | 'turn.transcript' | 'workflow.contract';
|
|
1
|
+
export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'client.live_latency' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn_latency.stage' | 'turn.transcript' | 'workflow.contract';
|
|
2
2
|
export type VoiceTraceEvent<TPayload extends Record<string, unknown> = Record<string, unknown>> = {
|
|
3
3
|
at: number;
|
|
4
4
|
id?: string;
|