@absolutejs/voice 0.0.22-beta.502 → 0.0.22-beta.504
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/index.js
CHANGED
|
@@ -7017,13 +7017,13 @@ var getCampaignWindowMinute = (at, offsetMinutes = 0) => {
|
|
|
7017
7017
|
minuteOfDay: date.getUTCHours() * 60 + date.getUTCMinutes()
|
|
7018
7018
|
};
|
|
7019
7019
|
};
|
|
7020
|
-
var isWithinCampaignTimeWindow = (
|
|
7021
|
-
const { dayOfWeek, minuteOfDay } = getCampaignWindowMinute(at,
|
|
7022
|
-
if (
|
|
7020
|
+
var isWithinCampaignTimeWindow = (window2, at) => {
|
|
7021
|
+
const { dayOfWeek, minuteOfDay } = getCampaignWindowMinute(at, window2.timeZoneOffsetMinutes ?? 0);
|
|
7022
|
+
if (window2.daysOfWeek && !window2.daysOfWeek.includes(dayOfWeek)) {
|
|
7023
7023
|
return false;
|
|
7024
7024
|
}
|
|
7025
|
-
const start = normalizeHour(
|
|
7026
|
-
const end = normalizeHour(
|
|
7025
|
+
const start = normalizeHour(window2.startHour) * 60;
|
|
7026
|
+
const end = normalizeHour(window2.endHour) * 60;
|
|
7027
7027
|
if (start === end) {
|
|
7028
7028
|
return true;
|
|
7029
7029
|
}
|
|
@@ -36781,6 +36781,104 @@ var createVoiceRouteAuth = (options) => {
|
|
|
36781
36781
|
}
|
|
36782
36782
|
});
|
|
36783
36783
|
};
|
|
36784
|
+
// src/client/browserNoiseSuppression.ts
|
|
36785
|
+
var isBrowser = () => typeof window !== "undefined" && typeof window.AudioContext !== "undefined";
|
|
36786
|
+
var applyBrowserNoiseSuppression = async (options) => {
|
|
36787
|
+
if (!isBrowser()) {
|
|
36788
|
+
throw new Error("applyBrowserNoiseSuppression requires a browser environment with AudioContext");
|
|
36789
|
+
}
|
|
36790
|
+
const ownsContext = !options.audioContext;
|
|
36791
|
+
const audioContext = options.audioContext ?? new AudioContext({ sampleRate: 48000 });
|
|
36792
|
+
if (audioContext.state === "suspended") {
|
|
36793
|
+
try {
|
|
36794
|
+
await audioContext.resume();
|
|
36795
|
+
} catch {}
|
|
36796
|
+
}
|
|
36797
|
+
await audioContext.audioWorklet.addModule(options.workletUrl);
|
|
36798
|
+
const source = audioContext.createMediaStreamSource(options.stream);
|
|
36799
|
+
const node = new AudioWorkletNode(audioContext, options.processorName, options.nodeOptions);
|
|
36800
|
+
if (options.initialPort) {
|
|
36801
|
+
node.port.postMessage(options.initialPort);
|
|
36802
|
+
}
|
|
36803
|
+
const destination = audioContext.createMediaStreamDestination();
|
|
36804
|
+
source.connect(node);
|
|
36805
|
+
node.connect(destination);
|
|
36806
|
+
return {
|
|
36807
|
+
node,
|
|
36808
|
+
stop: async () => {
|
|
36809
|
+
try {
|
|
36810
|
+
node.disconnect();
|
|
36811
|
+
} catch {}
|
|
36812
|
+
try {
|
|
36813
|
+
source.disconnect();
|
|
36814
|
+
} catch {}
|
|
36815
|
+
try {
|
|
36816
|
+
destination.disconnect();
|
|
36817
|
+
} catch {}
|
|
36818
|
+
if (ownsContext) {
|
|
36819
|
+
await audioContext.close();
|
|
36820
|
+
}
|
|
36821
|
+
},
|
|
36822
|
+
stream: destination.stream
|
|
36823
|
+
};
|
|
36824
|
+
};
|
|
36825
|
+
var BROWSER_NOISE_SUPPRESSOR_PRESETS = {
|
|
36826
|
+
deepfilternet: (workletUrl) => ({
|
|
36827
|
+
label: "DeepFilterNet",
|
|
36828
|
+
processorName: "deepfilter-suppressor",
|
|
36829
|
+
workletUrl
|
|
36830
|
+
}),
|
|
36831
|
+
rnnoise: (workletUrl) => ({
|
|
36832
|
+
label: "RNNoise",
|
|
36833
|
+
processorName: "rnnoise-processor",
|
|
36834
|
+
workletUrl
|
|
36835
|
+
})
|
|
36836
|
+
};
|
|
36837
|
+
// src/client/htmxAttributes.ts
|
|
36838
|
+
var escapeAttr = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
36839
|
+
var normalizeHxKey = (key) => key.startsWith("hx-") ? key : `hx-${key}`;
|
|
36840
|
+
var buildVoiceHTMXAttributes = (attrs) => {
|
|
36841
|
+
if (!attrs)
|
|
36842
|
+
return "";
|
|
36843
|
+
const out = [];
|
|
36844
|
+
if (attrs.poll && attrs.refreshUrl) {
|
|
36845
|
+
const intervalSec = Math.max(1, Math.round((attrs.pollIntervalMs ?? 5000) / 1000));
|
|
36846
|
+
out.push(`hx-get="${escapeAttr(attrs.refreshUrl)}"`);
|
|
36847
|
+
out.push(`hx-trigger="every ${intervalSec}s"`);
|
|
36848
|
+
out.push(`hx-swap="${escapeAttr(attrs.swap ?? "outerHTML")}"`);
|
|
36849
|
+
if (attrs.target) {
|
|
36850
|
+
out.push(`hx-target="${escapeAttr(attrs.target)}"`);
|
|
36851
|
+
}
|
|
36852
|
+
} else if (attrs.swap || attrs.target) {
|
|
36853
|
+
if (attrs.swap)
|
|
36854
|
+
out.push(`hx-swap="${escapeAttr(attrs.swap)}"`);
|
|
36855
|
+
if (attrs.target)
|
|
36856
|
+
out.push(`hx-target="${escapeAttr(attrs.target)}"`);
|
|
36857
|
+
}
|
|
36858
|
+
for (const [rawKey, value] of Object.entries(attrs.pushAttributes ?? {})) {
|
|
36859
|
+
const key = normalizeHxKey(rawKey);
|
|
36860
|
+
out.push(`${key}="${escapeAttr(value)}"`);
|
|
36861
|
+
}
|
|
36862
|
+
return out.length === 0 ? "" : ` ${out.join(" ")}`;
|
|
36863
|
+
};
|
|
36864
|
+
var FIRST_TAG_RE = /^(\s*)<([a-zA-Z][\w-]*)((?:\s|>|\/))/;
|
|
36865
|
+
var wrapVoiceHTMLWithHTMXPolling = (html, attrs) => {
|
|
36866
|
+
const attrString = buildVoiceHTMXAttributes(attrs);
|
|
36867
|
+
if (!attrString)
|
|
36868
|
+
return html;
|
|
36869
|
+
const match = FIRST_TAG_RE.exec(html);
|
|
36870
|
+
if (!match)
|
|
36871
|
+
return html;
|
|
36872
|
+
const [matched, leading, tag, terminator] = match;
|
|
36873
|
+
const replaced = `${leading}<${tag}${attrString}${terminator}`;
|
|
36874
|
+
return html.replace(matched, replaced);
|
|
36875
|
+
};
|
|
36876
|
+
var wrapVoiceHTMLInHTMXContainer = (html, attrs) => {
|
|
36877
|
+
const tag = attrs.elementTag ?? "div";
|
|
36878
|
+
const classAttr = attrs.className ? ` class="${escapeAttr(attrs.className)}"` : "";
|
|
36879
|
+
const hx = buildVoiceHTMXAttributes(attrs);
|
|
36880
|
+
return `<${tag}${classAttr}${hx}>${html}</${tag}>`;
|
|
36881
|
+
};
|
|
36784
36882
|
// src/client/costDashboard.ts
|
|
36785
36883
|
var padTwo = (value) => String(value).padStart(2, "0");
|
|
36786
36884
|
var formatBucketKey = (epochMs, bucketBy) => {
|
|
@@ -36860,6 +36958,7 @@ var buildVoiceCostDashboardReport = (options) => {
|
|
|
36860
36958
|
windowStartMs: Number.isFinite(minMs) ? minMs : 0
|
|
36861
36959
|
};
|
|
36862
36960
|
};
|
|
36961
|
+
|
|
36863
36962
|
// src/client/liveCallViewer.ts
|
|
36864
36963
|
var EVENT_BUFFER_LIMIT = 200;
|
|
36865
36964
|
var createLiveCallViewer = (options) => {
|
|
@@ -36967,6 +37066,7 @@ var createLiveCallViewer = (options) => {
|
|
|
36967
37066
|
}
|
|
36968
37067
|
};
|
|
36969
37068
|
};
|
|
37069
|
+
|
|
36970
37070
|
// src/client/replayTimeline.ts
|
|
36971
37071
|
var categorize = (entry) => {
|
|
36972
37072
|
const event = entry.event.toLowerCase();
|
|
@@ -37017,6 +37117,276 @@ var buildReplayTimelineReport = (input) => {
|
|
|
37017
37117
|
}
|
|
37018
37118
|
};
|
|
37019
37119
|
};
|
|
37120
|
+
|
|
37121
|
+
// src/client/htmxDashboardRenderers.ts
|
|
37122
|
+
var escapeHtml50 = (text) => text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37123
|
+
var formatUsd = (value, currency = "USD") => new Intl.NumberFormat("en-US", {
|
|
37124
|
+
currency,
|
|
37125
|
+
maximumFractionDigits: 4,
|
|
37126
|
+
minimumFractionDigits: 2,
|
|
37127
|
+
style: "currency"
|
|
37128
|
+
}).format(value);
|
|
37129
|
+
var formatInteger = (value) => new Intl.NumberFormat("en-US").format(value);
|
|
37130
|
+
var formatRelative = (ms) => {
|
|
37131
|
+
const seconds = Math.max(0, Math.floor(ms / 1000));
|
|
37132
|
+
const minutes = Math.floor(seconds / 60);
|
|
37133
|
+
const remaining = seconds % 60;
|
|
37134
|
+
return `${String(minutes).padStart(2, "0")}:${String(remaining).padStart(2, "0")}`;
|
|
37135
|
+
};
|
|
37136
|
+
var polledWrapperAttributes = (attrs) => buildVoiceHTMXAttributes(attrs);
|
|
37137
|
+
var renderCostRow = (bucket, currency, isTotal) => `<tr data-bucket-key="${escapeHtml50(bucket.bucketKey)}" style="${isTotal ? "border-top:2px solid rgba(255,255,255,0.15);font-weight:600;" : ""}">
|
|
37138
|
+
<td style="padding:8px 12px;">${escapeHtml50(bucket.bucketKey)}</td>
|
|
37139
|
+
<td style="padding:8px 12px;text-align:right;">${formatInteger(bucket.callCount)}</td>
|
|
37140
|
+
<td style="padding:8px 12px;text-align:right;">${formatUsd(bucket.llmUsd, currency)}</td>
|
|
37141
|
+
<td style="padding:8px 12px;text-align:right;">${formatUsd(bucket.ttsUsd, currency)}</td>
|
|
37142
|
+
<td style="padding:8px 12px;text-align:right;">${formatUsd(bucket.sttUsd, currency)}</td>
|
|
37143
|
+
<td style="padding:8px 12px;text-align:right;">${formatUsd(bucket.telephonyUsd, currency)}</td>
|
|
37144
|
+
<td style="padding:8px 12px;text-align:right;">${formatUsd(bucket.totalUsd, currency)}</td>
|
|
37145
|
+
</tr>`;
|
|
37146
|
+
var defaultCostDashboard = ({
|
|
37147
|
+
attributes,
|
|
37148
|
+
currency = "USD",
|
|
37149
|
+
emptyMessage = "No cost events in window.",
|
|
37150
|
+
report,
|
|
37151
|
+
title = "Voice cost dashboard"
|
|
37152
|
+
}) => {
|
|
37153
|
+
const body = report.buckets.map((bucket) => renderCostRow(bucket, currency, false)).join("");
|
|
37154
|
+
const total = renderCostRow(report.grandTotal, currency, true);
|
|
37155
|
+
const inner = report.buckets.length === 0 ? `<p style="font-size:13px;opacity:0.7;">${escapeHtml50(emptyMessage)}</p>` : `<table style="border-collapse:collapse;font-size:13px;width:100%;">
|
|
37156
|
+
<thead><tr style="opacity:0.7;text-align:left;">
|
|
37157
|
+
<th style="padding:8px 12px;">Bucket</th>
|
|
37158
|
+
<th style="padding:8px 12px;text-align:right;">Calls</th>
|
|
37159
|
+
<th style="padding:8px 12px;text-align:right;">LLM</th>
|
|
37160
|
+
<th style="padding:8px 12px;text-align:right;">TTS</th>
|
|
37161
|
+
<th style="padding:8px 12px;text-align:right;">STT</th>
|
|
37162
|
+
<th style="padding:8px 12px;text-align:right;">Tel.</th>
|
|
37163
|
+
<th style="padding:8px 12px;text-align:right;">Total</th>
|
|
37164
|
+
</tr></thead><tbody>${body}${total}</tbody></table>`;
|
|
37165
|
+
return `<section aria-label="voice-cost-dashboard" class="absolute-voice-cost-dashboard"${polledWrapperAttributes(attributes)} style="background:#0f172a;border-radius:16px;color:#f8fafc;font-family:ui-sans-serif,system-ui,sans-serif;padding:20px;">
|
|
37166
|
+
<header style="align-items:baseline;display:flex;gap:12px;margin-bottom:12px;">
|
|
37167
|
+
<strong style="font-size:16px;">${escapeHtml50(title)}</strong>
|
|
37168
|
+
<span style="font-size:13px;opacity:0.7;">${report.buckets.length} buckets \xB7 grand total ${formatUsd(report.grandTotal.totalUsd, currency)}</span>
|
|
37169
|
+
</header>
|
|
37170
|
+
${inner}
|
|
37171
|
+
</section>`;
|
|
37172
|
+
};
|
|
37173
|
+
var REPLAY_CATEGORY_COLOR = {
|
|
37174
|
+
agent: "#3b82f6",
|
|
37175
|
+
lifecycle: "#94a3b8",
|
|
37176
|
+
tool: "#f59e0b",
|
|
37177
|
+
user: "#10b981"
|
|
37178
|
+
};
|
|
37179
|
+
var renderReplayEntry = (event, startedAt) => `<li style="align-items:center;border-left:3px solid ${REPLAY_CATEGORY_COLOR[event.category]};display:flex;font-size:13px;gap:12px;padding-left:12px;">
|
|
37180
|
+
<span style="color:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;width:60px;">${formatRelative(event.at - startedAt)}</span>
|
|
37181
|
+
<strong style="font-size:13px;">${escapeHtml50(event.label)}</strong>
|
|
37182
|
+
${event.detail ? `<span style="opacity:0.85;">${escapeHtml50(event.detail)}</span>` : ""}
|
|
37183
|
+
</li>`;
|
|
37184
|
+
var defaultReplayTimeline = ({
|
|
37185
|
+
attributes,
|
|
37186
|
+
emptyMessage = "No timeline events.",
|
|
37187
|
+
report,
|
|
37188
|
+
title
|
|
37189
|
+
}) => {
|
|
37190
|
+
const headline = escapeHtml50(title ?? report.metadata.title ?? "Replay");
|
|
37191
|
+
const items = report.events.map((event) => renderReplayEntry(event, report.startedAt)).join("");
|
|
37192
|
+
const inner = report.events.length === 0 ? `<p style="font-size:13px;opacity:0.7;">${escapeHtml50(emptyMessage)}</p>` : `<ol style="display:flex;flex-direction:column;gap:6px;list-style:none;margin:0;padding:0;">${items}</ol>`;
|
|
37193
|
+
return `<section aria-label="voice-replay-timeline" class="absolute-voice-replay-timeline"${polledWrapperAttributes(attributes)} style="background:#0f172a;border-radius:16px;color:#f8fafc;font-family:ui-sans-serif,system-ui,sans-serif;padding:20px;">
|
|
37194
|
+
<header style="align-items:baseline;display:flex;gap:12px;margin-bottom:12px;">
|
|
37195
|
+
<strong style="font-size:16px;">${headline}</strong>
|
|
37196
|
+
<span style="font-size:13px;opacity:0.7;">${report.events.length} events \xB7 ${report.summary.userTurns} user \xB7 ${report.summary.agentTurns} agent \xB7 ${report.summary.toolCalls} tool</span>
|
|
37197
|
+
</header>
|
|
37198
|
+
${inner}
|
|
37199
|
+
</section>`;
|
|
37200
|
+
};
|
|
37201
|
+
var LIVE_CATEGORY_COLOR = {
|
|
37202
|
+
agent_audio: "#3b82f6",
|
|
37203
|
+
agent_text: "#3b82f6",
|
|
37204
|
+
lifecycle: "#94a3b8",
|
|
37205
|
+
tool: "#f59e0b",
|
|
37206
|
+
transcript: "#10b981"
|
|
37207
|
+
};
|
|
37208
|
+
var renderLiveEntry = (event, firstAt) => `<li style="align-items:center;border-left:3px solid ${LIVE_CATEGORY_COLOR[event.kind] ?? "#94a3b8"};display:flex;font-size:13px;gap:12px;padding-left:12px;">
|
|
37209
|
+
<span style="color:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;width:60px;">${formatRelative(event.at - firstAt)}</span>
|
|
37210
|
+
<strong style="font-size:13px;">${escapeHtml50(event.title)}</strong>
|
|
37211
|
+
${event.detail ? `<span style="opacity:0.85;">${escapeHtml50(event.detail)}</span>` : ""}
|
|
37212
|
+
</li>`;
|
|
37213
|
+
var defaultLiveCallViewer = ({
|
|
37214
|
+
attributes,
|
|
37215
|
+
state,
|
|
37216
|
+
title = "Live call"
|
|
37217
|
+
}) => {
|
|
37218
|
+
const firstAt = state.events[0]?.at ?? Date.now();
|
|
37219
|
+
const items = state.events.map((event) => renderLiveEntry(event, firstAt)).join("");
|
|
37220
|
+
return `<section aria-label="voice-live-call-viewer" class="absolute-voice-live-call-viewer" data-agent-state="${escapeHtml50(state.agentState)}"${polledWrapperAttributes(attributes)} style="background:#0f172a;border-radius:16px;color:#f8fafc;font-family:ui-sans-serif,system-ui,sans-serif;padding:20px;">
|
|
37221
|
+
<header style="align-items:center;display:flex;gap:12px;margin-bottom:12px;">
|
|
37222
|
+
<strong style="font-size:16px;">${escapeHtml50(title)}</strong>
|
|
37223
|
+
<span style="background:rgba(59,130,246,0.18);border-radius:999px;font-size:11px;padding:3px 10px;text-transform:uppercase;">${escapeHtml50(state.agentState)}</span>
|
|
37224
|
+
<span style="font-size:13px;margin-left:auto;opacity:0.7;">${escapeHtml50(state.sessionId)} \xB7 ${formatRelative(state.callDurationMs)}</span>
|
|
37225
|
+
</header>
|
|
37226
|
+
${state.partialTranscript ? `<p style="background:rgba(16,185,129,0.12);border-radius:12px;font-size:13px;margin:0 0 12px;opacity:0.95;padding:10px 12px;">"${escapeHtml50(state.partialTranscript)}"</p>` : ""}
|
|
37227
|
+
<ol style="display:flex;flex-direction:column;gap:6px;list-style:none;margin:0;max-height:320px;overflow-y:auto;padding:0;">${items}</ol>
|
|
37228
|
+
</section>`;
|
|
37229
|
+
};
|
|
37230
|
+
var resolveVoiceDashboardRenderers = (custom) => ({
|
|
37231
|
+
costDashboard: custom?.costDashboard ?? defaultCostDashboard,
|
|
37232
|
+
liveCallViewer: custom?.liveCallViewer ?? defaultLiveCallViewer,
|
|
37233
|
+
replayTimeline: custom?.replayTimeline ?? defaultReplayTimeline
|
|
37234
|
+
});
|
|
37235
|
+
var renderVoiceCostDashboardHTMX = (input) => (input.custom ?? defaultCostDashboard)(input);
|
|
37236
|
+
var renderVoiceReplayTimelineHTMX = (input) => (input.custom ?? defaultReplayTimeline)(input);
|
|
37237
|
+
var renderVoiceLiveCallViewerHTMX = (input) => (input.custom ?? defaultLiveCallViewer)(input);
|
|
37238
|
+
var renderVoiceCostDashboardFromEvents = (input) => {
|
|
37239
|
+
const report = buildVoiceCostDashboardReport({
|
|
37240
|
+
bucketBy: input.options?.bucketBy,
|
|
37241
|
+
events: input.events,
|
|
37242
|
+
fromMs: input.options?.fromMs,
|
|
37243
|
+
toMs: input.options?.toMs
|
|
37244
|
+
});
|
|
37245
|
+
return renderVoiceCostDashboardHTMX({
|
|
37246
|
+
attributes: input.attributes,
|
|
37247
|
+
currency: input.currency,
|
|
37248
|
+
custom: input.renderer,
|
|
37249
|
+
report,
|
|
37250
|
+
title: input.title
|
|
37251
|
+
});
|
|
37252
|
+
};
|
|
37253
|
+
var renderVoiceReplayTimelineFromArtifact = (input) => {
|
|
37254
|
+
const report = buildReplayTimelineReport({ artifact: input.artifact });
|
|
37255
|
+
return renderVoiceReplayTimelineHTMX({
|
|
37256
|
+
attributes: input.attributes,
|
|
37257
|
+
custom: input.renderer,
|
|
37258
|
+
report,
|
|
37259
|
+
title: input.title
|
|
37260
|
+
});
|
|
37261
|
+
};
|
|
37262
|
+
var renderVoiceLiveCallViewerFromViewer = (input) => renderVoiceLiveCallViewerHTMX({
|
|
37263
|
+
attributes: input.attributes,
|
|
37264
|
+
custom: input.renderer,
|
|
37265
|
+
state: input.viewer.getState(),
|
|
37266
|
+
title: input.title
|
|
37267
|
+
});
|
|
37268
|
+
var renderVoiceLiveCallViewerFromState = (input) => renderVoiceLiveCallViewerHTMX({
|
|
37269
|
+
attributes: input.attributes,
|
|
37270
|
+
custom: input.renderer,
|
|
37271
|
+
state: input.state,
|
|
37272
|
+
title: input.title
|
|
37273
|
+
});
|
|
37274
|
+
var createLiveCallViewerFromOptions = createLiveCallViewer;
|
|
37275
|
+
// src/htmxDashboardRoutes.ts
|
|
37276
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
37277
|
+
var HTML_HEADERS = { "content-type": "text/html; charset=utf-8" };
|
|
37278
|
+
var createVoiceCostDashboardHTMXRoute = (options) => {
|
|
37279
|
+
const renderers = resolveVoiceDashboardRenderers(options.render);
|
|
37280
|
+
const path = options.path ?? "/voice/htmx/cost-dashboard";
|
|
37281
|
+
return new Elysia54({ name: options.name ?? "voice-cost-dashboard-htmx" }).get(path, async () => {
|
|
37282
|
+
const events = await Promise.resolve(options.resolveEvents());
|
|
37283
|
+
const attributes = {
|
|
37284
|
+
poll: typeof options.pollIntervalMs === "number",
|
|
37285
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
37286
|
+
refreshUrl: path
|
|
37287
|
+
};
|
|
37288
|
+
const html = renderVoiceCostDashboardFromEvents({
|
|
37289
|
+
attributes,
|
|
37290
|
+
currency: options.currency,
|
|
37291
|
+
events,
|
|
37292
|
+
options: {
|
|
37293
|
+
bucketBy: options.bucketBy,
|
|
37294
|
+
fromMs: options.fromMs?.(),
|
|
37295
|
+
toMs: options.toMs?.()
|
|
37296
|
+
},
|
|
37297
|
+
renderer: renderers.costDashboard,
|
|
37298
|
+
title: options.title
|
|
37299
|
+
});
|
|
37300
|
+
return new Response(html, { headers: HTML_HEADERS });
|
|
37301
|
+
});
|
|
37302
|
+
};
|
|
37303
|
+
var createVoiceReplayTimelineHTMXRoute = (options) => {
|
|
37304
|
+
const renderers = resolveVoiceDashboardRenderers(options.render);
|
|
37305
|
+
const basePath = options.path ?? "/voice/htmx/replay";
|
|
37306
|
+
return new Elysia54({
|
|
37307
|
+
name: options.name ?? "voice-replay-timeline-htmx"
|
|
37308
|
+
}).get(`${basePath}/:artifactId`, async ({ params, set }) => {
|
|
37309
|
+
const { artifactId } = params;
|
|
37310
|
+
const artifact = await Promise.resolve(options.resolveArtifact(artifactId));
|
|
37311
|
+
if (!artifact) {
|
|
37312
|
+
set.status = 404;
|
|
37313
|
+
return new Response(`<div class="absolute-voice-replay-timeline" data-status="not-found" style="background:#0f172a;color:#f8fafc;padding:20px;border-radius:16px;">Replay artifact not found.</div>`, { headers: HTML_HEADERS, status: 404 });
|
|
37314
|
+
}
|
|
37315
|
+
const html = renderVoiceReplayTimelineFromArtifact({
|
|
37316
|
+
artifact,
|
|
37317
|
+
renderer: renderers.replayTimeline,
|
|
37318
|
+
title: options.title
|
|
37319
|
+
});
|
|
37320
|
+
return new Response(html, { headers: HTML_HEADERS });
|
|
37321
|
+
});
|
|
37322
|
+
};
|
|
37323
|
+
var createVoiceLiveCallViewerHTMXRoute = (options) => {
|
|
37324
|
+
const renderers = resolveVoiceDashboardRenderers(options.render);
|
|
37325
|
+
const basePath = options.path ?? "/voice/htmx/live";
|
|
37326
|
+
return new Elysia54({
|
|
37327
|
+
name: options.name ?? "voice-live-call-viewer-htmx"
|
|
37328
|
+
}).get(`${basePath}/:sessionId`, async ({ params, set }) => {
|
|
37329
|
+
const { sessionId } = params;
|
|
37330
|
+
const viewer = await Promise.resolve(options.resolveViewer(sessionId));
|
|
37331
|
+
if (!viewer) {
|
|
37332
|
+
set.status = 404;
|
|
37333
|
+
return new Response(`<div class="absolute-voice-live-call-viewer" data-status="not-found" style="background:#0f172a;color:#f8fafc;padding:20px;border-radius:16px;">No active call for ${sessionId}.</div>`, { headers: HTML_HEADERS, status: 404 });
|
|
37334
|
+
}
|
|
37335
|
+
const attributes = {
|
|
37336
|
+
poll: typeof options.pollIntervalMs === "number",
|
|
37337
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
37338
|
+
refreshUrl: `${basePath}/${sessionId}`
|
|
37339
|
+
};
|
|
37340
|
+
const html = renderVoiceLiveCallViewerFromViewer({
|
|
37341
|
+
attributes,
|
|
37342
|
+
renderer: renderers.liveCallViewer,
|
|
37343
|
+
title: options.title,
|
|
37344
|
+
viewer
|
|
37345
|
+
});
|
|
37346
|
+
return new Response(html, { headers: HTML_HEADERS });
|
|
37347
|
+
});
|
|
37348
|
+
};
|
|
37349
|
+
var createVoiceHTMXDashboardRoutes = (options) => {
|
|
37350
|
+
let app = new Elysia54({ name: options.name ?? "voice-htmx-dashboards" });
|
|
37351
|
+
if (options.cost) {
|
|
37352
|
+
app = app.use(createVoiceCostDashboardHTMXRoute({
|
|
37353
|
+
...options.cost,
|
|
37354
|
+
render: options.render
|
|
37355
|
+
}));
|
|
37356
|
+
}
|
|
37357
|
+
if (options.replay) {
|
|
37358
|
+
app = app.use(createVoiceReplayTimelineHTMXRoute({
|
|
37359
|
+
...options.replay,
|
|
37360
|
+
render: options.render
|
|
37361
|
+
}));
|
|
37362
|
+
}
|
|
37363
|
+
if (options.liveCall) {
|
|
37364
|
+
app = app.use(createVoiceLiveCallViewerHTMXRoute({
|
|
37365
|
+
...options.liveCall,
|
|
37366
|
+
render: options.render
|
|
37367
|
+
}));
|
|
37368
|
+
}
|
|
37369
|
+
return app;
|
|
37370
|
+
};
|
|
37371
|
+
var createVoiceHTMXDashboardRoutesFromStores = (options) => createVoiceHTMXDashboardRoutes({
|
|
37372
|
+
cost: options.traceStore ? {
|
|
37373
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
37374
|
+
resolveEvents: async () => {
|
|
37375
|
+
const events = await options.traceStore.list({
|
|
37376
|
+
type: "cost.ready"
|
|
37377
|
+
});
|
|
37378
|
+
return events;
|
|
37379
|
+
}
|
|
37380
|
+
} : undefined,
|
|
37381
|
+
liveCall: options.liveViewerByCallId ? {
|
|
37382
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
37383
|
+
resolveViewer: options.liveViewerByCallId
|
|
37384
|
+
} : undefined,
|
|
37385
|
+
render: options.render,
|
|
37386
|
+
replay: options.reviewStore ? {
|
|
37387
|
+
resolveArtifact: async (artifactId) => await options.reviewStore.get(artifactId) ?? undefined
|
|
37388
|
+
} : undefined
|
|
37389
|
+
});
|
|
37020
37390
|
// src/retention.ts
|
|
37021
37391
|
var defaultResolveAt = (event) => {
|
|
37022
37392
|
if (!event || typeof event !== "object")
|
|
@@ -37653,10 +38023,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
37653
38023
|
return report;
|
|
37654
38024
|
};
|
|
37655
38025
|
// src/turnLatency.ts
|
|
37656
|
-
import { Elysia as
|
|
38026
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
37657
38027
|
var DEFAULT_WARN_AFTER_MS2 = 1800;
|
|
37658
38028
|
var DEFAULT_FAIL_AFTER_MS2 = 3200;
|
|
37659
|
-
var
|
|
38029
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37660
38030
|
var firstNumber3 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
37661
38031
|
var getString19 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
37662
38032
|
var createTraceStageIndex = (events) => {
|
|
@@ -37792,11 +38162,11 @@ await traceStore.append({
|
|
|
37792
38162
|
turnId,
|
|
37793
38163
|
type: 'turn_latency.stage'
|
|
37794
38164
|
});`;
|
|
37795
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
37796
|
-
<header><div><p class="eyebrow">${
|
|
37797
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
38165
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml51(turn.status)}">
|
|
38166
|
+
<header><div><p class="eyebrow">${escapeHtml51(turn.sessionId)} \xB7 ${escapeHtml51(turn.turnId)}</p><h2>${escapeHtml51(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml51(turn.status)}</strong></header>
|
|
38167
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml51(stage.label)}</dt><dd>${escapeHtml51(formatMs5(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
37798
38168
|
</article>`).join("");
|
|
37799
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38169
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn,.primitive{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(251,191,36,.1))}.eyebrow{color:#5eead4;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2a323a;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}.turn header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{font-weight:900;margin:0}@media(max-width:800px){main{padding:18px}.turn header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">End-to-end responsiveness</p><h1>${escapeHtml51(title)}</h1><div class="summary"><span class="pill ${escapeHtml51(report.status)}">${escapeHtml51(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml51(formatMs5(report.averageTotalMs))}</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTurnLatencyRoutes(...)</code> exposes the full turn waterfall</h2><p>Attach stage traces for speech detection, commit, model response, TTS send, and first audio so teams can prove where latency actually comes from.</p><pre><code>${escapeHtml51(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
37800
38170
|
};
|
|
37801
38171
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
37802
38172
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -37813,7 +38183,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
37813
38183
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
37814
38184
|
const path = options.path ?? "/api/turn-latency";
|
|
37815
38185
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
37816
|
-
const routes = new
|
|
38186
|
+
const routes = new Elysia55({
|
|
37817
38187
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
37818
38188
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
37819
38189
|
if (htmlPath) {
|
|
@@ -37822,8 +38192,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
37822
38192
|
return routes;
|
|
37823
38193
|
};
|
|
37824
38194
|
// src/liveLatency.ts
|
|
37825
|
-
import { Elysia as
|
|
37826
|
-
var
|
|
38195
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
38196
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37827
38197
|
var percentile6 = (values, percentileValue) => {
|
|
37828
38198
|
if (values.length === 0) {
|
|
37829
38199
|
return;
|
|
@@ -37890,13 +38260,13 @@ await traceStore.append({
|
|
|
37890
38260
|
sessionId,
|
|
37891
38261
|
type: 'client.live_latency'
|
|
37892
38262
|
});`;
|
|
37893
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
37894
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38263
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml52(sample.sessionId)}</td><td>${escapeHtml52(formatMs6(sample.latencyMs))}</td><td>${escapeHtml52(sample.status ?? "unknown")}</td><td>${escapeHtml52(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
38264
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml52(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero{background:linear-gradient(135deg,rgba(94,234,212,.16),rgba(245,158,11,.1));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fbbf24}.fail{color:#fca5a5}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.metrics article,table,.primitive{background:#141922;border:1px solid #26313d;border-radius:18px}.metrics article,.primitive{padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem;margin-top:.25rem}.primitive{margin:0 0 18px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#080b10;border:1px solid #26313d;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #26313d;padding:12px;text-align:left}@media(max-width:760px){main{padding:20px}}</style></head><body><main><section class="hero"><p class="eyebrow">Browser proof</p><h1>${escapeHtml52(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml52(report.status)}">Status: ${escapeHtml52(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml52(formatMs6(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml52(formatMs6(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml52(formatMs6(report.averageLatencyMs))}</strong></article><article><span>Samples</span><strong>${String(report.total)}</strong></article></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceLiveLatencyRoutes(...)</code> turns real browser timing into a release gate</h2><p>Persist live timing samples into the trace store so readiness, simulations, and trace timelines all point at the same self-hosted proof.</p><pre><code>${escapeHtml52(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Latency</th><th>Status</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="4">No live latency samples yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
37895
38265
|
};
|
|
37896
38266
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
37897
38267
|
const path = options.path ?? "/api/live-latency";
|
|
37898
38268
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
37899
|
-
const routes = new
|
|
38269
|
+
const routes = new Elysia56({
|
|
37900
38270
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
37901
38271
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
37902
38272
|
if (htmlPath) {
|
|
@@ -37913,9 +38283,9 @@ var createVoiceLiveLatencyRoutes = (options) => {
|
|
|
37913
38283
|
return routes;
|
|
37914
38284
|
};
|
|
37915
38285
|
// src/turnQuality.ts
|
|
37916
|
-
import { Elysia as
|
|
38286
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
37917
38287
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
37918
|
-
var
|
|
38288
|
+
var escapeHtml53 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37919
38289
|
var getTurnLatencyMs = (turn) => {
|
|
37920
38290
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
37921
38291
|
if (firstTranscriptAt === undefined) {
|
|
@@ -37985,24 +38355,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
37985
38355
|
};
|
|
37986
38356
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
37987
38357
|
const title = options.title ?? "Voice Turn Quality";
|
|
37988
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
38358
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml53(turn.status)}">
|
|
37989
38359
|
<div class="turn-header">
|
|
37990
38360
|
<div>
|
|
37991
|
-
<p class="eyebrow">${
|
|
37992
|
-
<h2>${
|
|
38361
|
+
<p class="eyebrow">${escapeHtml53(turn.sessionId)} \xB7 ${escapeHtml53(turn.turnId)}</p>
|
|
38362
|
+
<h2>${escapeHtml53(turn.text || "Empty turn")}</h2>
|
|
37993
38363
|
</div>
|
|
37994
|
-
<strong>${
|
|
38364
|
+
<strong>${escapeHtml53(turn.status)}</strong>
|
|
37995
38365
|
</div>
|
|
37996
38366
|
<dl>
|
|
37997
|
-
<div><dt>Source</dt><dd>${
|
|
38367
|
+
<div><dt>Source</dt><dd>${escapeHtml53(turn.source ?? "unknown")}</dd></div>
|
|
37998
38368
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
37999
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
38000
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
38369
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml53(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
38370
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml53(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
38001
38371
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
38002
38372
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
38003
38373
|
</dl>
|
|
38004
38374
|
</article>`).join("");
|
|
38005
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38375
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(251,191,36,.16),rgba(34,197,94,.1))}.eyebrow{color:#fbbf24;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.turn-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.warn,.unknown{color:#fde68a}.fail{color:#fca5a5}.turn.fail{border-color:rgba(248,113,113,.45)}dl{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.turn-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime STT Debugging</p><h1>${escapeHtml53(title)}</h1><div class="summary"><span class="pill ${escapeHtml53(report.status)}">${escapeHtml53(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${String(report.warnings)} warnings</span><span class="pill">${String(report.failed)} failed</span><span class="pill">${String(report.sessions)} sessions</span></div></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
38006
38376
|
};
|
|
38007
38377
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
38008
38378
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -38019,7 +38389,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
38019
38389
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
38020
38390
|
const path = options.path ?? "/api/turn-quality";
|
|
38021
38391
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
38022
|
-
const routes = new
|
|
38392
|
+
const routes = new Elysia57({
|
|
38023
38393
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
38024
38394
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
38025
38395
|
if (htmlPath) {
|
|
@@ -38028,10 +38398,10 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
38028
38398
|
return routes;
|
|
38029
38399
|
};
|
|
38030
38400
|
// src/phoneAgent.ts
|
|
38031
|
-
import { Elysia as
|
|
38401
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
38032
38402
|
|
|
38033
38403
|
// src/phoneAgentProductionSmoke.ts
|
|
38034
|
-
import { Elysia as
|
|
38404
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
38035
38405
|
var defaultRequirements = [
|
|
38036
38406
|
"media-started",
|
|
38037
38407
|
"transcript",
|
|
@@ -38039,7 +38409,7 @@ var defaultRequirements = [
|
|
|
38039
38409
|
"lifecycle-outcome",
|
|
38040
38410
|
"no-session-error"
|
|
38041
38411
|
];
|
|
38042
|
-
var
|
|
38412
|
+
var escapeHtml54 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
38043
38413
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
38044
38414
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
38045
38415
|
const value = event.payload[key];
|
|
@@ -38148,10 +38518,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
38148
38518
|
});
|
|
38149
38519
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
38150
38520
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
38151
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
38152
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
38153
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
38154
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38521
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml54(issue.requirement)}</strong>: ${escapeHtml54(issue.message)}</li>`).join("");
|
|
38522
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml54(outcome)}</span>`).join("");
|
|
38523
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml54(requirement)}</span>`).join("");
|
|
38524
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml54(title)}</title><style>body{background:#0e141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1050px;padding:32px}.hero,.panel{background:#151d26;border:1px solid #283544;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.metric{background:#0f151d;border:1px solid #283544;border-radius:16px;padding:14px}.metric strong{display:block;font-size:1.8rem}.pill{background:#0f151d;border:1px solid #3f3f46;border-radius:999px;display:inline-flex;margin:4px;padding:7px 10px}.issues{color:#fca5a5}code{color:#fde68a}@media(max-width:720px){main{padding:18px}}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent production smoke</p><h1>${escapeHtml54(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml54(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml54(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml54(report.sessionId)}</code>` : ""}.</p></section><section class="panel"><h2>Observed Trace Evidence</h2><div class="grid"><div class="metric"><span>Media starts</span><strong>${String(report.observed.mediaStarts)}</strong></div><div class="metric"><span>Transcripts</span><strong>${String(report.observed.transcripts)}</strong></div><div class="metric"><span>Assistant responses</span><strong>${String(report.observed.assistantResponses)}</strong></div><div class="metric"><span>Session errors</span><strong>${String(report.observed.sessionErrors)}</strong></div></div><p>${outcomes || '<span class="pill">No lifecycle outcome</span>'}</p></section><section class="panel"><h2>Requirements</h2><p>${requirements}</p>${issues ? `<ul class="issues">${issues}</ul>` : '<p class="pass">All required phone-agent smoke evidence is present.</p>'}</section></main></body></html>`;
|
|
38155
38525
|
};
|
|
38156
38526
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
38157
38527
|
query,
|
|
@@ -38174,7 +38544,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
38174
38544
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
38175
38545
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
38176
38546
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
38177
|
-
const routes = new
|
|
38547
|
+
const routes = new Elysia58({
|
|
38178
38548
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
38179
38549
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
38180
38550
|
if (htmlPath) {
|
|
@@ -38217,7 +38587,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
38217
38587
|
"completed",
|
|
38218
38588
|
"failed"
|
|
38219
38589
|
];
|
|
38220
|
-
var
|
|
38590
|
+
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
38221
38591
|
var loadRouteJson = async (input) => {
|
|
38222
38592
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
38223
38593
|
headers: {
|
|
@@ -38455,10 +38825,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
38455
38825
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
38456
38826
|
const urls = entry?.setup.urls;
|
|
38457
38827
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
38458
|
-
return `<tr><td>${
|
|
38828
|
+
return `<tr><td>${escapeHtml55(carrier.name ?? carrier.provider)}</td><td>${escapeHtml55(carrier.provider)}</td><td><code>${escapeHtml55(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml55(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml55(entry.status)}">${escapeHtml55(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml55(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml55(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml55(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
38459
38829
|
}).join("");
|
|
38460
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
38461
|
-
const snippet =
|
|
38830
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml55(stage)}</code></li>`).join("");
|
|
38831
|
+
const snippet = escapeHtml55(`const phoneAgent = createVoicePhoneAgent({
|
|
38462
38832
|
carriers: [
|
|
38463
38833
|
{
|
|
38464
38834
|
provider: 'twilio',
|
|
@@ -38492,11 +38862,11 @@ app.use(
|
|
|
38492
38862
|
);`);
|
|
38493
38863
|
const checklist = report.carriers.map((carrier) => {
|
|
38494
38864
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
38495
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
38496
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
38497
|
-
return `<article><h3>${
|
|
38865
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml55(issue)}</li>`).join("") ?? "";
|
|
38866
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml55(step)}</li>`).join("") ?? "";
|
|
38867
|
+
return `<article><h3>${escapeHtml55(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
38498
38868
|
}).join("");
|
|
38499
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38869
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(report.title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#365a60}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.warn{color:#fde68a}.muted{color:#aab5c0}table{background:#151d27;border:1px solid #283544;border-collapse:collapse;border-radius:18px;display:block;overflow:auto;width:100%}td,th{border-bottom:1px solid #283544;padding:12px;text-align:left;vertical-align:top}code{color:#fde68a;overflow-wrap:anywhere}.primitive p{color:#cbd5de;line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #283544;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}.checklist{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));margin:18px 0}.checklist article{background:#151d27;border:1px solid #283544;border-radius:18px;padding:18px}.checklist ol{padding-left:20px}.issues{color:#fca5a5}.stages{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));padding-left:18px}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Phone agent setup</p><h1>${escapeHtml55(report.title)}</h1><p>One self-hosted entrypoint for carrier routes, setup reports, smoke checks, and normalized call lifecycle stages.</p><p class="badge ${report.ready ? "pass" : "fail"}">Ready: ${String(report.ready)}</p>${report.matrixPath ? `<p><a href="${escapeHtml55(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoicePhoneAgent(...)</code> builds this carrier control plane</h2><p>Mount carrier routes once, expose setup and smoke proof, then feed the same carrier matrix and phone-agent smoke reports into production readiness so carrier regressions block deploys.</p><pre><code>${snippet}</code></pre></section><h2>Carrier Setup Checklist</h2><section class="checklist">${checklist}</section><h2>Carrier URLs</h2><table><thead><tr><th>Name</th><th>Provider</th><th>Setup</th><th>Smoke</th><th>Status</th><th>Answer/TwiML/TeXML</th><th>Webhook</th><th>Stream</th></tr></thead><tbody>${carrierRows}</tbody></table><h2>Lifecycle Schema</h2><ul class="stages">${stageList}</ul></main></body></html>`;
|
|
38500
38870
|
};
|
|
38501
38871
|
var createVoicePhoneAgent = (options) => {
|
|
38502
38872
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -38505,7 +38875,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
38505
38875
|
setupPath: resolveSetupPath(carrier),
|
|
38506
38876
|
smokePath: resolveSmokePath(carrier)
|
|
38507
38877
|
}));
|
|
38508
|
-
const app = new
|
|
38878
|
+
const app = new Elysia59({
|
|
38509
38879
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
38510
38880
|
});
|
|
38511
38881
|
for (const carrier of options.carriers) {
|
|
@@ -38703,10 +39073,10 @@ var readRecentJsonFiles = async (directory, limit) => {
|
|
|
38703
39073
|
};
|
|
38704
39074
|
const existingRecords = [];
|
|
38705
39075
|
for (let index = 0;index < files.length && existingRecords.length < limit; ) {
|
|
38706
|
-
const
|
|
38707
|
-
const records = await Promise.all(
|
|
39076
|
+
const window2 = files.slice(index, index + limit - existingRecords.length);
|
|
39077
|
+
const records = await Promise.all(window2.map((file) => readRecentFile(file)));
|
|
38708
39078
|
existingRecords.push(...records.filter(isDefined));
|
|
38709
|
-
index +=
|
|
39079
|
+
index += window2.length;
|
|
38710
39080
|
}
|
|
38711
39081
|
if (missingPaths.size > 0) {
|
|
38712
39082
|
await writeRecentJsonFileIndex(directory, (await readRecentJsonFileIndex(directory)).filter((entry) => !missingPaths.has(entry.path)));
|
|
@@ -40314,8 +40684,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
40314
40684
|
};
|
|
40315
40685
|
};
|
|
40316
40686
|
// src/providerCapabilities.ts
|
|
40317
|
-
import { Elysia as
|
|
40318
|
-
var
|
|
40687
|
+
import { Elysia as Elysia60 } from "elysia";
|
|
40688
|
+
var escapeHtml56 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
40319
40689
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
40320
40690
|
configured: true,
|
|
40321
40691
|
features: options.features?.[provider],
|
|
@@ -40380,27 +40750,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
40380
40750
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
40381
40751
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
40382
40752
|
const cards = report.capabilities.map((capability) => {
|
|
40383
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
40384
|
-
return `<article class="card ${
|
|
40753
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml56(feature)}</span>`).join("");
|
|
40754
|
+
return `<article class="card ${escapeHtml56(capability.status)}">
|
|
40385
40755
|
<div class="card-header">
|
|
40386
40756
|
<div>
|
|
40387
|
-
<p class="eyebrow">${
|
|
40388
|
-
<h2>${
|
|
40757
|
+
<p class="eyebrow">${escapeHtml56(capability.kind)}</p>
|
|
40758
|
+
<h2>${escapeHtml56(capability.label ?? capability.provider)}</h2>
|
|
40389
40759
|
</div>
|
|
40390
|
-
<strong>${
|
|
40760
|
+
<strong>${escapeHtml56(capability.status)}</strong>
|
|
40391
40761
|
</div>
|
|
40392
|
-
${capability.description ? `<p>${
|
|
40762
|
+
${capability.description ? `<p>${escapeHtml56(capability.description)}</p>` : ""}
|
|
40393
40763
|
<dl>
|
|
40394
40764
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
40395
40765
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
40396
|
-
<div><dt>Model</dt><dd>${
|
|
40766
|
+
<div><dt>Model</dt><dd>${escapeHtml56(capability.model ?? "default")}</dd></div>
|
|
40397
40767
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
40398
40768
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
40399
40769
|
</dl>
|
|
40400
40770
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
40401
40771
|
</article>`;
|
|
40402
40772
|
}).join("");
|
|
40403
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
40773
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml56(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.16),rgba(34,197,94,.12))}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0 1rem}.summary,.features{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.selected,.healthy{color:#86efac}.unconfigured,.degraded,.rate-limited,.suppressed{color:#fca5a5}.idle,.recoverable{color:#fde68a}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Discovery</p><h1>${escapeHtml56(title)}</h1><div class="summary"><span class="pill">${String(report.configured)} configured</span><span class="pill">${String(report.selected)} selected</span><span class="pill">${String(report.unconfigured)} missing</span><span class="pill">${String(report.total)} total</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider capabilities configured.</p></article>'}</section></main></body></html>`;
|
|
40404
40774
|
};
|
|
40405
40775
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
40406
40776
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -40417,7 +40787,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
40417
40787
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
40418
40788
|
const path = options.path ?? "/api/provider-capabilities";
|
|
40419
40789
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
40420
|
-
const routes = new
|
|
40790
|
+
const routes = new Elysia60({
|
|
40421
40791
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
40422
40792
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
40423
40793
|
if (htmlPath) {
|
|
@@ -40426,7 +40796,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
40426
40796
|
return routes;
|
|
40427
40797
|
};
|
|
40428
40798
|
// src/providerOrchestration.ts
|
|
40429
|
-
import { Elysia as
|
|
40799
|
+
import { Elysia as Elysia61 } from "elysia";
|
|
40430
40800
|
var defaultRequirement = {
|
|
40431
40801
|
minProviders: 1,
|
|
40432
40802
|
requireBudgetPolicy: false,
|
|
@@ -40439,7 +40809,7 @@ var statusRank7 = {
|
|
|
40439
40809
|
warn: 1,
|
|
40440
40810
|
fail: 2
|
|
40441
40811
|
};
|
|
40442
|
-
var
|
|
40812
|
+
var escapeHtml57 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
40443
40813
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
40444
40814
|
var uniqueSorted8 = (values) => [
|
|
40445
40815
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -40582,27 +40952,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
40582
40952
|
};
|
|
40583
40953
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
40584
40954
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
40585
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
40586
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
40955
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml57(surface.status)}">
|
|
40956
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml57(surface.surface)}</p><h2>${escapeHtml57(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml57(surface.status)}</strong></div>
|
|
40587
40957
|
<dl>
|
|
40588
|
-
<div><dt>Providers</dt><dd>${
|
|
40589
|
-
<div><dt>Fallback</dt><dd>${
|
|
40958
|
+
<div><dt>Providers</dt><dd>${escapeHtml57(surface.providers.join(", ") || "none")}</dd></div>
|
|
40959
|
+
<div><dt>Fallback</dt><dd>${escapeHtml57(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
40590
40960
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
40591
40961
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
40592
40962
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
40593
40963
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
40594
40964
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
40595
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
40965
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml57(surface.fallbackMode || "default")}</dd></div>
|
|
40596
40966
|
</dl>
|
|
40597
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
40967
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml57(issue.status)}</strong> ${escapeHtml57(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
40598
40968
|
</article>`).join("");
|
|
40599
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
40969
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml57(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.card{background:#172033;border:1px solid #2d3b55;border-radius:22px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(59,130,246,.18),rgba(20,184,166,.12))}.eyebrow{color:#93c5fd;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f172a;border:1px solid #334155;border-radius:999px;padding:7px 10px}.grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}.card-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.pass strong{color:#86efac}.warn strong{color:#fde68a}.fail strong{color:#fca5a5}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}dt{color:#a8b0b8;font-size:.8rem}dd{margin:0;overflow-wrap:anywhere}li{margin:.35rem 0}@media(max-width:800px){main{padding:18px}.card-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider Policy Proof</p><h1>${escapeHtml57(title)}</h1><div class="summary"><span class="pill">${escapeHtml57(report.profileId)}</span><span class="pill">${escapeHtml57(report.status)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.providers)} providers</span><span class="pill">${String(report.issues.length)} issues</span></div></section><section class="grid">${cards || '<article class="card"><p>No provider orchestration surfaces configured.</p></article>'}</section></main></body></html>`;
|
|
40600
40970
|
};
|
|
40601
40971
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
40602
40972
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
40603
40973
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
40604
40974
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
40605
|
-
const routes = new
|
|
40975
|
+
const routes = new Elysia61({
|
|
40606
40976
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
40607
40977
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
40608
40978
|
if (htmlPath) {
|
|
@@ -40775,8 +41145,8 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
40775
41145
|
return report;
|
|
40776
41146
|
};
|
|
40777
41147
|
// src/voiceMonitoring.ts
|
|
40778
|
-
import { Elysia as
|
|
40779
|
-
var
|
|
41148
|
+
import { Elysia as Elysia62 } from "elysia";
|
|
41149
|
+
var escapeHtml58 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
40780
41150
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
40781
41151
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
40782
41152
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -41029,14 +41399,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
41029
41399
|
};
|
|
41030
41400
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
41031
41401
|
const title = options.title ?? "Voice Monitors";
|
|
41032
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
41033
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
41034
|
-
const snippet =
|
|
41402
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml58(run.label)}</td><td class="${escapeHtml58(run.status)}">${escapeHtml58(run.status)}</td><td>${escapeHtml58(run.severity)}</td><td>${escapeHtml58(String(run.value ?? ""))}</td><td>${escapeHtml58(String(run.threshold ?? ""))}</td><td>${escapeHtml58(run.detail ?? "")}</td></tr>`).join("");
|
|
41403
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml58(issue.label)}</strong> <span class="${escapeHtml58(issue.status)}">${escapeHtml58(issue.status)}</span> ${escapeHtml58(issue.detail ?? "")}</li>`).join("");
|
|
41404
|
+
const snippet = escapeHtml58(`app.use(createVoiceMonitorRoutes({
|
|
41035
41405
|
evidence,
|
|
41036
41406
|
issueStore,
|
|
41037
41407
|
monitors: [defineVoiceMonitor(...)]
|
|
41038
41408
|
}));`);
|
|
41039
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
41409
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml58(title)}</title><style>body{background:#10141b;color:#f8f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#171f2b;border:1px solid #2e3a4b;border-radius:24px;margin-bottom:16px;padding:22px}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);line-height:.92;margin:.2rem 0 1rem}.pill{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;margin-right:8px;padding:8px 12px}.pass{color:#86efac}.warn,.acknowledged{color:#fde68a}.fail,.open{color:#fca5a5}.resolved,.muted{color:#cbd5e1}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3a4b;padding:12px;text-align:left;vertical-align:top}pre{background:#0c1118;border:1px solid #2e3a4b;border-radius:16px;color:#dbeafe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Code-owned monitoring</p><h1>${escapeHtml58(title)}</h1><p class="pill ${escapeHtml58(report.status)}">Status: ${escapeHtml58(report.status)}</p><p class="pill">Open issues: ${String(report.summary.open)}</p><p class="pill">Critical: ${String(report.summary.criticalOpen)}</p></section><section class="card"><h2>Monitor Runs</h2><table><thead><tr><th>Monitor</th><th>Status</th><th>Severity</th><th>Value</th><th>Threshold</th><th>Detail</th></tr></thead><tbody>${runs}</tbody></table></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No monitor issues.</p>'}</section><section class="card"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceMonitorRoutes(...)</code></h2><pre><code>${snippet}</code></pre></section></main></body></html>`;
|
|
41040
41410
|
};
|
|
41041
41411
|
var actorFromRequest = async (request) => {
|
|
41042
41412
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -41060,7 +41430,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
41060
41430
|
monitors: options.monitors,
|
|
41061
41431
|
now: options.now
|
|
41062
41432
|
});
|
|
41063
|
-
const routes = new
|
|
41433
|
+
const routes = new Elysia62({
|
|
41064
41434
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
41065
41435
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
41066
41436
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -41107,7 +41477,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
41107
41477
|
};
|
|
41108
41478
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
41109
41479
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
41110
|
-
return new
|
|
41480
|
+
return new Elysia62({
|
|
41111
41481
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
41112
41482
|
}).get(path, () => ({
|
|
41113
41483
|
isRunning: options.runner.isRunning()
|
|
@@ -41495,8 +41865,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
41495
41865
|
};
|
|
41496
41866
|
};
|
|
41497
41867
|
// src/providerStackRecommendations.ts
|
|
41498
|
-
import { Elysia as
|
|
41499
|
-
var
|
|
41868
|
+
import { Elysia as Elysia63 } from "elysia";
|
|
41869
|
+
var escapeHtml59 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
41500
41870
|
var profileProviderPriorities = {
|
|
41501
41871
|
"meeting-recorder": {
|
|
41502
41872
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -41811,17 +42181,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
41811
42181
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
41812
42182
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
41813
42183
|
const rows = report.rows.map((row) => {
|
|
41814
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
41815
|
-
return `<article class="row ${
|
|
42184
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml59(check.status)}"><strong>${escapeHtml59(check.label)}</strong><span>${escapeHtml59(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml59(check.remediation.href)}">${escapeHtml59(check.remediation.label)}</a>` : escapeHtml59(check.remediation.label)}: ${escapeHtml59(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
42185
|
+
return `<article class="row ${escapeHtml59(row.status)}">
|
|
41816
42186
|
<div>
|
|
41817
|
-
<p class="eyebrow">${
|
|
41818
|
-
<h2>${
|
|
41819
|
-
<p class="status ${
|
|
42187
|
+
<p class="eyebrow">${escapeHtml59(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
42188
|
+
<h2>${escapeHtml59(row.provider)}</h2>
|
|
42189
|
+
<p class="status ${escapeHtml59(row.status)}">${escapeHtml59(row.status.toUpperCase())}</p>
|
|
41820
42190
|
</div>
|
|
41821
42191
|
<ul>${checks}</ul>
|
|
41822
42192
|
</article>`;
|
|
41823
42193
|
}).join("");
|
|
41824
|
-
const snippet =
|
|
42194
|
+
const snippet = escapeHtml59(`const providerContracts = () =>
|
|
41825
42195
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
41826
42196
|
env: process.env,
|
|
41827
42197
|
providers: {
|
|
@@ -41842,7 +42212,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
41842
42212
|
providerContractMatrix: () =>
|
|
41843
42213
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
41844
42214
|
});`);
|
|
41845
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
42215
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml59(title)}</title><style>body{background:#0f1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.primitive,.row{background:#17201b;border:1px solid #2d3b32;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(125,211,252,.12))}.primitive{background:#111814;border-color:#41604a}.eyebrow{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}h2{margin:.2rem 0}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.primitive code{color:#bbf7d0}.primitive p{color:#c8d8ca;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#08110d;border:1px solid #294132;border-radius:18px;color:#d9f99d;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.row.pass,.pass{border-color:rgba(34,197,94,.65)}.status.warn,.row.warn,.warn{border-color:rgba(245,158,11,.7)}.status.fail,.row.fail,.fail{border-color:rgba(239,68,68,.75)}.row{display:grid;gap:20px;grid-template-columns:minmax(180px,.45fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#111814;border:1px solid #2d3b32;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.row li em{color:#f9d77e;font-style:normal}.row li a{color:#86efac}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Provider contracts</p><h1>${escapeHtml59(title)}</h1><p>Self-hosted provider proof for configured state, required env, latency budgets, fallback, streaming, and declared capabilities.</p><div class="summary"><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.warned)} warning</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} total</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderContractMatrixPreset(...)</code> builds this matrix</h2><p>Give AbsoluteJS your configured LLM, STT, and TTS providers once. It turns them into deploy-checkable proof for env, fallback, streaming, latency budgets, selected providers, and profile-required capabilities without a hosted dashboard.</p><pre><code>${snippet}</code></pre></section>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
|
|
41846
42216
|
};
|
|
41847
42217
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
41848
42218
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -41857,7 +42227,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
41857
42227
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
41858
42228
|
const path = options.path ?? "/api/provider-contracts";
|
|
41859
42229
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
41860
|
-
const routes = new
|
|
42230
|
+
const routes = new Elysia63({
|
|
41861
42231
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
41862
42232
|
});
|
|
41863
42233
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -41975,7 +42345,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
41975
42345
|
return assertion;
|
|
41976
42346
|
};
|
|
41977
42347
|
// src/opsConsoleRoutes.ts
|
|
41978
|
-
import { Elysia as
|
|
42348
|
+
import { Elysia as Elysia64 } from "elysia";
|
|
41979
42349
|
var DEFAULT_LINKS = [
|
|
41980
42350
|
{
|
|
41981
42351
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -42010,7 +42380,7 @@ var DEFAULT_LINKS = [
|
|
|
42010
42380
|
label: "Handoffs"
|
|
42011
42381
|
}
|
|
42012
42382
|
];
|
|
42013
|
-
var
|
|
42383
|
+
var escapeHtml60 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
42014
42384
|
var countProviderStatuses = (providers) => {
|
|
42015
42385
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
42016
42386
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -42079,20 +42449,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
42079
42449
|
trace
|
|
42080
42450
|
};
|
|
42081
42451
|
};
|
|
42082
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
42452
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml60(input.label)}</span><strong>${escapeHtml60(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml60(input.status)}">${escapeHtml60(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml60(input.href)}">Open</a>` : ""}</article>`;
|
|
42083
42453
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
42084
42454
|
const links = report.links.map((link) => `<article class="surface">
|
|
42085
|
-
<div><h2>${
|
|
42086
|
-
<p><a href="${
|
|
42455
|
+
<div><h2>${escapeHtml60(link.label)}</h2>${link.description ? `<p>${escapeHtml60(link.description)}</p>` : ""}</div>
|
|
42456
|
+
<p><a href="${escapeHtml60(link.href)}">Open ${escapeHtml60(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml60(link.statusHref)}">Status</a>` : ""}</p>
|
|
42087
42457
|
</article>`).join("");
|
|
42088
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
42089
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
42458
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml60(session.sessionId)}</td><td>${escapeHtml60(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml60(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
42459
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml60(event.kind)}</td><td>${escapeHtml60(event.provider ?? "unknown")}</td><td>${escapeHtml60(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml60(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
42090
42460
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
42091
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
42461
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml60(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#101316;color:#f6f2e8;margin:0}main{max-width:1180px;margin:auto;padding:32px}a{color:#fbbf24}header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;margin-bottom:24px}.eyebrow{color:#fbbf24;font-weight:800;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.5rem);line-height:.95;margin:.2rem 0 1rem}.muted{color:#a8b0b8}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.metric,.surface{background:#181d22;border:1px solid #2a323a;border-radius:20px;padding:18px}.metric strong{display:block;font-size:2.2rem;margin:.25rem 0}.pass,.healthy{color:#86efac}.fail,.failed,.degraded{color:#fca5a5}.surfaces{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:24px 0}table{width:100%;border-collapse:collapse;background:#181d22;border-radius:16px;overflow:hidden;margin:12px 0 28px}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left}section{margin-top:30px}@media(max-width:700px){main{padding:20px}header{display:block}}</style></head><body><main><header><div><p class="eyebrow">Self-hosted voice operations</p><h1>${escapeHtml60(title)}</h1><p class="muted">One deployable control plane for quality gates, failover, traces, sessions, handoffs, and provider health.</p></div><p class="muted">Checked ${escapeHtml60(new Date(report.checkedAt).toLocaleString())}</p></header><div class="grid">${renderMetricCard({ label: "Quality", value: report.quality.status, status: report.quality.status, href: "/quality" })}${renderMetricCard({ label: "Events", value: report.eventCount, href: "/diagnostics" })}${renderMetricCard({ label: "Sessions", value: report.sessions.total, status: report.sessions.failed > 0 ? "failed" : "healthy", href: "/sessions" })}${renderMetricCard({ label: "Handoffs failed", value: report.handoffs.failed, status: report.handoffs.failed > 0 ? "failed" : "healthy", href: "/handoffs" })}${renderMetricCard({ label: "Providers degraded", value: report.providers.degraded, status: report.providers.degraded > 0 ? "degraded" : "healthy", href: "/resilience" })}</div><section><h2>Operational Surfaces</h2><div class="surfaces">${links}</div></section><section><h2>Recent Sessions</h2><table><thead><tr><th>Session</th><th>Status</th><th>Turns</th><th>Errors</th><th>Replay</th></tr></thead><tbody>${sessions}</tbody></table></section><section><h2>Recent Provider Routing</h2><table><thead><tr><th>Kind</th><th>Provider</th><th>Status</th><th>Elapsed</th><th>Session</th></tr></thead><tbody>${routing}</tbody></table></section></main></body></html>`;
|
|
42092
42462
|
};
|
|
42093
42463
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
42094
42464
|
const path = options.path ?? "/ops-console";
|
|
42095
|
-
const routes = new
|
|
42465
|
+
const routes = new Elysia64({
|
|
42096
42466
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
42097
42467
|
});
|
|
42098
42468
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -42109,7 +42479,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
42109
42479
|
return routes;
|
|
42110
42480
|
};
|
|
42111
42481
|
// src/incidentBundle.ts
|
|
42112
|
-
import { Elysia as
|
|
42482
|
+
import { Elysia as Elysia65 } from "elysia";
|
|
42113
42483
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
42114
42484
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
42115
42485
|
return false;
|
|
@@ -42326,7 +42696,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
42326
42696
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
42327
42697
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
42328
42698
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
42329
|
-
const routes = new
|
|
42699
|
+
const routes = new Elysia65({
|
|
42330
42700
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
42331
42701
|
});
|
|
42332
42702
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -42527,19 +42897,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
42527
42897
|
};
|
|
42528
42898
|
};
|
|
42529
42899
|
// src/opsStatusRoutes.ts
|
|
42530
|
-
import { Elysia as
|
|
42531
|
-
var
|
|
42900
|
+
import { Elysia as Elysia66 } from "elysia";
|
|
42901
|
+
var escapeHtml61 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
42532
42902
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
42533
42903
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
42534
42904
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
42535
42905
|
const value = "recovered" in surface ? surface.total === 0 ? "0 events" : `${surface.recovered}/${surface.total}` : ("auditTotal" in surface) ? `${surface.auditTotal + surface.traceTotal} deliveries` : ("total" in surface) ? `${Math.max(surface.total - ("failed" in surface ? surface.failed : ("degraded" in surface) ? surface.degraded : 0), 0)}/${surface.total}` : surface.status;
|
|
42536
|
-
return `<article class="surface ${
|
|
42906
|
+
return `<article class="surface ${escapeHtml61(surface.status)}"><span>${escapeHtml61(surface.status.toUpperCase())}</span><h2>${escapeHtml61(key)}</h2><strong>${escapeHtml61(value)}</strong></article>`;
|
|
42537
42907
|
}).join("");
|
|
42538
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
42908
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml61(title)}</title><style>body{background:#0d141b;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.2),rgba(245,158,11,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.surfaces{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.surface{background:#151d26;border:1px solid #283544;border-radius:20px;padding:18px}.surface span{color:#aab5c0;font-size:.78rem;font-weight:900;letter-spacing:.08em}.surface strong{font-size:1.5rem}.pass{border-color:rgba(34,197,94,.55)}.fail{border-color:rgba(239,68,68,.75)}a{color:#5eead4}</style></head><body><main><section class="hero"><p class="eyebrow">Ops status</p><h1>${escapeHtml61(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml61(report.status)}">Overall: ${escapeHtml61(report.status.toUpperCase())}</p><p>${report.passed}/${report.total} checks passing</p></section><section class="surfaces">${surfaces || '<article class="surface pass"><span>PASS</span><h2>No checks configured</h2><strong>0/0</strong></article>'}</section></main></body></html>`;
|
|
42539
42909
|
};
|
|
42540
42910
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
42541
42911
|
const path = options.path ?? "/api/voice/ops-status";
|
|
42542
|
-
const routes = new
|
|
42912
|
+
const routes = new Elysia66({
|
|
42543
42913
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
42544
42914
|
});
|
|
42545
42915
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -42972,8 +43342,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
42972
43342
|
};
|
|
42973
43343
|
};
|
|
42974
43344
|
// src/traceDeliveryRoutes.ts
|
|
42975
|
-
import { Elysia as
|
|
42976
|
-
var
|
|
43345
|
+
import { Elysia as Elysia67 } from "elysia";
|
|
43346
|
+
var escapeHtml62 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
42977
43347
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
42978
43348
|
var getNumber12 = (value) => {
|
|
42979
43349
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -43054,14 +43424,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
43054
43424
|
if (entries.length === 0) {
|
|
43055
43425
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
43056
43426
|
}
|
|
43057
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
43427
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml62(sinkId)}</strong>: ${escapeHtml62(result.status)}${result.deliveredTo ? ` to ${escapeHtml62(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml62(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
43058
43428
|
};
|
|
43059
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
43429
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml62(event.type)} <small>${escapeHtml62(event.id)}</small>${event.sessionId ? ` session=${escapeHtml62(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
43060
43430
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
43061
43431
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
43062
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
43063
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
43064
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
43432
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml62(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
43433
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml62(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml62(delivery.deliveryStatus)}</span><h2>${escapeHtml62(delivery.id)}</h2><p>${escapeHtml62(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml62(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml62(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
43434
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml62(title)}</title><style>body{background:#0f1318;color:#f4efe1;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(14,165,233,.14));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#86efac;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,5vw,4.8rem);line-height:.92;margin:.2rem 0 1rem}.grid{display:grid;gap:12px;grid-template-columns:repeat(4,1fr);margin-bottom:16px}.grid article,.delivery{background:#151b22;border:1px solid #26313d;border-radius:22px;padding:18px}.grid span,.delivery span{color:#86efac;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.grid strong{display:block;font-size:2rem}.deliveries{display:grid;gap:14px}.delivery.failed{border-color:rgba(239,68,68,.75)}.delivery.pending{border-color:rgba(245,158,11,.7)}.delivery.delivered{border-color:rgba(34,197,94,.55)}.delivery.skipped{border-color:rgba(148,163,184,.6)}.head{align-items:start;display:flex;gap:14px;justify-content:space-between}.delivery h2{font-size:1.05rem;margin:.3rem 0;overflow-wrap:anywhere}.delivery h3{margin:1rem 0 .3rem}.delivery p,.delivery li{color:#c8d0d8}.error{color:#fecaca!important}button{background:#86efac;border:0;border-radius:999px;color:#07111f;cursor:pointer;font-weight:900;margin-top:12px;padding:10px 14px}@media(max-width:760px){main{padding:20px}.grid{grid-template-columns:1fr 1fr}.head{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Trace export health</p><h1>${escapeHtml62(title)}</h1><p>Checked ${escapeHtml62(new Date(report.checkedAt).toLocaleString())}. Showing ${String(report.deliveries.length)} delivery item(s).</p>${drainAction}</section>${renderMetricGrid3(report)}<section class="deliveries">${rows || "<p>No trace deliveries match this filter.</p>"}</section></main></body></html>`;
|
|
43065
43435
|
};
|
|
43066
43436
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
43067
43437
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -43081,7 +43451,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
43081
43451
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
43082
43452
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
43083
43453
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
43084
|
-
const routes = new
|
|
43454
|
+
const routes = new Elysia67({
|
|
43085
43455
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
43086
43456
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
43087
43457
|
if (htmlPath !== false) {
|
|
@@ -43234,7 +43604,7 @@ var createVoiceMemoryStore = () => {
|
|
|
43234
43604
|
return { get, getOrCreate, list, remove, set };
|
|
43235
43605
|
};
|
|
43236
43606
|
// src/opsWebhook.ts
|
|
43237
|
-
import { Elysia as
|
|
43607
|
+
import { Elysia as Elysia68 } from "elysia";
|
|
43238
43608
|
var toHex7 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
43239
43609
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
43240
43610
|
const encoder2 = new TextEncoder;
|
|
@@ -43364,7 +43734,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
43364
43734
|
};
|
|
43365
43735
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
43366
43736
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
43367
|
-
return new
|
|
43737
|
+
return new Elysia68().post(path, async ({ body, request, set }) => {
|
|
43368
43738
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
43369
43739
|
if (options.signingSecret) {
|
|
43370
43740
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -43819,7 +44189,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
43819
44189
|
};
|
|
43820
44190
|
};
|
|
43821
44191
|
// src/postCallAnalysis.ts
|
|
43822
|
-
import { Elysia as
|
|
44192
|
+
import { Elysia as Elysia69 } from "elysia";
|
|
43823
44193
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
43824
44194
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
43825
44195
|
var getPathValue3 = (source, path) => {
|
|
@@ -43998,7 +44368,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
43998
44368
|
};
|
|
43999
44369
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
44000
44370
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
44001
|
-
const routes = new
|
|
44371
|
+
const routes = new Elysia69({
|
|
44002
44372
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
44003
44373
|
});
|
|
44004
44374
|
routes.get(path, async ({ query }) => {
|
|
@@ -44023,7 +44393,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
44023
44393
|
return routes;
|
|
44024
44394
|
};
|
|
44025
44395
|
// src/guardrails.ts
|
|
44026
|
-
import { Elysia as
|
|
44396
|
+
import { Elysia as Elysia70 } from "elysia";
|
|
44027
44397
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
44028
44398
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
44029
44399
|
var matchesRule = async (rule, input) => {
|
|
@@ -44325,7 +44695,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
44325
44695
|
};
|
|
44326
44696
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
44327
44697
|
const path = options.path ?? "/api/voice/guardrails";
|
|
44328
|
-
const routes = new
|
|
44698
|
+
const routes = new Elysia70({
|
|
44329
44699
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
44330
44700
|
});
|
|
44331
44701
|
routes.all(path, async ({ request }) => {
|
|
@@ -45104,7 +45474,7 @@ var shapeTelephonyAssistantText = (text, options = {}) => {
|
|
|
45104
45474
|
return ensureTerminalPunctuation(normalizeWhitespace(limitedChars));
|
|
45105
45475
|
};
|
|
45106
45476
|
// src/proofPack.ts
|
|
45107
|
-
import { Elysia as
|
|
45477
|
+
import { Elysia as Elysia71 } from "elysia";
|
|
45108
45478
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
45109
45479
|
import { dirname as dirname3, join as join4 } from "path";
|
|
45110
45480
|
var toGeneratedAt = (value) => value === undefined ? new Date().toISOString() : typeof value === "number" ? new Date(value).toISOString() : value;
|
|
@@ -45690,7 +46060,7 @@ var createVoiceProofPackArtifacts = (input) => [
|
|
|
45690
46060
|
var createVoiceProofPackRoutes = (options) => {
|
|
45691
46061
|
const jsonPath = options.jsonPath ?? "/api/voice/proof-pack";
|
|
45692
46062
|
const markdownPath = options.markdownPath ?? "/voice/proof-pack.md";
|
|
45693
|
-
const app = new
|
|
46063
|
+
const app = new Elysia71({ name: options.name ?? "voice-proof-pack" });
|
|
45694
46064
|
if (jsonPath !== false) {
|
|
45695
46065
|
app.get(jsonPath, async () => new Response(JSON.stringify(await resolveProofPack(options.source), null, 2), {
|
|
45696
46066
|
headers: {
|
|
@@ -46791,7 +47161,7 @@ var buildVoiceMultilingualProofReadinessCheck = (report, options = {}) => {
|
|
|
46791
47161
|
};
|
|
46792
47162
|
};
|
|
46793
47163
|
// src/monitor.ts
|
|
46794
|
-
import { Elysia as
|
|
47164
|
+
import { Elysia as Elysia72 } from "elysia";
|
|
46795
47165
|
var buildAudioFanout = () => {
|
|
46796
47166
|
const handlers = new Set;
|
|
46797
47167
|
return {
|
|
@@ -47080,7 +47450,7 @@ var createVoiceLiveMonitorRoutes = (options) => {
|
|
|
47080
47450
|
transfer: options.controlHandlers?.transfer ?? buildDefaultControlHandler("transfer"),
|
|
47081
47451
|
voicemail: options.controlHandlers?.voicemail ?? buildDefaultControlHandler("voicemail")
|
|
47082
47452
|
};
|
|
47083
|
-
const app = new
|
|
47453
|
+
const app = new Elysia72({ name: "absolutejs-voice-monitor" });
|
|
47084
47454
|
const unsubscribers = new WeakMap;
|
|
47085
47455
|
if (listenPath !== false && listenPath.length > 0) {
|
|
47086
47456
|
app.ws(`/${listenPath.replace(/^\/+/, "")}`, {
|
|
@@ -47253,6 +47623,8 @@ var createVoiceLiveMonitorRoutes = (options) => {
|
|
|
47253
47623
|
export {
|
|
47254
47624
|
writeVoiceProofPack,
|
|
47255
47625
|
writeVoiceMediaPipelineArtifacts,
|
|
47626
|
+
wrapVoiceHTMLWithHTMXPolling,
|
|
47627
|
+
wrapVoiceHTMLInHTMXContainer,
|
|
47256
47628
|
withVoiceOpsTaskId,
|
|
47257
47629
|
withVoiceIntegrationEventId,
|
|
47258
47630
|
voiceTelephonyOutcomeToRouteResult,
|
|
@@ -47352,6 +47724,7 @@ export {
|
|
|
47352
47724
|
resolveVoiceOpsPreset,
|
|
47353
47725
|
resolveVoiceMonitorIssue,
|
|
47354
47726
|
resolveVoiceDiagnosticsTraceFilter,
|
|
47727
|
+
resolveVoiceDashboardRenderers,
|
|
47355
47728
|
resolveVoiceAuditTrailFilter,
|
|
47356
47729
|
resolveVoiceAuditDeliveryFilter,
|
|
47357
47730
|
resolveVoiceAssistantMode,
|
|
@@ -47382,6 +47755,8 @@ export {
|
|
|
47382
47755
|
renderVoiceScenarioFixtureEvalHTML,
|
|
47383
47756
|
renderVoiceScenarioEvalHTML,
|
|
47384
47757
|
renderVoiceResilienceHTML,
|
|
47758
|
+
renderVoiceReplayTimelineHTMX,
|
|
47759
|
+
renderVoiceReplayTimelineFromArtifact,
|
|
47385
47760
|
renderVoiceReconnectContractHTML,
|
|
47386
47761
|
renderVoiceRealtimeProviderContractHTML,
|
|
47387
47762
|
renderVoiceRealtimeChannelMarkdown,
|
|
@@ -47427,6 +47802,9 @@ export {
|
|
|
47427
47802
|
renderVoiceMediaPipelineMarkdown,
|
|
47428
47803
|
renderVoiceMediaPipelineHTML,
|
|
47429
47804
|
renderVoiceLiveLatencyHTML,
|
|
47805
|
+
renderVoiceLiveCallViewerHTMX,
|
|
47806
|
+
renderVoiceLiveCallViewerFromViewer,
|
|
47807
|
+
renderVoiceLiveCallViewerFromState,
|
|
47430
47808
|
renderVoiceLatencySLOMarkdown,
|
|
47431
47809
|
renderVoiceIncidentTimelineMarkdown,
|
|
47432
47810
|
renderVoiceIncidentTimelineHTML,
|
|
@@ -47443,6 +47821,8 @@ export {
|
|
|
47443
47821
|
renderVoiceDeliveryRuntimeHTML,
|
|
47444
47822
|
renderVoiceDataControlMarkdown,
|
|
47445
47823
|
renderVoiceDataControlHTML,
|
|
47824
|
+
renderVoiceCostDashboardHTMX,
|
|
47825
|
+
renderVoiceCostDashboardFromEvents,
|
|
47446
47826
|
renderVoiceCompetitiveCoverageMarkdown,
|
|
47447
47827
|
renderVoiceCompetitiveCoverageHTML,
|
|
47448
47828
|
renderVoiceCampaignsHTML,
|
|
@@ -47676,6 +48056,7 @@ export {
|
|
|
47676
48056
|
createVoiceReviewSavedEvent,
|
|
47677
48057
|
createVoiceRetentionScheduler,
|
|
47678
48058
|
createVoiceResilienceRoutes,
|
|
48059
|
+
createVoiceReplayTimelineHTMXRoute,
|
|
47679
48060
|
createVoiceRedisTelnyxWebhookEventStore,
|
|
47680
48061
|
createVoiceRedisTelephonyWebhookIdempotencyStore,
|
|
47681
48062
|
createVoiceRedisTaskLeaseCoordinator,
|
|
@@ -47800,6 +48181,7 @@ export {
|
|
|
47800
48181
|
createVoiceLiveOpsController,
|
|
47801
48182
|
createVoiceLiveMonitorRoutes,
|
|
47802
48183
|
createVoiceLiveLatencyRoutes,
|
|
48184
|
+
createVoiceLiveCallViewerHTMXRoute,
|
|
47803
48185
|
createVoiceLinearIssueUpdateSink,
|
|
47804
48186
|
createVoiceLinearIssueSyncSinks,
|
|
47805
48187
|
createVoiceLinearIssueSink,
|
|
@@ -47823,6 +48205,8 @@ export {
|
|
|
47823
48205
|
createVoiceHandoffDeliveryWorkerLoop,
|
|
47824
48206
|
createVoiceHandoffDeliveryWorker,
|
|
47825
48207
|
createVoiceHandoffDeliveryRecord,
|
|
48208
|
+
createVoiceHTMXDashboardRoutesFromStores,
|
|
48209
|
+
createVoiceHTMXDashboardRoutes,
|
|
47826
48210
|
createVoiceHMACAuthVerifier,
|
|
47827
48211
|
createVoiceGuardrailRuntime,
|
|
47828
48212
|
createVoiceGuardrailRoutes,
|
|
@@ -47861,6 +48245,7 @@ export {
|
|
|
47861
48245
|
createVoiceDeliveryRuntime,
|
|
47862
48246
|
createVoiceDataControlRoutes,
|
|
47863
48247
|
createVoiceDTMFTool,
|
|
48248
|
+
createVoiceCostDashboardHTMXRoute,
|
|
47864
48249
|
createVoiceCostAccountant,
|
|
47865
48250
|
createVoiceCompetitiveCoverageRoutes,
|
|
47866
48251
|
createVoiceCampaignWorkerLoop,
|
|
@@ -47929,6 +48314,7 @@ export {
|
|
|
47929
48314
|
createMemoryVoiceTelnyxWebhookEventStore,
|
|
47930
48315
|
createMemoryVoiceTelephonyWebhookIdempotencyStore,
|
|
47931
48316
|
createMemoryVoicePlivoWebhookNonceStore,
|
|
48317
|
+
createLiveCallViewerFromOptions,
|
|
47932
48318
|
createLiveCallViewer,
|
|
47933
48319
|
createJSONVoiceAssistantModel,
|
|
47934
48320
|
createInMemoryVoiceCallQuota,
|
|
@@ -48017,6 +48403,7 @@ export {
|
|
|
48017
48403
|
buildVoiceIncidentRecoveryOutcomeReadinessCheck,
|
|
48018
48404
|
buildVoiceIncidentBundle,
|
|
48019
48405
|
buildVoiceIOProviderRouterTraceEvent,
|
|
48406
|
+
buildVoiceHTMXAttributes,
|
|
48020
48407
|
buildVoiceGuardrailReport,
|
|
48021
48408
|
buildVoiceFailureReplay,
|
|
48022
48409
|
buildVoiceDiagnosticsMarkdown,
|
|
@@ -48084,6 +48471,7 @@ export {
|
|
|
48084
48471
|
applyVoiceCampaignTelephonyOutcome,
|
|
48085
48472
|
applyRiskTieredPhraseHintCorrections,
|
|
48086
48473
|
applyPhraseHintCorrections,
|
|
48474
|
+
applyBrowserNoiseSuppression,
|
|
48087
48475
|
appendVoiceRealCallProfileRecoveryEvidence,
|
|
48088
48476
|
appendVoiceProviderRouterTraceEvent,
|
|
48089
48477
|
appendVoiceIOProviderRouterTraceEvent,
|
|
@@ -48097,5 +48485,6 @@ export {
|
|
|
48097
48485
|
DEFAULT_VOICE_REDACTION_PATTERNS,
|
|
48098
48486
|
DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS,
|
|
48099
48487
|
DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS,
|
|
48100
|
-
DEFAULT_VOICE_PRICE_BOOK
|
|
48488
|
+
DEFAULT_VOICE_PRICE_BOOK,
|
|
48489
|
+
BROWSER_NOISE_SUPPRESSOR_PRESETS
|
|
48101
48490
|
};
|