@absolutejs/voice 0.0.22-beta.88 → 0.0.22-beta.89
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 +1 -1
- package/dist/index.js +68 -9
- package/dist/productionReadiness.d.ts +8 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export type { VoiceTurnQualityHTMLHandlerOptions, VoiceTurnQualityItem, VoiceTur
|
|
|
62
62
|
export type { VoiceOutcomeContractDefinition, VoiceOutcomeContractHTMLHandlerOptions, VoiceOutcomeContractIssue, VoiceOutcomeContractOptions, VoiceOutcomeContractReport, VoiceOutcomeContractRoutesOptions, VoiceOutcomeContractStatus, VoiceOutcomeContractSuiteReport } from './outcomeContract';
|
|
63
63
|
export type { VoiceTelephonyOutcomeAction, VoiceTelephonyOutcomeDecision, VoiceTelephonyOutcomePolicy, VoiceTelephonyOutcomeProviderEvent, VoiceTelephonyOutcomeRouteResult, VoiceTelephonyOutcomeStatusDecision, VoiceTelephonyWebhookDecision, VoiceTelephonyWebhookHandlerOptions, VoiceTelephonyWebhookIdempotencyStore, VoiceTelephonyWebhookParseInput, VoiceTelephonyWebhookProvider, VoiceTelephonyWebhookRoutesOptions, VoiceTelephonyWebhookVerificationResult, StoredVoiceTelephonyWebhookDecision } from './telephonyOutcome';
|
|
64
64
|
export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesOptions } from './opsConsoleRoutes';
|
|
65
|
-
export type { VoiceProductionReadinessCheck, VoiceProductionReadinessReport, VoiceProductionReadinessRoutesOptions, VoiceProductionReadinessStatus } from './productionReadiness';
|
|
65
|
+
export type { VoiceProductionReadinessAction, VoiceProductionReadinessCheck, VoiceProductionReadinessReport, VoiceProductionReadinessRoutesOptions, VoiceProductionReadinessStatus } from './productionReadiness';
|
|
66
66
|
export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
|
|
67
67
|
export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
|
|
68
68
|
export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
|
package/dist/index.js
CHANGED
|
@@ -9641,35 +9641,82 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9641
9641
|
href: options.links?.quality ?? "/quality",
|
|
9642
9642
|
label: "Quality gates",
|
|
9643
9643
|
status: quality.status,
|
|
9644
|
-
value: quality.status
|
|
9644
|
+
value: quality.status,
|
|
9645
|
+
actions: quality.status === "pass" ? [] : [
|
|
9646
|
+
{
|
|
9647
|
+
description: "Open the quality report to inspect failing gates.",
|
|
9648
|
+
href: options.links?.quality ?? "/quality",
|
|
9649
|
+
label: "Inspect quality gates"
|
|
9650
|
+
}
|
|
9651
|
+
]
|
|
9645
9652
|
},
|
|
9646
9653
|
{
|
|
9647
9654
|
detail: degradedProviders === 0 ? "No configured providers are currently degraded." : `${degradedProviders} provider(s) are degraded, suppressed, or rate-limited.`,
|
|
9648
9655
|
href: options.links?.resilience ?? "/resilience",
|
|
9649
9656
|
label: "Provider health",
|
|
9650
9657
|
status: degradedProviders > 0 ? "fail" : "pass",
|
|
9651
|
-
value: degradedProviders
|
|
9658
|
+
value: degradedProviders,
|
|
9659
|
+
actions: degradedProviders > 0 ? [
|
|
9660
|
+
{
|
|
9661
|
+
description: "Open provider health, fallback state, and recovery controls.",
|
|
9662
|
+
href: options.links?.resilience ?? "/resilience",
|
|
9663
|
+
label: "Open provider recovery"
|
|
9664
|
+
}
|
|
9665
|
+
] : []
|
|
9652
9666
|
},
|
|
9653
9667
|
{
|
|
9654
9668
|
detail: failedSessions === 0 ? sessions.length > 0 ? "Recent sessions have no recorded provider/session failures." : "No sessions have been recorded yet; run a smoke or live session for proof." : `${failedSessions} recent session(s) have failures.`,
|
|
9655
9669
|
href: options.links?.sessions ?? "/sessions",
|
|
9656
9670
|
label: "Session health",
|
|
9657
9671
|
status: failedSessions > 0 ? "fail" : sessions.length === 0 ? "warn" : "pass",
|
|
9658
|
-
value: `${sessions.length - failedSessions}/${sessions.length}
|
|
9672
|
+
value: `${sessions.length - failedSessions}/${sessions.length}`,
|
|
9673
|
+
actions: failedSessions > 0 ? [
|
|
9674
|
+
{
|
|
9675
|
+
description: "Open failed sessions and replay traces.",
|
|
9676
|
+
href: `${options.links?.sessions ?? "/sessions"}?status=failed`,
|
|
9677
|
+
label: "Replay failed sessions"
|
|
9678
|
+
}
|
|
9679
|
+
] : sessions.length === 0 ? [
|
|
9680
|
+
{
|
|
9681
|
+
description: "Open sessions after running a smoke or live call.",
|
|
9682
|
+
href: options.links?.sessions ?? "/sessions",
|
|
9683
|
+
label: "Open sessions"
|
|
9684
|
+
}
|
|
9685
|
+
] : []
|
|
9659
9686
|
},
|
|
9660
9687
|
{
|
|
9661
9688
|
detail: handoffs.failed === 0 ? "No failed handoff deliveries are recorded." : `${handoffs.failed} handoff delivery failure(s) are recorded.`,
|
|
9662
9689
|
href: options.links?.handoffs ?? "/handoffs",
|
|
9663
9690
|
label: "Handoff delivery",
|
|
9664
9691
|
status: handoffs.failed > 0 ? "fail" : "pass",
|
|
9665
|
-
value: `${handoffs.total - handoffs.failed}/${handoffs.total}
|
|
9692
|
+
value: `${handoffs.total - handoffs.failed}/${handoffs.total}`,
|
|
9693
|
+
actions: handoffs.failed > 0 ? [
|
|
9694
|
+
{
|
|
9695
|
+
description: "Retry queued or failed handoff deliveries.",
|
|
9696
|
+
href: options.links?.handoffRetry ?? "/api/voice-handoffs/retry",
|
|
9697
|
+
label: "Retry handoff deliveries",
|
|
9698
|
+
method: "POST"
|
|
9699
|
+
},
|
|
9700
|
+
{
|
|
9701
|
+
description: "Inspect handoff queue and delivery errors.",
|
|
9702
|
+
href: options.links?.handoffs ?? "/handoffs",
|
|
9703
|
+
label: "Open handoff queue"
|
|
9704
|
+
}
|
|
9705
|
+
] : []
|
|
9666
9706
|
},
|
|
9667
9707
|
{
|
|
9668
9708
|
detail: routingEvents.length > 0 ? `${routingSessions.length} session(s) have provider routing evidence.` : "No provider routing traces are recorded yet.",
|
|
9669
9709
|
href: options.links?.resilience ?? "/resilience",
|
|
9670
9710
|
label: "Routing evidence",
|
|
9671
9711
|
status: routingEvents.length > 0 ? "pass" : "warn",
|
|
9672
|
-
value: routingEvents.length
|
|
9712
|
+
value: routingEvents.length,
|
|
9713
|
+
actions: routingEvents.length > 0 ? [] : [
|
|
9714
|
+
{
|
|
9715
|
+
description: "Open provider routing and run a smoke or simulation to create evidence.",
|
|
9716
|
+
href: options.links?.resilience ?? "/resilience",
|
|
9717
|
+
label: "Open routing evidence"
|
|
9718
|
+
}
|
|
9719
|
+
]
|
|
9673
9720
|
}
|
|
9674
9721
|
];
|
|
9675
9722
|
const carrierSummary = carriers ? {
|
|
@@ -9685,7 +9732,14 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9685
9732
|
href: options.links?.carriers ?? "/carriers",
|
|
9686
9733
|
label: "Carrier readiness",
|
|
9687
9734
|
status: carrierSummary.status,
|
|
9688
|
-
value: `${carrierSummary.ready}/${carrierSummary.providers}
|
|
9735
|
+
value: `${carrierSummary.ready}/${carrierSummary.providers}`,
|
|
9736
|
+
actions: carrierSummary.status === "pass" ? [] : [
|
|
9737
|
+
{
|
|
9738
|
+
description: "Open the carrier matrix for exact missing env, signing, and URL issues.",
|
|
9739
|
+
href: options.links?.carriers ?? "/carriers",
|
|
9740
|
+
label: "Open carrier matrix"
|
|
9741
|
+
}
|
|
9742
|
+
]
|
|
9689
9743
|
});
|
|
9690
9744
|
}
|
|
9691
9745
|
return {
|
|
@@ -9694,6 +9748,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9694
9748
|
links: {
|
|
9695
9749
|
carriers: "/carriers",
|
|
9696
9750
|
handoffs: "/handoffs",
|
|
9751
|
+
handoffRetry: "/api/voice-handoffs/retry",
|
|
9697
9752
|
quality: "/quality",
|
|
9698
9753
|
resilience: "/resilience",
|
|
9699
9754
|
sessions: "/sessions",
|
|
@@ -9726,16 +9781,20 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
9726
9781
|
};
|
|
9727
9782
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
9728
9783
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
9729
|
-
const checks = report.checks.map((check) =>
|
|
9784
|
+
const checks = report.checks.map((check, index) => {
|
|
9785
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml15(action.href)}">${escapeHtml15(action.label)}</button>` : `<a href="${escapeHtml15(action.href)}">${escapeHtml15(action.label)}</a>`).join("");
|
|
9786
|
+
return `<article class="check ${escapeHtml15(check.status)}">
|
|
9730
9787
|
<div>
|
|
9731
9788
|
<span>${escapeHtml15(check.status.toUpperCase())}</span>
|
|
9732
9789
|
<h2>${escapeHtml15(check.label)}</h2>
|
|
9733
9790
|
${check.detail ? `<p>${escapeHtml15(check.detail)}</p>` : ""}
|
|
9791
|
+
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
9734
9792
|
</div>
|
|
9735
9793
|
<strong>${escapeHtml15(String(check.value ?? check.status))}</strong>
|
|
9736
9794
|
${check.href ? `<a href="${escapeHtml15(check.href)}">Open surface</a>` : ""}
|
|
9737
|
-
</article
|
|
9738
|
-
|
|
9795
|
+
</article>`;
|
|
9796
|
+
}).join("");
|
|
9797
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml15(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(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.status.pass,.check.pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p{color:#b9c0c8;margin:.2rem 0 0}.check strong{font-size:1.5rem}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml15(title)}</h1><p>One deployable pass/fail report for quality gates, provider failover, session health, handoffs, routing evidence, and optional carrier readiness.</p><p class="status ${escapeHtml15(report.status)}">Overall: ${escapeHtml15(report.status.toUpperCase())}</p><p>Checked ${escapeHtml15(new Date(report.checkedAt).toLocaleString())}</p></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
|
|
9739
9798
|
};
|
|
9740
9799
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
9741
9800
|
const path = options.path ?? "/api/production-readiness";
|
|
@@ -2,7 +2,14 @@ import { Elysia } from 'elysia';
|
|
|
2
2
|
import { type VoiceTelephonyCarrierMatrixInput } from './telephony/matrix';
|
|
3
3
|
import type { VoiceTraceEventStore } from './trace';
|
|
4
4
|
export type VoiceProductionReadinessStatus = 'fail' | 'pass' | 'warn';
|
|
5
|
+
export type VoiceProductionReadinessAction = {
|
|
6
|
+
description?: string;
|
|
7
|
+
href: string;
|
|
8
|
+
label: string;
|
|
9
|
+
method?: 'GET' | 'POST';
|
|
10
|
+
};
|
|
5
11
|
export type VoiceProductionReadinessCheck = {
|
|
12
|
+
actions?: VoiceProductionReadinessAction[];
|
|
6
13
|
detail?: string;
|
|
7
14
|
href?: string;
|
|
8
15
|
label: string;
|
|
@@ -15,6 +22,7 @@ export type VoiceProductionReadinessReport = {
|
|
|
15
22
|
links: {
|
|
16
23
|
carriers?: string;
|
|
17
24
|
handoffs?: string;
|
|
25
|
+
handoffRetry?: string;
|
|
18
26
|
quality?: string;
|
|
19
27
|
resilience?: string;
|
|
20
28
|
sessions?: string;
|