@absolutejs/voice 0.0.22-beta.431 → 0.0.22-beta.433
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/incidentTimeline.d.ts +148 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +587 -170
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30113,8 +30113,421 @@ var createVoiceOperationalStatusRoutes = (options) => {
|
|
|
30113
30113
|
}
|
|
30114
30114
|
return routes;
|
|
30115
30115
|
};
|
|
30116
|
-
// src/
|
|
30116
|
+
// src/incidentTimeline.ts
|
|
30117
30117
|
import { Elysia as Elysia46 } from "elysia";
|
|
30118
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30119
|
+
var resolveValue2 = async (value) => typeof value === "function" ? await value() : value;
|
|
30120
|
+
var linkForSession = (link, sessionId) => {
|
|
30121
|
+
if (!link || !sessionId) {
|
|
30122
|
+
return;
|
|
30123
|
+
}
|
|
30124
|
+
return typeof link === "function" ? link(sessionId) : link;
|
|
30125
|
+
};
|
|
30126
|
+
var statusToSeverity = (status) => status === "fail" || status === "failed" ? "critical" : status === "warn" || status === "warning" || status === "recovered" ? "warn" : "info";
|
|
30127
|
+
var failureReplayStatusToSeverity = (status) => status === "failed" ? "critical" : status === "healthy" ? "info" : "warn";
|
|
30128
|
+
var withinWindow = (event, now, windowMs) => !windowMs || event.at >= now - windowMs;
|
|
30129
|
+
var eventStatus2 = (event) => event.severity === "critical" ? "fail" : event.severity === "warn" ? "warn" : "pass";
|
|
30130
|
+
var defaultIncidentRecoveryActions = (events, links) => {
|
|
30131
|
+
const actions = [];
|
|
30132
|
+
const add = (action) => {
|
|
30133
|
+
const key = `${action.id}:${action.sessionId ?? ""}:${action.href ?? ""}`;
|
|
30134
|
+
if (actions.some((existing) => `${existing.id}:${existing.sessionId ?? ""}:${existing.href ?? ""}` === key)) {
|
|
30135
|
+
return;
|
|
30136
|
+
}
|
|
30137
|
+
actions.push(action);
|
|
30138
|
+
};
|
|
30139
|
+
for (const event of events) {
|
|
30140
|
+
if (event.category === "delivery") {
|
|
30141
|
+
add({
|
|
30142
|
+
detail: "Ask the app to tick delivery workers or retry failed delivery queue work.",
|
|
30143
|
+
eventId: event.id,
|
|
30144
|
+
href: links.deliveryRuntime,
|
|
30145
|
+
id: "delivery.retry",
|
|
30146
|
+
label: "Retry delivery work",
|
|
30147
|
+
method: "POST",
|
|
30148
|
+
sessionId: event.sessionId
|
|
30149
|
+
});
|
|
30150
|
+
}
|
|
30151
|
+
if (event.category === "readiness" || event.category === "operational-status") {
|
|
30152
|
+
add({
|
|
30153
|
+
detail: "Refresh production readiness and proof freshness before declaring the incident resolved.",
|
|
30154
|
+
eventId: event.id,
|
|
30155
|
+
href: links.productionReadiness ?? links.operationalStatus,
|
|
30156
|
+
id: "readiness.refresh",
|
|
30157
|
+
label: "Refresh readiness proof",
|
|
30158
|
+
method: "POST",
|
|
30159
|
+
sessionId: event.sessionId
|
|
30160
|
+
});
|
|
30161
|
+
}
|
|
30162
|
+
if (event.sessionId) {
|
|
30163
|
+
add({
|
|
30164
|
+
detail: "Generate or open a support/debug artifact for the affected call.",
|
|
30165
|
+
eventId: event.id,
|
|
30166
|
+
href: linkForSession(links.supportBundle, event.sessionId) ?? linkForSession(links.callDebugger, event.sessionId),
|
|
30167
|
+
id: "support.bundle",
|
|
30168
|
+
label: "Generate support bundle",
|
|
30169
|
+
method: "POST",
|
|
30170
|
+
sessionId: event.sessionId
|
|
30171
|
+
});
|
|
30172
|
+
}
|
|
30173
|
+
}
|
|
30174
|
+
if (events.some((event) => event.severity !== "info")) {
|
|
30175
|
+
add({
|
|
30176
|
+
detail: "Rerun the app proof pack to confirm the current release evidence is fresh.",
|
|
30177
|
+
href: links.proofPack,
|
|
30178
|
+
id: "proof.rerun",
|
|
30179
|
+
label: "Rerun proof pack",
|
|
30180
|
+
method: "POST"
|
|
30181
|
+
});
|
|
30182
|
+
}
|
|
30183
|
+
return actions;
|
|
30184
|
+
};
|
|
30185
|
+
var worstStatus3 = (statuses) => statuses.includes("fail") ? "fail" : statuses.includes("warn") ? "warn" : "pass";
|
|
30186
|
+
var pushOperationalStatusEvents = (events, report, links) => {
|
|
30187
|
+
if (!report) {
|
|
30188
|
+
return;
|
|
30189
|
+
}
|
|
30190
|
+
for (const check of report.checks) {
|
|
30191
|
+
if (check.status === "pass") {
|
|
30192
|
+
continue;
|
|
30193
|
+
}
|
|
30194
|
+
events.push({
|
|
30195
|
+
action: {
|
|
30196
|
+
href: check.href ?? links.operationalStatus,
|
|
30197
|
+
label: "Open source"
|
|
30198
|
+
},
|
|
30199
|
+
at: report.checkedAt,
|
|
30200
|
+
category: check.label.toLowerCase().includes("readiness") ? "readiness" : "operational-status",
|
|
30201
|
+
detail: check.detail,
|
|
30202
|
+
href: check.href ?? links.operationalStatus,
|
|
30203
|
+
id: `operational:${check.label}`,
|
|
30204
|
+
label: check.label,
|
|
30205
|
+
severity: statusToSeverity(check.status),
|
|
30206
|
+
source: "operational-status",
|
|
30207
|
+
value: check.value
|
|
30208
|
+
});
|
|
30209
|
+
}
|
|
30210
|
+
};
|
|
30211
|
+
var pushOpsRecoveryEvents = (events, report, links) => {
|
|
30212
|
+
if (!report) {
|
|
30213
|
+
return;
|
|
30214
|
+
}
|
|
30215
|
+
for (const issue of report.issues) {
|
|
30216
|
+
events.push({
|
|
30217
|
+
action: {
|
|
30218
|
+
href: issue.href ?? links.operationalStatus,
|
|
30219
|
+
label: "Inspect recovery issue"
|
|
30220
|
+
},
|
|
30221
|
+
at: report.checkedAt,
|
|
30222
|
+
category: "recovery",
|
|
30223
|
+
detail: issue.detail,
|
|
30224
|
+
href: issue.href,
|
|
30225
|
+
id: `ops-recovery:${issue.code}`,
|
|
30226
|
+
label: issue.label,
|
|
30227
|
+
severity: issue.severity === "fail" ? "critical" : "warn",
|
|
30228
|
+
source: "ops-recovery",
|
|
30229
|
+
value: issue.value
|
|
30230
|
+
});
|
|
30231
|
+
}
|
|
30232
|
+
for (const session of report.failedSessions) {
|
|
30233
|
+
events.push({
|
|
30234
|
+
action: {
|
|
30235
|
+
href: session.operationsRecordHref ?? linkForSession(links.operationsRecords, session.sessionId) ?? linkForSession(links.callDebugger, session.sessionId),
|
|
30236
|
+
label: "Open affected call"
|
|
30237
|
+
},
|
|
30238
|
+
at: session.at,
|
|
30239
|
+
category: "call",
|
|
30240
|
+
detail: session.error,
|
|
30241
|
+
href: session.operationsRecordHref ?? linkForSession(links.operationsRecords, session.sessionId),
|
|
30242
|
+
id: `failed-session:${session.sessionId}:${session.at}`,
|
|
30243
|
+
label: "Failed session",
|
|
30244
|
+
sessionId: session.sessionId,
|
|
30245
|
+
severity: "critical",
|
|
30246
|
+
source: "ops-recovery",
|
|
30247
|
+
value: session.provider
|
|
30248
|
+
});
|
|
30249
|
+
}
|
|
30250
|
+
};
|
|
30251
|
+
var pushMonitorEvents = (events, issues, links) => {
|
|
30252
|
+
if (!issues) {
|
|
30253
|
+
return;
|
|
30254
|
+
}
|
|
30255
|
+
for (const issue of issues) {
|
|
30256
|
+
if (issue.status === "resolved") {
|
|
30257
|
+
continue;
|
|
30258
|
+
}
|
|
30259
|
+
const sessionId = issue.impactedSessions[0];
|
|
30260
|
+
events.push({
|
|
30261
|
+
action: {
|
|
30262
|
+
href: issue.operationsRecordHrefs[0] ?? linkForSession(links.operationsRecords, sessionId) ?? links.monitorIssues,
|
|
30263
|
+
label: "Open monitor evidence"
|
|
30264
|
+
},
|
|
30265
|
+
at: issue.lastSeenAt,
|
|
30266
|
+
category: "monitor",
|
|
30267
|
+
detail: issue.detail,
|
|
30268
|
+
href: issue.operationsRecordHrefs[0] ?? linkForSession(links.operationsRecords, sessionId) ?? links.monitorIssues,
|
|
30269
|
+
id: `monitor:${issue.id}`,
|
|
30270
|
+
label: issue.label,
|
|
30271
|
+
sessionId,
|
|
30272
|
+
severity: issue.severity === "critical" ? "critical" : issue.severity === "warn" ? "warn" : "info",
|
|
30273
|
+
source: `monitor:${issue.monitorId}`,
|
|
30274
|
+
value: issue.value
|
|
30275
|
+
});
|
|
30276
|
+
}
|
|
30277
|
+
};
|
|
30278
|
+
var pushOperationsRecordEvents = (events, records, links) => {
|
|
30279
|
+
if (!records) {
|
|
30280
|
+
return;
|
|
30281
|
+
}
|
|
30282
|
+
for (const record of records) {
|
|
30283
|
+
if (record.status === "healthy") {
|
|
30284
|
+
continue;
|
|
30285
|
+
}
|
|
30286
|
+
const href = linkForSession(links.operationsRecords, record.sessionId);
|
|
30287
|
+
const debuggerHref = linkForSession(links.callDebugger, record.sessionId);
|
|
30288
|
+
events.push({
|
|
30289
|
+
action: {
|
|
30290
|
+
href: debuggerHref ?? href,
|
|
30291
|
+
label: debuggerHref ? "Open call debugger" : "Open operations record"
|
|
30292
|
+
},
|
|
30293
|
+
at: record.checkedAt,
|
|
30294
|
+
category: "call",
|
|
30295
|
+
detail: record.status === "failed" ? "Call operations record failed." : "Call operations record has warnings.",
|
|
30296
|
+
href,
|
|
30297
|
+
id: `operations-record:${record.sessionId}`,
|
|
30298
|
+
label: `Operations record ${record.status}`,
|
|
30299
|
+
sessionId: record.sessionId,
|
|
30300
|
+
severity: statusToSeverity(record.status),
|
|
30301
|
+
source: "operations-record",
|
|
30302
|
+
value: record.outcome.complete ? "complete" : "incomplete"
|
|
30303
|
+
});
|
|
30304
|
+
}
|
|
30305
|
+
};
|
|
30306
|
+
var pushFailureReplayEvents = (events, replays, links) => {
|
|
30307
|
+
if (!replays) {
|
|
30308
|
+
return;
|
|
30309
|
+
}
|
|
30310
|
+
for (const replay of replays) {
|
|
30311
|
+
if (replay.status === "healthy") {
|
|
30312
|
+
continue;
|
|
30313
|
+
}
|
|
30314
|
+
const href = replay.operationsRecordHref ?? linkForSession(links.failureReplay, replay.sessionId) ?? linkForSession(links.callDebugger, replay.sessionId);
|
|
30315
|
+
events.push({
|
|
30316
|
+
action: {
|
|
30317
|
+
href: linkForSession(links.callDebugger, replay.sessionId) ?? href ?? linkForSession(links.supportBundle, replay.sessionId),
|
|
30318
|
+
label: "Open replay/debug artifact"
|
|
30319
|
+
},
|
|
30320
|
+
at: replay.providers.steps[0]?.at ?? replay.media.steps[0]?.at ?? Date.now(),
|
|
30321
|
+
category: "failure-replay",
|
|
30322
|
+
detail: replay.summary.issues.join("; ") || replay.summary.userHeard.join(" ") || `Failure replay is ${replay.status}.`,
|
|
30323
|
+
href,
|
|
30324
|
+
id: `failure-replay:${replay.sessionId}`,
|
|
30325
|
+
label: `Failure replay ${replay.status}`,
|
|
30326
|
+
sessionId: replay.sessionId,
|
|
30327
|
+
severity: failureReplayStatusToSeverity(replay.status),
|
|
30328
|
+
source: "failure-replay",
|
|
30329
|
+
value: `${replay.providers.errors} provider errors / ${replay.media.errors} media errors`
|
|
30330
|
+
});
|
|
30331
|
+
}
|
|
30332
|
+
};
|
|
30333
|
+
var buildVoiceIncidentTimelineReport = async (options) => {
|
|
30334
|
+
const now = options.now ?? Date.now();
|
|
30335
|
+
const links = options.links ?? {};
|
|
30336
|
+
const [
|
|
30337
|
+
operationalStatus,
|
|
30338
|
+
opsRecovery,
|
|
30339
|
+
monitorIssues,
|
|
30340
|
+
operationsRecords,
|
|
30341
|
+
failureReplays
|
|
30342
|
+
] = await Promise.all([
|
|
30343
|
+
resolveValue2(options.operationalStatus),
|
|
30344
|
+
resolveValue2(options.opsRecovery),
|
|
30345
|
+
resolveValue2(options.monitorIssues),
|
|
30346
|
+
resolveValue2(options.operationsRecords),
|
|
30347
|
+
resolveValue2(options.failureReplays)
|
|
30348
|
+
]);
|
|
30349
|
+
const events = [];
|
|
30350
|
+
pushOperationalStatusEvents(events, operationalStatus, links);
|
|
30351
|
+
pushOpsRecoveryEvents(events, opsRecovery, links);
|
|
30352
|
+
pushMonitorEvents(events, monitorIssues, links);
|
|
30353
|
+
pushOperationsRecordEvents(events, operationsRecords, links);
|
|
30354
|
+
pushFailureReplayEvents(events, failureReplays, links);
|
|
30355
|
+
const filtered = events.filter((event) => withinWindow(event, now, options.windowMs)).sort((left, right) => right.at - left.at).slice(0, options.limit ?? 50);
|
|
30356
|
+
const summary = {
|
|
30357
|
+
critical: filtered.filter((event) => event.severity === "critical").length,
|
|
30358
|
+
info: filtered.filter((event) => event.severity === "info").length,
|
|
30359
|
+
total: filtered.length,
|
|
30360
|
+
warn: filtered.filter((event) => event.severity === "warn").length
|
|
30361
|
+
};
|
|
30362
|
+
const baseReport = {
|
|
30363
|
+
events: filtered,
|
|
30364
|
+
generatedAt: now,
|
|
30365
|
+
links,
|
|
30366
|
+
status: worstStatus3(filtered.map(eventStatus2)),
|
|
30367
|
+
summary,
|
|
30368
|
+
windowMs: options.windowMs
|
|
30369
|
+
};
|
|
30370
|
+
const configuredActions = typeof options.recoveryActions === "function" ? await options.recoveryActions({
|
|
30371
|
+
events: filtered,
|
|
30372
|
+
report: baseReport
|
|
30373
|
+
}) : options.recoveryActions;
|
|
30374
|
+
return {
|
|
30375
|
+
...baseReport,
|
|
30376
|
+
actions: configuredActions === undefined ? defaultIncidentRecoveryActions(filtered, links) : [...configuredActions]
|
|
30377
|
+
};
|
|
30378
|
+
};
|
|
30379
|
+
var renderVoiceIncidentTimelineMarkdown = (report, options = {}) => {
|
|
30380
|
+
const title = options.title ?? "AbsoluteJS Voice Incident Timeline";
|
|
30381
|
+
const rows = report.events.map((event) => {
|
|
30382
|
+
const when = new Date(event.at).toISOString();
|
|
30383
|
+
const target = event.href ? ` [open](${event.href})` : "";
|
|
30384
|
+
const session = event.sessionId ? ` session=${event.sessionId}` : "";
|
|
30385
|
+
const value = event.value === undefined ? "" : ` value=${event.value}`;
|
|
30386
|
+
return `- ${when} ${event.severity.toUpperCase()} ${event.label}${session}${value}${target}${event.detail ? ` - ${event.detail}` : ""}`;
|
|
30387
|
+
}).join(`
|
|
30388
|
+
`);
|
|
30389
|
+
return `# ${title}
|
|
30390
|
+
|
|
30391
|
+
Status: ${report.status}
|
|
30392
|
+
|
|
30393
|
+
Generated: ${new Date(report.generatedAt).toISOString()}
|
|
30394
|
+
|
|
30395
|
+
Summary: ${report.summary.critical} critical, ${report.summary.warn} warn, ${report.summary.info} info, ${report.summary.total} total.
|
|
30396
|
+
|
|
30397
|
+
## Events
|
|
30398
|
+
|
|
30399
|
+
${rows || "- No incident timeline events."}
|
|
30400
|
+
|
|
30401
|
+
## Recovery Actions
|
|
30402
|
+
|
|
30403
|
+
${report.actions.map((action) => `- ${action.method ?? "GET"} ${action.id}: ${action.label}${action.href ? ` (${action.href})` : ""}${action.detail ? ` - ${action.detail}` : ""}`).join(`
|
|
30404
|
+
`) || "- No recovery actions."}
|
|
30405
|
+
`;
|
|
30406
|
+
};
|
|
30407
|
+
var renderVoiceIncidentTimelineHTML = (report, options = {}) => {
|
|
30408
|
+
const title = options.title ?? "AbsoluteJS Voice Incident Timeline";
|
|
30409
|
+
const events = report.events.map((event) => `<article class="${escapeHtml43(event.severity)}">
|
|
30410
|
+
<span>${escapeHtml43(event.severity.toUpperCase())} / ${escapeHtml43(event.category)}</span>
|
|
30411
|
+
<h2>${escapeHtml43(event.label)}</h2>
|
|
30412
|
+
<p>${escapeHtml43(new Date(event.at).toLocaleString())}${event.sessionId ? ` \xB7 session ${escapeHtml43(event.sessionId)}` : ""}</p>
|
|
30413
|
+
${event.value === undefined ? "" : `<strong>${escapeHtml43(String(event.value))}</strong>`}
|
|
30414
|
+
${event.detail ? `<p>${escapeHtml43(event.detail)}</p>` : ""}
|
|
30415
|
+
<div>${event.href ? `<a href="${escapeHtml43(event.href)}">Open source</a>` : ""}${event.action?.href ? `<a href="${escapeHtml43(event.action.href)}">${escapeHtml43(event.action.label)}</a>` : ""}</div>
|
|
30416
|
+
</article>`).join("");
|
|
30417
|
+
const actions = report.actions.map((action) => {
|
|
30418
|
+
const label = escapeHtml43(action.label);
|
|
30419
|
+
const detail = action.detail ? `<p>${escapeHtml43(action.detail)}</p>` : "";
|
|
30420
|
+
const href = action.href ? `<a href="${escapeHtml43(action.href)}">Open target</a>` : "";
|
|
30421
|
+
const control = action.method === "POST" ? `<button type="button" data-voice-incident-action="${escapeHtml43(action.id)}" ${action.disabled ? "disabled" : ""}>${label}</button>` : href;
|
|
30422
|
+
return `<article class="action"><span>${escapeHtml43(action.method ?? "GET")}</span><h2>${label}</h2>${detail}<div>${control}${href && action.method === "POST" ? href : ""}</div></article>`;
|
|
30423
|
+
}).join("");
|
|
30424
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml43(title)}</title><style>body{background:#11110d;color:#faf4df;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1100px;padding:32px}.hero{background:linear-gradient(135deg,rgba(248,113,113,.2),rgba(245,158,11,.13),rgba(34,197,94,.12));border:1px solid #39301d;border-radius:30px;margin-bottom:18px;padding:28px}.eyebrow{color:#fcd34d;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);letter-spacing:-.06em;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,.75)}.status.fail{border-color:rgba(239,68,68,.85)}.grid{display:grid;gap:14px}.actions{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));margin:0 0 18px}.summary{display:flex;flex-wrap:wrap;gap:10px}.summary span{background:#181711;border:1px solid #39301d;border-radius:999px;padding:8px 12px}article{background:#181711;border:1px solid #39301d;border-radius:22px;padding:18px}article.critical{border-color:rgba(239,68,68,.85)}article.warn{border-color:rgba(245,158,11,.75)}article.info{border-color:rgba(34,197,94,.55)}article.action{border-color:#5b4a22}article span{color:#fcd34d;font-size:.78rem;font-weight:900;letter-spacing:.08em}article h2{margin:.35rem 0}.muted,article p{color:#cfc5a8}article strong{display:block;font-size:1.3rem;margin:.5rem 0}a{color:#fde68a;margin-right:12px}button{background:#fcd34d;border:0;border-radius:999px;color:#171307;cursor:pointer;font-weight:900;padding:10px 14px}button:disabled{cursor:not-allowed;opacity:.55}</style></head><body><main><section class="hero"><p class="eyebrow">Operational triage</p><h1>${escapeHtml43(title)}</h1><p class="status ${escapeHtml43(report.status)}">Overall: ${escapeHtml43(report.status.toUpperCase())}</p><p class="muted">Generated ${escapeHtml43(new Date(report.generatedAt).toLocaleString())}</p><div class="summary"><span>${String(report.summary.critical)} critical</span><span>${String(report.summary.warn)} warn</span><span>${String(report.summary.info)} info</span><span>${String(report.summary.total)} total</span></div></section><h2>Recovery actions</h2><section class="actions">${actions || '<article class="action"><span>NONE</span><h2>No recovery actions</h2><p>No executable actions are available for this report.</p></article>'}</section><h2>Timeline</h2><section class="grid">${events || '<article class="info"><span>INFO</span><h2>No incident events</h2><p>No non-pass operational events were found in this window.</p></article>'}</section></main><script>document.querySelectorAll("[data-voice-incident-action]").forEach((button)=>{button.addEventListener("click",async()=>{const id=button.getAttribute("data-voice-incident-action");if(!id)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch("/api/voice/incident-timeline/actions/"+encodeURIComponent(id),{method:"POST"});button.textContent=response.ok?"Done":"Failed";if(response.ok)setTimeout(()=>location.reload(),700)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1600)}})});</script></body></html>`;
|
|
30425
|
+
};
|
|
30426
|
+
var createVoiceIncidentTimelineRoutes = (options) => {
|
|
30427
|
+
const path = options.path ?? "/api/voice/incident-timeline";
|
|
30428
|
+
const htmlPath = options.htmlPath === undefined ? "/voice/incident-timeline" : options.htmlPath;
|
|
30429
|
+
const markdownPath = options.markdownPath === undefined ? "/voice/incident-timeline.md" : options.markdownPath;
|
|
30430
|
+
const actionPath = options.actionPath === undefined ? "/api/voice/incident-timeline/actions" : options.actionPath;
|
|
30431
|
+
const routes = new Elysia46({
|
|
30432
|
+
name: options.name ?? "absolutejs-voice-incident-timeline"
|
|
30433
|
+
}).get(path, async () => {
|
|
30434
|
+
const report = await buildVoiceIncidentTimelineReport(options);
|
|
30435
|
+
return new Response(JSON.stringify(report), {
|
|
30436
|
+
headers: {
|
|
30437
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
30438
|
+
...options.headers
|
|
30439
|
+
},
|
|
30440
|
+
status: report.status === "fail" ? 503 : 200
|
|
30441
|
+
});
|
|
30442
|
+
});
|
|
30443
|
+
if (htmlPath !== false) {
|
|
30444
|
+
routes.get(htmlPath, async () => {
|
|
30445
|
+
const report = await buildVoiceIncidentTimelineReport(options);
|
|
30446
|
+
const body = await (options.render ?? ((input) => renderVoiceIncidentTimelineHTML(input, { title: options.title })))(report);
|
|
30447
|
+
return new Response(body, {
|
|
30448
|
+
headers: {
|
|
30449
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
30450
|
+
...options.headers
|
|
30451
|
+
}
|
|
30452
|
+
});
|
|
30453
|
+
});
|
|
30454
|
+
}
|
|
30455
|
+
if (markdownPath !== false) {
|
|
30456
|
+
routes.get(markdownPath, async () => {
|
|
30457
|
+
const report = await buildVoiceIncidentTimelineReport(options);
|
|
30458
|
+
return new Response(renderVoiceIncidentTimelineMarkdown(report, {
|
|
30459
|
+
title: options.title
|
|
30460
|
+
}), {
|
|
30461
|
+
headers: {
|
|
30462
|
+
"Content-Type": "text/markdown; charset=utf-8",
|
|
30463
|
+
...options.headers
|
|
30464
|
+
}
|
|
30465
|
+
});
|
|
30466
|
+
});
|
|
30467
|
+
}
|
|
30468
|
+
if (actionPath !== false) {
|
|
30469
|
+
routes.get(actionPath, async () => {
|
|
30470
|
+
const report = await buildVoiceIncidentTimelineReport(options);
|
|
30471
|
+
return new Response(JSON.stringify({
|
|
30472
|
+
actions: report.actions,
|
|
30473
|
+
generatedAt: report.generatedAt,
|
|
30474
|
+
status: report.status
|
|
30475
|
+
}), {
|
|
30476
|
+
headers: {
|
|
30477
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
30478
|
+
...options.headers
|
|
30479
|
+
}
|
|
30480
|
+
});
|
|
30481
|
+
}).post(`${actionPath}/:actionId`, async ({ params, request }) => {
|
|
30482
|
+
const actionId = params.actionId;
|
|
30483
|
+
const report = await buildVoiceIncidentTimelineReport(options);
|
|
30484
|
+
const action = report.actions.find((item) => item.id === actionId);
|
|
30485
|
+
const handler = options.actionHandlers?.[actionId];
|
|
30486
|
+
if (!action) {
|
|
30487
|
+
return new Response(JSON.stringify({
|
|
30488
|
+
actionId,
|
|
30489
|
+
ok: false,
|
|
30490
|
+
status: "not_found"
|
|
30491
|
+
}), {
|
|
30492
|
+
headers: {
|
|
30493
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
30494
|
+
...options.headers
|
|
30495
|
+
},
|
|
30496
|
+
status: 404
|
|
30497
|
+
});
|
|
30498
|
+
}
|
|
30499
|
+
if (action.disabled || action.method !== "POST" || !handler) {
|
|
30500
|
+
return new Response(JSON.stringify({
|
|
30501
|
+
actionId,
|
|
30502
|
+
ok: false,
|
|
30503
|
+
status: action.disabled ? "disabled" : "not_executable"
|
|
30504
|
+
}), {
|
|
30505
|
+
headers: {
|
|
30506
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
30507
|
+
...options.headers
|
|
30508
|
+
},
|
|
30509
|
+
status: 409
|
|
30510
|
+
});
|
|
30511
|
+
}
|
|
30512
|
+
const result = await handler({
|
|
30513
|
+
action,
|
|
30514
|
+
actionId,
|
|
30515
|
+
report,
|
|
30516
|
+
request
|
|
30517
|
+
});
|
|
30518
|
+
return new Response(JSON.stringify(result), {
|
|
30519
|
+
headers: {
|
|
30520
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
30521
|
+
...options.headers
|
|
30522
|
+
},
|
|
30523
|
+
status: result.ok ? 200 : 500
|
|
30524
|
+
});
|
|
30525
|
+
});
|
|
30526
|
+
}
|
|
30527
|
+
return routes;
|
|
30528
|
+
};
|
|
30529
|
+
// src/dataControl.ts
|
|
30530
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
30118
30531
|
var voiceComplianceRedactionDefaults = {
|
|
30119
30532
|
keys: [
|
|
30120
30533
|
"apiKey",
|
|
@@ -30353,7 +30766,7 @@ var parseRetentionScopes = (value) => {
|
|
|
30353
30766
|
const allowed = new Set(allRetentionScopes);
|
|
30354
30767
|
return value.split(",").map((entry) => entry.trim()).filter((entry) => allowed.has(entry));
|
|
30355
30768
|
};
|
|
30356
|
-
var
|
|
30769
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30357
30770
|
var buildStorageSurfaces = (options) => [
|
|
30358
30771
|
{
|
|
30359
30772
|
configured: Boolean(options.session ?? options.sessions),
|
|
@@ -30590,12 +31003,12 @@ var buildVoiceDataControlReport = async (options) => {
|
|
|
30590
31003
|
zeroRetentionAvailable: true
|
|
30591
31004
|
};
|
|
30592
31005
|
};
|
|
30593
|
-
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${
|
|
31006
|
+
var renderDataRetentionReportRows = (report) => report.scopes.map((scope) => `<tr><td>${escapeHtml44(scope.scope)}</td><td>${scope.scannedCount}</td><td>${scope.deletedCount}</td><td>${escapeHtml44(scope.skippedReason ?? "")}</td><td><code>${escapeHtml44(scope.deletedIds.join(", "))}</code></td></tr>`).join("");
|
|
30594
31007
|
var renderVoiceDataControlHTML = (report, options = {}) => {
|
|
30595
31008
|
const title = options.title ?? "Voice Data Control";
|
|
30596
|
-
const storageRows = report.storage.map((surface) => `<tr><td>${
|
|
30597
|
-
const keyRows = report.providerKeys.map((key) => `<tr><td>${
|
|
30598
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${
|
|
31009
|
+
const storageRows = report.storage.map((surface) => `<tr><td>${escapeHtml44(surface.name)}</td><td>${surface.configured ? "Configured" : "Missing"}</td><td>${escapeHtml44(surface.control)}</td><td>${surface.selfHosted ? "Yes" : "No"}</td></tr>`).join("");
|
|
31010
|
+
const keyRows = report.providerKeys.map((key) => `<tr><td>${escapeHtml44(key.name)}</td><td><code>${escapeHtml44(key.env ?? "n/a")}</code></td><td>${key.required ? "Required" : "Optional"}</td><td>${escapeHtml44(key.recommendation)}</td></tr>`).join("");
|
|
31011
|
+
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:#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>${escapeHtml44(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>`;
|
|
30599
31012
|
};
|
|
30600
31013
|
var renderVoiceDataControlMarkdown = (report, options = {}) => [
|
|
30601
31014
|
`# ${options.title ?? "Voice Data Control"}`,
|
|
@@ -30653,7 +31066,7 @@ var parseRetentionPolicyBody = (body, options, dryRun) => {
|
|
|
30653
31066
|
var createVoiceDataControlRoutes = (options) => {
|
|
30654
31067
|
const path = options.path ?? "/data-control";
|
|
30655
31068
|
const title = options.title ?? "AbsoluteJS Voice Data Control";
|
|
30656
|
-
const routes = new
|
|
31069
|
+
const routes = new Elysia47({
|
|
30657
31070
|
name: options.name ?? "absolutejs-voice-data-control"
|
|
30658
31071
|
});
|
|
30659
31072
|
routes.get(path, async ({ query }) => {
|
|
@@ -30729,10 +31142,10 @@ var createVoiceDataControlRoutes = (options) => {
|
|
|
30729
31142
|
return routes;
|
|
30730
31143
|
};
|
|
30731
31144
|
// src/evalRoutes.ts
|
|
30732
|
-
import { Elysia as
|
|
31145
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
30733
31146
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
30734
31147
|
import { dirname as dirname2 } from "path";
|
|
30735
|
-
var
|
|
31148
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30736
31149
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
30737
31150
|
var normalizeSearchText = (value) => value.trim().toLowerCase();
|
|
30738
31151
|
var getString18 = (value) => typeof value === "string" ? value : undefined;
|
|
@@ -31054,7 +31467,7 @@ var createVoiceFileScenarioFixtureStore = (filePath) => ({
|
|
|
31054
31467
|
var formatTime = (value) => value === undefined ? "unknown" : new Date(value).toLocaleString();
|
|
31055
31468
|
var formatPercent = (value) => `${(value * 100).toFixed(2)}%`;
|
|
31056
31469
|
var renderVoiceEvalPrimitiveCopy = () => {
|
|
31057
|
-
const snippet =
|
|
31470
|
+
const snippet = escapeHtml45(`app.use(
|
|
31058
31471
|
createVoiceEvalRoutes({
|
|
31059
31472
|
path: '/evals',
|
|
31060
31473
|
store: traceStore,
|
|
@@ -31075,48 +31488,48 @@ var renderVoiceEvalPrimitiveCopy = () => {
|
|
|
31075
31488
|
};
|
|
31076
31489
|
var renderVoiceEvalHTML = (report, options = {}) => {
|
|
31077
31490
|
const title = options.title ?? "AbsoluteJS Voice Evals";
|
|
31078
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
31079
|
-
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${
|
|
31491
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
|
|
31492
|
+
const trend = report.trend.length ? report.trend.map((bucket) => `<tr><td>${escapeHtml45(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>';
|
|
31080
31493
|
const sessions = report.sessions.length ? report.sessions.map((session) => {
|
|
31081
31494
|
const failedMetrics = Object.entries(session.quality.metrics).filter(([, metric]) => !metric.pass).map(([, metric]) => metric.label).join(", ");
|
|
31082
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
31083
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
31495
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : escapeHtml45(session.sessionId);
|
|
31496
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml45(session.status)}</td><td>${session.eventCount}</td><td>${session.summary.turnCount}</td><td>${session.summary.errorCount}</td><td>${escapeHtml45(formatTime(session.endedAt))}</td><td>${escapeHtml45(failedMetrics || "none")}</td></tr>`;
|
|
31084
31497
|
}).join("") : '<tr><td colspan="7">No sessions found.</td></tr>';
|
|
31085
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31498
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(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>`;
|
|
31086
31499
|
};
|
|
31087
31500
|
var renderVoiceEvalBaselineHTML = (comparison, options = {}) => {
|
|
31088
31501
|
const title = options.title ?? "AbsoluteJS Voice Eval Baseline";
|
|
31089
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
31090
|
-
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${
|
|
31091
|
-
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${
|
|
31092
|
-
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${
|
|
31093
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31502
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
|
|
31503
|
+
const reasons = comparison.reasons.length ? comparison.reasons.map((reason) => `<li>${escapeHtml45(reason)}</li>`).join("") : "<li>No baseline regressions detected.</li>";
|
|
31504
|
+
const newFailures = comparison.newFailedSessionIds.length ? comparison.newFailedSessionIds.map((id) => `<li>${escapeHtml45(id)}</li>`).join("") : "<li>none</li>";
|
|
31505
|
+
const recovered = comparison.recoveredSessionIds.length ? comparison.recoveredSessionIds.map((id) => `<li>${escapeHtml45(id)}</li>`).join("") : "<li>none</li>";
|
|
31506
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(title)}</h1><p class="status ${comparison.status}">${comparison.status}</p><div class="grid"><article class="card"><span>Baseline pass rate</span><strong>${escapeHtml45(formatPercent(comparison.baseline.passRate))}</strong></article><article class="card"><span>Current pass rate</span><strong>${escapeHtml45(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>${escapeHtml45(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>`;
|
|
31094
31507
|
};
|
|
31095
31508
|
var renderVoiceScenarioEvalHTML = (report, options = {}) => {
|
|
31096
31509
|
const title = options.title ?? "AbsoluteJS Voice Scenario Evals";
|
|
31097
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
31510
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
|
|
31098
31511
|
const scenarios = report.scenarios.length ? report.scenarios.map((scenario) => {
|
|
31099
|
-
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${
|
|
31512
|
+
const scenarioIssues = scenario.issues.length ? `<ul>${scenario.issues.map((issue) => `<li>${escapeHtml45(issue)}</li>`).join("")}</ul>` : "";
|
|
31100
31513
|
const sessions = scenario.sessions.length ? scenario.sessions.map((session) => {
|
|
31101
|
-
const sessionLabel = session.operationsRecordHref ? `<a href="${
|
|
31102
|
-
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${
|
|
31514
|
+
const sessionLabel = session.operationsRecordHref ? `<a href="${escapeHtml45(session.operationsRecordHref)}">${escapeHtml45(session.sessionId)}</a>` : escapeHtml45(session.sessionId);
|
|
31515
|
+
return `<tr class="${session.status}"><td>${sessionLabel}</td><td>${escapeHtml45(session.status)}</td><td>${session.eventCount}</td><td>${escapeHtml45(session.issues.join(", ") || "none")}</td></tr>`;
|
|
31103
31516
|
}).join("") : '<tr><td colspan="4">No matching sessions.</td></tr>';
|
|
31104
|
-
return `<section class="scenario ${scenario.status}"><h2>${
|
|
31517
|
+
return `<section class="scenario ${scenario.status}"><h2>${escapeHtml45(scenario.label)}</h2>${scenario.description ? `<p>${escapeHtml45(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>`;
|
|
31105
31518
|
}).join("") : "<section><p>No scenarios configured.</p></section>";
|
|
31106
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31519
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(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>`;
|
|
31107
31520
|
};
|
|
31108
31521
|
var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
|
|
31109
31522
|
const title = options.title ?? "AbsoluteJS Voice Fixture Evals";
|
|
31110
|
-
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${
|
|
31523
|
+
const links = options.links?.length ? `<nav>${options.links.map((link) => `<a href="${escapeHtml45(link.href)}">${escapeHtml45(link.label)}</a>`).join("")}</nav>` : "";
|
|
31111
31524
|
const fixtures = report.fixtures.length ? report.fixtures.map((fixture) => {
|
|
31112
|
-
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${
|
|
31113
|
-
return `<section class="${fixture.status}"><h2>${
|
|
31525
|
+
const scenarios = fixture.report.scenarios.map((scenario) => `<tr class="${scenario.status}"><td>${escapeHtml45(scenario.label)}</td><td>${escapeHtml45(scenario.status)}</td><td>${scenario.matchedSessions}</td><td>${escapeHtml45([...scenario.issues, ...scenario.sessions.flatMap((session) => session.issues)].join(", ") || "none")}</td></tr>`).join("");
|
|
31526
|
+
return `<section class="${fixture.status}"><h2>${escapeHtml45(fixture.label)}</h2>${fixture.description ? `<p>${escapeHtml45(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>`;
|
|
31114
31527
|
}).join("") : "<section><p>No scenario fixtures configured.</p></section>";
|
|
31115
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31528
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml45(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>${escapeHtml45(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>`;
|
|
31116
31529
|
};
|
|
31117
31530
|
var createVoiceEvalRoutes = (options) => {
|
|
31118
31531
|
const path = options.path ?? "/evals";
|
|
31119
|
-
const routes = new
|
|
31532
|
+
const routes = new Elysia48({
|
|
31120
31533
|
name: options.name ?? "absolutejs-voice-evals"
|
|
31121
31534
|
});
|
|
31122
31535
|
const getReport = () => runVoiceSessionEvals({
|
|
@@ -31253,11 +31666,11 @@ var createVoiceEvalRoutes = (options) => {
|
|
|
31253
31666
|
return routes;
|
|
31254
31667
|
};
|
|
31255
31668
|
// src/simulationSuite.ts
|
|
31256
|
-
import { Elysia as
|
|
31669
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
31257
31670
|
|
|
31258
31671
|
// src/outcomeContract.ts
|
|
31259
|
-
import { Elysia as
|
|
31260
|
-
var
|
|
31672
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
31673
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31261
31674
|
var resolveSessionHref4 = (value, sessionId) => {
|
|
31262
31675
|
if (value === false) {
|
|
31263
31676
|
return;
|
|
@@ -31468,13 +31881,13 @@ var assertVoiceOutcomeContractEvidence = (report, input = {}) => {
|
|
|
31468
31881
|
var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
31469
31882
|
const title = options.title ?? "Voice Outcome Contracts";
|
|
31470
31883
|
const contracts = report.contracts.map((contract) => {
|
|
31471
|
-
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${
|
|
31884
|
+
const sessionLinks = contract.operationsRecordHrefs.length ? `<p>${contract.operationsRecordHrefs.map((href, index) => `<a href="${escapeHtml46(href)}">${escapeHtml46(contract.sessionIds[index] ?? href)}</a>`).join(" \xB7 ")}</p>` : "";
|
|
31472
31885
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
31473
31886
|
<div class="contract-header">
|
|
31474
31887
|
<div>
|
|
31475
|
-
<p class="eyebrow">${
|
|
31476
|
-
<h2>${
|
|
31477
|
-
${contract.description ? `<p>${
|
|
31888
|
+
<p class="eyebrow">${escapeHtml46(contract.contractId)}</p>
|
|
31889
|
+
<h2>${escapeHtml46(contract.label ?? contract.contractId)}</h2>
|
|
31890
|
+
${contract.description ? `<p>${escapeHtml46(contract.description)}</p>` : ""}
|
|
31478
31891
|
${sessionLinks}
|
|
31479
31892
|
</div>
|
|
31480
31893
|
<strong>${contract.pass ? "pass" : "fail"}</strong>
|
|
@@ -31486,10 +31899,10 @@ var renderVoiceOutcomeContractHTML = (report, options = {}) => {
|
|
|
31486
31899
|
<span>handoffs ${String(contract.matched.handoffs)}</span>
|
|
31487
31900
|
<span>events ${String(contract.matched.integrationEvents)}</span>
|
|
31488
31901
|
</div>
|
|
31489
|
-
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${
|
|
31902
|
+
${contract.issues.length ? `<ul>${contract.issues.map((issue) => `<li>${escapeHtml46(issue.message)}</li>`).join("")}</ul>` : ""}
|
|
31490
31903
|
</section>`;
|
|
31491
31904
|
}).join("");
|
|
31492
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31905
|
+
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,.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>${escapeHtml46(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>`;
|
|
31493
31906
|
};
|
|
31494
31907
|
var createVoiceOutcomeContractJSONHandler = (options) => async () => runVoiceOutcomeContractSuite(options);
|
|
31495
31908
|
var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
@@ -31505,7 +31918,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
|
|
|
31505
31918
|
var createVoiceOutcomeContractRoutes = (options) => {
|
|
31506
31919
|
const path = options.path ?? "/api/outcome-contracts";
|
|
31507
31920
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
31508
|
-
const routes = new
|
|
31921
|
+
const routes = new Elysia49({
|
|
31509
31922
|
name: options.name ?? "absolutejs-voice-outcome-contracts"
|
|
31510
31923
|
}).get(path, createVoiceOutcomeContractJSONHandler(options));
|
|
31511
31924
|
if (htmlPath) {
|
|
@@ -31515,7 +31928,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
|
|
|
31515
31928
|
};
|
|
31516
31929
|
|
|
31517
31930
|
// src/toolContract.ts
|
|
31518
|
-
import { Elysia as
|
|
31931
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
31519
31932
|
|
|
31520
31933
|
// src/toolRuntime.ts
|
|
31521
31934
|
var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
|
|
@@ -31724,7 +32137,7 @@ var createDefaultTurn = (caseId) => ({
|
|
|
31724
32137
|
});
|
|
31725
32138
|
var defaultApi = {};
|
|
31726
32139
|
var sameJSON = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
31727
|
-
var
|
|
32140
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31728
32141
|
var resolveSessionHref5 = (value, sessionId) => {
|
|
31729
32142
|
if (value === false) {
|
|
31730
32143
|
return;
|
|
@@ -31973,7 +32386,7 @@ var assertVoiceToolContractEvidence = (report, input = {}) => {
|
|
|
31973
32386
|
};
|
|
31974
32387
|
var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
31975
32388
|
const title = options.title ?? "Voice Tool Contracts";
|
|
31976
|
-
const snippet =
|
|
32389
|
+
const snippet = escapeHtml47(`app.use(
|
|
31977
32390
|
createVoiceToolContractRoutes({
|
|
31978
32391
|
htmlPath: '/tool-contracts',
|
|
31979
32392
|
path: '/api/tool-contracts',
|
|
@@ -31999,20 +32412,20 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
31999
32412
|
);`);
|
|
32000
32413
|
const contracts = report.contracts.map((contract) => {
|
|
32001
32414
|
const cases = contract.cases.map((testCase) => `<tr>
|
|
32002
|
-
<td>${testCase.operationsRecordHref ? `<a href="${
|
|
32415
|
+
<td>${testCase.operationsRecordHref ? `<a href="${escapeHtml47(testCase.operationsRecordHref)}">${escapeHtml47(testCase.label ?? testCase.caseId)}</a>` : escapeHtml47(testCase.label ?? testCase.caseId)}</td>
|
|
32003
32416
|
<td class="${testCase.pass ? "pass" : "fail"}">${testCase.pass ? "pass" : "fail"}</td>
|
|
32004
|
-
<td>${
|
|
32005
|
-
<td>${
|
|
32417
|
+
<td>${escapeHtml47(testCase.status)}</td>
|
|
32418
|
+
<td>${escapeHtml47(testCase.sessionId)}</td>
|
|
32006
32419
|
<td>${String(testCase.attempts)}</td>
|
|
32007
32420
|
<td>${String(testCase.elapsedMs)}ms</td>
|
|
32008
32421
|
<td>${testCase.timedOut ? "yes" : "no"}</td>
|
|
32009
|
-
<td>${
|
|
32422
|
+
<td>${escapeHtml47(testCase.issues.map((issue) => issue.message).join(" ") || testCase.error || "")}</td>
|
|
32010
32423
|
</tr>`).join("");
|
|
32011
32424
|
return `<section class="contract ${contract.pass ? "pass" : "fail"}">
|
|
32012
32425
|
<div class="contract-header">
|
|
32013
32426
|
<div>
|
|
32014
|
-
<p class="eyebrow">${
|
|
32015
|
-
<h2>${
|
|
32427
|
+
<p class="eyebrow">${escapeHtml47(contract.toolName)}</p>
|
|
32428
|
+
<h2>${escapeHtml47(contract.label ?? contract.contractId)}</h2>
|
|
32016
32429
|
</div>
|
|
32017
32430
|
<strong class="${contract.pass ? "pass" : "fail"}">${contract.pass ? "Passing" : "Failing"}</strong>
|
|
32018
32431
|
</div>
|
|
@@ -32022,7 +32435,7 @@ var renderVoiceToolContractHTML = (report, options = {}) => {
|
|
|
32022
32435
|
</table>
|
|
32023
32436
|
</section>`;
|
|
32024
32437
|
}).join("");
|
|
32025
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32438
|
+
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:#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>${escapeHtml47(title)}</h1><div class="summary"><span class="pill ${report.status === "pass" ? "pass" : "fail"}">${escapeHtml47(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>`;
|
|
32026
32439
|
};
|
|
32027
32440
|
var createVoiceToolContractJSONHandler = (options) => () => runVoiceToolContractSuite(options);
|
|
32028
32441
|
var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
@@ -32039,7 +32452,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
|
|
|
32039
32452
|
var createVoiceToolContractRoutes = (options) => {
|
|
32040
32453
|
const path = options.path ?? "/api/tool-contracts";
|
|
32041
32454
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
32042
|
-
const routes = new
|
|
32455
|
+
const routes = new Elysia50({
|
|
32043
32456
|
name: options.name ?? "absolutejs-voice-tool-contracts"
|
|
32044
32457
|
}).get(path, createVoiceToolContractJSONHandler(options));
|
|
32045
32458
|
if (htmlPath) {
|
|
@@ -32049,7 +32462,7 @@ var createVoiceToolContractRoutes = (options) => {
|
|
|
32049
32462
|
};
|
|
32050
32463
|
|
|
32051
32464
|
// src/simulationSuite.ts
|
|
32052
|
-
var
|
|
32465
|
+
var escapeHtml48 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32053
32466
|
var summarizeSection = (report) => ({
|
|
32054
32467
|
failed: report.failed,
|
|
32055
32468
|
passed: report.passed,
|
|
@@ -32245,15 +32658,15 @@ var renderSection = (label, summary) => {
|
|
|
32245
32658
|
if (!summary) {
|
|
32246
32659
|
return "";
|
|
32247
32660
|
}
|
|
32248
|
-
return `<article class="${
|
|
32661
|
+
return `<article class="${escapeHtml48(summary.status)}"><span>${escapeHtml48(label)}</span><strong>${escapeHtml48(summary.status)}</strong><p>${summary.passed}/${summary.total} passed, ${summary.failed} failed.</p></article>`;
|
|
32249
32662
|
};
|
|
32250
32663
|
var renderAction = (action) => {
|
|
32251
|
-
const content = `<strong>${
|
|
32252
|
-
return action.href ? `<a class="action" href="${
|
|
32664
|
+
const content = `<strong>${escapeHtml48(action.label)}</strong><p>${escapeHtml48(action.description)}</p><span>${escapeHtml48(action.section)} / ${escapeHtml48(action.severity)}</span>`;
|
|
32665
|
+
return action.href ? `<a class="action" href="${escapeHtml48(action.href)}">${content}</a>` : `<article class="action">${content}</article>`;
|
|
32253
32666
|
};
|
|
32254
32667
|
var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
|
|
32255
32668
|
const title = options.title ?? "Voice Simulation Suite";
|
|
32256
|
-
const snippet =
|
|
32669
|
+
const snippet = escapeHtml48(`app.use(
|
|
32257
32670
|
createVoiceSimulationSuiteRoutes({
|
|
32258
32671
|
htmlPath: '/voice/simulations',
|
|
32259
32672
|
path: '/api/voice/simulations',
|
|
@@ -32286,12 +32699,12 @@ app.use(
|
|
|
32286
32699
|
store: traceStore
|
|
32287
32700
|
})
|
|
32288
32701
|
);`);
|
|
32289
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
32702
|
+
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:#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>${escapeHtml48(title)}</h1><p>One report for session quality, scenario evals, fixture simulations, tool contracts, and outcome contracts.</p><p class="badge ${escapeHtml48(report.status)}">Status: ${escapeHtml48(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>${escapeHtml48(JSON.stringify({ summary: report.summary, actions: report.actions }, null, 2))}</pre></main></body></html>`;
|
|
32290
32703
|
};
|
|
32291
32704
|
var createVoiceSimulationSuiteRoutes = (options) => {
|
|
32292
32705
|
const path = options.path ?? "/api/voice/simulations";
|
|
32293
32706
|
const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
|
|
32294
|
-
const app = new
|
|
32707
|
+
const app = new Elysia51({
|
|
32295
32708
|
name: options.name ?? "absolutejs-voice-simulation-suite"
|
|
32296
32709
|
}).get(path, () => runVoiceSimulationSuite(options));
|
|
32297
32710
|
if (htmlPath) {
|
|
@@ -32908,10 +33321,10 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
32908
33321
|
return report;
|
|
32909
33322
|
};
|
|
32910
33323
|
// src/turnLatency.ts
|
|
32911
|
-
import { Elysia as
|
|
33324
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
32912
33325
|
var DEFAULT_WARN_AFTER_MS2 = 1800;
|
|
32913
33326
|
var DEFAULT_FAIL_AFTER_MS2 = 3200;
|
|
32914
|
-
var
|
|
33327
|
+
var escapeHtml49 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
32915
33328
|
var firstNumber4 = (values) => values.filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
32916
33329
|
var getString19 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
32917
33330
|
var createTraceStageIndex = (events) => {
|
|
@@ -33043,11 +33456,11 @@ await traceStore.append({
|
|
|
33043
33456
|
turnId,
|
|
33044
33457
|
type: 'turn_latency.stage'
|
|
33045
33458
|
});`;
|
|
33046
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
33047
|
-
<header><div><p class="eyebrow">${
|
|
33048
|
-
<dl>${turn.stages.map((stage) => `<div><dt>${
|
|
33459
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml49(turn.status)}">
|
|
33460
|
+
<header><div><p class="eyebrow">${escapeHtml49(turn.sessionId)} \xB7 ${escapeHtml49(turn.turnId)}</p><h2>${escapeHtml49(turn.text || "Empty turn")}</h2></div><strong>${escapeHtml49(turn.status)}</strong></header>
|
|
33461
|
+
<dl>${turn.stages.map((stage) => `<div><dt>${escapeHtml49(stage.label)}</dt><dd>${escapeHtml49(formatMs4(stage.valueMs))}</dd></div>`).join("")}</dl>
|
|
33049
33462
|
</article>`).join("");
|
|
33050
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33463
|
+
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{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>${escapeHtml49(title)}</h1><div class="summary"><span class="pill ${escapeHtml49(report.status)}">${escapeHtml49(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">avg ${escapeHtml49(formatMs4(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>${escapeHtml49(snippet)}</code></pre></section>${turns || '<section class="turn"><p>No committed turns found.</p></section>'}</main></body></html>`;
|
|
33051
33464
|
};
|
|
33052
33465
|
var createVoiceTurnLatencyJSONHandler = (options) => async () => summarizeVoiceTurnLatency(options);
|
|
33053
33466
|
var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
@@ -33064,7 +33477,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
33064
33477
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
33065
33478
|
const path = options.path ?? "/api/turn-latency";
|
|
33066
33479
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
33067
|
-
const routes = new
|
|
33480
|
+
const routes = new Elysia52({
|
|
33068
33481
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
33069
33482
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
33070
33483
|
if (htmlPath) {
|
|
@@ -33073,8 +33486,8 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
33073
33486
|
return routes;
|
|
33074
33487
|
};
|
|
33075
33488
|
// src/liveLatency.ts
|
|
33076
|
-
import { Elysia as
|
|
33077
|
-
var
|
|
33489
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
33490
|
+
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33078
33491
|
var percentile6 = (values, percentileValue) => {
|
|
33079
33492
|
if (values.length === 0) {
|
|
33080
33493
|
return;
|
|
@@ -33141,13 +33554,13 @@ await traceStore.append({
|
|
|
33141
33554
|
sessionId,
|
|
33142
33555
|
type: 'client.live_latency'
|
|
33143
33556
|
});`;
|
|
33144
|
-
const rows = report.recent.map((sample) => `<tr><td>${
|
|
33145
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33557
|
+
const rows = report.recent.map((sample) => `<tr><td>${escapeHtml50(sample.sessionId)}</td><td>${escapeHtml50(formatMs5(sample.latencyMs))}</td><td>${escapeHtml50(sample.status ?? "unknown")}</td><td>${escapeHtml50(new Date(sample.at).toLocaleString())}</td></tr>`).join("");
|
|
33558
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml50(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>${escapeHtml50(title)}</h1><p>Recent real browser speech-to-assistant response measurements from persisted <code>client.live_latency</code> traces.</p><p class="status ${escapeHtml50(report.status)}">Status: ${escapeHtml50(report.status)}</p><section class="metrics"><article><span>p50</span><strong>${escapeHtml50(formatMs5(report.p50LatencyMs))}</strong></article><article><span>p95</span><strong>${escapeHtml50(formatMs5(report.p95LatencyMs))}</strong></article><article><span>Average</span><strong>${escapeHtml50(formatMs5(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>${escapeHtml50(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>`;
|
|
33146
33559
|
};
|
|
33147
33560
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
33148
33561
|
const path = options.path ?? "/api/live-latency";
|
|
33149
33562
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
33150
|
-
const routes = new
|
|
33563
|
+
const routes = new Elysia53({
|
|
33151
33564
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
33152
33565
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
33153
33566
|
if (htmlPath) {
|
|
@@ -33164,9 +33577,9 @@ var createVoiceLiveLatencyRoutes = (options) => {
|
|
|
33164
33577
|
return routes;
|
|
33165
33578
|
};
|
|
33166
33579
|
// src/turnQuality.ts
|
|
33167
|
-
import { Elysia as
|
|
33580
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
33168
33581
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
33169
|
-
var
|
|
33582
|
+
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33170
33583
|
var getTurnLatencyMs = (turn) => {
|
|
33171
33584
|
const firstTranscriptAt = turn.transcripts.map((transcript) => transcript.endedAtMs ?? transcript.startedAtMs).filter((value) => typeof value === "number").sort((left, right) => left - right)[0];
|
|
33172
33585
|
if (firstTranscriptAt === undefined) {
|
|
@@ -33236,24 +33649,24 @@ var summarizeVoiceTurnQuality = async (options) => {
|
|
|
33236
33649
|
};
|
|
33237
33650
|
var renderVoiceTurnQualityHTML = (report, options = {}) => {
|
|
33238
33651
|
const title = options.title ?? "Voice Turn Quality";
|
|
33239
|
-
const turns = report.turns.map((turn) => `<article class="turn ${
|
|
33652
|
+
const turns = report.turns.map((turn) => `<article class="turn ${escapeHtml51(turn.status)}">
|
|
33240
33653
|
<div class="turn-header">
|
|
33241
33654
|
<div>
|
|
33242
|
-
<p class="eyebrow">${
|
|
33243
|
-
<h2>${
|
|
33655
|
+
<p class="eyebrow">${escapeHtml51(turn.sessionId)} \xB7 ${escapeHtml51(turn.turnId)}</p>
|
|
33656
|
+
<h2>${escapeHtml51(turn.text || "Empty turn")}</h2>
|
|
33244
33657
|
</div>
|
|
33245
|
-
<strong>${
|
|
33658
|
+
<strong>${escapeHtml51(turn.status)}</strong>
|
|
33246
33659
|
</div>
|
|
33247
33660
|
<dl>
|
|
33248
|
-
<div><dt>Source</dt><dd>${
|
|
33661
|
+
<div><dt>Source</dt><dd>${escapeHtml51(turn.source ?? "unknown")}</dd></div>
|
|
33249
33662
|
<div><dt>Confidence</dt><dd>${turn.averageConfidence === undefined ? "n/a" : `${Math.round(turn.averageConfidence * 100)}%`}</dd></div>
|
|
33250
|
-
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${
|
|
33251
|
-
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${
|
|
33663
|
+
<div><dt>Fallback</dt><dd>${turn.fallbackUsed ? `yes (${escapeHtml51(turn.fallbackSelectionReason ?? "selected")})` : "no"}</dd></div>
|
|
33664
|
+
<div><dt>Correction</dt><dd>${turn.correctionChanged ? `changed${turn.correctionProvider ? ` by ${escapeHtml51(turn.correctionProvider)}` : ""}` : "none"}</dd></div>
|
|
33252
33665
|
<div><dt>Transcripts</dt><dd>${String(turn.selectedTranscriptCount)} selected \xB7 ${String(turn.finalTranscriptCount)} final \xB7 ${String(turn.partialTranscriptCount)} partial</dd></div>
|
|
33253
33666
|
<div><dt>Cost</dt><dd>${turn.costUnits === undefined ? "n/a" : String(turn.costUnits)}</dd></div>
|
|
33254
33667
|
</dl>
|
|
33255
33668
|
</article>`).join("");
|
|
33256
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33669
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml51(title)}</title><style>body{background:#101316;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,.turn{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>${escapeHtml51(title)}</h1><div class="summary"><span class="pill ${escapeHtml51(report.status)}">${escapeHtml51(report.status)}</span><span class="pill">${String(report.total)} turns</span><span class="pill">${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>`;
|
|
33257
33670
|
};
|
|
33258
33671
|
var createVoiceTurnQualityJSONHandler = (options) => async () => summarizeVoiceTurnQuality(options);
|
|
33259
33672
|
var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
@@ -33270,7 +33683,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
33270
33683
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
33271
33684
|
const path = options.path ?? "/api/turn-quality";
|
|
33272
33685
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
33273
|
-
const routes = new
|
|
33686
|
+
const routes = new Elysia54({
|
|
33274
33687
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
33275
33688
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
33276
33689
|
if (htmlPath) {
|
|
@@ -33279,10 +33692,10 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
33279
33692
|
return routes;
|
|
33280
33693
|
};
|
|
33281
33694
|
// src/phoneAgent.ts
|
|
33282
|
-
import { Elysia as
|
|
33695
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
33283
33696
|
|
|
33284
33697
|
// src/phoneAgentProductionSmoke.ts
|
|
33285
|
-
import { Elysia as
|
|
33698
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
33286
33699
|
var defaultRequirements = [
|
|
33287
33700
|
"media-started",
|
|
33288
33701
|
"transcript",
|
|
@@ -33290,7 +33703,7 @@ var defaultRequirements = [
|
|
|
33290
33703
|
"lifecycle-outcome",
|
|
33291
33704
|
"no-session-error"
|
|
33292
33705
|
];
|
|
33293
|
-
var
|
|
33706
|
+
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
33294
33707
|
var payloadType = (event) => typeof event.payload.type === "string" ? event.payload.type : undefined;
|
|
33295
33708
|
var hasTextPayload = (event) => ["text", "assistantText", "transcript"].some((key) => {
|
|
33296
33709
|
const value = event.payload[key];
|
|
@@ -33399,10 +33812,10 @@ var resolveHandlerOptions = async (options, input) => ({
|
|
|
33399
33812
|
});
|
|
33400
33813
|
var renderVoicePhoneAgentProductionSmokeHTML = (report, options = {}) => {
|
|
33401
33814
|
const title = options.title ?? "AbsoluteJS Voice Phone Smoke Contract";
|
|
33402
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
33403
|
-
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${
|
|
33404
|
-
const requirements = report.required.map((requirement) => `<span class="pill">${
|
|
33405
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
33815
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml52(issue.requirement)}</strong>: ${escapeHtml52(issue.message)}</li>`).join("");
|
|
33816
|
+
const outcomes = report.observed.lifecycleOutcomes.map((outcome) => `<span class="pill">${escapeHtml52(outcome)}</span>`).join("");
|
|
33817
|
+
const requirements = report.required.map((requirement) => `<span class="pill">${escapeHtml52(requirement)}</span>`).join("");
|
|
33818
|
+
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:#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>${escapeHtml52(title)}</h1><p class="status ${report.pass ? "pass" : "fail"}">${report.pass ? "PASS" : "FAIL"}</p><p>Contract <code>${escapeHtml52(report.contractId)}</code>${report.provider ? ` for <code>${escapeHtml52(report.provider)}</code>` : ""}${report.sessionId ? ` on session <code>${escapeHtml52(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>`;
|
|
33406
33819
|
};
|
|
33407
33820
|
var createVoicePhoneAgentProductionSmokeJSONHandler = (options) => async ({
|
|
33408
33821
|
query,
|
|
@@ -33425,7 +33838,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
33425
33838
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
33426
33839
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
33427
33840
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
33428
|
-
const routes = new
|
|
33841
|
+
const routes = new Elysia55({
|
|
33429
33842
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
33430
33843
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
33431
33844
|
if (htmlPath) {
|
|
@@ -33468,7 +33881,7 @@ var PHONE_AGENT_LIFECYCLE_STAGES = [
|
|
|
33468
33881
|
"completed",
|
|
33469
33882
|
"failed"
|
|
33470
33883
|
];
|
|
33471
|
-
var
|
|
33884
|
+
var escapeHtml53 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
33472
33885
|
var loadRouteJson = async (input) => {
|
|
33473
33886
|
const response = await input.app.handle(new Request(new URL(input.path, input.origin).toString(), {
|
|
33474
33887
|
headers: {
|
|
@@ -33706,10 +34119,10 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
33706
34119
|
const entry = findCarrierMatrixEntry(report.matrix, carrier);
|
|
33707
34120
|
const urls = entry?.setup.urls;
|
|
33708
34121
|
const primaryUrl = carrier.provider === "plivo" ? urls?.twiml : urls?.twiml;
|
|
33709
|
-
return `<tr><td>${
|
|
34122
|
+
return `<tr><td>${escapeHtml53(carrier.name ?? carrier.provider)}</td><td>${escapeHtml53(carrier.provider)}</td><td><code>${escapeHtml53(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml53(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml53(entry.status)}">${escapeHtml53(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml53(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml53(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml53(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
33710
34123
|
}).join("");
|
|
33711
|
-
const stageList = report.lifecycleStages.map((stage) => `<li><code>${
|
|
33712
|
-
const snippet =
|
|
34124
|
+
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml53(stage)}</code></li>`).join("");
|
|
34125
|
+
const snippet = escapeHtml53(`const phoneAgent = createVoicePhoneAgent({
|
|
33713
34126
|
carriers: [
|
|
33714
34127
|
{
|
|
33715
34128
|
provider: 'twilio',
|
|
@@ -33743,11 +34156,11 @@ app.use(
|
|
|
33743
34156
|
);`);
|
|
33744
34157
|
const checklist = report.carriers.map((carrier) => {
|
|
33745
34158
|
const instruction = report.setupInstructions.find((candidate) => candidate.provider === carrier.provider && candidate.carrierName === (carrier.name ?? carrier.provider));
|
|
33746
|
-
const issueList = instruction?.issues.map((issue) => `<li>${
|
|
33747
|
-
const steps = instruction?.steps.map((step) => `<li>${
|
|
33748
|
-
return `<article><h3>${
|
|
34159
|
+
const issueList = instruction?.issues.map((issue) => `<li>${escapeHtml53(issue)}</li>`).join("") ?? "";
|
|
34160
|
+
const steps = instruction?.steps.map((step) => `<li>${escapeHtml53(step)}</li>`).join("") ?? "";
|
|
34161
|
+
return `<article><h3>${escapeHtml53(carrier.name ?? carrier.provider)}</h3><ol>${steps}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
33749
34162
|
}).join("");
|
|
33750
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
34163
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml53(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>${escapeHtml53(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="${escapeHtml53(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>`;
|
|
33751
34164
|
};
|
|
33752
34165
|
var createVoicePhoneAgent = (options) => {
|
|
33753
34166
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -33756,7 +34169,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
33756
34169
|
setupPath: resolveSetupPath(carrier),
|
|
33757
34170
|
smokePath: resolveSmokePath(carrier)
|
|
33758
34171
|
}));
|
|
33759
|
-
const app = new
|
|
34172
|
+
const app = new Elysia56({
|
|
33760
34173
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
33761
34174
|
});
|
|
33762
34175
|
for (const carrier of options.carriers) {
|
|
@@ -35503,8 +35916,8 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
35503
35916
|
};
|
|
35504
35917
|
};
|
|
35505
35918
|
// src/providerCapabilities.ts
|
|
35506
|
-
import { Elysia as
|
|
35507
|
-
var
|
|
35919
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
35920
|
+
var escapeHtml54 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
35508
35921
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
35509
35922
|
configured: true,
|
|
35510
35923
|
features: options.features?.[provider],
|
|
@@ -35567,27 +35980,27 @@ var summarizeVoiceProviderCapabilities = async (options) => {
|
|
|
35567
35980
|
var renderVoiceProviderCapabilityHTML = (report, options = {}) => {
|
|
35568
35981
|
const title = options.title ?? "Voice Provider Capabilities";
|
|
35569
35982
|
const cards = report.capabilities.map((capability) => {
|
|
35570
|
-
const features = (capability.features ?? []).map((feature) => `<span class="pill">${
|
|
35571
|
-
return `<article class="card ${
|
|
35983
|
+
const features = (capability.features ?? []).map((feature) => `<span class="pill">${escapeHtml54(feature)}</span>`).join("");
|
|
35984
|
+
return `<article class="card ${escapeHtml54(capability.status)}">
|
|
35572
35985
|
<div class="card-header">
|
|
35573
35986
|
<div>
|
|
35574
|
-
<p class="eyebrow">${
|
|
35575
|
-
<h2>${
|
|
35987
|
+
<p class="eyebrow">${escapeHtml54(capability.kind)}</p>
|
|
35988
|
+
<h2>${escapeHtml54(capability.label ?? capability.provider)}</h2>
|
|
35576
35989
|
</div>
|
|
35577
|
-
<strong>${
|
|
35990
|
+
<strong>${escapeHtml54(capability.status)}</strong>
|
|
35578
35991
|
</div>
|
|
35579
|
-
${capability.description ? `<p>${
|
|
35992
|
+
${capability.description ? `<p>${escapeHtml54(capability.description)}</p>` : ""}
|
|
35580
35993
|
<dl>
|
|
35581
35994
|
<div><dt>Configured</dt><dd>${capability.configured ? "yes" : "no"}</dd></div>
|
|
35582
35995
|
<div><dt>Selected</dt><dd>${capability.selected ? "yes" : "no"}</dd></div>
|
|
35583
|
-
<div><dt>Model</dt><dd>${
|
|
35996
|
+
<div><dt>Model</dt><dd>${escapeHtml54(capability.model ?? "default")}</dd></div>
|
|
35584
35997
|
<div><dt>Runs</dt><dd>${String(capability.health?.runCount ?? 0)}</dd></div>
|
|
35585
35998
|
<div><dt>Errors</dt><dd>${String(capability.health?.errorCount ?? 0)}</dd></div>
|
|
35586
35999
|
</dl>
|
|
35587
36000
|
${features ? `<div class="features">${features}</div>` : ""}
|
|
35588
36001
|
</article>`;
|
|
35589
36002
|
}).join("");
|
|
35590
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
36003
|
+
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:#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>${escapeHtml54(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>`;
|
|
35591
36004
|
};
|
|
35592
36005
|
var createVoiceProviderCapabilityJSONHandler = (options) => async () => summarizeVoiceProviderCapabilities(options);
|
|
35593
36006
|
var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
@@ -35604,7 +36017,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
35604
36017
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
35605
36018
|
const path = options.path ?? "/api/provider-capabilities";
|
|
35606
36019
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
35607
|
-
const routes = new
|
|
36020
|
+
const routes = new Elysia57({
|
|
35608
36021
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
35609
36022
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
35610
36023
|
if (htmlPath) {
|
|
@@ -35613,7 +36026,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
35613
36026
|
return routes;
|
|
35614
36027
|
};
|
|
35615
36028
|
// src/providerOrchestration.ts
|
|
35616
|
-
import { Elysia as
|
|
36029
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
35617
36030
|
var defaultRequirement = {
|
|
35618
36031
|
minProviders: 1,
|
|
35619
36032
|
requireBudgetPolicy: false,
|
|
@@ -35626,7 +36039,7 @@ var statusRank6 = {
|
|
|
35626
36039
|
warn: 1,
|
|
35627
36040
|
fail: 2
|
|
35628
36041
|
};
|
|
35629
|
-
var
|
|
36042
|
+
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
35630
36043
|
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
35631
36044
|
var uniqueSorted8 = (values) => [
|
|
35632
36045
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
@@ -35769,27 +36182,27 @@ var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
|
35769
36182
|
};
|
|
35770
36183
|
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
35771
36184
|
const title = options.title ?? "Voice Provider Orchestration";
|
|
35772
|
-
const cards = report.surfaces.map((surface) => `<article class="card ${
|
|
35773
|
-
<div class="card-header"><div><p class="eyebrow">${
|
|
36185
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml55(surface.status)}">
|
|
36186
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml55(surface.surface)}</p><h2>${escapeHtml55(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml55(surface.status)}</strong></div>
|
|
35774
36187
|
<dl>
|
|
35775
|
-
<div><dt>Providers</dt><dd>${
|
|
35776
|
-
<div><dt>Fallback</dt><dd>${
|
|
36188
|
+
<div><dt>Providers</dt><dd>${escapeHtml55(surface.providers.join(", ") || "none")}</dd></div>
|
|
36189
|
+
<div><dt>Fallback</dt><dd>${escapeHtml55(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
35777
36190
|
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
35778
36191
|
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
35779
36192
|
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
35780
36193
|
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
35781
36194
|
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
35782
|
-
<div><dt>Fallback mode</dt><dd>${
|
|
36195
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml55(surface.fallbackMode || "default")}</dd></div>
|
|
35783
36196
|
</dl>
|
|
35784
|
-
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${
|
|
36197
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml55(issue.status)}</strong> ${escapeHtml55(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
35785
36198
|
</article>`).join("");
|
|
35786
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
36199
|
+
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{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>${escapeHtml55(title)}</h1><div class="summary"><span class="pill">${escapeHtml55(report.profileId)}</span><span class="pill">${escapeHtml55(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>`;
|
|
35787
36200
|
};
|
|
35788
36201
|
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
35789
36202
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
35790
36203
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
35791
36204
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
35792
|
-
const routes = new
|
|
36205
|
+
const routes = new Elysia58({
|
|
35793
36206
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
35794
36207
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
35795
36208
|
if (htmlPath) {
|
|
@@ -35960,8 +36373,8 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
35960
36373
|
return report;
|
|
35961
36374
|
};
|
|
35962
36375
|
// src/voiceMonitoring.ts
|
|
35963
|
-
import { Elysia as
|
|
35964
|
-
var
|
|
36376
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
36377
|
+
var escapeHtml56 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
35965
36378
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
35966
36379
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
35967
36380
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -36214,14 +36627,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
36214
36627
|
};
|
|
36215
36628
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
36216
36629
|
const title = options.title ?? "Voice Monitors";
|
|
36217
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
36218
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
36219
|
-
const snippet =
|
|
36630
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml56(run.label)}</td><td class="${escapeHtml56(run.status)}">${escapeHtml56(run.status)}</td><td>${escapeHtml56(run.severity)}</td><td>${escapeHtml56(String(run.value ?? ""))}</td><td>${escapeHtml56(String(run.threshold ?? ""))}</td><td>${escapeHtml56(run.detail ?? "")}</td></tr>`).join("");
|
|
36631
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml56(issue.label)}</strong> <span class="${escapeHtml56(issue.status)}">${escapeHtml56(issue.status)}</span> ${escapeHtml56(issue.detail ?? "")}</li>`).join("");
|
|
36632
|
+
const snippet = escapeHtml56(`app.use(createVoiceMonitorRoutes({
|
|
36220
36633
|
evidence,
|
|
36221
36634
|
issueStore,
|
|
36222
36635
|
monitors: [defineVoiceMonitor(...)]
|
|
36223
36636
|
}));`);
|
|
36224
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
36637
|
+
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:#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>${escapeHtml56(title)}</h1><p class="pill ${escapeHtml56(report.status)}">Status: ${escapeHtml56(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>`;
|
|
36225
36638
|
};
|
|
36226
36639
|
var actorFromRequest = async (request) => {
|
|
36227
36640
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -36245,7 +36658,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
36245
36658
|
monitors: options.monitors,
|
|
36246
36659
|
now: options.now
|
|
36247
36660
|
});
|
|
36248
|
-
const routes = new
|
|
36661
|
+
const routes = new Elysia59({
|
|
36249
36662
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
36250
36663
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
36251
36664
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -36292,7 +36705,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
36292
36705
|
};
|
|
36293
36706
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
36294
36707
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
36295
|
-
return new
|
|
36708
|
+
return new Elysia59({
|
|
36296
36709
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
36297
36710
|
}).get(path, () => ({
|
|
36298
36711
|
isRunning: options.runner.isRunning()
|
|
@@ -36668,8 +37081,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
36668
37081
|
};
|
|
36669
37082
|
};
|
|
36670
37083
|
// src/providerStackRecommendations.ts
|
|
36671
|
-
import { Elysia as
|
|
36672
|
-
var
|
|
37084
|
+
import { Elysia as Elysia60 } from "elysia";
|
|
37085
|
+
var escapeHtml57 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
36673
37086
|
var profileProviderPriorities = {
|
|
36674
37087
|
"meeting-recorder": {
|
|
36675
37088
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -36988,17 +37401,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
36988
37401
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
36989
37402
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
36990
37403
|
const rows = report.rows.map((row) => {
|
|
36991
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
36992
|
-
return `<article class="row ${
|
|
37404
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml57(check.status)}"><strong>${escapeHtml57(check.label)}</strong><span>${escapeHtml57(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml57(check.remediation.href)}">${escapeHtml57(check.remediation.label)}</a>` : escapeHtml57(check.remediation.label)}: ${escapeHtml57(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
37405
|
+
return `<article class="row ${escapeHtml57(row.status)}">
|
|
36993
37406
|
<div>
|
|
36994
|
-
<p class="eyebrow">${
|
|
36995
|
-
<h2>${
|
|
36996
|
-
<p class="status ${
|
|
37407
|
+
<p class="eyebrow">${escapeHtml57(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
37408
|
+
<h2>${escapeHtml57(row.provider)}</h2>
|
|
37409
|
+
<p class="status ${escapeHtml57(row.status)}">${escapeHtml57(row.status.toUpperCase())}</p>
|
|
36997
37410
|
</div>
|
|
36998
37411
|
<ul>${checks}</ul>
|
|
36999
37412
|
</article>`;
|
|
37000
37413
|
}).join("");
|
|
37001
|
-
const snippet =
|
|
37414
|
+
const snippet = escapeHtml57(`const providerContracts = () =>
|
|
37002
37415
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
37003
37416
|
env: process.env,
|
|
37004
37417
|
providers: {
|
|
@@ -37019,7 +37432,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
37019
37432
|
providerContractMatrix: () =>
|
|
37020
37433
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
37021
37434
|
});`);
|
|
37022
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
37435
|
+
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:#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>${escapeHtml57(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>`;
|
|
37023
37436
|
};
|
|
37024
37437
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
37025
37438
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -37034,7 +37447,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
37034
37447
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
37035
37448
|
const path = options.path ?? "/api/provider-contracts";
|
|
37036
37449
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
37037
|
-
const routes = new
|
|
37450
|
+
const routes = new Elysia60({
|
|
37038
37451
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
37039
37452
|
});
|
|
37040
37453
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -37152,7 +37565,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
37152
37565
|
return assertion;
|
|
37153
37566
|
};
|
|
37154
37567
|
// src/opsConsoleRoutes.ts
|
|
37155
|
-
import { Elysia as
|
|
37568
|
+
import { Elysia as Elysia61 } from "elysia";
|
|
37156
37569
|
var DEFAULT_LINKS = [
|
|
37157
37570
|
{
|
|
37158
37571
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -37187,7 +37600,7 @@ var DEFAULT_LINKS = [
|
|
|
37187
37600
|
label: "Handoffs"
|
|
37188
37601
|
}
|
|
37189
37602
|
];
|
|
37190
|
-
var
|
|
37603
|
+
var escapeHtml58 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37191
37604
|
var countProviderStatuses = (providers) => {
|
|
37192
37605
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
37193
37606
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -37256,20 +37669,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
37256
37669
|
trace
|
|
37257
37670
|
};
|
|
37258
37671
|
};
|
|
37259
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
37672
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml58(input.label)}</span><strong>${escapeHtml58(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml58(input.status)}">${escapeHtml58(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml58(input.href)}">Open</a>` : ""}</article>`;
|
|
37260
37673
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
37261
37674
|
const links = report.links.map((link) => `<article class="surface">
|
|
37262
|
-
<div><h2>${
|
|
37263
|
-
<p><a href="${
|
|
37675
|
+
<div><h2>${escapeHtml58(link.label)}</h2>${link.description ? `<p>${escapeHtml58(link.description)}</p>` : ""}</div>
|
|
37676
|
+
<p><a href="${escapeHtml58(link.href)}">Open ${escapeHtml58(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml58(link.statusHref)}">Status</a>` : ""}</p>
|
|
37264
37677
|
</article>`).join("");
|
|
37265
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
37266
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
37678
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml58(session.sessionId)}</td><td>${escapeHtml58(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml58(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
37679
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml58(event.kind)}</td><td>${escapeHtml58(event.provider ?? "unknown")}</td><td>${escapeHtml58(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml58(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
37267
37680
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
37268
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
37681
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml58(title)}</title><style>body{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>${escapeHtml58(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 ${escapeHtml58(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>`;
|
|
37269
37682
|
};
|
|
37270
37683
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
37271
37684
|
const path = options.path ?? "/ops-console";
|
|
37272
|
-
const routes = new
|
|
37685
|
+
const routes = new Elysia61({
|
|
37273
37686
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
37274
37687
|
});
|
|
37275
37688
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -37286,7 +37699,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
37286
37699
|
return routes;
|
|
37287
37700
|
};
|
|
37288
37701
|
// src/incidentBundle.ts
|
|
37289
|
-
import { Elysia as
|
|
37702
|
+
import { Elysia as Elysia62 } from "elysia";
|
|
37290
37703
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
37291
37704
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
37292
37705
|
return false;
|
|
@@ -37487,7 +37900,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
37487
37900
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
37488
37901
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
37489
37902
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
37490
|
-
const routes = new
|
|
37903
|
+
const routes = new Elysia62({
|
|
37491
37904
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
37492
37905
|
});
|
|
37493
37906
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -37688,19 +38101,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
37688
38101
|
};
|
|
37689
38102
|
};
|
|
37690
38103
|
// src/opsStatusRoutes.ts
|
|
37691
|
-
import { Elysia as
|
|
37692
|
-
var
|
|
38104
|
+
import { Elysia as Elysia63 } from "elysia";
|
|
38105
|
+
var escapeHtml59 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37693
38106
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
37694
38107
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
37695
38108
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
37696
38109
|
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;
|
|
37697
|
-
return `<article class="surface ${
|
|
38110
|
+
return `<article class="surface ${escapeHtml59(surface.status)}"><span>${escapeHtml59(surface.status.toUpperCase())}</span><h2>${escapeHtml59(key)}</h2><strong>${escapeHtml59(value)}</strong></article>`;
|
|
37698
38111
|
}).join("");
|
|
37699
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38112
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml59(title)}</title><style>body{background:#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>${escapeHtml59(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml59(report.status)}">Overall: ${escapeHtml59(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>`;
|
|
37700
38113
|
};
|
|
37701
38114
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
37702
38115
|
const path = options.path ?? "/api/voice/ops-status";
|
|
37703
|
-
const routes = new
|
|
38116
|
+
const routes = new Elysia63({
|
|
37704
38117
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
37705
38118
|
});
|
|
37706
38119
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -38133,8 +38546,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
38133
38546
|
};
|
|
38134
38547
|
};
|
|
38135
38548
|
// src/traceDeliveryRoutes.ts
|
|
38136
|
-
import { Elysia as
|
|
38137
|
-
var
|
|
38549
|
+
import { Elysia as Elysia64 } from "elysia";
|
|
38550
|
+
var escapeHtml60 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
38138
38551
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
38139
38552
|
var getNumber12 = (value) => {
|
|
38140
38553
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -38215,14 +38628,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
38215
38628
|
if (entries.length === 0) {
|
|
38216
38629
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
38217
38630
|
}
|
|
38218
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
38631
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml60(sinkId)}</strong>: ${escapeHtml60(result.status)}${result.deliveredTo ? ` to ${escapeHtml60(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml60(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
38219
38632
|
};
|
|
38220
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
38633
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml60(event.type)} <small>${escapeHtml60(event.id)}</small>${event.sessionId ? ` session=${escapeHtml60(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
38221
38634
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
38222
38635
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
38223
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
38224
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
38225
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
38636
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml60(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
38637
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml60(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml60(delivery.deliveryStatus)}</span><h2>${escapeHtml60(delivery.id)}</h2><p>${escapeHtml60(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml60(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml60(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
38638
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml60(title)}</title><style>body{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>${escapeHtml60(title)}</h1><p>Checked ${escapeHtml60(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>`;
|
|
38226
38639
|
};
|
|
38227
38640
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
38228
38641
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -38242,7 +38655,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
38242
38655
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
38243
38656
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
38244
38657
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
38245
|
-
const routes = new
|
|
38658
|
+
const routes = new Elysia64({
|
|
38246
38659
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
38247
38660
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
38248
38661
|
if (htmlPath !== false) {
|
|
@@ -38339,7 +38752,7 @@ var createVoiceMemoryStore = () => {
|
|
|
38339
38752
|
return { get, getOrCreate, list, remove, set };
|
|
38340
38753
|
};
|
|
38341
38754
|
// src/opsWebhook.ts
|
|
38342
|
-
import { Elysia as
|
|
38755
|
+
import { Elysia as Elysia65 } from "elysia";
|
|
38343
38756
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
38344
38757
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
38345
38758
|
const encoder2 = new TextEncoder;
|
|
@@ -38469,7 +38882,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
38469
38882
|
};
|
|
38470
38883
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
38471
38884
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
38472
|
-
return new
|
|
38885
|
+
return new Elysia65().post(path, async ({ body, request, set }) => {
|
|
38473
38886
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
38474
38887
|
if (options.signingSecret) {
|
|
38475
38888
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -38924,7 +39337,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
38924
39337
|
};
|
|
38925
39338
|
};
|
|
38926
39339
|
// src/postCallAnalysis.ts
|
|
38927
|
-
import { Elysia as
|
|
39340
|
+
import { Elysia as Elysia66 } from "elysia";
|
|
38928
39341
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
38929
39342
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
38930
39343
|
var getPathValue3 = (source, path) => {
|
|
@@ -39103,7 +39516,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
39103
39516
|
};
|
|
39104
39517
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
39105
39518
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
39106
|
-
const routes = new
|
|
39519
|
+
const routes = new Elysia66({
|
|
39107
39520
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
39108
39521
|
});
|
|
39109
39522
|
routes.get(path, async ({ query }) => {
|
|
@@ -39128,7 +39541,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
39128
39541
|
return routes;
|
|
39129
39542
|
};
|
|
39130
39543
|
// src/guardrails.ts
|
|
39131
|
-
import { Elysia as
|
|
39544
|
+
import { Elysia as Elysia67 } from "elysia";
|
|
39132
39545
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
39133
39546
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
39134
39547
|
var matchesRule = async (rule, input) => {
|
|
@@ -39430,7 +39843,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
39430
39843
|
};
|
|
39431
39844
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
39432
39845
|
const path = options.path ?? "/api/voice/guardrails";
|
|
39433
|
-
const routes = new
|
|
39846
|
+
const routes = new Elysia67({
|
|
39434
39847
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
39435
39848
|
});
|
|
39436
39849
|
routes.all(path, async ({ request }) => {
|
|
@@ -40212,7 +40625,7 @@ var shapeTelephonyAssistantText = (text, options = {}) => {
|
|
|
40212
40625
|
return ensureTerminalPunctuation(normalizeWhitespace(limitedChars));
|
|
40213
40626
|
};
|
|
40214
40627
|
// src/proofPack.ts
|
|
40215
|
-
import { Elysia as
|
|
40628
|
+
import { Elysia as Elysia68 } from "elysia";
|
|
40216
40629
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
40217
40630
|
import { dirname as dirname3, join as join4 } from "path";
|
|
40218
40631
|
var toGeneratedAt = (value) => value === undefined ? new Date().toISOString() : typeof value === "number" ? new Date(value).toISOString() : value;
|
|
@@ -40779,7 +41192,7 @@ var createVoiceProofPackArtifacts = (input) => [
|
|
|
40779
41192
|
var createVoiceProofPackRoutes = (options) => {
|
|
40780
41193
|
const jsonPath = options.jsonPath ?? "/api/voice/proof-pack";
|
|
40781
41194
|
const markdownPath = options.markdownPath ?? "/voice/proof-pack.md";
|
|
40782
|
-
const app = new
|
|
41195
|
+
const app = new Elysia68({ name: options.name ?? "voice-proof-pack" });
|
|
40783
41196
|
if (jsonPath !== false) {
|
|
40784
41197
|
app.get(jsonPath, async () => new Response(JSON.stringify(await resolveProofPack(options.source), null, 2), {
|
|
40785
41198
|
headers: {
|
|
@@ -40959,6 +41372,8 @@ export {
|
|
|
40959
41372
|
renderVoiceMediaPipelineHTML,
|
|
40960
41373
|
renderVoiceLiveLatencyHTML,
|
|
40961
41374
|
renderVoiceLatencySLOMarkdown,
|
|
41375
|
+
renderVoiceIncidentTimelineMarkdown,
|
|
41376
|
+
renderVoiceIncidentTimelineHTML,
|
|
40962
41377
|
renderVoiceHandoffHealthHTML,
|
|
40963
41378
|
renderVoiceGuardrailMarkdown,
|
|
40964
41379
|
renderVoiceFailureReplayMarkdown,
|
|
@@ -41291,6 +41706,7 @@ export {
|
|
|
41291
41706
|
createVoiceIntegrationSinkWorker,
|
|
41292
41707
|
createVoiceIntegrationHTTPSink,
|
|
41293
41708
|
createVoiceIntegrationEvent,
|
|
41709
|
+
createVoiceIncidentTimelineRoutes,
|
|
41294
41710
|
createVoiceIncidentBundleRoutes,
|
|
41295
41711
|
createVoiceInMemoryRealCallProfileRecoveryJobStore,
|
|
41296
41712
|
createVoiceHubSpotTaskUpdateSink,
|
|
@@ -41458,6 +41874,7 @@ export {
|
|
|
41458
41874
|
buildVoiceMediaPipelineReport,
|
|
41459
41875
|
buildVoiceLiveOpsControlState,
|
|
41460
41876
|
buildVoiceLatencySLOGate,
|
|
41877
|
+
buildVoiceIncidentTimelineReport,
|
|
41461
41878
|
buildVoiceIncidentBundle,
|
|
41462
41879
|
buildVoiceIOProviderRouterTraceEvent,
|
|
41463
41880
|
buildVoiceGuardrailReport,
|