@absolutejs/voice 0.0.22-beta.166 → 0.0.22-beta.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +94 -33
- package/dist/providerStackRecommendations.d.ts +46 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export { assertVoiceProviderRoutingContract, runVoiceProviderRoutingContract } f
|
|
|
46
46
|
export { createVoicePhoneAgentProductionSmokeHTMLHandler, createVoicePhoneAgentProductionSmokeJSONHandler, createVoicePhoneAgentProductionSmokeRoutes, renderVoicePhoneAgentProductionSmokeHTML, runVoicePhoneAgentProductionSmokeContract } from './phoneAgentProductionSmoke';
|
|
47
47
|
export { buildVoiceProductionReadinessGate, buildVoiceProductionReadinessReport, createVoiceProductionReadinessRoutes, renderVoiceProductionReadinessHTML, summarizeVoiceProductionReadinessGate } from './productionReadiness';
|
|
48
48
|
export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './readinessProfiles';
|
|
49
|
-
export { buildVoiceProviderContractMatrix, evaluateVoiceProviderStackGaps, recommendVoiceProviderStack } from './providerStackRecommendations';
|
|
49
|
+
export { buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
|
|
50
50
|
export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
|
|
51
51
|
export { summarizeVoiceOpsStatus } from './opsStatus';
|
|
52
52
|
export { createVoiceOpsStatusRoutes, renderVoiceOpsStatusHTML } from './opsStatusRoutes';
|
|
@@ -106,7 +106,7 @@ export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesO
|
|
|
106
106
|
export type { VoiceOpsStatus, VoiceOpsStatusLink, VoiceOpsStatusOptions, VoiceOpsStatusReport, VoiceOpsStatusRoutesOptions } from './opsStatus';
|
|
107
107
|
export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptions, VoiceProductionReadinessAuditRequirement, VoiceProductionReadinessAuditSummary, VoiceProductionReadinessCheck, VoiceProductionReadinessGateIssue, VoiceProductionReadinessGateOptions, VoiceProductionReadinessGateProfile, VoiceProductionReadinessGateProfileSurface, VoiceProductionReadinessGateReport, VoiceProductionReadinessOpsActionHistoryOptions, VoiceProductionReadinessOpsActionHistorySummary, VoiceProductionReadinessProfileExplanation, VoiceProductionReadinessProfileSurface, VoiceProductionReadinessProofSource, VoiceProductionReadinessReport, VoiceProductionReadinessRoutesOptions, VoiceProductionReadinessTraceDeliverySummary, VoiceProductionReadinessAuditDeliveryOptions, VoiceProductionReadinessAuditDeliverySummary, VoiceProductionReadinessTraceDeliveryOptions, VoiceProductionReadinessStatus } from './productionReadiness';
|
|
108
108
|
export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
|
|
109
|
-
export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
|
|
109
|
+
export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
|
|
110
110
|
export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
|
|
111
111
|
export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
|
|
112
112
|
export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
|
package/dist/index.js
CHANGED
|
@@ -21342,6 +21342,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
21342
21342
|
};
|
|
21343
21343
|
};
|
|
21344
21344
|
// src/providerStackRecommendations.ts
|
|
21345
|
+
import { Elysia as Elysia34 } from "elysia";
|
|
21346
|
+
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21345
21347
|
var profileProviderPriorities = {
|
|
21346
21348
|
"meeting-recorder": {
|
|
21347
21349
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -21489,6 +21491,61 @@ var buildVoiceProviderContractMatrix = (input) => {
|
|
|
21489
21491
|
warned
|
|
21490
21492
|
};
|
|
21491
21493
|
};
|
|
21494
|
+
var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "function" ? await matrix() : matrix;
|
|
21495
|
+
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
21496
|
+
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
21497
|
+
const rows = report.rows.map((row) => {
|
|
21498
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml36(check.status)}"><strong>${escapeHtml36(check.label)}</strong><span>${escapeHtml36(check.detail ?? check.status)}</span></li>`).join("");
|
|
21499
|
+
return `<article class="row ${escapeHtml36(row.status)}">
|
|
21500
|
+
<div>
|
|
21501
|
+
<p class="eyebrow">${escapeHtml36(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
21502
|
+
<h2>${escapeHtml36(row.provider)}</h2>
|
|
21503
|
+
<p class="status ${escapeHtml36(row.status)}">${escapeHtml36(row.status.toUpperCase())}</p>
|
|
21504
|
+
</div>
|
|
21505
|
+
<ul>${checks}</ul>
|
|
21506
|
+
</article>`;
|
|
21507
|
+
}).join("");
|
|
21508
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml36(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,.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))}.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}.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}@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>${escapeHtml36(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>${rows || '<article class="row"><p>No provider contracts configured.</p></article>'}</main></body></html>`;
|
|
21509
|
+
};
|
|
21510
|
+
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
21511
|
+
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
21512
|
+
const report = buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(options.matrix));
|
|
21513
|
+
const body = await (options.render ?? renderVoiceProviderContractMatrixHTML)(report, { title: options.title });
|
|
21514
|
+
return new Response(body, {
|
|
21515
|
+
headers: {
|
|
21516
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
21517
|
+
}
|
|
21518
|
+
});
|
|
21519
|
+
};
|
|
21520
|
+
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
21521
|
+
const path = options.path ?? "/api/provider-contracts";
|
|
21522
|
+
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
21523
|
+
const routes = new Elysia34({
|
|
21524
|
+
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
21525
|
+
});
|
|
21526
|
+
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
21527
|
+
routes.get(path, async () => {
|
|
21528
|
+
const report = await jsonHandler();
|
|
21529
|
+
return new Response(JSON.stringify(report), {
|
|
21530
|
+
headers: {
|
|
21531
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
21532
|
+
...options.headers
|
|
21533
|
+
}
|
|
21534
|
+
});
|
|
21535
|
+
});
|
|
21536
|
+
if (htmlPath !== false) {
|
|
21537
|
+
routes.get(htmlPath, async () => {
|
|
21538
|
+
const response = await createVoiceProviderContractMatrixHTMLHandler(options)();
|
|
21539
|
+
return new Response(response.body, {
|
|
21540
|
+
headers: {
|
|
21541
|
+
...Object.fromEntries(response.headers.entries()),
|
|
21542
|
+
...options.headers
|
|
21543
|
+
}
|
|
21544
|
+
});
|
|
21545
|
+
});
|
|
21546
|
+
}
|
|
21547
|
+
return routes;
|
|
21548
|
+
};
|
|
21492
21549
|
var normalizeCapability = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
21493
21550
|
var includesCapability = (capabilities, required) => {
|
|
21494
21551
|
const normalizedRequired = normalizeCapability(required);
|
|
@@ -21522,7 +21579,7 @@ var evaluateVoiceProviderStackGaps = (input) => {
|
|
|
21522
21579
|
};
|
|
21523
21580
|
};
|
|
21524
21581
|
// src/opsConsoleRoutes.ts
|
|
21525
|
-
import { Elysia as
|
|
21582
|
+
import { Elysia as Elysia35 } from "elysia";
|
|
21526
21583
|
var DEFAULT_LINKS = [
|
|
21527
21584
|
{
|
|
21528
21585
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -21557,7 +21614,7 @@ var DEFAULT_LINKS = [
|
|
|
21557
21614
|
label: "Handoffs"
|
|
21558
21615
|
}
|
|
21559
21616
|
];
|
|
21560
|
-
var
|
|
21617
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21561
21618
|
var countProviderStatuses = (providers) => {
|
|
21562
21619
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
21563
21620
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -21626,20 +21683,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
21626
21683
|
trace
|
|
21627
21684
|
};
|
|
21628
21685
|
};
|
|
21629
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
21686
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml37(input.label)}</span><strong>${escapeHtml37(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml37(input.status)}">${escapeHtml37(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml37(input.href)}">Open</a>` : ""}</article>`;
|
|
21630
21687
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
21631
21688
|
const links = report.links.map((link) => `<article class="surface">
|
|
21632
|
-
<div><h2>${
|
|
21633
|
-
<p><a href="${
|
|
21689
|
+
<div><h2>${escapeHtml37(link.label)}</h2>${link.description ? `<p>${escapeHtml37(link.description)}</p>` : ""}</div>
|
|
21690
|
+
<p><a href="${escapeHtml37(link.href)}">Open ${escapeHtml37(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml37(link.statusHref)}">Status</a>` : ""}</p>
|
|
21634
21691
|
</article>`).join("");
|
|
21635
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
21636
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
21692
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml37(session.sessionId)}</td><td>${escapeHtml37(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml37(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
21693
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml37(event.kind)}</td><td>${escapeHtml37(event.provider ?? "unknown")}</td><td>${escapeHtml37(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml37(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
21637
21694
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
21638
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21695
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml37(title)}</title><style>body{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>${escapeHtml37(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 ${escapeHtml37(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>`;
|
|
21639
21696
|
};
|
|
21640
21697
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
21641
21698
|
const path = options.path ?? "/ops-console";
|
|
21642
|
-
const routes = new
|
|
21699
|
+
const routes = new Elysia35({
|
|
21643
21700
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
21644
21701
|
});
|
|
21645
21702
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -21827,19 +21884,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
21827
21884
|
};
|
|
21828
21885
|
};
|
|
21829
21886
|
// src/opsStatusRoutes.ts
|
|
21830
|
-
import { Elysia as
|
|
21831
|
-
var
|
|
21887
|
+
import { Elysia as Elysia36 } from "elysia";
|
|
21888
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
21832
21889
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
21833
21890
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
21834
21891
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
21835
21892
|
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;
|
|
21836
|
-
return `<article class="surface ${
|
|
21893
|
+
return `<article class="surface ${escapeHtml38(surface.status)}"><span>${escapeHtml38(surface.status.toUpperCase())}</span><h2>${escapeHtml38(key)}</h2><strong>${escapeHtml38(value)}</strong></article>`;
|
|
21837
21894
|
}).join("");
|
|
21838
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
21895
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml38(title)}</title><style>body{background:#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>${escapeHtml38(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml38(report.status)}">Overall: ${escapeHtml38(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>`;
|
|
21839
21896
|
};
|
|
21840
21897
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
21841
21898
|
const path = options.path ?? "/api/voice/ops-status";
|
|
21842
|
-
const routes = new
|
|
21899
|
+
const routes = new Elysia36({
|
|
21843
21900
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
21844
21901
|
});
|
|
21845
21902
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -22272,8 +22329,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
22272
22329
|
};
|
|
22273
22330
|
};
|
|
22274
22331
|
// src/traceDeliveryRoutes.ts
|
|
22275
|
-
import { Elysia as
|
|
22276
|
-
var
|
|
22332
|
+
import { Elysia as Elysia37 } from "elysia";
|
|
22333
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
22277
22334
|
var getString12 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
22278
22335
|
var getNumber7 = (value) => {
|
|
22279
22336
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -22354,14 +22411,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
22354
22411
|
if (entries.length === 0) {
|
|
22355
22412
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
22356
22413
|
}
|
|
22357
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
22414
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml39(sinkId)}</strong>: ${escapeHtml39(result.status)}${result.deliveredTo ? ` to ${escapeHtml39(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml39(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
22358
22415
|
};
|
|
22359
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
22416
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml39(event.type)} <small>${escapeHtml39(event.id)}</small>${event.sessionId ? ` session=${escapeHtml39(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
22360
22417
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
22361
22418
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
22362
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
22363
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
22364
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22419
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml39(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
22420
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml39(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml39(delivery.deliveryStatus)}</span><h2>${escapeHtml39(delivery.id)}</h2><p>${escapeHtml39(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml39(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml39(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
22421
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml39(title)}</title><style>body{background:#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>${escapeHtml39(title)}</h1><p>Checked ${escapeHtml39(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>`;
|
|
22365
22422
|
};
|
|
22366
22423
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
22367
22424
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -22381,7 +22438,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
22381
22438
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
22382
22439
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
22383
22440
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
22384
|
-
const routes = new
|
|
22441
|
+
const routes = new Elysia37({
|
|
22385
22442
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
22386
22443
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
22387
22444
|
if (htmlPath !== false) {
|
|
@@ -22399,8 +22456,8 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
22399
22456
|
return routes;
|
|
22400
22457
|
};
|
|
22401
22458
|
// src/traceTimeline.ts
|
|
22402
|
-
import { Elysia as
|
|
22403
|
-
var
|
|
22459
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
22460
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
22404
22461
|
var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
22405
22462
|
var getNumber8 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
22406
22463
|
var firstString3 = (payload, keys) => {
|
|
@@ -22568,20 +22625,20 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
22568
22625
|
};
|
|
22569
22626
|
};
|
|
22570
22627
|
var formatMs3 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
22571
|
-
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${
|
|
22628
|
+
var renderProviderCards2 = (session) => session.providers.length === 0 ? '<p class="muted">No provider events recorded for this session.</p>' : `<div class="providers">${session.providers.map((provider) => `<article><strong>${escapeHtml40(provider.provider)}</strong><dl><div><dt>Events</dt><dd>${String(provider.eventCount)}</dd></div><div><dt>Avg</dt><dd>${formatMs3(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs3(provider.maxElapsedMs)}</dd></div><div><dt>Errors</dt><dd>${String(provider.errorCount)}</dd></div><div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div><div><dt>Timeouts</dt><dd>${String(provider.timeoutCount)}</dd></div></dl></article>`).join("")}</div>`;
|
|
22572
22629
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
22573
|
-
const events = session.events.map((event) => `<tr class="${
|
|
22574
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
22575
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22630
|
+
const events = session.events.map((event) => `<tr class="${escapeHtml40(event.status ?? "")}"><td>+${String(event.offsetMs)}ms</td><td>${escapeHtml40(event.type)}</td><td>${escapeHtml40(event.label)}</td><td>${escapeHtml40(event.provider ?? "")}</td><td>${escapeHtml40(event.status ?? "")}</td><td>${formatMs3(event.elapsedMs)}</td></tr>`).join("");
|
|
22631
|
+
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${escapeHtml40(issue.severity)}">${escapeHtml40(issue.code)}: ${escapeHtml40(issue.message)}</li>`).join("") : "<li>none</li>";
|
|
22632
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(options.title ?? "Voice Trace Timeline")}</title><style>${timelineCSS}</style></head><body><main><a href="/traces">Back to traces</a><header><p class="eyebrow">Call timeline</p><h1>${escapeHtml40(session.sessionId)}</h1><p class="status ${escapeHtml40(session.status)}">${escapeHtml40(session.status)}</p></header><section class="metrics"><article><span>Events</span><strong>${String(session.summary.eventCount)}</strong></article><article><span>Turns</span><strong>${String(session.summary.turnCount)}</strong></article><article><span>Errors</span><strong>${String(session.summary.errorCount)}</strong></article><article><span>Duration</span><strong>${formatMs3(session.summary.callDurationMs)}</strong></article></section><section><h2>Providers</h2>${renderProviderCards2(session)}</section><section><h2>Issues</h2><ul>${issues}</ul></section><section><h2>Timeline</h2><table><thead><tr><th>Offset</th><th>Type</th><th>Event</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${events}</tbody></table></section></main></body></html>`;
|
|
22576
22633
|
};
|
|
22577
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
22634
|
+
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${escapeHtml40(session.status)}"><td><a href="/traces/${encodeURIComponent(session.sessionId)}">${escapeHtml40(session.sessionId)}</a></td><td>${escapeHtml40(session.status)}</td><td>${String(session.summary.eventCount)}</td><td>${String(session.summary.turnCount)}</td><td>${String(session.summary.errorCount)}</td><td>${formatMs3(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml40(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
22578
22635
|
var timelineCSS = "body{background:#0f1318;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}a{color:#fbbf24}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.5rem);line-height:.92;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.metrics,.providers{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:20px 0}.metrics article,.providers article{background:#181f27;border:1px solid #2b3642;border-radius:20px;padding:16px}.metrics span,dt,.muted{color:#a8b0b8}.metrics strong{display:block;font-size:2rem}dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0 0}dd{font-weight:800;margin:4px 0 0}table{background:#181f27;border-collapse:collapse;border-radius:18px;overflow:hidden;width:100%}td,th{border-bottom:1px solid #2b3642;padding:12px;text-align:left}section{margin-top:28px}@media(max-width:760px){main{padding:20px}table{font-size:.9rem}}";
|
|
22579
|
-
var renderVoiceTraceTimelineHTML = (report, options = {}) => `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
22636
|
+
var renderVoiceTraceTimelineHTML = (report, options = {}) => `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml40(options.title ?? "Voice Trace Timelines")}</title><style>${timelineCSS}</style></head><body><main><header><p class="eyebrow">Self-hosted voice debugging</p><h1>${escapeHtml40(options.title ?? "Voice Trace Timelines")}</h1><p class="muted">Per-call event timelines with provider latency, fallback, timeout, handoff, and error context.</p></header><section class="metrics"><article><span>Sessions</span><strong>${String(report.total)}</strong></article><article><span>Failed</span><strong>${String(report.failed)}</strong></article><article><span>Warnings</span><strong>${String(report.warnings)}</strong></article></section><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Duration</th><th>Providers</th></tr></thead><tbody>${renderSessionRows(report)}</tbody></table></main></body></html>`;
|
|
22580
22637
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
22581
22638
|
const path = options.path ?? "/api/voice-traces";
|
|
22582
22639
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
22583
22640
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
22584
|
-
const routes = new
|
|
22641
|
+
const routes = new Elysia38({
|
|
22585
22642
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
22586
22643
|
});
|
|
22587
22644
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -23234,7 +23291,7 @@ var createVoiceMemoryStore = () => {
|
|
|
23234
23291
|
return { get, getOrCreate, list, remove, set };
|
|
23235
23292
|
};
|
|
23236
23293
|
// src/opsWebhook.ts
|
|
23237
|
-
import { Elysia as
|
|
23294
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
23238
23295
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
23239
23296
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
23240
23297
|
const encoder = new TextEncoder;
|
|
@@ -23364,7 +23421,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
23364
23421
|
};
|
|
23365
23422
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
23366
23423
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
23367
|
-
return new
|
|
23424
|
+
return new Elysia39().post(path, async ({ body, request, set }) => {
|
|
23368
23425
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
23369
23426
|
if (options.signingSecret) {
|
|
23370
23427
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -24298,6 +24355,7 @@ export {
|
|
|
24298
24355
|
renderVoiceReconnectContractHTML,
|
|
24299
24356
|
renderVoiceQualityHTML,
|
|
24300
24357
|
renderVoiceProviderHealthHTML,
|
|
24358
|
+
renderVoiceProviderContractMatrixHTML,
|
|
24301
24359
|
renderVoiceProviderCapabilityHTML,
|
|
24302
24360
|
renderVoiceProductionReadinessHTML,
|
|
24303
24361
|
renderVoicePhoneAgentProductionSmokeHTML,
|
|
@@ -24454,6 +24512,9 @@ export {
|
|
|
24454
24512
|
createVoiceProviderHealthRoutes,
|
|
24455
24513
|
createVoiceProviderHealthJSONHandler,
|
|
24456
24514
|
createVoiceProviderHealthHTMLHandler,
|
|
24515
|
+
createVoiceProviderContractMatrixRoutes,
|
|
24516
|
+
createVoiceProviderContractMatrixJSONHandler,
|
|
24517
|
+
createVoiceProviderContractMatrixHTMLHandler,
|
|
24457
24518
|
createVoiceProviderCapabilityRoutes,
|
|
24458
24519
|
createVoiceProviderCapabilityJSONHandler,
|
|
24459
24520
|
createVoiceProviderCapabilityHTMLHandler,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
1
2
|
import type { VoiceReadinessProfileName } from './readinessProfiles';
|
|
2
3
|
export type VoiceProviderStackKind = 'llm' | 'stt' | 'tts';
|
|
3
4
|
export type VoiceProviderStackInput<TProvider extends string = string> = {
|
|
@@ -58,6 +59,18 @@ export type VoiceProviderContractDefinition<TProvider extends string = string> =
|
|
|
58
59
|
export type VoiceProviderContractMatrixInput<TProvider extends string = string> = {
|
|
59
60
|
contracts: readonly VoiceProviderContractDefinition<TProvider>[];
|
|
60
61
|
};
|
|
62
|
+
export type VoiceProviderContractMatrixHandlerOptions<TProvider extends string = string> = VoiceProviderContractMatrixInput<TProvider> | (() => Promise<VoiceProviderContractMatrixInput<TProvider>> | VoiceProviderContractMatrixInput<TProvider>);
|
|
63
|
+
export type VoiceProviderContractMatrixHTMLHandlerOptions<TProvider extends string = string> = {
|
|
64
|
+
matrix: VoiceProviderContractMatrixHandlerOptions<TProvider>;
|
|
65
|
+
render?: (report: VoiceProviderContractMatrixReport<TProvider>) => string | Promise<string>;
|
|
66
|
+
title?: string;
|
|
67
|
+
};
|
|
68
|
+
export type VoiceProviderContractMatrixRoutesOptions<TProvider extends string = string> = VoiceProviderContractMatrixHTMLHandlerOptions<TProvider> & {
|
|
69
|
+
headers?: HeadersInit;
|
|
70
|
+
htmlPath?: false | string;
|
|
71
|
+
name?: string;
|
|
72
|
+
path?: string;
|
|
73
|
+
};
|
|
61
74
|
export type VoiceProviderContractMatrixRow<TProvider extends string = string> = {
|
|
62
75
|
checks: VoiceProviderContractCheck[];
|
|
63
76
|
configured: boolean;
|
|
@@ -76,4 +89,37 @@ export type VoiceProviderContractMatrixReport<TProvider extends string = string>
|
|
|
76
89
|
};
|
|
77
90
|
export declare const recommendVoiceProviderStack: <TProvider extends string = string>(input: VoiceProviderStackInput<TProvider>) => VoiceProviderStackRecommendation<TProvider>;
|
|
78
91
|
export declare const buildVoiceProviderContractMatrix: <TProvider extends string = string>(input: VoiceProviderContractMatrixInput<TProvider>) => VoiceProviderContractMatrixReport<TProvider>;
|
|
92
|
+
export declare const renderVoiceProviderContractMatrixHTML: <TProvider extends string = string>(report: VoiceProviderContractMatrixReport<TProvider>, options?: {
|
|
93
|
+
title?: string;
|
|
94
|
+
}) => string;
|
|
95
|
+
export declare const createVoiceProviderContractMatrixJSONHandler: <TProvider extends string = string>(matrix: VoiceProviderContractMatrixHandlerOptions<TProvider>) => () => Promise<VoiceProviderContractMatrixReport<TProvider>>;
|
|
96
|
+
export declare const createVoiceProviderContractMatrixHTMLHandler: <TProvider extends string = string>(options: VoiceProviderContractMatrixHTMLHandlerOptions<TProvider>) => () => Promise<Response>;
|
|
97
|
+
export declare const createVoiceProviderContractMatrixRoutes: <TProvider extends string = string>(options: VoiceProviderContractMatrixRoutesOptions<TProvider>) => Elysia<"", {
|
|
98
|
+
decorator: {};
|
|
99
|
+
store: {};
|
|
100
|
+
derive: {};
|
|
101
|
+
resolve: {};
|
|
102
|
+
}, {
|
|
103
|
+
typebox: {};
|
|
104
|
+
error: {};
|
|
105
|
+
}, {
|
|
106
|
+
schema: {};
|
|
107
|
+
standaloneSchema: {};
|
|
108
|
+
macro: {};
|
|
109
|
+
macroFn: {};
|
|
110
|
+
parser: {};
|
|
111
|
+
response: {};
|
|
112
|
+
}, {}, {
|
|
113
|
+
derive: {};
|
|
114
|
+
resolve: {};
|
|
115
|
+
schema: {};
|
|
116
|
+
standaloneSchema: {};
|
|
117
|
+
response: {};
|
|
118
|
+
}, {
|
|
119
|
+
derive: {};
|
|
120
|
+
resolve: {};
|
|
121
|
+
schema: {};
|
|
122
|
+
standaloneSchema: {};
|
|
123
|
+
response: {};
|
|
124
|
+
}>;
|
|
79
125
|
export declare const evaluateVoiceProviderStackGaps: <TProvider extends string = string>(input: VoiceProviderStackCapabilityGapInput<TProvider>) => VoiceProviderStackCapabilityGapReport<TProvider>;
|