@absolutejs/voice 0.0.22-beta.359 → 0.0.22-beta.360
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.d.ts +2 -2
- package/dist/index.js +674 -521
- package/dist/profileSwitchRecommendation.d.ts +87 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -125,7 +125,7 @@ var conditionAudioChunk = (audio, config) => {
|
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
// src/plugin.ts
|
|
128
|
-
import { Elysia } from "elysia";
|
|
128
|
+
import { Elysia as Elysia2 } from "elysia";
|
|
129
129
|
import { resolve } from "path";
|
|
130
130
|
|
|
131
131
|
// src/htmx.ts
|
|
@@ -5208,6 +5208,9 @@ var createVoiceSession = (options) => {
|
|
|
5208
5208
|
return api;
|
|
5209
5209
|
};
|
|
5210
5210
|
|
|
5211
|
+
// src/profileSwitchRecommendation.ts
|
|
5212
|
+
import { Elysia } from "elysia";
|
|
5213
|
+
|
|
5211
5214
|
// src/audit.ts
|
|
5212
5215
|
var includes = (filter, value) => {
|
|
5213
5216
|
if (!filter) {
|
|
@@ -5374,6 +5377,8 @@ var createVoiceAuditLogger = (store) => ({
|
|
|
5374
5377
|
|
|
5375
5378
|
// src/profileSwitchRecommendation.ts
|
|
5376
5379
|
var readDefaults = (input) => ("defaults" in input) ? input.defaults : input;
|
|
5380
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5381
|
+
var stringifyForHtml = (value) => escapeHtml3(JSON.stringify(value, null, 2) ?? "");
|
|
5377
5382
|
var isNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
5378
5383
|
var exceeds = (observed, budget) => isNumber(observed) && isNumber(budget) && observed > budget;
|
|
5379
5384
|
var scoreProfile = (profile, observed) => {
|
|
@@ -5531,6 +5536,151 @@ var applyVoiceProfileSwitchGuard = async (options) => {
|
|
|
5531
5536
|
}
|
|
5532
5537
|
return decision;
|
|
5533
5538
|
};
|
|
5539
|
+
var resolvePolicyProofDefaults = async (defaults) => typeof defaults === "function" ? await defaults() : defaults;
|
|
5540
|
+
var createDefaultPolicyProofCases = (input) => [
|
|
5541
|
+
{
|
|
5542
|
+
description: "Strong evidence can auto-apply a better measured profile.",
|
|
5543
|
+
expectedAction: "switch",
|
|
5544
|
+
id: "auto-switch",
|
|
5545
|
+
label: "Auto switch",
|
|
5546
|
+
options: { mode: "auto" }
|
|
5547
|
+
},
|
|
5548
|
+
{
|
|
5549
|
+
description: "Recommend mode records the recommendation without changing selection.",
|
|
5550
|
+
expectedAction: "recommend",
|
|
5551
|
+
id: "recommend-only",
|
|
5552
|
+
label: "Recommend only",
|
|
5553
|
+
options: { mode: "recommend" }
|
|
5554
|
+
},
|
|
5555
|
+
{
|
|
5556
|
+
description: "Off mode records that switching is disabled by policy.",
|
|
5557
|
+
expectedAction: "disabled",
|
|
5558
|
+
id: "disabled",
|
|
5559
|
+
label: "Disabled",
|
|
5560
|
+
options: { mode: "off" }
|
|
5561
|
+
},
|
|
5562
|
+
{
|
|
5563
|
+
description: "Allowed-profile policy prevents switching outside scope.",
|
|
5564
|
+
expectedAction: "blocked",
|
|
5565
|
+
expectedBlockedByPolicy: "allowed-profiles",
|
|
5566
|
+
id: "allowed-policy",
|
|
5567
|
+
label: "Allowed profiles",
|
|
5568
|
+
options: {
|
|
5569
|
+
allowedProfileIds: input.allowedProfileIds.slice(0, 1),
|
|
5570
|
+
mode: "auto"
|
|
5571
|
+
}
|
|
5572
|
+
},
|
|
5573
|
+
{
|
|
5574
|
+
description: "Blocked-profile policy rejects unsafe target profiles.",
|
|
5575
|
+
expectedAction: "blocked",
|
|
5576
|
+
expectedBlockedByPolicy: "blocked-profiles",
|
|
5577
|
+
id: "blocked-policy",
|
|
5578
|
+
label: "Blocked profiles",
|
|
5579
|
+
options: {
|
|
5580
|
+
blockedProfileIds: input.recommendedProfileId ? [input.recommendedProfileId] : input.allowedProfileIds.slice(-1),
|
|
5581
|
+
mode: "auto"
|
|
5582
|
+
}
|
|
5583
|
+
},
|
|
5584
|
+
{
|
|
5585
|
+
description: "Max-switch budget stops repeated automatic changes.",
|
|
5586
|
+
expectedAction: "blocked",
|
|
5587
|
+
expectedBlockedByPolicy: "max-switches",
|
|
5588
|
+
id: "max-switches",
|
|
5589
|
+
label: "Max switches",
|
|
5590
|
+
options: {
|
|
5591
|
+
autoSwitchCount: 1,
|
|
5592
|
+
maxAutoSwitchesPerSession: 1,
|
|
5593
|
+
mode: "auto"
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5596
|
+
];
|
|
5597
|
+
var runVoiceProfileSwitchPolicyProof = async (options) => {
|
|
5598
|
+
const defaultsInput = await resolvePolicyProofDefaults(options.defaults);
|
|
5599
|
+
const defaults = readDefaults(defaultsInput);
|
|
5600
|
+
const allowedProfileIds = options.allowedProfileIds ?? defaults.profiles.map((profile) => profile.profileId);
|
|
5601
|
+
const observed = options.observed ?? {
|
|
5602
|
+
currentProfileId: allowedProfileIds[0],
|
|
5603
|
+
fallbackUsed: true,
|
|
5604
|
+
providerP95Ms: 950,
|
|
5605
|
+
turnWarnings: 3
|
|
5606
|
+
};
|
|
5607
|
+
const baseRecommendation = recommendVoiceProfileSwitch({
|
|
5608
|
+
defaults: defaultsInput,
|
|
5609
|
+
observed
|
|
5610
|
+
});
|
|
5611
|
+
const cases = options.cases ?? createDefaultPolicyProofCases({
|
|
5612
|
+
allowedProfileIds,
|
|
5613
|
+
recommendedProfileId: baseRecommendation.recommendedProfile?.profileId
|
|
5614
|
+
});
|
|
5615
|
+
const results = await Promise.all(cases.map(async (proofCase) => {
|
|
5616
|
+
const caseOptions = proofCase.options ?? {};
|
|
5617
|
+
const decision = await applyVoiceProfileSwitchGuard({
|
|
5618
|
+
actor: options.actor,
|
|
5619
|
+
allowedProfileIds,
|
|
5620
|
+
audit: options.audit,
|
|
5621
|
+
defaults: defaultsInput,
|
|
5622
|
+
maxAutoSwitchesPerSession: 1,
|
|
5623
|
+
metadata: {
|
|
5624
|
+
...options.metadata,
|
|
5625
|
+
caseId: proofCase.id,
|
|
5626
|
+
proof: "profile-switch-policy"
|
|
5627
|
+
},
|
|
5628
|
+
minConfidence: options.minConfidence ?? 0.75,
|
|
5629
|
+
sessionId: `profile-policy-proof-${proofCase.id}`,
|
|
5630
|
+
...caseOptions,
|
|
5631
|
+
observed: caseOptions.observed ?? observed
|
|
5632
|
+
});
|
|
5633
|
+
const ok = (!proofCase.expectedAction || decision.action === proofCase.expectedAction) && (!proofCase.expectedBlockedByPolicy || decision.blockedByPolicy === proofCase.expectedBlockedByPolicy);
|
|
5634
|
+
return {
|
|
5635
|
+
...proofCase,
|
|
5636
|
+
decision,
|
|
5637
|
+
ok
|
|
5638
|
+
};
|
|
5639
|
+
}));
|
|
5640
|
+
return {
|
|
5641
|
+
generatedAt: new Date().toISOString(),
|
|
5642
|
+
ok: results.every((result) => result.ok),
|
|
5643
|
+
observed,
|
|
5644
|
+
results,
|
|
5645
|
+
summary: {
|
|
5646
|
+
failed: results.filter((result) => !result.ok).length,
|
|
5647
|
+
passed: results.filter((result) => result.ok).length,
|
|
5648
|
+
total: results.length
|
|
5649
|
+
}
|
|
5650
|
+
};
|
|
5651
|
+
};
|
|
5652
|
+
var renderVoiceProfileSwitchPolicyProofHTML = (report, options = {}) => {
|
|
5653
|
+
const title = options.title ?? "Voice Profile Switch Policy Proof";
|
|
5654
|
+
const rows = report.results.map((result) => `<tr>
|
|
5655
|
+
<td><strong>${escapeHtml3(result.label ?? result.id)}</strong><p>${escapeHtml3(result.description ?? "")}</p></td>
|
|
5656
|
+
<td>${escapeHtml3(result.expectedAction ?? "n/a")}</td>
|
|
5657
|
+
<td>${escapeHtml3(result.decision.action)}</td>
|
|
5658
|
+
<td>${escapeHtml3(result.decision.selectedProfileId ?? "none")}</td>
|
|
5659
|
+
<td>${escapeHtml3(result.decision.blockedByPolicy ?? "none")}</td>
|
|
5660
|
+
<td>${Math.round(result.decision.confidence * 100)}%</td>
|
|
5661
|
+
<td><span class="status ${result.ok ? "pass" : "fail"}">${result.ok ? "PASS" : "FAIL"}</span></td>
|
|
5662
|
+
</tr>`).join("");
|
|
5663
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml3(title)}</title><style>:root{color-scheme:dark;background:#07110e;color:#e8fff5;font-family:ui-sans-serif,system-ui,sans-serif}body{margin:0;padding:32px;background:radial-gradient(circle at top left,rgba(45,212,191,.2),transparent 34%),#07110e}main{max-width:1120px;margin:0 auto}a{color:#67e8f9}.hero,.card{border:1px solid rgba(148,163,184,.24);border-radius:24px;background:rgba(15,23,42,.72);box-shadow:0 24px 90px rgba(0,0,0,.24);padding:24px;margin-bottom:18px}.metric-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.metric{border:1px solid rgba(148,163,184,.2);border-radius:18px;padding:16px;background:rgba(8,47,73,.34)}.metric span{display:block;color:#9ca3af;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.metric strong{display:block;margin-top:8px;font-size:1.6rem}table{width:100%;border-collapse:collapse;overflow:hidden;border-radius:18px}th,td{padding:14px;text-align:left;border-bottom:1px solid rgba(148,163,184,.18);vertical-align:top}th{color:#a7f3d0;text-transform:uppercase;font-size:.75rem;letter-spacing:.08em}td p{margin:.4rem 0 0;color:#a7b5ae}pre{white-space:pre-wrap;overflow:auto;border-radius:18px;background:#020617;padding:18px;color:#d1fae5}.status{display:inline-flex;border-radius:999px;padding:5px 10px;font-weight:800;font-size:.75rem}.pass{background:rgba(34,197,94,.18);color:#bbf7d0}.fail{background:rgba(239,68,68,.18);color:#fecaca}</style></head><body><main><section class="hero"><p><a href="#raw-report">Raw report</a></p><h1>${escapeHtml3(title)}</h1><p>This page proves profile switching is production-bounded: teams can disable it, run recommend-only, auto-apply with confidence, restrict allowed targets, block unsafe targets, and cap automatic switches per session.</p><div class="metric-grid"><div class="metric"><span>Status</span><strong>${report.ok ? "PASS" : "FAIL"}</strong></div><div class="metric"><span>Cases</span><strong>${report.summary.passed}/${report.summary.total}</strong></div><div class="metric"><span>Generated</span><strong>${escapeHtml3(report.generatedAt)}</strong></div></div></section><section class="card"><h2>Policy Cases</h2><table><thead><tr><th>Case</th><th>Expected</th><th>Actual</th><th>Selected</th><th>Blocked by</th><th>Confidence</th><th>Status</th></tr></thead><tbody>${rows}</tbody></table></section><section class="card" id="raw-report"><h2>Raw Report</h2><pre>${stringifyForHtml(report)}</pre></section></main></body></html>`;
|
|
5664
|
+
};
|
|
5665
|
+
var createVoiceProfileSwitchPolicyProofRoutes = (options) => {
|
|
5666
|
+
const path = options.path ?? "/api/voice/profile-switch-policy-proof";
|
|
5667
|
+
const htmlPath = options.htmlPath === undefined ? "/voice/profile-switch-policy" : options.htmlPath;
|
|
5668
|
+
const routes = new Elysia({
|
|
5669
|
+
name: options.name ?? "absolutejs-voice-profile-switch-policy-proof"
|
|
5670
|
+
}).get(path, async () => runVoiceProfileSwitchPolicyProof(options));
|
|
5671
|
+
if (htmlPath) {
|
|
5672
|
+
routes.get(htmlPath, async () => {
|
|
5673
|
+
const report = await runVoiceProfileSwitchPolicyProof(options);
|
|
5674
|
+
const render = options.render ?? ((input) => renderVoiceProfileSwitchPolicyProofHTML(input, {
|
|
5675
|
+
title: options.title
|
|
5676
|
+
}));
|
|
5677
|
+
return new Response(await render(report), {
|
|
5678
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
5679
|
+
});
|
|
5680
|
+
});
|
|
5681
|
+
}
|
|
5682
|
+
return routes;
|
|
5683
|
+
};
|
|
5534
5684
|
|
|
5535
5685
|
// src/plugin.ts
|
|
5536
5686
|
var resolveQueryScenario = (query) => {
|
|
@@ -5904,9 +6054,9 @@ var voice = (config) => {
|
|
|
5904
6054
|
};
|
|
5905
6055
|
const htmxRoutes = () => {
|
|
5906
6056
|
if (!config.htmx) {
|
|
5907
|
-
return new
|
|
6057
|
+
return new Elysia2;
|
|
5908
6058
|
}
|
|
5909
|
-
return new
|
|
6059
|
+
return new Elysia2().get(htmxRoute, async ({ query }) => {
|
|
5910
6060
|
const sessionId = typeof query.sessionId === "string" && query.sessionId.trim() ? query.sessionId.trim() : undefined;
|
|
5911
6061
|
const session = sessionId ? await config.session.get(sessionId) : undefined;
|
|
5912
6062
|
const result = session?.turns.toReversed().find((turn) => turn.result !== undefined)?.result;
|
|
@@ -5929,7 +6079,7 @@ var voice = (config) => {
|
|
|
5929
6079
|
}
|
|
5930
6080
|
}));
|
|
5931
6081
|
};
|
|
5932
|
-
return new
|
|
6082
|
+
return new Elysia2({ name: "absolutejs-voice" }).ws(config.path, {
|
|
5933
6083
|
close: async (ws, code, reason) => {
|
|
5934
6084
|
const socketState = runtime.socketSessions.get(ws);
|
|
5935
6085
|
if (!socketState) {
|
|
@@ -6044,7 +6194,7 @@ var voice = (config) => {
|
|
|
6044
6194
|
}).use(htmxRoutes());
|
|
6045
6195
|
};
|
|
6046
6196
|
// src/campaign.ts
|
|
6047
|
-
import { Elysia as
|
|
6197
|
+
import { Elysia as Elysia3 } from "elysia";
|
|
6048
6198
|
var createId2 = () => crypto.randomUUID();
|
|
6049
6199
|
var cloneRecord = (record) => ({
|
|
6050
6200
|
attempts: record.attempts.map((attempt) => ({ ...attempt })),
|
|
@@ -7134,7 +7284,7 @@ var assertVoiceCampaignReadinessEvidence = (report, input = {}) => {
|
|
|
7134
7284
|
}
|
|
7135
7285
|
return assertion;
|
|
7136
7286
|
};
|
|
7137
|
-
var
|
|
7287
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7138
7288
|
var getString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
7139
7289
|
var campaignAttemptSessionId = (attempt) => getString(attempt.metadata?.sessionId) ?? getString(attempt.metadata?.voiceSessionId) ?? getString(attempt.metadata?.callSessionId);
|
|
7140
7290
|
var resolveCampaignOperationsRecordHref = (value, input) => {
|
|
@@ -7152,7 +7302,7 @@ var resolveCampaignOperationsRecordHref = (value, input) => {
|
|
|
7152
7302
|
};
|
|
7153
7303
|
var renderVoiceCampaignsHTML = (records, options = {}) => {
|
|
7154
7304
|
const title = options.title ?? "Voice Campaigns";
|
|
7155
|
-
const rows = records.map((record) => `<tr><td>${
|
|
7305
|
+
const rows = records.map((record) => `<tr><td>${escapeHtml4(record.campaign.name)}</td><td>${escapeHtml4(record.campaign.status)}</td><td>${String(record.recipients.length)}</td><td>${String(record.attempts.length)}</td><td>${new Date(record.campaign.updatedAt).toLocaleString()}</td></tr>`).join("");
|
|
7156
7306
|
const summary = summarizeVoiceCampaigns(records);
|
|
7157
7307
|
const attemptRows = records.flatMap((record) => record.attempts.slice(-8).reverse().map((attempt) => {
|
|
7158
7308
|
const recipient = record.recipients.find((item) => item.id === attempt.recipientId);
|
|
@@ -7163,15 +7313,15 @@ var renderVoiceCampaignsHTML = (records, options = {}) => {
|
|
|
7163
7313
|
recipient,
|
|
7164
7314
|
sessionId
|
|
7165
7315
|
});
|
|
7166
|
-
return `<tr><td>${
|
|
7316
|
+
return `<tr><td>${escapeHtml4(record.campaign.name)}</td><td>${escapeHtml4(attempt.status)}</td><td>${escapeHtml4(recipient?.phone ?? attempt.recipientId)}</td><td>${escapeHtml4(sessionId ?? "")}</td><td>${href ? `<a href="${escapeHtml4(href)}">Open operations record</a>` : ""}</td></tr>`;
|
|
7167
7317
|
})).slice(0, 20).join("");
|
|
7168
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
7318
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml4(title)}</title><style>body{background:#111827;color:#f9fafb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero{background:linear-gradient(135deg,rgba(251,146,60,.18),rgba(45,212,191,.12));border:1px solid #334155;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#fdba74;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:18px 0}.grid article,table{background:#172033;border:1px solid #334155;border-radius:18px}.grid article{padding:16px}.grid span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0}table{border-collapse:collapse;margin-top:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #334155;padding:12px;text-align:left}a{color:#fdba74}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted outbound</p><h1>${escapeHtml4(title)}</h1><p>Campaign orchestration, recipients, attempts, retries, and outcomes without a hosted dialer dashboard.</p><section class="grid"><article><span>Campaigns</span><strong>${String(summary.campaigns.total)}</strong></article><article><span>Recipients</span><strong>${String(summary.recipients.total)}</strong></article><article><span>Attempts</span><strong>${String(summary.attempts.total)}</strong></article><article><span>Running</span><strong>${String(summary.campaigns.running)}</strong></article></section></section><table><thead><tr><th>Name</th><th>Status</th><th>Recipients</th><th>Attempts</th><th>Updated</th></tr></thead><tbody>${rows || '<tr><td colspan="5">No campaigns yet.</td></tr>'}</tbody></table><h2>Recent attempts</h2><table><thead><tr><th>Campaign</th><th>Status</th><th>Recipient</th><th>Session</th><th>Debug</th></tr></thead><tbody>${attemptRows || '<tr><td colspan="5">No attempts yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
7169
7319
|
};
|
|
7170
7320
|
var renderVoiceCampaignObservabilityHTML = (report, options = {}) => {
|
|
7171
7321
|
const title = options.title ?? "Voice Campaign Observability";
|
|
7172
|
-
const campaignRows = report.campaigns.map((campaign) => `<tr><td>${
|
|
7173
|
-
const failureRows = report.failureReasons.map((failure) => `<tr><td>${
|
|
7174
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
7322
|
+
const campaignRows = report.campaigns.map((campaign) => `<tr><td>${escapeHtml4(campaign.name)}</td><td>${escapeHtml4(campaign.status)}</td><td>${String(campaign.queueDepth)}</td><td>${String(campaign.activeAttempts)}</td><td>${String(campaign.stuckRecipients + campaign.stuckAttempts)}</td><td>${campaign.lease ? escapeHtml4(campaign.lease.workerId) : "none"}</td></tr>`).join("");
|
|
7323
|
+
const failureRows = report.failureReasons.map((failure) => `<tr><td>${escapeHtml4(failure.reason)}</td><td>${String(failure.count)}</td></tr>`).join("");
|
|
7324
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml4(title)}</title><style>body{background:#0b1220;color:#e5edf7;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(20,184,166,.2),rgba(251,146,60,.14));border:1px solid #334155;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.2rem,5vw,4.6rem);line-height:.95;margin:.2rem 0 1rem}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));margin:18px 0}.card,table{background:#111c2f;border:1px solid #334155;border-radius:18px}.card{padding:16px}.card span{color:#9fb0c5}.card strong{display:block;font-size:2rem;margin:.25rem 0}table{border-collapse:collapse;margin-top:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #334155;padding:12px;text-align:left}.warn{color:#fde68a}.bad{color:#fecaca}</style></head><body><main><section class="hero"><p class="eyebrow">Campaign ops</p><h1>${escapeHtml4(title)}</h1><p>Queue depth, active leases, attempt rates, failure reasons, and stuck work for self-hosted outbound voice.</p><section class="grid"><article class="card"><span>Queued recipients</span><strong>${String(report.queue.queuedRecipients)}</strong></article><article class="card"><span>Active attempts</span><strong>${String(report.queue.activeAttempts)}</strong></article><article class="card"><span>Running campaigns</span><strong>${String(report.queue.runningCampaigns)}</strong></article><article class="card"><span>Active leases</span><strong>${report.leases.known ? String(report.leases.active) : "n/a"}</strong></article><article class="card"><span>Attempts/window</span><strong>${String(report.attemptRate.started)}</strong></article><article class="card"><span>Stuck work</span><strong class="${report.stuck.attempts.length + report.stuck.recipients.length > 0 ? "bad" : ""}">${String(report.stuck.attempts.length + report.stuck.recipients.length)}</strong></article></section></section><h2>Campaigns</h2><table><thead><tr><th>Name</th><th>Status</th><th>Queued</th><th>Active</th><th>Stuck</th><th>Lease</th></tr></thead><tbody>${campaignRows || '<tr><td colspan="6">No campaigns yet.</td></tr>'}</tbody></table><h2>Failure Reasons</h2><table><thead><tr><th>Reason</th><th>Count</th></tr></thead><tbody>${failureRows || '<tr><td colspan="2">No failures recorded.</td></tr>'}</tbody></table></main></body></html>`;
|
|
7175
7325
|
};
|
|
7176
7326
|
var readJsonBody = async (request) => {
|
|
7177
7327
|
const text = await request.text();
|
|
@@ -7181,7 +7331,7 @@ var createVoiceCampaignRoutes = (options) => {
|
|
|
7181
7331
|
const runtime = createVoiceCampaign(options);
|
|
7182
7332
|
const path = options.path ?? "/api/voice/campaigns";
|
|
7183
7333
|
const htmlPath = options.htmlPath === undefined ? "/voice/campaigns" : options.htmlPath;
|
|
7184
|
-
const app = new
|
|
7334
|
+
const app = new Elysia3({ name: options.name ?? "absolutejs-voice-campaigns" }).get(path, async () => ({
|
|
7185
7335
|
campaigns: await runtime.list(),
|
|
7186
7336
|
summary: await runtime.summarize()
|
|
7187
7337
|
})).get(`${path}/observability`, async () => buildVoiceCampaignObservabilityReport(await runtime.list(), options.observability)).get(`${path}/readiness-proof`, () => runVoiceCampaignReadinessProof()).post(path, async ({ request }) => runtime.create(await readJsonBody(request))).get(`${path}/:campaignId`, ({ params }) => runtime.get(params.campaignId)).delete(`${path}/:campaignId`, async ({ params }) => {
|
|
@@ -9015,10 +9165,10 @@ var summarizeVoiceAssistantRuns = async (input) => {
|
|
|
9015
9165
|
};
|
|
9016
9166
|
};
|
|
9017
9167
|
// src/assistantHealth.ts
|
|
9018
|
-
import { Elysia as
|
|
9168
|
+
import { Elysia as Elysia5 } from "elysia";
|
|
9019
9169
|
|
|
9020
9170
|
// src/providerHealth.ts
|
|
9021
|
-
import { Elysia as
|
|
9171
|
+
import { Elysia as Elysia4 } from "elysia";
|
|
9022
9172
|
var getString2 = (value) => typeof value === "string" ? value : undefined;
|
|
9023
9173
|
var getNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
9024
9174
|
var isProviderStatus = (value) => value === "success" || value === "fallback" || value === "error";
|
|
@@ -9159,16 +9309,16 @@ var summarizeVoiceProviderHealth = async (input) => {
|
|
|
9159
9309
|
}
|
|
9160
9310
|
return summaries;
|
|
9161
9311
|
};
|
|
9162
|
-
var
|
|
9312
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9163
9313
|
var renderVoiceProviderHealthHTML = (providers) => providers.length === 0 ? '<p class="voice-provider-empty">No provider status yet.</p>' : [
|
|
9164
9314
|
'<div class="voice-provider-health">',
|
|
9165
9315
|
...providers.map((provider) => {
|
|
9166
9316
|
const suppressionSeconds = typeof provider.suppressionRemainingMs === "number" ? Math.ceil(provider.suppressionRemainingMs / 1000) : undefined;
|
|
9167
9317
|
return [
|
|
9168
|
-
`<article class="voice-provider-card ${
|
|
9318
|
+
`<article class="voice-provider-card ${escapeHtml5(provider.status)}">`,
|
|
9169
9319
|
'<div class="voice-provider-card-header">',
|
|
9170
|
-
`<strong>${
|
|
9171
|
-
`<span>${
|
|
9320
|
+
`<strong>${escapeHtml5(provider.provider)}</strong>`,
|
|
9321
|
+
`<span>${escapeHtml5(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>`,
|
|
9172
9322
|
"</div>",
|
|
9173
9323
|
"<dl>",
|
|
9174
9324
|
`<div><dt>Runs</dt><dd>${String(provider.runCount)}</dd></div>`,
|
|
@@ -9178,7 +9328,7 @@ var renderVoiceProviderHealthHTML = (providers) => providers.length === 0 ? '<p
|
|
|
9178
9328
|
`<div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div>`,
|
|
9179
9329
|
"</dl>",
|
|
9180
9330
|
suppressionSeconds ? `<p>Temporarily suppressed for ${String(suppressionSeconds)}s.</p>` : "",
|
|
9181
|
-
provider.lastError ? `<p>${
|
|
9331
|
+
provider.lastError ? `<p>${escapeHtml5(provider.lastError)}</p>` : "",
|
|
9182
9332
|
"</article>"
|
|
9183
9333
|
].join("");
|
|
9184
9334
|
}),
|
|
@@ -9199,7 +9349,7 @@ var createVoiceProviderHealthHTMLHandler = (options) => async () => {
|
|
|
9199
9349
|
var createVoiceProviderHealthRoutes = (options) => {
|
|
9200
9350
|
const path = options.path ?? "/api/provider-status";
|
|
9201
9351
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
9202
|
-
const routes = new
|
|
9352
|
+
const routes = new Elysia4({
|
|
9203
9353
|
name: options.name ?? "absolutejs-voice-provider-health"
|
|
9204
9354
|
}).get(path, createVoiceProviderHealthJSONHandler(options));
|
|
9205
9355
|
if (htmlPath) {
|
|
@@ -9209,7 +9359,7 @@ var createVoiceProviderHealthRoutes = (options) => {
|
|
|
9209
9359
|
};
|
|
9210
9360
|
|
|
9211
9361
|
// src/assistantHealth.ts
|
|
9212
|
-
var
|
|
9362
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
9213
9363
|
var renderCountMap = (values) => {
|
|
9214
9364
|
const entries = Object.entries(values).sort((left, right) => right[1] - left[1]);
|
|
9215
9365
|
if (entries.length === 0) {
|
|
@@ -9217,7 +9367,7 @@ var renderCountMap = (values) => {
|
|
|
9217
9367
|
}
|
|
9218
9368
|
return [
|
|
9219
9369
|
'<div class="voice-assistant-health-metrics">',
|
|
9220
|
-
...entries.map(([label, value]) => `<div><span>${
|
|
9370
|
+
...entries.map(([label, value]) => `<div><span>${escapeHtml6(label)}</span><strong>${String(value)}</strong></div>`),
|
|
9221
9371
|
"</div>"
|
|
9222
9372
|
].join("");
|
|
9223
9373
|
};
|
|
@@ -9278,11 +9428,11 @@ var renderVoiceAssistantHealthHTML = (summary) => {
|
|
|
9278
9428
|
'<div class="voice-assistant-health-failures">',
|
|
9279
9429
|
...failures.map((failure) => [
|
|
9280
9430
|
"<article>",
|
|
9281
|
-
`<strong>${
|
|
9282
|
-
`<span>${
|
|
9283
|
-
failure.error ? `<p>${
|
|
9284
|
-
`<small>${
|
|
9285
|
-
failure.replayHref ? `<p><a href="${
|
|
9431
|
+
`<strong>${escapeHtml6(failure.provider ?? failure.assistantId ?? failure.type)}</strong>`,
|
|
9432
|
+
`<span>${escapeHtml6(failure.status ?? (failure.rateLimited ? "rate-limited" : "error"))}</span>`,
|
|
9433
|
+
failure.error ? `<p>${escapeHtml6(failure.error)}</p>` : "",
|
|
9434
|
+
`<small>${escapeHtml6(failure.sessionId)}${failure.turnId ? ` / ${escapeHtml6(failure.turnId)}` : ""}</small>`,
|
|
9435
|
+
failure.replayHref ? `<p><a href="${escapeHtml6(failure.replayHref)}">Open replay</a></p>` : "",
|
|
9286
9436
|
"</article>"
|
|
9287
9437
|
].join("")),
|
|
9288
9438
|
"</div>"
|
|
@@ -9306,7 +9456,7 @@ var createVoiceAssistantHealthHTMLHandler = (options) => async () => {
|
|
|
9306
9456
|
var createVoiceAssistantHealthRoutes = (options) => {
|
|
9307
9457
|
const path = options.path ?? "/api/assistant-health";
|
|
9308
9458
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
9309
|
-
const routes = new
|
|
9459
|
+
const routes = new Elysia5({
|
|
9310
9460
|
name: options.name ?? "absolutejs-voice-assistant-health"
|
|
9311
9461
|
}).get(path, createVoiceAssistantHealthJSONHandler(options));
|
|
9312
9462
|
if (htmlPath) {
|
|
@@ -9315,7 +9465,7 @@ var createVoiceAssistantHealthRoutes = (options) => {
|
|
|
9315
9465
|
return routes;
|
|
9316
9466
|
};
|
|
9317
9467
|
// src/auditRoutes.ts
|
|
9318
|
-
import { Elysia as
|
|
9468
|
+
import { Elysia as Elysia6 } from "elysia";
|
|
9319
9469
|
|
|
9320
9470
|
// src/trace.ts
|
|
9321
9471
|
var createVoiceTraceEventId = (event) => [
|
|
@@ -9700,7 +9850,7 @@ var exportVoiceTrace = async (input) => {
|
|
|
9700
9850
|
};
|
|
9701
9851
|
};
|
|
9702
9852
|
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
9703
|
-
var
|
|
9853
|
+
var escapeHtml7 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
9704
9854
|
var formatTraceValue = (value) => {
|
|
9705
9855
|
if (value === undefined || value === null) {
|
|
9706
9856
|
return "";
|
|
@@ -9980,10 +10130,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
9980
10130
|
const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
|
|
9981
10131
|
return [
|
|
9982
10132
|
"<tr>",
|
|
9983
|
-
`<td>${
|
|
9984
|
-
`<td>${
|
|
9985
|
-
`<td>${
|
|
9986
|
-
`<td><code>${
|
|
10133
|
+
`<td>${escapeHtml7(String(offset))}</td>`,
|
|
10134
|
+
`<td>${escapeHtml7(event.type)}</td>`,
|
|
10135
|
+
`<td>${escapeHtml7(event.turnId ?? "")}</td>`,
|
|
10136
|
+
`<td><code>${escapeHtml7(JSON.stringify(event.payload))}</code></td>`,
|
|
9987
10137
|
"</tr>"
|
|
9988
10138
|
].join("");
|
|
9989
10139
|
}).join(`
|
|
@@ -9994,7 +10144,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
9994
10144
|
"<head>",
|
|
9995
10145
|
'<meta charset="utf-8" />',
|
|
9996
10146
|
'<meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
9997
|
-
`<title>${
|
|
10147
|
+
`<title>${escapeHtml7(options.title ?? "Voice Trace")}</title>`,
|
|
9998
10148
|
"<style>",
|
|
9999
10149
|
"body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
|
|
10000
10150
|
"main{max-width:1100px;margin:auto}",
|
|
@@ -10008,7 +10158,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
10008
10158
|
"</style>",
|
|
10009
10159
|
"</head>",
|
|
10010
10160
|
"<body><main>",
|
|
10011
|
-
`<h1>${
|
|
10161
|
+
`<h1>${escapeHtml7(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
|
|
10012
10162
|
`<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
|
|
10013
10163
|
'<section class="summary">',
|
|
10014
10164
|
`<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
|
|
@@ -10022,7 +10172,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
10022
10172
|
eventRows,
|
|
10023
10173
|
"</tbody></table>",
|
|
10024
10174
|
"<h2>Markdown Export</h2>",
|
|
10025
|
-
`<pre>${
|
|
10175
|
+
`<pre>${escapeHtml7(markdown)}</pre>`,
|
|
10026
10176
|
"</main></body></html>"
|
|
10027
10177
|
].join(`
|
|
10028
10178
|
`);
|
|
@@ -10035,7 +10185,7 @@ var buildVoiceTraceReplay = (events, options = {}) => ({
|
|
|
10035
10185
|
});
|
|
10036
10186
|
|
|
10037
10187
|
// src/auditExport.ts
|
|
10038
|
-
var
|
|
10188
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10039
10189
|
var normalizeRedactionKey2 = (key) => key.trim().toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
10040
10190
|
var resolveReplacement2 = (input) => typeof input.options.replacement === "function" ? input.options.replacement({
|
|
10041
10191
|
key: input.key,
|
|
@@ -10153,8 +10303,8 @@ var renderVoiceAuditHTML = (events, options = {}) => {
|
|
|
10153
10303
|
const markdown = renderVoiceAuditMarkdown(events, options);
|
|
10154
10304
|
const renderEvents = options.redact ? redactVoiceAuditEvents(events, options.redact) : events;
|
|
10155
10305
|
const summary = summarizeVoiceAuditTrail(renderEvents);
|
|
10156
|
-
const rows = renderEvents.map((event) => `<tr><td>${
|
|
10157
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
10306
|
+
const rows = renderEvents.map((event) => `<tr><td>${escapeHtml8(new Date(event.at).toISOString())}</td><td>${escapeHtml8(event.type)}</td><td>${escapeHtml8(event.action)}</td><td>${escapeHtml8(event.outcome ?? "")}</td><td><code>${escapeHtml8(JSON.stringify(event.payload ?? {}))}</code></td></tr>`).join("");
|
|
10307
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml8(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}.summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:.75rem;margin:1rem 0}.card{background:white;border:1px solid #ded9cc;border-radius:12px;padding:1rem}table{border-collapse:collapse;width:100%;background:white;border:1px solid #ded9cc}th,td{border-bottom:1px solid #eee8dc;padding:.65rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}pre{background:#181713;color:#f8f7f2;padding:1rem;border-radius:12px;overflow:auto}</style></head><body><main><h1>${escapeHtml8(title)}</h1><section class="summary"><div class="card"><strong>Events</strong><br>${summary.total}</div><div class="card"><strong>Errors</strong><br>${summary.errors}</div><div class="card"><strong>Latest</strong><br>${summary.latestAt ? escapeHtml8(new Date(summary.latestAt).toLocaleString()) : "never"}</div></section><table><thead><tr><th>At</th><th>Type</th><th>Action</th><th>Outcome</th><th>Payload</th></tr></thead><tbody>${rows}</tbody></table><h2>Markdown Export</h2><pre>${escapeHtml8(markdown)}</pre></main></body></html>`;
|
|
10158
10308
|
};
|
|
10159
10309
|
var buildVoiceAuditExport = (events, options = {}) => {
|
|
10160
10310
|
const exportEvents = options.redact ? redactVoiceAuditEvents(events, options.redact) : events;
|
|
@@ -10167,7 +10317,7 @@ var buildVoiceAuditExport = (events, options = {}) => {
|
|
|
10167
10317
|
};
|
|
10168
10318
|
|
|
10169
10319
|
// src/auditRoutes.ts
|
|
10170
|
-
var
|
|
10320
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10171
10321
|
var getString4 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
10172
10322
|
var getNumber2 = (value) => {
|
|
10173
10323
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -10265,21 +10415,21 @@ var buildVoiceAuditTrailReport = async (options) => {
|
|
|
10265
10415
|
};
|
|
10266
10416
|
var renderVoiceAuditTrailHTML = (report, options = {}) => {
|
|
10267
10417
|
const title = options.title ?? "AbsoluteJS Voice Audit Trail";
|
|
10268
|
-
const chips = report.summary.byType.map(([type, count]) => `<span>${
|
|
10418
|
+
const chips = report.summary.byType.map(([type, count]) => `<span>${escapeHtml9(type)} <strong>${count}</strong></span>`).join("");
|
|
10269
10419
|
const rows = report.events.map((event) => {
|
|
10270
10420
|
const actor = event.actor ? `${event.actor.kind}:${event.actor.id}` : "unknown";
|
|
10271
10421
|
const resource = event.resource ? `${event.resource.type}${event.resource.id ? `:${event.resource.id}` : ""}` : "";
|
|
10272
10422
|
const payload = event.payload ? JSON.stringify(event.payload, null, 2) : "";
|
|
10273
|
-
return `<article class="event ${
|
|
10423
|
+
return `<article class="event ${escapeHtml9(event.outcome ?? "unknown")}"><div><span>${escapeHtml9(event.type)}</span><h2>${escapeHtml9(event.action)}</h2><p>${escapeHtml9(new Date(event.at).toLocaleString())}</p><p>Actor: ${escapeHtml9(actor)}${resource ? ` \xB7 Resource: ${escapeHtml9(resource)}` : ""}</p>${event.sessionId ? `<p>Session: ${escapeHtml9(event.sessionId)}</p>` : ""}</div><strong>${escapeHtml9(event.outcome ?? "recorded")}</strong>${payload ? `<pre>${escapeHtml9(payload)}</pre>` : ""}</article>`;
|
|
10274
10424
|
}).join("");
|
|
10275
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
10425
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml9(title)}</title><style>body{background:#11140f;color:#f7f1df;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,.18),rgba(245,158,11,.12));border:1px solid #2c3327;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#facc15;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}.chips{display:flex;flex-wrap:wrap;gap:10px}.chips span{border:1px solid #46513b;border-radius:999px;padding:8px 12px}.events{display:grid;gap:14px}.event{background:#181d15;border:1px solid #2c3327;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto;padding:18px}.event.error{border-color:rgba(239,68,68,.75)}.event.skipped{border-color:rgba(245,158,11,.7)}.event.success{border-color:rgba(34,197,94,.55)}.event span{color:#facc15;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.event h2{margin:.2rem 0}.event p{color:#c8ccb8;margin:.2rem 0}.event strong{text-transform:uppercase}pre{background:#0c0f0a;border-radius:14px;grid-column:1/-1;overflow:auto;padding:14px;white-space:pre-wrap}@media(max-width:760px){main{padding:20px}.event{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted evidence</p><h1>${escapeHtml9(title)}</h1><p>${report.summary.total} event(s), ${report.summary.errors} error(s). Latest ${report.summary.latestAt ? escapeHtml9(new Date(report.summary.latestAt).toLocaleString()) : "never"}.</p><div class="chips">${chips}</div></section><section class="events">${rows || "<p>No audit events match this filter.</p>"}</section></main></body></html>`;
|
|
10276
10426
|
};
|
|
10277
10427
|
var createVoiceAuditTrailRoutes = (options) => {
|
|
10278
10428
|
const path = options.path ?? "/api/voice-audit";
|
|
10279
10429
|
const htmlPath = options.htmlPath ?? "/audit";
|
|
10280
10430
|
const exportPath = options.exportPath ?? `${path}/export`;
|
|
10281
10431
|
const exportHtmlPath = options.exportHtmlPath ?? (htmlPath === false ? false : `${htmlPath}/export`);
|
|
10282
|
-
const routes = new
|
|
10432
|
+
const routes = new Elysia6({
|
|
10283
10433
|
name: options.name ?? "absolutejs-voice-audit-trail"
|
|
10284
10434
|
});
|
|
10285
10435
|
routes.get(path, async ({ query }) => buildVoiceAuditTrailReport({
|
|
@@ -10799,8 +10949,8 @@ var createVoiceAuditSinkDeliveryWorkerLoop = (options) => {
|
|
|
10799
10949
|
};
|
|
10800
10950
|
};
|
|
10801
10951
|
// src/auditDeliveryRoutes.ts
|
|
10802
|
-
import { Elysia as
|
|
10803
|
-
var
|
|
10952
|
+
import { Elysia as Elysia7 } from "elysia";
|
|
10953
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10804
10954
|
var getString5 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
10805
10955
|
var getNumber3 = (value) => {
|
|
10806
10956
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -10881,14 +11031,14 @@ var renderSinkResults = (delivery) => {
|
|
|
10881
11031
|
if (entries.length === 0) {
|
|
10882
11032
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
10883
11033
|
}
|
|
10884
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
11034
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml10(sinkId)}</strong>: ${escapeHtml10(result.status)}${result.deliveredTo ? ` to ${escapeHtml10(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml10(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
10885
11035
|
};
|
|
10886
|
-
var renderEventList = (delivery) => delivery.events.length === 0 ? "<p>No audit events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
11036
|
+
var renderEventList = (delivery) => delivery.events.length === 0 ? "<p>No audit events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml10(event.type)} ${escapeHtml10(event.action)} <small>${escapeHtml10(event.id)}</small></li>`).join("")}</ul>`;
|
|
10887
11037
|
var renderVoiceAuditDeliveryHTML = (report, options = {}) => {
|
|
10888
11038
|
const title = options.title ?? "AbsoluteJS Voice Audit Deliveries";
|
|
10889
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
10890
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
10891
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
11039
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml10(options.workerPath ?? "/api/voice-audit-deliveries/drain")}"><button type="submit">Drain audit deliveries</button></form>`;
|
|
11040
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml10(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml10(delivery.deliveryStatus)}</span><h2>${escapeHtml10(delivery.id)}</h2><p>${escapeHtml10(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml10(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml10(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults(delivery)}<h3>Events</h3>${renderEventList(delivery)}</article>`).join("");
|
|
11041
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml10(title)}</title><style>body{background:#101418;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(14,165,233,.17),rgba(245,158,11,.13));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#38bdf8;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:#93c5fd;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:#38bdf8;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">Compliance export health</p><h1>${escapeHtml10(title)}</h1><p>Checked ${escapeHtml10(new Date(report.checkedAt).toLocaleString())}. Showing ${String(report.deliveries.length)} delivery item(s).</p>${drainAction}</section>${renderMetricGrid(report)}<section class="deliveries">${rows || "<p>No audit deliveries match this filter.</p>"}</section></main></body></html>`;
|
|
10892
11042
|
};
|
|
10893
11043
|
var createVoiceAuditDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceAuditDeliveryReport(options, resolveVoiceAuditDeliveryFilter(query, options.filter));
|
|
10894
11044
|
var createVoiceAuditDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -10908,7 +11058,7 @@ var createVoiceAuditDeliveryRoutes = (options) => {
|
|
|
10908
11058
|
const path = options.path ?? "/api/voice-audit-deliveries";
|
|
10909
11059
|
const htmlPath = options.htmlPath === undefined ? "/audit/deliveries" : options.htmlPath;
|
|
10910
11060
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
10911
|
-
const routes = new
|
|
11061
|
+
const routes = new Elysia7({
|
|
10912
11062
|
name: options.name ?? "absolutejs-voice-audit-deliveries"
|
|
10913
11063
|
}).get(path, createVoiceAuditDeliveryJSONHandler(options));
|
|
10914
11064
|
if (htmlPath !== false) {
|
|
@@ -10926,8 +11076,8 @@ var createVoiceAuditDeliveryRoutes = (options) => {
|
|
|
10926
11076
|
return routes;
|
|
10927
11077
|
};
|
|
10928
11078
|
// src/bargeInRoutes.ts
|
|
10929
|
-
import { Elysia as
|
|
10930
|
-
var
|
|
11079
|
+
import { Elysia as Elysia8 } from "elysia";
|
|
11080
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
10931
11081
|
var isBargeInPayload = (value) => !!value && typeof value === "object" && typeof value.at === "number" && typeof value.id === "string" && typeof value.reason === "string" && typeof value.status === "string";
|
|
10932
11082
|
var toBargeInEvent = (event) => event.type === "client.barge_in" && isBargeInPayload(event.payload) ? event.payload : undefined;
|
|
10933
11083
|
var summarizeVoiceBargeIn = (events, options = {}) => {
|
|
@@ -10983,14 +11133,14 @@ const bargeInMonitor = createVoiceBargeInMonitor({
|
|
|
10983
11133
|
path: '/api/voice-barge-in',
|
|
10984
11134
|
sessionId
|
|
10985
11135
|
});`;
|
|
10986
|
-
const sessions = report.sessions.length ? report.sessions.map((session) => `<tr><td>${
|
|
10987
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
11136
|
+
const sessions = report.sessions.length ? report.sessions.map((session) => `<tr><td>${escapeHtml11(session.sessionId)}</td><td>${String(session.total)}</td><td>${String(session.passed)}</td><td>${String(session.failed)}</td><td>${String(session.averageLatencyMs ?? 0)}ms</td></tr>`).join("") : '<tr><td colspan="5">No barge-in events yet.</td></tr>';
|
|
11137
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml11(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.warn{color:#fbbf24}.fail{color:#fca5a5}.empty{color:#cbd5e1}.metrics{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:20px 0}.metrics article,.primitive{background:#181f27;border:1px solid #2b3642;border-radius:20px;padding:16px}.metrics span{color:#a8b0b8}.metrics strong{display:block;font-size:2rem}.primitive{margin:0 0 20px}.primitive h2{margin:.2rem 0 .5rem}.primitive p{color:#cbd5e1}.primitive pre{background:#0a0d10;border:1px solid #2b3642;border-radius:16px;color:#d9fff7;overflow:auto;padding:16px}table{background:#181f27;border-collapse:collapse;border-radius:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #2b3642;padding:12px;text-align:left}</style></head><body><main><p class="eyebrow">Interruption quality</p><h1>${escapeHtml11(title)}</h1><p class="status ${escapeHtml11(report.status)}">Status: ${escapeHtml11(report.status)}</p><section class="metrics"><article><span>Interruptions</span><strong>${String(report.total)}</strong></article><article><span>Avg latency</span><strong>${String(report.averageLatencyMs ?? 0)}ms</strong></article><article><span>Passed</span><strong>${String(report.passed)}</strong></article><article><span>Failed</span><strong>${String(report.failed)}</strong></article></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceBargeInRoutes(...)</code> proves interruption quality</h2><p>Use the shared trace store for browser interrupts, readiness gates, trace timelines, and production evidence instead of trusting a black-box hosted dashboard.</p><pre><code>${escapeHtml11(snippet)}</code></pre></section><table><thead><tr><th>Session</th><th>Total</th><th>Passed</th><th>Failed</th><th>Avg latency</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
|
|
10988
11138
|
};
|
|
10989
11139
|
var createVoiceBargeInRoutes = (options) => {
|
|
10990
11140
|
const path = options.path ?? "/api/voice-barge-in";
|
|
10991
11141
|
const htmlPath = options.htmlPath ?? "/barge-in";
|
|
10992
11142
|
const title = options.title ?? "AbsoluteJS Voice Barge-In";
|
|
10993
|
-
const routes = new
|
|
11143
|
+
const routes = new Elysia8({
|
|
10994
11144
|
name: options.name ?? "absolutejs-voice-barge-in"
|
|
10995
11145
|
});
|
|
10996
11146
|
routes.get(path, async () => summarizeVoiceBargeIn(await options.store.list(), {
|
|
@@ -11022,8 +11172,8 @@ var createVoiceBargeInRoutes = (options) => {
|
|
|
11022
11172
|
return routes;
|
|
11023
11173
|
};
|
|
11024
11174
|
// src/reconnectContract.ts
|
|
11025
|
-
import { Elysia as
|
|
11026
|
-
var
|
|
11175
|
+
import { Elysia as Elysia9 } from "elysia";
|
|
11176
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11027
11177
|
var unique = (values) => [...new Set(values)];
|
|
11028
11178
|
var isReconnectPayload = (value) => {
|
|
11029
11179
|
if (!value || typeof value !== "object") {
|
|
@@ -11143,8 +11293,8 @@ var runVoiceReconnectContract = (options) => {
|
|
|
11143
11293
|
};
|
|
11144
11294
|
};
|
|
11145
11295
|
var renderVoiceReconnectContractHTML = (report) => {
|
|
11146
|
-
const issues = report.issues.map((issue) => `<li class="${
|
|
11147
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>Voice Reconnect Contract</title><style>body{background:#0d1117;color:#f8fafc;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,.card{background:#151b23;border:1px solid #30363d;border-radius:18px;margin-bottom:16px;padding:20px}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.25rem,7vw,4.5rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0d1117;border:1px solid #30363d;border-radius:999px;padding:7px 10px}.pass{color:#86efac}.fail,.error{color:#fca5a5}.warning{color:#fde68a}li{margin:8px 0}</style></head><body><main><section class="hero"><p class="eyebrow">Reconnect Resume Proof</p><h1>Voice reconnect contract</h1><div class="summary"><span class="pill ${report.pass ? "pass" : "fail"}">${report.pass ? "pass" : "fail"}</span><span class="pill">${String(report.snapshotCount)} snapshots</span><span class="pill">${String(report.summary.attempts)} attempts</span><span class="pill">statuses ${
|
|
11296
|
+
const issues = report.issues.map((issue) => `<li class="${escapeHtml12(issue.severity)}"><strong>${escapeHtml12(issue.code)}</strong>: ${escapeHtml12(issue.message)}</li>`).join("");
|
|
11297
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>Voice Reconnect Contract</title><style>body{background:#0d1117;color:#f8fafc;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,.card{background:#151b23;border:1px solid #30363d;border-radius:18px;margin-bottom:16px;padding:20px}.eyebrow{color:#7dd3fc;font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}h1{font-size:clamp(2.25rem,7vw,4.5rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0d1117;border:1px solid #30363d;border-radius:999px;padding:7px 10px}.pass{color:#86efac}.fail,.error{color:#fca5a5}.warning{color:#fde68a}li{margin:8px 0}</style></head><body><main><section class="hero"><p class="eyebrow">Reconnect Resume Proof</p><h1>Voice reconnect contract</h1><div class="summary"><span class="pill ${report.pass ? "pass" : "fail"}">${report.pass ? "pass" : "fail"}</span><span class="pill">${String(report.snapshotCount)} snapshots</span><span class="pill">${String(report.summary.attempts)} attempts</span><span class="pill">statuses ${escapeHtml12(report.statuses.join(", ") || "none")}</span></div></section><section class="card"><h2>Summary</h2><p>reconnected ${String(report.summary.reconnected)} \xB7 resumed ${String(report.summary.resumed)} \xB7 exhausted ${String(report.summary.exhausted)} \xB7 duplicate turns ${String(report.summary.duplicateTurnIds.length)}</p></section><section class="card"><h2>Issues</h2>${issues ? `<ul>${issues}</ul>` : '<p class="pass">No contract issues.</p>'}</section></main></body></html>`;
|
|
11148
11298
|
};
|
|
11149
11299
|
var createVoiceReconnectContractRoutes = (options) => {
|
|
11150
11300
|
const path = options.path ?? "/api/voice/reconnect-contract";
|
|
@@ -11155,7 +11305,7 @@ var createVoiceReconnectContractRoutes = (options) => {
|
|
|
11155
11305
|
requireResume: options.requireResume,
|
|
11156
11306
|
snapshots: await options.getSnapshots()
|
|
11157
11307
|
});
|
|
11158
|
-
const app = new
|
|
11308
|
+
const app = new Elysia9({ name: options.name ?? "absolutejs-voice-reconnect-contract" }).get(path, async () => new Response(JSON.stringify(await buildReport()), {
|
|
11159
11309
|
headers: {
|
|
11160
11310
|
"content-type": "application/json; charset=utf-8",
|
|
11161
11311
|
...options.headers
|
|
@@ -11176,14 +11326,14 @@ var createVoiceReconnectContractRoutes = (options) => {
|
|
|
11176
11326
|
return app;
|
|
11177
11327
|
};
|
|
11178
11328
|
// src/realtimeChannel.ts
|
|
11179
|
-
import { Elysia as
|
|
11329
|
+
import { Elysia as Elysia10 } from "elysia";
|
|
11180
11330
|
var DEFAULT_REALTIME_FORMAT2 = {
|
|
11181
11331
|
channels: 1,
|
|
11182
11332
|
container: "raw",
|
|
11183
11333
|
encoding: "pcm_s16le",
|
|
11184
11334
|
sampleRateHz: 24000
|
|
11185
11335
|
};
|
|
11186
|
-
var
|
|
11336
|
+
var escapeHtml13 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11187
11337
|
var formatLabel = (format) => `${format.container}/${format.encoding}/${String(format.sampleRateHz)}hz/${String(format.channels)}ch`;
|
|
11188
11338
|
var formatMatches = (actual, expected) => actual.container === expected.container && actual.encoding === expected.encoding && actual.sampleRateHz === expected.sampleRateHz && actual.channels === expected.channels;
|
|
11189
11339
|
var validateFormat = (label, actual, expected, issues) => {
|
|
@@ -11437,9 +11587,9 @@ var renderVoiceRealtimeChannelMarkdown = (report) => [
|
|
|
11437
11587
|
].join(`
|
|
11438
11588
|
`);
|
|
11439
11589
|
var renderVoiceRealtimeChannelHTML = (report, title = "Voice Realtime Channel Proof") => {
|
|
11440
|
-
const issues = report.issues.map((issue) => `<li class="${
|
|
11441
|
-
const rows = report.runtime.samples.map((sample) => `<tr><td>${
|
|
11442
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
11590
|
+
const issues = report.issues.map((issue) => `<li class="${escapeHtml13(issue.severity)}"><strong>${escapeHtml13(issue.code)}</strong>: ${escapeHtml13(issue.message)}</li>`).join("");
|
|
11591
|
+
const rows = report.runtime.samples.map((sample) => `<tr><td>${escapeHtml13(sample.kind)}</td><td>${escapeHtml13(sample.source ?? "runtime")}</td><td>${escapeHtml13(sample.format ? formatLabel(sample.format) : "n/a")}</td><td>${escapeHtml13(sample.latencyMs ?? "n/a")}</td><td>${escapeHtml13(sample.ok ?? true)}</td></tr>`).join("");
|
|
11592
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml13(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.card{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(59,130,246,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr))}.metric{background:#101814;border:1px solid #2e3d36;border-radius:18px;padding:14px}.metric span{color:#a8b5ad;display:block;font-size:.78rem;text-transform:uppercase}.metric strong{display:block;font-size:1.65rem;margin-top:5px}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:7px 11px}.pass{color:#86efac}.warn{color:#fde68a}.fail,.error{color:#fecaca}.warning{color:#fde68a}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3d36;padding:10px;text-align:left}.links a{color:#5eead4;margin-right:12px}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime / duplex readiness</p><h1>${escapeHtml13(title)}</h1><p class="status ${escapeHtml13(report.status)}">${escapeHtml13(report.status)}</p><p>Provider <strong>${escapeHtml13(report.provider)}</strong> \xB7 ${escapeHtml13(report.surface)}</p><p class="links">${report.readinessHref ? `<a href="${escapeHtml13(report.readinessHref)}">Readiness</a>` : ""}${report.operationsRecordHref ? `<a href="${escapeHtml13(report.operationsRecordHref)}">Operations record</a>` : ""}</p><section class="summary"><div class="metric"><span>Input</span><strong>${escapeHtml13(formatLabel(report.inputFormat))}</strong></div><div class="metric"><span>Output</span><strong>${escapeHtml13(formatLabel(report.outputFormat))}</strong></div><div class="metric"><span>Browser capture</span><strong>${escapeHtml13(report.browserCapture ? `${String(report.browserCapture.sampleRateHz)}hz` : "missing")}</strong></div><div class="metric"><span>Resampling</span><strong>${report.browserCapture?.resamplingRequired ? "required" : "not required"}</strong></div><div class="metric"><span>Input samples</span><strong>${String(report.runtime.inputAudioSamples)}</strong></div><div class="metric"><span>Assistant samples</span><strong>${String(report.runtime.assistantAudioSamples)}</strong></div></section></section><section class="card"><h2>Issues</h2><ul>${issues || '<li class="pass">No realtime channel issues.</li>'}</ul></section><section class="card"><h2>Runtime Samples</h2><table><thead><tr><th>Kind</th><th>Source</th><th>Format</th><th>Latency ms</th><th>OK</th></tr></thead><tbody>${rows || '<tr><td colspan="5">No runtime samples configured.</td></tr>'}</tbody></table></section></main></body></html>`;
|
|
11443
11593
|
};
|
|
11444
11594
|
var createVoiceRealtimeChannelRoutes = (options) => {
|
|
11445
11595
|
const path = options.path ?? "/api/voice/realtime-channel";
|
|
@@ -11466,7 +11616,7 @@ var createVoiceRealtimeChannelRoutes = (options) => {
|
|
|
11466
11616
|
return reportOptions;
|
|
11467
11617
|
};
|
|
11468
11618
|
const report = async () => buildVoiceRealtimeChannelReport(await resolveOptions());
|
|
11469
|
-
const app = new
|
|
11619
|
+
const app = new Elysia10({ name: options.name ?? "voice-realtime-channel" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
11470
11620
|
headers: {
|
|
11471
11621
|
"content-type": "application/json; charset=utf-8",
|
|
11472
11622
|
...headers
|
|
@@ -11495,7 +11645,7 @@ var createVoiceRealtimeChannelRoutes = (options) => {
|
|
|
11495
11645
|
return app;
|
|
11496
11646
|
};
|
|
11497
11647
|
// src/realtimeProviderContracts.ts
|
|
11498
|
-
import { Elysia as
|
|
11648
|
+
import { Elysia as Elysia11 } from "elysia";
|
|
11499
11649
|
var defaultRequiredCapabilities = [
|
|
11500
11650
|
"browser-format-negotiation",
|
|
11501
11651
|
"raw-pcm",
|
|
@@ -11521,7 +11671,7 @@ var statusRank = {
|
|
|
11521
11671
|
};
|
|
11522
11672
|
var statusExceeds = (actual, max) => statusRank[actual] > statusRank[max];
|
|
11523
11673
|
var rollupStatus = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
11524
|
-
var
|
|
11674
|
+
var escapeHtml14 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11525
11675
|
var resolveProviderHref = (value, provider) => typeof value === "string" ? value : value?.[provider];
|
|
11526
11676
|
var createVoiceRealtimeProviderContractMatrixPreset = (options = {}) => {
|
|
11527
11677
|
const providers = options.providers ?? defaultRealtimeProviders;
|
|
@@ -11695,17 +11845,17 @@ var assertVoiceRealtimeProviderContractEvidence = (report, input = {}) => {
|
|
|
11695
11845
|
var resolveMatrix = async (matrix) => typeof matrix === "function" ? await matrix() : matrix;
|
|
11696
11846
|
var renderVoiceRealtimeProviderContractHTML = (report, title = "Voice Realtime Provider Contracts") => {
|
|
11697
11847
|
const rows = report.rows.map((row) => {
|
|
11698
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
11699
|
-
return `<article class="row ${
|
|
11848
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml14(check.status)}"><strong>${escapeHtml14(check.label)}</strong><span>${escapeHtml14(check.detail ?? check.status)}</span></li>`).join("");
|
|
11849
|
+
return `<article class="row ${escapeHtml14(row.status)}"><div><p class="eyebrow">${row.selected ? "selected" : "available"}</p><h2>${escapeHtml14(row.provider)}</h2><p class="status ${escapeHtml14(row.status)}">${escapeHtml14(row.status)}</p></div><ul>${checks}</ul></article>`;
|
|
11700
11850
|
}).join("");
|
|
11701
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
11851
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml14(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,.row{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.1))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill,.status{border:1px solid #3f4f45;border-radius:999px;display:inline-flex;padding:8px 12px}.row{display:grid;gap:18px;grid-template-columns:minmax(190px,.4fr) 1fr}.row ul{display:grid;gap:10px;list-style:none;margin:0;padding:0}.row li{background:#101814;border:1px solid #2e3d36;border-radius:16px;display:grid;gap:4px;padding:12px}.row li span{color:#b8c2ba}.pass{color:#86efac}.warn{color:#fde68a}.fail{color:#fecaca}@media(max-width:760px){main{padding:18px}.row{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Realtime provider contracts</p><h1>${escapeHtml14(title)}</h1><p>Provider-level proof for duplex audio, browser format negotiation, turn commit, latency, reconnect, barge-in, trace evidence, fallback, and readiness gates.</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>${rows || '<article class="row"><p>No realtime provider contracts configured.</p></article>'}</main></body></html>`;
|
|
11702
11852
|
};
|
|
11703
11853
|
var createVoiceRealtimeProviderContractRoutes = (options) => {
|
|
11704
11854
|
const path = options.path ?? "/api/voice/realtime-provider-contracts";
|
|
11705
11855
|
const htmlPath = options.htmlPath ?? "/voice/realtime-provider-contracts";
|
|
11706
11856
|
const title = options.title ?? "Voice Realtime Provider Contracts";
|
|
11707
11857
|
const report = async () => buildVoiceRealtimeProviderContractMatrix(await resolveMatrix(options.matrix));
|
|
11708
|
-
const routes = new
|
|
11858
|
+
const routes = new Elysia11({
|
|
11709
11859
|
name: options.name ?? "voice-realtime-provider-contracts"
|
|
11710
11860
|
}).get(path, async () => {
|
|
11711
11861
|
return new Response(JSON.stringify(await report(), null, 2), {
|
|
@@ -11730,8 +11880,8 @@ var createVoiceRealtimeProviderContractRoutes = (options) => {
|
|
|
11730
11880
|
return routes;
|
|
11731
11881
|
};
|
|
11732
11882
|
// src/diagnosticsRoutes.ts
|
|
11733
|
-
import { Elysia as
|
|
11734
|
-
var
|
|
11883
|
+
import { Elysia as Elysia12 } from "elysia";
|
|
11884
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
11735
11885
|
var getString6 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
11736
11886
|
var getNumber4 = (value) => {
|
|
11737
11887
|
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : undefined;
|
|
@@ -11797,9 +11947,9 @@ var renderDiagnosticsIndex = (input) => {
|
|
|
11797
11947
|
const rows = [...sessions.entries()].sort(([, left], [, right]) => (right.at(-1)?.at ?? 0) - (left.at(-1)?.at ?? 0)).slice(0, 50).map(([sessionId, events]) => {
|
|
11798
11948
|
const summary = summarizeVoiceTrace(events);
|
|
11799
11949
|
const encoded = encodeURIComponent(sessionId);
|
|
11800
|
-
return `<tr><td>${
|
|
11950
|
+
return `<tr><td>${escapeHtml15(sessionId)}</td><td>${summary.eventCount}</td><td>${summary.turnCount}</td><td>${summary.errorCount}</td><td><a href="${input.basePath}/html?sessionId=${encoded}&redact=true">HTML</a> \xB7 <a href="${input.basePath}/markdown?sessionId=${encoded}&redact=true">Markdown</a> \xB7 <a href="${input.basePath}/json?sessionId=${encoded}&redact=true">JSON</a></td></tr>`;
|
|
11801
11951
|
}).join("");
|
|
11802
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
11952
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml15(input.title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}table{width:100%;border-collapse:collapse;background:white}td,th{border-bottom:1px solid #eee;padding:.7rem;text-align:left}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml15(input.title)}</h1><p>Recent voice trace diagnostics. Exports support filters: sessionId, traceId, turnId, scenarioId, type, provider, status, since, until, limit, redact.</p><table><thead><tr><th>Session</th><th>Events</th><th>Turns</th><th>Errors</th><th>Exports</th></tr></thead><tbody>${rows}</tbody></table></main></body></html>`;
|
|
11803
11953
|
};
|
|
11804
11954
|
var withRedaction = (events, query, defaultRedact) => {
|
|
11805
11955
|
const shouldRedact = query.redact === undefined ? defaultRedact : getBoolean(query.redact);
|
|
@@ -11808,7 +11958,7 @@ var withRedaction = (events, query, defaultRedact) => {
|
|
|
11808
11958
|
var createVoiceDiagnosticsRoutes = (options) => {
|
|
11809
11959
|
const path = options.path ?? "/diagnostics";
|
|
11810
11960
|
const title = options.title ?? "AbsoluteJS Voice Diagnostics";
|
|
11811
|
-
const routes = new
|
|
11961
|
+
const routes = new Elysia12({
|
|
11812
11962
|
name: options.name ?? "absolutejs-voice-diagnostics"
|
|
11813
11963
|
});
|
|
11814
11964
|
routes.get(path, async () => {
|
|
@@ -11865,7 +12015,7 @@ var createVoiceDiagnosticsRoutes = (options) => {
|
|
|
11865
12015
|
return routes;
|
|
11866
12016
|
};
|
|
11867
12017
|
// src/mediaPipelineRoutes.ts
|
|
11868
|
-
import { Elysia as
|
|
12018
|
+
import { Elysia as Elysia13 } from "elysia";
|
|
11869
12019
|
|
|
11870
12020
|
// node_modules/@absolutejs/media/dist/index.js
|
|
11871
12021
|
var formatLabel2 = (format) => `${format.container}/${format.encoding}/${String(format.sampleRateHz)}hz/${String(format.channels)}ch`;
|
|
@@ -12530,7 +12680,7 @@ var buildMediaPipelineCalibrationReport = (input = {}) => {
|
|
|
12530
12680
|
};
|
|
12531
12681
|
|
|
12532
12682
|
// src/mediaPipelineRoutes.ts
|
|
12533
|
-
var
|
|
12683
|
+
var escapeHtml16 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12534
12684
|
var statusRank2 = {
|
|
12535
12685
|
pass: 0,
|
|
12536
12686
|
warn: 1,
|
|
@@ -12714,9 +12864,9 @@ var renderVoiceMediaPipelineHTML = (report, title = "Voice Media Pipeline Proof"
|
|
|
12714
12864
|
...report.calibration.issues,
|
|
12715
12865
|
...report.interruption.issues,
|
|
12716
12866
|
...report.quality.issues
|
|
12717
|
-
].map((issue) => `<li class="${
|
|
12718
|
-
const segments = report.vad.segments.map((segment) => `<tr><td>${
|
|
12719
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
12867
|
+
].map((issue) => `<li class="${escapeHtml16(issue.severity)}"><strong>${escapeHtml16(issue.code)}</strong>: ${escapeHtml16(issue.message)}</li>`).join("");
|
|
12868
|
+
const segments = report.vad.segments.map((segment) => `<tr><td>${escapeHtml16(segment.segmentId)}</td><td>${escapeHtml16(segment.frameCount)}</td><td>${escapeHtml16(segment.durationMs ?? "n/a")}</td><td>${escapeHtml16(segment.turnId ?? "n/a")}</td></tr>`).join("");
|
|
12869
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml16(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero,.card{background:#17201d;border:1px solid #2e3d36;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:.1em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.8rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.summary{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr))}.metric{background:#101814;border:1px solid #2e3d36;border-radius:18px;padding:14px}.metric span{color:#a8b5ad;display:block;font-size:.78rem;text-transform:uppercase}.metric strong{display:block;font-size:1.65rem;margin-top:5px}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:7px 11px}.pass{color:#86efac}.warn,.warning{color:#fde68a}.fail,.error{color:#fecaca}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2e3d36;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Native media pipeline</p><h1>${escapeHtml16(title)}</h1><p class="status ${escapeHtml16(report.status)}">${escapeHtml16(report.status)}</p><p>${escapeHtml16(report.surface)}</p><section class="summary"><div class="metric"><span>Frames</span><strong>${String(report.frames)}</strong></div><div class="metric"><span>Input audio</span><strong>${String(report.calibration.inputAudioFrames)}</strong></div><div class="metric"><span>Assistant audio</span><strong>${String(report.calibration.assistantAudioFrames)}</strong></div><div class="metric"><span>Trace linked</span><strong>${String(report.calibration.traceLinkedFrames)}</strong></div><div class="metric"><span>First audio</span><strong>${escapeHtml16(report.calibration.firstAudioLatencyMs ?? "n/a")}ms</strong></div><div class="metric"><span>VAD segments</span><strong>${String(report.vad.segments.length)}</strong></div><div class="metric"><span>Media quality</span><strong>${escapeHtml16(report.quality.status)}</strong></div><div class="metric"><span>Media gaps</span><strong>${String(report.quality.gapCount)}</strong></div><div class="metric"><span>Media jitter</span><strong>${escapeHtml16(report.quality.jitterMs ?? "n/a")}ms</strong></div><div class="metric"><span>Speech ratio</span><strong>${String(report.quality.speechRatio)}</strong></div><div class="metric"><span>Timestamp drift</span><strong>${escapeHtml16(report.quality.timestampDriftMs ?? "n/a")}ms</strong></div><div class="metric"><span>Interruptions</span><strong>${String(report.interruption.interruptionFrames)}</strong></div><div class="metric"><span>Processor graph</span><strong>${String(report.processorGraph?.nodes.length ?? 0)} nodes</strong></div><div class="metric"><span>Graph out/drop</span><strong>${String(report.processorGraph?.emittedFrames ?? 0)}/${String(report.processorGraph?.droppedFrames ?? 0)}</strong></div><div class="metric"><span>Resampling</span><strong>${report.calibration.resamplingRequired ? "required" : "not required"}</strong></div><div class="metric"><span>Transport</span><strong>${escapeHtml16(report.transport?.state ?? "n/a")}</strong></div><div class="metric"><span>Transport in/out</span><strong>${String(report.transport?.inputFrames ?? 0)}/${String(report.transport?.outputFrames ?? 0)}</strong></div><div class="metric"><span>Backpressure</span><strong>${String(report.transport?.backpressureEvents ?? 0)}</strong></div></section></section><section class="card"><h2>Issues</h2><ul>${issues || '<li class="pass">No media pipeline issues.</li>'}</ul></section><section class="card"><h2>VAD Segments</h2><table><thead><tr><th>Segment</th><th>Frames</th><th>Duration ms</th><th>Turn</th></tr></thead><tbody>${segments || '<tr><td colspan="4">No VAD segments.</td></tr>'}</tbody></table></section></main></body></html>`;
|
|
12720
12870
|
};
|
|
12721
12871
|
var createVoiceMediaPipelineRoutes = (options = {}) => {
|
|
12722
12872
|
const path = options.path ?? "/api/voice/media-pipeline";
|
|
@@ -12743,7 +12893,7 @@ var createVoiceMediaPipelineRoutes = (options = {}) => {
|
|
|
12743
12893
|
return reportOptions;
|
|
12744
12894
|
};
|
|
12745
12895
|
const report = async () => buildVoiceMediaPipelineReport(await resolveOptions());
|
|
12746
|
-
const app = new
|
|
12896
|
+
const app = new Elysia13({ name: options.name ?? "voice-media-pipeline" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
12747
12897
|
headers: {
|
|
12748
12898
|
"content-type": "application/json; charset=utf-8",
|
|
12749
12899
|
...headers
|
|
@@ -12772,7 +12922,7 @@ var createVoiceMediaPipelineRoutes = (options = {}) => {
|
|
|
12772
12922
|
return app;
|
|
12773
12923
|
};
|
|
12774
12924
|
// src/telephonyMediaRoutes.ts
|
|
12775
|
-
import { Elysia as
|
|
12925
|
+
import { Elysia as Elysia14 } from "elysia";
|
|
12776
12926
|
var demoPayload = Buffer.from(new Uint8Array([1, 2, 3, 4])).toString("base64");
|
|
12777
12927
|
var demoEnvelope = (carrier) => {
|
|
12778
12928
|
if (carrier === "twilio") {
|
|
@@ -12860,7 +13010,7 @@ var byteLength = (audio) => {
|
|
|
12860
13010
|
}
|
|
12861
13011
|
return audio instanceof ArrayBuffer ? audio.byteLength : audio.byteLength;
|
|
12862
13012
|
};
|
|
12863
|
-
var
|
|
13013
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12864
13014
|
var buildVoiceTelephonyMediaReport = (input = {}) => {
|
|
12865
13015
|
const carriers = input.carriers ?? [
|
|
12866
13016
|
{ carrier: "twilio" },
|
|
@@ -12949,13 +13099,13 @@ var getLatestVoiceTelephonyMediaReport = async (options) => {
|
|
|
12949
13099
|
};
|
|
12950
13100
|
var renderVoiceTelephonyMediaHTML = (report, options = {}) => {
|
|
12951
13101
|
const title = options.title ?? "Voice Telephony Media Proof";
|
|
12952
|
-
const rows = report.carriers.map((carrier) => `<tr><td>${
|
|
12953
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13102
|
+
const rows = report.carriers.map((carrier) => `<tr><td>${escapeHtml17(carrier.carrier)}</td><td>${escapeHtml17(carrier.status)}</td><td>${String(carrier.audioBytes)}</td><td>${String(carrier.lifecycle.mediaEvents)}</td><td>${escapeHtml17(carrier.lifecycle.started ? "yes" : "no")}</td><td>${escapeHtml17(carrier.lifecycle.stopped ? "yes" : "no")}</td><td>${escapeHtml17(carrier.frame?.kind ?? "missing")}</td><td>${escapeHtml17(carrier.frame?.format?.encoding ?? "missing")}</td><td>${escapeHtml17(carrier.issues.join(" ") || "none")}</td></tr>`).join("");
|
|
13103
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml17(title)}</title><style>body{background:#111827;color:#e5e7eb;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,table{background:#0f172a;border:1px solid #334155;border-radius:20px;margin-bottom:16px}.hero{padding:22px}.eyebrow{color:#67e8f9;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.fail{color:#fecaca}code{color:#bfdbfe}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #334155;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Carrier media serializer proof</p><h1>${escapeHtml17(title)}</h1><p class="status ${escapeHtml17(report.status)}">Status: ${escapeHtml17(report.status)}</p><p>Twilio, Telnyx, and Plivo media payload envelopes are parsed into generic <code>MediaFrame</code> objects, serialized back into carrier envelopes, and checked for start/media/stop lifecycle sequencing by <code>@absolutejs/media</code>.</p></section><table><thead><tr><th>Carrier</th><th>Status</th><th>Audio bytes</th><th>Media events</th><th>Started</th><th>Stopped</th><th>Frame kind</th><th>Encoding</th><th>Issues</th></tr></thead><tbody>${rows}</tbody></table></main></body></html>`;
|
|
12954
13104
|
};
|
|
12955
13105
|
var createVoiceTelephonyMediaRoutes = (options = {}) => {
|
|
12956
13106
|
const path = options.path ?? "/api/voice/telephony/media";
|
|
12957
13107
|
const htmlPath = options.htmlPath === undefined ? "/voice/telephony-media" : options.htmlPath;
|
|
12958
|
-
const routes = new
|
|
13108
|
+
const routes = new Elysia14({
|
|
12959
13109
|
name: options.name ?? "absolutejs-voice-telephony-media"
|
|
12960
13110
|
});
|
|
12961
13111
|
routes.get(path, async () => options.store ? await getLatestVoiceTelephonyMediaReport({
|
|
@@ -12979,8 +13129,8 @@ var createVoiceTelephonyMediaRoutes = (options = {}) => {
|
|
|
12979
13129
|
return routes;
|
|
12980
13130
|
};
|
|
12981
13131
|
// src/browserMediaRoutes.ts
|
|
12982
|
-
import { Elysia as
|
|
12983
|
-
var
|
|
13132
|
+
import { Elysia as Elysia15 } from "elysia";
|
|
13133
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
12984
13134
|
var isMediaWebRTCStatsReport = (value) => {
|
|
12985
13135
|
const report = value;
|
|
12986
13136
|
return !!report && typeof report === "object" && (report.status === "pass" || report.status === "warn" || report.status === "fail") && typeof report.activeCandidatePairs === "number" && typeof report.liveAudioTracks === "number" && typeof report.packetLossRatio === "number" && typeof report.bytesReceived === "number" && typeof report.bytesSent === "number" && Array.isArray(report.issues);
|
|
@@ -13050,14 +13200,14 @@ var renderVoiceBrowserMediaHTML = (report, options = {}) => {
|
|
|
13050
13200
|
const latestContinuity = report.latest?.continuity;
|
|
13051
13201
|
const rows = report.recent.slice(0, 20).map((sample) => {
|
|
13052
13202
|
const stalledStreams = (sample.continuity?.stalledInboundStreams ?? 0) + (sample.continuity?.stalledOutboundStreams ?? 0);
|
|
13053
|
-
return `<tr><td>${
|
|
13203
|
+
return `<tr><td>${escapeHtml18(sample.sessionId)}</td><td>${escapeHtml18(mergeIssues(sample.report, sample.continuity).status)}</td><td>${String(sample.report.activeCandidatePairs)}</td><td>${String(sample.report.liveAudioTracks)}</td><td>${String(sample.continuity?.inboundAudioStreams ?? "n/a")}</td><td>${String(sample.continuity?.outboundAudioStreams ?? "n/a")}</td><td>${String(stalledStreams)}</td><td>${String(sample.report.roundTripTimeMs ?? "n/a")}ms</td><td>${String(sample.report.jitterMs ?? "n/a")}ms</td><td>${String(sample.report.packetLossRatio)}</td><td>${escapeHtml18(new Date(sample.at).toLocaleString())}</td></tr>`;
|
|
13054
13204
|
}).join("");
|
|
13055
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13205
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml18(title)}</title><style>body{background:#0f172a;color:#e2e8f0;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,.primitive,table{background:#111827;border:1px solid #334155;border-radius:22px;margin-bottom:16px}.hero,.primitive{padding:22px}.eyebrow{color:#93c5fd;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}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#86efac}.warn,.empty{color:#fde68a}.fail{color:#fecaca}.metrics{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin-top:18px}.metric{background:#0b1220;border:1px solid #263244;border-radius:16px;padding:14px}.metric span{color:#94a3b8}.metric strong{display:block;font-size:1.7rem;margin-top:4px}.primitive code{color:#bfdbfe}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #334155;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Browser WebRTC media proof</p><h1>${escapeHtml18(title)}</h1><p class="status ${escapeHtml18(report.status)}">Status: ${escapeHtml18(report.status)}</p><p>Recent <code>client.browser_media</code> traces from browser <code>RTCPeerConnection.getStats()</code> reports, including aggregate transport stats and per-stream continuity.</p><section class="metrics"><div class="metric"><span>Reports</span><strong>${String(report.total)}</strong></div><div class="metric"><span>Candidate pairs</span><strong>${String(latest?.activeCandidatePairs ?? 0)}</strong></div><div class="metric"><span>Live audio tracks</span><strong>${String(latest?.liveAudioTracks ?? 0)}</strong></div><div class="metric"><span>Inbound streams</span><strong>${String(latestContinuity?.inboundAudioStreams ?? "n/a")}</strong></div><div class="metric"><span>Outbound streams</span><strong>${String(latestContinuity?.outboundAudioStreams ?? "n/a")}</strong></div><div class="metric"><span>Stalled streams</span><strong>${String((latestContinuity?.stalledInboundStreams ?? 0) + (latestContinuity?.stalledOutboundStreams ?? 0))}</strong></div><div class="metric"><span>RTT</span><strong>${String(latest?.roundTripTimeMs ?? "n/a")}ms</strong></div><div class="metric"><span>Jitter</span><strong>${String(latest?.jitterMs ?? "n/a")}ms</strong></div><div class="metric"><span>Loss</span><strong>${String(latest?.packetLossRatio ?? "n/a")}</strong></div></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><p><code>createVoiceBrowserMediaReporter({ peerConnection, continuity })</code> runs in the browser and posts reports here. <code>getLatestVoiceBrowserMediaReport(...)</code> can feed production readiness with aggregate and continuity issues merged.</p></section><table><thead><tr><th>Session</th><th>Status</th><th>Pairs</th><th>Tracks</th><th>Inbound</th><th>Outbound</th><th>Stalled</th><th>RTT</th><th>Jitter</th><th>Loss</th><th>Measured</th></tr></thead><tbody>${rows || '<tr><td colspan="11">No browser media reports yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
13056
13206
|
};
|
|
13057
13207
|
var createVoiceBrowserMediaRoutes = (options) => {
|
|
13058
13208
|
const path = options.path ?? "/api/voice/browser-media";
|
|
13059
13209
|
const htmlPath = options.htmlPath === undefined ? "/voice/browser-media" : options.htmlPath;
|
|
13060
|
-
const routes = new
|
|
13210
|
+
const routes = new Elysia15({
|
|
13061
13211
|
name: options.name ?? "absolutejs-voice-browser-media"
|
|
13062
13212
|
});
|
|
13063
13213
|
routes.get(path, () => summarizeVoiceBrowserMedia(options));
|
|
@@ -13091,9 +13241,9 @@ var createVoiceBrowserMediaRoutes = (options) => {
|
|
|
13091
13241
|
return routes;
|
|
13092
13242
|
};
|
|
13093
13243
|
// src/browserCallProfiles.ts
|
|
13094
|
-
import { Elysia as
|
|
13244
|
+
import { Elysia as Elysia16 } from "elysia";
|
|
13095
13245
|
var DEFAULT_MAX_AGE_MS = 10 * 60 * 1000;
|
|
13096
|
-
var
|
|
13246
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13097
13247
|
var toTime = (value) => {
|
|
13098
13248
|
if (value === undefined) {
|
|
13099
13249
|
return;
|
|
@@ -13233,8 +13383,8 @@ var renderVoiceBrowserCallProfileMarkdown = (report, options = {}) => {
|
|
|
13233
13383
|
var renderVoiceBrowserCallProfileHTML = (report, options = {}) => {
|
|
13234
13384
|
const normalized = buildVoiceBrowserCallProfileReport(report);
|
|
13235
13385
|
const title = options.title ?? "Voice Browser Call Profiles";
|
|
13236
|
-
const rows = normalized.results.map((result) => `<tr><td>${
|
|
13237
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13386
|
+
const rows = normalized.results.map((result) => `<tr><td>${escapeHtml19(result.framework)}</td><td class="${result.ok ? "pass" : "fail"}">${result.ok ? "pass" : "fail"}</td><td>${String(result.summary?.openSockets ?? 0)}</td><td>${String(result.summary?.sentBytes ?? 0)}</td><td>${String(result.summary?.receivedBytes ?? 0)}</td><td>${String(result.summary?.messageCount ?? 0)}</td><td>${escapeHtml19(result.error ?? "")}</td></tr>`).join("");
|
|
13387
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml19(title)}</title><style>body{background:#11140f;color:#f4f0df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,.primitive,table{background:#191d15;border:1px solid #323a27;border-radius:22px;margin-bottom:16px}.hero,.primitive{padding:22px}.eyebrow{color:#bef264;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}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.pass{color:#bef264}.warn,.empty,.stale{color:#fde68a}.fail{color:#fecaca}.metrics{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin-top:18px}.metric{background:#10130d;border:1px solid #303827;border-radius:16px;padding:14px}.metric span{color:#b8c3a3}.metric strong{display:block;font-size:1.7rem;margin-top:4px}.primitive code{color:#d9f99d}table{border-collapse:collapse;overflow:hidden;width:100%}td,th{border-bottom:1px solid #323a27;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Real browser microphone proof</p><h1>${escapeHtml19(title)}</h1><p class="status ${escapeHtml19(normalized.status)}">Status: ${escapeHtml19(normalized.status)}</p><p>Framework parity proof from real browser pages opening the voice WebSocket and sending microphone audio bytes.</p><section class="metrics"><div class="metric"><span>Frameworks</span><strong>${String(normalized.summary.totalFrameworks)}</strong></div><div class="metric"><span>Passing</span><strong>${String(normalized.summary.passedFrameworks.length)}</strong></div><div class="metric"><span>Open sockets</span><strong>${String(normalized.summary.openSockets)}</strong></div><div class="metric"><span>Sent bytes</span><strong>${String(normalized.summary.sentBytes)}</strong></div><div class="metric"><span>Received bytes</span><strong>${String(normalized.summary.receivedBytes)}</strong></div><div class="metric"><span>Messages</span><strong>${String(normalized.summary.totalMessages)}</strong></div></section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><p><code>buildVoiceBrowserCallProfileReport(...)</code> normalizes browser-call evidence. <code>evaluateVoiceBrowserCallProfileEvidence(...)</code> gates required frameworks, WebSocket opens, sent bytes, and freshness. <code>createVoiceBrowserCallProfileRoutes(...)</code> serves JSON, HTML, and Markdown.</p></section><table><thead><tr><th>Framework</th><th>Status</th><th>WebSockets</th><th>Sent bytes</th><th>Received bytes</th><th>Messages</th><th>Error</th></tr></thead><tbody>${rows || '<tr><td colspan="7">No browser call profile evidence yet.</td></tr>'}</tbody></table></main></body></html>`;
|
|
13238
13388
|
};
|
|
13239
13389
|
var resolveSource = async (options) => {
|
|
13240
13390
|
const source = typeof options.source === "function" ? await options.source() : options.source;
|
|
@@ -13247,7 +13397,7 @@ var createVoiceBrowserCallProfileRoutes = (options = {}) => {
|
|
|
13247
13397
|
const jsonPath = options.jsonPath ?? "/api/voice/browser-call-profiles";
|
|
13248
13398
|
const htmlPath = options.htmlPath === undefined ? "/voice/browser-call-profiles" : options.htmlPath;
|
|
13249
13399
|
const markdownPath = options.markdownPath === undefined ? "/voice/browser-call-profiles.md" : options.markdownPath;
|
|
13250
|
-
const routes = new
|
|
13400
|
+
const routes = new Elysia16({
|
|
13251
13401
|
name: options.name ?? "absolutejs-voice-browser-call-profiles"
|
|
13252
13402
|
});
|
|
13253
13403
|
routes.get(jsonPath, () => resolveSource(options));
|
|
@@ -13276,8 +13426,8 @@ var createVoiceBrowserCallProfileRoutes = (options = {}) => {
|
|
|
13276
13426
|
return routes;
|
|
13277
13427
|
};
|
|
13278
13428
|
// src/demoReadyRoutes.ts
|
|
13279
|
-
import { Elysia as
|
|
13280
|
-
var
|
|
13429
|
+
import { Elysia as Elysia17 } from "elysia";
|
|
13430
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13281
13431
|
var rollupStatus2 = (sections) => sections.some((section) => section.status === "fail") ? "fail" : sections.some((section) => section.status === "warn") ? "warn" : "pass";
|
|
13282
13432
|
var resolveLoader = async (loader, input) => typeof loader === "function" ? await loader(input) : loader;
|
|
13283
13433
|
var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
@@ -13361,17 +13511,17 @@ var buildVoiceDemoReadyReport = async (options, input = {}) => {
|
|
|
13361
13511
|
};
|
|
13362
13512
|
};
|
|
13363
13513
|
var renderVoiceDemoReadyHTML = (report) => {
|
|
13364
|
-
const sections = report.sections.map((section) => `<article class="section ${
|
|
13365
|
-
<div><span>${
|
|
13366
|
-
<strong>${
|
|
13367
|
-
${section.href ? `<a href="${
|
|
13514
|
+
const sections = report.sections.map((section) => `<article class="section ${escapeHtml20(section.status)}">
|
|
13515
|
+
<div><span>${escapeHtml20(section.status.toUpperCase())}</span><h2>${escapeHtml20(section.label)}</h2>${section.description ? `<p>${escapeHtml20(section.description)}</p>` : ""}</div>
|
|
13516
|
+
<strong>${escapeHtml20(String(section.value ?? section.status))}</strong>
|
|
13517
|
+
${section.href ? `<a href="${escapeHtml20(section.href)}">Open</a>` : ""}
|
|
13368
13518
|
</article>`).join("");
|
|
13369
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
13519
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml20(report.title)}</title><style>body{background:#0d141b;color:#f8f3e7;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(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}.sections{display:grid;gap:14px}.section{align-items:center;background:#151d26;border:1px solid #283544;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.section span{color:#aab5c0;font-size:.78rem;font-weight:900;letter-spacing:.08em}.section h2{margin:.2rem 0}.section p{color:#b9c0c8;margin:.2rem 0 0}.section strong{font-size:1.4rem}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.65)}.fail{border-color:rgba(239,68,68,.75)}a{color:#5eead4}@media(max-width:760px){main{padding:20px}.section{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Demo readiness</p><h1>${escapeHtml20(report.title)}</h1><p>One customer-facing checklist for the self-hosted voice proof surfaces: ops status, production readiness, phone setup, and phone smoke traces.</p><p class="status ${escapeHtml20(report.status)}">Overall: ${escapeHtml20(report.status.toUpperCase())}</p><p>Checked ${escapeHtml20(new Date(report.checkedAt).toLocaleString())}</p></section><section class="sections">${sections || '<article class="section warn"><div><span>WARN</span><h2>No checks configured</h2><p>Add ops status, production readiness, phone setup, or phone smoke loaders.</p></div><strong>warn</strong></article>'}</section></main></body></html>`;
|
|
13370
13520
|
};
|
|
13371
13521
|
var createVoiceDemoReadyRoutes = (options) => {
|
|
13372
13522
|
const path = options.path ?? "/api/demo-ready";
|
|
13373
13523
|
const htmlPath = options.htmlPath ?? "/demo-ready";
|
|
13374
|
-
const routes = new
|
|
13524
|
+
const routes = new Elysia17({
|
|
13375
13525
|
name: options.name ?? "absolutejs-voice-demo-ready"
|
|
13376
13526
|
});
|
|
13377
13527
|
routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
|
|
@@ -13390,7 +13540,7 @@ var createVoiceDemoReadyRoutes = (options) => {
|
|
|
13390
13540
|
return routes;
|
|
13391
13541
|
};
|
|
13392
13542
|
// src/deliverySinkRoutes.ts
|
|
13393
|
-
import { Elysia as
|
|
13543
|
+
import { Elysia as Elysia18 } from "elysia";
|
|
13394
13544
|
|
|
13395
13545
|
// src/queue.ts
|
|
13396
13546
|
var releaseLeaseScript = `
|
|
@@ -14333,7 +14483,7 @@ var createVoiceOpsTaskProcessorWorkerLoop = (options) => {
|
|
|
14333
14483
|
};
|
|
14334
14484
|
|
|
14335
14485
|
// src/deliverySinkRoutes.ts
|
|
14336
|
-
var
|
|
14486
|
+
var escapeHtml21 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14337
14487
|
var deliveryStatus = (summary) => {
|
|
14338
14488
|
if (!summary) {
|
|
14339
14489
|
return "warn";
|
|
@@ -14432,13 +14582,13 @@ var renderSurfaceCard = (surface) => {
|
|
|
14432
14582
|
return "";
|
|
14433
14583
|
}
|
|
14434
14584
|
const value = `${surface.summary.delivered}/${surface.summary.total}`;
|
|
14435
|
-
const body = `<span>${
|
|
14436
|
-
return `<article>${surface.href ? `<a href="${
|
|
14585
|
+
const body = `<span>${escapeHtml21(surface.label)}</span><strong>${escapeHtml21(value)}</strong><p class="muted">Delivered export records.</p>`;
|
|
14586
|
+
return `<article>${surface.href ? `<a href="${escapeHtml21(surface.href)}">${body}</a>` : body}</article>`;
|
|
14437
14587
|
};
|
|
14438
14588
|
var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
14439
14589
|
const title = options.title ?? "AbsoluteJS Voice Delivery Sinks";
|
|
14440
|
-
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${
|
|
14441
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
14590
|
+
const sinks = report.sinks.length ? report.sinks.map((sink) => `<article><span>${escapeHtml21(sink.kind)}</span><strong style="font-size:1.5rem">${escapeHtml21(sink.label)}</strong>${sink.description ? `<p class="muted">${escapeHtml21(sink.description)}</p>` : ""}${sink.mode ? `<p class="muted">Mode: ${escapeHtml21(sink.mode)}</p>` : ""}${sink.target ? `<p class="muted">Target: <code>${escapeHtml21(sink.target)}</code></p>` : ""}${sink.href ? `<p><a href="${escapeHtml21(sink.href)}">Open sink</a></p>` : ""}</article>`).join("") : '<article><span>Sink</span><strong style="font-size:1.5rem">Not described</strong><p class="muted">Pass sink descriptors to document your file, webhook, S3, SQLite, or Postgres targets.</p></article>';
|
|
14591
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml21(title)}</title><style>body{background:#11120d;color:#fbf7e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{max-width:1120px;margin:auto;padding:32px}a{color:#fde68a;text-decoration:none}.hero{background:linear-gradient(135deg,rgba(253,230,138,.2),rgba(34,197,94,.14));border:1px solid #3a3420;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fde68a;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #575030;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.pass{border-color:rgba(34,197,94,.65)}.status.warn{border-color:rgba(245,158,11,.65)}.status.fail{border-color:rgba(239,68,68,.75)}.muted{color:#b8b093}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin:18px 0}article,.card{background:#191a13;border:1px solid #33311f;border-radius:22px;padding:18px}article span{color:#b8b093;display:block;font-weight:800}article strong{display:block;font-size:2.4rem;margin-top:8px}pre{background:#0c0d09;border:1px solid #33311f;border-radius:18px;color:#fef3c7;overflow:auto;padding:16px}code{color:#fef3c7}</style></head><body><main><p><a href="/production-readiness">Production readiness</a></p><section class="hero"><p class="eyebrow">Composable sink primitive</p><h1>${escapeHtml21(title)}</h1><p class="muted">Delivery queues prove audit and trace exports without owning your infrastructure. Swap file, webhook, S3, SQLite, or Postgres sinks behind the same readiness surface.</p><p class="status ${escapeHtml21(report.status)}">Overall: ${escapeHtml21(report.status.toUpperCase())}</p><p class="muted">Checked ${escapeHtml21(new Date(report.checkedAt).toLocaleString())}</p></section><section class="grid">${renderSurfaceCard(report.auditDeliveries)}${renderSurfaceCard(report.traceDeliveries)}${sinks}</section><section class="card"><h2>Primitive shape</h2><p class="muted">Mount delivery sink routes beside audit and trace delivery queues. Production readiness can consume the same stores for pass/fail evidence.</p><pre>createVoiceDeliverySinkRoutes({
|
|
14442
14592
|
auditDeliveries: { store: runtimeStorage.auditDeliveries },
|
|
14443
14593
|
traceDeliveries: { store: runtimeStorage.traceDeliveries },
|
|
14444
14594
|
sinks: createVoiceDeliverySinkPair({
|
|
@@ -14450,7 +14600,7 @@ var renderVoiceDeliverySinkHTML = (report, options = {}) => {
|
|
|
14450
14600
|
var createVoiceDeliverySinkRoutes = (options) => {
|
|
14451
14601
|
const path = options.path ?? "/api/voice-delivery-sinks";
|
|
14452
14602
|
const htmlPath = options.htmlPath === undefined ? "/delivery-sinks" : options.htmlPath;
|
|
14453
|
-
const routes = new
|
|
14603
|
+
const routes = new Elysia18({
|
|
14454
14604
|
name: options.name ?? "absolutejs-voice-delivery-sinks"
|
|
14455
14605
|
}).get(path, () => buildVoiceDeliverySinkReport(options));
|
|
14456
14606
|
if (htmlPath !== false) {
|
|
@@ -14468,7 +14618,7 @@ var createVoiceDeliverySinkRoutes = (options) => {
|
|
|
14468
14618
|
return routes;
|
|
14469
14619
|
};
|
|
14470
14620
|
// src/opsActionAuditRoutes.ts
|
|
14471
|
-
import { Elysia as
|
|
14621
|
+
import { Elysia as Elysia19 } from "elysia";
|
|
14472
14622
|
var readRecordBody = (body) => {
|
|
14473
14623
|
if (!body || typeof body !== "object") {
|
|
14474
14624
|
throw new Error("Voice ops action audit requires a JSON body.");
|
|
@@ -14543,7 +14693,7 @@ var createVoiceOpsActionAuditRoutes = (options) => {
|
|
|
14543
14693
|
const path = options.path ?? "/api/voice/ops-actions/audit";
|
|
14544
14694
|
const historyPath = options.historyPath === undefined ? "/api/voice/ops-actions/history" : options.historyPath;
|
|
14545
14695
|
const historyHtmlPath = options.historyHtmlPath === undefined ? "/voice/ops-actions" : options.historyHtmlPath;
|
|
14546
|
-
const routes = new
|
|
14696
|
+
const routes = new Elysia19({
|
|
14547
14697
|
name: options.name ?? "absolutejs-voice-ops-action-audit"
|
|
14548
14698
|
}).post(path, async ({ body, request, set }) => {
|
|
14549
14699
|
try {
|
|
@@ -14593,13 +14743,13 @@ var buildVoiceOpsActionHistoryReport = async (options) => {
|
|
|
14593
14743
|
total: entries.length
|
|
14594
14744
|
};
|
|
14595
14745
|
};
|
|
14596
|
-
var
|
|
14746
|
+
var escapeHtml22 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14597
14747
|
var renderVoiceOpsActionHistoryHTML = (report) => {
|
|
14598
|
-
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${
|
|
14748
|
+
const rows = report.entries.map((entry) => `<article class="${entry.ok ? "ok" : "fail"}"><span>${escapeHtml22(entry.ok ? "success" : "error")}</span><strong>${escapeHtml22(entry.actionId)}</strong><p>${escapeHtml22(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</p>${entry.error ? `<p>${escapeHtml22(entry.error)}</p>` : ""}</article>`).join("");
|
|
14599
14749
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>Voice Ops Action History</title><style>body{background:#11140f;color:#f7f1df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:980px;padding:32px}.hero,article{background:#181d15;border:1px solid #2c3327;border-radius:24px;padding:20px}.hero{margin-bottom:16px}h1{font-size:clamp(2rem,6vw,4rem);line-height:.95}section{display:grid;gap:12px}article.ok{border-color:rgba(34,197,94,.55)}article.fail{border-color:rgba(239,68,68,.75)}span{color:#facc15;font-weight:900;text-transform:uppercase}p{color:#c8ccb8}</style></head><body><main><section class="hero"><span>Operator proof</span><h1>Voice Ops Action History</h1><p>${String(report.total)} action(s), ${String(report.failed)} failed.</p></section><section>${rows || "<p>No operator actions have been recorded.</p>"}</section></main></body></html>`;
|
|
14600
14750
|
};
|
|
14601
14751
|
// src/platformCoverage.ts
|
|
14602
|
-
import { Elysia as
|
|
14752
|
+
import { Elysia as Elysia20 } from "elysia";
|
|
14603
14753
|
var buildVoicePlatformCoverageSummary = (input) => {
|
|
14604
14754
|
const coverage = input.coverage ?? [];
|
|
14605
14755
|
const ok = input.ok ?? (coverage.length > 0 && coverage.every((surface) => surface.status === "pass"));
|
|
@@ -14660,7 +14810,7 @@ var assertVoicePlatformCoverage = (summary, input = {}) => {
|
|
|
14660
14810
|
var normalizeCoverageSummary = (value) => ("status" in value) && ("total" in value) && ("coverage" in value) ? value : buildVoicePlatformCoverageSummary(value);
|
|
14661
14811
|
var createVoicePlatformCoverageRoutes = (options) => {
|
|
14662
14812
|
const path = options.path ?? "/api/voice/platform-coverage";
|
|
14663
|
-
const routes = new
|
|
14813
|
+
const routes = new Elysia20({
|
|
14664
14814
|
name: options.name ?? "absolutejs-voice-platform-coverage"
|
|
14665
14815
|
});
|
|
14666
14816
|
routes.get(path, async () => {
|
|
@@ -14672,8 +14822,8 @@ var createVoicePlatformCoverageRoutes = (options) => {
|
|
|
14672
14822
|
return routes;
|
|
14673
14823
|
};
|
|
14674
14824
|
// src/competitiveCoverage.ts
|
|
14675
|
-
import { Elysia as
|
|
14676
|
-
var
|
|
14825
|
+
import { Elysia as Elysia21 } from "elysia";
|
|
14826
|
+
var escapeHtml23 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
14677
14827
|
var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
|
|
14678
14828
|
var resolveSurfaceStatus = (surface) => {
|
|
14679
14829
|
if (surface.status)
|
|
@@ -14841,24 +14991,24 @@ var renderVoiceCompetitiveCoverageMarkdown = (report, title = "Voice Competitive
|
|
|
14841
14991
|
`);
|
|
14842
14992
|
var renderVoiceCompetitiveCoverageHTML = (report, title = "Voice Competitive Coverage") => {
|
|
14843
14993
|
const surfaceCards = report.surfaces.map((surface) => {
|
|
14844
|
-
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${
|
|
14845
|
-
return `<article class="surface ${
|
|
14846
|
-
<header><div><p class="eyebrow">${
|
|
14847
|
-
<p>${
|
|
14994
|
+
const evidence = (surface.evidence ?? []).map((item) => `<li><strong>${escapeHtml23(item.name)}</strong>${item.kind ? ` <span>${escapeHtml23(item.kind)}</span>` : ""}${item.status ? ` <em>${escapeHtml23(item.status)}</em>` : ""}${item.href ? ` <a href="${escapeHtml23(item.href)}">open</a>` : ""}</li>`).join("");
|
|
14995
|
+
return `<article class="surface ${escapeHtml23(surface.status)} ${escapeHtml23(surface.depth)}">
|
|
14996
|
+
<header><div><p class="eyebrow">${escapeHtml23(surface.coverage)} \xB7 ${escapeHtml23(surface.depth)}</p><h2>${escapeHtml23(surface.surface)}</h2></div><strong>${escapeHtml23(surface.status)}</strong></header>
|
|
14997
|
+
<p>${escapeHtml23(surface.why)}</p>
|
|
14848
14998
|
<dl>
|
|
14849
|
-
<div><dt>Competitors</dt><dd>${
|
|
14850
|
-
<div><dt>Operations record</dt><dd>${
|
|
14851
|
-
<div><dt>Readiness gate</dt><dd>${
|
|
14852
|
-
<div><dt>Frameworks</dt><dd>${
|
|
14999
|
+
<div><dt>Competitors</dt><dd>${escapeHtml23((surface.competitors ?? []).join(", ") || "n/a")}</dd></div>
|
|
15000
|
+
<div><dt>Operations record</dt><dd>${escapeHtml23(surface.operationsRecord ?? "unknown")}</dd></div>
|
|
15001
|
+
<div><dt>Readiness gate</dt><dd>${escapeHtml23(surface.readinessGate ?? "unknown")}</dd></div>
|
|
15002
|
+
<div><dt>Frameworks</dt><dd>${escapeHtml23((surface.frameworkPrimitives ?? []).join(", ") || "n/a")}</dd></div>
|
|
14853
15003
|
</dl>
|
|
14854
|
-
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${
|
|
14855
|
-
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${
|
|
15004
|
+
${surface.remainingGap ? `<p class="gap"><strong>Gap:</strong> ${escapeHtml23(surface.remainingGap)}</p>` : ""}
|
|
15005
|
+
${surface.nextMove ? `<p class="next"><strong>Next:</strong> ${escapeHtml23(surface.nextMove)}</p>` : ""}
|
|
14856
15006
|
${evidence ? `<h3>Evidence</h3><ul>${evidence}</ul>` : '<p class="muted">No evidence links configured.</p>'}
|
|
14857
15007
|
</article>`;
|
|
14858
15008
|
}).join(`
|
|
14859
15009
|
`);
|
|
14860
|
-
const issueList = report.issues.map((issue) => `<li class="${
|
|
14861
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
15010
|
+
const issueList = report.issues.map((issue) => `<li class="${escapeHtml23(issue.severity)}"><strong>${escapeHtml23(issue.code)}</strong>${issue.surface ? ` ${escapeHtml23(issue.surface)}` : ""}: ${escapeHtml23(issue.message)}</li>`).join("");
|
|
15011
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml23(title)}</title><style>body{background:#0e1412;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.surface,.issues{background:#17201c;border:1px solid #2e3c35;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.16),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;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{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.surfaces{display:grid;gap:14px}.surface header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.surface.pass{border-color:rgba(34,197,94,.55)}.surface.warn{border-color:rgba(245,158,11,.72)}.surface.fail{border-color:rgba(239,68,68,.75)}.surface.advantage h2{color:#bbf7d0}.surface.intentional-gap h2{color:#cbd5e1}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}dt{color:#9fb0a8;font-size:.8rem;font-weight:800}dd{margin:0;overflow-wrap:anywhere}.gap{color:#fde68a}.next{color:#bfdbfe}.muted{color:#a8b5ad}a{color:#5eead4}.issues li{margin:.4rem 0}.issues .error{color:#fecaca}.issues .warning{color:#fde68a}@media(max-width:760px){main{padding:18px}.surface header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted market proof</p><h1>${escapeHtml23(title)}</h1><p>Generated ${escapeHtml23(report.generatedAt)}. This report scores whether AbsoluteJS Voice merely covers a hosted-platform buyer surface or beats it for a code-owned/self-hosted buyer.</p><div class="summary"><span class="pill">Status ${escapeHtml23(report.status)}</span><span class="pill">Vapi-style ${escapeHtml23(report.vapiCoverageEstimate)}</span><span class="pill">Market ${escapeHtml23(report.marketCoverageEstimate)}</span><span class="pill">${String(report.summary.surfaces)} surfaces</span><span class="pill">${String(report.summary.advantage)} advantage</span><span class="pill">${String(report.summary.intentionalGaps)} intentional gaps</span></div></section><section class="issues"><h2>Issues</h2><ul>${issueList || "<li>No issues.</li>"}</ul></section><section class="surfaces">${surfaceCards || '<article class="surface"><p>No competitive surfaces configured.</p></article>'}</section></main></body></html>`;
|
|
14862
15012
|
};
|
|
14863
15013
|
var normalizeCompetitiveCoverageReport = (value) => ("status" in value) && ("summary" in value) && ("issues" in value) ? value : buildVoiceCompetitiveCoverageReport(value);
|
|
14864
15014
|
var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
@@ -14871,7 +15021,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
14871
15021
|
const value = typeof options.source === "function" ? await options.source() : options.source;
|
|
14872
15022
|
return normalizeCompetitiveCoverageReport(value);
|
|
14873
15023
|
};
|
|
14874
|
-
const app = new
|
|
15024
|
+
const app = new Elysia21({
|
|
14875
15025
|
name: options.name ?? "absolutejs-voice-competitive-coverage"
|
|
14876
15026
|
}).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
14877
15027
|
headers: {
|
|
@@ -14902,7 +15052,7 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
14902
15052
|
return app;
|
|
14903
15053
|
};
|
|
14904
15054
|
// src/proofTrends.ts
|
|
14905
|
-
import { Elysia as
|
|
15055
|
+
import { Elysia as Elysia22 } from "elysia";
|
|
14906
15056
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
14907
15057
|
var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
|
|
14908
15058
|
{
|
|
@@ -15755,7 +15905,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
15755
15905
|
}
|
|
15756
15906
|
};
|
|
15757
15907
|
};
|
|
15758
|
-
var
|
|
15908
|
+
var escapeHtml24 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15759
15909
|
var escapeMarkdown2 = (value) => value.replaceAll("|", "\\|");
|
|
15760
15910
|
var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
|
|
15761
15911
|
`# ${title}`,
|
|
@@ -15788,11 +15938,11 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
15788
15938
|
].join(`
|
|
15789
15939
|
`);
|
|
15790
15940
|
var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
|
|
15791
|
-
const cards = report.recommendations.map((recommendation) => `<article class="${
|
|
15792
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
15793
|
-
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${
|
|
15794
|
-
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${
|
|
15795
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
15941
|
+
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml24(recommendation.status)}"><p class="eyebrow">${escapeHtml24(recommendation.surface)} \xB7 ${escapeHtml24(recommendation.status)}</p><h2>${escapeHtml24(recommendation.recommendation)}</h2><p>${escapeHtml24(recommendation.nextMove)}</p><pre>${escapeHtml24(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
15942
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml24(issue)}</li>`).join("");
|
|
15943
|
+
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml24(provider.label ?? provider.id)}</strong><span>${escapeHtml24(provider.role ?? "provider")} \xB7 ${escapeHtml24(provider.status)} \xB7 p95 ${escapeHtml24(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml24(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml24(provider.nextMove)}</small></li>`).join("");
|
|
15944
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml24(profile.label ?? profile.id)}</strong><span>${escapeHtml24(profile.status)} \xB7 ${escapeHtml24(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml24(profile.nextMove)}</small></li>`).join("");
|
|
15945
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml24(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;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:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml24(title)}</h1><p>Generated ${escapeHtml24(report.generatedAt)} from ${escapeHtml24(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml24(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml24(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
15796
15946
|
};
|
|
15797
15947
|
var renderVoiceRealCallProfileHistoryMarkdown = (report, title = "Voice Real-Call Profile History") => [
|
|
15798
15948
|
`# ${title}`,
|
|
@@ -15826,18 +15976,18 @@ var renderVoiceRealCallProfileHistoryMarkdown = (report, title = "Voice Real-Cal
|
|
|
15826
15976
|
].join(`
|
|
15827
15977
|
`);
|
|
15828
15978
|
var renderVoiceRealCallProfileHistoryHTML = (report, title = "Voice Real-Call Profile History") => {
|
|
15829
|
-
const profileRows = report.summary.profiles?.length ? report.summary.profiles.map((profile) => `<tr><td>${
|
|
15830
|
-
const defaultRows = report.defaults.profiles.length > 0 ? report.defaults.profiles.map((profile) => `<tr><td>${
|
|
15831
|
-
const recommendations = report.recommendations.recommendations.map((recommendation) => `<article class="${
|
|
15832
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
15833
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
15979
|
+
const profileRows = report.summary.profiles?.length ? report.summary.profiles.map((profile) => `<tr><td>${escapeHtml24(profile.label ?? profile.id)}</td><td>${escapeHtml24(profile.status ?? "unknown")}</td><td>${escapeHtml24(profile.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml24(profile.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml24(profile.maxTurnP95Ms ?? "n/a")}</td><td>${escapeHtml24(formatProviderMix(profile.providers ?? []))}</td></tr>`).join("") : '<tr><td colspan="6">No profiles present.</td></tr>';
|
|
15980
|
+
const defaultRows = report.defaults.profiles.length > 0 ? report.defaults.profiles.map((profile) => `<tr><td>${escapeHtml24(profile.label ?? profile.profileId)}</td><td>${escapeHtml24(profile.status)}</td><td>${escapeHtml24(Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "n/a")}</td><td>${escapeHtml24(profile.latencyBudgets.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml24(profile.latencyBudgets.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml24(profile.latencyBudgets.maxTurnP95Ms ?? "n/a")}</td></tr>`).join("") : '<tr><td colspan="6">No actionable defaults present.</td></tr>';
|
|
15981
|
+
const recommendations = report.recommendations.recommendations.map((recommendation) => `<article class="${escapeHtml24(recommendation.status)}"><p class="eyebrow">${escapeHtml24(recommendation.surface)} \xB7 ${escapeHtml24(recommendation.status)}</p><h2>${escapeHtml24(recommendation.recommendation)}</h2><p>${escapeHtml24(recommendation.nextMove)}</p></article>`).join("");
|
|
15982
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml24(issue)}</li>`).join("");
|
|
15983
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml24(title)}</title><style>body{background:#111510;color:#f6f0dd;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article,.card{background:#182117;border:1px solid #32412d;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.16),rgba(20,184,166,.12))}.eyebrow{color:#bef264;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #52624b;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #32412d;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Real-call benchmark history</p><h1>${escapeHtml24(title)}</h1><p>Generated ${escapeHtml24(report.generatedAt)} from ${escapeHtml24(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml24(report.status)}</span><span class="pill">Reports ${String(report.reports)}</span><span class="pill">Profiles ${String(report.summary.profileCount)}</span><span class="pill">Defaults ${String(report.defaults.summary.actionableProfiles)}/${String(report.defaults.summary.profileCount)}</span><span class="pill">Cycles ${String(report.summary.cycles ?? 0)}</span><span class="pill">Best mix ${escapeHtml24(formatProviderMix(report.recommendations.bestProviders))}</span></div></section><section class="card"><h2>Profiles</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Live p95</th><th>Provider p95</th><th>Turn p95</th><th>Provider mix</th></tr></thead><tbody>${profileRows}</tbody></table></section><section class="card"><h2>Actionable Defaults</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Provider routes</th><th>Live budget</th><th>Provider budget</th><th>Turn budget</th></tr></thead><tbody>${defaultRows}</tbody></table></section>${recommendations}<section class="card"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
15834
15984
|
};
|
|
15835
15985
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
15836
15986
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
15837
15987
|
const htmlPath = options.htmlPath === undefined ? "/voice/proof-trend-recommendations" : options.htmlPath;
|
|
15838
15988
|
const markdownPath = options.markdownPath === undefined ? "/voice/proof-trend-recommendations.md" : options.markdownPath;
|
|
15839
15989
|
const title = options.title ?? "Voice Provider Runtime Recommendations";
|
|
15840
|
-
const routes = new
|
|
15990
|
+
const routes = new Elysia22({
|
|
15841
15991
|
name: options.name ?? "absolutejs-voice-proof-trend-recommendations"
|
|
15842
15992
|
});
|
|
15843
15993
|
const loadReport = async () => {
|
|
@@ -15879,7 +16029,7 @@ var createVoiceRealCallProfileHistoryRoutes = (options = {}) => {
|
|
|
15879
16029
|
const htmlPath = options.htmlPath === undefined ? "/voice/real-call-profile-history" : options.htmlPath;
|
|
15880
16030
|
const markdownPath = options.markdownPath === undefined ? "/voice/real-call-profile-history.md" : options.markdownPath;
|
|
15881
16031
|
const title = options.title ?? "Voice Real-Call Profile History";
|
|
15882
|
-
const routes = new
|
|
16032
|
+
const routes = new Elysia22({
|
|
15883
16033
|
name: options.name ?? "absolutejs-voice-real-call-profile-history"
|
|
15884
16034
|
});
|
|
15885
16035
|
const loadReport = async () => {
|
|
@@ -15917,7 +16067,7 @@ var createVoiceRealCallProfileHistoryRoutes = (options = {}) => {
|
|
|
15917
16067
|
};
|
|
15918
16068
|
var createVoiceProofTrendRoutes = (options) => {
|
|
15919
16069
|
const path = options.path ?? "/api/voice/proof-trends";
|
|
15920
|
-
const routes = new
|
|
16070
|
+
const routes = new Elysia22({
|
|
15921
16071
|
name: options.name ?? "absolutejs-voice-proof-trends"
|
|
15922
16072
|
});
|
|
15923
16073
|
routes.get(path, async () => {
|
|
@@ -15950,11 +16100,11 @@ var formatVoiceProofTrendAge = (ageMs) => {
|
|
|
15950
16100
|
return `${days}d ${hours % 24}h`;
|
|
15951
16101
|
};
|
|
15952
16102
|
// src/providerDecisionTraces.ts
|
|
15953
|
-
import { Elysia as
|
|
16103
|
+
import { Elysia as Elysia24 } from "elysia";
|
|
15954
16104
|
|
|
15955
16105
|
// src/resilienceRoutes.ts
|
|
15956
|
-
import { Elysia as
|
|
15957
|
-
var
|
|
16106
|
+
import { Elysia as Elysia23 } from "elysia";
|
|
16107
|
+
var escapeHtml25 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
15958
16108
|
var getString7 = (value) => typeof value === "string" ? value : undefined;
|
|
15959
16109
|
var getNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
15960
16110
|
var getBoolean2 = (value) => value === true;
|
|
@@ -16102,13 +16252,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
16102
16252
|
};
|
|
16103
16253
|
var renderProviderCards = (title, providers) => {
|
|
16104
16254
|
if (providers.length === 0) {
|
|
16105
|
-
return `<p class="muted">No ${
|
|
16255
|
+
return `<p class="muted">No ${escapeHtml25(title)} provider health yet.</p>`;
|
|
16106
16256
|
}
|
|
16107
16257
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
16108
|
-
<article class="card provider ${
|
|
16258
|
+
<article class="card provider ${escapeHtml25(provider.status)}">
|
|
16109
16259
|
<div class="card-header">
|
|
16110
|
-
<strong>${
|
|
16111
|
-
<span>${
|
|
16260
|
+
<strong>${escapeHtml25(provider.provider)}</strong>
|
|
16261
|
+
<span>${escapeHtml25(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
16112
16262
|
</div>
|
|
16113
16263
|
<dl>
|
|
16114
16264
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -16117,7 +16267,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
16117
16267
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
16118
16268
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
16119
16269
|
</dl>
|
|
16120
|
-
${provider.lastError ? `<p class="muted">${
|
|
16270
|
+
${provider.lastError ? `<p class="muted">${escapeHtml25(provider.lastError)}</p>` : ""}
|
|
16121
16271
|
</article>
|
|
16122
16272
|
`).join("")}</div>`;
|
|
16123
16273
|
};
|
|
@@ -16126,24 +16276,24 @@ var renderTimeline2 = (events) => {
|
|
|
16126
16276
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
16127
16277
|
}
|
|
16128
16278
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
16129
|
-
<article class="card event ${
|
|
16279
|
+
<article class="card event ${escapeHtml25(event.status ?? "unknown")}">
|
|
16130
16280
|
<div class="card-header">
|
|
16131
|
-
<strong>${
|
|
16281
|
+
<strong>${escapeHtml25(event.kind.toUpperCase())} ${escapeHtml25(event.operation ?? "generate")}</strong>
|
|
16132
16282
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
16133
16283
|
</div>
|
|
16134
16284
|
<p>
|
|
16135
|
-
<span class="pill">${
|
|
16136
|
-
<span class="pill">provider: ${
|
|
16137
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
16285
|
+
<span class="pill">${escapeHtml25(event.status ?? "unknown")}</span>
|
|
16286
|
+
<span class="pill">provider: ${escapeHtml25(event.provider ?? "unknown")}</span>
|
|
16287
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml25(event.fallbackProvider)}</span>` : ""}
|
|
16138
16288
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
16139
16289
|
</p>
|
|
16140
16290
|
<dl>
|
|
16141
16291
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
16142
16292
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
16143
16293
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
16144
|
-
<div><dt>Session</dt><dd>${
|
|
16294
|
+
<div><dt>Session</dt><dd>${escapeHtml25(event.sessionId)}</dd></div>
|
|
16145
16295
|
</dl>
|
|
16146
|
-
${event.error ? `<p class="muted">${
|
|
16296
|
+
${event.error ? `<p class="muted">${escapeHtml25(event.error)}</p>` : ""}
|
|
16147
16297
|
</article>
|
|
16148
16298
|
`).join("")}</div>`;
|
|
16149
16299
|
};
|
|
@@ -16153,9 +16303,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
16153
16303
|
const status = latest?.status ?? "idle";
|
|
16154
16304
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
16155
16305
|
return `<div>
|
|
16156
|
-
<dt>${
|
|
16157
|
-
<dd>${
|
|
16158
|
-
<small>${
|
|
16306
|
+
<dt>${escapeHtml25(kind.toUpperCase())}</dt>
|
|
16307
|
+
<dd>${escapeHtml25(provider)}${escapeHtml25(fallback)}</dd>
|
|
16308
|
+
<small>${escapeHtml25(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
|
|
16159
16309
|
</div>`;
|
|
16160
16310
|
};
|
|
16161
16311
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -16163,10 +16313,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
16163
16313
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
16164
16314
|
}
|
|
16165
16315
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
16166
|
-
<article class="card session ${
|
|
16316
|
+
<article class="card session ${escapeHtml25(session.status)}">
|
|
16167
16317
|
<div class="card-header">
|
|
16168
|
-
<strong>${
|
|
16169
|
-
<span>${
|
|
16318
|
+
<strong>${escapeHtml25(session.sessionId)}</strong>
|
|
16319
|
+
<span>${escapeHtml25(session.status)}</span>
|
|
16170
16320
|
</div>
|
|
16171
16321
|
<p>
|
|
16172
16322
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -16193,21 +16343,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
16193
16343
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
16194
16344
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
16195
16345
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
16196
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
16197
|
-
<p class="muted">${
|
|
16346
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml25(pathPrefix)}">
|
|
16347
|
+
<p class="muted">${escapeHtml25(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
16198
16348
|
<div class="simulate-actions">
|
|
16199
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
16200
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
16349
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml25(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml25(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
16350
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml25(provider.provider)}">Mark ${escapeHtml25(provider.provider)} recovered</button>`).join("")}
|
|
16201
16351
|
</div>
|
|
16202
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
16352
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml25(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
16203
16353
|
<pre class="simulate-output" hidden></pre>
|
|
16204
16354
|
</div>`;
|
|
16205
16355
|
};
|
|
16206
16356
|
var renderVoiceResilienceHTML = (input) => {
|
|
16207
16357
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
16208
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
16209
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
16210
|
-
const snippet =
|
|
16358
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml25(kind)}: ${String(count)}</span>`).join("");
|
|
16359
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml25(link.href)}">${escapeHtml25(link.label)}</a>`).join(" \xB7 ") : "";
|
|
16360
|
+
const snippet = escapeHtml25(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
16211
16361
|
kind: 'stt',
|
|
16212
16362
|
providers: ['deepgram', 'assemblyai'],
|
|
16213
16363
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -16245,7 +16395,7 @@ app.use(
|
|
|
16245
16395
|
<head>
|
|
16246
16396
|
<meta charset="utf-8" />
|
|
16247
16397
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
16248
|
-
<title>${
|
|
16398
|
+
<title>${escapeHtml25(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
16249
16399
|
<style>
|
|
16250
16400
|
:root { color-scheme: dark; }
|
|
16251
16401
|
body { background: radial-gradient(circle at top left, #172554, #09090b 36%, #050505); color: #f4f4f5; font-family: ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; }
|
|
@@ -16397,7 +16547,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
16397
16547
|
};
|
|
16398
16548
|
var createVoiceResilienceRoutes = (options) => {
|
|
16399
16549
|
const path = options.path ?? "/resilience";
|
|
16400
|
-
const routes = new
|
|
16550
|
+
const routes = new Elysia23({
|
|
16401
16551
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
16402
16552
|
}).get(path, async () => {
|
|
16403
16553
|
const events = await options.store.list();
|
|
@@ -16438,7 +16588,7 @@ var createVoiceResilienceRoutes = (options) => {
|
|
|
16438
16588
|
};
|
|
16439
16589
|
|
|
16440
16590
|
// src/providerDecisionTraces.ts
|
|
16441
|
-
var
|
|
16591
|
+
var escapeHtml26 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16442
16592
|
var getString8 = (value) => typeof value === "string" ? value : undefined;
|
|
16443
16593
|
var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
16444
16594
|
var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
|
|
@@ -16679,7 +16829,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
|
|
|
16679
16829
|
<head>
|
|
16680
16830
|
<meta charset="utf-8" />
|
|
16681
16831
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
16682
|
-
<title>${
|
|
16832
|
+
<title>${escapeHtml26(title)}</title>
|
|
16683
16833
|
<style>
|
|
16684
16834
|
body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
|
|
16685
16835
|
main{max-width:1100px;margin:0 auto;padding:32px}
|
|
@@ -16693,8 +16843,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
16693
16843
|
</head>
|
|
16694
16844
|
<body>
|
|
16695
16845
|
<main>
|
|
16696
|
-
<p class="status ${report.status}">${
|
|
16697
|
-
<h1>${
|
|
16846
|
+
<p class="status ${report.status}">${escapeHtml26(report.status)}</p>
|
|
16847
|
+
<h1>${escapeHtml26(title)}</h1>
|
|
16698
16848
|
<p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
|
|
16699
16849
|
<section class="grid">
|
|
16700
16850
|
<article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
|
|
@@ -16705,10 +16855,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
|
|
|
16705
16855
|
</section>
|
|
16706
16856
|
<section class="surfaces">
|
|
16707
16857
|
${report.surfaces.map((surface) => `<article class="surface">
|
|
16708
|
-
<header><strong>${
|
|
16858
|
+
<header><strong>${escapeHtml26(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml26(surface.status)}</span></header>
|
|
16709
16859
|
<p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
|
|
16710
|
-
<p class="muted">Providers: ${
|
|
16711
|
-
<p>${surface.reasons.map((reason) => `<code>${
|
|
16860
|
+
<p class="muted">Providers: ${escapeHtml26(surface.providers.join(", ") || "none")}</p>
|
|
16861
|
+
<p>${surface.reasons.map((reason) => `<code>${escapeHtml26(reason)}</code>`).join(" ")}</p>
|
|
16712
16862
|
</article>`).join(`
|
|
16713
16863
|
`)}
|
|
16714
16864
|
</section>
|
|
@@ -16722,7 +16872,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16722
16872
|
const headers = options.headers ?? {};
|
|
16723
16873
|
const title = options.title ?? "Provider Decision Traces";
|
|
16724
16874
|
const report = () => buildVoiceProviderDecisionTraceReport(options);
|
|
16725
|
-
const app = new
|
|
16875
|
+
const app = new Elysia24({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
|
|
16726
16876
|
headers: {
|
|
16727
16877
|
"content-type": "application/json; charset=utf-8",
|
|
16728
16878
|
...headers
|
|
@@ -16750,7 +16900,7 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
|
|
|
16750
16900
|
return app;
|
|
16751
16901
|
};
|
|
16752
16902
|
// src/sloCalibration.ts
|
|
16753
|
-
import { Elysia as
|
|
16903
|
+
import { Elysia as Elysia25 } from "elysia";
|
|
16754
16904
|
var DEFAULT_HEADROOM_MULTIPLIER = 1.5;
|
|
16755
16905
|
var DEFAULT_WARN_RATIO = 0.8;
|
|
16756
16906
|
var DEFAULT_MIN_PASSING_RUNS = 3;
|
|
@@ -16931,7 +17081,7 @@ var buildVoiceSloReadinessThresholdReport = (input, options = {}) => {
|
|
|
16931
17081
|
};
|
|
16932
17082
|
};
|
|
16933
17083
|
var escapeMarkdown3 = (value) => value.replaceAll("|", "\\|");
|
|
16934
|
-
var
|
|
17084
|
+
var escapeHtml27 = (value) => String(value).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
16935
17085
|
var formatMs = (value) => value === undefined ? "n/a" : `${value.toLocaleString()} ms`;
|
|
16936
17086
|
var readinessThresholdRows = (report) => [
|
|
16937
17087
|
{
|
|
@@ -17022,15 +17172,15 @@ ${report.issues.map((issue) => `- ${issue}`).join(`
|
|
|
17022
17172
|
};
|
|
17023
17173
|
var renderVoiceSloReadinessThresholdHTML = (report, options = {}) => {
|
|
17024
17174
|
const title = options.title ?? "Calibration -> Active Readiness Gate";
|
|
17025
|
-
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${
|
|
17026
|
-
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${
|
|
17027
|
-
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${
|
|
17028
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
17175
|
+
const rows = readinessThresholdRows(report).map((row) => `<tr><td>${escapeHtml27(row.control)}</td><td>${escapeHtml27(formatMs(row.value))}</td><td>${escapeHtml27(row.usedBy)}</td></tr>`).join("");
|
|
17176
|
+
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml27(issue)}</li>`).join("");
|
|
17177
|
+
const sources = report.sources.length === 0 ? "<li>n/a</li>" : report.sources.map((source) => `<li><code>${escapeHtml27(source)}</code></li>`).join("");
|
|
17178
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml27(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1040px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}.status{font-size:1.6rem;font-weight:800;text-transform:uppercase}</style></head><body><main><h1>${escapeHtml27(title)}</h1><p>This page shows the calibrated thresholds currently driving production readiness gates.</p><section class="summary"><div class="card"><strong>Status</strong><br><span class="status">${escapeHtml27(report.status)}</span></div><div class="card"><strong>Live evidence max age</strong><br>${escapeHtml27(formatMs(report.liveLatencyMaxAgeMs))}</div><div class="card"><strong>Provider p95 gate</strong><br>${escapeHtml27(formatMs(report.providerSlo.llm?.maxP95ElapsedMs))}</div><div class="card"><strong>Barge-in gate</strong><br>${escapeHtml27(formatMs(report.bargeIn.thresholdMs))}</div></section><h2>Active Readiness Thresholds</h2><table><thead><tr><th>Threshold</th><th>Active value</th><th>Used by</th></tr></thead><tbody>${rows}</tbody></table><h2>Sources</h2><ul>${sources}</ul><h2>Issues</h2><ul>${issues}</ul></main></body></html>`;
|
|
17029
17179
|
};
|
|
17030
17180
|
var createVoiceSloCalibrationRoutes = (options) => {
|
|
17031
17181
|
const path = options.path ?? "/api/voice/slo-calibration";
|
|
17032
17182
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-calibration.md" : options.markdownPath;
|
|
17033
|
-
const routes = new
|
|
17183
|
+
const routes = new Elysia25({
|
|
17034
17184
|
name: options.name ?? "absolutejs-voice-slo-calibration"
|
|
17035
17185
|
});
|
|
17036
17186
|
const loadReport = async () => buildVoiceSloCalibrationReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -17054,7 +17204,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
17054
17204
|
const path = options.path ?? "/api/voice/slo-readiness-thresholds";
|
|
17055
17205
|
const htmlPath = options.htmlPath === undefined ? "/voice/slo-readiness-thresholds" : options.htmlPath;
|
|
17056
17206
|
const markdownPath = options.markdownPath === undefined ? "/voice/slo-readiness-thresholds.md" : options.markdownPath;
|
|
17057
|
-
const routes = new
|
|
17207
|
+
const routes = new Elysia25({
|
|
17058
17208
|
name: options.name ?? "absolutejs-voice-slo-readiness-thresholds"
|
|
17059
17209
|
});
|
|
17060
17210
|
const loadReport = async () => buildVoiceSloReadinessThresholdReport(typeof options.source === "function" ? await options.source() : options.source, options);
|
|
@@ -17088,7 +17238,7 @@ var createVoiceSloReadinessThresholdRoutes = (options) => {
|
|
|
17088
17238
|
return routes;
|
|
17089
17239
|
};
|
|
17090
17240
|
// src/liveOps.ts
|
|
17091
|
-
import { Elysia as
|
|
17241
|
+
import { Elysia as Elysia26 } from "elysia";
|
|
17092
17242
|
var VOICE_LIVE_OPS_ACTIONS = [
|
|
17093
17243
|
"assign",
|
|
17094
17244
|
"create-task",
|
|
@@ -17398,7 +17548,7 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
17398
17548
|
const controller = createVoiceLiveOpsController(options);
|
|
17399
17549
|
const path = options.path ?? "/api/voice/live-ops/action";
|
|
17400
17550
|
const controlPath = options.controlPath ?? "/api/voice/live-ops/control/:sessionId";
|
|
17401
|
-
return new
|
|
17551
|
+
return new Elysia26({
|
|
17402
17552
|
name: options.name ?? "absolutejs-voice-live-ops"
|
|
17403
17553
|
}).post(path, async ({ request, set }) => {
|
|
17404
17554
|
try {
|
|
@@ -17420,15 +17570,15 @@ var createVoiceLiveOpsRoutes = (options = {}) => {
|
|
|
17420
17570
|
});
|
|
17421
17571
|
};
|
|
17422
17572
|
// src/deliveryRuntime.ts
|
|
17423
|
-
import { Elysia as
|
|
17573
|
+
import { Elysia as Elysia27 } from "elysia";
|
|
17424
17574
|
import { mkdir } from "fs/promises";
|
|
17425
17575
|
import { dirname, join } from "path";
|
|
17426
|
-
var
|
|
17576
|
+
var escapeHtml28 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17427
17577
|
var renderSummaryCard = (label, summary) => {
|
|
17428
17578
|
if (!summary) {
|
|
17429
|
-
return `<article><span>${
|
|
17579
|
+
return `<article><span>${escapeHtml28(label)}</span><strong>Disabled</strong><p class="muted">No worker configured.</p></article>`;
|
|
17430
17580
|
}
|
|
17431
|
-
return `<article><span>${
|
|
17581
|
+
return `<article><span>${escapeHtml28(label)}</span><strong>${String(summary.delivered)}/${String(summary.total)}</strong><p class="muted">${String(summary.pending)} pending · ${String(summary.failed)} failed · ${String(summary.deadLettered)} dead-lettered</p></article>`;
|
|
17432
17582
|
};
|
|
17433
17583
|
var resolvePresetLeases = (leases) => ("claim" in leases) ? {
|
|
17434
17584
|
audit: leases,
|
|
@@ -17639,9 +17789,9 @@ var buildVoiceDeliveryRuntimeReport = async (runtime) => ({
|
|
|
17639
17789
|
});
|
|
17640
17790
|
var renderVoiceDeliveryRuntimeHTML = (report, options = {}) => {
|
|
17641
17791
|
const title = options.title ?? "AbsoluteJS Voice Delivery Runtime";
|
|
17642
|
-
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${
|
|
17643
|
-
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${
|
|
17644
|
-
const snippet =
|
|
17792
|
+
const tickForm = options.tickPath === false ? "" : `<form method="post" action="${escapeHtml28(options.tickPath ?? "/api/voice-delivery-runtime/tick")}"><button type="submit">Tick delivery workers</button></form>`;
|
|
17793
|
+
const requeueForm = options.requeueDeadLettersPath === false ? "" : `<form method="post" action="${escapeHtml28(options.requeueDeadLettersPath ?? "/api/voice-delivery-runtime/requeue-dead-letters")}"><button type="submit">Requeue dead letters</button></form>`;
|
|
17794
|
+
const snippet = escapeHtml28(`const deliveryRuntime = createVoiceDeliveryRuntime(
|
|
17645
17795
|
createVoiceDeliveryRuntimePresetConfig({
|
|
17646
17796
|
audit: {
|
|
17647
17797
|
deliveries: runtimeStorage.auditDeliveries,
|
|
@@ -17667,14 +17817,14 @@ app.use(
|
|
|
17667
17817
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
17668
17818
|
})
|
|
17669
17819
|
);`);
|
|
17670
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
17820
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml28(title)}</title><style>body{background:#0f1411;color:#f7f2df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}a{color:#86efac;text-decoration:none}.hero{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(14,165,233,.13));border:1px solid #263a30;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}.status{border:1px solid #64748b;border-radius:999px;display:inline-flex;font-weight:900;padding:8px 12px}.status.running{border-color:rgba(34,197,94,.7);color:#bbf7d0}.muted{color:#b9c3b4}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin:18px 0}article,.card{background:#151d18;border:1px solid #263a30;border-radius:22px;padding:18px}.primitive{background:#111a15;border-color:#41604a}article span{color:#b9c3b4;display:block;font-weight:800}article strong{display:block;font-size:2.3rem;margin-top:8px}.actions{display:flex;flex-wrap:wrap;gap:10px}button{background:#86efac;border:0;border-radius:999px;color:#07120b;cursor:pointer;font-weight:900;margin-top:12px;padding:10px 14px}pre{background:#09100c;border:1px solid #263a30;border-radius:18px;color:#dcfce7;overflow:auto;padding:16px}.primitive p{color:#c8d8ca;line-height:1.55}.primitive code{color:#bbf7d0}</style></head><body><main><p><a href="/delivery-sinks">Delivery sinks</a></p><section class="hero"><p class="eyebrow">Worker control plane</p><h1>${escapeHtml28(title)}</h1><p class="muted">Inspect queue summaries, manually tick failed/pending audit and trace deliveries, and requeue dead letters after operator review.</p><p class="status ${report.isRunning ? "running" : ""}">${report.isRunning ? "Running" : "Stopped"}</p><p class="muted">Checked ${escapeHtml28(new Date(report.checkedAt).toLocaleString())}</p><div class="actions">${tickForm}${requeueForm}</div></section><section class="grid">${renderSummaryCard("Audit", report.summary.audit)}${renderSummaryCard("Trace", report.summary.trace)}</section><section class="card primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceDeliveryRuntimeRoutes(...)</code> builds this control plane</h2><p>Own the audit and trace delivery queues in your app, mount one runtime route group, and pass the same runtime into production readiness so failed or dead-lettered exports block deploys.</p><pre><code>${snippet}</code></pre></section></main></body></html>`;
|
|
17671
17821
|
};
|
|
17672
17822
|
var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
17673
17823
|
const path = options.path ?? "/api/voice-delivery-runtime";
|
|
17674
17824
|
const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
|
|
17675
17825
|
const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
|
|
17676
17826
|
const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
|
|
17677
|
-
const routes = new
|
|
17827
|
+
const routes = new Elysia27({
|
|
17678
17828
|
name: options.name ?? "absolutejs-voice-delivery-runtime"
|
|
17679
17829
|
}).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
|
|
17680
17830
|
if (tickPath !== false) {
|
|
@@ -17710,7 +17860,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
|
|
|
17710
17860
|
return routes;
|
|
17711
17861
|
};
|
|
17712
17862
|
// src/dataControl.ts
|
|
17713
|
-
import { Elysia as
|
|
17863
|
+
import { Elysia as Elysia28 } from "elysia";
|
|
17714
17864
|
var voiceComplianceRedactionDefaults = {
|
|
17715
17865
|
keys: [
|
|
17716
17866
|
"apiKey",
|
|
@@ -17949,7 +18099,7 @@ var parseRetentionScopes = (value) => {
|
|
|
17949
18099
|
const allowed = new Set(allRetentionScopes);
|
|
17950
18100
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
17951
18101
|
};
|
|
17952
|
-
var
|
|
18102
|
+
var escapeHtml29 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
17953
18103
|
var buildStorageSurfaces = (options) => [
|
|
17954
18104
|
{
|
|
17955
18105
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -18186,12 +18336,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
18186
18336
|
zeroRetentionAvailable: true
|
|
18187
18337
|
};
|
|
18188
18338
|
};
|
|
18189
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
18339
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml29(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml29(scope.skippedReason ?? "")}</td><td><code>${escapeHtml29(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
18190
18340
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
18191
18341
|
const title = options.title ?? "Voice Data Control";
|
|
18192
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
18193
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
18194
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
18342
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml29(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml29(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
18343
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml29(key.name)}</td><td><code>${escapeHtml29(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml29(key.recommendation)}</td></tr>`).join("");
|
|
18344
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml29(title)}</title><style>body{background:#f8f7f2;color:#181713;font-family:ui-sans-serif,system-ui,sans-serif;line-height:1.45;margin:2rem}main{max-width:1120px;margin:auto}.summary{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card,table{background:white;border:1px solid #ddd6c8;border-radius:14px}.card{padding:1rem}table{border-collapse:collapse;width:100%;overflow:hidden}td,th{border-bottom:1px solid #eee8dc;padding:.7rem;text-align:left;vertical-align:top}code{white-space:pre-wrap;word-break:break-word}a{color:#9a3412}</style></head><body><main><h1>${escapeHtml29(title)}</h1><p>Self-hosted data-control proof for retention, redaction, audit export, deletion planning, customer-owned storage, and provider key handling.</p><section class="summary"><div class="card"><strong>Redaction</strong><br>${report.redaction.enabled ? "enabled" : "disabled"}</div><div class="card"><strong>Retention dry-run deletes</strong><br>${report.retentionPlan.deletedCount}</div><div class="card"><strong>Audit export events</strong><br>${report.auditExport?.events.length ?? 0}</div><div class="card"><strong>Zero retention recipe</strong><br>${report.zeroRetentionAvailable ? "available" : "missing"}</div></section><h2>Customer-Owned Storage</h2><table><thead><tr><th>Surface</th><th>Status</th><th>Control</th><th>Self-hosted</th></tr></thead><tbody>${storageRows}</tbody></table><h2>Retention Plan</h2><table><thead><tr><th>Scope</th><th>Scanned</th><th>Would delete</th><th>Skipped</th><th>Ids</th></tr></thead><tbody>${renderDataRetentionReportRows(report.retentionPlan)}</tbody></table><h2>Provider Keys</h2><table><thead><tr><th>Provider</th><th>Env</th><th>Required</th><th>Recommendation</th></tr></thead><tbody>${keyRows}</tbody></table><p><a href="./data-control/audit.md">Redacted audit Markdown</a> \xB7 <a href="./data-control/audit.html">Redacted audit HTML</a></p></main></body></html>`;
|
|
18195
18345
|
};
|
|
18196
18346
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
18197
18347
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -18249,7 +18399,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
18249
18399
|
var createVoiceDataControlRoutes = (options) => {
|
|
18250
18400
|
const path = options.path ?? "/data-control";
|
|
18251
18401
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
18252
|
-
const routes = new
|
|
18402
|
+
const routes = new Elysia28({
|
|
18253
18403
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
18254
18404
|
});
|
|
18255
18405
|
routes.get(path, async ({ query }) => {
|
|
@@ -18325,16 +18475,16 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
18325
18475
|
return routes;
|
|
18326
18476
|
};
|
|
18327
18477
|
// src/evalRoutes.ts
|
|
18328
|
-
import { Elysia as
|
|
18478
|
+
import { Elysia as Elysia31 } from "elysia";
|
|
18329
18479
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
18330
18480
|
import { dirname as dirname2 } from "path";
|
|
18331
18481
|
|
|
18332
18482
|
// src/qualityRoutes.ts
|
|
18333
|
-
import { Elysia as
|
|
18483
|
+
import { Elysia as Elysia30 } from "elysia";
|
|
18334
18484
|
|
|
18335
18485
|
// src/handoffHealth.ts
|
|
18336
|
-
import { Elysia as
|
|
18337
|
-
var
|
|
18486
|
+
import { Elysia as Elysia29 } from "elysia";
|
|
18487
|
+
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18338
18488
|
var getString9 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
18339
18489
|
var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
|
|
18340
18490
|
var increment3 = (record, key) => {
|
|
@@ -18452,10 +18602,10 @@ var renderActionSummary = (summary) => {
|
|
|
18452
18602
|
return [
|
|
18453
18603
|
'<section class="voice-handoff-health-columns">',
|
|
18454
18604
|
"<article><h3>Actions</h3>",
|
|
18455
|
-
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${
|
|
18605
|
+
actions.length === 0 ? "<p>No handoff actions yet.</p>" : `<ul>${actions.map(([action, count]) => `<li>${escapeHtml30(action)}: ${String(count)}</li>`).join("")}</ul>`,
|
|
18456
18606
|
"</article>",
|
|
18457
18607
|
"<article><h3>Adapters</h3>",
|
|
18458
|
-
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${
|
|
18608
|
+
adapters.length === 0 ? "<p>No adapter deliveries yet.</p>" : `<ul>${adapters.map(([adapterId, counts]) => `<li>${escapeHtml30(adapterId)}: ${String(counts.delivered)} delivered / ${String(counts.failed)} failed / ${String(counts.skipped)} skipped</li>`).join("")}</ul>`,
|
|
18459
18609
|
"</article>",
|
|
18460
18610
|
"</section>"
|
|
18461
18611
|
].join("");
|
|
@@ -18469,22 +18619,22 @@ var renderVoiceHandoffHealthHTML = (summary) => [
|
|
|
18469
18619
|
summary.events.length === 0 ? '<p class="voice-handoff-health-empty">No handoffs found.</p>' : [
|
|
18470
18620
|
'<div class="voice-handoff-health-events">',
|
|
18471
18621
|
...summary.events.map((event) => [
|
|
18472
|
-
`<article class="${
|
|
18622
|
+
`<article class="${escapeHtml30(event.status)}">`,
|
|
18473
18623
|
'<div class="voice-handoff-health-event-header">',
|
|
18474
|
-
`<strong>${
|
|
18475
|
-
`<span>${
|
|
18624
|
+
`<strong>${escapeHtml30(event.action ?? "handoff")}</strong>`,
|
|
18625
|
+
`<span>${escapeHtml30(event.status)}</span>`,
|
|
18476
18626
|
"</div>",
|
|
18477
|
-
`<p><small>${
|
|
18478
|
-
event.target ? `<p>Target: ${
|
|
18479
|
-
event.reason ? `<p>Reason: ${
|
|
18627
|
+
`<p><small>${escapeHtml30(event.sessionId)}</small></p>`,
|
|
18628
|
+
event.target ? `<p>Target: ${escapeHtml30(event.target)}</p>` : "",
|
|
18629
|
+
event.reason ? `<p>Reason: ${escapeHtml30(event.reason)}</p>` : "",
|
|
18480
18630
|
event.deliveries.length ? `<ul>${event.deliveries.map((delivery) => [
|
|
18481
18631
|
"<li>",
|
|
18482
|
-
`${
|
|
18483
|
-
delivery.deliveredTo ? ` to ${
|
|
18484
|
-
delivery.error ? ` (${
|
|
18632
|
+
`${escapeHtml30(delivery.adapterId)}: ${escapeHtml30(delivery.status)}`,
|
|
18633
|
+
delivery.deliveredTo ? ` to ${escapeHtml30(delivery.deliveredTo)}` : "",
|
|
18634
|
+
delivery.error ? ` (${escapeHtml30(delivery.error)})` : "",
|
|
18485
18635
|
"</li>"
|
|
18486
18636
|
].join("")).join("")}</ul>` : "",
|
|
18487
|
-
event.replayHref ? `<p><a href="${
|
|
18637
|
+
event.replayHref ? `<p><a href="${escapeHtml30(event.replayHref)}">Open replay</a></p>` : "",
|
|
18488
18638
|
"</article>"
|
|
18489
18639
|
].join("")),
|
|
18490
18640
|
"</div>"
|
|
@@ -18516,7 +18666,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
|
|
|
18516
18666
|
var createVoiceHandoffHealthRoutes = (options = {}) => {
|
|
18517
18667
|
const path = options.path ?? "/api/voice-handoffs";
|
|
18518
18668
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
18519
|
-
const routes = new
|
|
18669
|
+
const routes = new Elysia29({
|
|
18520
18670
|
name: options.name ?? "absolutejs-voice-handoff-health"
|
|
18521
18671
|
}).get(path, createVoiceHandoffHealthJSONHandler(options));
|
|
18522
18672
|
if (htmlPath) {
|
|
@@ -18637,17 +18787,17 @@ var evaluateVoiceQuality = async (input) => {
|
|
|
18637
18787
|
thresholds
|
|
18638
18788
|
};
|
|
18639
18789
|
};
|
|
18640
|
-
var
|
|
18790
|
+
var escapeHtml31 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18641
18791
|
var formatMetricValue = (metric) => metric.unit === "rate" ? `${(metric.actual * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.actual)}ms` : String(metric.actual);
|
|
18642
18792
|
var formatThreshold = (metric) => metric.unit === "rate" ? `${(metric.threshold * 100).toFixed(2)}%` : metric.unit === "ms" ? `${Math.round(metric.threshold)}ms` : String(metric.threshold);
|
|
18643
18793
|
var renderVoiceQualityHTML = (report, options = {}) => {
|
|
18644
|
-
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${
|
|
18645
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
18794
|
+
const rows = Object.entries(report.metrics).map(([key, metric]) => `<tr class="${metric.pass ? "pass" : "fail"}"><td>${escapeHtml31(metric.label)}</td><td>${escapeHtml31(formatMetricValue(metric))}</td><td>${escapeHtml31(formatThreshold(metric))}</td><td>${metric.pass ? "pass" : "fail"}</td><td><code>${escapeHtml31(key)}</code></td></tr>`).join("");
|
|
18795
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml31(link.href)}">${escapeHtml31(link.label)}</a>`).join("")}</nav>` : "";
|
|
18646
18796
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>AbsoluteJS Voice Quality</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1100px;margin:auto}nav{display:flex;flex-wrap:wrap;gap:.5rem;margin:0 0 1.25rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;padding:.35rem .75rem;font-weight:800}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}table{border-collapse:collapse;width:100%;background:white;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}.pass td{border-left:4px solid #16a34a}.fail td{border-left:4px solid #dc2626}code{background:#f3f4f6;padding:.15rem .3rem;border-radius:.3rem}</style></head><body><main>${links}<h1>Voice quality gates</h1><p class="status ${report.status}">${report.status}</p><p>${report.eventCount} event(s) checked.</p><table><thead><tr><th>Metric</th><th>Actual</th><th>Threshold</th><th>Status</th><th>Key</th></tr></thead><tbody>${rows}</tbody></table></main></body></html>`;
|
|
18647
18797
|
};
|
|
18648
18798
|
var createVoiceQualityRoutes = (options) => {
|
|
18649
18799
|
const path = options.path ?? "/quality";
|
|
18650
|
-
const routes = new
|
|
18800
|
+
const routes = new Elysia30({
|
|
18651
18801
|
name: options.name ?? "absolutejs-voice-quality"
|
|
18652
18802
|
});
|
|
18653
18803
|
const getReport = () => evaluateVoiceQuality({
|
|
@@ -18676,7 +18826,7 @@ var createVoiceQualityRoutes = (options) => {
|
|
|
18676
18826
|
};
|
|
18677
18827
|
|
|
18678
18828
|
// src/evalRoutes.ts
|
|
18679
|
-
var
|
|
18829
|
+
var escapeHtml32 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
18680
18830
|
var rate2 = (count, total) => count / Math.max(1, total);
|
|
18681
18831
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
18682
18832
|
var getString11 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -18998,7 +19148,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
18998
19148
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
18999
19149
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
19000
19150
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
19001
|
-
const snippet =
|
|
19151
|
+
const snippet = escapeHtml32(`app.use(
|
|
19002
19152
|
createVoiceEvalRoutes({
|
|
19003
19153
|
path: '/evals',
|
|
19004
19154
|
store: traceStore,
|
|
@@ -19019,48 +19169,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
19019
19169
|
};
|
|
19020
19170
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
19021
19171
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
19022
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
19023
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
19172
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml32(link.href)}">${escapeHtml32(link.label)}</a>`).join("")}</nav>` : "";
|
|
19173
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml32(bucket.key)}</td><td>${bucket.total}</td><td>${bucket.passed}</td><td>${bucket.failed}</td></tr>`).join("") : '<tr><td colspan="4">No eval buckets yet.</td></tr>';
|
|
19024
19174
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
19025
19175
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
19026
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
19027
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
19176
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml32(session.operationsRecordHref)}">${escapeHtml32(session.sessionId)}</a>` : escapeHtml32(session.sessionId);
|
|
19177
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml32(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml32(formatTime(session.endedAt))}</td><td>${escapeHtml32(failedMetrics || "none")}</td></tr>`;
|
|
19028
19178
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
19029
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19179
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{color:#166534}.fail{color:#991b1b}.status.pass{background:#dcfce7}.status.fail{background:#fee2e2}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,.primitive{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3;margin:1rem 0}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}table{border-collapse:collapse;background:white;width:100%;margin:1rem 0 2rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml32(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}<h2>Trend</h2><table><thead><tr><th>Day</th><th>Total</th><th>Passed</th><th>Failed</th></tr></thead><tbody>${trend}</tbody></table><h2>Session Eval Results</h2><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Last event</th><th>Failed metrics</th></tr></thead><tbody>${sessions}</tbody></table></main></body></html>`;
|
|
19030
19180
|
};
|
|
19031
19181
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
19032
19182
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
19033
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
19034
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
19035
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
19036
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
19037
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19183
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml32(link.href)}">${escapeHtml32(link.label)}</a>`).join("")}</nav>` : "";
|
|
19184
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml32(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
19185
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml32(id)}</li>`).join("") : "<li>none</li>";
|
|
19186
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml32(id)}</li>`).join("") : "<li>none</li>";
|
|
19187
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1000px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.pass{background:#dcfce7;color:#166534}.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:1rem 0}.card{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.card strong{display:block;font-size:2rem}section{background:white;border:1px solid #e7e5e4;border-radius:1rem;margin:1rem 0;padding:1rem}</style></head><body><main>${links}<h1>${escapeHtml32(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml32(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml32(formatPercent(comparison.current.passRate))}</strong></article><article class="card"><span>Failed delta</span><strong>${comparison.deltas.failed}</strong></article><article class="card"><span>Pass rate delta</span><strong>${escapeHtml32(formatPercent(comparison.deltas.passRate))}</strong></article></div><section><h2>Regression Reasons</h2><ul>${reasons}</ul></section><section><h2>New Failed Sessions</h2><ul>${newFailures}</ul></section><section><h2>Recovered Sessions</h2><ul>${recovered}</ul></section></main></body></html>`;
|
|
19038
19188
|
};
|
|
19039
19189
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
19040
19190
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
19041
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
19191
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml32(link.href)}">${escapeHtml32(link.label)}</a>`).join("")}</nav>` : "";
|
|
19042
19192
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
19043
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
19193
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml32(issue)}</li>`).join("")}</ul>` : "";
|
|
19044
19194
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
19045
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
19046
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
19195
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml32(session.operationsRecordHref)}">${escapeHtml32(session.sessionId)}</a>` : escapeHtml32(session.sessionId);
|
|
19196
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml32(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml32(session.issues.join(", ") || "none")}</td></tr>`;
|
|
19047
19197
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
19048
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
19198
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml32(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml32(scenario.description)}</p>` : ""}<p class="status ${scenario.status}">${scenario.status}</p><p>${scenario.passed} passed, ${scenario.failed} failed, ${scenario.matchedSessions} matched.</p>${scenarioIssues}<table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Issues</th></tr></thead><tbody>${sessions}</tbody></table></section>`;
|
|
19049
19199
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
19050
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19200
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml32(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${scenarios}</main></body></html>`;
|
|
19051
19201
|
};
|
|
19052
19202
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
19053
19203
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
19054
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
19204
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml32(link.href)}">${escapeHtml32(link.label)}</a>`).join("")}</nav>` : "";
|
|
19055
19205
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
19056
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
19057
|
-
return `<section class="${fixture.status}"><h2>${
|
|
19206
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml32(scenario.label)}</td><td>${escapeHtml32(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml32([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
19207
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml32(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml32(fixture.description)}</p>` : ""}<p class="status ${fixture.status}">${fixture.status}</p><table><thead><tr><th>Scenario</th><th>Status</th><th>Sessions</th><th>Issues</th></tr></thead><tbody>${scenarios}</tbody></table></section>`;
|
|
19058
19208
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
19059
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19209
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;background:#f8f7f2;color:#181713}main{max-width:1180px;margin:auto}nav{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}nav a{background:#181713;border-radius:999px;color:white;padding:.35rem .7rem;text-decoration:none}.eyebrow{font-size:.78rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.status{border-radius:999px;display:inline-flex;font-weight:800;padding:.35rem .75rem}.status.pass{background:#dcfce7;color:#166534}.status.fail{background:#fee2e2;color:#991b1b}.grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));margin:1rem 0}.card,section{background:white;border:1px solid #e7e5e4;border-radius:1rem;padding:1rem}.primitive{background:#fffdf7;border-color:#d6c7a3}.primitive p{line-height:1.55}.primitive pre{background:#181713;border-radius:.85rem;color:#fef3c7;overflow:auto;padding:1rem}.primitive code{color:#fef3c7}.card strong{display:block;font-size:2rem}section{margin:1rem 0}table{border-collapse:collapse;width:100%;margin-top:1rem}td,th{border-bottom:1px solid #eee;padding:.75rem;text-align:left}tr.fail td{border-left:4px solid #dc2626}tr.pass td{border-left:4px solid #16a34a}</style></head><body><main>${links}<h1>${escapeHtml32(title)}</h1><p class="status ${report.status}">${report.status}</p><div class="grid"><article class="card"><span>Total</span><strong>${report.total}</strong></article><article class="card"><span>Passed</span><strong>${report.passed}</strong></article><article class="card"><span>Failed</span><strong>${report.failed}</strong></article></div>${renderVoiceEvalPrimitiveCopy()}${fixtures}</main></body></html>`;
|
|
19060
19210
|
};
|
|
19061
19211
|
var createVoiceEvalRoutes = (options) => {
|
|
19062
19212
|
const path = options.path ?? "/evals";
|
|
19063
|
-
const routes = new
|
|
19213
|
+
const routes = new Elysia31({
|
|
19064
19214
|
name: options.name ?? "absolutejs-voice-evals"
|
|
19065
19215
|
});
|
|
19066
19216
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -19197,11 +19347,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
19197
19347
|
return routes;
|
|
19198
19348
|
};
|
|
19199
19349
|
// src/simulationSuite.ts
|
|
19200
|
-
import { Elysia as
|
|
19350
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
19201
19351
|
|
|
19202
19352
|
// src/outcomeContract.ts
|
|
19203
|
-
import { Elysia as
|
|
19204
|
-
var
|
|
19353
|
+
import { Elysia as Elysia32 } from "elysia";
|
|
19354
|
+
var escapeHtml33 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19205
19355
|
var resolveSessionHref2 = (value, sessionId) => {
|
|
19206
19356
|
if (value === false) {
|
|
19207
19357
|
return;
|
|
@@ -19412,13 +19562,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
19412
19562
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
19413
19563
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
19414
19564
|
const contracts = report.contracts.map((contract) => {
|
|
19415
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
19565
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml33(href)}">${escapeHtml33(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
19416
19566
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
19417
19567
|
<div class="contract-header">
|
|
19418
19568
|
<div>
|
|
19419
|
-
<p class="eyebrow">${
|
|
19420
|
-
<h2>${
|
|
19421
|
-
${contract.description ? `<p>${
|
|
19569
|
+
<p class="eyebrow">${escapeHtml33(contract.contractId)}</p>
|
|
19570
|
+
<h2>${escapeHtml33(contract.label ?? contract.contractId)}</h2>
|
|
19571
|
+
${contract.description ? `<p>${escapeHtml33(contract.description)}</p>` : ""}
|
|
19422
19572
|
${sessionLinks}
|
|
19423
19573
|
</div>
|
|
19424
19574
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -19430,10 +19580,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
19430
19580
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
19431
19581
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
19432
19582
|
</div>
|
|
19433
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
19583
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml33(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
19434
19584
|
</section>`;
|
|
19435
19585
|
}).join("");
|
|
19436
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
19586
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml33(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,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(14,165,233,.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}.summary,.grid{display:flex;flex-wrap:wrap;gap:10px}.pill,.grid span{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{display:flex;gap:16px;justify-content:space-between}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}li{margin:8px 0}@media(max-width:800px){main{padding:18px}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Business Outcome Verification</p><h1>${escapeHtml33(title)}</h1><div class="summary"><span class="pill ${report.status}">${report.status}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section>${contracts || '<section class="contract"><p>No outcome contracts configured.</p></section>'}</main></body></html>`;
|
|
19437
19587
|
};
|
|
19438
19588
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
19439
19589
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -19449,7 +19599,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
19449
19599
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
19450
19600
|
const path = options.path ?? "/api/outcome-contracts";
|
|
19451
19601
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
19452
|
-
const routes = new
|
|
19602
|
+
const routes = new Elysia32({
|
|
19453
19603
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
19454
19604
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
19455
19605
|
if (htmlPath) {
|
|
@@ -19459,7 +19609,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
19459
19609
|
};
|
|
19460
19610
|
|
|
19461
19611
|
// src/toolContract.ts
|
|
19462
|
-
import { Elysia as
|
|
19612
|
+
import { Elysia as Elysia33 } from "elysia";
|
|
19463
19613
|
|
|
19464
19614
|
// src/toolRuntime.ts
|
|
19465
19615
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -19668,7 +19818,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
19668
19818
|
});
|
|
19669
19819
|
var defaultApi = {};
|
|
19670
19820
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
19671
|
-
var
|
|
19821
|
+
var escapeHtml34 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19672
19822
|
var resolveSessionHref3 = (value, sessionId) => {
|
|
19673
19823
|
if (value === false) {
|
|
19674
19824
|
return;
|
|
@@ -19917,7 +20067,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
19917
20067
|
};
|
|
19918
20068
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
19919
20069
|
const title = options.title ?? "Voice Tool Contracts";
|
|
19920
|
-
const snippet =
|
|
20070
|
+
const snippet = escapeHtml34(`app.use(
|
|
19921
20071
|
createVoiceToolContractRoutes({
|
|
19922
20072
|
htmlPath: '/tool-contracts',
|
|
19923
20073
|
path: '/api/tool-contracts',
|
|
@@ -19943,20 +20093,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
19943
20093
|
);`);
|
|
19944
20094
|
const contracts = report.contracts.map((contract) => {
|
|
19945
20095
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
19946
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
20096
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml34(testCase.operationsRecordHref)}">${escapeHtml34(testCase.label ?? testCase.caseId)}</a>` : escapeHtml34(testCase.label ?? testCase.caseId)}</td>
|
|
19947
20097
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
19948
|
-
<td>${
|
|
19949
|
-
<td>${
|
|
20098
|
+
<td>${escapeHtml34(testCase.status)}</td>
|
|
20099
|
+
<td>${escapeHtml34(testCase.sessionId)}</td>
|
|
19950
20100
|
<td>${String(testCase.attempts)}</td>
|
|
19951
20101
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
19952
20102
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
19953
|
-
<td>${
|
|
20103
|
+
<td>${escapeHtml34(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
19954
20104
|
</tr>`).join("");
|
|
19955
20105
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
19956
20106
|
<div class="contract-header">
|
|
19957
20107
|
<div>
|
|
19958
|
-
<p class="eyebrow">${
|
|
19959
|
-
<h2>${
|
|
20108
|
+
<p class="eyebrow">${escapeHtml34(contract.toolName)}</p>
|
|
20109
|
+
<h2>${escapeHtml34(contract.label ?? contract.contractId)}</h2>
|
|
19960
20110
|
</div>
|
|
19961
20111
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
19962
20112
|
</div>
|
|
@@ -19966,7 +20116,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
19966
20116
|
</table>
|
|
19967
20117
|
</section>`;
|
|
19968
20118
|
}).join("");
|
|
19969
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20119
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml34(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,.primitive,.contract{background:#181d22;border:1px solid #2a323a;border-radius:20px;margin-bottom:16px;padding:20px}.hero{background:linear-gradient(135deg,rgba(34,197,94,.14),rgba(245,158,11,.12))}.primitive{background:#151b20;border-color:#5a4421}.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}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{background:#0f1217;border:1px solid #3f3f46;border-radius:999px;padding:7px 10px}.contract-header{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}h2{margin:.2rem 0 1rem}.pass{color:#86efac}.fail{color:#fca5a5}.contract.fail{border-color:rgba(248,113,113,.45)}.primitive p{color:#d8dee6;line-height:1.55}.primitive pre{background:#0f1217;border:1px solid #2a323a;border-radius:16px;color:#fef3c7;overflow:auto;padding:14px}.primitive code{color:#fef3c7}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #2a323a;padding:12px;text-align:left;vertical-align:top}th{color:#a8b0b8;font-size:.82rem}@media(max-width:800px){main{padding:18px}table{display:block;overflow:auto}.contract-header{display:block}}</style></head><body><main><section class="hero"><p class="eyebrow">Tool Reliability</p><h1>${escapeHtml34(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml34(report.status)}</span><span class="pill">${String(report.passed)} passing</span><span class="pill">${String(report.failed)} failing</span><span class="pill">${String(report.total)} contracts</span></div></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceToolContractRoutes(...)</code> certifies tool behavior</h2><p>Define deterministic tool cases for retries, idempotency, timeouts, result shape, and error handling so assistant tools fail in pre-production instead of live calls.</p><pre><code>${snippet}</code></pre></section>${contracts || '<section class="contract"><p>No tool contracts configured.</p></section>'}</main></body></html>`;
|
|
19970
20120
|
};
|
|
19971
20121
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
19972
20122
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -19983,7 +20133,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
19983
20133
|
var createVoiceToolContractRoutes = (options) => {
|
|
19984
20134
|
const path = options.path ?? "/api/tool-contracts";
|
|
19985
20135
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
19986
|
-
const routes = new
|
|
20136
|
+
const routes = new Elysia33({
|
|
19987
20137
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
19988
20138
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
19989
20139
|
if (htmlPath) {
|
|
@@ -19993,7 +20143,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
19993
20143
|
};
|
|
19994
20144
|
|
|
19995
20145
|
// src/simulationSuite.ts
|
|
19996
|
-
var
|
|
20146
|
+
var escapeHtml35 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19997
20147
|
var summarizeSection = (report) => ({
|
|
19998
20148
|
failed: report.failed,
|
|
19999
20149
|
passed: report.passed,
|
|
@@ -20189,15 +20339,15 @@ var renderSection = (label, summary) => {
|
|
|
20189
20339
|
if (!summary) {
|
|
20190
20340
|
return "";
|
|
20191
20341
|
}
|
|
20192
|
-
return `<article class="${
|
|
20342
|
+
return `<article class="${escapeHtml35(summary.status)}"><span>${escapeHtml35(label)}</span><strong>${escapeHtml35(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
20193
20343
|
};
|
|
20194
20344
|
var renderAction = (action) => {
|
|
20195
|
-
const content = `<strong>${
|
|
20196
|
-
return action.href ? `<a class="action" href="${
|
|
20345
|
+
const content = `<strong>${escapeHtml35(action.label)}</strong><p>${escapeHtml35(action.description)}</p><span>${escapeHtml35(action.section)} / ${escapeHtml35(action.severity)}</span>`;
|
|
20346
|
+
return action.href ? `<a class="action" href="${escapeHtml35(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
20197
20347
|
};
|
|
20198
20348
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
20199
20349
|
const title = options.title ?? "Voice Simulation Suite";
|
|
20200
|
-
const snippet =
|
|
20350
|
+
const snippet = escapeHtml35(`app.use(
|
|
20201
20351
|
createVoiceSimulationSuiteRoutes({
|
|
20202
20352
|
htmlPath: '/voice/simulations',
|
|
20203
20353
|
path: '/api/voice/simulations',
|
|
@@ -20230,12 +20380,12 @@ app.use(
|
|
|
20230
20380
|
store: traceStore
|
|
20231
20381
|
})
|
|
20232
20382
|
);`);
|
|
20233
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
20383
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml35(title)}</title><style>body{background:#10151c;color:#f8f3e7;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1080px;padding:32px}.hero,.primitive{background:linear-gradient(135deg,rgba(34,197,94,.18),rgba(59,130,246,.12));border:1px solid #283544;border-radius:28px;margin-bottom:18px;padding:28px}.primitive{background:#151d27;border-color:#355078}.eyebrow{color:#93c5fd;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.badge{border:1px solid #3f3f46;border-radius:999px;display:inline-flex;padding:8px 12px}.pass{color:#86efac}.fail{color:#fca5a5}.grid,.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin:18px 0}.grid article,.action{background:#151d27;border:1px solid #283544;border-radius:18px;color:inherit;padding:16px;text-decoration:none}.grid span,.action span{color:#aab5c0}.grid strong{display:block;font-size:2rem;margin:.25rem 0;text-transform:uppercase}.action strong{display:block;color:#f8f3e7;margin-bottom:.35rem}.action p,.primitive p{color:#d8dee6;line-height:1.55;margin:.3rem 0 .6rem}pre{background:#151d27;border:1px solid #283544;border-radius:18px;overflow:auto;padding:16px}.primitive pre{background:#0b1118;color:#dbeafe}.primitive code{color:#bfdbfe}</style></head><body><main><section class="hero"><p class="eyebrow">Pre-production proof</p><h1>${escapeHtml35(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml35(report.status)}">Status: ${escapeHtml35(report.status)}</p><section class="grid">${renderSection("Sessions", report.summary.sessions)}${renderSection("Scenarios", report.summary.scenarios)}${renderSection("Fixtures", report.summary.fixtures)}${renderSection("Tools", report.summary.tools)}${renderSection("Outcomes", report.summary.outcomes)}</section></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceSimulationSuiteRoutes(...)</code> builds this pre-production proof surface</h2><p>Run session quality checks, scenario evals, fixture-backed simulations, tool contracts, and outcome contracts from one route group before live traffic sees a regression.</p><pre><code>${snippet}</code></pre></section><h2>Actions</h2><section class="actions">${report.actions.length > 0 ? report.actions.map(renderAction).join("") : '<article class="action"><strong>No action required</strong><p>All enabled simulation sections are passing.</p></article>'}</section><pre>${escapeHtml35(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
20234
20384
|
};
|
|
20235
20385
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
20236
20386
|
const path = options.path ?? "/api/voice/simulations";
|
|
20237
20387
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
20238
|
-
const app = new
|
|
20388
|
+
const app = new Elysia34({
|
|
20239
20389
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
20240
20390
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
20241
20391
|
if (htmlPath) {
|
|
@@ -20547,9 +20697,9 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
20547
20697
|
};
|
|
20548
20698
|
};
|
|
20549
20699
|
// src/sessionReplay.ts
|
|
20550
|
-
import { Elysia as
|
|
20700
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
20551
20701
|
var getString12 = (value) => typeof value === "string" ? value : undefined;
|
|
20552
|
-
var
|
|
20702
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
20553
20703
|
var increment4 = (record, key) => {
|
|
20554
20704
|
record[key] = (record[key] ?? 0) + 1;
|
|
20555
20705
|
};
|
|
@@ -20743,10 +20893,10 @@ var summarizeVoiceSessions = async (options = {}) => {
|
|
|
20743
20893
|
var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="voice-sessions-empty">No voice sessions found.</p>' : [
|
|
20744
20894
|
'<div class="voice-sessions-list">',
|
|
20745
20895
|
...sessions.map((session) => [
|
|
20746
|
-
`<article class="voice-session-card ${
|
|
20896
|
+
`<article class="voice-session-card ${escapeHtml36(session.status)}">`,
|
|
20747
20897
|
'<div class="voice-session-card-header">',
|
|
20748
|
-
`<strong>${
|
|
20749
|
-
`<span>${
|
|
20898
|
+
`<strong>${escapeHtml36(session.sessionId)}</strong>`,
|
|
20899
|
+
`<span>${escapeHtml36(session.status)}</span>`,
|
|
20750
20900
|
"</div>",
|
|
20751
20901
|
"<dl>",
|
|
20752
20902
|
`<div><dt>Events</dt><dd>${String(session.eventCount)}</dd></div>`,
|
|
@@ -20754,9 +20904,9 @@ var renderVoiceSessionsHTML = (sessions) => sessions.length === 0 ? '<p class="v
|
|
|
20754
20904
|
`<div><dt>Transcripts</dt><dd>${String(session.transcriptCount)}</dd></div>`,
|
|
20755
20905
|
`<div><dt>Errors</dt><dd>${String(session.errorCount)}</dd></div>`,
|
|
20756
20906
|
"</dl>",
|
|
20757
|
-
session.latestOutcome ? `<p>Outcome: ${
|
|
20758
|
-
session.providers.length ? `<p>Providers: ${session.providers.map(
|
|
20759
|
-
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${
|
|
20907
|
+
session.latestOutcome ? `<p>Outcome: ${escapeHtml36(session.latestOutcome)}</p>` : "",
|
|
20908
|
+
session.providers.length ? `<p>Providers: ${session.providers.map(escapeHtml36).join(", ")}</p>` : "",
|
|
20909
|
+
session.replayHref ? `<p>${session.operationsRecordHref ? `<a href="${escapeHtml36(session.operationsRecordHref)}">Open operations record</a> \xB7 ` : ""}<a href="${escapeHtml36(session.replayHref)}">Open replay</a></p>` : "",
|
|
20760
20910
|
"</article>"
|
|
20761
20911
|
].join("")),
|
|
20762
20912
|
"</div>"
|
|
@@ -20787,7 +20937,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
|
|
|
20787
20937
|
var createVoiceSessionListRoutes = (options = {}) => {
|
|
20788
20938
|
const path = options.path ?? "/api/voice-sessions";
|
|
20789
20939
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20790
|
-
const routes = new
|
|
20940
|
+
const routes = new Elysia35({
|
|
20791
20941
|
name: options.name ?? "absolutejs-voice-session-list"
|
|
20792
20942
|
}).get(path, createVoiceSessionsJSONHandler(options));
|
|
20793
20943
|
if (htmlPath) {
|
|
@@ -20815,7 +20965,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
|
|
|
20815
20965
|
var createVoiceSessionReplayRoutes = (options) => {
|
|
20816
20966
|
const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
|
|
20817
20967
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
20818
|
-
const routes = new
|
|
20968
|
+
const routes = new Elysia35({
|
|
20819
20969
|
name: options.name ?? "absolutejs-voice-session-replay"
|
|
20820
20970
|
}).get(path, createVoiceSessionReplayJSONHandler(options));
|
|
20821
20971
|
if (htmlPath) {
|
|
@@ -21129,10 +21279,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
21129
21279
|
return report;
|
|
21130
21280
|
};
|
|
21131
21281
|
// src/turnLatency.ts
|
|
21132
|
-
import { Elysia as
|
|
21282
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
21133
21283
|
var DEFAULT_WARN_AFTER_MS = 1800;
|
|
21134
21284
|
var DEFAULT_FAIL_AFTER_MS = 3200;
|
|
21135
|
-
var
|
|
21285
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21136
21286
|
var firstNumber2 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
21137
21287
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
21138
21288
|
var createTraceStageIndex = (events) => {
|
|
@@ -21264,11 +21414,11 @@ await traceStore.append({
|
|
|
21264
21414
|
turnId,
|
|
21265
21415
|
type: 'turn_latency.stage'
|
|
21266
21416
|
});`;
|
|
21267
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
21268
|
-
<header><div><p class="eyebrow">${
|
|
21269
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
21417
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml37(turn.status)}">
|
|
21418
|
+
<header><div><p class="eyebrow">${escapeHtml37(turn.sessionId)} \xB7 ${escapeHtml37(turn.turnId)}</p><h2>${escapeHtml37(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml37(turn.status)}</strong></header>
|
|
21419
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml37(stage.label)}</dt><dd>${escapeHtml37(formatMs2(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
21270
21420
|
</article>`).join("");
|
|
21271
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21421
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml37(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>${escapeHtml37(title)}</h1><div class="summary"><span class="pill ${escapeHtml37(report.status)}">${escapeHtml37(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml37(formatMs2(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>${escapeHtml37(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
21272
21422
|
};
|
|
21273
21423
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
21274
21424
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -21285,7 +21435,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
21285
21435
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
21286
21436
|
const path = options.path ?? "/api/turn-latency";
|
|
21287
21437
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
21288
|
-
const routes = new
|
|
21438
|
+
const routes = new Elysia36({
|
|
21289
21439
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
21290
21440
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
21291
21441
|
if (htmlPath) {
|
|
@@ -21294,8 +21444,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
21294
21444
|
return routes;
|
|
21295
21445
|
};
|
|
21296
21446
|
// src/liveLatency.ts
|
|
21297
|
-
import { Elysia as
|
|
21298
|
-
var
|
|
21447
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
21448
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21299
21449
|
var percentile3 = (values, percentileValue) => {
|
|
21300
21450
|
if (values.length === 0) {
|
|
21301
21451
|
return;
|
|
@@ -21362,13 +21512,13 @@ await traceStore.append({
|
|
|
21362
21512
|
sessionId,
|
|
21363
21513
|
type: 'client.live_latency'
|
|
21364
21514
|
});`;
|
|
21365
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
21366
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21515
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml38(sample.sessionId)}</td><td>${escapeHtml38(formatMs3(sample.latencyMs))}</td><td>${escapeHtml38(sample.status ?? "unknown")}</td><td>${escapeHtml38(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
21516
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(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>${escapeHtml38(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml38(report.status)}">Status: ${escapeHtml38(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml38(formatMs3(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml38(formatMs3(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml38(formatMs3(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>${escapeHtml38(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>`;
|
|
21367
21517
|
};
|
|
21368
21518
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
21369
21519
|
const path = options.path ?? "/api/live-latency";
|
|
21370
21520
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
21371
|
-
const routes = new
|
|
21521
|
+
const routes = new Elysia37({
|
|
21372
21522
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
21373
21523
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
21374
21524
|
if (htmlPath) {
|
|
@@ -21687,9 +21837,9 @@ None.
|
|
|
21687
21837
|
`}`;
|
|
21688
21838
|
};
|
|
21689
21839
|
// src/turnQuality.ts
|
|
21690
|
-
import { Elysia as
|
|
21840
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
21691
21841
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
21692
|
-
var
|
|
21842
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21693
21843
|
var getTurnLatencyMs = (turn) => {
|
|
21694
21844
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
21695
21845
|
if (firstTranscriptAt === undefined) {
|
|
@@ -21760,24 +21910,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
21760
21910
|
};
|
|
21761
21911
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
21762
21912
|
const title = options.title ?? "Voice Turn Quality";
|
|
21763
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
21913
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml39(turn.status)}">
|
|
21764
21914
|
<div class="turn-header">
|
|
21765
21915
|
<div>
|
|
21766
|
-
<p class="eyebrow">${
|
|
21767
|
-
<h2>${
|
|
21916
|
+
<p class="eyebrow">${escapeHtml39(turn.sessionId)} \xB7 ${escapeHtml39(turn.turnId)}</p>
|
|
21917
|
+
<h2>${escapeHtml39(turn.text || "Empty turn")}</h2>
|
|
21768
21918
|
</div>
|
|
21769
|
-
<strong>${
|
|
21919
|
+
<strong>${escapeHtml39(turn.status)}</strong>
|
|
21770
21920
|
</div>
|
|
21771
21921
|
<dl>
|
|
21772
|
-
<div><dt>Source</dt><dd>${
|
|
21922
|
+
<div><dt>Source</dt><dd>${escapeHtml39(turn.source ?? "unknown")}</dd></div>
|
|
21773
21923
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
21774
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
21775
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
21924
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml39(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
21925
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml39(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
21776
21926
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
21777
21927
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
21778
21928
|
</dl>
|
|
21779
21929
|
</article>`).join("");
|
|
21780
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21930
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml39(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>${escapeHtml39(title)}</h1><div class="summary"><span class="pill ${escapeHtml39(report.status)}">${escapeHtml39(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>`;
|
|
21781
21931
|
};
|
|
21782
21932
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
21783
21933
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -21794,7 +21944,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
21794
21944
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
21795
21945
|
const path = options.path ?? "/api/turn-quality";
|
|
21796
21946
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
21797
|
-
const routes = new
|
|
21947
|
+
const routes = new Elysia38({
|
|
21798
21948
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
21799
21949
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
21800
21950
|
if (htmlPath) {
|
|
@@ -21803,7 +21953,7 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
21803
21953
|
return routes;
|
|
21804
21954
|
};
|
|
21805
21955
|
// src/telephonyOutcome.ts
|
|
21806
|
-
import { Elysia as
|
|
21956
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
21807
21957
|
var DEFAULT_COMPLETED_STATUSES = [
|
|
21808
21958
|
"answered",
|
|
21809
21959
|
"completed",
|
|
@@ -22564,7 +22714,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
|
22564
22714
|
var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
22565
22715
|
const path = options.path ?? "/api/voice/telephony/webhook";
|
|
22566
22716
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
22567
|
-
return new
|
|
22717
|
+
return new Elysia39({
|
|
22568
22718
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
22569
22719
|
}).post(path, async ({ query, request }) => {
|
|
22570
22720
|
try {
|
|
@@ -22585,12 +22735,12 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
22585
22735
|
});
|
|
22586
22736
|
};
|
|
22587
22737
|
// src/phoneAgent.ts
|
|
22588
|
-
import { Elysia as
|
|
22738
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
22589
22739
|
|
|
22590
22740
|
// src/telephony/plivo.ts
|
|
22591
22741
|
import { Buffer as Buffer5 } from "buffer";
|
|
22592
22742
|
import { Database } from "bun:sqlite";
|
|
22593
|
-
import { Elysia as
|
|
22743
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
22594
22744
|
|
|
22595
22745
|
// src/telephony/contract.ts
|
|
22596
22746
|
var DEFAULT_REQUIREMENTS = [
|
|
@@ -22674,7 +22824,7 @@ var evaluateVoiceTelephonyContract = (input) => {
|
|
|
22674
22824
|
|
|
22675
22825
|
// src/telephony/twilio.ts
|
|
22676
22826
|
import { Buffer as Buffer4 } from "buffer";
|
|
22677
|
-
import { Elysia as
|
|
22827
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
22678
22828
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
22679
22829
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
22680
22830
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -22704,7 +22854,7 @@ var resolveTwilioStreamParameters = async (parameters, input) => {
|
|
|
22704
22854
|
return parameters;
|
|
22705
22855
|
};
|
|
22706
22856
|
var joinUrlPath2 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
22707
|
-
var
|
|
22857
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
22708
22858
|
var getWebhookVerificationUrl = (webhook, input) => {
|
|
22709
22859
|
if (!webhook?.verificationUrl) {
|
|
22710
22860
|
return;
|
|
@@ -22747,23 +22897,23 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
|
|
|
22747
22897
|
};
|
|
22748
22898
|
var renderTwilioVoiceSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22749
22899
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio setup</p>
|
|
22750
|
-
<h1>${
|
|
22900
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
22751
22901
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
22752
22902
|
<section>
|
|
22753
22903
|
<h2>URLs</h2>
|
|
22754
22904
|
<ul>
|
|
22755
|
-
<li><strong>TwiML:</strong> <code>${
|
|
22756
|
-
<li><strong>Media stream:</strong> <code>${
|
|
22757
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
22905
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml40(status.urls.twiml)}</code></li>
|
|
22906
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml40(status.urls.stream)}</code></li>
|
|
22907
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml40(status.urls.webhook)}</code></li>
|
|
22758
22908
|
</ul>
|
|
22759
22909
|
</section>
|
|
22760
22910
|
<section>
|
|
22761
22911
|
<h2>Signing</h2>
|
|
22762
22912
|
<p>Mode: <code>${status.signing.mode}</code></p>
|
|
22763
|
-
${status.signing.verificationUrl ? `<p>Verification URL: <code>${
|
|
22913
|
+
${status.signing.verificationUrl ? `<p>Verification URL: <code>${escapeHtml40(status.signing.verificationUrl)}</code></p>` : ""}
|
|
22764
22914
|
</section>
|
|
22765
|
-
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
22766
|
-
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
22915
|
+
${status.missing.length ? `<section><h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml40(name)}</code></li>`).join("")}</ul></section>` : ""}
|
|
22916
|
+
${status.warnings.length ? `<section><h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml40(warning)}</li>`).join("")}</ul></section>` : ""}
|
|
22767
22917
|
</main>`;
|
|
22768
22918
|
var extractTwilioStreamUrl = (twiml) => twiml.match(/<Stream\b[^>]*\surl="([^"]+)"/i)?.[1]?.replaceAll("&", "&");
|
|
22769
22919
|
var createSmokeCheck = (name, status, message, details) => ({
|
|
@@ -22774,20 +22924,20 @@ var createSmokeCheck = (name, status, message, details) => ({
|
|
|
22774
22924
|
});
|
|
22775
22925
|
var renderTwilioVoiceSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
22776
22926
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Twilio smoke test</p>
|
|
22777
|
-
<h1>${
|
|
22927
|
+
<h1>${escapeHtml40(title)}</h1>
|
|
22778
22928
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
22779
22929
|
<section>
|
|
22780
22930
|
<h2>Checks</h2>
|
|
22781
22931
|
<ul>
|
|
22782
|
-
${report.checks.map((check) => `<li><strong>${
|
|
22932
|
+
${report.checks.map((check) => `<li><strong>${escapeHtml40(check.name)}</strong>: ${escapeHtml40(check.status)}${check.message ? ` - ${escapeHtml40(check.message)}` : ""}</li>`).join("")}
|
|
22783
22933
|
</ul>
|
|
22784
22934
|
</section>
|
|
22785
22935
|
<section>
|
|
22786
22936
|
<h2>Observed URLs</h2>
|
|
22787
22937
|
<ul>
|
|
22788
|
-
<li><strong>TwiML:</strong> <code>${
|
|
22789
|
-
<li><strong>Stream:</strong> <code>${
|
|
22790
|
-
<li><strong>Webhook:</strong> <code>${
|
|
22938
|
+
<li><strong>TwiML:</strong> <code>${escapeHtml40(report.setup.urls.twiml)}</code></li>
|
|
22939
|
+
<li><strong>Stream:</strong> <code>${escapeHtml40(report.twiml?.streamUrl ?? report.setup.urls.stream)}</code></li>
|
|
22940
|
+
<li><strong>Webhook:</strong> <code>${escapeHtml40(report.setup.urls.webhook)}</code></li>
|
|
22791
22941
|
</ul>
|
|
22792
22942
|
</section>
|
|
22793
22943
|
</main>`;
|
|
@@ -23333,7 +23483,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
23333
23483
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
|
|
23334
23484
|
const bridges = new WeakMap;
|
|
23335
23485
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
23336
|
-
const app = new
|
|
23486
|
+
const app = new Elysia40({
|
|
23337
23487
|
name: options.name ?? "absolutejs-voice-twilio"
|
|
23338
23488
|
}).get(twimlPath, async ({ query, request }) => {
|
|
23339
23489
|
const streamUrl = await resolveTwilioStreamUrl(options, {
|
|
@@ -23470,7 +23620,7 @@ var createTwilioVoiceRoutes = (options) => {
|
|
|
23470
23620
|
|
|
23471
23621
|
// src/telephony/plivo.ts
|
|
23472
23622
|
var escapeXml3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23473
|
-
var
|
|
23623
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
23474
23624
|
var joinUrlPath3 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
23475
23625
|
var resolveRequestOrigin2 = (request) => {
|
|
23476
23626
|
const url = new URL(request.url);
|
|
@@ -23901,21 +24051,21 @@ var buildPlivoVoiceSetupStatus = async (options, input) => {
|
|
|
23901
24051
|
};
|
|
23902
24052
|
var renderPlivoSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23903
24053
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo setup</p>
|
|
23904
|
-
<h1>${
|
|
24054
|
+
<h1>${escapeHtml41(title)}</h1>
|
|
23905
24055
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
23906
24056
|
<ul>
|
|
23907
|
-
<li><strong>Answer XML:</strong> <code>${
|
|
23908
|
-
<li><strong>Audio stream:</strong> <code>${
|
|
23909
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
24057
|
+
<li><strong>Answer XML:</strong> <code>${escapeHtml41(status.urls.answer)}</code></li>
|
|
24058
|
+
<li><strong>Audio stream:</strong> <code>${escapeHtml41(status.urls.stream)}</code></li>
|
|
24059
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml41(status.urls.webhook)}</code></li>
|
|
23910
24060
|
</ul>
|
|
23911
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
23912
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
24061
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml41(name)}</code></li>`).join("")}</ul>` : ""}
|
|
24062
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml41(warning)}</li>`).join("")}</ul>` : ""}
|
|
23913
24063
|
</main>`;
|
|
23914
24064
|
var renderPlivoSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
23915
24065
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Plivo smoke test</p>
|
|
23916
|
-
<h1>${
|
|
24066
|
+
<h1>${escapeHtml41(title)}</h1>
|
|
23917
24067
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
23918
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
24068
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml41(check.name)}</strong>: ${escapeHtml41(check.status)}${check.message ? ` - ${escapeHtml41(check.message)}` : ""}</li>`).join("")}</ul>
|
|
23919
24069
|
</main>`;
|
|
23920
24070
|
var runPlivoSmokeTest = async (input) => {
|
|
23921
24071
|
const setup = await buildPlivoVoiceSetupStatus(input.options, input);
|
|
@@ -24005,7 +24155,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
24005
24155
|
nonceStore: options.webhook.nonceStore,
|
|
24006
24156
|
verificationUrl: options.webhook.verificationUrl
|
|
24007
24157
|
}) : undefined);
|
|
24008
|
-
const app = new
|
|
24158
|
+
const app = new Elysia41({
|
|
24009
24159
|
name: options.name ?? "absolutejs-voice-plivo"
|
|
24010
24160
|
}).get(answerPath, async ({ query, request }) => {
|
|
24011
24161
|
const streamUrl = await resolvePlivoStreamUrl(options, {
|
|
@@ -24117,9 +24267,9 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
24117
24267
|
// src/telephony/telnyx.ts
|
|
24118
24268
|
import { Buffer as Buffer6 } from "buffer";
|
|
24119
24269
|
import { Database as Database2 } from "bun:sqlite";
|
|
24120
|
-
import { Elysia as
|
|
24270
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
24121
24271
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24122
|
-
var
|
|
24272
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24123
24273
|
var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
24124
24274
|
var resolveRequestOrigin3 = (request) => {
|
|
24125
24275
|
const url = new URL(request.url);
|
|
@@ -24513,21 +24663,21 @@ var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
|
24513
24663
|
};
|
|
24514
24664
|
var renderTelnyxSetupHTML = (status, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
24515
24665
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx setup</p>
|
|
24516
|
-
<h1>${
|
|
24666
|
+
<h1>${escapeHtml42(title)}</h1>
|
|
24517
24667
|
<p><strong>Status:</strong> ${status.ready ? "Ready" : "Needs attention"}</p>
|
|
24518
24668
|
<ul>
|
|
24519
|
-
<li><strong>TeXML:</strong> <code>${
|
|
24520
|
-
<li><strong>Media stream:</strong> <code>${
|
|
24521
|
-
<li><strong>Status webhook:</strong> <code>${
|
|
24669
|
+
<li><strong>TeXML:</strong> <code>${escapeHtml42(status.urls.texml)}</code></li>
|
|
24670
|
+
<li><strong>Media stream:</strong> <code>${escapeHtml42(status.urls.stream)}</code></li>
|
|
24671
|
+
<li><strong>Status webhook:</strong> <code>${escapeHtml42(status.urls.webhook)}</code></li>
|
|
24522
24672
|
</ul>
|
|
24523
|
-
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${
|
|
24524
|
-
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${
|
|
24673
|
+
${status.missing.length ? `<h2>Missing env</h2><ul>${status.missing.map((name) => `<li><code>${escapeHtml42(name)}</code></li>`).join("")}</ul>` : ""}
|
|
24674
|
+
${status.warnings.length ? `<h2>Warnings</h2><ul>${status.warnings.map((warning) => `<li>${escapeHtml42(warning)}</li>`).join("")}</ul>` : ""}
|
|
24525
24675
|
</main>`;
|
|
24526
24676
|
var renderTelnyxSmokeHTML = (report, title) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 860px; margin: 40px auto; padding: 0 20px;">
|
|
24527
24677
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Telnyx smoke test</p>
|
|
24528
|
-
<h1>${
|
|
24678
|
+
<h1>${escapeHtml42(title)}</h1>
|
|
24529
24679
|
<p><strong>Status:</strong> ${report.pass ? "Pass" : "Fail"}</p>
|
|
24530
|
-
<ul>${report.checks.map((check) => `<li><strong>${
|
|
24680
|
+
<ul>${report.checks.map((check) => `<li><strong>${escapeHtml42(check.name)}</strong>: ${escapeHtml42(check.status)}${check.message ? ` - ${escapeHtml42(check.message)}` : ""}</li>`).join("")}</ul>
|
|
24531
24681
|
</main>`;
|
|
24532
24682
|
var runTelnyxSmokeTest = async (input) => {
|
|
24533
24683
|
const setup = await buildTelnyxVoiceSetupStatus(input.options, input);
|
|
@@ -24620,7 +24770,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
24620
24770
|
publicKey: options.webhook.publicKey,
|
|
24621
24771
|
toleranceSeconds: options.webhook.toleranceSeconds
|
|
24622
24772
|
}) : undefined);
|
|
24623
|
-
const app = new
|
|
24773
|
+
const app = new Elysia42({
|
|
24624
24774
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
24625
24775
|
}).get(texmlPath, async ({ query, request }) => {
|
|
24626
24776
|
const streamUrl = await resolveTelnyxStreamUrl(options, {
|
|
@@ -24730,8 +24880,8 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
24730
24880
|
};
|
|
24731
24881
|
|
|
24732
24882
|
// src/telephony/matrix.ts
|
|
24733
|
-
import { Elysia as
|
|
24734
|
-
var
|
|
24883
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
24884
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
24735
24885
|
var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
|
|
24736
24886
|
var resolveEntryStatus = (contract, setup, smoke) => {
|
|
24737
24887
|
if (!contract.pass || !setup.ready || smoke?.pass === false) {
|
|
@@ -24792,13 +24942,13 @@ var badgeStyles = {
|
|
|
24792
24942
|
};
|
|
24793
24943
|
var renderVoiceTelephonyCarrierMatrixHTML = (matrix, options = {}) => `<main style="font-family: ui-sans-serif, system-ui; max-width: 1040px; margin: 40px auto; padding: 0 20px; color: #172033;">
|
|
24794
24944
|
<p style="letter-spacing: .12em; text-transform: uppercase; color: #52606d;">Carrier matrix</p>
|
|
24795
|
-
<h1 style="font-size: 34px; margin: 0 0 8px;">${
|
|
24945
|
+
<h1 style="font-size: 34px; margin: 0 0 8px;">${escapeHtml43(options.title ?? "AbsoluteJS Voice Carrier Matrix")}</h1>
|
|
24796
24946
|
<p style="color:#52606d; margin: 0 0 24px;">${matrix.summary.ready}/${matrix.summary.providers} ready, ${matrix.summary.contractsPassing}/${matrix.summary.providers} contract passing, ${matrix.summary.smokePassing}/${matrix.summary.providers} smoke passing.</p>
|
|
24797
24947
|
<section style="display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px;">
|
|
24798
24948
|
${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; border-radius:18px; padding:18px; background:#fff; box-shadow:0 18px 48px rgba(15,23,42,.08);">
|
|
24799
24949
|
<div style="display:flex; justify-content:space-between; gap:12px; align-items:center;">
|
|
24800
|
-
<h2 style="margin:0; font-size:20px;">${
|
|
24801
|
-
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${
|
|
24950
|
+
<h2 style="margin:0; font-size:20px;">${escapeHtml43(entry.name)}</h2>
|
|
24951
|
+
<span style="border:1px solid; border-radius:999px; padding:4px 10px; font-size:12px; font-weight:700; ${badgeStyles[entry.status]}">${escapeHtml43(entry.status.toUpperCase())}</span>
|
|
24802
24952
|
</div>
|
|
24803
24953
|
<dl style="display:grid; grid-template-columns: 1fr 1fr; gap:8px 12px; margin:16px 0;">
|
|
24804
24954
|
<dt style="color:#64748b;">Setup</dt><dd style="margin:0; font-weight:700;">${entry.ready ? "Ready" : "Needs attention"}</dd>
|
|
@@ -24806,15 +24956,15 @@ ${matrix.entries.map((entry) => `<article style="border:1px solid #d9e2ec; borde
|
|
|
24806
24956
|
<dt style="color:#64748b;">Smoke</dt><dd style="margin:0; font-weight:700;">${entry.smoke ? entry.smoke.pass ? "Pass" : "Fail" : "Missing"}</dd>
|
|
24807
24957
|
<dt style="color:#64748b;">Contract</dt><dd style="margin:0; font-weight:700;">${entry.contract.pass ? "Pass" : "Fail"}</dd>
|
|
24808
24958
|
</dl>
|
|
24809
|
-
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${
|
|
24810
|
-
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${
|
|
24811
|
-
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${
|
|
24959
|
+
<p style="margin:0 0 8px; color:#475569;"><strong>Stream:</strong> <code>${escapeHtml43(entry.setup.urls.stream || "missing")}</code></p>
|
|
24960
|
+
<p style="margin:0 0 12px; color:#475569;"><strong>Webhook:</strong> <code>${escapeHtml43(entry.setup.urls.webhook || "missing")}</code></p>
|
|
24961
|
+
${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry.issues.map((issue) => `<li>${escapeHtml43(issue.severity)}: ${escapeHtml43(issue.message)}</li>`).join("")}</ul>` : '<p style="margin:12px 0 0; color:#166534;">No contract issues.</p>'}
|
|
24812
24962
|
</article>`).join("")}
|
|
24813
24963
|
</section>
|
|
24814
24964
|
</main>`;
|
|
24815
24965
|
var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
24816
24966
|
const path = options.path ?? "/api/voice/telephony/carriers";
|
|
24817
|
-
return new
|
|
24967
|
+
return new Elysia43({
|
|
24818
24968
|
name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
|
|
24819
24969
|
}).get(path, async ({ query, request }) => {
|
|
24820
24970
|
const providers = await options.load({ query, request });
|
|
@@ -24836,7 +24986,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
|
|
|
24836
24986
|
};
|
|
24837
24987
|
|
|
24838
24988
|
// src/phoneAgentProductionSmoke.ts
|
|
24839
|
-
import { Elysia as
|
|
24989
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
24840
24990
|
var defaultRequirements = [
|
|
24841
24991
|
"media-started",
|
|
24842
24992
|
"transcript",
|
|
@@ -24844,7 +24994,7 @@ var defaultRequirements = [
|
|
|
24844
24994
|
"lifecycle-outcome",
|
|
24845
24995
|
"no-session-error"
|
|
24846
24996
|
];
|
|
24847
|
-
var
|
|
24997
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
24848
24998
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
24849
24999
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
24850
25000
|
const value = event.payload[key];
|
|
@@ -24953,10 +25103,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
24953
25103
|
});
|
|
24954
25104
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
24955
25105
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
24956
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
24957
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
24958
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
24959
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25106
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml44(issue.requirement)}</strong>: ${escapeHtml44(issue.message)}</li>`).join("");
|
|
25107
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml44(outcome)}</span>`).join("");
|
|
25108
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml44(requirement)}</span>`).join("");
|
|
25109
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml44(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>${escapeHtml44(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml44(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml44(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml44(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>`;
|
|
24960
25110
|
};
|
|
24961
25111
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
24962
25112
|
query,
|
|
@@ -24979,7 +25129,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
24979
25129
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
24980
25130
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
24981
25131
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
24982
|
-
const routes = new
|
|
25132
|
+
const routes = new Elysia44({
|
|
24983
25133
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
24984
25134
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
24985
25135
|
if (htmlPath) {
|
|
@@ -25022,7 +25172,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
25022
25172
|
"completed",
|
|
25023
25173
|
"failed"
|
|
25024
25174
|
];
|
|
25025
|
-
var
|
|
25175
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
25026
25176
|
var loadRouteJson = async (input) => {
|
|
25027
25177
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
25028
25178
|
headers: {
|
|
@@ -25260,10 +25410,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
25260
25410
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
25261
25411
|
const urls = entry?.setup.urls;
|
|
25262
25412
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
25263
|
-
return `<tr><td>${
|
|
25413
|
+
return `<tr><td>${escapeHtml45(carrier.name ?? carrier.provider)}</td><td>${escapeHtml45(carrier.provider)}</td><td><code>${escapeHtml45(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml45(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml45(entry.status)}">${escapeHtml45(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml45(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml45(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml45(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
25264
25414
|
}).join("");
|
|
25265
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
25266
|
-
const snippet =
|
|
25415
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml45(stage)}</code></li>`).join("");
|
|
25416
|
+
const snippet = escapeHtml45(`const phoneAgent = createVoicePhoneAgent({
|
|
25267
25417
|
carriers: [
|
|
25268
25418
|
{
|
|
25269
25419
|
provider: 'twilio',
|
|
@@ -25297,11 +25447,11 @@ app.use(
|
|
|
25297
25447
|
);`);
|
|
25298
25448
|
const checklist = report.carriers.map((carrier) => {
|
|
25299
25449
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
25300
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
25301
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
25302
|
-
return `<article><h3>${
|
|
25450
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml45(issue)}</li>`).join("") ?? "";
|
|
25451
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml45(step)}</li>`).join("") ?? "";
|
|
25452
|
+
return `<article><h3>${escapeHtml45(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
25303
25453
|
}).join("");
|
|
25304
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25454
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(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="${escapeHtml45(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>`;
|
|
25305
25455
|
};
|
|
25306
25456
|
var createVoicePhoneAgent = (options) => {
|
|
25307
25457
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -25310,7 +25460,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
25310
25460
|
setupPath: resolveSetupPath(carrier),
|
|
25311
25461
|
smokePath: resolveSmokePath(carrier)
|
|
25312
25462
|
}));
|
|
25313
|
-
const app = new
|
|
25463
|
+
const app = new Elysia45({
|
|
25314
25464
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
25315
25465
|
});
|
|
25316
25466
|
for (const carrier of options.carriers) {
|
|
@@ -26940,8 +27090,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
26940
27090
|
};
|
|
26941
27091
|
};
|
|
26942
27092
|
// src/providerCapabilities.ts
|
|
26943
|
-
import { Elysia as
|
|
26944
|
-
var
|
|
27093
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
27094
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
26945
27095
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
26946
27096
|
configured: true,
|
|
26947
27097
|
features: options.features?.[provider],
|
|
@@ -27004,27 +27154,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
27004
27154
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
27005
27155
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
27006
27156
|
const cards = report.capabilities.map((capability) => {
|
|
27007
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
27008
|
-
return `<article class="card ${
|
|
27157
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml46(feature)}</span>`).join("");
|
|
27158
|
+
return `<article class="card ${escapeHtml46(capability.status)}">
|
|
27009
27159
|
<div class="card-header">
|
|
27010
27160
|
<div>
|
|
27011
|
-
<p class="eyebrow">${
|
|
27012
|
-
<h2>${
|
|
27161
|
+
<p class="eyebrow">${escapeHtml46(capability.kind)}</p>
|
|
27162
|
+
<h2>${escapeHtml46(capability.label ?? capability.provider)}</h2>
|
|
27013
27163
|
</div>
|
|
27014
|
-
<strong>${
|
|
27164
|
+
<strong>${escapeHtml46(capability.status)}</strong>
|
|
27015
27165
|
</div>
|
|
27016
|
-
${capability.description ? `<p>${
|
|
27166
|
+
${capability.description ? `<p>${escapeHtml46(capability.description)}</p>` : ""}
|
|
27017
27167
|
<dl>
|
|
27018
27168
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
27019
27169
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
27020
|
-
<div><dt>Model</dt><dd>${
|
|
27170
|
+
<div><dt>Model</dt><dd>${escapeHtml46(capability.model ?? "default")}</dd></div>
|
|
27021
27171
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
27022
27172
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
27023
27173
|
</dl>
|
|
27024
27174
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
27025
27175
|
</article>`;
|
|
27026
27176
|
}).join("");
|
|
27027
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27177
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml46(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>${escapeHtml46(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>`;
|
|
27028
27178
|
};
|
|
27029
27179
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
27030
27180
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -27041,7 +27191,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
27041
27191
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
27042
27192
|
const path = options.path ?? "/api/provider-capabilities";
|
|
27043
27193
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
27044
|
-
const routes = new
|
|
27194
|
+
const routes = new Elysia46({
|
|
27045
27195
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
27046
27196
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
27047
27197
|
if (htmlPath) {
|
|
@@ -27050,7 +27200,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
27050
27200
|
return routes;
|
|
27051
27201
|
};
|
|
27052
27202
|
// src/providerOrchestration.ts
|
|
27053
|
-
import { Elysia as
|
|
27203
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
27054
27204
|
var defaultRequirement = {
|
|
27055
27205
|
minProviders: 1,
|
|
27056
27206
|
requireBudgetPolicy: false,
|
|
@@ -27063,7 +27213,7 @@ var statusRank4 = {
|
|
|
27063
27213
|
warn: 1,
|
|
27064
27214
|
fail: 2
|
|
27065
27215
|
};
|
|
27066
|
-
var
|
|
27216
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27067
27217
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
27068
27218
|
var uniqueSorted6 = (values) => [
|
|
27069
27219
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -27206,27 +27356,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
27206
27356
|
};
|
|
27207
27357
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
27208
27358
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
27209
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
27210
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
27359
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml47(surface.status)}">
|
|
27360
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml47(surface.surface)}</p><h2>${escapeHtml47(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml47(surface.status)}</strong></div>
|
|
27211
27361
|
<dl>
|
|
27212
|
-
<div><dt>Providers</dt><dd>${
|
|
27213
|
-
<div><dt>Fallback</dt><dd>${
|
|
27362
|
+
<div><dt>Providers</dt><dd>${escapeHtml47(surface.providers.join(", ") || "none")}</dd></div>
|
|
27363
|
+
<div><dt>Fallback</dt><dd>${escapeHtml47(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
27214
27364
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
27215
27365
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
27216
27366
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
27217
27367
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
27218
27368
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
27219
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
27369
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml47(surface.fallbackMode || "default")}</dd></div>
|
|
27220
27370
|
</dl>
|
|
27221
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
27371
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml47(issue.status)}</strong> ${escapeHtml47(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
27222
27372
|
</article>`).join("");
|
|
27223
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27373
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml47(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>${escapeHtml47(title)}</h1><div class="summary"><span class="pill">${escapeHtml47(report.profileId)}</span><span class="pill">${escapeHtml47(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>`;
|
|
27224
27374
|
};
|
|
27225
27375
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
27226
27376
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
27227
27377
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
27228
27378
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
27229
|
-
const routes = new
|
|
27379
|
+
const routes = new Elysia47({
|
|
27230
27380
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
27231
27381
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
27232
27382
|
if (htmlPath) {
|
|
@@ -27397,7 +27547,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
27397
27547
|
return report;
|
|
27398
27548
|
};
|
|
27399
27549
|
// src/providerSlo.ts
|
|
27400
|
-
import { Elysia as
|
|
27550
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
27401
27551
|
var defaultThresholds = {
|
|
27402
27552
|
llm: {
|
|
27403
27553
|
maxAverageElapsedMs: 2500,
|
|
@@ -27430,7 +27580,7 @@ var statusRank5 = {
|
|
|
27430
27580
|
warn: 1,
|
|
27431
27581
|
fail: 2
|
|
27432
27582
|
};
|
|
27433
|
-
var
|
|
27583
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27434
27584
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
27435
27585
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
27436
27586
|
var uniqueSorted7 = (values) => [
|
|
@@ -27726,11 +27876,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
27726
27876
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
27727
27877
|
const kindCards = providerKinds.map((kind) => {
|
|
27728
27878
|
const kindReport = report.kinds[kind];
|
|
27729
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
27879
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml48(metric.label)}</dt><dd>${escapeHtml48(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml48(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
27730
27880
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
27731
|
-
return `<article class="${
|
|
27881
|
+
return `<article class="${escapeHtml48(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml48(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml48(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
27732
27882
|
}).join("");
|
|
27733
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
27883
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml48(issue.status)}"><strong>${escapeHtml48(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml48(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
27734
27884
|
const snippet = `createVoiceProviderSloRoutes({
|
|
27735
27885
|
store: runtimeStorage.traces,
|
|
27736
27886
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -27740,7 +27890,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
27740
27890
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
27741
27891
|
}
|
|
27742
27892
|
})`;
|
|
27743
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
27893
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml48(title)}</title><style>body{background:#101318;color:#f8f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,article,.primitive{background:#171b22;border:1px solid #2c3340;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.2),rgba(245,158,11,.12))}.eyebrow{color:#7dd3fc;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.9rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status,article h2 span{border:1px solid #475569;border-radius:999px;display:inline-flex;font-size:.85rem;padding:6px 10px}.pass{border-color:rgba(34,197,94,.65)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}dt{color:#cbd5e1;font-size:.78rem;text-transform:uppercase}dd{font-size:1.7rem;font-weight:900;margin:0}small{color:#a8b3c2}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#101318;border:1px solid #2c3340;border-radius:16px;padding:12px}li span{color:#cbd5e1;display:block;margin-top:4px}.primitive{background:#11161d}.primitive code{color:#bae6fd}.primitive pre{background:#070b10;border:1px solid #243041;border-radius:16px;color:#e0f2fe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Provider latency and fallback proof</p><h1>${escapeHtml48(title)}</h1><p class="status ${escapeHtml48(report.status)}">${escapeHtml48(report.status)}</p><p>${report.events} provider routing event(s), ${report.eventsWithLatency} latency sample(s).</p></section><section class="grid">${kindCards}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderSloRoutes(...)</code> turns provider speed into release evidence</h2><p>Pair this report with production readiness so LLM/STT/TTS latency, timeout, fallback, and unresolved error regressions block deploys.</p><pre><code>${escapeHtml48(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
27744
27894
|
};
|
|
27745
27895
|
var createVoiceProviderSloRoutes = (options) => {
|
|
27746
27896
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -27751,7 +27901,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
27751
27901
|
...options.headers ?? {}
|
|
27752
27902
|
};
|
|
27753
27903
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
27754
|
-
const app = new
|
|
27904
|
+
const app = new Elysia48({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
27755
27905
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
27756
27906
|
if (markdownPath !== false) {
|
|
27757
27907
|
app.get(markdownPath, async () => {
|
|
@@ -27781,10 +27931,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
27781
27931
|
return app;
|
|
27782
27932
|
};
|
|
27783
27933
|
// src/productionReadiness.ts
|
|
27784
|
-
import { Elysia as
|
|
27934
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
27785
27935
|
|
|
27786
27936
|
// src/telephony/security.ts
|
|
27787
|
-
import { Elysia as
|
|
27937
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
27788
27938
|
|
|
27789
27939
|
// src/postgresStore.ts
|
|
27790
27940
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -28522,7 +28672,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
28522
28672
|
};
|
|
28523
28673
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
28524
28674
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
28525
|
-
return new
|
|
28675
|
+
return new Elysia49({
|
|
28526
28676
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
28527
28677
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
28528
28678
|
};
|
|
@@ -28579,8 +28729,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
28579
28729
|
};
|
|
28580
28730
|
|
|
28581
28731
|
// src/opsRecovery.ts
|
|
28582
|
-
import { Elysia as
|
|
28583
|
-
var
|
|
28732
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
28733
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28584
28734
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
28585
28735
|
var hrefForSession = (value, sessionId) => {
|
|
28586
28736
|
if (typeof value === "function") {
|
|
@@ -28794,19 +28944,19 @@ ${failedSessions || "None."}
|
|
|
28794
28944
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
28795
28945
|
`;
|
|
28796
28946
|
};
|
|
28797
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
28947
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml49(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml49(label)}</span><strong>not configured</strong></article>`;
|
|
28798
28948
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
28799
28949
|
const title = options.title ?? "Voice Ops Recovery";
|
|
28800
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
28801
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
28802
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
28803
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
28950
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml49(issue.severity)}</td><td><code>${escapeHtml49(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml49(issue.href)}">${escapeHtml49(issue.label)}</a>` : escapeHtml49(issue.label)}</td><td>${escapeHtml49(String(issue.value ?? ""))}</td><td>${escapeHtml49(issue.detail ?? "")}</td></tr>`).join("");
|
|
28951
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml49(provider.provider)}</td><td>${escapeHtml49(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml49(provider.lastError ?? "")}</td></tr>`).join("");
|
|
28952
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml49(session.operationsRecordHref)}">${escapeHtml49(session.sessionId)}</a>` : escapeHtml49(session.sessionId)}${session.provider ? ` via ${escapeHtml49(session.provider)}` : ""}${session.error ? `: ${escapeHtml49(session.error)}` : ""}</li>`).join("");
|
|
28953
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml49(title)}</title><style>body{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml49(title)}</h1><p><span class="status">${escapeHtml49(report.status)}</span> Checked ${escapeHtml49(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml49(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
|
|
28804
28954
|
};
|
|
28805
28955
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
28806
28956
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
28807
28957
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
28808
28958
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
28809
|
-
const routes = new
|
|
28959
|
+
const routes = new Elysia50({
|
|
28810
28960
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
28811
28961
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
28812
28962
|
if (htmlPath) {
|
|
@@ -28836,18 +28986,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
28836
28986
|
};
|
|
28837
28987
|
|
|
28838
28988
|
// src/observabilityExport.ts
|
|
28839
|
-
import { Elysia as
|
|
28989
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
28840
28990
|
import { Database as Database4 } from "bun:sqlite";
|
|
28841
28991
|
import { createHash } from "crypto";
|
|
28842
28992
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
28843
28993
|
import { join as join3 } from "path";
|
|
28844
28994
|
|
|
28845
28995
|
// src/operationsRecord.ts
|
|
28846
|
-
import { Elysia as
|
|
28996
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
28847
28997
|
|
|
28848
28998
|
// src/traceTimeline.ts
|
|
28849
|
-
import { Elysia as
|
|
28850
|
-
var
|
|
28999
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
29000
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
28851
29001
|
var getString16 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
28852
29002
|
var getNumber9 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
28853
29003
|
var firstString4 = (payload, keys) => {
|
|
@@ -29030,17 +29180,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
29030
29180
|
};
|
|
29031
29181
|
};
|
|
29032
29182
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
29033
|
-
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${
|
|
29183
|
+
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${escapeHtml50(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs4(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs4(provider.maxElapsedMs)}</dd></div><div><dt>Errors</dt><dd>${String(provider.errorCount)}</dd></div><div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div><div><dt>Timeouts</dt><dd>${String(provider.timeoutCount)}</dd></div></dl></article>`).join("")}</div>`;
|
|
29034
29184
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
29035
|
-
const events = session.events.map((event) => `<tr class="${
|
|
29036
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
29037
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
29038
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
29185
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml50(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml50(event.type)}</td><td>${escapeHtml50(event.label)}</td><td>${escapeHtml50(event.provider ?? "")}</td><td>${escapeHtml50(event.status ?? "")}</td><td>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
29186
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml50(issue.severity)}">${escapeHtml50(issue.code)}: ${escapeHtml50(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
29187
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml50(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
29188
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(options.title ?? "Voice Trace Timeline")}</title><style>${timelineCSS}</style></head><body><main><a href="/traces">Back to traces</a><header><p class="eyebrow">Call timeline</p><h1>${escapeHtml50(session.sessionId)}</h1><p class="status ${escapeHtml50(session.status)}">${escapeHtml50(session.status)}</p>${supportLinks}</header><section class="metrics"><article><span>Events</span><strong>${String(session.summary.eventCount)}</strong></article><article><span>Turns</span><strong>${String(session.summary.turnCount)}</strong></article><article><span>Errors</span><strong>${String(session.summary.errorCount)}</strong></article><article><span>Duration</span><strong>${formatMs4(session.summary.callDurationMs)}</strong></article></section><section><h2>Providers</h2>${renderProviderCards2(session)}</section><section><h2>Issues</h2><ul>${issues}</ul></section><section><h2>Timeline</h2><table><thead><tr><th>Offset</th><th>Type</th><th>Event</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${events}</tbody></table></section></main></body></html>`;
|
|
29039
29189
|
};
|
|
29040
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
29190
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml50(session.status)}"><td>${session.operationsRecordHref ? `<a href="${escapeHtml50(session.operationsRecordHref)}">${escapeHtml50(session.sessionId)}</a>` : `<a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml50(session.sessionId)}</a>`}</td><td>${escapeHtml50(session.status)}</td><td>${String(session.summary.eventCount)}</td><td>${String(session.summary.turnCount)}</td><td>${String(session.summary.errorCount)}</td><td>${formatMs4(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml50(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
29041
29191
|
var timelineCSS = "body{background:#0f1318;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}a{color:#fbbf24}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.metrics,.providers{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:20px 0}.metrics article,.providers article{background:#181f27;border:1px solid #2b3642;border-radius:20px;padding:16px}.metrics span,dt,.muted{color:#a8b0b8}.metrics strong{display:block;font-size:2rem}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0 0}dd{font-weight:800;margin:4px 0 0}table{background:#181f27;border-collapse:collapse;border-radius:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #2b3642;padding:12px;text-align:left}section{margin-top:28px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}";
|
|
29042
29192
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
29043
|
-
const snippet =
|
|
29193
|
+
const snippet = escapeHtml50(`const traceStore = createVoiceTraceSinkStore({
|
|
29044
29194
|
store: runtimeStorage.traces,
|
|
29045
29195
|
sinks: [
|
|
29046
29196
|
createVoiceTraceHTTPSink({
|
|
@@ -29066,13 +29216,13 @@ app.use(
|
|
|
29066
29216
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
29067
29217
|
})
|
|
29068
29218
|
);`);
|
|
29069
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
29219
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(options.title ?? "Voice Trace Timelines")}</title><style>${timelineCSS}.primitive{background:#181f27;border:1px solid #334155;border-radius:20px;margin:20px 0;padding:18px}.primitive p{line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #2b3642;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.primitive code{color:#bfdbfe}</style></head><body><main><header><p class="eyebrow">Self-hosted voice debugging</p><h1>${escapeHtml50(options.title ?? "Voice Trace Timelines")}</h1><p class="muted">Per-call event timelines with provider latency, fallback, timeout, handoff, and error context.</p></header><section class="metrics"><article><span>Sessions</span><strong>${String(report.total)}</strong></article><article><span>Failed</span><strong>${String(report.failed)}</strong></article><article><span>Warnings</span><strong>${String(report.warnings)}</strong></article></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTraceTimelineRoutes(...)</code> makes traces the proof backbone</h2><p class="muted">Mount trace timelines from the same trace store used by readiness, simulations, provider recovery, delivery sinks, and phone-agent smoke proof.</p><pre><code>${snippet}</code></pre></section><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Duration</th><th>Providers</th></tr></thead><tbody>${renderSessionRows(report)}</tbody></table></main></body></html>`;
|
|
29070
29220
|
};
|
|
29071
29221
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
29072
29222
|
const path = options.path ?? "/api/voice-traces";
|
|
29073
29223
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
29074
29224
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
29075
|
-
const routes = new
|
|
29225
|
+
const routes = new Elysia51({
|
|
29076
29226
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
29077
29227
|
});
|
|
29078
29228
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -29702,7 +29852,7 @@ var renderVoiceFailureReplayMarkdown = (report) => {
|
|
|
29702
29852
|
].join(`
|
|
29703
29853
|
`);
|
|
29704
29854
|
};
|
|
29705
|
-
var
|
|
29855
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29706
29856
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
29707
29857
|
var outcomeLabels = (outcome) => [
|
|
29708
29858
|
outcome.complete ? "complete" : undefined,
|
|
@@ -29812,18 +29962,18 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
29812
29962
|
`);
|
|
29813
29963
|
};
|
|
29814
29964
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
29815
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
29816
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
29817
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
29965
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml51(provider.provider)}</strong><span>${String(provider.eventCount)} events</span><span>${formatMs5(provider.averageElapsedMs)} avg</span><span>${String(provider.errorCount)} errors</span></article>`).join("") : '<p class="muted">No provider events recorded.</p>';
|
|
29966
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml51(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml51(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml51(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml51(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
29967
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml51(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml51(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.surface ? `<p><span class="label">Surface</span>${escapeHtml51(decision.surface)}</p>` : ""}${decision.kind ? `<p><span class="label">Kind</span>${escapeHtml51(decision.kind)}</p>` : ""}${decision.selectedProvider ? `<p>Selected: ${escapeHtml51(decision.selectedProvider)}</p>` : ""}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml51(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml51(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml51(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
29818
29968
|
const providerDecisionSummary = record.providerDecisionSummary;
|
|
29819
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
29820
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
29821
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
29822
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
29823
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
29969
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml51(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml51(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml51(handoff.status ?? "")}</span><p>${escapeHtml51(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
29970
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml51(tool.toolName ?? "tool")}</strong> <span>${escapeHtml51(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml51(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
29971
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml51(review.title)}</strong> <span>${escapeHtml51(review.summary.outcome ?? "")}</span><p>${escapeHtml51(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
29972
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml51(task.title)}</strong> <span>${escapeHtml51(task.status)}</span><p>${escapeHtml51(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
29973
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml51(event.type)}</strong> <span>${escapeHtml51(event.deliveryStatus ?? "local")}</span><p>${escapeHtml51(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
29824
29974
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
29825
29975
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
29826
|
-
return `<li><strong>assistant.guardrail ${
|
|
29976
|
+
return `<li><strong>assistant.guardrail ${escapeHtml51(decision.stage ?? "unknown")}</strong> <span>${escapeHtml51(decision.status ?? "")}</span><p>Allowed: ${escapeHtml51(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml51(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml51(decision.turnId)}` : ""}</p><p>${escapeHtml51(findings)}</p></li>`;
|
|
29827
29977
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
29828
29978
|
const telephonyMedia = record.telephonyMedia.events.length ? record.telephonyMedia.events.slice(0, 50).map((event) => {
|
|
29829
29979
|
const details = [
|
|
@@ -29834,9 +29984,9 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
29834
29984
|
event.sequenceNumber ? `Seq: ${event.sequenceNumber}` : undefined,
|
|
29835
29985
|
`Audio bytes: ${String(event.audioBytes)}`
|
|
29836
29986
|
].filter((detail) => typeof detail === "string");
|
|
29837
|
-
return `<li><strong>${
|
|
29987
|
+
return `<li><strong>${escapeHtml51(event.event)}</strong> <span>${escapeHtml51(new Date(event.at).toLocaleString())}</span><p>${escapeHtml51(details.join(" \xB7 "))}</p></li>`;
|
|
29838
29988
|
}).join("") : "<li>No telephony media trace events recorded.</li>";
|
|
29839
|
-
const snippet =
|
|
29989
|
+
const snippet = escapeHtml51(`app.use(
|
|
29840
29990
|
createVoiceOperationsRecordRoutes({
|
|
29841
29991
|
audit: auditStore,
|
|
29842
29992
|
integrationEvents: opsEvents,
|
|
@@ -29850,16 +30000,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
29850
30000
|
tasks: opsTasks
|
|
29851
30001
|
})
|
|
29852
30002
|
);`);
|
|
29853
|
-
const incidentMarkdown =
|
|
29854
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
29855
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30003
|
+
const incidentMarkdown = escapeHtml51(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
30004
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml51(options.incidentHref)}">Download incident.md</a>` : "";
|
|
30005
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(options.title ?? "Voice Operations Record")}</title><style>body{background:#101417;color:#f9f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.eyebrow{color:#fbbf24;font-size:.8rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.card,.primitive{background:#182025;border:1px solid #2d3a43;border-radius:20px;padding:16px}.card span,.muted,.label{color:#a9b4bd}.label{display:block;font-size:.72rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.card strong{display:block;font-size:2rem}section{margin-top:28px}article{display:grid;gap:8px}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#182025;border:1px solid #2d3a43;border-radius:16px;padding:14px}pre{background:#080d10;border:1px solid #2d3a43;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}.hero-actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.two-column{display:grid;gap:18px;grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr)}@media(max-width:860px){main{padding:20px}.two-column{grid-template-columns:1fr}}</style></head><body><main><p class="eyebrow">Call log replacement</p><h1>${escapeHtml51(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml51(record.status)}">${escapeHtml51(record.status)}</p><div class="hero-actions"><a href="#transcript">Transcript</a><a href="#provider-decisions">Provider decisions</a><a href="#telephony-media">Telephony media</a><a href="#guardrails">Guardrails</a><a href="#incident-handoff">Incident handoff</a>${incidentLink}</div><section class="grid"><div class="card"><span>Events</span><strong>${String(record.summary.eventCount)}</strong></div><div class="card"><span>Turns</span><strong>${String(record.summary.turnCount)}</strong></div><div class="card"><span>Errors</span><strong>${String(record.summary.errorCount)}</strong></div><div class="card"><span>Duration</span><strong>${formatMs5(record.summary.callDurationMs)}</strong></div><div class="card"><span>Provider recovery</span><strong>${escapeHtml51(providerDecisionSummary.recoveryStatus)}</strong><span>${String(providerDecisionSummary.fallbacks)} fallback / ${String(providerDecisionSummary.degraded)} degraded / ${String(providerDecisionSummary.errors)} errors</span></div><div class="card"><span>Telephony media</span><strong>${String(record.telephonyMedia.media)}</strong><span>${String(record.telephonyMedia.inbound)} inbound / ${String(record.telephonyMedia.outbound)} outbound / ${String(record.telephonyMedia.clears)} clears</span></div><div class="card"><span>Guardrails</span><strong>${String(record.guardrails.blocked)}</strong></div><div class="card"><span>Audit</span><strong>${String(record.audit?.total ?? 0)}</strong></div><div class="card"><span>Reviews</span><strong>${String(record.reviews?.total ?? 0)}</strong></div><div class="card"><span>Tasks</span><strong>${String(record.tasks?.total ?? 0)}</strong></div><div class="card"><span>Integrations</span><strong>${String(record.integrationEvents?.total ?? 0)}</strong></div></section><section class="two-column"><div><h2 id="transcript">Transcript</h2><ul>${transcript}</ul></div><div><h2 id="provider-decisions">Provider Decisions</h2><ul>${providerDecisions}</ul></div></section><section id="telephony-media"><h2>Telephony Media</h2><p class="muted">Live <code>client.telephony_media</code> stream lifecycle evidence attached to this session. Carriers: ${escapeHtml51(record.telephonyMedia.carriers.join(", ") || "none")}. Streams: ${escapeHtml51(record.telephonyMedia.streamIds.join(", ") || "none")}. Inbound: ${String(record.telephonyMedia.inbound)}. Outbound: ${String(record.telephonyMedia.outbound)}. Marks: ${String(record.telephonyMedia.marks)}. Clears: ${String(record.telephonyMedia.clears)}.</p><ul>${telephonyMedia}</ul></section><section id="guardrails"><h2>Guardrail Evidence</h2><p class="muted">Live <code>assistant.guardrail</code> decisions attached to this session.</p><ul>${guardrails}</ul></section><section id="incident-handoff"><h2>Copyable Incident Handoff</h2><p class="muted">Paste this into Slack, Linear, Zendesk, or an incident review. ${incidentLink}</p><pre><code>${incidentMarkdown}</code></pre></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceOperationsRecordRoutes(...)</code> gives every call one debuggable object</h2><p class="muted">Use this as the support/debug payload across traces, provider routing, tools, handoffs, guardrails, audit, latency, replay, reviews, tasks, media streams, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Provider Summary</h2><div class="grid">${providers}</div></section><section><h2>Handoffs</h2><ul>${handoffs}</ul></section><section><h2>Tools</h2><ul>${tools}</ul></section><section><h2>Reviews</h2><ul>${reviews}</ul></section><section><h2>Tasks</h2><ul>${tasks}</ul></section><section><h2>Integration Events</h2><ul>${integrationEvents}</ul></section></main></body></html>`;
|
|
29856
30006
|
};
|
|
29857
30007
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
29858
30008
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
29859
30009
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
29860
30010
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
29861
30011
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
29862
|
-
const routes = new
|
|
30012
|
+
const routes = new Elysia52({
|
|
29863
30013
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
29864
30014
|
});
|
|
29865
30015
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -30510,7 +30660,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
30510
30660
|
...options.headers ?? {}
|
|
30511
30661
|
};
|
|
30512
30662
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
30513
|
-
const app = new
|
|
30663
|
+
const app = new Elysia53({
|
|
30514
30664
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
30515
30665
|
});
|
|
30516
30666
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -31319,7 +31469,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
31319
31469
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
31320
31470
|
}
|
|
31321
31471
|
});
|
|
31322
|
-
const app = new
|
|
31472
|
+
const app = new Elysia53({
|
|
31323
31473
|
name: options.name ?? "absolute-voice-observability-export"
|
|
31324
31474
|
});
|
|
31325
31475
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -31396,7 +31546,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
31396
31546
|
};
|
|
31397
31547
|
|
|
31398
31548
|
// src/productionReadiness.ts
|
|
31399
|
-
var
|
|
31549
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31400
31550
|
var rollupStatus4 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
31401
31551
|
var readinessGateCodes = {
|
|
31402
31552
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -33043,25 +33193,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
33043
33193
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
33044
33194
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
33045
33195
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
33046
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
33047
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
33196
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml52(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
33197
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml52(report.profile.name)}</h2><p>${escapeHtml52(report.profile.description)}</p><p>${escapeHtml52(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml52(surface.href)}">${escapeHtml52(surface.label)}</a>` : escapeHtml52(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
33048
33198
|
const checks = report.checks.map((check, index) => {
|
|
33049
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
33050
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
33051
|
-
return `<article class="check ${
|
|
33199
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml52(action.href)}">${escapeHtml52(action.label)}</button>` : `<a href="${escapeHtml52(action.href)}">${escapeHtml52(action.label)}</a>`).join("");
|
|
33200
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml52(check.status)}: observed ${escapeHtml52(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml52(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml52(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml52(check.gateExplanation.unit)}` : ""}. ${escapeHtml52(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml52(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
33201
|
+
return `<article class="check ${escapeHtml52(check.status)}">
|
|
33052
33202
|
<div>
|
|
33053
|
-
<span>${
|
|
33054
|
-
<h2>${
|
|
33055
|
-
${check.detail ? `<p>${
|
|
33203
|
+
<span>${escapeHtml52(check.status.toUpperCase())}</span>
|
|
33204
|
+
<h2>${escapeHtml52(check.label)}</h2>
|
|
33205
|
+
${check.detail ? `<p>${escapeHtml52(check.detail)}</p>` : ""}
|
|
33056
33206
|
${explanation}
|
|
33057
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
33207
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml52(check.proofSource.href)}">${escapeHtml52(check.proofSource.sourceLabel)}</a>` : escapeHtml52(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml52(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
33058
33208
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
33059
33209
|
</div>
|
|
33060
|
-
<strong>${
|
|
33061
|
-
${check.href ? `<a href="${
|
|
33210
|
+
<strong>${escapeHtml52(String(check.value ?? check.status))}</strong>
|
|
33211
|
+
${check.href ? `<a href="${escapeHtml52(check.href)}">Open surface</a>` : ""}
|
|
33062
33212
|
</article>`;
|
|
33063
33213
|
}).join("");
|
|
33064
|
-
const snippet =
|
|
33214
|
+
const snippet = escapeHtml52(`createVoiceProductionReadinessRoutes({
|
|
33065
33215
|
htmlPath: '/production-readiness',
|
|
33066
33216
|
path: '/api/production-readiness',
|
|
33067
33217
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -33077,13 +33227,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
33077
33227
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
33078
33228
|
store: traceStore
|
|
33079
33229
|
});`);
|
|
33080
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33230
|
+
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,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;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{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml52(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml52(report.status)}">Overall: ${escapeHtml52(report.status.toUpperCase())}</p><p>Checked ${escapeHtml52(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
|
|
33081
33231
|
};
|
|
33082
33232
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
33083
33233
|
const path = options.path ?? "/api/production-readiness";
|
|
33084
33234
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
33085
33235
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
33086
|
-
const routes = new
|
|
33236
|
+
const routes = new Elysia54({
|
|
33087
33237
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
33088
33238
|
});
|
|
33089
33239
|
const resolveOptions = async (input) => {
|
|
@@ -33131,8 +33281,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
33131
33281
|
return routes;
|
|
33132
33282
|
};
|
|
33133
33283
|
// src/voiceMonitoring.ts
|
|
33134
|
-
import { Elysia as
|
|
33135
|
-
var
|
|
33284
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
33285
|
+
var escapeHtml53 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33136
33286
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
33137
33287
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
33138
33288
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -33385,14 +33535,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
33385
33535
|
};
|
|
33386
33536
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
33387
33537
|
const title = options.title ?? "Voice Monitors";
|
|
33388
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
33389
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
33390
|
-
const snippet =
|
|
33538
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml53(run.label)}</td><td class="${escapeHtml53(run.status)}">${escapeHtml53(run.status)}</td><td>${escapeHtml53(run.severity)}</td><td>${escapeHtml53(String(run.value ?? ""))}</td><td>${escapeHtml53(String(run.threshold ?? ""))}</td><td>${escapeHtml53(run.detail ?? "")}</td></tr>`).join("");
|
|
33539
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml53(issue.label)}</strong> <span class="${escapeHtml53(issue.status)}">${escapeHtml53(issue.status)}</span> ${escapeHtml53(issue.detail ?? "")}</li>`).join("");
|
|
33540
|
+
const snippet = escapeHtml53(`app.use(createVoiceMonitorRoutes({
|
|
33391
33541
|
evidence,
|
|
33392
33542
|
issueStore,
|
|
33393
33543
|
monitors: [defineVoiceMonitor(...)]
|
|
33394
33544
|
}));`);
|
|
33395
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33545
|
+
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:#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>${escapeHtml53(title)}</h1><p class="pill ${escapeHtml53(report.status)}">Status: ${escapeHtml53(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>`;
|
|
33396
33546
|
};
|
|
33397
33547
|
var actorFromRequest = async (request) => {
|
|
33398
33548
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -33416,7 +33566,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
33416
33566
|
monitors: options.monitors,
|
|
33417
33567
|
now: options.now
|
|
33418
33568
|
});
|
|
33419
|
-
const routes = new
|
|
33569
|
+
const routes = new Elysia55({
|
|
33420
33570
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
33421
33571
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
33422
33572
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -33463,7 +33613,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
33463
33613
|
};
|
|
33464
33614
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
33465
33615
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
33466
|
-
return new
|
|
33616
|
+
return new Elysia55({
|
|
33467
33617
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
33468
33618
|
}).get(path, () => ({
|
|
33469
33619
|
isRunning: options.runner.isRunning()
|
|
@@ -33839,8 +33989,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
33839
33989
|
};
|
|
33840
33990
|
};
|
|
33841
33991
|
// src/providerStackRecommendations.ts
|
|
33842
|
-
import { Elysia as
|
|
33843
|
-
var
|
|
33992
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
33993
|
+
var escapeHtml54 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33844
33994
|
var profileProviderPriorities = {
|
|
33845
33995
|
"meeting-recorder": {
|
|
33846
33996
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -34159,17 +34309,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
34159
34309
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
34160
34310
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
34161
34311
|
const rows = report.rows.map((row) => {
|
|
34162
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
34163
|
-
return `<article class="row ${
|
|
34312
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml54(check.status)}"><strong>${escapeHtml54(check.label)}</strong><span>${escapeHtml54(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml54(check.remediation.href)}">${escapeHtml54(check.remediation.label)}</a>` : escapeHtml54(check.remediation.label)}: ${escapeHtml54(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
34313
|
+
return `<article class="row ${escapeHtml54(row.status)}">
|
|
34164
34314
|
<div>
|
|
34165
|
-
<p class="eyebrow">${
|
|
34166
|
-
<h2>${
|
|
34167
|
-
<p class="status ${
|
|
34315
|
+
<p class="eyebrow">${escapeHtml54(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
34316
|
+
<h2>${escapeHtml54(row.provider)}</h2>
|
|
34317
|
+
<p class="status ${escapeHtml54(row.status)}">${escapeHtml54(row.status.toUpperCase())}</p>
|
|
34168
34318
|
</div>
|
|
34169
34319
|
<ul>${checks}</ul>
|
|
34170
34320
|
</article>`;
|
|
34171
34321
|
}).join("");
|
|
34172
|
-
const snippet =
|
|
34322
|
+
const snippet = escapeHtml54(`const providerContracts = () =>
|
|
34173
34323
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
34174
34324
|
env: process.env,
|
|
34175
34325
|
providers: {
|
|
@@ -34190,7 +34340,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
34190
34340
|
providerContractMatrix: () =>
|
|
34191
34341
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
34192
34342
|
});`);
|
|
34193
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
34343
|
+
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:#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>${escapeHtml54(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>`;
|
|
34194
34344
|
};
|
|
34195
34345
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
34196
34346
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -34205,7 +34355,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
34205
34355
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
34206
34356
|
const path = options.path ?? "/api/provider-contracts";
|
|
34207
34357
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
34208
|
-
const routes = new
|
|
34358
|
+
const routes = new Elysia56({
|
|
34209
34359
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
34210
34360
|
});
|
|
34211
34361
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -34323,7 +34473,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
34323
34473
|
return assertion;
|
|
34324
34474
|
};
|
|
34325
34475
|
// src/opsConsoleRoutes.ts
|
|
34326
|
-
import { Elysia as
|
|
34476
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
34327
34477
|
var DEFAULT_LINKS = [
|
|
34328
34478
|
{
|
|
34329
34479
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -34358,7 +34508,7 @@ var DEFAULT_LINKS = [
|
|
|
34358
34508
|
label: "Handoffs"
|
|
34359
34509
|
}
|
|
34360
34510
|
];
|
|
34361
|
-
var
|
|
34511
|
+
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
34362
34512
|
var countProviderStatuses = (providers) => {
|
|
34363
34513
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
34364
34514
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -34427,20 +34577,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
34427
34577
|
trace
|
|
34428
34578
|
};
|
|
34429
34579
|
};
|
|
34430
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
34580
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml55(input.label)}</span><strong>${escapeHtml55(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml55(input.status)}">${escapeHtml55(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml55(input.href)}">Open</a>` : ""}</article>`;
|
|
34431
34581
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
34432
34582
|
const links = report.links.map((link) => `<article class="surface">
|
|
34433
|
-
<div><h2>${
|
|
34434
|
-
<p><a href="${
|
|
34583
|
+
<div><h2>${escapeHtml55(link.label)}</h2>${link.description ? `<p>${escapeHtml55(link.description)}</p>` : ""}</div>
|
|
34584
|
+
<p><a href="${escapeHtml55(link.href)}">Open ${escapeHtml55(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml55(link.statusHref)}">Status</a>` : ""}</p>
|
|
34435
34585
|
</article>`).join("");
|
|
34436
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
34437
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
34586
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml55(session.sessionId)}</td><td>${escapeHtml55(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml55(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
34587
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml55(event.kind)}</td><td>${escapeHtml55(event.provider ?? "unknown")}</td><td>${escapeHtml55(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml55(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
34438
34588
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
34439
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
34589
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml55(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>${escapeHtml55(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 ${escapeHtml55(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>`;
|
|
34440
34590
|
};
|
|
34441
34591
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
34442
34592
|
const path = options.path ?? "/ops-console";
|
|
34443
|
-
const routes = new
|
|
34593
|
+
const routes = new Elysia57({
|
|
34444
34594
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
34445
34595
|
});
|
|
34446
34596
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -34457,7 +34607,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
34457
34607
|
return routes;
|
|
34458
34608
|
};
|
|
34459
34609
|
// src/incidentBundle.ts
|
|
34460
|
-
import { Elysia as
|
|
34610
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
34461
34611
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
34462
34612
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
34463
34613
|
return false;
|
|
@@ -34658,7 +34808,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
34658
34808
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
34659
34809
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
34660
34810
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
34661
|
-
const routes = new
|
|
34811
|
+
const routes = new Elysia58({
|
|
34662
34812
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
34663
34813
|
});
|
|
34664
34814
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -34859,19 +35009,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
34859
35009
|
};
|
|
34860
35010
|
};
|
|
34861
35011
|
// src/opsStatusRoutes.ts
|
|
34862
|
-
import { Elysia as
|
|
34863
|
-
var
|
|
35012
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
35013
|
+
var escapeHtml56 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
34864
35014
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
34865
35015
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
34866
35016
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
34867
35017
|
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;
|
|
34868
|
-
return `<article class="surface ${
|
|
35018
|
+
return `<article class="surface ${escapeHtml56(surface.status)}"><span>${escapeHtml56(surface.status.toUpperCase())}</span><h2>${escapeHtml56(key)}</h2><strong>${escapeHtml56(value)}</strong></article>`;
|
|
34869
35019
|
}).join("");
|
|
34870
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
35020
|
+
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:#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>${escapeHtml56(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml56(report.status)}">Overall: ${escapeHtml56(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>`;
|
|
34871
35021
|
};
|
|
34872
35022
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
34873
35023
|
const path = options.path ?? "/api/voice/ops-status";
|
|
34874
|
-
const routes = new
|
|
35024
|
+
const routes = new Elysia59({
|
|
34875
35025
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
34876
35026
|
});
|
|
34877
35027
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -35304,8 +35454,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
35304
35454
|
};
|
|
35305
35455
|
};
|
|
35306
35456
|
// src/traceDeliveryRoutes.ts
|
|
35307
|
-
import { Elysia as
|
|
35308
|
-
var
|
|
35457
|
+
import { Elysia as Elysia60 } from "elysia";
|
|
35458
|
+
var escapeHtml57 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
35309
35459
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
35310
35460
|
var getNumber12 = (value) => {
|
|
35311
35461
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -35386,14 +35536,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
35386
35536
|
if (entries.length === 0) {
|
|
35387
35537
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
35388
35538
|
}
|
|
35389
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
35539
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml57(sinkId)}</strong>: ${escapeHtml57(result.status)}${result.deliveredTo ? ` to ${escapeHtml57(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml57(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
35390
35540
|
};
|
|
35391
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
35541
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml57(event.type)} <small>${escapeHtml57(event.id)}</small>${event.sessionId ? ` session=${escapeHtml57(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
35392
35542
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
35393
35543
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
35394
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
35395
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
35396
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
35544
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml57(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
35545
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml57(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml57(delivery.deliveryStatus)}</span><h2>${escapeHtml57(delivery.id)}</h2><p>${escapeHtml57(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml57(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml57(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
35546
|
+
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:#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>${escapeHtml57(title)}</h1><p>Checked ${escapeHtml57(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>`;
|
|
35397
35547
|
};
|
|
35398
35548
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
35399
35549
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -35413,7 +35563,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
35413
35563
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
35414
35564
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
35415
35565
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
35416
|
-
const routes = new
|
|
35566
|
+
const routes = new Elysia60({
|
|
35417
35567
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
35418
35568
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
35419
35569
|
if (htmlPath !== false) {
|
|
@@ -35510,7 +35660,7 @@ var createVoiceMemoryStore = () => {
|
|
|
35510
35660
|
return { get, getOrCreate, list, remove, set };
|
|
35511
35661
|
};
|
|
35512
35662
|
// src/opsWebhook.ts
|
|
35513
|
-
import { Elysia as
|
|
35663
|
+
import { Elysia as Elysia61 } from "elysia";
|
|
35514
35664
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
35515
35665
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
35516
35666
|
const encoder = new TextEncoder;
|
|
@@ -35640,7 +35790,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
35640
35790
|
};
|
|
35641
35791
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
35642
35792
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
35643
|
-
return new
|
|
35793
|
+
return new Elysia61().post(path, async ({ body, request, set }) => {
|
|
35644
35794
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
35645
35795
|
if (options.signingSecret) {
|
|
35646
35796
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -36095,7 +36245,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
36095
36245
|
};
|
|
36096
36246
|
};
|
|
36097
36247
|
// src/postCallAnalysis.ts
|
|
36098
|
-
import { Elysia as
|
|
36248
|
+
import { Elysia as Elysia62 } from "elysia";
|
|
36099
36249
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
36100
36250
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
36101
36251
|
var getPathValue3 = (source, path) => {
|
|
@@ -36274,7 +36424,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
36274
36424
|
};
|
|
36275
36425
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
36276
36426
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
36277
|
-
const routes = new
|
|
36427
|
+
const routes = new Elysia62({
|
|
36278
36428
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
36279
36429
|
});
|
|
36280
36430
|
routes.get(path, async ({ query }) => {
|
|
@@ -36299,7 +36449,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
36299
36449
|
return routes;
|
|
36300
36450
|
};
|
|
36301
36451
|
// src/guardrails.ts
|
|
36302
|
-
import { Elysia as
|
|
36452
|
+
import { Elysia as Elysia63 } from "elysia";
|
|
36303
36453
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
36304
36454
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
36305
36455
|
var matchesRule = async (rule, input) => {
|
|
@@ -36601,7 +36751,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
36601
36751
|
};
|
|
36602
36752
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
36603
36753
|
const path = options.path ?? "/api/voice/guardrails";
|
|
36604
|
-
const routes = new
|
|
36754
|
+
const routes = new Elysia63({
|
|
36605
36755
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
36606
36756
|
});
|
|
36607
36757
|
routes.all(path, async ({ request }) => {
|
|
@@ -37446,6 +37596,7 @@ export {
|
|
|
37446
37596
|
runVoiceScenarioEvals,
|
|
37447
37597
|
runVoiceReconnectContract,
|
|
37448
37598
|
runVoiceProviderRoutingContract,
|
|
37599
|
+
runVoiceProfileSwitchPolicyProof,
|
|
37449
37600
|
runVoicePhoneAgentProductionSmokeContract,
|
|
37450
37601
|
runVoiceOutcomeContractSuite,
|
|
37451
37602
|
runVoiceCampaignReadinessProof,
|
|
@@ -37510,6 +37661,7 @@ export {
|
|
|
37510
37661
|
renderVoiceProviderCapabilityHTML,
|
|
37511
37662
|
renderVoiceProofTrendRecommendationMarkdown,
|
|
37512
37663
|
renderVoiceProofTrendRecommendationHTML,
|
|
37664
|
+
renderVoiceProfileSwitchPolicyProofHTML,
|
|
37513
37665
|
renderVoiceProductionReadinessHTML,
|
|
37514
37666
|
renderVoicePostCallAnalysisMarkdown,
|
|
37515
37667
|
renderVoicePhoneAgentProductionSmokeHTML,
|
|
@@ -37763,6 +37915,7 @@ export {
|
|
|
37763
37915
|
createVoiceProviderCapabilityHTMLHandler,
|
|
37764
37916
|
createVoiceProofTrendRoutes,
|
|
37765
37917
|
createVoiceProofTrendRecommendationRoutes,
|
|
37918
|
+
createVoiceProfileSwitchPolicyProofRoutes,
|
|
37766
37919
|
createVoiceProductionReadinessRoutes,
|
|
37767
37920
|
createVoicePostgresTraceSinkDeliveryStore,
|
|
37768
37921
|
createVoicePostgresTraceEventStore,
|