@absolutejs/voice 0.0.22-beta.450 → 0.0.22-beta.452
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/htmxBootstrap.js +4 -1
- package/dist/client/index.js +91 -4
- package/dist/generated/htmxBootstrapBundle.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +94 -5
- package/dist/proofTrends.d.ts +29 -0
- package/dist/react/index.js +91 -4
- package/dist/vue/index.js +91 -4
- package/package.json +1 -1
|
@@ -2099,7 +2099,10 @@ var parseOptionalNumber = (value) => {
|
|
|
2099
2099
|
return Number.isFinite(parsed) ? parsed : undefined;
|
|
2100
2100
|
};
|
|
2101
2101
|
var resolveElement2 = (root, selector, ctor) => {
|
|
2102
|
-
|
|
2102
|
+
if (!selector) {
|
|
2103
|
+
return null;
|
|
2104
|
+
}
|
|
2105
|
+
const value = document.querySelector(selector);
|
|
2103
2106
|
return value instanceof ctor ? value : null;
|
|
2104
2107
|
};
|
|
2105
2108
|
var requireElement = (root, selector, ctor, name) => {
|
package/dist/client/index.js
CHANGED
|
@@ -6261,6 +6261,7 @@ var readString = (value) => typeof value === "string" && value.trim() ? value :
|
|
|
6261
6261
|
var readNumber2 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
6262
6262
|
var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
|
|
6263
6263
|
var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms ?? maxNumber((report.summary.providers ?? []).map((provider) => provider.p95Ms)) ?? maxNumber(report.cycles.flatMap((cycle) => (cycle.providers ?? []).map((provider) => provider.p95Ms)));
|
|
6264
|
+
var readProofTrendMaxReconnectP95 = (report) => report.summary.maxReconnectP95Ms ?? report.summary.reconnect?.resumeLatencyP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.reconnect?.resumeLatencyP95Ms));
|
|
6264
6265
|
var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
|
|
6265
6266
|
var readRuntimeChannelMetric = (report, key) => {
|
|
6266
6267
|
const summaryValue = report.summary.runtimeChannel?.[key];
|
|
@@ -6322,6 +6323,42 @@ var aggregateProofTrendRuntimeChannel = (channels) => {
|
|
|
6322
6323
|
status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
|
|
6323
6324
|
};
|
|
6324
6325
|
};
|
|
6326
|
+
var aggregateProofTrendReconnect = (reconnects) => {
|
|
6327
|
+
if (reconnects.length === 0) {
|
|
6328
|
+
return;
|
|
6329
|
+
}
|
|
6330
|
+
const hasFailure = reconnects.some((reconnect) => reconnect.status === "fail" || reconnect.exhausted === true || reconnect.reconnected === false || reconnect.resumed === false);
|
|
6331
|
+
return {
|
|
6332
|
+
attempts: maxNumber(reconnects.map((reconnect) => reconnect.attempts)),
|
|
6333
|
+
exhausted: reconnects.some((reconnect) => reconnect.exhausted === true),
|
|
6334
|
+
maxAttempts: maxNumber(reconnects.map((reconnect) => reconnect.maxAttempts)),
|
|
6335
|
+
resumeLatencyP95Ms: maxNumber(reconnects.map((reconnect) => reconnect.resumeLatencyP95Ms)),
|
|
6336
|
+
reconnected: reconnects.some((reconnect) => reconnect.reconnected === true),
|
|
6337
|
+
resumed: reconnects.some((reconnect) => reconnect.resumed === true),
|
|
6338
|
+
samples: reconnects.reduce((total, reconnect) => total + (reconnect.samples ?? 0), 0),
|
|
6339
|
+
snapshotCount: reconnects.reduce((total, reconnect) => total + (reconnect.snapshotCount ?? 0), 0),
|
|
6340
|
+
status: hasFailure ? "fail" : reconnects.some((reconnect) => reconnect.status === "warn") ? "warn" : "pass"
|
|
6341
|
+
};
|
|
6342
|
+
};
|
|
6343
|
+
var summarizeReconnectTraceEvidence = (events) => {
|
|
6344
|
+
const reconnectEvents = events.filter((event) => event.type === "client.reconnect");
|
|
6345
|
+
if (reconnectEvents.length === 0) {
|
|
6346
|
+
return;
|
|
6347
|
+
}
|
|
6348
|
+
const statuses = reconnectEvents.map((event) => readString(readTraceRecord(event).status)).filter((status) => status !== undefined);
|
|
6349
|
+
const reconnectPayloads = reconnectEvents.map((event) => readTraceRecord(event));
|
|
6350
|
+
return {
|
|
6351
|
+
attempts: maxNumber(reconnectPayloads.map((payload) => readNumber2(payload.attempts))),
|
|
6352
|
+
exhausted: statuses.includes("exhausted"),
|
|
6353
|
+
maxAttempts: maxNumber(reconnectPayloads.map((payload) => readNumber2(payload.maxAttempts))),
|
|
6354
|
+
resumeLatencyP95Ms: percentile(reconnectPayloads.map((payload) => readNumber2(payload.resumeLatencyP95Ms) ?? readNumber2(payload.resumeLatencyMs)).filter((value) => value !== undefined), 95),
|
|
6355
|
+
reconnected: statuses.includes("reconnecting"),
|
|
6356
|
+
resumed: statuses.includes("resumed") || statuses.includes("pass"),
|
|
6357
|
+
samples: reconnectEvents.length,
|
|
6358
|
+
snapshotCount: reconnectEvents.length,
|
|
6359
|
+
status: reconnectEvents.some((event) => isFailingTraceStatus(readTraceStatus(readTraceRecord(event)))) ? "fail" : "pass"
|
|
6360
|
+
};
|
|
6361
|
+
};
|
|
6325
6362
|
var readTraceRecord = (event) => event.payload;
|
|
6326
6363
|
var readTraceProfileId = (events, options) => {
|
|
6327
6364
|
for (const event of events) {
|
|
@@ -6469,6 +6506,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
|
|
|
6469
6506
|
}).filter((value) => value !== undefined);
|
|
6470
6507
|
const turnP95Ms = summarizeTurnTraceP95(sessionEvents);
|
|
6471
6508
|
const providerP95Ms = maxNumber(providers.map((provider) => provider.p95Ms));
|
|
6509
|
+
const reconnect = summarizeReconnectTraceEvidence(sessionEvents);
|
|
6472
6510
|
const runtimeChannel = summarizeRuntimeChannelTraceEvidence(sessionEvents);
|
|
6473
6511
|
const surfaces = readRealCallProfileTraceSurfaces(sessionEvents);
|
|
6474
6512
|
if (providers.length === 0 && runtimeChannel === undefined && liveLatencies.length === 0 && surfaces.length === 0) {
|
|
@@ -6484,6 +6522,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
|
|
|
6484
6522
|
profileLabel: options.profileLabels?.[profileId] ?? (profileId === options.defaultProfileId ? options.defaultProfileLabel : undefined),
|
|
6485
6523
|
providerP95Ms,
|
|
6486
6524
|
providers,
|
|
6525
|
+
reconnect,
|
|
6487
6526
|
runtimeChannel,
|
|
6488
6527
|
sessionId,
|
|
6489
6528
|
surfaces: surfaces.length > 0 ? surfaces : undefined,
|
|
@@ -6491,11 +6530,45 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
|
|
|
6491
6530
|
};
|
|
6492
6531
|
}).filter((evidence) => evidence !== undefined);
|
|
6493
6532
|
};
|
|
6533
|
+
var normalizeReconnectReport = (report) => ("contract" in report) ? report.contract : report;
|
|
6534
|
+
var buildVoiceRealCallProfileEvidenceFromReconnectProofReports = (input, options = {}) => {
|
|
6535
|
+
const reports = Array.isArray(input) ? input : [input];
|
|
6536
|
+
const profileId = options.profileId ?? "reconnect-resume";
|
|
6537
|
+
return reports.map((report, index) => {
|
|
6538
|
+
const contract = normalizeReconnectReport(report);
|
|
6539
|
+
const generatedAt = "generatedAt" in report ? report.generatedAt : new Date(contract.checkedAt).toISOString();
|
|
6540
|
+
const ok = "ok" in report ? report.ok : contract.pass;
|
|
6541
|
+
const operationsRecordHref = typeof options.operationsRecordHref === "function" ? options.operationsRecordHref(report, index) : options.operationsRecordHref;
|
|
6542
|
+
const sessionId = typeof options.sessionId === "function" ? options.sessionId(report, index) : options.sessionId ?? `reconnect-proof-${String(index + 1)}-${String(contract.checkedAt)}`;
|
|
6543
|
+
return {
|
|
6544
|
+
generatedAt,
|
|
6545
|
+
ok,
|
|
6546
|
+
operationsRecordHref,
|
|
6547
|
+
profileDescription: options.profileDescription,
|
|
6548
|
+
profileId,
|
|
6549
|
+
profileLabel: options.profileLabel,
|
|
6550
|
+
reconnect: {
|
|
6551
|
+
attempts: contract.summary.attempts,
|
|
6552
|
+
exhausted: contract.summary.exhausted,
|
|
6553
|
+
maxAttempts: contract.summary.maxAttempts,
|
|
6554
|
+
resumeLatencyP95Ms: contract.resumeLatencyP95Ms,
|
|
6555
|
+
reconnected: contract.summary.reconnected,
|
|
6556
|
+
resumed: contract.summary.resumed,
|
|
6557
|
+
samples: 1,
|
|
6558
|
+
snapshotCount: contract.snapshotCount,
|
|
6559
|
+
status: ok ? "pass" : "fail"
|
|
6560
|
+
},
|
|
6561
|
+
sessionId,
|
|
6562
|
+
surfaces: [...new Set(["reconnect", ...options.surfaces ?? []])].sort()
|
|
6563
|
+
};
|
|
6564
|
+
});
|
|
6565
|
+
};
|
|
6494
6566
|
var loadVoiceRealCallProfileEvidenceFromTraceStore = async (options) => buildVoiceRealCallProfileEvidenceFromTraceEvents(await options.store.list({ limit: options.limit ?? 5000 }), options);
|
|
6495
6567
|
var realCallProfileTraceSignalTypes = new Set([
|
|
6496
6568
|
"client.barge_in",
|
|
6497
6569
|
"client.browser_media",
|
|
6498
6570
|
"client.live_latency",
|
|
6571
|
+
"client.reconnect",
|
|
6499
6572
|
"client.telephony_media",
|
|
6500
6573
|
"provider.decision",
|
|
6501
6574
|
"session.error",
|
|
@@ -6558,15 +6631,16 @@ var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.
|
|
|
6558
6631
|
var exceedsProofTrendBudget = (value, budget) => value !== undefined && (!Number.isFinite(value) || value > budget);
|
|
6559
6632
|
var readProofTrendProfileStatus = (profile, budgets) => {
|
|
6560
6633
|
const runtimeChannel = profile.runtimeChannel;
|
|
6561
|
-
const
|
|
6562
|
-
const
|
|
6634
|
+
const reconnect = profile.reconnect;
|
|
6635
|
+
const hasBudgetEvidence = profile.maxLiveP95Ms !== undefined || profile.maxProviderP95Ms !== undefined || profile.maxReconnectP95Ms !== undefined || profile.maxTurnP95Ms !== undefined || profile.providers?.some((provider) => provider.p95Ms !== undefined) === true || runtimeChannel?.maxFirstAudioLatencyMs !== undefined || runtimeChannel?.maxInterruptionP95Ms !== undefined || runtimeChannel?.maxJitterMs !== undefined || runtimeChannel?.maxTimestampDriftMs !== undefined || runtimeChannel?.maxBackpressureEvents !== undefined || reconnect?.resumeLatencyP95Ms !== undefined || reconnect?.samples !== undefined;
|
|
6636
|
+
const budgetFailed = exceedsProofTrendBudget(profile.maxLiveP95Ms, budgets.maxLiveP95Ms) || exceedsProofTrendBudget(profile.maxProviderP95Ms, budgets.maxProviderP95Ms) || exceedsProofTrendBudget(profile.maxReconnectP95Ms ?? reconnect?.resumeLatencyP95Ms, budgets.maxReconnectP95Ms) || exceedsProofTrendBudget(profile.maxTurnP95Ms, budgets.maxTurnP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxFirstAudioLatencyMs, budgets.maxRuntimeFirstAudioLatencyMs) || exceedsProofTrendBudget(runtimeChannel?.maxInterruptionP95Ms, budgets.maxRuntimeInterruptionP95Ms) || exceedsProofTrendBudget(runtimeChannel?.maxJitterMs, budgets.maxRuntimeJitterMs) || exceedsProofTrendBudget(runtimeChannel?.maxTimestampDriftMs, budgets.maxRuntimeTimestampDriftMs) || exceedsProofTrendBudget(runtimeChannel?.maxBackpressureEvents, 0) || reconnect?.status === "fail";
|
|
6563
6637
|
if (budgetFailed || !hasBudgetEvidence && profile.status === "fail") {
|
|
6564
6638
|
return "fail";
|
|
6565
6639
|
}
|
|
6566
|
-
if (profile.status === "warn" || runtimeChannel?.status === "warn" || profile.providers?.some((provider) => provider.status === "warn") === true) {
|
|
6640
|
+
if (profile.status === "warn" || reconnect?.status === "warn" || runtimeChannel?.status === "warn" || profile.providers?.some((provider) => provider.status === "warn") === true) {
|
|
6567
6641
|
return "warn";
|
|
6568
6642
|
}
|
|
6569
|
-
if (hasBudgetEvidence || profile.status === "pass" || runtimeChannel?.status === "pass" || profile.providers?.some((provider) => provider.status === "pass") === true) {
|
|
6643
|
+
if (hasBudgetEvidence || profile.status === "pass" || reconnect?.status === "pass" || runtimeChannel?.status === "pass" || profile.providers?.some((provider) => provider.status === "pass") === true) {
|
|
6570
6644
|
return "pass";
|
|
6571
6645
|
}
|
|
6572
6646
|
return;
|
|
@@ -6576,6 +6650,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
|
6576
6650
|
const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
|
|
6577
6651
|
const providerCap = options.maxProviderP95Ms ?? 1000;
|
|
6578
6652
|
const liveCap = options.maxLiveP95Ms ?? 800;
|
|
6653
|
+
const reconnectCap = options.maxReconnectP95Ms ?? 1500;
|
|
6579
6654
|
const turnCap = options.maxTurnP95Ms ?? 700;
|
|
6580
6655
|
const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
|
|
6581
6656
|
const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
|
|
@@ -6584,6 +6659,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
|
6584
6659
|
const budgets = {
|
|
6585
6660
|
maxLiveP95Ms: liveCap,
|
|
6586
6661
|
maxProviderP95Ms: providerCap,
|
|
6662
|
+
maxReconnectP95Ms: reconnectCap,
|
|
6587
6663
|
maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
|
|
6588
6664
|
maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
|
|
6589
6665
|
maxRuntimeJitterMs: runtimeJitterCap,
|
|
@@ -6606,8 +6682,10 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
|
6606
6682
|
label: definition.label ?? profiles.find(Boolean)?.label,
|
|
6607
6683
|
maxLiveP95Ms: maxNumber(profiles.map((profile) => profile.maxLiveP95Ms)),
|
|
6608
6684
|
maxProviderP95Ms: maxNumber(profiles.map((profile) => profile.maxProviderP95Ms)),
|
|
6685
|
+
maxReconnectP95Ms: maxNumber(profiles.map((profile) => profile.maxReconnectP95Ms)),
|
|
6609
6686
|
maxTurnP95Ms: maxNumber(profiles.map((profile) => profile.maxTurnP95Ms)),
|
|
6610
6687
|
providers: aggregateProofTrendProviders(profiles.flatMap((profile) => profile.providers ?? [])),
|
|
6688
|
+
reconnect: aggregateProofTrendReconnect(profiles.map((profile) => profile.reconnect).filter((reconnect) => reconnect !== undefined)),
|
|
6611
6689
|
runtimeChannel: aggregateProofTrendRuntimeChannel(profiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
|
|
6612
6690
|
sessionCount: profiles.reduce((total, profile) => total + (profile.sessionCount ?? 0), 0),
|
|
6613
6691
|
surfaces: [
|
|
@@ -6647,6 +6725,7 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
|
6647
6725
|
var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
|
|
6648
6726
|
const providerCap = options.maxProviderP95Ms ?? 1000;
|
|
6649
6727
|
const liveCap = options.maxLiveP95Ms ?? 800;
|
|
6728
|
+
const reconnectCap = options.maxReconnectP95Ms ?? 1500;
|
|
6650
6729
|
const turnCap = options.maxTurnP95Ms ?? 700;
|
|
6651
6730
|
const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
|
|
6652
6731
|
const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
|
|
@@ -6655,6 +6734,7 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
|
|
|
6655
6734
|
const budgets = {
|
|
6656
6735
|
maxLiveP95Ms: liveCap,
|
|
6657
6736
|
maxProviderP95Ms: providerCap,
|
|
6737
|
+
maxReconnectP95Ms: reconnectCap,
|
|
6658
6738
|
maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
|
|
6659
6739
|
maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
|
|
6660
6740
|
maxRuntimeJitterMs: runtimeJitterCap,
|
|
@@ -6684,8 +6764,10 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
|
|
|
6684
6764
|
label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
|
|
6685
6765
|
maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
|
|
6686
6766
|
maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
|
|
6767
|
+
maxReconnectP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.reconnect?.resumeLatencyP95Ms)),
|
|
6687
6768
|
maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
|
|
6688
6769
|
providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
|
|
6770
|
+
reconnect: aggregateProofTrendReconnect(matchingEvidence.map((evidence) => evidence.reconnect).filter((reconnect) => reconnect !== undefined)),
|
|
6689
6771
|
runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined)),
|
|
6690
6772
|
sessionCount: new Set(matchingEvidence.map((evidence) => evidence.sessionId)).size,
|
|
6691
6773
|
surfaces: [
|
|
@@ -6704,6 +6786,7 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
|
|
|
6704
6786
|
ok: evidence.ok !== false,
|
|
6705
6787
|
providers: evidence.providers,
|
|
6706
6788
|
runtimeChannel: evidence.runtimeChannel,
|
|
6789
|
+
reconnect: evidence.reconnect,
|
|
6707
6790
|
turnLatency: evidence.turnP95Ms === undefined ? undefined : {
|
|
6708
6791
|
p95Ms: evidence.turnP95Ms,
|
|
6709
6792
|
samples: 1,
|
|
@@ -6714,9 +6797,11 @@ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
|
|
|
6714
6797
|
cycles: options.evidence.length,
|
|
6715
6798
|
maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
|
|
6716
6799
|
maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
|
|
6800
|
+
maxReconnectP95Ms: maxNumber(options.evidence.map((evidence) => evidence.reconnect?.resumeLatencyP95Ms)),
|
|
6717
6801
|
maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
|
|
6718
6802
|
profiles,
|
|
6719
6803
|
providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
|
|
6804
|
+
reconnect: aggregateProofTrendReconnect(options.evidence.map((evidence) => evidence.reconnect).filter((reconnect) => reconnect !== undefined)),
|
|
6720
6805
|
runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
|
|
6721
6806
|
};
|
|
6722
6807
|
return buildVoiceProofTrendReport({
|
|
@@ -7535,10 +7620,12 @@ var buildVoiceRealCallProfileHistoryReport = (options = {}) => {
|
|
|
7535
7620
|
failedReports: history.filter((report) => report.ok !== true).length,
|
|
7536
7621
|
maxLiveP95Ms: maxNumber(profileHistory.map(readProofTrendMaxLiveP95)),
|
|
7537
7622
|
maxProviderP95Ms: maxNumber(profileHistory.map(readProofTrendMaxProviderP95)),
|
|
7623
|
+
maxReconnectP95Ms: maxNumber(profileHistory.map(readProofTrendMaxReconnectP95)),
|
|
7538
7624
|
maxTurnP95Ms: maxNumber(profileHistory.map(readProofTrendMaxTurnP95)),
|
|
7539
7625
|
profileCount: profiles.length,
|
|
7540
7626
|
profiles,
|
|
7541
7627
|
providers: readProofTrendProviders(profileHistory),
|
|
7628
|
+
reconnect: aggregateProofTrendReconnect(profileHistory.map((report) => report.summary.reconnect).filter((reconnect) => reconnect !== undefined)),
|
|
7542
7629
|
runtimeChannel: aggregateProofTrendRuntimeChannel(profileHistory.map(readProofTrendRuntimeChannel).filter((channel) => channel !== undefined))
|
|
7543
7630
|
};
|
|
7544
7631
|
const trend = buildVoiceProofTrendReport({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const HTMX_BOOTSTRAP_BUNDLE = "var Ue=(e)=>{if(typeof e!==\"string\")return e;return document.querySelector(e)},Ne=(e,n,t,o)=>{let r=n??e.getAttribute(\"hx-get\")??\"\";if(!r)return\"\";let i=new URL(r,window.location.origin);if(o)i.searchParams.set(t,o);else i.searchParams.delete(t);return`${i.pathname}${i.search}${i.hash}`},de=(e,n)=>{if(typeof window>\"u\"||typeof document>\"u\")return()=>{};let t=Ue(n.element);if(!t)return()=>{};let o=n.eventName??\"voice-refresh\",r=n.sessionQueryParam??\"sessionId\",i=()=>{let l=window,g=Ne(t,n.route,r,e.sessionId);if(g)t.setAttribute(\"hx-get\",g);l.htmx?.process?.(t),l.htmx?.trigger?.(t,o)},c=e.subscribe(i);return i(),()=>{c()}};var He=(e)=>Math.max(-1,Math.min(1,e)),Ge=(e)=>{let n=new Int16Array(e.length);for(let t=0;t<e.length;t+=1){let o=He(e[t]??0);n[t]=o<0?o*32768:o*32767}return new Uint8Array(n.buffer)},Be=(e)=>{let n=e instanceof Uint8Array?e:new Uint8Array(e);if(n.byteLength<2)return 0;let t=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(t.length===0)return 0;let o=0;for(let r of t){let i=r/32768;o+=i*i}return Math.min(1,Math.max(0,Math.sqrt(o/t.length)*5.5))},We=(e,n,t)=>{if(n===t)return e;let o=n/t,r=Math.round(e.length/o),i=new Float32Array(r),c=0,l=0;while(c<i.length){let g=Math.round((c+1)*o),y=0,d=0;for(let h=l;h<g&&h<e.length;h+=1)y+=e[h]??0,d+=1;i[c]=d>0?y/d:0,c+=1,l=g}return i},ge=(e)=>{let n=null,t=null,o=null,r=null;return{start:async()=>{if(typeof navigator>\"u\"||!navigator.mediaDevices?.getUserMedia)throw Error(\"Browser microphone capture requires navigator.mediaDevices.getUserMedia.\");let l=(typeof window<\"u\"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!l)throw Error(\"Browser microphone capture requires AudioContext support.\");r=await navigator.mediaDevices.getUserMedia({audio:{channelCount:e.channelCount??1}}),n=new l,t=n.createMediaStreamSource(r),o=n.createScriptProcessor(4096,1,1),o.onaudioprocess=(g)=>{let y=g.inputBuffer.getChannelData(0),d=We(y,n?.sampleRate??48000,e.sampleRateHz??16000),h=Ge(d);e.onLevel?.(Be(h)),e.onAudio(h)},t.connect(o),o.connect(n.destination)},stop:()=>{o?.disconnect(),t?.disconnect(),r?.getTracks().forEach((l)=>l.stop()),n?.close(),e.onLevel?.(0),n=null,r=null,o=null,t=null}}};var ee=(e)=>{if(typeof e===\"string\"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e===\"object\"){let n=e;for(let t of[\"message\",\"reason\",\"description\"]){let o=n[t];if(typeof o===\"string\"&&o.trim())return o}if(\"error\"in n)return ee(n.error);if(\"cause\"in n)return ee(n.cause);try{return JSON.stringify(e)}catch{}}return\"Unexpected error\"},Ae=(e)=>{switch(e.type){case\"audio\":return{chunk:Uint8Array.from(atob(e.chunkBase64),(n)=>n.charCodeAt(0)),format:e.format,receivedAt:e.receivedAt,turnId:e.turnId,type:\"audio\"};case\"assistant\":return{text:e.text,type:\"assistant\"};case\"complete\":return{sessionId:e.sessionId,type:\"complete\"};case\"connection\":return{reconnect:e.reconnect,type:\"connection\"};case\"call_lifecycle\":return{event:e.event,sessionId:e.sessionId,type:\"call_lifecycle\"};case\"error\":return{message:ee(e.message),type:\"error\"};case\"final\":return{transcript:e.transcript,type:\"final\"};case\"partial\":return{transcript:e.transcript,type:\"partial\"};case\"replay\":return{assistantTexts:e.assistantTexts,call:e.call,partial:e.partial,scenarioId:e.scenarioId,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,status:e.status,turns:e.turns,type:\"replay\"};case\"session\":return{sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,type:\"session\"};case\"turn\":return{turn:e.turn,type:\"turn\"};default:return null}};var H=(e,n,t,o)=>{e.push({code:t,message:o,severity:n})};var $e=(e)=>e.length===0?void 0:e.reduce((n,t)=>n+t,0)/e.length,K=(e)=>e.length===0?void 0:Math.max(...e);var b=(e,n)=>{let t=e[n];return typeof t===\"number\"&&Number.isFinite(t)?t:void 0},Z=(e,n)=>{let t=e[n];return typeof t===\"boolean\"?t:void 0},D=(e,n)=>{let t=e[n];return typeof t===\"string\"?t:void 0},ne=(e)=>String(e.id??D(e,\"ssrc\")??b(e,\"ssrc\")??D(e,\"trackIdentifier\")??D(e,\"mid\")??\"unknown\"),he=(e)=>e===void 0?void 0:e*1000;var ke=(e)=>{let n={};for(let[t,o]of Object.entries(e))if(o===null||typeof o===\"boolean\"||typeof o===\"number\"||typeof o===\"string\")n[t]=o;return n};var ye=(e={})=>{let n=e.stats??[],t=[],o=n.filter((s)=>s.type===\"inbound-rtp\"&&D(s,\"kind\")!==\"video\"),r=n.filter((s)=>s.type===\"outbound-rtp\"&&D(s,\"kind\")!==\"video\"),i=n.filter((s)=>s.type===\"candidate-pair\"),c=n.filter((s)=>(s.type===\"track\"||s.type===\"media-source\")&&D(s,\"kind\")===\"audio\"),l=i.filter((s)=>Z(s,\"selected\")===!0||Z(s,\"nominated\")===!0||D(s,\"state\")===\"succeeded\").length,g=c.filter((s)=>D(s,\"readyState\")!==\"ended\"&&D(s,\"trackState\")!==\"ended\"&&Z(s,\"ended\")!==!0).length,y=c.filter((s)=>D(s,\"readyState\")===\"ended\"||D(s,\"trackState\")===\"ended\"||Z(s,\"ended\")===!0).length,d=o.reduce((s,S)=>s+(b(S,\"packetsReceived\")??0),0),h=r.reduce((s,S)=>s+(b(S,\"packetsSent\")??0),0),a=[...o,...r].reduce((s,S)=>s+Math.max(0,b(S,\"packetsLost\")??0),0),M=d+a,C=M===0?0:a/M,I=o.reduce((s,S)=>s+(b(S,\"bytesReceived\")??0),0),w=r.reduce((s,S)=>s+(b(S,\"bytesSent\")??0),0),R=K(i.map((s)=>he(b(s,\"currentRoundTripTime\")??b(s,\"roundTripTime\"))).filter((s)=>s!==void 0)),u=K([...o,...r].map((s)=>he(b(s,\"jitter\"))).filter((s)=>s!==void 0)),O=K(o.map((s)=>{let S=b(s,\"jitterBufferDelay\"),L=b(s,\"jitterBufferEmittedCount\");return S!==void 0&&L!==void 0&&L>0?S/L*1000:void 0}).filter((s)=>s!==void 0)),U=c.map((s)=>b(s,\"audioLevel\")).filter((s)=>s!==void 0);if(e.requireConnectedCandidatePair&&i.length>0&&l===0)H(t,\"error\",\"media.webrtc_candidate_pair_missing\",\"No active WebRTC candidate pair was observed.\");if(e.requireLiveAudioTrack&&g===0)H(t,\"error\",\"media.webrtc_audio_track_missing\",\"No live WebRTC audio track was observed.\");if(e.maxPacketLossRatio!==void 0&&C>e.maxPacketLossRatio)H(t,\"warning\",\"media.webrtc_packet_loss\",`Observed WebRTC packet loss ratio ${String(C)} above ${String(e.maxPacketLossRatio)}.`);if(e.maxRoundTripTimeMs!==void 0&&R!==void 0&&R>e.maxRoundTripTimeMs)H(t,\"warning\",\"media.webrtc_round_trip_time\",`Observed WebRTC RTT ${String(R)}ms above ${String(e.maxRoundTripTimeMs)}ms.`);if(e.maxJitterMs!==void 0&&u!==void 0&&u>e.maxJitterMs)H(t,\"warning\",\"media.webrtc_jitter\",`Observed WebRTC jitter ${String(u)}ms above ${String(e.maxJitterMs)}ms.`);return{activeCandidatePairs:l,audioLevelAverage:$e(U),bytesReceived:I,bytesSent:w,checkedAt:Date.now(),endedAudioTracks:y,inboundPackets:d,issues:t,jitterBufferDelayMs:O,jitterMs:u,liveAudioTracks:g,outboundPackets:h,packetLossRatio:C,packetsLost:a,roundTripTimeMs:R,status:t.some((s)=>s.severity===\"error\")?\"fail\":t.length>0?\"warn\":\"pass\",totalStats:n.length}},Ce=async(e)=>{return[...(await e.peerConnection.getStats(e.selector??null)).values()].map(ke)};var fe=(e={})=>{let n=e.stats??[],t=e.previousStats??[],o=[],r=new Map(t.map((a)=>[ne(a),a])),c=n.filter((a)=>(a.type===\"inbound-rtp\"||a.type===\"outbound-rtp\")&&D(a,\"kind\")!==\"video\"&&D(a,\"mediaType\")!==\"video\").map((a)=>{let M=a.type===\"outbound-rtp\"?\"outbound\":\"inbound\",C=M===\"outbound\"?\"packetsSent\":\"packetsReceived\",I=M===\"outbound\"?\"bytesSent\":\"bytesReceived\",w=r.get(ne(a)),R=b(a,C),u=w?b(w,C):void 0,O=b(a,I),U=w?b(w,I):void 0,s=a.timestamp!==void 0&&w?.timestamp!==void 0?a.timestamp-w.timestamp:void 0;return{bytesDelta:O!==void 0&&U!==void 0?O-U:void 0,currentPackets:R,direction:M,id:ne(a),packetDelta:R!==void 0&&u!==void 0?R-u:void 0,previousPackets:u,timeDeltaMs:s}}),l=c.filter((a)=>a.direction===\"inbound\"),g=c.filter((a)=>a.direction===\"outbound\"),y=K(c.map((a)=>a.timeDeltaMs).filter((a)=>a!==void 0)),d=l.filter((a)=>e.maxInboundPacketStallMs!==void 0&&a.timeDeltaMs!==void 0&&a.timeDeltaMs>=e.maxInboundPacketStallMs&&a.packetDelta!==void 0&&a.packetDelta<=0).length,h=g.filter((a)=>e.maxOutboundPacketStallMs!==void 0&&a.timeDeltaMs!==void 0&&a.timeDeltaMs>=e.maxOutboundPacketStallMs&&a.packetDelta!==void 0&&a.packetDelta<=0).length;if(e.requireInboundAudio&&l.length===0)H(o,\"error\",\"media.webrtc_inbound_audio_missing\",\"No inbound WebRTC audio RTP stream was observed.\");if(e.requireOutboundAudio&&g.length===0)H(o,\"error\",\"media.webrtc_outbound_audio_missing\",\"No outbound WebRTC audio RTP stream was observed.\");if(e.maxGapMs!==void 0&&y!==void 0&&y>e.maxGapMs)H(o,\"warning\",\"media.webrtc_stream_gap\",`Observed WebRTC stream sample gap ${String(y)}ms above ${String(e.maxGapMs)}ms.`);if(d>0)H(o,\"error\",\"media.webrtc_inbound_stalled\",`${String(d)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(h>0)H(o,\"error\",\"media.webrtc_outbound_stalled\",`${String(h)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:l.length,issues:o,maxObservedGapMs:y,outboundAudioStreams:g.length,stalledInboundStreams:d,stalledOutboundStreams:h,status:o.some((a)=>a.severity===\"error\")?\"fail\":o.length>0?\"warn\":\"pass\",streams:c,totalStats:n.length}};var qe=\"/api/voice/browser-media\",Xe=5000,ze=async(e)=>e.peerConnection??await e.getPeerConnection?.()??null,Ye=async(e,n)=>{let t=n.fetch??globalThis.fetch;if(!t)return;await t(n.path??qe,{body:JSON.stringify(e),headers:{\"Content-Type\":\"application/json\"},keepalive:!0,method:\"POST\"})},Te=(e)=>{let n=null,t=[],o=async()=>{let c=await ze(e);if(!c)return;let l=await Ce({peerConnection:c}),g=ye({...e,stats:l}),y=e.continuity===!1?void 0:fe({...e.continuity,previousStats:t,stats:l}),d={at:Date.now(),continuity:y,report:g,scenarioId:e.getScenarioId?.()??null,sessionId:e.getSessionId?.()??null};return t=l,e.onReport?.(d),await Ye(d,e),d},r=()=>{o().catch((c)=>{e.onError?.(c)})},i=()=>{if(n)clearInterval(n),n=null};return{close:i,reportOnce:o,start:()=>{if(n)return;r(),n=setInterval(r,e.intervalMs??Xe)},stop:i}};var B=()=>{},Je=()=>B,Qe={callControl:B,close:B,endTurn:B,getReadyState:()=>3,getScenarioId:()=>\"\",getSessionId:()=>\"\",send:B,sendAudio:B,simulateDisconnect:B,start:()=>{},subscribe:Je},Ze=()=>crypto.randomUUID(),Ke=(e,n,t)=>{let{hostname:o,port:r,protocol:i}=window.location,c=i===\"https:\"?\"wss:\":\"ws:\",l=r?`:${r}`:\"\",g=new URL(`${c}//${o}${l}${e}`);if(g.searchParams.set(\"sessionId\",n),t)g.searchParams.set(\"scenarioId\",t);return g.toString()},me=(e)=>{if(!e||typeof e!==\"object\"||!(\"type\"in e))return!1;switch(e.type){case\"audio\":case\"assistant\":case\"call_lifecycle\":case\"complete\":case\"connection\":case\"error\":case\"final\":case\"partial\":case\"pong\":case\"replay\":case\"session\":case\"turn\":return!0;default:return!1}},je=(e)=>{if(typeof e.data!==\"string\")return null;try{let n=JSON.parse(e.data);return me(n)?n:null}catch{return null}},Se=(e,n={})=>{if(typeof window>\"u\")return Qe;let t=new Set,o=n.reconnect!==!1,r=n.maxReconnectAttempts??10,i=n.pingInterval??30000,c={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Ze(),ws:null},l=(s)=>{t.forEach((S)=>S(s))},g=()=>{if(c.pingInterval)clearInterval(c.pingInterval),c.pingInterval=null;if(c.reconnectTimeout)clearTimeout(c.reconnectTimeout),c.reconnectTimeout=null},y=()=>{if(c.ws?.readyState!==1)return;while(c.pendingMessages.length>0){let s=c.pendingMessages.shift();if(s!==void 0)c.ws.send(s)}},d=()=>{let s=Date.now()+500;c.reconnectAttempts+=1,l({reconnect:{attempts:c.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:r,nextAttemptAt:s,status:\"reconnecting\"},type:\"connection\"}),c.reconnectTimeout=setTimeout(()=>{if(c.reconnectAttempts>r){l({reconnect:{attempts:c.reconnectAttempts,maxAttempts:r,status:\"exhausted\"},type:\"connection\"});return}h()},500)},h=()=>{let s=new WebSocket(Ke(e,c.sessionId,c.scenarioId));s.binaryType=\"arraybuffer\",s.onopen=()=>{let S=c.reconnectAttempts>0;if(c.isConnected=!0,y(),S)l({reconnect:{attempts:c.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:r,status:\"resumed\"},type:\"connection\"}),c.reconnectAttempts=0;t.forEach((L)=>L({scenarioId:c.scenarioId??void 0,sessionId:c.sessionId,status:\"active\",type:\"session\"})),c.pingInterval=setInterval(()=>{if(s.readyState===1)s.send(JSON.stringify({type:\"ping\"}))},i)},s.onmessage=(S)=>{let L=je(S);if(!L)return;if(L.type===\"session\")c.sessionId=L.sessionId,c.scenarioId=L.scenarioId??c.scenarioId;t.forEach((X)=>X(L))},s.onclose=(S)=>{if(c.isConnected=!1,g(),o&&S.code!==1000&&c.reconnectAttempts<r)d();else if(o&&S.code!==1000)l({reconnect:{attempts:c.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:r,status:\"exhausted\"},type:\"connection\"})},c.ws=s},a=(s)=>{if(c.ws?.readyState===1){c.ws.send(s);return}c.pendingMessages.push(s)},M=(s)=>{a(JSON.stringify(s))},C=(s={})=>{if(s.sessionId)c.sessionId=s.sessionId;if(s.scenarioId)c.scenarioId=s.scenarioId;M({type:\"start\",sessionId:c.sessionId,scenarioId:c.scenarioId??void 0})},I=(s)=>{a(s)},w=()=>{M({type:\"end_turn\"})},R=(s)=>{M({...s,type:\"call_control\"})},u=()=>{if(g(),c.ws)c.ws.close(1000),c.ws=null;c.isConnected=!1,t.clear()},O=()=>{if(c.ws?.readyState===1)c.ws.close(4000,\"absolutejs-voice-reconnect-proof\")},U=(s)=>{return t.add(s),()=>{t.delete(s)}};return h(),{callControl:R,close:u,endTurn:w,getReadyState:()=>c.ws?.readyState??3,getScenarioId:()=>c.scenarioId??\"\",getSessionId:()=>c.sessionId,send:M,sendAudio:I,simulateDisconnect:O,start:C,subscribe:U}};var ve=()=>({attempts:0,maxAttempts:0,status:\"idle\"}),Fe=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,sessionMetadata:null,scenarioId:null,partial:\"\",reconnect:ve(),sessionId:null,status:\"idle\",turns:[]}),Me=()=>{let e=Fe(),n=new Set,t=()=>{n.forEach((r)=>r())};return{dispatch:(r)=>{switch(r.type){case\"audio\":e={...e,assistantAudio:[...e.assistantAudio,{chunk:r.chunk,format:r.format,receivedAt:r.receivedAt,turnId:r.turnId}]};break;case\"assistant\":e={...e,assistantTexts:[...e.assistantTexts,r.text]};break;case\"complete\":e={...e,sessionId:r.sessionId,status:\"completed\"};break;case\"call_lifecycle\":e={...e,call:{...e.call,disposition:r.event.type===\"end\"?r.event.disposition:e.call?.disposition,endedAt:r.event.type===\"end\"?r.event.at:e.call?.endedAt,events:[...e.call?.events??[],r.event],lastEventAt:r.event.at,startedAt:e.call?.startedAt??r.event.at},sessionId:r.sessionId};break;case\"connected\":e={...e,isConnected:!0,reconnect:e.reconnect.status===\"reconnecting\"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:\"resumed\"}:e.reconnect};break;case\"connection\":e={...e,reconnect:r.reconnect};break;case\"disconnected\":e={...e,isConnected:!1};break;case\"error\":e={...e,error:r.message};break;case\"final\":e={...e,partial:r.transcript.text,turns:e.turns.map((i)=>i)};break;case\"partial\":e={...e,partial:r.transcript.text};break;case\"replay\":e={...e,assistantTexts:[...r.assistantTexts],call:r.call??null,error:null,isConnected:r.status===\"active\",partial:r.partial,reconnect:e.reconnect.status===\"reconnecting\"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:\"resumed\"}:e.reconnect,scenarioId:r.scenarioId??e.scenarioId,sessionId:r.sessionId,sessionMetadata:r.sessionMetadata??e.sessionMetadata,status:r.status,turns:[...r.turns]};break;case\"session\":e={...e,error:null,scenarioId:r.scenarioId??e.scenarioId,isConnected:r.status===\"active\",sessionId:r.sessionId,sessionMetadata:r.sessionMetadata??e.sessionMetadata,status:r.status};break;case\"turn\":e={...e,partial:\"\",turns:[...e.turns,r.turn]};break}t()},getServerSnapshot:()=>e,getSnapshot:()=>e,subscribe:(r)=>{return n.add(r),()=>{n.delete(r)}}}};var Ie=(e,n={})=>{let t=Se(e,n),o=Me(),r=n.browserMedia&&typeof window<\"u\"?Te({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??t.getScenarioId():t.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??t.getSessionId():t.getSessionId()}):null,i=new Set,c=(d)=>Promise.resolve().then(()=>{if(!d?.sessionId&&!d?.scenarioId)return;t.start(d),r?.start()}),l=()=>{i.forEach((d)=>d())},g=()=>{if(!n.reconnectReportPath||typeof fetch>\"u\")return;let d=o.getSnapshot(),h=JSON.stringify({at:Date.now(),reconnect:d.reconnect,scenarioId:d.scenarioId,sessionId:t.getSessionId(),turnIds:d.turns.map((a)=>a.id)});fetch(n.reconnectReportPath,{body:h,headers:{\"Content-Type\":\"application/json\"},keepalive:!0,method:\"POST\"}).catch(()=>{})},y=t.subscribe((d)=>{let h=Ae(d);if(h){if(o.dispatch(h),d.type===\"connection\")g();l()}});return{callControl(d){t.callControl(d)},close(){y(),r?.close(),t.close(),o.dispatch({type:\"disconnected\"}),l()},endTurn(){t.endTurn()},get error(){return o.getSnapshot().error},getServerSnapshot(){return o.getServerSnapshot()},getSnapshot(){return o.getSnapshot()},get isConnected(){return o.getSnapshot().isConnected},get scenarioId(){return o.getSnapshot().scenarioId},get sessionMetadata(){return o.getSnapshot().sessionMetadata},start:c,get partial(){return o.getSnapshot().partial},get reconnect(){return o.getSnapshot().reconnect},get sessionId(){return t.getSessionId()},get status(){return o.getSnapshot().status},get turns(){return o.getSnapshot().turns},get assistantTexts(){return o.getSnapshot().assistantTexts},get assistantAudio(){return o.getSnapshot().assistantAudio},get call(){return o.getSnapshot().call},sendAudio(d){t.sendAudio(d)},simulateDisconnect(){t.simulateDisconnect()},subscribe(d){return i.add(d),()=>{i.delete(d)}}}};var Ve=(e)=>{if(!e||e.enabled===!1)return;return{enabled:!0,maxGain:e.maxGain??3,noiseGateAttenuation:e.noiseGateAttenuation??0.15,noiseGateThreshold:e.noiseGateThreshold??0.006,targetLevel:e.targetLevel??0.08}};var pe={balanced:{qualityProfile:\"general\",silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:\"general\",silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},\"long-form\":{qualityProfile:\"general\",silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},en={general:{},\"accent-heavy\":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},\"noisy-room\":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},\"short-command\":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var we=(e)=>{let n=e?.profile??\"fast\",t=e?.qualityProfile??\"general\",o=pe[n],r=en[t];return{profile:n,qualityProfile:t,silenceMs:e?.silenceMs??r.silenceMs??o.silenceMs,speechThreshold:e?.speechThreshold??r.speechThreshold??o.speechThreshold,transcriptStabilityMs:e?.transcriptStabilityMs??r.transcriptStabilityMs??o.transcriptStabilityMs}};var nn={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"short-command\",profile:\"balanced\"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"general\",profile:\"fast\"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"accent-heavy\",profile:\"long-form\"}},\"guided-intake\":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:\"turn-scoped\",turnDetection:{qualityProfile:\"accent-heavy\",profile:\"long-form\"}},\"noisy-room\":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},\"pstn-balanced\":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},\"pstn-fast\":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\"}}},Le=(e=\"default\")=>{let n=nn[e];return{audioConditioning:Ve(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:e,sttLifecycle:n.sttLifecycle??\"continuous\",turnDetection:we(n.turnDetection)}};var on=(e)=>({assistantAudio:[...e.assistantAudio],assistantTexts:[...e.assistantTexts],call:e.call,error:e.error,isConnected:e.isConnected,isRecording:!1,partial:e.partial,reconnect:e.reconnect,recordingError:null,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,turns:[...e.turns]}),m=(e,n={})=>{let t=Le(n.preset),o=Ie(e,{...t.connection,...n.connection}),r=null,i=on(o),c=new Set,l=()=>{for(let C of c)C()},g=()=>{if(i={...i,assistantAudio:[...o.assistantAudio],assistantTexts:[...o.assistantTexts],call:o.call,error:o.error,isConnected:o.isConnected,partial:o.partial,reconnect:o.reconnect,sessionId:o.sessionId,sessionMetadata:o.sessionMetadata,scenarioId:o.scenarioId,status:o.status,turns:[...o.turns]},n.autoStopOnComplete!==!1&&i.status===\"completed\"&&i.isRecording)r?.stop(),r=null,i={...i,isRecording:!1};l()},y=o.subscribe(g);g();let d=()=>{if(r)return r;return r=ge({channelCount:n.capture?.channelCount??t.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(C)=>{if(n.capture?.onAudio){n.capture.onAudio(C,o.sendAudio);return}o.sendAudio(C)},sampleRateHz:n.capture?.sampleRateHz??t.capture.sampleRateHz}),r},h=()=>{r?.stop(),r=null,i={...i,isRecording:!1},l()},a=async()=>{if(i.isRecording)return;try{i={...i,recordingError:null},l(),await d().start(),i={...i,isRecording:!0},l()}catch(C){throw r=null,i={...i,isRecording:!1,recordingError:C instanceof Error?C.message:String(C)},l(),C}};return{bindHTMX(C){return de(o,C)},callControl:(C)=>o.callControl(C),close:()=>{y(),h(),o.close()},endTurn:()=>o.endTurn(),get error(){return i.error},getServerSnapshot:()=>i,getSnapshot:()=>i,get isConnected(){return i.isConnected},get isRecording(){return i.isRecording},get partial(){return i.partial},get recordingError(){return i.recordingError},get reconnect(){return i.reconnect},sendAudio:(C)=>o.sendAudio(C),simulateDisconnect:()=>o.simulateDisconnect(),get sessionId(){return i.sessionId},get sessionMetadata(){return i.sessionMetadata},get scenarioId(){return i.scenarioId},startRecording:a,get status(){return i.status},stopRecording:h,subscribe:(C)=>{return c.add(C),()=>{c.delete(C)}},toggleRecording:async()=>{if(i.isRecording){h();return}await a()},get turns(){return i.turns},get assistantTexts(){return i.assistantTexts},get assistantAudio(){return i.assistantAudio},get call(){return i.call}}};var tn=()=>({activeSourceCount:0,error:null,isActive:!1,isPlaying:!1,lastInterruptLatencyMs:void 0,lastPlaybackStopLatencyMs:void 0,processedChunkCount:0,queuedChunkCount:0}),cn=()=>{if(typeof window>\"u\")return typeof AudioContext>\"u\"?void 0:AudioContext;return window.AudioContext??window.webkitAudioContext},rn=(e,n)=>{let t=n.format;if(t.container!==\"raw\"||t.encoding!==\"pcm_s16le\")throw Error(`Unsupported assistant audio format: ${t.container}/${t.encoding}`);let o=n.chunk,r=Math.max(1,t.channels),i=Math.floor(o.byteLength/2),c=Math.max(1,Math.floor(i/r)),l=e.createBuffer(r,c,t.sampleRateHz),g=new DataView(o.buffer,o.byteOffset,o.byteLength);for(let y=0;y<r;y+=1){let d=l.getChannelData(y);for(let h=0;h<c;h+=1){let M=(h*r+y)*2;if(M+1>=o.byteLength){d[h]=0;continue}d[h]=g.getInt16(M,!0)/32768}}return l},j=(e,n={})=>{let t=new Set,o=new Set,r=(n.lookaheadMs??15)/1000,i=tn(),c=null,l=null,g=0,y=Promise.resolve(),d=null,h=null,a=null,M=null,C=()=>{for(let A of t)A()},I=(A)=>{i={...i,...A},C()},w=()=>{if(i.error!==null)I({error:null})},R=()=>{if(M!==null)clearTimeout(M),M=null},u=(A)=>{R(),d=null,I({activeSourceCount:o.size,isPlaying:!1,lastInterruptLatencyMs:A,lastPlaybackStopLatencyMs:i.lastPlaybackStopLatencyMs??A}),a?.(),a=null,h=null},O=(A)=>{if(!A)return 0;return Math.max(0,((A.baseLatency??0)+(A.outputLatency??0))*1000)},U=(A)=>{if(!l)return;let f=1;if(l.gain.setValueAtTime){l.gain.setValueAtTime(f,A?.currentTime??0);return}l.gain.value=f},s=(A)=>{if(!l)return;let f=0;if(l.gain.setValueAtTime){l.gain.setValueAtTime(f,A?.currentTime??0);return}l.gain.value=f},S=()=>{if(d===null||o.size>0)return;u(Date.now()-d)},L=async()=>{if(c)return c;if(n.createAudioContext)c=n.createAudioContext();else{let A=cn();if(!A)throw Error(\"Assistant audio playback requires AudioContext support.\");c=new A}if(c.createGain)l=c.createGain(),l.connect?.(c.destination);return g=c.currentTime,c},X=async(A)=>{let f=await L(),E=rn(f,A),V=f.createBufferSource();V.buffer=E,V.connect(l??f.destination),V.onended=()=>{o.delete(V),V.disconnect?.(),I({activeSourceCount:o.size,isPlaying:o.size>0&&i.isActive}),S()};let Y=Math.max(f.currentTime+r,g);g=Y+E.duration,o.add(V),I({activeSourceCount:o.size,isPlaying:!0}),V.start(Y)},_=(A)=>{for(let f of[...o])f.stop?.();if(g=c?c.currentTime:0,A?.forceClear){for(let f of o)f.disconnect?.();o.clear(),S()}},W=async()=>{if(!i.isActive)return;let A=e.assistantAudio.slice(i.processedChunkCount);if(A.length===0)return;try{w();for(let f of A)await X(f);I({processedChunkCount:e.assistantAudio.length,queuedChunkCount:i.queuedChunkCount+A.length})}catch(f){I({error:f instanceof Error?f.message:String(f)})}},P=()=>{return y=y.then(()=>W(),()=>W()),y},$=e.subscribe(()=>{if(n.autoStart&&!i.isActive&&e.assistantAudio.length>0){N.start();return}if(i.isActive)P()}),N={close:async()=>{if($(),_({forceClear:!0}),R(),a?.(),a=null,h=null,d=null,c&&c.state!==\"closed\")await c.close();c=null,l?.disconnect?.(),l=null,g=0,I({activeSourceCount:0,isActive:!1,isPlaying:!1})},get activeSourceCount(){return i.activeSourceCount},get error(){return i.error},getSnapshot:()=>i,get isActive(){return i.isActive},get isPlaying(){return i.isPlaying},interrupt:async()=>{let A=Date.now(),f=await L();d=A,s(f);let E=Date.now()-A+O(f);if(I({isActive:!1,isPlaying:o.size>0,lastPlaybackStopLatencyMs:E}),o.size===0){u(E);return}if(!h)h=new Promise((V)=>{a=V});R(),M=setTimeout(()=>{for(let V of o)V.disconnect?.();o.clear(),u(Date.now()-A)},250),_(),await h},get lastInterruptLatencyMs(){return i.lastInterruptLatencyMs},get lastPlaybackStopLatencyMs(){return i.lastPlaybackStopLatencyMs},pause:async()=>{if(!c){I({activeSourceCount:0,isActive:!1,isPlaying:!1});return}await c.suspend(),I({activeSourceCount:o.size,isActive:!1,isPlaying:!1})},get processedChunkCount(){return i.processedChunkCount},get queuedChunkCount(){return i.queuedChunkCount},start:async()=>{try{w();let A=await L();if(U(A),A.state===\"suspended\")await A.resume();I({activeSourceCount:o.size,isActive:!0,isPlaying:A.state===\"running\"}),await P()}catch(A){throw I({error:A instanceof Error?A.message:String(A),isActive:!1,isPlaying:!1}),A}},subscribe:(A)=>{return t.add(A),()=>{t.delete(A)}}};return N};var sn=()=>`barge-in:${Date.now()}:${crypto.randomUUID?.()??Math.random().toString(36).slice(2)}`,ln=(e,n)=>{let t=e.filter((c)=>c.status===\"stopped\"),o=t.map((c)=>c.latencyMs).filter((c)=>typeof c===\"number\"),r=t.filter((c)=>typeof c.latencyMs===\"number\"&&c.latencyMs>n).length,i=t.length-r;return{averageLatencyMs:o.length>0?Math.round(o.reduce((c,l)=>c+l,0)/o.length):void 0,events:[...e],failed:r,lastEvent:e.at(-1),passed:i,status:e.length===0?\"empty\":r>0?\"fail\":t.length===0?\"warn\":\"pass\",thresholdMs:n,total:t.length}},ue=(e={})=>{let n=new Set,t=e.thresholdMs??250,o=e.fetch??globalThis.fetch,r=[],i=()=>{for(let g of n)g()},c=(g)=>{if(!e.path||typeof o!==\"function\")return;o(e.path,{body:JSON.stringify(g),headers:{\"Content-Type\":\"application/json\"},method:\"POST\"}).catch(()=>{})},l=(g,y)=>{let d={at:Date.now(),id:sn(),latencyMs:y.latencyMs,playbackStopLatencyMs:y.playbackStopLatencyMs,reason:y.reason,sessionId:y.sessionId,status:g,thresholdMs:t};return r.push(d),c(d),i(),d};return{getSnapshot:()=>ln(r,t),recordRequested:(g)=>l(\"requested\",g),recordSkipped:(g)=>l(\"skipped\",g),recordStopped:(g)=>l(\"stopped\",g),subscribe:(g)=>{return n.add(g),()=>{n.delete(g)}}}};var an=0.08,dn=(e,n={})=>(n.enabled??!0)&&e>=(n.interruptThreshold??an),oe=(e,n,t={})=>{let o=e.partial,r=(c)=>{if(!n.isPlaying||t.enabled===!1){t.monitor?.recordSkipped({reason:c,sessionId:e.sessionId});return}t.monitor?.recordRequested({reason:c,sessionId:e.sessionId}),n.interrupt().then(()=>{t.monitor?.recordStopped({latencyMs:n.lastInterruptLatencyMs,playbackStopLatencyMs:n.lastPlaybackStopLatencyMs,reason:c,sessionId:e.sessionId})})},i=e.subscribe(()=>{if(t.interruptOnPartial===!1){o=e.partial;return}if(!o&&e.partial)r(\"partial-transcript\");o=e.partial});return{close:()=>{i()},handleLevel:(c)=>{if(dn(c,t))r(\"input-level\")},sendAudio:(c)=>{r(\"manual-audio\"),e.sendAudio(c)}}};var se=48,gn=320,An=88,hn=\"Guided test\",yn=\"General recording\",Cn=\"Pick a scenario to begin the demo.\",fn=\"I can walk you through a short guided voice test.\",Tn=\"I can capture one freeform recording and confirm that it landed.\",Sn=\"Choose a scenario to begin. Guided test asks follow-up prompts. General recording just captures what you say.\",Mn=\"Click Start general recording to capture one freeform answer.\",_e=\"Speak freely. When you pause, the recording will be captured.\",re=\"Recording saved. Start again if you want another capture.\",Ee=\"Guided test complete. Review the saved summary below.\",Pe=\"All prompts are covered. You can stop the microphone or keep speaking for extra detail.\",In=\"Ready. Start guided test or general recording to begin.\",Vn=\"Live. Answer the prompt, then click Stop microphone when finished.\",Re=[\"Start with a quick introduction about who you are.\",\"Now describe what you are trying to do or test.\",\"Finish with any detail that feels blocked, risky, or unclear.\"],De=(e,n,t)=>Math.min(t,Math.max(n,e)),q=(e)=>e.replaceAll(\"&\",\"&\").replaceAll(\"<\",\"<\").replaceAll(\">\",\">\").replaceAll('\"',\""\").replaceAll(\"'\",\"'\"),te=(e,n)=>{let t=e[n];if(typeof t===\"string\"&&t.trim())return t;return null},ie=(e)=>{if(typeof e===\"string\"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e===\"object\"){let n=e,t=te(n,\"message\")??te(n,\"reason\")??te(n,\"description\");if(t)return t;if(\"error\"in n)return ie(n.error);if(\"cause\"in n)return ie(n.cause);try{return JSON.stringify(e)}catch{}}return\"Unexpected error\"},wn=(e)=>{let n=[e.status];if(e.attempts>0||e.maxAttempts>0)n.push(`${e.attempts}/${e.maxAttempts} attempts`);if(e.nextAttemptAt){let t=Math.max(0,e.nextAttemptAt-Date.now());n.push(`retry in ${Math.ceil(t/100)/10}s`)}return n.join(\" \u00B7 \")},v=(e=se)=>Array.from({length:e},()=>0),be=(e,n,t=se)=>{let o=e.slice(-(t-1));o.push(De(n,0,1));while(o.length<t)o.unshift(0);return o},Ln=(e,n=gn,t=An)=>{let o=e.length>1?e:v(se),r=n/(o.length-1),i=t/2,c=t*0.34;if(Math.max(...o,0)<=0.015)return`M 0 ${i} L ${n} ${i}`;let g=o.map((d,h)=>{let a=h*0.76,M=Math.sin(a)*0.78+Math.sin(a*0.41)*0.22,C=d*c,I=r*h,w=De(i+M*C,8,t-8);return{x:I,y:w}});if(g.length===0)return`M 0 ${i} L ${n} ${i}`;let y=`M ${g[0]?.x??0} ${g[0]?.y??i}`;for(let d=1;d<g.length;d+=1){let h=g[d-1],a=g[d];if(!h||!a)continue;let M=(h.x+a.x)/2;y+=` Q ${M} ${h.y} ${a.x} ${a.y}`}return y},un=(e)=>{if(!e)return Re;try{let n=JSON.parse(e);if(Array.isArray(n)){let t=n.filter((o)=>typeof o===\"string\").map((o)=>o.trim()).filter(Boolean);if(t.length>0)return t}}catch{}return Re},ce=(e)=>{if(!e)return;let n=Number(e);return Number.isFinite(n)?n:void 0},Rn=(e,n,t)=>{let o=n?document.querySelector(n):e.querySelector(n??\"\");return o instanceof t?o:null},x=(e,n,t,o)=>{let r=n?document.querySelector(n):null;if(r instanceof t)return r;let i=e.querySelector(`#${o}`);if(i instanceof t)return i;throw Error(`Voice HTMX bootstrap could not find the required element \"${o}\".`)},bn=(e)=>{if(!e.mode)return Cn;if(!e.hasStarted)return e.mode===\"guided\"?fn:Tn;if(e.status===\"completed\")return e.mode===\"guided\"?Ee:re;if(e.mode===\"general\")return _e;return e.guidedPrompts[e.turnCount]??Pe},_n=(e)=>{if(!e.mode)return Sn;if(e.status===\"completed\")return e.mode===\"guided\"?Ee:re;if(!e.hasStarted)return e.mode===\"guided\"?`Click Start guided test to begin. First prompt: ${e.guidedPrompts[0]??\"Answer the first prompt.\"}`:Mn;if(e.mode===\"general\")return e.turnCount===0?_e:re;return e.guidedPrompts[e.turnCount]??Pe},En=(e)=>{let n=e.dataset.voiceGuidedPath,t=e.dataset.voiceGeneralPath;if(!n||!t)throw Error(\"Voice HTMX bootstrap requires data-voice-guided-path and data-voice-general-path.\");let o=un(e.dataset.voiceGuidedPrompts),r=e.dataset.voiceGuidedLabel??hn,i=e.dataset.voiceGeneralLabel??yn,c=e.dataset.voiceReconnectReportPath,l=e.dataset.voiceBargeInPath,g=l?ue({path:l,thresholdMs:ce(e.dataset.voiceBargeInThresholdMs)}):null,y=ce(e.dataset.voiceBargeInRecentWindowMs)??4000,d=ce(e.dataset.voiceBargeInSpeechThreshold)??0.04,h=x(document,e.dataset.voiceSync,HTMLElement,\"voice-htmx-sync\"),a=x(e,e.dataset.voiceConnection,HTMLElement,\"metric-connection\"),M=x(e,e.dataset.voiceError,HTMLElement,\"status-error\"),C=x(e,e.dataset.voiceMicrophone,HTMLElement,\"status-mic\"),I=x(e,e.dataset.voicePrompt,HTMLElement,\"status-prompt\"),w=Rn(e,e.dataset.voiceReconnect,HTMLElement),R=x(e,e.dataset.voiceChat,HTMLElement,\"chat-list\"),u=x(e,e.dataset.voiceStartGuided,HTMLButtonElement,\"start-guided\"),O=x(e,e.dataset.voiceStartGeneral,HTMLButtonElement,\"start-general\"),U=x(e,e.dataset.voiceStop,HTMLButtonElement,\"stop-mic\"),s=x(e,e.dataset.voiceMonitor,HTMLElement,\"voice-monitor\"),S=x(e,e.dataset.voiceMonitorCopy,HTMLElement,\"voice-monitor-copy\"),L=x(e,e.dataset.voiceWaveGlow,SVGPathElement,\"voice-wave-glow\"),X=x(e,e.dataset.voiceWavePath,SVGPathElement,\"voice-wave-path\"),_=null,W={general:!1,guided:!1},P=!1,$=null,N=v(),A=null,f=null,E=m(n,{capture:{onAudio:(T,G)=>{if(A){A.sendAudio(T);return}G(T)},onLevel:(T)=>{A?.handleLevel(T),N=be(N,T),F()}},connection:{reconnectReportPath:c},preset:\"guided-intake\"}),V=m(t,{capture:{onAudio:(T,G)=>{if(f){f.sendAudio(T);return}G(T)},onLevel:(T)=>{f?.handleLevel(T),N=be(N,T),F()}},connection:{reconnectReportPath:c},preset:\"dictation\"}),Y=E.bindHTMX({element:h}),xe=V.bindHTMX({element:h}),J=j(E),Q=j(V);A=oe(E,J,{interruptThreshold:d,monitor:g??void 0}),f=oe(V,Q,{interruptThreshold:d,monitor:g??void 0});let z=()=>_===\"general\"?V:E,Dn=()=>_===\"general\"?Q:J,F=()=>{let T=Ln(N);L.setAttribute(\"d\",T),X.setAttribute(\"d\",T),S.innerHTML=`<span class=\"voice-live-dot\"></span>${P?\"Microphone live\":\"Microphone idle\"}`,S.classList.toggle(\"is-live\",P),s.classList.toggle(\"is-live\",P)},k=()=>{let T=z(),G=(_?W[_]:!1)||T.turns.length>0,ae=T.status;if(a.textContent=T.isConnected?\"Connected\":\"Waiting\",M.textContent=$||T.error||\"None\",w)w.textContent=wn(T.reconnect);C.textContent=P?Vn:In,I.textContent=_n({guidedPrompts:o,hasStarted:G,mode:_,status:ae,turnCount:T.turns.length}),u.hidden=P,O.hidden=P,U.hidden=!P,R.innerHTML=`<article class=\"voice-chat-message assistant\">\n <div class=\"voice-chat-role\">${q(_===\"general\"?i:_===\"guided\"?r:\"Voice demo\")}</div>\n <p class=\"voice-turn-text\">${q(bn({generalLabel:i,guidedLabel:r,guidedPrompts:o,hasStarted:G,mode:_,status:ae,turnCount:T.turns.length}))}</p>\n</article>${T.turns.map((p)=>`<div class=\"voice-chat-stack\">\n <article class=\"voice-chat-message user\">\n <div class=\"voice-chat-role\">You</div>\n <p class=\"voice-turn-text\">${q(p.text)}</p>\n </article>\n ${p.assistantText?`<article class=\"voice-chat-message assistant\">\n <div class=\"voice-chat-role\">${q(_===\"general\"?i:_===\"guided\"?r:\"Guide\")}</div>\n <p class=\"voice-turn-text\">${q(p.assistantText)}</p>\n </article>`:\"\"}\n</div>`).join(\"\")}${T.partial?`<article class=\"voice-chat-message user pending\">\n <div class=\"voice-chat-role\">Speaking</div>\n <p class=\"voice-turn-text\">${q(T.partial)}</p>\n</article>`:\"\"}`,F()},Oe=()=>{z().stopRecording(),P=!1,$=null,N=v(),k()},le=async(T)=>{_=T,W={...W,[T]:!0};try{await z().startRecording(),$=null,P=!0,k()}catch(G){z().stopRecording(),P=!1,N=v(),$=ie(G),k()}};E.subscribe(()=>{if(E.assistantAudio.length>0)J.start().catch(()=>{});k()}),V.subscribe(()=>{if(V.assistantAudio.length>0)Q.start().catch(()=>{});k()}),u.addEventListener(\"click\",()=>{le(\"guided\")}),O.addEventListener(\"click\",()=>{le(\"general\")}),U.addEventListener(\"click\",()=>{Oe()}),e.addEventListener(\"absolute-voice-simulate-disconnect\",()=>{z().simulateDisconnect()}),window.addEventListener(\"beforeunload\",()=>{E.stopRecording(),V.stopRecording(),A?.close(),f?.close(),J.close(),Q.close(),Y(),xe(),E.close(),V.close()}),k()},Pn=()=>{if(typeof window>\"u\"||typeof document>\"u\")return;let e=Array.from(document.querySelectorAll(\"[data-voice-htmx]\"));for(let n of e)if(n instanceof HTMLElement)En(n)};Pn();export{Pn as initVoiceHTMX};\n";
|
|
1
|
+
export declare const HTMX_BOOTSTRAP_BUNDLE = "var Ue=(e)=>{if(typeof e!==\"string\")return e;return document.querySelector(e)},Ne=(e,n,t,o)=>{let r=n??e.getAttribute(\"hx-get\")??\"\";if(!r)return\"\";let i=new URL(r,window.location.origin);if(o)i.searchParams.set(t,o);else i.searchParams.delete(t);return`${i.pathname}${i.search}${i.hash}`},de=(e,n)=>{if(typeof window>\"u\"||typeof document>\"u\")return()=>{};let t=Ue(n.element);if(!t)return()=>{};let o=n.eventName??\"voice-refresh\",r=n.sessionQueryParam??\"sessionId\",i=()=>{let l=window,g=Ne(t,n.route,r,e.sessionId);if(g)t.setAttribute(\"hx-get\",g);l.htmx?.process?.(t),l.htmx?.trigger?.(t,o)},c=e.subscribe(i);return i(),()=>{c()}};var He=(e)=>Math.max(-1,Math.min(1,e)),Ge=(e)=>{let n=new Int16Array(e.length);for(let t=0;t<e.length;t+=1){let o=He(e[t]??0);n[t]=o<0?o*32768:o*32767}return new Uint8Array(n.buffer)},Be=(e)=>{let n=e instanceof Uint8Array?e:new Uint8Array(e);if(n.byteLength<2)return 0;let t=new Int16Array(n.buffer,n.byteOffset,Math.floor(n.byteLength/2));if(t.length===0)return 0;let o=0;for(let r of t){let i=r/32768;o+=i*i}return Math.min(1,Math.max(0,Math.sqrt(o/t.length)*5.5))},We=(e,n,t)=>{if(n===t)return e;let o=n/t,r=Math.round(e.length/o),i=new Float32Array(r),c=0,l=0;while(c<i.length){let g=Math.round((c+1)*o),y=0,d=0;for(let h=l;h<g&&h<e.length;h+=1)y+=e[h]??0,d+=1;i[c]=d>0?y/d:0,c+=1,l=g}return i},ge=(e)=>{let n=null,t=null,o=null,r=null;return{start:async()=>{if(typeof navigator>\"u\"||!navigator.mediaDevices?.getUserMedia)throw Error(\"Browser microphone capture requires navigator.mediaDevices.getUserMedia.\");let l=(typeof window<\"u\"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!l)throw Error(\"Browser microphone capture requires AudioContext support.\");r=await navigator.mediaDevices.getUserMedia({audio:{channelCount:e.channelCount??1}}),n=new l,t=n.createMediaStreamSource(r),o=n.createScriptProcessor(4096,1,1),o.onaudioprocess=(g)=>{let y=g.inputBuffer.getChannelData(0),d=We(y,n?.sampleRate??48000,e.sampleRateHz??16000),h=Ge(d);e.onLevel?.(Be(h)),e.onAudio(h)},t.connect(o),o.connect(n.destination)},stop:()=>{o?.disconnect(),t?.disconnect(),r?.getTracks().forEach((l)=>l.stop()),n?.close(),e.onLevel?.(0),n=null,r=null,o=null,t=null}}};var ee=(e)=>{if(typeof e===\"string\"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e===\"object\"){let n=e;for(let t of[\"message\",\"reason\",\"description\"]){let o=n[t];if(typeof o===\"string\"&&o.trim())return o}if(\"error\"in n)return ee(n.error);if(\"cause\"in n)return ee(n.cause);try{return JSON.stringify(e)}catch{}}return\"Unexpected error\"},Ae=(e)=>{switch(e.type){case\"audio\":return{chunk:Uint8Array.from(atob(e.chunkBase64),(n)=>n.charCodeAt(0)),format:e.format,receivedAt:e.receivedAt,turnId:e.turnId,type:\"audio\"};case\"assistant\":return{text:e.text,type:\"assistant\"};case\"complete\":return{sessionId:e.sessionId,type:\"complete\"};case\"connection\":return{reconnect:e.reconnect,type:\"connection\"};case\"call_lifecycle\":return{event:e.event,sessionId:e.sessionId,type:\"call_lifecycle\"};case\"error\":return{message:ee(e.message),type:\"error\"};case\"final\":return{transcript:e.transcript,type:\"final\"};case\"partial\":return{transcript:e.transcript,type:\"partial\"};case\"replay\":return{assistantTexts:e.assistantTexts,call:e.call,partial:e.partial,scenarioId:e.scenarioId,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,status:e.status,turns:e.turns,type:\"replay\"};case\"session\":return{sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,type:\"session\"};case\"turn\":return{turn:e.turn,type:\"turn\"};default:return null}};var H=(e,n,t,o)=>{e.push({code:t,message:o,severity:n})};var $e=(e)=>e.length===0?void 0:e.reduce((n,t)=>n+t,0)/e.length,K=(e)=>e.length===0?void 0:Math.max(...e);var b=(e,n)=>{let t=e[n];return typeof t===\"number\"&&Number.isFinite(t)?t:void 0},Z=(e,n)=>{let t=e[n];return typeof t===\"boolean\"?t:void 0},D=(e,n)=>{let t=e[n];return typeof t===\"string\"?t:void 0},ne=(e)=>String(e.id??D(e,\"ssrc\")??b(e,\"ssrc\")??D(e,\"trackIdentifier\")??D(e,\"mid\")??\"unknown\"),he=(e)=>e===void 0?void 0:e*1000;var ke=(e)=>{let n={};for(let[t,o]of Object.entries(e))if(o===null||typeof o===\"boolean\"||typeof o===\"number\"||typeof o===\"string\")n[t]=o;return n};var ye=(e={})=>{let n=e.stats??[],t=[],o=n.filter((s)=>s.type===\"inbound-rtp\"&&D(s,\"kind\")!==\"video\"),r=n.filter((s)=>s.type===\"outbound-rtp\"&&D(s,\"kind\")!==\"video\"),i=n.filter((s)=>s.type===\"candidate-pair\"),c=n.filter((s)=>(s.type===\"track\"||s.type===\"media-source\")&&D(s,\"kind\")===\"audio\"),l=i.filter((s)=>Z(s,\"selected\")===!0||Z(s,\"nominated\")===!0||D(s,\"state\")===\"succeeded\").length,g=c.filter((s)=>D(s,\"readyState\")!==\"ended\"&&D(s,\"trackState\")!==\"ended\"&&Z(s,\"ended\")!==!0).length,y=c.filter((s)=>D(s,\"readyState\")===\"ended\"||D(s,\"trackState\")===\"ended\"||Z(s,\"ended\")===!0).length,d=o.reduce((s,S)=>s+(b(S,\"packetsReceived\")??0),0),h=r.reduce((s,S)=>s+(b(S,\"packetsSent\")??0),0),a=[...o,...r].reduce((s,S)=>s+Math.max(0,b(S,\"packetsLost\")??0),0),M=d+a,C=M===0?0:a/M,I=o.reduce((s,S)=>s+(b(S,\"bytesReceived\")??0),0),w=r.reduce((s,S)=>s+(b(S,\"bytesSent\")??0),0),R=K(i.map((s)=>he(b(s,\"currentRoundTripTime\")??b(s,\"roundTripTime\"))).filter((s)=>s!==void 0)),u=K([...o,...r].map((s)=>he(b(s,\"jitter\"))).filter((s)=>s!==void 0)),O=K(o.map((s)=>{let S=b(s,\"jitterBufferDelay\"),L=b(s,\"jitterBufferEmittedCount\");return S!==void 0&&L!==void 0&&L>0?S/L*1000:void 0}).filter((s)=>s!==void 0)),U=c.map((s)=>b(s,\"audioLevel\")).filter((s)=>s!==void 0);if(e.requireConnectedCandidatePair&&i.length>0&&l===0)H(t,\"error\",\"media.webrtc_candidate_pair_missing\",\"No active WebRTC candidate pair was observed.\");if(e.requireLiveAudioTrack&&g===0)H(t,\"error\",\"media.webrtc_audio_track_missing\",\"No live WebRTC audio track was observed.\");if(e.maxPacketLossRatio!==void 0&&C>e.maxPacketLossRatio)H(t,\"warning\",\"media.webrtc_packet_loss\",`Observed WebRTC packet loss ratio ${String(C)} above ${String(e.maxPacketLossRatio)}.`);if(e.maxRoundTripTimeMs!==void 0&&R!==void 0&&R>e.maxRoundTripTimeMs)H(t,\"warning\",\"media.webrtc_round_trip_time\",`Observed WebRTC RTT ${String(R)}ms above ${String(e.maxRoundTripTimeMs)}ms.`);if(e.maxJitterMs!==void 0&&u!==void 0&&u>e.maxJitterMs)H(t,\"warning\",\"media.webrtc_jitter\",`Observed WebRTC jitter ${String(u)}ms above ${String(e.maxJitterMs)}ms.`);return{activeCandidatePairs:l,audioLevelAverage:$e(U),bytesReceived:I,bytesSent:w,checkedAt:Date.now(),endedAudioTracks:y,inboundPackets:d,issues:t,jitterBufferDelayMs:O,jitterMs:u,liveAudioTracks:g,outboundPackets:h,packetLossRatio:C,packetsLost:a,roundTripTimeMs:R,status:t.some((s)=>s.severity===\"error\")?\"fail\":t.length>0?\"warn\":\"pass\",totalStats:n.length}},Ce=async(e)=>{return[...(await e.peerConnection.getStats(e.selector??null)).values()].map(ke)};var fe=(e={})=>{let n=e.stats??[],t=e.previousStats??[],o=[],r=new Map(t.map((a)=>[ne(a),a])),c=n.filter((a)=>(a.type===\"inbound-rtp\"||a.type===\"outbound-rtp\")&&D(a,\"kind\")!==\"video\"&&D(a,\"mediaType\")!==\"video\").map((a)=>{let M=a.type===\"outbound-rtp\"?\"outbound\":\"inbound\",C=M===\"outbound\"?\"packetsSent\":\"packetsReceived\",I=M===\"outbound\"?\"bytesSent\":\"bytesReceived\",w=r.get(ne(a)),R=b(a,C),u=w?b(w,C):void 0,O=b(a,I),U=w?b(w,I):void 0,s=a.timestamp!==void 0&&w?.timestamp!==void 0?a.timestamp-w.timestamp:void 0;return{bytesDelta:O!==void 0&&U!==void 0?O-U:void 0,currentPackets:R,direction:M,id:ne(a),packetDelta:R!==void 0&&u!==void 0?R-u:void 0,previousPackets:u,timeDeltaMs:s}}),l=c.filter((a)=>a.direction===\"inbound\"),g=c.filter((a)=>a.direction===\"outbound\"),y=K(c.map((a)=>a.timeDeltaMs).filter((a)=>a!==void 0)),d=l.filter((a)=>e.maxInboundPacketStallMs!==void 0&&a.timeDeltaMs!==void 0&&a.timeDeltaMs>=e.maxInboundPacketStallMs&&a.packetDelta!==void 0&&a.packetDelta<=0).length,h=g.filter((a)=>e.maxOutboundPacketStallMs!==void 0&&a.timeDeltaMs!==void 0&&a.timeDeltaMs>=e.maxOutboundPacketStallMs&&a.packetDelta!==void 0&&a.packetDelta<=0).length;if(e.requireInboundAudio&&l.length===0)H(o,\"error\",\"media.webrtc_inbound_audio_missing\",\"No inbound WebRTC audio RTP stream was observed.\");if(e.requireOutboundAudio&&g.length===0)H(o,\"error\",\"media.webrtc_outbound_audio_missing\",\"No outbound WebRTC audio RTP stream was observed.\");if(e.maxGapMs!==void 0&&y!==void 0&&y>e.maxGapMs)H(o,\"warning\",\"media.webrtc_stream_gap\",`Observed WebRTC stream sample gap ${String(y)}ms above ${String(e.maxGapMs)}ms.`);if(d>0)H(o,\"error\",\"media.webrtc_inbound_stalled\",`${String(d)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(h>0)H(o,\"error\",\"media.webrtc_outbound_stalled\",`${String(h)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:l.length,issues:o,maxObservedGapMs:y,outboundAudioStreams:g.length,stalledInboundStreams:d,stalledOutboundStreams:h,status:o.some((a)=>a.severity===\"error\")?\"fail\":o.length>0?\"warn\":\"pass\",streams:c,totalStats:n.length}};var qe=\"/api/voice/browser-media\",Xe=5000,ze=async(e)=>e.peerConnection??await e.getPeerConnection?.()??null,Ye=async(e,n)=>{let t=n.fetch??globalThis.fetch;if(!t)return;await t(n.path??qe,{body:JSON.stringify(e),headers:{\"Content-Type\":\"application/json\"},keepalive:!0,method:\"POST\"})},Te=(e)=>{let n=null,t=[],o=async()=>{let c=await ze(e);if(!c)return;let l=await Ce({peerConnection:c}),g=ye({...e,stats:l}),y=e.continuity===!1?void 0:fe({...e.continuity,previousStats:t,stats:l}),d={at:Date.now(),continuity:y,report:g,scenarioId:e.getScenarioId?.()??null,sessionId:e.getSessionId?.()??null};return t=l,e.onReport?.(d),await Ye(d,e),d},r=()=>{o().catch((c)=>{e.onError?.(c)})},i=()=>{if(n)clearInterval(n),n=null};return{close:i,reportOnce:o,start:()=>{if(n)return;r(),n=setInterval(r,e.intervalMs??Xe)},stop:i}};var B=()=>{},Je=()=>B,Qe={callControl:B,close:B,endTurn:B,getReadyState:()=>3,getScenarioId:()=>\"\",getSessionId:()=>\"\",send:B,sendAudio:B,simulateDisconnect:B,start:()=>{},subscribe:Je},Ze=()=>crypto.randomUUID(),Ke=(e,n,t)=>{let{hostname:o,port:r,protocol:i}=window.location,c=i===\"https:\"?\"wss:\":\"ws:\",l=r?`:${r}`:\"\",g=new URL(`${c}//${o}${l}${e}`);if(g.searchParams.set(\"sessionId\",n),t)g.searchParams.set(\"scenarioId\",t);return g.toString()},me=(e)=>{if(!e||typeof e!==\"object\"||!(\"type\"in e))return!1;switch(e.type){case\"audio\":case\"assistant\":case\"call_lifecycle\":case\"complete\":case\"connection\":case\"error\":case\"final\":case\"partial\":case\"pong\":case\"replay\":case\"session\":case\"turn\":return!0;default:return!1}},je=(e)=>{if(typeof e.data!==\"string\")return null;try{let n=JSON.parse(e.data);return me(n)?n:null}catch{return null}},Se=(e,n={})=>{if(typeof window>\"u\")return Qe;let t=new Set,o=n.reconnect!==!1,r=n.maxReconnectAttempts??10,i=n.pingInterval??30000,c={isConnected:!1,pendingMessages:[],scenarioId:n.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectTimeout:null,sessionId:n.sessionId??Ze(),ws:null},l=(s)=>{t.forEach((S)=>S(s))},g=()=>{if(c.pingInterval)clearInterval(c.pingInterval),c.pingInterval=null;if(c.reconnectTimeout)clearTimeout(c.reconnectTimeout),c.reconnectTimeout=null},y=()=>{if(c.ws?.readyState!==1)return;while(c.pendingMessages.length>0){let s=c.pendingMessages.shift();if(s!==void 0)c.ws.send(s)}},d=()=>{let s=Date.now()+500;c.reconnectAttempts+=1,l({reconnect:{attempts:c.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:r,nextAttemptAt:s,status:\"reconnecting\"},type:\"connection\"}),c.reconnectTimeout=setTimeout(()=>{if(c.reconnectAttempts>r){l({reconnect:{attempts:c.reconnectAttempts,maxAttempts:r,status:\"exhausted\"},type:\"connection\"});return}h()},500)},h=()=>{let s=new WebSocket(Ke(e,c.sessionId,c.scenarioId));s.binaryType=\"arraybuffer\",s.onopen=()=>{let S=c.reconnectAttempts>0;if(c.isConnected=!0,y(),S)l({reconnect:{attempts:c.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:r,status:\"resumed\"},type:\"connection\"}),c.reconnectAttempts=0;t.forEach((L)=>L({scenarioId:c.scenarioId??void 0,sessionId:c.sessionId,status:\"active\",type:\"session\"})),c.pingInterval=setInterval(()=>{if(s.readyState===1)s.send(JSON.stringify({type:\"ping\"}))},i)},s.onmessage=(S)=>{let L=je(S);if(!L)return;if(L.type===\"session\")c.sessionId=L.sessionId,c.scenarioId=L.scenarioId??c.scenarioId;t.forEach((X)=>X(L))},s.onclose=(S)=>{if(c.isConnected=!1,g(),o&&S.code!==1000&&c.reconnectAttempts<r)d();else if(o&&S.code!==1000)l({reconnect:{attempts:c.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:r,status:\"exhausted\"},type:\"connection\"})},c.ws=s},a=(s)=>{if(c.ws?.readyState===1){c.ws.send(s);return}c.pendingMessages.push(s)},M=(s)=>{a(JSON.stringify(s))},C=(s={})=>{if(s.sessionId)c.sessionId=s.sessionId;if(s.scenarioId)c.scenarioId=s.scenarioId;M({type:\"start\",sessionId:c.sessionId,scenarioId:c.scenarioId??void 0})},I=(s)=>{a(s)},w=()=>{M({type:\"end_turn\"})},R=(s)=>{M({...s,type:\"call_control\"})},u=()=>{if(g(),c.ws)c.ws.close(1000),c.ws=null;c.isConnected=!1,t.clear()},O=()=>{if(c.ws?.readyState===1)c.ws.close(4000,\"absolutejs-voice-reconnect-proof\")},U=(s)=>{return t.add(s),()=>{t.delete(s)}};return h(),{callControl:R,close:u,endTurn:w,getReadyState:()=>c.ws?.readyState??3,getScenarioId:()=>c.scenarioId??\"\",getSessionId:()=>c.sessionId,send:M,sendAudio:I,simulateDisconnect:O,start:C,subscribe:U}};var ve=()=>({attempts:0,maxAttempts:0,status:\"idle\"}),Fe=()=>({assistantAudio:[],assistantTexts:[],call:null,error:null,isConnected:!1,sessionMetadata:null,scenarioId:null,partial:\"\",reconnect:ve(),sessionId:null,status:\"idle\",turns:[]}),Me=()=>{let e=Fe(),n=new Set,t=()=>{n.forEach((r)=>r())};return{dispatch:(r)=>{switch(r.type){case\"audio\":e={...e,assistantAudio:[...e.assistantAudio,{chunk:r.chunk,format:r.format,receivedAt:r.receivedAt,turnId:r.turnId}]};break;case\"assistant\":e={...e,assistantTexts:[...e.assistantTexts,r.text]};break;case\"complete\":e={...e,sessionId:r.sessionId,status:\"completed\"};break;case\"call_lifecycle\":e={...e,call:{...e.call,disposition:r.event.type===\"end\"?r.event.disposition:e.call?.disposition,endedAt:r.event.type===\"end\"?r.event.at:e.call?.endedAt,events:[...e.call?.events??[],r.event],lastEventAt:r.event.at,startedAt:e.call?.startedAt??r.event.at},sessionId:r.sessionId};break;case\"connected\":e={...e,isConnected:!0,reconnect:e.reconnect.status===\"reconnecting\"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:\"resumed\"}:e.reconnect};break;case\"connection\":e={...e,reconnect:r.reconnect};break;case\"disconnected\":e={...e,isConnected:!1};break;case\"error\":e={...e,error:r.message};break;case\"final\":e={...e,partial:r.transcript.text,turns:e.turns.map((i)=>i)};break;case\"partial\":e={...e,partial:r.transcript.text};break;case\"replay\":e={...e,assistantTexts:[...r.assistantTexts],call:r.call??null,error:null,isConnected:r.status===\"active\",partial:r.partial,reconnect:e.reconnect.status===\"reconnecting\"?{...e.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:\"resumed\"}:e.reconnect,scenarioId:r.scenarioId??e.scenarioId,sessionId:r.sessionId,sessionMetadata:r.sessionMetadata??e.sessionMetadata,status:r.status,turns:[...r.turns]};break;case\"session\":e={...e,error:null,scenarioId:r.scenarioId??e.scenarioId,isConnected:r.status===\"active\",sessionId:r.sessionId,sessionMetadata:r.sessionMetadata??e.sessionMetadata,status:r.status};break;case\"turn\":e={...e,partial:\"\",turns:[...e.turns,r.turn]};break}t()},getServerSnapshot:()=>e,getSnapshot:()=>e,subscribe:(r)=>{return n.add(r),()=>{n.delete(r)}}}};var Ie=(e,n={})=>{let t=Se(e,n),o=Me(),r=n.browserMedia&&typeof window<\"u\"?Te({...n.browserMedia,getScenarioId:()=>n.browserMedia?n.browserMedia.getScenarioId?.()??t.getScenarioId():t.getScenarioId(),getSessionId:()=>n.browserMedia?n.browserMedia.getSessionId?.()??t.getSessionId():t.getSessionId()}):null,i=new Set,c=(d)=>Promise.resolve().then(()=>{if(!d?.sessionId&&!d?.scenarioId)return;t.start(d),r?.start()}),l=()=>{i.forEach((d)=>d())},g=()=>{if(!n.reconnectReportPath||typeof fetch>\"u\")return;let d=o.getSnapshot(),h=JSON.stringify({at:Date.now(),reconnect:d.reconnect,scenarioId:d.scenarioId,sessionId:t.getSessionId(),turnIds:d.turns.map((a)=>a.id)});fetch(n.reconnectReportPath,{body:h,headers:{\"Content-Type\":\"application/json\"},keepalive:!0,method:\"POST\"}).catch(()=>{})},y=t.subscribe((d)=>{let h=Ae(d);if(h){if(o.dispatch(h),d.type===\"connection\")g();l()}});return{callControl(d){t.callControl(d)},close(){y(),r?.close(),t.close(),o.dispatch({type:\"disconnected\"}),l()},endTurn(){t.endTurn()},get error(){return o.getSnapshot().error},getServerSnapshot(){return o.getServerSnapshot()},getSnapshot(){return o.getSnapshot()},get isConnected(){return o.getSnapshot().isConnected},get scenarioId(){return o.getSnapshot().scenarioId},get sessionMetadata(){return o.getSnapshot().sessionMetadata},start:c,get partial(){return o.getSnapshot().partial},get reconnect(){return o.getSnapshot().reconnect},get sessionId(){return t.getSessionId()},get status(){return o.getSnapshot().status},get turns(){return o.getSnapshot().turns},get assistantTexts(){return o.getSnapshot().assistantTexts},get assistantAudio(){return o.getSnapshot().assistantAudio},get call(){return o.getSnapshot().call},sendAudio(d){t.sendAudio(d)},simulateDisconnect(){t.simulateDisconnect()},subscribe(d){return i.add(d),()=>{i.delete(d)}}}};var Ve=(e)=>{if(!e||e.enabled===!1)return;return{enabled:!0,maxGain:e.maxGain??3,noiseGateAttenuation:e.noiseGateAttenuation??0.15,noiseGateThreshold:e.noiseGateThreshold??0.006,targetLevel:e.targetLevel??0.08}};var pe={balanced:{qualityProfile:\"general\",silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:\"general\",silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},\"long-form\":{qualityProfile:\"general\",silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},en={general:{},\"accent-heavy\":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},\"noisy-room\":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},\"short-command\":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var we=(e)=>{let n=e?.profile??\"fast\",t=e?.qualityProfile??\"general\",o=pe[n],r=en[t];return{profile:n,qualityProfile:t,silenceMs:e?.silenceMs??r.silenceMs??o.silenceMs,speechThreshold:e?.speechThreshold??r.speechThreshold??o.speechThreshold,transcriptStabilityMs:e?.transcriptStabilityMs??r.transcriptStabilityMs??o.transcriptStabilityMs}};var nn={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"short-command\",profile:\"balanced\"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"general\",profile:\"fast\"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"accent-heavy\",profile:\"long-form\"}},\"guided-intake\":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:\"turn-scoped\",turnDetection:{qualityProfile:\"accent-heavy\",profile:\"long-form\"}},\"noisy-room\":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},\"pstn-balanced\":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},\"pstn-fast\":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:\"continuous\",turnDetection:{qualityProfile:\"noisy-room\",profile:\"long-form\"}}},Le=(e=\"default\")=>{let n=nn[e];return{audioConditioning:Ve(n.audioConditioning),capture:{channelCount:n.capture?.channelCount??1,sampleRateHz:n.capture?.sampleRateHz??16000},connection:{...n.connection},name:e,sttLifecycle:n.sttLifecycle??\"continuous\",turnDetection:we(n.turnDetection)}};var on=(e)=>({assistantAudio:[...e.assistantAudio],assistantTexts:[...e.assistantTexts],call:e.call,error:e.error,isConnected:e.isConnected,isRecording:!1,partial:e.partial,reconnect:e.reconnect,recordingError:null,sessionId:e.sessionId,sessionMetadata:e.sessionMetadata,scenarioId:e.scenarioId,status:e.status,turns:[...e.turns]}),m=(e,n={})=>{let t=Le(n.preset),o=Ie(e,{...t.connection,...n.connection}),r=null,i=on(o),c=new Set,l=()=>{for(let C of c)C()},g=()=>{if(i={...i,assistantAudio:[...o.assistantAudio],assistantTexts:[...o.assistantTexts],call:o.call,error:o.error,isConnected:o.isConnected,partial:o.partial,reconnect:o.reconnect,sessionId:o.sessionId,sessionMetadata:o.sessionMetadata,scenarioId:o.scenarioId,status:o.status,turns:[...o.turns]},n.autoStopOnComplete!==!1&&i.status===\"completed\"&&i.isRecording)r?.stop(),r=null,i={...i,isRecording:!1};l()},y=o.subscribe(g);g();let d=()=>{if(r)return r;return r=ge({channelCount:n.capture?.channelCount??t.capture.channelCount,onLevel:n.capture?.onLevel,onAudio:(C)=>{if(n.capture?.onAudio){n.capture.onAudio(C,o.sendAudio);return}o.sendAudio(C)},sampleRateHz:n.capture?.sampleRateHz??t.capture.sampleRateHz}),r},h=()=>{r?.stop(),r=null,i={...i,isRecording:!1},l()},a=async()=>{if(i.isRecording)return;try{i={...i,recordingError:null},l(),await d().start(),i={...i,isRecording:!0},l()}catch(C){throw r=null,i={...i,isRecording:!1,recordingError:C instanceof Error?C.message:String(C)},l(),C}};return{bindHTMX(C){return de(o,C)},callControl:(C)=>o.callControl(C),close:()=>{y(),h(),o.close()},endTurn:()=>o.endTurn(),get error(){return i.error},getServerSnapshot:()=>i,getSnapshot:()=>i,get isConnected(){return i.isConnected},get isRecording(){return i.isRecording},get partial(){return i.partial},get recordingError(){return i.recordingError},get reconnect(){return i.reconnect},sendAudio:(C)=>o.sendAudio(C),simulateDisconnect:()=>o.simulateDisconnect(),get sessionId(){return i.sessionId},get sessionMetadata(){return i.sessionMetadata},get scenarioId(){return i.scenarioId},startRecording:a,get status(){return i.status},stopRecording:h,subscribe:(C)=>{return c.add(C),()=>{c.delete(C)}},toggleRecording:async()=>{if(i.isRecording){h();return}await a()},get turns(){return i.turns},get assistantTexts(){return i.assistantTexts},get assistantAudio(){return i.assistantAudio},get call(){return i.call}}};var tn=()=>({activeSourceCount:0,error:null,isActive:!1,isPlaying:!1,lastInterruptLatencyMs:void 0,lastPlaybackStopLatencyMs:void 0,processedChunkCount:0,queuedChunkCount:0}),cn=()=>{if(typeof window>\"u\")return typeof AudioContext>\"u\"?void 0:AudioContext;return window.AudioContext??window.webkitAudioContext},rn=(e,n)=>{let t=n.format;if(t.container!==\"raw\"||t.encoding!==\"pcm_s16le\")throw Error(`Unsupported assistant audio format: ${t.container}/${t.encoding}`);let o=n.chunk,r=Math.max(1,t.channels),i=Math.floor(o.byteLength/2),c=Math.max(1,Math.floor(i/r)),l=e.createBuffer(r,c,t.sampleRateHz),g=new DataView(o.buffer,o.byteOffset,o.byteLength);for(let y=0;y<r;y+=1){let d=l.getChannelData(y);for(let h=0;h<c;h+=1){let M=(h*r+y)*2;if(M+1>=o.byteLength){d[h]=0;continue}d[h]=g.getInt16(M,!0)/32768}}return l},j=(e,n={})=>{let t=new Set,o=new Set,r=(n.lookaheadMs??15)/1000,i=tn(),c=null,l=null,g=0,y=Promise.resolve(),d=null,h=null,a=null,M=null,C=()=>{for(let A of t)A()},I=(A)=>{i={...i,...A},C()},w=()=>{if(i.error!==null)I({error:null})},R=()=>{if(M!==null)clearTimeout(M),M=null},u=(A)=>{R(),d=null,I({activeSourceCount:o.size,isPlaying:!1,lastInterruptLatencyMs:A,lastPlaybackStopLatencyMs:i.lastPlaybackStopLatencyMs??A}),a?.(),a=null,h=null},O=(A)=>{if(!A)return 0;return Math.max(0,((A.baseLatency??0)+(A.outputLatency??0))*1000)},U=(A)=>{if(!l)return;let f=1;if(l.gain.setValueAtTime){l.gain.setValueAtTime(f,A?.currentTime??0);return}l.gain.value=f},s=(A)=>{if(!l)return;let f=0;if(l.gain.setValueAtTime){l.gain.setValueAtTime(f,A?.currentTime??0);return}l.gain.value=f},S=()=>{if(d===null||o.size>0)return;u(Date.now()-d)},L=async()=>{if(c)return c;if(n.createAudioContext)c=n.createAudioContext();else{let A=cn();if(!A)throw Error(\"Assistant audio playback requires AudioContext support.\");c=new A}if(c.createGain)l=c.createGain(),l.connect?.(c.destination);return g=c.currentTime,c},X=async(A)=>{let f=await L(),E=rn(f,A),V=f.createBufferSource();V.buffer=E,V.connect(l??f.destination),V.onended=()=>{o.delete(V),V.disconnect?.(),I({activeSourceCount:o.size,isPlaying:o.size>0&&i.isActive}),S()};let Y=Math.max(f.currentTime+r,g);g=Y+E.duration,o.add(V),I({activeSourceCount:o.size,isPlaying:!0}),V.start(Y)},_=(A)=>{for(let f of[...o])f.stop?.();if(g=c?c.currentTime:0,A?.forceClear){for(let f of o)f.disconnect?.();o.clear(),S()}},W=async()=>{if(!i.isActive)return;let A=e.assistantAudio.slice(i.processedChunkCount);if(A.length===0)return;try{w();for(let f of A)await X(f);I({processedChunkCount:e.assistantAudio.length,queuedChunkCount:i.queuedChunkCount+A.length})}catch(f){I({error:f instanceof Error?f.message:String(f)})}},P=()=>{return y=y.then(()=>W(),()=>W()),y},$=e.subscribe(()=>{if(n.autoStart&&!i.isActive&&e.assistantAudio.length>0){N.start();return}if(i.isActive)P()}),N={close:async()=>{if($(),_({forceClear:!0}),R(),a?.(),a=null,h=null,d=null,c&&c.state!==\"closed\")await c.close();c=null,l?.disconnect?.(),l=null,g=0,I({activeSourceCount:0,isActive:!1,isPlaying:!1})},get activeSourceCount(){return i.activeSourceCount},get error(){return i.error},getSnapshot:()=>i,get isActive(){return i.isActive},get isPlaying(){return i.isPlaying},interrupt:async()=>{let A=Date.now(),f=await L();d=A,s(f);let E=Date.now()-A+O(f);if(I({isActive:!1,isPlaying:o.size>0,lastPlaybackStopLatencyMs:E}),o.size===0){u(E);return}if(!h)h=new Promise((V)=>{a=V});R(),M=setTimeout(()=>{for(let V of o)V.disconnect?.();o.clear(),u(Date.now()-A)},250),_(),await h},get lastInterruptLatencyMs(){return i.lastInterruptLatencyMs},get lastPlaybackStopLatencyMs(){return i.lastPlaybackStopLatencyMs},pause:async()=>{if(!c){I({activeSourceCount:0,isActive:!1,isPlaying:!1});return}await c.suspend(),I({activeSourceCount:o.size,isActive:!1,isPlaying:!1})},get processedChunkCount(){return i.processedChunkCount},get queuedChunkCount(){return i.queuedChunkCount},start:async()=>{try{w();let A=await L();if(U(A),A.state===\"suspended\")await A.resume();I({activeSourceCount:o.size,isActive:!0,isPlaying:A.state===\"running\"}),await P()}catch(A){throw I({error:A instanceof Error?A.message:String(A),isActive:!1,isPlaying:!1}),A}},subscribe:(A)=>{return t.add(A),()=>{t.delete(A)}}};return N};var sn=()=>`barge-in:${Date.now()}:${crypto.randomUUID?.()??Math.random().toString(36).slice(2)}`,ln=(e,n)=>{let t=e.filter((c)=>c.status===\"stopped\"),o=t.map((c)=>c.latencyMs).filter((c)=>typeof c===\"number\"),r=t.filter((c)=>typeof c.latencyMs===\"number\"&&c.latencyMs>n).length,i=t.length-r;return{averageLatencyMs:o.length>0?Math.round(o.reduce((c,l)=>c+l,0)/o.length):void 0,events:[...e],failed:r,lastEvent:e.at(-1),passed:i,status:e.length===0?\"empty\":r>0?\"fail\":t.length===0?\"warn\":\"pass\",thresholdMs:n,total:t.length}},ue=(e={})=>{let n=new Set,t=e.thresholdMs??250,o=e.fetch??globalThis.fetch,r=[],i=()=>{for(let g of n)g()},c=(g)=>{if(!e.path||typeof o!==\"function\")return;o(e.path,{body:JSON.stringify(g),headers:{\"Content-Type\":\"application/json\"},method:\"POST\"}).catch(()=>{})},l=(g,y)=>{let d={at:Date.now(),id:sn(),latencyMs:y.latencyMs,playbackStopLatencyMs:y.playbackStopLatencyMs,reason:y.reason,sessionId:y.sessionId,status:g,thresholdMs:t};return r.push(d),c(d),i(),d};return{getSnapshot:()=>ln(r,t),recordRequested:(g)=>l(\"requested\",g),recordSkipped:(g)=>l(\"skipped\",g),recordStopped:(g)=>l(\"stopped\",g),subscribe:(g)=>{return n.add(g),()=>{n.delete(g)}}}};var an=0.08,dn=(e,n={})=>(n.enabled??!0)&&e>=(n.interruptThreshold??an),oe=(e,n,t={})=>{let o=e.partial,r=(c)=>{if(!n.isPlaying||t.enabled===!1){t.monitor?.recordSkipped({reason:c,sessionId:e.sessionId});return}t.monitor?.recordRequested({reason:c,sessionId:e.sessionId}),n.interrupt().then(()=>{t.monitor?.recordStopped({latencyMs:n.lastInterruptLatencyMs,playbackStopLatencyMs:n.lastPlaybackStopLatencyMs,reason:c,sessionId:e.sessionId})})},i=e.subscribe(()=>{if(t.interruptOnPartial===!1){o=e.partial;return}if(!o&&e.partial)r(\"partial-transcript\");o=e.partial});return{close:()=>{i()},handleLevel:(c)=>{if(dn(c,t))r(\"input-level\")},sendAudio:(c)=>{r(\"manual-audio\"),e.sendAudio(c)}}};var se=48,gn=320,An=88,hn=\"Guided test\",yn=\"General recording\",Cn=\"Pick a scenario to begin the demo.\",fn=\"I can walk you through a short guided voice test.\",Tn=\"I can capture one freeform recording and confirm that it landed.\",Sn=\"Choose a scenario to begin. Guided test asks follow-up prompts. General recording just captures what you say.\",Mn=\"Click Start general recording to capture one freeform answer.\",_e=\"Speak freely. When you pause, the recording will be captured.\",re=\"Recording saved. Start again if you want another capture.\",Ee=\"Guided test complete. Review the saved summary below.\",Pe=\"All prompts are covered. You can stop the microphone or keep speaking for extra detail.\",In=\"Ready. Start guided test or general recording to begin.\",Vn=\"Live. Answer the prompt, then click Stop microphone when finished.\",Re=[\"Start with a quick introduction about who you are.\",\"Now describe what you are trying to do or test.\",\"Finish with any detail that feels blocked, risky, or unclear.\"],De=(e,n,t)=>Math.min(t,Math.max(n,e)),q=(e)=>e.replaceAll(\"&\",\"&\").replaceAll(\"<\",\"<\").replaceAll(\">\",\">\").replaceAll('\"',\""\").replaceAll(\"'\",\"'\"),te=(e,n)=>{let t=e[n];if(typeof t===\"string\"&&t.trim())return t;return null},ie=(e)=>{if(typeof e===\"string\"&&e.trim())return e;if(e instanceof Error&&e.message.trim())return e.message;if(e&&typeof e===\"object\"){let n=e,t=te(n,\"message\")??te(n,\"reason\")??te(n,\"description\");if(t)return t;if(\"error\"in n)return ie(n.error);if(\"cause\"in n)return ie(n.cause);try{return JSON.stringify(e)}catch{}}return\"Unexpected error\"},wn=(e)=>{let n=[e.status];if(e.attempts>0||e.maxAttempts>0)n.push(`${e.attempts}/${e.maxAttempts} attempts`);if(e.nextAttemptAt){let t=Math.max(0,e.nextAttemptAt-Date.now());n.push(`retry in ${Math.ceil(t/100)/10}s`)}return n.join(\" \u00B7 \")},v=(e=se)=>Array.from({length:e},()=>0),be=(e,n,t=se)=>{let o=e.slice(-(t-1));o.push(De(n,0,1));while(o.length<t)o.unshift(0);return o},Ln=(e,n=gn,t=An)=>{let o=e.length>1?e:v(se),r=n/(o.length-1),i=t/2,c=t*0.34;if(Math.max(...o,0)<=0.015)return`M 0 ${i} L ${n} ${i}`;let g=o.map((d,h)=>{let a=h*0.76,M=Math.sin(a)*0.78+Math.sin(a*0.41)*0.22,C=d*c,I=r*h,w=De(i+M*C,8,t-8);return{x:I,y:w}});if(g.length===0)return`M 0 ${i} L ${n} ${i}`;let y=`M ${g[0]?.x??0} ${g[0]?.y??i}`;for(let d=1;d<g.length;d+=1){let h=g[d-1],a=g[d];if(!h||!a)continue;let M=(h.x+a.x)/2;y+=` Q ${M} ${h.y} ${a.x} ${a.y}`}return y},un=(e)=>{if(!e)return Re;try{let n=JSON.parse(e);if(Array.isArray(n)){let t=n.filter((o)=>typeof o===\"string\").map((o)=>o.trim()).filter(Boolean);if(t.length>0)return t}}catch{}return Re},ce=(e)=>{if(!e)return;let n=Number(e);return Number.isFinite(n)?n:void 0},Rn=(e,n,t)=>{if(!n)return null;let o=document.querySelector(n);return o instanceof t?o:null},x=(e,n,t,o)=>{let r=n?document.querySelector(n):null;if(r instanceof t)return r;let i=e.querySelector(`#${o}`);if(i instanceof t)return i;throw Error(`Voice HTMX bootstrap could not find the required element \"${o}\".`)},bn=(e)=>{if(!e.mode)return Cn;if(!e.hasStarted)return e.mode===\"guided\"?fn:Tn;if(e.status===\"completed\")return e.mode===\"guided\"?Ee:re;if(e.mode===\"general\")return _e;return e.guidedPrompts[e.turnCount]??Pe},_n=(e)=>{if(!e.mode)return Sn;if(e.status===\"completed\")return e.mode===\"guided\"?Ee:re;if(!e.hasStarted)return e.mode===\"guided\"?`Click Start guided test to begin. First prompt: ${e.guidedPrompts[0]??\"Answer the first prompt.\"}`:Mn;if(e.mode===\"general\")return e.turnCount===0?_e:re;return e.guidedPrompts[e.turnCount]??Pe},En=(e)=>{let n=e.dataset.voiceGuidedPath,t=e.dataset.voiceGeneralPath;if(!n||!t)throw Error(\"Voice HTMX bootstrap requires data-voice-guided-path and data-voice-general-path.\");let o=un(e.dataset.voiceGuidedPrompts),r=e.dataset.voiceGuidedLabel??hn,i=e.dataset.voiceGeneralLabel??yn,c=e.dataset.voiceReconnectReportPath,l=e.dataset.voiceBargeInPath,g=l?ue({path:l,thresholdMs:ce(e.dataset.voiceBargeInThresholdMs)}):null,y=ce(e.dataset.voiceBargeInRecentWindowMs)??4000,d=ce(e.dataset.voiceBargeInSpeechThreshold)??0.04,h=x(document,e.dataset.voiceSync,HTMLElement,\"voice-htmx-sync\"),a=x(e,e.dataset.voiceConnection,HTMLElement,\"metric-connection\"),M=x(e,e.dataset.voiceError,HTMLElement,\"status-error\"),C=x(e,e.dataset.voiceMicrophone,HTMLElement,\"status-mic\"),I=x(e,e.dataset.voicePrompt,HTMLElement,\"status-prompt\"),w=Rn(e,e.dataset.voiceReconnect,HTMLElement),R=x(e,e.dataset.voiceChat,HTMLElement,\"chat-list\"),u=x(e,e.dataset.voiceStartGuided,HTMLButtonElement,\"start-guided\"),O=x(e,e.dataset.voiceStartGeneral,HTMLButtonElement,\"start-general\"),U=x(e,e.dataset.voiceStop,HTMLButtonElement,\"stop-mic\"),s=x(e,e.dataset.voiceMonitor,HTMLElement,\"voice-monitor\"),S=x(e,e.dataset.voiceMonitorCopy,HTMLElement,\"voice-monitor-copy\"),L=x(e,e.dataset.voiceWaveGlow,SVGPathElement,\"voice-wave-glow\"),X=x(e,e.dataset.voiceWavePath,SVGPathElement,\"voice-wave-path\"),_=null,W={general:!1,guided:!1},P=!1,$=null,N=v(),A=null,f=null,E=m(n,{capture:{onAudio:(T,G)=>{if(A){A.sendAudio(T);return}G(T)},onLevel:(T)=>{A?.handleLevel(T),N=be(N,T),F()}},connection:{reconnectReportPath:c},preset:\"guided-intake\"}),V=m(t,{capture:{onAudio:(T,G)=>{if(f){f.sendAudio(T);return}G(T)},onLevel:(T)=>{f?.handleLevel(T),N=be(N,T),F()}},connection:{reconnectReportPath:c},preset:\"dictation\"}),Y=E.bindHTMX({element:h}),xe=V.bindHTMX({element:h}),J=j(E),Q=j(V);A=oe(E,J,{interruptThreshold:d,monitor:g??void 0}),f=oe(V,Q,{interruptThreshold:d,monitor:g??void 0});let z=()=>_===\"general\"?V:E,Dn=()=>_===\"general\"?Q:J,F=()=>{let T=Ln(N);L.setAttribute(\"d\",T),X.setAttribute(\"d\",T),S.innerHTML=`<span class=\"voice-live-dot\"></span>${P?\"Microphone live\":\"Microphone idle\"}`,S.classList.toggle(\"is-live\",P),s.classList.toggle(\"is-live\",P)},k=()=>{let T=z(),G=(_?W[_]:!1)||T.turns.length>0,ae=T.status;if(a.textContent=T.isConnected?\"Connected\":\"Waiting\",M.textContent=$||T.error||\"None\",w)w.textContent=wn(T.reconnect);C.textContent=P?Vn:In,I.textContent=_n({guidedPrompts:o,hasStarted:G,mode:_,status:ae,turnCount:T.turns.length}),u.hidden=P,O.hidden=P,U.hidden=!P,R.innerHTML=`<article class=\"voice-chat-message assistant\">\n <div class=\"voice-chat-role\">${q(_===\"general\"?i:_===\"guided\"?r:\"Voice demo\")}</div>\n <p class=\"voice-turn-text\">${q(bn({generalLabel:i,guidedLabel:r,guidedPrompts:o,hasStarted:G,mode:_,status:ae,turnCount:T.turns.length}))}</p>\n</article>${T.turns.map((p)=>`<div class=\"voice-chat-stack\">\n <article class=\"voice-chat-message user\">\n <div class=\"voice-chat-role\">You</div>\n <p class=\"voice-turn-text\">${q(p.text)}</p>\n </article>\n ${p.assistantText?`<article class=\"voice-chat-message assistant\">\n <div class=\"voice-chat-role\">${q(_===\"general\"?i:_===\"guided\"?r:\"Guide\")}</div>\n <p class=\"voice-turn-text\">${q(p.assistantText)}</p>\n </article>`:\"\"}\n</div>`).join(\"\")}${T.partial?`<article class=\"voice-chat-message user pending\">\n <div class=\"voice-chat-role\">Speaking</div>\n <p class=\"voice-turn-text\">${q(T.partial)}</p>\n</article>`:\"\"}`,F()},Oe=()=>{z().stopRecording(),P=!1,$=null,N=v(),k()},le=async(T)=>{_=T,W={...W,[T]:!0};try{await z().startRecording(),$=null,P=!0,k()}catch(G){z().stopRecording(),P=!1,N=v(),$=ie(G),k()}};E.subscribe(()=>{if(E.assistantAudio.length>0)J.start().catch(()=>{});k()}),V.subscribe(()=>{if(V.assistantAudio.length>0)Q.start().catch(()=>{});k()}),u.addEventListener(\"click\",()=>{le(\"guided\")}),O.addEventListener(\"click\",()=>{le(\"general\")}),U.addEventListener(\"click\",()=>{Oe()}),e.addEventListener(\"absolute-voice-simulate-disconnect\",()=>{z().simulateDisconnect()}),window.addEventListener(\"beforeunload\",()=>{E.stopRecording(),V.stopRecording(),A?.close(),f?.close(),J.close(),Q.close(),Y(),xe(),E.close(),V.close()}),k()},Pn=()=>{if(typeof window>\"u\"||typeof document>\"u\")return;let e=Array.from(document.querySelectorAll(\"[data-voice-htmx]\"));for(let n of e)if(n instanceof HTMLElement)En(n)};Pn();export{Pn as initVoiceHTMX};\n";
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export { assertVoicePlatformCoverage, buildVoicePlatformCoverageSummary, createV
|
|
|
31
31
|
export { assertVoiceCompetitiveCoverage, buildVoiceCompetitiveCoverageReport, createVoiceCompetitiveCoverageRoutes, evaluateVoiceCompetitiveCoverage, renderVoiceCompetitiveCoverageHTML, renderVoiceCompetitiveCoverageMarkdown, } from "./competitiveCoverage";
|
|
32
32
|
export type { VoiceCompetitiveCoverageAssertionInput, VoiceCompetitiveCoverageAssertionReport, VoiceCompetitiveCoverageIssue, VoiceCompetitiveCoverageLevel, VoiceCompetitiveCoverageReport, VoiceCompetitiveCoverageReportInput, VoiceCompetitiveCoverageRoutesOptions, VoiceCompetitiveCoverageStatus, VoiceCompetitiveCoverageSummary, VoiceCompetitiveDepthLevel, VoiceCompetitiveEvidence, VoiceCompetitiveSurface, } from "./competitiveCoverage";
|
|
33
33
|
export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertionReport, VoicePlatformCoverageEvidence, VoicePlatformCoverageRoutesOptions, VoicePlatformCoverageStatus, VoicePlatformCoverageSummary, VoicePlatformCoverageSummaryInput, VoicePlatformCoverageSurface, } from "./platformCoverage";
|
|
34
|
-
export { assertVoiceProofTrendEvidence, appendVoiceRealCallProfileRecoveryEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReportFromRealCallProfiles, buildVoiceProofTrendReport, buildVoiceRealCallProfileEvidenceFromTraceEvents, buildVoiceRealCallProfileDefaults, buildVoiceRealCallProfileHistoryReport, buildVoiceRealCallProfileReadinessCheck, buildVoiceRealCallProfileRecoveryJobHistoryCheck, buildVoiceRealCallProfileRecoveryActions, createVoiceInMemoryRealCallProfileRecoveryJobStore, createVoiceRealCallProfileTraceCollector, createVoiceSQLiteRealCallProfileRecoveryJobStore, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, createVoiceRealCallProfileHistoryRoutes, createVoiceRealCallProfileRecoveryActionRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, loadVoiceRealCallProfileEvidenceFromTraceStore, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown, renderVoiceRealCallProfileHistoryHTML, renderVoiceRealCallProfileHistoryMarkdown, runVoiceRealCallProfileRecoveryLoop, resolveVoiceRealCallProfileProviderRoute, } from "./proofTrends";
|
|
34
|
+
export { assertVoiceProofTrendEvidence, appendVoiceRealCallProfileRecoveryEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReportFromRealCallProfiles, buildVoiceProofTrendReport, buildVoiceRealCallProfileEvidenceFromTraceEvents, buildVoiceRealCallProfileEvidenceFromReconnectProofReports, buildVoiceRealCallProfileDefaults, buildVoiceRealCallProfileHistoryReport, buildVoiceRealCallProfileReadinessCheck, buildVoiceRealCallProfileRecoveryJobHistoryCheck, buildVoiceRealCallProfileRecoveryActions, createVoiceInMemoryRealCallProfileRecoveryJobStore, createVoiceRealCallProfileTraceCollector, createVoiceSQLiteRealCallProfileRecoveryJobStore, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, createVoiceRealCallProfileHistoryRoutes, createVoiceRealCallProfileRecoveryActionRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, loadVoiceRealCallProfileEvidenceFromTraceStore, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown, renderVoiceRealCallProfileHistoryHTML, renderVoiceRealCallProfileHistoryMarkdown, runVoiceRealCallProfileRecoveryLoop, resolveVoiceRealCallProfileProviderRoute, } from "./proofTrends";
|
|
35
35
|
export { createVoiceEvidenceAssertion, createVoiceProofAssertion, summarizeVoiceProofAssertions, } from "./proofAssertions";
|
|
36
36
|
export { buildVoiceSessionSnapshot, buildVoiceSessionSnapshotStatus, createVoiceSessionSnapshotRoutes, parseVoiceSessionSnapshot, } from "./sessionSnapshot";
|
|
37
37
|
export { buildVoiceCallDebuggerReport, createVoiceCallDebuggerRoutes, renderVoiceCallDebuggerHTML, resolveLatestVoiceCallDebuggerSessionId, } from "./callDebugger";
|
|
@@ -46,7 +46,7 @@ export { buildVoiceProviderDecisionTraceReport, createVoiceProviderDecisionTrace
|
|
|
46
46
|
export type { VoiceProviderDecisionStatus, VoiceProviderDecisionSurfaceReport, VoiceProviderDecisionTrace, VoiceProviderDecisionTraceInput, VoiceProviderDecisionTraceIssue, VoiceProviderDecisionTraceReport, VoiceProviderDecisionTraceReportOptions, VoiceProviderDecisionTraceRoutesOptions, } from "./providerDecisionTraces";
|
|
47
47
|
export { appendVoiceIOProviderRouterTraceEvent, appendVoiceProviderRouterTraceEvent, buildVoiceIOProviderRouterTraceEvent, buildVoiceProviderRouterTraceEvent, } from "./providerRouterTraces";
|
|
48
48
|
export type { VoiceIOProviderRouterTraceAppendOptions, VoiceIOProviderRouterTraceEventOptions, VoiceProviderRouterTraceAppendOptions, VoiceProviderRouterTraceEventOptions, } from "./providerRouterTraces";
|
|
49
|
-
export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendRealCallProfileEvidence, VoiceProofTrendRealCallProfileReportOptions, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendRuntimeChannelSummary, VoiceProofTrendStatus, VoiceProofTrendSummary, VoiceRealCallProfileDefault, VoiceRealCallProfileDefaultsOptions, VoiceRealCallProfileDefaultsReport, VoiceRealCallProfileHistoryOptions, VoiceRealCallProfileHistoryReport, VoiceRealCallProfileHistoryRoutesOptions, VoiceRealCallProfileProviderRouteOptions, VoiceRealCallProfileReadinessCheckOptions, VoiceRealCallProfileRecoveryActionOptions, VoiceRealCallProfileRecoveryAction, VoiceRealCallProfileRecoveryActionHandler, VoiceRealCallProfileRecoveryActionHandlerInput, VoiceRealCallProfileRecoveryActionId, VoiceRealCallProfileRecoveryJobHistoryCheckOptions, VoiceRealCallProfileRecoveryActionResult, VoiceRealCallProfileRecoveryActionRoutesOptions, VoiceRealCallProfileRecoveryJob, VoiceRealCallProfileRecoveryJobCreateInput, VoiceRealCallProfileRecoveryJobListOptions, VoiceRealCallProfileRecoveryJobStatus, VoiceRealCallProfileRecoveryJobStore, VoiceRealCallProfileRecoveryJobUpdate, VoiceRealCallProfileRecoveryLoopAction, VoiceRealCallProfileRecoveryLoopJob, VoiceRealCallProfileRecoveryLoopJobResult, VoiceRealCallProfileRecoveryLoopOptions, VoiceRealCallProfileRecoveryLoopReport, VoiceRealCallProfileRecoveryLoopStartFailure, VoiceRealCallProfileRecoveryEvidenceOptions, VoiceRealCallProfileRecoveryEvidenceProvider, VoiceRealCallProfileRecoveryEvidenceProviderRole, VoiceRealCallProfileRecoveryEvidenceResult, VoiceSQLiteRealCallProfileRecoveryJobStoreOptions, VoiceRealCallProfileTraceCollector, VoiceRealCallProfileTraceCollectorEvidenceOptions, VoiceRealCallProfileTraceCollectorOptions, VoiceRealCallProfileTraceEvidenceOptions, VoiceRealCallProfileTraceStoreEvidenceOptions, } from "./proofTrends";
|
|
49
|
+
export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendReconnectSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendRealCallProfileEvidence, VoiceProofTrendRealCallProfileReportOptions, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendRuntimeChannelSummary, VoiceProofTrendStatus, VoiceProofTrendSummary, VoiceRealCallProfileDefault, VoiceRealCallProfileDefaultsOptions, VoiceRealCallProfileDefaultsReport, VoiceRealCallProfileHistoryOptions, VoiceRealCallProfileHistoryReport, VoiceRealCallProfileHistoryRoutesOptions, VoiceRealCallProfileProviderRouteOptions, VoiceRealCallProfileReadinessCheckOptions, VoiceRealCallProfileRecoveryActionOptions, VoiceRealCallProfileRecoveryAction, VoiceRealCallProfileRecoveryActionHandler, VoiceRealCallProfileRecoveryActionHandlerInput, VoiceRealCallProfileRecoveryActionId, VoiceRealCallProfileRecoveryJobHistoryCheckOptions, VoiceRealCallProfileRecoveryActionResult, VoiceRealCallProfileRecoveryActionRoutesOptions, VoiceRealCallProfileRecoveryJob, VoiceRealCallProfileRecoveryJobCreateInput, VoiceRealCallProfileRecoveryJobListOptions, VoiceRealCallProfileRecoveryJobStatus, VoiceRealCallProfileRecoveryJobStore, VoiceRealCallProfileRecoveryJobUpdate, VoiceRealCallProfileRecoveryLoopAction, VoiceRealCallProfileRecoveryLoopJob, VoiceRealCallProfileRecoveryLoopJobResult, VoiceRealCallProfileRecoveryLoopOptions, VoiceRealCallProfileRecoveryLoopReport, VoiceRealCallProfileRecoveryLoopStartFailure, VoiceRealCallProfileRecoveryEvidenceOptions, VoiceRealCallProfileRecoveryEvidenceProvider, VoiceRealCallProfileRecoveryEvidenceProviderRole, VoiceRealCallProfileRecoveryEvidenceResult, VoiceSQLiteRealCallProfileRecoveryJobStoreOptions, VoiceRealCallProfileTraceCollector, VoiceRealCallProfileTraceCollectorEvidenceOptions, VoiceRealCallProfileTraceCollectorOptions, VoiceRealCallProfileTraceEvidenceOptions, VoiceRealCallProfileTraceStoreEvidenceOptions, VoiceReconnectRealCallProfileEvidenceOptions, } from "./proofTrends";
|
|
50
50
|
export { assertVoiceSloCalibration, buildVoiceSloCalibrationReport, buildVoiceSloReadinessThresholdReport, createVoiceSloReadinessThresholdOptions, createVoiceSloReadinessThresholdRoutes, createVoiceSloThresholdProfile, createVoiceSloCalibrationRoutes, renderVoiceSloCalibrationMarkdown, renderVoiceSloReadinessThresholdHTML, renderVoiceSloReadinessThresholdMarkdown, } from "./sloCalibration";
|
|
51
51
|
export type { VoiceSloCalibrationMetricKey, VoiceSloCalibrationOptions, VoiceSloCalibrationReport, VoiceSloCalibrationRoutesOptions, VoiceSloCalibrationSample, VoiceSloCalibrationStatus, VoiceSloCalibrationThreshold, VoiceSloCalibrationThresholds, VoiceSloReadinessThresholdReport, VoiceSloReadinessThresholdReportOptions, VoiceSloReadinessThresholdOptions, VoiceSloReadinessThresholdRoutesOptions, VoiceSloThresholdProfile, } from "./sloCalibration";
|
|
52
52
|
export { assertVoiceLiveOpsControlEvidence, assertVoiceLiveOpsEvidence, buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, evaluateVoiceLiveOpsControlEvidence, evaluateVoiceLiveOpsEvidence, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS, } from "./liveOps";
|