@absolutejs/voice 0.0.22-beta.175 → 0.0.22-beta.177
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +75 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17529,6 +17529,38 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
17529
17529
|
return `<tr><td>${escapeHtml32(carrier.name ?? carrier.provider)}</td><td>${escapeHtml32(carrier.provider)}</td><td><code>${escapeHtml32(carrier.setupPath || "disabled")}</code></td><td><code>${escapeHtml32(carrier.smokePath || "disabled")}</code></td><td>${entry ? `<span class="${escapeHtml32(entry.status)}">${escapeHtml32(entry.status.toUpperCase())}</span>` : "unknown"}</td><td>${primaryUrl ? `<code>${escapeHtml32(primaryUrl)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.webhook ? `<code>${escapeHtml32(urls.webhook)}</code>` : '<span class="muted">missing</span>'}</td><td>${urls?.stream ? `<code>${escapeHtml32(urls.stream)}</code>` : '<span class="muted">missing</span>'}</td></tr>`;
|
|
17530
17530
|
}).join("");
|
|
17531
17531
|
const stageList = report.lifecycleStages.map((stage) => `<li><code>${escapeHtml32(stage)}</code></li>`).join("");
|
|
17532
|
+
const snippet = escapeHtml32(`const phoneAgent = createVoicePhoneAgent({
|
|
17533
|
+
carriers: [
|
|
17534
|
+
{
|
|
17535
|
+
provider: 'twilio',
|
|
17536
|
+
options: {
|
|
17537
|
+
twiml: { streamUrl: 'wss://your-app.example/api/voice/twilio/stream' },
|
|
17538
|
+
webhook: { validateSignature: true }
|
|
17539
|
+
}
|
|
17540
|
+
}
|
|
17541
|
+
],
|
|
17542
|
+
productionSmoke: {
|
|
17543
|
+
store: traceStore,
|
|
17544
|
+
required: [
|
|
17545
|
+
'carrier-contract',
|
|
17546
|
+
'media-started',
|
|
17547
|
+
'transcript',
|
|
17548
|
+
'assistant-response',
|
|
17549
|
+
'lifecycle-outcome',
|
|
17550
|
+
'no-session-error'
|
|
17551
|
+
]
|
|
17552
|
+
}
|
|
17553
|
+
});
|
|
17554
|
+
|
|
17555
|
+
app.use(phoneAgent.routes);
|
|
17556
|
+
|
|
17557
|
+
app.use(
|
|
17558
|
+
createVoiceProductionReadinessRoutes({
|
|
17559
|
+
carriers: loadCarrierMatrixInputs,
|
|
17560
|
+
phoneAgentSmokes: loadPhoneAgentSmokeReports,
|
|
17561
|
+
store: traceStore
|
|
17562
|
+
})
|
|
17563
|
+
);`);
|
|
17532
17564
|
const checklist = report.carriers.map((carrier) => {
|
|
17533
17565
|
const entry = report.matrix?.entries.find((candidate) => candidate.provider === carrier.provider && (candidate.name === carrier.name || candidate.name === (carrier.name ?? carrier.provider)));
|
|
17534
17566
|
const urls = entry?.setup.urls;
|
|
@@ -17537,7 +17569,7 @@ var renderVoicePhoneAgentSetupHTML = (report) => {
|
|
|
17537
17569
|
const issueList = entry?.issues.map((issue) => `<li>${escapeHtml32(issue.severity)}: ${escapeHtml32(issue.message)}</li>`).join("") ?? "";
|
|
17538
17570
|
return `<article><h3>${escapeHtml32(carrier.name ?? carrier.provider)}</h3><ol><li>Set ${escapeHtml32(answerLabel)} to <code>${escapeHtml32(answerUrl ?? "missing")}</code>.</li><li>Set status webhook to <code>${escapeHtml32(urls?.webhook ?? "missing")}</code>.</li><li>Allow media stream URL <code>${escapeHtml32(urls?.stream ?? "missing")}</code>.</li><li>Open setup: ${carrier.setupPath ? `<a href="${escapeHtml32(carrier.setupPath)}?format=html">${escapeHtml32(carrier.setupPath)}</a>` : '<span class="muted">disabled</span>'}.</li><li>Run smoke: ${carrier.smokePath ? `<a href="${escapeHtml32(carrier.smokePath)}?format=html">${escapeHtml32(carrier.smokePath)}</a>` : '<span class="muted">disabled</span>'}.</li>${report.productionSmokePath ? `<li>Certify production smoke traces: <a href="${escapeHtml32(report.productionSmokePath.replace("/api/", "/"))}?sessionId=">${escapeHtml32(report.productionSmokePath)}</a>.</li>` : ""}</ol>${issueList ? `<ul class="issues">${issueList}</ul>` : '<p class="pass">No carrier contract issues.</p>'}</article>`;
|
|
17539
17571
|
}).join("");
|
|
17540
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(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{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.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}.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>${escapeHtml32(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="${escapeHtml32(report.matrixPath)}?format=html">Open carrier matrix</a></p>` : ""}</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>`;
|
|
17572
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml32(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>${escapeHtml32(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="${escapeHtml32(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>`;
|
|
17541
17573
|
};
|
|
17542
17574
|
var createVoicePhoneAgent = (options) => {
|
|
17543
17575
|
const carrierSummaries = options.carriers.map((carrier) => ({
|
|
@@ -19921,6 +19953,39 @@ var renderVoiceResilienceHTML = (input) => {
|
|
|
19921
19953
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
19922
19954
|
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml34(kind)}: ${String(count)}</span>`).join("");
|
|
19923
19955
|
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml34(link.href)}">${escapeHtml34(link.label)}</a>`).join(" \xB7 ") : "";
|
|
19956
|
+
const snippet = escapeHtml34(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
19957
|
+
kind: 'stt',
|
|
19958
|
+
providers: ['deepgram', 'assemblyai'],
|
|
19959
|
+
fallback: ['deepgram', 'assemblyai'],
|
|
19960
|
+
onProviderEvent: async (event, input) => {
|
|
19961
|
+
await traceStore.append({
|
|
19962
|
+
at: event.at,
|
|
19963
|
+
payload: { ...event, providerStatus: event.status },
|
|
19964
|
+
sessionId: input.sessionId,
|
|
19965
|
+
type: 'session.error'
|
|
19966
|
+
});
|
|
19967
|
+
}
|
|
19968
|
+
});
|
|
19969
|
+
|
|
19970
|
+
app.use(
|
|
19971
|
+
createVoiceResilienceRoutes({
|
|
19972
|
+
store: traceStore,
|
|
19973
|
+
sttProviders: ['deepgram', 'assemblyai'],
|
|
19974
|
+
sttSimulation: {
|
|
19975
|
+
failureProviders: ['deepgram'],
|
|
19976
|
+
fallbackRequiredProvider: 'assemblyai',
|
|
19977
|
+
providers: [{ provider: 'deepgram' }, { provider: 'assemblyai' }],
|
|
19978
|
+
run: sttSimulator.run
|
|
19979
|
+
}
|
|
19980
|
+
})
|
|
19981
|
+
);
|
|
19982
|
+
|
|
19983
|
+
app.use(
|
|
19984
|
+
createVoiceProductionReadinessRoutes({
|
|
19985
|
+
links: { resilience: '/resilience' },
|
|
19986
|
+
store: traceStore
|
|
19987
|
+
})
|
|
19988
|
+
);`);
|
|
19924
19989
|
return `<!doctype html>
|
|
19925
19990
|
<html lang="en">
|
|
19926
19991
|
<head>
|
|
@@ -19955,6 +20020,9 @@ var renderVoiceResilienceHTML = (input) => {
|
|
|
19955
20020
|
button:disabled { cursor: not-allowed; opacity: 0.45; }
|
|
19956
20021
|
.simulate-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
|
|
19957
20022
|
.simulate-output { background: #050505; border: 1px solid #27272a; border-radius: 14px; color: #d4d4d8; overflow: auto; padding: 12px; white-space: pre-wrap; }
|
|
20023
|
+
.primitive { border-color: rgba(245, 158, 11, 0.45); }
|
|
20024
|
+
.primitive pre { background: #050505; border: 1px solid #27272a; border-radius: 14px; color: #fef3c7; overflow: auto; padding: 14px; }
|
|
20025
|
+
.primitive code { color: #fef3c7; }
|
|
19958
20026
|
a { color: #f59e0b; }
|
|
19959
20027
|
@media (max-width: 850px) { .grid, .provider-grid, .session-grid, dl { grid-template-columns: 1fr; } }
|
|
19960
20028
|
</style>
|
|
@@ -19967,6 +20035,12 @@ var renderVoiceResilienceHTML = (input) => {
|
|
|
19967
20035
|
${links ? `<p>${links}</p>` : ""}
|
|
19968
20036
|
<p>${kindCounts || '<span class="pill">No routing events yet</span>'}</p>
|
|
19969
20037
|
</section>
|
|
20038
|
+
<section class="primitive">
|
|
20039
|
+
<p class="muted">Copy into your app</p>
|
|
20040
|
+
<h2><code>createVoiceResilienceRoutes(...)</code> builds this failover proof surface</h2>
|
|
20041
|
+
<p class="muted">Mount one route group for provider health, routing traces, and failure simulation. Feed the same trace store into production readiness so unresolved provider errors fail the deploy gate while recovered fallback stays visible.</p>
|
|
20042
|
+
<pre><code>${snippet}</code></pre>
|
|
20043
|
+
</section>
|
|
19970
20044
|
<section class="grid">
|
|
19971
20045
|
<article class="card metric"><span>Total routing events</span><strong>${summary.total}</strong></article>
|
|
19972
20046
|
<article class="card metric"><span>Fallbacks</span><strong>${summary.fallbacks}</strong></article>
|