@absolutejs/voice 0.0.22-beta.291 → 0.0.22-beta.293
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/README.md +102 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +489 -166
- package/dist/modelAdapters.d.ts +37 -0
- package/dist/productionReadiness.d.ts +15 -0
- package/dist/providerOrchestration.d.ts +109 -0
- package/dist/testing/index.js +87 -12
- package/dist/vue/useVoiceReadinessFailures.d.ts +20 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21650,6 +21650,7 @@ var createStoredVoiceExternalObjectMap = (mapping) => createVoiceExternalObjectM
|
|
|
21650
21650
|
sourceType: mapping.sourceType
|
|
21651
21651
|
});
|
|
21652
21652
|
// src/modelAdapters.ts
|
|
21653
|
+
var isVoiceProviderRoutingPolicyPreset = (value) => value === "balanced" || value === "cost-cap" || value === "cost-first" || value === "latency-first" || value === "quality-first";
|
|
21653
21654
|
var resolveVoiceProviderRoutingPolicyPreset = (preset, options = {}) => {
|
|
21654
21655
|
switch (preset) {
|
|
21655
21656
|
case "balanced":
|
|
@@ -21691,6 +21692,75 @@ var resolveVoiceProviderRoutingPolicyPreset = (preset, options = {}) => {
|
|
|
21691
21692
|
};
|
|
21692
21693
|
}
|
|
21693
21694
|
};
|
|
21695
|
+
var resolveVoiceProviderRoutingPolicy = (policy) => {
|
|
21696
|
+
if (!policy) {
|
|
21697
|
+
return;
|
|
21698
|
+
}
|
|
21699
|
+
if (typeof policy === "string") {
|
|
21700
|
+
return isVoiceProviderRoutingPolicyPreset(policy) ? resolveVoiceProviderRoutingPolicyPreset(policy) : {
|
|
21701
|
+
strategy: policy
|
|
21702
|
+
};
|
|
21703
|
+
}
|
|
21704
|
+
return policy;
|
|
21705
|
+
};
|
|
21706
|
+
var mergeDefinedProviderPolicyFields = (base, surface) => {
|
|
21707
|
+
const next = {
|
|
21708
|
+
...base ?? {}
|
|
21709
|
+
};
|
|
21710
|
+
if (surface.allowProviders !== undefined) {
|
|
21711
|
+
next.allowProviders = surface.allowProviders;
|
|
21712
|
+
}
|
|
21713
|
+
if (surface.fallbackMode !== undefined) {
|
|
21714
|
+
next.fallbackMode = surface.fallbackMode;
|
|
21715
|
+
}
|
|
21716
|
+
if (surface.maxCost !== undefined) {
|
|
21717
|
+
next.maxCost = surface.maxCost;
|
|
21718
|
+
}
|
|
21719
|
+
if (surface.maxLatencyMs !== undefined) {
|
|
21720
|
+
next.maxLatencyMs = surface.maxLatencyMs;
|
|
21721
|
+
}
|
|
21722
|
+
if (surface.minQuality !== undefined) {
|
|
21723
|
+
next.minQuality = surface.minQuality;
|
|
21724
|
+
}
|
|
21725
|
+
if (surface.strategy !== undefined) {
|
|
21726
|
+
next.strategy = surface.strategy;
|
|
21727
|
+
}
|
|
21728
|
+
if (surface.weights !== undefined) {
|
|
21729
|
+
next.weights = {
|
|
21730
|
+
...base?.weights ?? {},
|
|
21731
|
+
...surface.weights
|
|
21732
|
+
};
|
|
21733
|
+
}
|
|
21734
|
+
return next;
|
|
21735
|
+
};
|
|
21736
|
+
var createVoiceProviderOrchestrationProfile = (options) => {
|
|
21737
|
+
const surfaceNames = Object.keys(options.surfaces);
|
|
21738
|
+
const defaultSurface = options.defaultSurface ?? surfaceNames[0];
|
|
21739
|
+
if (!defaultSurface || !options.surfaces[defaultSurface]) {
|
|
21740
|
+
throw new Error("Voice provider orchestration profile has no surfaces.");
|
|
21741
|
+
}
|
|
21742
|
+
return {
|
|
21743
|
+
defaultSurface,
|
|
21744
|
+
id: options.id,
|
|
21745
|
+
resolve: (surface = defaultSurface) => {
|
|
21746
|
+
const config = options.surfaces[surface];
|
|
21747
|
+
if (!config) {
|
|
21748
|
+
throw new Error(`Voice provider orchestration profile ${options.id} has no surface "${surface}".`);
|
|
21749
|
+
}
|
|
21750
|
+
const policy = mergeDefinedProviderPolicyFields(resolveVoiceProviderRoutingPolicy(config.policy), config);
|
|
21751
|
+
return {
|
|
21752
|
+
allowProviders: config.allowProviders,
|
|
21753
|
+
fallback: config.fallback,
|
|
21754
|
+
fallbackMode: config.fallbackMode,
|
|
21755
|
+
policy,
|
|
21756
|
+
providerHealth: config.providerHealth,
|
|
21757
|
+
providerProfiles: config.providerProfiles,
|
|
21758
|
+
timeoutMs: config.timeoutMs
|
|
21759
|
+
};
|
|
21760
|
+
},
|
|
21761
|
+
surfaces: options.surfaces
|
|
21762
|
+
};
|
|
21763
|
+
};
|
|
21694
21764
|
var OUTPUT_SCHEMA = {
|
|
21695
21765
|
additionalProperties: false,
|
|
21696
21766
|
properties: {
|
|
@@ -21858,19 +21928,23 @@ var createJSONVoiceAssistantModel = (options) => ({
|
|
|
21858
21928
|
var createVoiceProviderRouter = (options) => {
|
|
21859
21929
|
const providerIds = Object.keys(options.providers);
|
|
21860
21930
|
const firstProvider = providerIds[0];
|
|
21861
|
-
const
|
|
21862
|
-
|
|
21863
|
-
} : options.policy;
|
|
21931
|
+
const orchestrationSurface = options.orchestrationProfile?.resolve(options.orchestrationSurface);
|
|
21932
|
+
const policy = resolveVoiceProviderRoutingPolicy(options.policy) ?? resolveVoiceProviderRoutingPolicy(orchestrationSurface?.policy);
|
|
21864
21933
|
const strategy = policy?.strategy ?? "prefer-selected";
|
|
21865
|
-
const fallbackMode = policy?.fallbackMode ?? options.fallbackMode ?? "provider-error";
|
|
21866
|
-
const
|
|
21934
|
+
const fallbackMode = policy?.fallbackMode ?? options.fallbackMode ?? orchestrationSurface?.fallbackMode ?? "provider-error";
|
|
21935
|
+
const providerProfiles = {
|
|
21936
|
+
...orchestrationSurface?.providerProfiles ?? {},
|
|
21937
|
+
...options.providerProfiles ?? {}
|
|
21938
|
+
};
|
|
21939
|
+
const providerHealthOption = options.providerHealth ?? orchestrationSurface?.providerHealth;
|
|
21940
|
+
const healthOptions = typeof providerHealthOption === "object" ? providerHealthOption : providerHealthOption ? {} : undefined;
|
|
21867
21941
|
const healthState = new Map;
|
|
21868
21942
|
const now = () => healthOptions?.now?.() ?? Date.now();
|
|
21869
21943
|
const failureThreshold = Math.max(1, healthOptions?.failureThreshold ?? 1);
|
|
21870
21944
|
const cooldownMs = Math.max(0, healthOptions?.cooldownMs ?? 30000);
|
|
21871
21945
|
const rateLimitCooldownMs = Math.max(0, healthOptions?.rateLimitCooldownMs ?? 60000);
|
|
21872
21946
|
const getProviderTimeoutMs = (provider) => {
|
|
21873
|
-
const timeoutMs =
|
|
21947
|
+
const timeoutMs = providerProfiles[provider]?.timeoutMs ?? options.timeoutMs ?? orchestrationSurface?.timeoutMs;
|
|
21874
21948
|
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : undefined;
|
|
21875
21949
|
};
|
|
21876
21950
|
const getHealth = (provider) => {
|
|
@@ -21936,12 +22010,12 @@ var createVoiceProviderRouter = (options) => {
|
|
|
21936
22010
|
return cloneHealth(provider);
|
|
21937
22011
|
};
|
|
21938
22012
|
const resolveAllowedProviders = async (input) => {
|
|
21939
|
-
const allowProviders = policy?.allowProviders ?? options.allowProviders;
|
|
22013
|
+
const allowProviders = policy?.allowProviders ?? options.allowProviders ?? orchestrationSurface?.allowProviders;
|
|
21940
22014
|
const allowed = typeof allowProviders === "function" ? await allowProviders(input) : allowProviders;
|
|
21941
22015
|
return new Set(allowed ?? providerIds);
|
|
21942
22016
|
};
|
|
21943
22017
|
const passesBudgetFilters = (provider) => {
|
|
21944
|
-
const profile =
|
|
22018
|
+
const profile = providerProfiles[provider];
|
|
21945
22019
|
if (typeof policy?.maxCost === "number" && typeof profile?.cost === "number" && profile.cost > policy.maxCost) {
|
|
21946
22020
|
return false;
|
|
21947
22021
|
}
|
|
@@ -21954,7 +22028,7 @@ var createVoiceProviderRouter = (options) => {
|
|
|
21954
22028
|
return true;
|
|
21955
22029
|
};
|
|
21956
22030
|
const getBalancedScore = (provider) => {
|
|
21957
|
-
const profile =
|
|
22031
|
+
const profile = providerProfiles[provider];
|
|
21958
22032
|
if (policy?.scoreProvider) {
|
|
21959
22033
|
return policy.scoreProvider(provider, profile);
|
|
21960
22034
|
}
|
|
@@ -21966,8 +22040,8 @@ var createVoiceProviderRouter = (options) => {
|
|
|
21966
22040
|
return providers;
|
|
21967
22041
|
}
|
|
21968
22042
|
return [...providers].sort((left, right) => {
|
|
21969
|
-
const leftProfile =
|
|
21970
|
-
const rightProfile =
|
|
22043
|
+
const leftProfile = providerProfiles[left];
|
|
22044
|
+
const rightProfile = providerProfiles[right];
|
|
21971
22045
|
if (strategy === "quality-first") {
|
|
21972
22046
|
return (rightProfile?.quality ?? Number.MIN_SAFE_INTEGER) - (leftProfile?.quality ?? Number.MIN_SAFE_INTEGER) || (leftProfile?.priority ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.priority ?? Number.MAX_SAFE_INTEGER) || (leftProfile?.latencyMs ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.latencyMs ?? Number.MAX_SAFE_INTEGER) || (leftProfile?.cost ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.cost ?? Number.MAX_SAFE_INTEGER);
|
|
21973
22047
|
}
|
|
@@ -21982,7 +22056,8 @@ var createVoiceProviderRouter = (options) => {
|
|
|
21982
22056
|
const resolveOrder = async (input) => {
|
|
21983
22057
|
const selectedProvider = await options.selectProvider?.(input);
|
|
21984
22058
|
const allowedProviders = await resolveAllowedProviders(input);
|
|
21985
|
-
const
|
|
22059
|
+
const fallbackSource = options.fallback ?? orchestrationSurface?.fallback;
|
|
22060
|
+
const fallbackOrder = typeof fallbackSource === "function" ? await fallbackSource(input) : fallbackSource;
|
|
21986
22061
|
const allowedRankedProviders = sortProviders([
|
|
21987
22062
|
...fallbackOrder ?? providerIds
|
|
21988
22063
|
]).filter((provider) => allowedProviders.has(provider));
|
|
@@ -23275,9 +23350,215 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
23275
23350
|
}
|
|
23276
23351
|
return routes;
|
|
23277
23352
|
};
|
|
23278
|
-
// src/
|
|
23353
|
+
// src/providerOrchestration.ts
|
|
23279
23354
|
import { Elysia as Elysia37 } from "elysia";
|
|
23355
|
+
var defaultRequirement = {
|
|
23356
|
+
minProviders: 1,
|
|
23357
|
+
requireBudgetPolicy: false,
|
|
23358
|
+
requireCircuitBreaker: false,
|
|
23359
|
+
requireFallback: false,
|
|
23360
|
+
requireTimeoutBudget: false
|
|
23361
|
+
};
|
|
23362
|
+
var statusRank = {
|
|
23363
|
+
pass: 0,
|
|
23364
|
+
warn: 1,
|
|
23365
|
+
fail: 2
|
|
23366
|
+
};
|
|
23280
23367
|
var escapeHtml36 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
23368
|
+
var isProviderList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
23369
|
+
var uniqueSorted5 = (values) => [
|
|
23370
|
+
...new Set(values.filter((value) => typeof value === "string"))
|
|
23371
|
+
].sort();
|
|
23372
|
+
var policyRecord = (surface) => surface.policy && typeof surface.policy === "object" ? surface.policy : {};
|
|
23373
|
+
var surfaceProviderNames = (surface) => uniqueSorted5([
|
|
23374
|
+
...Object.keys(surface.providerProfiles ?? {}),
|
|
23375
|
+
...isProviderList(surface.fallback) ? surface.fallback : [],
|
|
23376
|
+
...isProviderList(surface.allowProviders) ? surface.allowProviders : []
|
|
23377
|
+
]);
|
|
23378
|
+
var surfaceStatus = (issues) => issues.reduce((status, issue) => statusRank[issue.status] > statusRank[status] ? issue.status : status, "pass");
|
|
23379
|
+
var resolvedRequirement = (surface, options) => ({
|
|
23380
|
+
...defaultRequirement,
|
|
23381
|
+
...options.defaultRequirement ?? {},
|
|
23382
|
+
...options.requirements?.[surface] ?? {}
|
|
23383
|
+
});
|
|
23384
|
+
var buildSurfaceReport = (surfaceName, config, resolved, requirement) => {
|
|
23385
|
+
const policy = policyRecord(resolved);
|
|
23386
|
+
const providers = surfaceProviderNames(resolved);
|
|
23387
|
+
const fallbackProviders = isProviderList(resolved.fallback) ? [...resolved.fallback] : [];
|
|
23388
|
+
const allowProviders = isProviderList(resolved.allowProviders) ? [...resolved.allowProviders] : [];
|
|
23389
|
+
const providerProfiles = Object.fromEntries(Object.entries(resolved.providerProfiles ?? {}).filter((entry) => Boolean(entry[1])));
|
|
23390
|
+
const timeoutMs = typeof resolved.timeoutMs === "number" ? resolved.timeoutMs : Object.values(providerProfiles).find((profile) => typeof profile.timeoutMs === "number")?.timeoutMs;
|
|
23391
|
+
const issues = [];
|
|
23392
|
+
const budgetPolicy = {
|
|
23393
|
+
maxCost: typeof policy.maxCost === "number" ? policy.maxCost : undefined,
|
|
23394
|
+
maxLatencyMs: typeof policy.maxLatencyMs === "number" ? policy.maxLatencyMs : undefined,
|
|
23395
|
+
minQuality: typeof policy.minQuality === "number" ? policy.minQuality : undefined
|
|
23396
|
+
};
|
|
23397
|
+
const hasBudgetPolicy = Object.values(budgetPolicy).some((value) => typeof value === "number");
|
|
23398
|
+
const circuitBreaker = Boolean(resolved.providerHealth);
|
|
23399
|
+
const timeoutBudget = typeof timeoutMs === "number";
|
|
23400
|
+
if (providers.length < requirement.minProviders) {
|
|
23401
|
+
issues.push({
|
|
23402
|
+
code: "voice.provider_orchestration.min_providers",
|
|
23403
|
+
message: `Surface ${surfaceName} has ${String(providers.length)} provider(s); expected at least ${String(requirement.minProviders)}.`,
|
|
23404
|
+
status: "fail",
|
|
23405
|
+
surface: surfaceName
|
|
23406
|
+
});
|
|
23407
|
+
}
|
|
23408
|
+
if (requirement.requireFallback && fallbackProviders.length === 0) {
|
|
23409
|
+
issues.push({
|
|
23410
|
+
code: "voice.provider_orchestration.fallback_missing",
|
|
23411
|
+
message: `Surface ${surfaceName} requires a fallback order.`,
|
|
23412
|
+
status: "fail",
|
|
23413
|
+
surface: surfaceName
|
|
23414
|
+
});
|
|
23415
|
+
}
|
|
23416
|
+
if (requirement.requireCircuitBreaker && !circuitBreaker) {
|
|
23417
|
+
issues.push({
|
|
23418
|
+
code: "voice.provider_orchestration.circuit_breaker_missing",
|
|
23419
|
+
message: `Surface ${surfaceName} requires providerHealth circuit-breaker settings.`,
|
|
23420
|
+
status: "fail",
|
|
23421
|
+
surface: surfaceName
|
|
23422
|
+
});
|
|
23423
|
+
}
|
|
23424
|
+
if (requirement.requireTimeoutBudget && !timeoutBudget) {
|
|
23425
|
+
issues.push({
|
|
23426
|
+
code: "voice.provider_orchestration.timeout_budget_missing",
|
|
23427
|
+
message: `Surface ${surfaceName} requires a route-level or provider-level timeout budget.`,
|
|
23428
|
+
status: "fail",
|
|
23429
|
+
surface: surfaceName
|
|
23430
|
+
});
|
|
23431
|
+
}
|
|
23432
|
+
if (requirement.requireBudgetPolicy && !hasBudgetPolicy) {
|
|
23433
|
+
issues.push({
|
|
23434
|
+
code: "voice.provider_orchestration.budget_policy_missing",
|
|
23435
|
+
message: `Surface ${surfaceName} requires maxCost, maxLatencyMs, or minQuality policy bounds.`,
|
|
23436
|
+
status: "fail",
|
|
23437
|
+
surface: surfaceName
|
|
23438
|
+
});
|
|
23439
|
+
}
|
|
23440
|
+
if (!requirement.requireFallback && fallbackProviders.length === 0 && providers.length > 1) {
|
|
23441
|
+
issues.push({
|
|
23442
|
+
code: "voice.provider_orchestration.fallback_unset",
|
|
23443
|
+
message: `Surface ${surfaceName} has multiple providers but no explicit fallback order.`,
|
|
23444
|
+
status: "warn",
|
|
23445
|
+
surface: surfaceName
|
|
23446
|
+
});
|
|
23447
|
+
}
|
|
23448
|
+
return {
|
|
23449
|
+
allowProviders,
|
|
23450
|
+
budgetPolicy,
|
|
23451
|
+
circuitBreaker,
|
|
23452
|
+
fallbackMode: resolved.fallbackMode ?? String(policy.fallbackMode ?? ""),
|
|
23453
|
+
fallbackProviders,
|
|
23454
|
+
issues,
|
|
23455
|
+
providerProfiles,
|
|
23456
|
+
providers,
|
|
23457
|
+
status: surfaceStatus(issues),
|
|
23458
|
+
strategy: typeof policy.strategy === "string" ? policy.strategy : typeof config.policy === "string" ? config.policy : undefined,
|
|
23459
|
+
surface: surfaceName,
|
|
23460
|
+
timeoutBudget,
|
|
23461
|
+
timeoutMs
|
|
23462
|
+
};
|
|
23463
|
+
};
|
|
23464
|
+
var buildVoiceProviderOrchestrationReport = (options) => {
|
|
23465
|
+
const surfaceNames = Object.keys(options.profile.surfaces);
|
|
23466
|
+
const surfaces = surfaceNames.map((surfaceName) => buildSurfaceReport(surfaceName, options.profile.surfaces[surfaceName], options.profile.resolve(surfaceName), resolvedRequirement(surfaceName, options)));
|
|
23467
|
+
const issues = surfaces.flatMap((surface) => surface.issues);
|
|
23468
|
+
const status = surfaceStatus(issues);
|
|
23469
|
+
const providers = uniqueSorted5(surfaces.flatMap((surface) => surface.providers)).length;
|
|
23470
|
+
return {
|
|
23471
|
+
checkedAt: Date.now(),
|
|
23472
|
+
issues,
|
|
23473
|
+
profileId: options.profile.id,
|
|
23474
|
+
status,
|
|
23475
|
+
summary: {
|
|
23476
|
+
failed: surfaces.filter((surface) => surface.status === "fail").length,
|
|
23477
|
+
passed: surfaces.filter((surface) => surface.status === "pass").length,
|
|
23478
|
+
providers,
|
|
23479
|
+
surfaces: surfaces.length,
|
|
23480
|
+
warned: surfaces.filter((surface) => surface.status === "warn").length
|
|
23481
|
+
},
|
|
23482
|
+
surfaces
|
|
23483
|
+
};
|
|
23484
|
+
};
|
|
23485
|
+
var renderVoiceProviderOrchestrationMarkdown = (report) => {
|
|
23486
|
+
const lines = [
|
|
23487
|
+
"# Voice Provider Orchestration",
|
|
23488
|
+
"",
|
|
23489
|
+
`- Profile: ${report.profileId}`,
|
|
23490
|
+
`- Status: ${report.status}`,
|
|
23491
|
+
`- Surfaces: ${String(report.summary.surfaces)}`,
|
|
23492
|
+
`- Providers: ${String(report.summary.providers)}`,
|
|
23493
|
+
""
|
|
23494
|
+
];
|
|
23495
|
+
for (const surface of report.surfaces) {
|
|
23496
|
+
lines.push(`## ${surface.surface}`, "", `- Status: ${surface.status}`, `- Strategy: ${surface.strategy ?? "default"}`, `- Providers: ${surface.providers.join(", ") || "none"}`, `- Fallback: ${surface.fallbackProviders.join(" -> ") || "none"}`, `- Circuit breaker: ${surface.circuitBreaker ? "yes" : "no"}`, `- Timeout budget: ${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}`, "");
|
|
23497
|
+
for (const issue of surface.issues) {
|
|
23498
|
+
lines.push(`- ${issue.status.toUpperCase()}: ${issue.message}`);
|
|
23499
|
+
}
|
|
23500
|
+
if (surface.issues.length > 0) {
|
|
23501
|
+
lines.push("");
|
|
23502
|
+
}
|
|
23503
|
+
}
|
|
23504
|
+
return lines.join(`
|
|
23505
|
+
`).trimEnd() + `
|
|
23506
|
+
`;
|
|
23507
|
+
};
|
|
23508
|
+
var renderVoiceProviderOrchestrationHTML = (report, options = {}) => {
|
|
23509
|
+
const title = options.title ?? "Voice Provider Orchestration";
|
|
23510
|
+
const cards = report.surfaces.map((surface) => `<article class="card ${escapeHtml36(surface.status)}">
|
|
23511
|
+
<div class="card-header"><div><p class="eyebrow">${escapeHtml36(surface.surface)}</p><h2>${escapeHtml36(surface.strategy ?? "default policy")}</h2></div><strong>${escapeHtml36(surface.status)}</strong></div>
|
|
23512
|
+
<dl>
|
|
23513
|
+
<div><dt>Providers</dt><dd>${escapeHtml36(surface.providers.join(", ") || "none")}</dd></div>
|
|
23514
|
+
<div><dt>Fallback</dt><dd>${escapeHtml36(surface.fallbackProviders.join(" -> ") || "none")}</dd></div>
|
|
23515
|
+
<div><dt>Circuit breaker</dt><dd>${surface.circuitBreaker ? "yes" : "no"}</dd></div>
|
|
23516
|
+
<div><dt>Timeout</dt><dd>${surface.timeoutBudget ? `${String(surface.timeoutMs)}ms` : "none"}</dd></div>
|
|
23517
|
+
<div><dt>Max cost</dt><dd>${surface.budgetPolicy.maxCost ?? "none"}</dd></div>
|
|
23518
|
+
<div><dt>Max latency</dt><dd>${surface.budgetPolicy.maxLatencyMs ? `${String(surface.budgetPolicy.maxLatencyMs)}ms` : "none"}</dd></div>
|
|
23519
|
+
<div><dt>Min quality</dt><dd>${surface.budgetPolicy.minQuality ?? "none"}</dd></div>
|
|
23520
|
+
<div><dt>Fallback mode</dt><dd>${escapeHtml36(surface.fallbackMode || "default")}</dd></div>
|
|
23521
|
+
</dl>
|
|
23522
|
+
${surface.issues.length ? `<ul>${surface.issues.map((issue) => `<li><strong>${escapeHtml36(issue.status)}</strong> ${escapeHtml36(issue.message)}</li>`).join("")}</ul>` : "<p>No orchestration issues.</p>"}
|
|
23523
|
+
</article>`).join("");
|
|
23524
|
+
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:#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>${escapeHtml36(title)}</h1><div class="summary"><span class="pill">${escapeHtml36(report.profileId)}</span><span class="pill">${escapeHtml36(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>`;
|
|
23525
|
+
};
|
|
23526
|
+
var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
23527
|
+
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
23528
|
+
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
23529
|
+
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
23530
|
+
const routes = new Elysia37({
|
|
23531
|
+
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
23532
|
+
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
23533
|
+
if (htmlPath) {
|
|
23534
|
+
routes.get(htmlPath, async () => {
|
|
23535
|
+
const report = buildVoiceProviderOrchestrationReport(options);
|
|
23536
|
+
const render = options.render ?? ((input) => renderVoiceProviderOrchestrationHTML(input, options));
|
|
23537
|
+
const body = await render(report);
|
|
23538
|
+
return new Response(body, {
|
|
23539
|
+
headers: {
|
|
23540
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
23541
|
+
...options.headers
|
|
23542
|
+
}
|
|
23543
|
+
});
|
|
23544
|
+
});
|
|
23545
|
+
}
|
|
23546
|
+
if (markdownPath) {
|
|
23547
|
+
routes.get(markdownPath, () => {
|
|
23548
|
+
const report = buildVoiceProviderOrchestrationReport(options);
|
|
23549
|
+
return new Response(renderVoiceProviderOrchestrationMarkdown(report), {
|
|
23550
|
+
headers: {
|
|
23551
|
+
"Content-Type": "text/markdown; charset=utf-8",
|
|
23552
|
+
...options.headers
|
|
23553
|
+
}
|
|
23554
|
+
});
|
|
23555
|
+
});
|
|
23556
|
+
}
|
|
23557
|
+
return routes;
|
|
23558
|
+
};
|
|
23559
|
+
// src/resilienceRoutes.ts
|
|
23560
|
+
import { Elysia as Elysia38 } from "elysia";
|
|
23561
|
+
var escapeHtml37 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
23281
23562
|
var getString13 = (value) => typeof value === "string" ? value : undefined;
|
|
23282
23563
|
var getNumber7 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
23283
23564
|
var getBoolean2 = (value) => value === true;
|
|
@@ -23425,13 +23706,13 @@ var summarizeRoutingEvents = (events) => {
|
|
|
23425
23706
|
};
|
|
23426
23707
|
var renderProviderCards = (title, providers) => {
|
|
23427
23708
|
if (providers.length === 0) {
|
|
23428
|
-
return `<p class="muted">No ${
|
|
23709
|
+
return `<p class="muted">No ${escapeHtml37(title)} provider health yet.</p>`;
|
|
23429
23710
|
}
|
|
23430
23711
|
return `<div class="provider-grid">${providers.map((provider) => `
|
|
23431
|
-
<article class="card provider ${
|
|
23712
|
+
<article class="card provider ${escapeHtml37(provider.status)}">
|
|
23432
23713
|
<div class="card-header">
|
|
23433
|
-
<strong>${
|
|
23434
|
-
<span>${
|
|
23714
|
+
<strong>${escapeHtml37(provider.provider)}</strong>
|
|
23715
|
+
<span>${escapeHtml37(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
|
|
23435
23716
|
</div>
|
|
23436
23717
|
<dl>
|
|
23437
23718
|
<div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
|
|
@@ -23440,7 +23721,7 @@ var renderProviderCards = (title, providers) => {
|
|
|
23440
23721
|
<div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
|
|
23441
23722
|
<div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
|
|
23442
23723
|
</dl>
|
|
23443
|
-
${provider.lastError ? `<p class="muted">${
|
|
23724
|
+
${provider.lastError ? `<p class="muted">${escapeHtml37(provider.lastError)}</p>` : ""}
|
|
23444
23725
|
</article>
|
|
23445
23726
|
`).join("")}</div>`;
|
|
23446
23727
|
};
|
|
@@ -23449,24 +23730,24 @@ var renderTimeline2 = (events) => {
|
|
|
23449
23730
|
return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
|
|
23450
23731
|
}
|
|
23451
23732
|
return `<div class="timeline">${events.slice(0, 40).map((event) => `
|
|
23452
|
-
<article class="card event ${
|
|
23733
|
+
<article class="card event ${escapeHtml37(event.status ?? "unknown")}">
|
|
23453
23734
|
<div class="card-header">
|
|
23454
|
-
<strong>${
|
|
23735
|
+
<strong>${escapeHtml37(event.kind.toUpperCase())} ${escapeHtml37(event.operation ?? "generate")}</strong>
|
|
23455
23736
|
<span>${new Date(event.at).toLocaleString()}</span>
|
|
23456
23737
|
</div>
|
|
23457
23738
|
<p>
|
|
23458
|
-
<span class="pill">${
|
|
23459
|
-
<span class="pill">provider: ${
|
|
23460
|
-
${event.fallbackProvider ? `<span class="pill">fallback: ${
|
|
23739
|
+
<span class="pill">${escapeHtml37(event.status ?? "unknown")}</span>
|
|
23740
|
+
<span class="pill">provider: ${escapeHtml37(event.provider ?? "unknown")}</span>
|
|
23741
|
+
${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml37(event.fallbackProvider)}</span>` : ""}
|
|
23461
23742
|
${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
|
|
23462
23743
|
</p>
|
|
23463
23744
|
<dl>
|
|
23464
23745
|
<div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
|
|
23465
23746
|
<div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
|
|
23466
23747
|
<div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
|
|
23467
|
-
<div><dt>Session</dt><dd>${
|
|
23748
|
+
<div><dt>Session</dt><dd>${escapeHtml37(event.sessionId)}</dd></div>
|
|
23468
23749
|
</dl>
|
|
23469
|
-
${event.error ? `<p class="muted">${
|
|
23750
|
+
${event.error ? `<p class="muted">${escapeHtml37(event.error)}</p>` : ""}
|
|
23470
23751
|
</article>
|
|
23471
23752
|
`).join("")}</div>`;
|
|
23472
23753
|
};
|
|
@@ -23476,9 +23757,9 @@ var renderSessionKind = (kind, summary) => {
|
|
|
23476
23757
|
const status = latest?.status ?? "idle";
|
|
23477
23758
|
const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
|
|
23478
23759
|
return `<div>
|
|
23479
|
-
<dt>${
|
|
23480
|
-
<dd>${
|
|
23481
|
-
<small>${
|
|
23760
|
+
<dt>${escapeHtml37(kind.toUpperCase())}</dt>
|
|
23761
|
+
<dd>${escapeHtml37(provider)}${escapeHtml37(fallback)}</dd>
|
|
23762
|
+
<small>${escapeHtml37(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
|
|
23482
23763
|
</div>`;
|
|
23483
23764
|
};
|
|
23484
23765
|
var renderSessionSummaries = (sessions) => {
|
|
@@ -23486,10 +23767,10 @@ var renderSessionSummaries = (sessions) => {
|
|
|
23486
23767
|
return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
|
|
23487
23768
|
}
|
|
23488
23769
|
return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
|
|
23489
|
-
<article class="card session ${
|
|
23770
|
+
<article class="card session ${escapeHtml37(session.status)}">
|
|
23490
23771
|
<div class="card-header">
|
|
23491
|
-
<strong>${
|
|
23492
|
-
<span>${
|
|
23772
|
+
<strong>${escapeHtml37(session.sessionId)}</strong>
|
|
23773
|
+
<span>${escapeHtml37(session.status)}</span>
|
|
23493
23774
|
</div>
|
|
23494
23775
|
<p>
|
|
23495
23776
|
<span class="pill">${session.eventCount} routing events</span>
|
|
@@ -23516,21 +23797,21 @@ var renderSimulationControls = (kind, simulation) => {
|
|
|
23516
23797
|
const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
|
|
23517
23798
|
const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
|
|
23518
23799
|
const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
|
|
23519
|
-
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${
|
|
23520
|
-
<p class="muted">${
|
|
23800
|
+
return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml37(pathPrefix)}">
|
|
23801
|
+
<p class="muted">${escapeHtml37(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
|
|
23521
23802
|
<div class="simulate-actions">
|
|
23522
|
-
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${
|
|
23523
|
-
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${
|
|
23803
|
+
${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml37(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml37(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
|
|
23804
|
+
${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml37(provider.provider)}">Mark ${escapeHtml37(provider.provider)} recovered</button>`).join("")}
|
|
23524
23805
|
</div>
|
|
23525
|
-
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${
|
|
23806
|
+
${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml37(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
|
|
23526
23807
|
<pre class="simulate-output" hidden></pre>
|
|
23527
23808
|
</div>`;
|
|
23528
23809
|
};
|
|
23529
23810
|
var renderVoiceResilienceHTML = (input) => {
|
|
23530
23811
|
const summary = summarizeRoutingEvents(input.routingEvents);
|
|
23531
|
-
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${
|
|
23532
|
-
const links = input.links?.length ? input.links.map((link) => `<a href="${
|
|
23533
|
-
const snippet =
|
|
23812
|
+
const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml37(kind)}: ${String(count)}</span>`).join("");
|
|
23813
|
+
const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml37(link.href)}">${escapeHtml37(link.label)}</a>`).join(" \xB7 ") : "";
|
|
23814
|
+
const snippet = escapeHtml37(`const sttSimulator = createVoiceIOProviderFailureSimulator({
|
|
23534
23815
|
kind: 'stt',
|
|
23535
23816
|
providers: ['deepgram', 'assemblyai'],
|
|
23536
23817
|
fallback: ['deepgram', 'assemblyai'],
|
|
@@ -23568,7 +23849,7 @@ app.use(
|
|
|
23568
23849
|
<head>
|
|
23569
23850
|
<meta charset="utf-8" />
|
|
23570
23851
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
23571
|
-
<title>${
|
|
23852
|
+
<title>${escapeHtml37(input.title ?? "AbsoluteJS Voice Resilience")}</title>
|
|
23572
23853
|
<style>
|
|
23573
23854
|
:root { color-scheme: dark; }
|
|
23574
23855
|
body { background: radial-gradient(circle at top left, #172554, #09090b 36%, #050505); color: #f4f4f5; font-family: ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; }
|
|
@@ -23720,7 +24001,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
|
|
|
23720
24001
|
};
|
|
23721
24002
|
var createVoiceResilienceRoutes = (options) => {
|
|
23722
24003
|
const path = options.path ?? "/resilience";
|
|
23723
|
-
const routes = new
|
|
24004
|
+
const routes = new Elysia38({
|
|
23724
24005
|
name: options.name ?? "absolutejs-voice-resilience"
|
|
23725
24006
|
}).get(path, async () => {
|
|
23726
24007
|
const events = await options.store.list();
|
|
@@ -23902,7 +24183,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
23902
24183
|
return report;
|
|
23903
24184
|
};
|
|
23904
24185
|
// src/providerSlo.ts
|
|
23905
|
-
import { Elysia as
|
|
24186
|
+
import { Elysia as Elysia39 } from "elysia";
|
|
23906
24187
|
var defaultThresholds = {
|
|
23907
24188
|
llm: {
|
|
23908
24189
|
maxAverageElapsedMs: 2500,
|
|
@@ -23930,15 +24211,15 @@ var defaultThresholds = {
|
|
|
23930
24211
|
}
|
|
23931
24212
|
};
|
|
23932
24213
|
var providerKinds = ["llm", "stt", "tts"];
|
|
23933
|
-
var
|
|
24214
|
+
var statusRank2 = {
|
|
23934
24215
|
pass: 0,
|
|
23935
24216
|
warn: 1,
|
|
23936
24217
|
fail: 2
|
|
23937
24218
|
};
|
|
23938
|
-
var
|
|
24219
|
+
var escapeHtml38 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
23939
24220
|
var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
|
|
23940
24221
|
var rate3 = (count, total) => count / Math.max(1, total);
|
|
23941
|
-
var
|
|
24222
|
+
var uniqueSorted6 = (values) => [
|
|
23942
24223
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
23943
24224
|
].sort();
|
|
23944
24225
|
var percentile5 = (values, rank) => {
|
|
@@ -24121,13 +24402,13 @@ var buildVoiceProviderSloReport = async (options = {}) => {
|
|
|
24121
24402
|
var evaluateVoiceProviderSloEvidence = (report, input = {}) => {
|
|
24122
24403
|
const issues = [];
|
|
24123
24404
|
const kindReports = Object.values(report.kinds);
|
|
24124
|
-
const providers =
|
|
24405
|
+
const providers = uniqueSorted6(kindReports.flatMap((kind) => kind.providers));
|
|
24125
24406
|
const kinds = providerKinds.filter((kind) => report.kinds[kind].events > 0);
|
|
24126
24407
|
const fallbacks = kindReports.reduce((total, kind) => total + kind.fallbacks, 0);
|
|
24127
24408
|
const timeouts = kindReports.reduce((total, kind) => total + kind.timeouts, 0);
|
|
24128
24409
|
const unresolvedErrors = kindReports.reduce((total, kind) => total + kind.unresolvedErrors, 0);
|
|
24129
24410
|
const maxStatus = input.maxStatus ?? "pass";
|
|
24130
|
-
if (
|
|
24411
|
+
if (statusRank2[report.status] > statusRank2[maxStatus]) {
|
|
24131
24412
|
issues.push(`Expected provider SLO status at most ${maxStatus}, found ${report.status}.`);
|
|
24132
24413
|
}
|
|
24133
24414
|
if (input.minEvents !== undefined && report.events < input.minEvents) {
|
|
@@ -24231,11 +24512,11 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
24231
24512
|
const title = options.title ?? "AbsoluteJS Voice Provider SLOs";
|
|
24232
24513
|
const kindCards = providerKinds.map((kind) => {
|
|
24233
24514
|
const kindReport = report.kinds[kind];
|
|
24234
|
-
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${
|
|
24515
|
+
const metrics = Object.values(kindReport.metrics).map((metric) => `<div><dt>${escapeHtml38(metric.label)}</dt><dd>${escapeHtml38(formatMetricValue2(metric))}</dd><small>budget ${escapeHtml38(formatMetricThreshold(metric))}</small></div>`).join("");
|
|
24235
24516
|
const providers = kindReport.providers.length ? kindReport.providers.join(", ") : "none recorded";
|
|
24236
|
-
return `<article class="${
|
|
24517
|
+
return `<article class="${escapeHtml38(kindReport.status)}"><h2>${kind.toUpperCase()} <span>${escapeHtml38(kindReport.status)}</span></h2><p>${kindReport.events} routing event(s), ${kindReport.eventsWithLatency} latency sample(s), providers: ${escapeHtml38(providers)}.</p><dl>${metrics}</dl></article>`;
|
|
24237
24518
|
}).join("");
|
|
24238
|
-
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${
|
|
24519
|
+
const issues = report.issues.length > 0 ? `<ul>${report.issues.map((issue) => `<li class="${escapeHtml38(issue.status)}"><strong>${escapeHtml38(issue.kind ? `${issue.kind.toUpperCase()} ${issue.label}` : issue.label)}</strong><span>${escapeHtml38(issue.detail ?? "")}</span></li>`).join("")}</ul>` : "<p>No provider SLO issues.</p>";
|
|
24239
24520
|
const snippet = `createVoiceProviderSloRoutes({
|
|
24240
24521
|
store: runtimeStorage.traces,
|
|
24241
24522
|
requiredKinds: ['llm', 'stt', 'tts'],
|
|
@@ -24245,7 +24526,7 @@ var renderVoiceProviderSloHTML = (report, options = {}) => {
|
|
|
24245
24526
|
tts: { maxAverageElapsedMs: 1200, maxP95ElapsedMs: 2200 }
|
|
24246
24527
|
}
|
|
24247
24528
|
})`;
|
|
24248
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
24529
|
+
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:#101318;color:#f8f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1180px;padding:32px}.hero,article,.primitive{background:#171b22;border:1px solid #2c3340;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(14,165,233,.2),rgba(245,158,11,.12))}.eyebrow{color:#7dd3fc;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.3rem,6vw,4.9rem);letter-spacing:-.06em;line-height:.9;margin:.2rem 0 1rem}.status,article h2 span{border:1px solid #475569;border-radius:999px;display:inline-flex;font-size:.85rem;padding:6px 10px}.pass{border-color:rgba(34,197,94,.65)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}dl{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}dt{color:#cbd5e1;font-size:.78rem;text-transform:uppercase}dd{font-size:1.7rem;font-weight:900;margin:0}small{color:#a8b3c2}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#101318;border:1px solid #2c3340;border-radius:16px;padding:12px}li span{color:#cbd5e1;display:block;margin-top:4px}.primitive{background:#11161d}.primitive code{color:#bae6fd}.primitive pre{background:#070b10;border:1px solid #243041;border-radius:16px;color:#e0f2fe;overflow:auto;padding:16px}</style></head><body><main><section class="hero"><p class="eyebrow">Provider latency and fallback proof</p><h1>${escapeHtml38(title)}</h1><p class="status ${escapeHtml38(report.status)}">${escapeHtml38(report.status)}</p><p>${report.events} provider routing event(s), ${report.eventsWithLatency} latency sample(s).</p></section><section class="grid">${kindCards}</section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProviderSloRoutes(...)</code> turns provider speed into release evidence</h2><p>Pair this report with production readiness so LLM/STT/TTS latency, timeout, fallback, and unresolved error regressions block deploys.</p><pre><code>${escapeHtml38(snippet)}</code></pre></section><section><h2>Issues</h2>${issues}</section></main></body></html>`;
|
|
24249
24530
|
};
|
|
24250
24531
|
var createVoiceProviderSloRoutes = (options) => {
|
|
24251
24532
|
const path = options.path ?? "/api/voice/provider-slos";
|
|
@@ -24256,7 +24537,7 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
24256
24537
|
...options.headers ?? {}
|
|
24257
24538
|
};
|
|
24258
24539
|
const buildReport = () => buildVoiceProviderSloReport(options);
|
|
24259
|
-
const app = new
|
|
24540
|
+
const app = new Elysia39({ name: options.name ?? "absolute-voice-provider-slos" });
|
|
24260
24541
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
24261
24542
|
if (markdownPath !== false) {
|
|
24262
24543
|
app.get(markdownPath, async () => {
|
|
@@ -24286,10 +24567,10 @@ var createVoiceProviderSloRoutes = (options) => {
|
|
|
24286
24567
|
return app;
|
|
24287
24568
|
};
|
|
24288
24569
|
// src/productionReadiness.ts
|
|
24289
|
-
import { Elysia as
|
|
24570
|
+
import { Elysia as Elysia45 } from "elysia";
|
|
24290
24571
|
|
|
24291
24572
|
// src/telephony/security.ts
|
|
24292
|
-
import { Elysia as
|
|
24573
|
+
import { Elysia as Elysia40 } from "elysia";
|
|
24293
24574
|
|
|
24294
24575
|
// src/postgresStore.ts
|
|
24295
24576
|
var normalizeIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
@@ -25027,7 +25308,7 @@ var assertVoiceTelephonyWebhookSecurityEvidence = (report, input = {}) => {
|
|
|
25027
25308
|
};
|
|
25028
25309
|
var createVoiceTelephonyWebhookSecurityRoutes = (options) => {
|
|
25029
25310
|
const path = options.path ?? "/api/voice/telephony/webhook-security";
|
|
25030
|
-
return new
|
|
25311
|
+
return new Elysia40({
|
|
25031
25312
|
name: options.name ?? "absolutejs-voice-telephony-webhook-security"
|
|
25032
25313
|
}).get(path, () => buildVoiceTelephonyWebhookSecurityReport(options.options));
|
|
25033
25314
|
};
|
|
@@ -25084,8 +25365,8 @@ var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
|
25084
25365
|
};
|
|
25085
25366
|
|
|
25086
25367
|
// src/opsRecovery.ts
|
|
25087
|
-
import { Elysia as
|
|
25088
|
-
var
|
|
25368
|
+
import { Elysia as Elysia41 } from "elysia";
|
|
25369
|
+
var escapeHtml39 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25089
25370
|
var getString14 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
25090
25371
|
var hrefForSession = (value, sessionId) => {
|
|
25091
25372
|
if (typeof value === "function") {
|
|
@@ -25299,19 +25580,19 @@ ${failedSessions || "None."}
|
|
|
25299
25580
|
${report.latency ? renderVoiceLatencySLOMarkdown(report.latency, { title: "Latency SLO" }) : "Latency SLO disabled."}
|
|
25300
25581
|
`;
|
|
25301
25582
|
};
|
|
25302
|
-
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${
|
|
25583
|
+
var renderDeliverySummary = (label, summary) => summary ? `<article><span>${escapeHtml39(label)}</span><strong>${String(summary.failed + summary.deadLettered)} failed</strong><small>${String(summary.pending)} pending \xB7 ${String(summary.retryEligible)} retry eligible \xB7 ${String(summary.total)} total</small></article>` : `<article><span>${escapeHtml39(label)}</span><strong>not configured</strong></article>`;
|
|
25303
25584
|
var renderVoiceOpsRecoveryHTML = (report, options = {}) => {
|
|
25304
25585
|
const title = options.title ?? "Voice Ops Recovery";
|
|
25305
|
-
const issues = report.issues.map((issue) => `<tr><td>${
|
|
25306
|
-
const providers = report.providers.providers.map((provider) => `<tr><td>${
|
|
25307
|
-
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${
|
|
25308
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25586
|
+
const issues = report.issues.map((issue) => `<tr><td>${escapeHtml39(issue.severity)}</td><td><code>${escapeHtml39(issue.code)}</code></td><td>${issue.href ? `<a href="${escapeHtml39(issue.href)}">${escapeHtml39(issue.label)}</a>` : escapeHtml39(issue.label)}</td><td>${escapeHtml39(String(issue.value ?? ""))}</td><td>${escapeHtml39(issue.detail ?? "")}</td></tr>`).join("");
|
|
25587
|
+
const providers = report.providers.providers.map((provider) => `<tr><td>${escapeHtml39(provider.provider)}</td><td>${escapeHtml39(provider.status)}</td><td>${String(provider.runCount)}</td><td>${String(provider.errorCount)}</td><td>${String(provider.fallbackCount)}</td><td>${escapeHtml39(provider.lastError ?? "")}</td></tr>`).join("");
|
|
25588
|
+
const failedSessions = report.failedSessions.map((session) => `<li>${session.operationsRecordHref ? `<a href="${escapeHtml39(session.operationsRecordHref)}">${escapeHtml39(session.sessionId)}</a>` : escapeHtml39(session.sessionId)}${session.provider ? ` via ${escapeHtml39(session.provider)}` : ""}${session.error ? `: ${escapeHtml39(session.error)}` : ""}</li>`).join("");
|
|
25589
|
+
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{font-family:ui-sans-serif,system-ui,sans-serif;background:#f8fafc;color:#172033;margin:2rem;line-height:1.45}main{max-width:1180px;margin:auto}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:.75rem;margin:1rem 0}article{background:white;border:1px solid #dbe3ef;border-radius:14px;padding:1rem;box-shadow:0 10px 28px rgba(15,23,42,.05)}article span{display:block;color:#64748b;font-size:.85rem}article strong{display:block;font-size:1.5rem;margin:.2rem 0}article small{color:#64748b}table{border-collapse:collapse;width:100%;background:white;border:1px solid #dbe3ef;border-radius:14px;overflow:hidden}th,td{border-bottom:1px solid #e2e8f0;padding:.7rem;text-align:left;vertical-align:top}code{font-size:.85em}.status{display:inline-flex;border-radius:999px;padding:.35rem .7rem;background:${report.status === "fail" ? "#fee2e2" : report.status === "warn" ? "#fef3c7" : "#dcfce7"};color:${report.status === "fail" ? "#991b1b" : report.status === "warn" ? "#92400e" : "#166534"};font-weight:700}</style></head><body><main><h1>${escapeHtml39(title)}</h1><p><span class="status">${escapeHtml39(report.status)}</span> Checked ${escapeHtml39(new Date(report.checkedAt).toLocaleString())}</p><section class="grid"><article><span>Recovered fallbacks</span><strong>${String(report.providers.recoveredFallbacks)}</strong></article><article><span>Unresolved providers</span><strong>${String(report.providers.unresolvedFailures)}</strong></article><article><span>Operator interventions</span><strong>${String(report.interventions.total)}</strong></article><article><span>Latency status</span><strong>${escapeHtml39(report.latency?.status ?? "disabled")}</strong></article>${renderDeliverySummary("Audit delivery", report.auditDeliveries)}${renderDeliverySummary("Trace delivery", report.traceDeliveries)}${renderDeliverySummary("Handoff delivery", report.handoffDeliveries)}</section><h2>Issues</h2><table><thead><tr><th>Severity</th><th>Code</th><th>Label</th><th>Value</th><th>Detail</th></tr></thead><tbody>${issues || '<tr><td colspan="5">No recovery issues.</td></tr>'}</tbody></table><h2>Providers</h2><table><thead><tr><th>Provider</th><th>Status</th><th>Runs</th><th>Errors</th><th>Fallbacks</th><th>Last error</th></tr></thead><tbody>${providers || '<tr><td colspan="6">No provider activity.</td></tr>'}</tbody></table><h2>Failed Sessions</h2><ul>${failedSessions || "<li>None.</li>"}</ul></main></body></html>`;
|
|
25309
25590
|
};
|
|
25310
25591
|
var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
25311
25592
|
const path = options.path ?? "/api/voice/ops-recovery";
|
|
25312
25593
|
const htmlPath = options.htmlPath === undefined ? "/ops-recovery" : options.htmlPath;
|
|
25313
25594
|
const markdownPath = options.markdownPath === undefined ? `${path}.md` : options.markdownPath;
|
|
25314
|
-
const routes = new
|
|
25595
|
+
const routes = new Elysia41({
|
|
25315
25596
|
name: options.name ?? "absolutejs-voice-ops-recovery"
|
|
25316
25597
|
}).get(path, async () => buildVoiceOpsRecoveryReport(options));
|
|
25317
25598
|
if (htmlPath) {
|
|
@@ -25341,18 +25622,18 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
25341
25622
|
};
|
|
25342
25623
|
|
|
25343
25624
|
// src/observabilityExport.ts
|
|
25344
|
-
import { Elysia as
|
|
25625
|
+
import { Elysia as Elysia44 } from "elysia";
|
|
25345
25626
|
import { Database as Database4 } from "bun:sqlite";
|
|
25346
25627
|
import { createHash } from "crypto";
|
|
25347
25628
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
25348
25629
|
import { join as join3 } from "path";
|
|
25349
25630
|
|
|
25350
25631
|
// src/operationsRecord.ts
|
|
25351
|
-
import { Elysia as
|
|
25632
|
+
import { Elysia as Elysia43 } from "elysia";
|
|
25352
25633
|
|
|
25353
25634
|
// src/traceTimeline.ts
|
|
25354
|
-
import { Elysia as
|
|
25355
|
-
var
|
|
25635
|
+
import { Elysia as Elysia42 } from "elysia";
|
|
25636
|
+
var escapeHtml40 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25356
25637
|
var getString15 = (value) => typeof value === "string" && value.trim() ? value : undefined;
|
|
25357
25638
|
var getNumber8 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
25358
25639
|
var firstString3 = (payload, keys) => {
|
|
@@ -25535,17 +25816,17 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
|
|
|
25535
25816
|
};
|
|
25536
25817
|
};
|
|
25537
25818
|
var formatMs4 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
25538
|
-
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>${
|
|
25819
|
+
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>${formatMs4(provider.averageElapsedMs)}</dd></div><div><dt>Max</dt><dd>${formatMs4(provider.maxElapsedMs)}</dd></div><div><dt>Errors</dt><dd>${String(provider.errorCount)}</dd></div><div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div><div><dt>Timeouts</dt><dd>${String(provider.timeoutCount)}</dd></div></dl></article>`).join("")}</div>`;
|
|
25539
25820
|
var renderVoiceTraceTimelineSessionHTML = (session, options = {}) => {
|
|
25540
|
-
const events = session.events.map((event) => `<tr class="${
|
|
25541
|
-
const issues = session.evaluation.issues.length ? session.evaluation.issues.map((issue) => `<li class="${
|
|
25542
|
-
const supportLinks = session.operationsRecordHref ? `<p><a href="${
|
|
25543
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25821
|
+
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>${formatMs4(event.elapsedMs)}</td></tr>`).join("");
|
|
25822
|
+
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>";
|
|
25823
|
+
const supportLinks = session.operationsRecordHref ? `<p><a href="${escapeHtml40(session.operationsRecordHref)}">Open operations record</a></p>` : "";
|
|
25824
|
+
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>${supportLinks}</header><section class="metrics"><article><span>Events</span><strong>${String(session.summary.eventCount)}</strong></article><article><span>Turns</span><strong>${String(session.summary.turnCount)}</strong></article><article><span>Errors</span><strong>${String(session.summary.errorCount)}</strong></article><article><span>Duration</span><strong>${formatMs4(session.summary.callDurationMs)}</strong></article></section><section><h2>Providers</h2>${renderProviderCards2(session)}</section><section><h2>Issues</h2><ul>${issues}</ul></section><section><h2>Timeline</h2><table><thead><tr><th>Offset</th><th>Type</th><th>Event</th><th>Provider</th><th>Status</th><th>Latency</th></tr></thead><tbody>${events}</tbody></table></section></main></body></html>`;
|
|
25544
25825
|
};
|
|
25545
|
-
var renderSessionRows = (report) => report.sessions.length === 0 ? '<tr><td colspan="7">No trace events recorded yet.</td></tr>' : report.sessions.map((session) => `<tr class="${
|
|
25826
|
+
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>${session.operationsRecordHref ? `<a href="${escapeHtml40(session.operationsRecordHref)}">${escapeHtml40(session.sessionId)}</a>` : `<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>${formatMs4(session.summary.callDurationMs)}</td><td>${session.providers.map((provider) => escapeHtml40(provider.provider)).join(", ")}</td></tr>`).join("");
|
|
25546
25827
|
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}}";
|
|
25547
25828
|
var renderVoiceTraceTimelineHTML = (report, options = {}) => {
|
|
25548
|
-
const snippet =
|
|
25829
|
+
const snippet = escapeHtml40(`const traceStore = createVoiceTraceSinkStore({
|
|
25549
25830
|
store: runtimeStorage.traces,
|
|
25550
25831
|
sinks: [
|
|
25551
25832
|
createVoiceTraceHTTPSink({
|
|
@@ -25571,13 +25852,13 @@ app.use(
|
|
|
25571
25852
|
traceDeliveries: runtimeStorage.traceDeliveries
|
|
25572
25853
|
})
|
|
25573
25854
|
);`);
|
|
25574
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
25855
|
+
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 Timelines")}</title><style>${timelineCSS}.primitive{background:#181f27;border:1px solid #334155;border-radius:20px;margin:20px 0;padding:18px}.primitive p{line-height:1.55}.primitive pre{background:#0b1118;border:1px solid #2b3642;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.primitive code{color:#bfdbfe}</style></head><body><main><header><p class="eyebrow">Self-hosted voice debugging</p><h1>${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><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceTraceTimelineRoutes(...)</code> makes traces the proof backbone</h2><p class="muted">Mount trace timelines from the same trace store used by readiness, simulations, provider recovery, delivery sinks, and phone-agent smoke proof.</p><pre><code>${snippet}</code></pre></section><table><thead><tr><th>Session</th><th>Status</th><th>Events</th><th>Turns</th><th>Errors</th><th>Duration</th><th>Providers</th></tr></thead><tbody>${renderSessionRows(report)}</tbody></table></main></body></html>`;
|
|
25575
25856
|
};
|
|
25576
25857
|
var createVoiceTraceTimelineRoutes = (options) => {
|
|
25577
25858
|
const path = options.path ?? "/api/voice-traces";
|
|
25578
25859
|
const htmlPath = options.htmlPath ?? "/traces";
|
|
25579
25860
|
const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
|
|
25580
|
-
const routes = new
|
|
25861
|
+
const routes = new Elysia42({
|
|
25581
25862
|
name: options.name ?? "absolutejs-voice-trace-timelines"
|
|
25582
25863
|
});
|
|
25583
25864
|
const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
|
|
@@ -25637,7 +25918,7 @@ var hasPayloadValue = (payload, key, values) => {
|
|
|
25637
25918
|
return typeof value === "string" && values.has(value);
|
|
25638
25919
|
};
|
|
25639
25920
|
var countIntegrationDeliveryStatus = (events, status) => events.filter((event) => event.deliveryStatus === status).length;
|
|
25640
|
-
var
|
|
25921
|
+
var uniqueSorted7 = (values) => [
|
|
25641
25922
|
...new Set(values.filter((value) => typeof value === "string"))
|
|
25642
25923
|
].sort();
|
|
25643
25924
|
var pushMissingValuesIssue = (input) => {
|
|
@@ -25816,11 +26097,11 @@ var buildVoiceOperationsRecord = async (options) => {
|
|
|
25816
26097
|
var evaluateVoiceOperationsRecordGuardrails = (record, input = {}) => {
|
|
25817
26098
|
const issues = [];
|
|
25818
26099
|
const decisions = record.guardrails.decisions;
|
|
25819
|
-
const proofs =
|
|
25820
|
-
const ruleIds =
|
|
25821
|
-
const stages =
|
|
25822
|
-
const statuses =
|
|
25823
|
-
const toolNames =
|
|
26100
|
+
const proofs = uniqueSorted7(decisions.map((decision) => decision.proof));
|
|
26101
|
+
const ruleIds = uniqueSorted7(decisions.flatMap((decision) => decision.findings.map((finding) => finding.ruleId)));
|
|
26102
|
+
const stages = uniqueSorted7(decisions.map((decision) => decision.stage));
|
|
26103
|
+
const statuses = uniqueSorted7(decisions.map((decision) => decision.status));
|
|
26104
|
+
const toolNames = uniqueSorted7(decisions.map((decision) => decision.toolName));
|
|
25824
26105
|
const minDecisions = input.minDecisions ?? 1;
|
|
25825
26106
|
if (record.guardrails.total < minDecisions) {
|
|
25826
26107
|
issues.push(`Expected at least ${String(minDecisions)} guardrail decisions, found ${String(record.guardrails.total)}.`);
|
|
@@ -25885,7 +26166,7 @@ var assertVoiceOperationsRecordGuardrails = (record, input = {}) => {
|
|
|
25885
26166
|
}
|
|
25886
26167
|
return report;
|
|
25887
26168
|
};
|
|
25888
|
-
var
|
|
26169
|
+
var escapeHtml41 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25889
26170
|
var formatMs5 = (value) => value === undefined ? "n/a" : `${String(value)}ms`;
|
|
25890
26171
|
var outcomeLabels = (outcome) => [
|
|
25891
26172
|
outcome.complete ? "complete" : undefined,
|
|
@@ -25940,19 +26221,19 @@ var renderVoiceOperationsRecordGuardrailMarkdown = (record) => {
|
|
|
25940
26221
|
`);
|
|
25941
26222
|
};
|
|
25942
26223
|
var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
25943
|
-
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${
|
|
25944
|
-
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${
|
|
25945
|
-
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${
|
|
25946
|
-
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${
|
|
25947
|
-
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${
|
|
25948
|
-
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${
|
|
25949
|
-
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${
|
|
25950
|
-
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${
|
|
26224
|
+
const providers = record.providers.length ? record.providers.map((provider) => `<article><strong>${escapeHtml41(provider.provider)}</strong><span>${String(provider.eventCount)} events</span><span>${formatMs5(provider.averageElapsedMs)} avg</span><span>${String(provider.errorCount)} errors</span></article>`).join("") : '<p class="muted">No provider events recorded.</p>';
|
|
26225
|
+
const transcript = record.transcript.length ? record.transcript.map((turn) => `<li><strong>${escapeHtml41(turn.id)}</strong>${turn.committedText ? `<p><span class="label">Caller</span>${escapeHtml41(turn.committedText)}</p>` : ""}${turn.assistantReplies.map((reply) => `<p><span class="label">Assistant</span>${escapeHtml41(reply)}</p>`).join("")}${turn.errors.map((error) => `<p class="error"><span class="label">Error</span>${escapeHtml41(error)}</p>`).join("")}</li>`).join("") : "<li>No transcript turns recorded.</li>";
|
|
26226
|
+
const providerDecisions = record.providerDecisions.length ? record.providerDecisions.map((decision) => `<li><strong>${escapeHtml41(decision.provider ?? decision.selectedProvider ?? decision.fallbackProvider ?? "provider")}</strong> <span>${escapeHtml41(decision.status ?? decision.type)}</span> ${formatMs5(decision.elapsedMs)}${decision.fallbackProvider ? `<p>Fallback: ${escapeHtml41(decision.fallbackProvider)}</p>` : ""}${decision.error ? `<p class="error">${escapeHtml41(decision.error)}</p>` : ""}${decision.reason ? `<p>${escapeHtml41(decision.reason)}</p>` : ""}</li>`).join("") : "<li>No provider decisions recorded.</li>";
|
|
26227
|
+
const handoffs = record.handoffs.length ? record.handoffs.map((handoff) => `<li><strong>${escapeHtml41(handoff.fromAgentId ?? "unknown")}</strong> to <strong>${escapeHtml41(handoff.targetAgentId ?? "unknown")}</strong> <span>${escapeHtml41(handoff.status ?? "")}</span><p>${escapeHtml41(handoff.summary ?? handoff.reason ?? "")}</p></li>`).join("") : "<li>No agent handoffs recorded.</li>";
|
|
26228
|
+
const tools = record.tools.length ? record.tools.map((tool) => `<li><strong>${escapeHtml41(tool.toolName ?? "tool")}</strong> <span>${escapeHtml41(tool.status ?? "")}</span> ${formatMs5(tool.elapsedMs)} ${tool.error ? `<p>${escapeHtml41(tool.error)}</p>` : ""}</li>`).join("") : "<li>No tool calls recorded.</li>";
|
|
26229
|
+
const reviews = record.reviews?.reviews.length ? record.reviews.reviews.map((review) => `<li><strong>${escapeHtml41(review.title)}</strong> <span>${escapeHtml41(review.summary.outcome ?? "")}</span><p>${escapeHtml41(review.postCall?.summary ?? review.transcript.actual)}</p></li>`).join("") : "<li>No call reviews recorded.</li>";
|
|
26230
|
+
const tasks = record.tasks?.tasks.length ? record.tasks.tasks.map((task) => `<li><strong>${escapeHtml41(task.title)}</strong> <span>${escapeHtml41(task.status)}</span><p>${escapeHtml41(task.recommendedAction)}</p></li>`).join("") : "<li>No ops tasks recorded.</li>";
|
|
26231
|
+
const integrationEvents = record.integrationEvents?.events.length ? record.integrationEvents.events.map((event) => `<li><strong>${escapeHtml41(event.type)}</strong> <span>${escapeHtml41(event.deliveryStatus ?? "local")}</span><p>${escapeHtml41(event.deliveryError ?? event.deliveredTo ?? "")}</p></li>`).join("") : "<li>No integration events recorded.</li>";
|
|
25951
26232
|
const guardrails = record.guardrails.total ? record.guardrails.decisions.map((decision) => {
|
|
25952
26233
|
const findings = decision.findings.map((finding) => finding.label ?? finding.ruleId ?? finding.action).filter((value) => typeof value === "string").join(", ") || "none";
|
|
25953
|
-
return `<li><strong>assistant.guardrail ${
|
|
26234
|
+
return `<li><strong>assistant.guardrail ${escapeHtml41(decision.stage ?? "unknown")}</strong> <span>${escapeHtml41(decision.status ?? "")}</span><p>Allowed: ${escapeHtml41(String(decision.allowed ?? "unknown"))} \xB7 Proof: ${escapeHtml41(decision.proof ?? "runtime")}${decision.turnId ? ` \xB7 Turn: ${escapeHtml41(decision.turnId)}` : ""}</p><p>${escapeHtml41(findings)}</p></li>`;
|
|
25954
26235
|
}).join("") : "<li>No assistant.guardrail events recorded.</li>";
|
|
25955
|
-
const snippet =
|
|
26236
|
+
const snippet = escapeHtml41(`app.use(
|
|
25956
26237
|
createVoiceOperationsRecordRoutes({
|
|
25957
26238
|
audit: auditStore,
|
|
25958
26239
|
integrationEvents: opsEvents,
|
|
@@ -25966,16 +26247,16 @@ var renderVoiceOperationsRecordHTML = (record, options = {}) => {
|
|
|
25966
26247
|
tasks: opsTasks
|
|
25967
26248
|
})
|
|
25968
26249
|
);`);
|
|
25969
|
-
const incidentMarkdown =
|
|
25970
|
-
const incidentLink = options.incidentHref ? `<a href="${
|
|
25971
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
26250
|
+
const incidentMarkdown = escapeHtml41(renderVoiceOperationsRecordIncidentMarkdown(record));
|
|
26251
|
+
const incidentLink = options.incidentHref ? `<a href="${escapeHtml41(options.incidentHref)}">Download incident.md</a>` : "";
|
|
26252
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml41(options.title ?? "Voice Operations Record")}</title><style>body{background:#101417;color:#f9f4e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.eyebrow{color:#fbbf24;font-size:.8rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,4.8rem);line-height:.9;margin:.2rem 0 1rem}.status{border:1px solid #475569;border-radius:999px;display:inline-flex;padding:8px 12px}.healthy{color:#86efac}.warning{color:#fbbf24}.failed,.error{color:#fca5a5}.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:20px 0}.card,.primitive{background:#182025;border:1px solid #2d3a43;border-radius:20px;padding:16px}.card span,.muted,.label{color:#a9b4bd}.label{display:block;font-size:.72rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.card strong{display:block;font-size:2rem}section{margin-top:28px}article{display:grid;gap:8px}ul{display:grid;gap:10px;list-style:none;padding:0}li{background:#182025;border:1px solid #2d3a43;border-radius:16px;padding:14px}pre{background:#080d10;border:1px solid #2d3a43;border-radius:16px;color:#dbeafe;overflow:auto;padding:14px}.hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}.hero-actions a{background:#fbbf24;border-radius:999px;color:#111827;font-weight:900;padding:10px 14px;text-decoration:none}.two-column{display:grid;gap:18px;grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr)}@media(max-width:860px){main{padding:20px}.two-column{grid-template-columns:1fr}}</style></head><body><main><p class="eyebrow">Call log replacement</p><h1>${escapeHtml41(options.title ?? "Voice Operations Record")}</h1><p class="status ${escapeHtml41(record.status)}">${escapeHtml41(record.status)}</p><div class="hero-actions"><a href="#transcript">Transcript</a><a href="#provider-decisions">Provider decisions</a><a href="#guardrails">Guardrails</a><a href="#incident-handoff">Incident handoff</a>${incidentLink}</div><section class="grid"><div class="card"><span>Events</span><strong>${String(record.summary.eventCount)}</strong></div><div class="card"><span>Turns</span><strong>${String(record.summary.turnCount)}</strong></div><div class="card"><span>Errors</span><strong>${String(record.summary.errorCount)}</strong></div><div class="card"><span>Duration</span><strong>${formatMs5(record.summary.callDurationMs)}</strong></div><div class="card"><span>Guardrails</span><strong>${String(record.guardrails.blocked)}</strong></div><div class="card"><span>Audit</span><strong>${String(record.audit?.total ?? 0)}</strong></div><div class="card"><span>Reviews</span><strong>${String(record.reviews?.total ?? 0)}</strong></div><div class="card"><span>Tasks</span><strong>${String(record.tasks?.total ?? 0)}</strong></div><div class="card"><span>Integrations</span><strong>${String(record.integrationEvents?.total ?? 0)}</strong></div></section><section class="two-column"><div><h2 id="transcript">Transcript</h2><ul>${transcript}</ul></div><div><h2 id="provider-decisions">Provider Decisions</h2><ul>${providerDecisions}</ul></div></section><section id="guardrails"><h2>Guardrail Evidence</h2><p class="muted">Live <code>assistant.guardrail</code> decisions attached to this session.</p><ul>${guardrails}</ul></section><section id="incident-handoff"><h2>Copyable Incident Handoff</h2><p class="muted">Paste this into Slack, Linear, Zendesk, or an incident review. ${incidentLink}</p><pre><code>${incidentMarkdown}</code></pre></section><section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceOperationsRecordRoutes(...)</code> gives every call one debuggable object</h2><p class="muted">Use this as the support/debug payload across traces, provider routing, tools, handoffs, guardrails, audit, latency, replay, reviews, tasks, and webhook delivery.</p><pre><code>${snippet}</code></pre></section><section><h2>Provider Summary</h2><div class="grid">${providers}</div></section><section><h2>Handoffs</h2><ul>${handoffs}</ul></section><section><h2>Tools</h2><ul>${tools}</ul></section><section><h2>Reviews</h2><ul>${reviews}</ul></section><section><h2>Tasks</h2><ul>${tasks}</ul></section><section><h2>Integration Events</h2><ul>${integrationEvents}</ul></section></main></body></html>`;
|
|
25972
26253
|
};
|
|
25973
26254
|
var createVoiceOperationsRecordRoutes = (options) => {
|
|
25974
26255
|
const path = options.path ?? "/api/voice-operations/:sessionId";
|
|
25975
26256
|
const htmlPath = options.htmlPath === undefined ? "/voice-operations/:sessionId" : options.htmlPath;
|
|
25976
26257
|
const incidentPath = options.incidentPath === undefined ? `${path}/incident.md` : options.incidentPath;
|
|
25977
26258
|
const incidentHtmlPath = options.incidentHtmlPath === undefined && htmlPath ? `${htmlPath}/incident.md` : options.incidentHtmlPath;
|
|
25978
|
-
const routes = new
|
|
26259
|
+
const routes = new Elysia43({
|
|
25979
26260
|
name: options.name ?? "absolutejs-voice-operations-record"
|
|
25980
26261
|
});
|
|
25981
26262
|
const buildRecord = (sessionId) => buildVoiceOperationsRecord({
|
|
@@ -26626,7 +26907,7 @@ var createVoiceObservabilityExportReplayRoutes = (options) => {
|
|
|
26626
26907
|
...options.headers ?? {}
|
|
26627
26908
|
};
|
|
26628
26909
|
const buildReport = () => resolveVoiceObservabilityExportReplayReport(options.source);
|
|
26629
|
-
const app = new
|
|
26910
|
+
const app = new Elysia44({
|
|
26630
26911
|
name: options.name ?? "absolute-voice-observability-export-replay"
|
|
26631
26912
|
});
|
|
26632
26913
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -27435,7 +27716,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
27435
27716
|
artifactDownload: options.links?.artifactDownload ?? (artifactDownloadPath ? (artifact) => `${artifactDownloadPath}/${encodeURIComponent(artifact.id)}` : undefined)
|
|
27436
27717
|
}
|
|
27437
27718
|
});
|
|
27438
|
-
const app = new
|
|
27719
|
+
const app = new Elysia44({
|
|
27439
27720
|
name: options.name ?? "absolute-voice-observability-export"
|
|
27440
27721
|
});
|
|
27441
27722
|
app.get(path, async () => Response.json(await buildReport(), { headers }));
|
|
@@ -27512,7 +27793,7 @@ var createVoiceObservabilityExportRoutes = (options = {}) => {
|
|
|
27512
27793
|
};
|
|
27513
27794
|
|
|
27514
27795
|
// src/productionReadiness.ts
|
|
27515
|
-
var
|
|
27796
|
+
var escapeHtml42 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
27516
27797
|
var rollupStatus3 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
27517
27798
|
var readinessGateCodes = {
|
|
27518
27799
|
"Agent squad contracts": "voice.readiness.agent_squad_contracts",
|
|
@@ -27661,6 +27942,12 @@ var resolveProviderSlo = async (options, input) => {
|
|
|
27661
27942
|
store: value.store ?? options.store
|
|
27662
27943
|
});
|
|
27663
27944
|
};
|
|
27945
|
+
var resolveProviderOrchestration = async (options, input) => {
|
|
27946
|
+
if (options.providerOrchestration === false || options.providerOrchestration === undefined) {
|
|
27947
|
+
return;
|
|
27948
|
+
}
|
|
27949
|
+
return typeof options.providerOrchestration === "function" ? await options.providerOrchestration(input) : options.providerOrchestration;
|
|
27950
|
+
};
|
|
27664
27951
|
var resolveProviderStack = async (options, input) => {
|
|
27665
27952
|
if (options.providerStack === false || options.providerStack === undefined) {
|
|
27666
27953
|
return;
|
|
@@ -28060,6 +28347,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28060
28347
|
agentSquadContracts,
|
|
28061
28348
|
providerRoutingContracts,
|
|
28062
28349
|
providerSlo,
|
|
28350
|
+
providerOrchestration,
|
|
28063
28351
|
providerStack,
|
|
28064
28352
|
providerContractMatrix,
|
|
28065
28353
|
phoneAgentSmokes,
|
|
@@ -28101,6 +28389,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28101
28389
|
resolveAgentSquadContracts(options, { query, request }),
|
|
28102
28390
|
resolveProviderRoutingContracts(options, { query, request }),
|
|
28103
28391
|
resolveProviderSlo(options, { query, request }),
|
|
28392
|
+
resolveProviderOrchestration(options, { query, request }),
|
|
28104
28393
|
resolveProviderStack(options, { query, request }),
|
|
28105
28394
|
resolveProviderContractMatrix(options, { query, request }),
|
|
28106
28395
|
resolvePhoneAgentSmokes(options, { query, request }),
|
|
@@ -28337,6 +28626,15 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28337
28626
|
issues: providerSlo.issues.length,
|
|
28338
28627
|
status: providerSlo.status
|
|
28339
28628
|
} : undefined;
|
|
28629
|
+
const providerOrchestrationSummary = providerOrchestration ? {
|
|
28630
|
+
failed: providerOrchestration.summary.failed,
|
|
28631
|
+
issues: providerOrchestration.issues.length,
|
|
28632
|
+
passed: providerOrchestration.summary.passed,
|
|
28633
|
+
providers: providerOrchestration.summary.providers,
|
|
28634
|
+
status: providerOrchestration.status,
|
|
28635
|
+
surfaces: providerOrchestration.summary.surfaces,
|
|
28636
|
+
warned: providerOrchestration.summary.warned
|
|
28637
|
+
} : undefined;
|
|
28340
28638
|
const phoneAgentSmokeSummary = phoneAgentSmokes ? {
|
|
28341
28639
|
failed: phoneAgentSmokes.filter((report) => !report.pass).length,
|
|
28342
28640
|
passed: phoneAgentSmokes.filter((report) => report.pass).length,
|
|
@@ -28584,6 +28882,24 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28584
28882
|
]
|
|
28585
28883
|
});
|
|
28586
28884
|
}
|
|
28885
|
+
if (providerOrchestrationSummary && providerOrchestration) {
|
|
28886
|
+
const firstIssue = providerOrchestration.issues[0];
|
|
28887
|
+
checks.push({
|
|
28888
|
+
detail: providerOrchestrationSummary.status === "pass" ? `${providerOrchestrationSummary.surfaces} provider orchestration surface(s) are production-shaped.` : firstIssue?.message ?? `${providerOrchestrationSummary.issues} provider orchestration issue(s) need review.`,
|
|
28889
|
+
href: options.links?.providerOrchestration ?? options.links?.providerContracts ?? "/voice/provider-orchestration",
|
|
28890
|
+
label: "Provider orchestration profiles",
|
|
28891
|
+
proofSource: proofSource("providerOrchestration", "providerOrchestration"),
|
|
28892
|
+
status: providerOrchestrationSummary.status,
|
|
28893
|
+
value: `${providerOrchestrationSummary.passed}/${providerOrchestrationSummary.surfaces}`,
|
|
28894
|
+
actions: providerOrchestrationSummary.status === "pass" ? [] : [
|
|
28895
|
+
{
|
|
28896
|
+
description: "Open provider orchestration proof and add missing fallback, circuit-breaker, timeout, or budget policy configuration.",
|
|
28897
|
+
href: options.links?.providerOrchestration ?? options.links?.providerContracts ?? "/voice/provider-orchestration",
|
|
28898
|
+
label: "Open provider orchestration proof"
|
|
28899
|
+
}
|
|
28900
|
+
]
|
|
28901
|
+
});
|
|
28902
|
+
}
|
|
28587
28903
|
if (phoneAgentSmokeSummary) {
|
|
28588
28904
|
checks.push({
|
|
28589
28905
|
detail: phoneAgentSmokeSummary.status === "pass" ? `${phoneAgentSmokeSummary.passed} phone-agent smoke contract(s) are passing.` : phoneAgentSmokeSummary.total === 0 ? "No phone-agent production smoke contracts are configured." : `${phoneAgentSmokeSummary.failed} phone-agent production smoke contract(s) failed.`,
|
|
@@ -28861,6 +29177,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28861
29177
|
phoneAgentSmoke: "/sessions",
|
|
28862
29178
|
telephonyWebhookSecurity: "/api/voice/telephony/webhook-security",
|
|
28863
29179
|
providerContracts: "/provider-contracts",
|
|
29180
|
+
providerOrchestration: "/voice/provider-orchestration",
|
|
28864
29181
|
providerRoutingContracts: "/resilience",
|
|
28865
29182
|
providerSlo: "/voice/provider-slos",
|
|
28866
29183
|
quality: "/quality",
|
|
@@ -28906,6 +29223,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28906
29223
|
},
|
|
28907
29224
|
providerStack,
|
|
28908
29225
|
providerContractMatrix,
|
|
29226
|
+
providerOrchestration: providerOrchestrationSummary,
|
|
28909
29227
|
providerRecovery,
|
|
28910
29228
|
phoneAgentSmokes: phoneAgentSmokeSummary,
|
|
28911
29229
|
telephonyWebhookSecurity: telephonyWebhookSecuritySummary,
|
|
@@ -28930,25 +29248,25 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
|
|
|
28930
29248
|
var buildVoiceProductionReadinessGate = async (options, input = {}) => summarizeVoiceProductionReadinessGate(await buildVoiceProductionReadinessReport(options, input), options.gate || undefined);
|
|
28931
29249
|
var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
28932
29250
|
const title = options.title ?? "AbsoluteJS Voice Production Readiness";
|
|
28933
|
-
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${
|
|
28934
|
-
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${
|
|
29251
|
+
const thresholdLink = report.links.sloReadinessThresholds ? `<p><a href="${escapeHtml42(report.links.sloReadinessThresholds)}">Open Calibration -> Active Readiness Gate</a> to inspect the thresholds currently driving calibrated provider, latency, interruption, reconnect, and monitoring gates.</p>` : "";
|
|
29252
|
+
const profile = report.profile ? `<section class="profile"><p class="eyebrow">Readiness profile</p><h2>${escapeHtml42(report.profile.name)}</h2><p>${escapeHtml42(report.profile.description)}</p><p>${escapeHtml42(report.profile.purpose)}</p><div class="profile-surfaces">${report.profile.surfaces.map((surface) => `<article class="${surface.configured ? "pass" : "warn"}"><span>${surface.configured ? "CONFIGURED" : "EXPECTED"}</span><strong>${surface.href ? `<a href="${escapeHtml42(surface.href)}">${escapeHtml42(surface.label)}</a>` : escapeHtml42(surface.label)}</strong></article>`).join("")}</div></section>` : "";
|
|
28935
29253
|
const checks = report.checks.map((check, index) => {
|
|
28936
|
-
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${
|
|
28937
|
-
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${
|
|
28938
|
-
return `<article class="check ${
|
|
29254
|
+
const actions = (check.actions ?? []).map((action) => action.method === "POST" ? `<button type="button" data-readiness-action="${index}" data-action-url="${escapeHtml42(action.href)}">${escapeHtml42(action.label)}</button>` : `<a href="${escapeHtml42(action.href)}">${escapeHtml42(action.label)}</a>`).join("");
|
|
29255
|
+
const explanation = check.gateExplanation ? `<p class="gate-explanation">Why this gate is ${escapeHtml42(check.status)}: observed ${escapeHtml42(String(check.gateExplanation.observed ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml42(check.gateExplanation.unit)}` : ""}; threshold ${escapeHtml42(String(check.gateExplanation.threshold ?? "n/a"))}${check.gateExplanation.unit ? ` ${escapeHtml42(check.gateExplanation.unit)}` : ""}. ${escapeHtml42(check.gateExplanation.remediation)} ${check.gateExplanation.sourceHref ? `<a href="${escapeHtml42(check.gateExplanation.sourceHref)}">Open threshold source</a>` : ""}</p>` : "";
|
|
29256
|
+
return `<article class="check ${escapeHtml42(check.status)}">
|
|
28939
29257
|
<div>
|
|
28940
|
-
<span>${
|
|
28941
|
-
<h2>${
|
|
28942
|
-
${check.detail ? `<p>${
|
|
29258
|
+
<span>${escapeHtml42(check.status.toUpperCase())}</span>
|
|
29259
|
+
<h2>${escapeHtml42(check.label)}</h2>
|
|
29260
|
+
${check.detail ? `<p>${escapeHtml42(check.detail)}</p>` : ""}
|
|
28943
29261
|
${explanation}
|
|
28944
|
-
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${
|
|
29262
|
+
${check.proofSource ? `<p class="proof-source">Proof source: ${check.proofSource.href ? `<a href="${escapeHtml42(check.proofSource.href)}">${escapeHtml42(check.proofSource.sourceLabel)}</a>` : escapeHtml42(check.proofSource.sourceLabel)}${check.proofSource.detail ? ` \xB7 ${escapeHtml42(check.proofSource.detail)}` : ""}</p>` : ""}
|
|
28945
29263
|
${actions ? `<p class="actions">${actions}</p>` : ""}
|
|
28946
29264
|
</div>
|
|
28947
|
-
<strong>${
|
|
28948
|
-
${check.href ? `<a href="${
|
|
29265
|
+
<strong>${escapeHtml42(String(check.value ?? check.status))}</strong>
|
|
29266
|
+
${check.href ? `<a href="${escapeHtml42(check.href)}">Open surface</a>` : ""}
|
|
28949
29267
|
</article>`;
|
|
28950
29268
|
}).join("");
|
|
28951
|
-
const snippet =
|
|
29269
|
+
const snippet = escapeHtml42(`createVoiceProductionReadinessRoutes({
|
|
28952
29270
|
htmlPath: '/production-readiness',
|
|
28953
29271
|
path: '/api/production-readiness',
|
|
28954
29272
|
gatePath: '/api/production-readiness/gate',
|
|
@@ -28964,13 +29282,13 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
|
|
|
28964
29282
|
providerRoutingContracts: loadProviderRoutingContracts,
|
|
28965
29283
|
store: traceStore
|
|
28966
29284
|
});`);
|
|
28967
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
29285
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${escapeHtml42(title)}</title><style>body{background:#0c0f14;color:#f6f2e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1060px;padding:32px}.hero,.primitive,.profile{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12));border:1px solid #26313d;border-radius:28px;margin-bottom:18px;padding:28px}.primitive,.profile{background:#111722}.primitive{border-color:#3a3f2d}.eyebrow{color:#fbbf24;font-weight:900;letter-spacing:.12em;text-transform:uppercase}h1{font-size:clamp(2.4rem,6vw,5rem);line-height:.9;margin:.2rem 0 1rem}.status{display:inline-flex;border:1px solid #3f3f46;border-radius:999px;padding:8px 12px}.primitive code{color:#fde68a}.primitive p{color:#c8ccd3;line-height:1.55;margin:.45rem 0 0}.primitive pre{background:#0b0f16;border:1px solid #2c3440;border-radius:18px;color:#fef3c7;margin:16px 0 0;overflow:auto;padding:16px}.status.pass,.check.pass,.profile-surfaces .pass{border-color:rgba(34,197,94,.55)}.status.warn,.check.warn,.profile-surfaces .warn{border-color:rgba(245,158,11,.65)}.status.fail,.check.fail{border-color:rgba(239,68,68,.75)}.checks{display:grid;gap:14px}.check{align-items:center;background:#141922;border:1px solid #26313d;border-radius:22px;display:grid;gap:16px;grid-template-columns:1fr auto auto;padding:18px}.check span,.profile-surfaces span{color:#a8b0b8;font-size:.78rem;font-weight:900;letter-spacing:.08em}.check h2{margin:.2rem 0}.check p,.profile p{color:#b9c0c8;margin:.2rem 0 0}.check .proof-source{color:#f9d77e;font-weight:800}.check .gate-explanation{background:#0b0f16;border:1px solid #2c3440;border-radius:14px;color:#fef3c7;margin-top:10px;padding:10px}.check strong{font-size:1.5rem}.profile-surfaces{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-top:16px}.profile-surfaces article{background:#141922;border:1px solid #26313d;border-radius:16px;padding:14px}.profile-surfaces strong{display:block;margin-top:6px}.actions{display:flex;flex-wrap:wrap;gap:10px}.check a,a{color:#fbbf24}button{background:#fbbf24;border:0;border-radius:999px;color:#111827;cursor:pointer;font-weight:800;padding:9px 12px}button:disabled{cursor:wait;opacity:.65}@media(max-width:760px){main{padding:20px}.check{grid-template-columns:1fr}}</style></head><body><main><section class="hero"><p class="eyebrow">Self-hosted readiness</p><h1>${escapeHtml42(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 ${escapeHtml42(report.status)}">Overall: ${escapeHtml42(report.status.toUpperCase())}</p><p>Checked ${escapeHtml42(new Date(report.checkedAt).toLocaleString())}</p>${thresholdLink}</section>${profile}<section class="primitive"><p class="eyebrow">Copy into your app</p><h2><code>createVoiceProductionReadinessRoutes(...)</code> builds this deploy gate</h2><p>Mount one package primitive to expose JSON readiness, HTML readiness, and a machine-readable gate route. Feed it the proof stores and contract reports your app already owns.</p><pre><code>${snippet}</code></pre></section><section class="checks">${checks}</section></main><script>document.querySelectorAll("[data-readiness-action]").forEach((button)=>{button.addEventListener("click",async()=>{const url=button.getAttribute("data-action-url");if(!url)return;button.disabled=true;const original=button.textContent;button.textContent="Running...";try{const response=await fetch(url,{method:"POST"});button.textContent=response.ok?"Done. Reloading...":"Failed";if(response.ok)setTimeout(()=>location.reload(),500)}catch{button.textContent="Failed"}finally{setTimeout(()=>{button.disabled=false;button.textContent=original},1500)}})});</script></body></html>`;
|
|
28968
29286
|
};
|
|
28969
29287
|
var createVoiceProductionReadinessRoutes = (options) => {
|
|
28970
29288
|
const path = options.path ?? "/api/production-readiness";
|
|
28971
29289
|
const gatePath = options.gatePath === undefined ? "/api/production-readiness/gate" : options.gatePath;
|
|
28972
29290
|
const htmlPath = options.htmlPath ?? "/production-readiness";
|
|
28973
|
-
const routes = new
|
|
29291
|
+
const routes = new Elysia45({
|
|
28974
29292
|
name: options.name ?? "absolutejs-voice-production-readiness"
|
|
28975
29293
|
});
|
|
28976
29294
|
const resolveOptions = async (input) => {
|
|
@@ -29018,8 +29336,8 @@ var createVoiceProductionReadinessRoutes = (options) => {
|
|
|
29018
29336
|
return routes;
|
|
29019
29337
|
};
|
|
29020
29338
|
// src/voiceMonitoring.ts
|
|
29021
|
-
import { Elysia as
|
|
29022
|
-
var
|
|
29339
|
+
import { Elysia as Elysia46 } from "elysia";
|
|
29340
|
+
var escapeHtml43 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29023
29341
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
29024
29342
|
var rollupStatus4 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
29025
29343
|
var createVoiceMemoryMonitorIssueStore = (initial = []) => {
|
|
@@ -29272,14 +29590,14 @@ ${rows || "| none | pass | info | | | No monitors configured. |"}
|
|
|
29272
29590
|
};
|
|
29273
29591
|
var renderVoiceMonitorHTML = (report, options = {}) => {
|
|
29274
29592
|
const title = options.title ?? "Voice Monitors";
|
|
29275
|
-
const runs = report.runs.map((run) => `<tr><td>${
|
|
29276
|
-
const issues = report.issues.map((issue) => `<li><strong>${
|
|
29277
|
-
const snippet =
|
|
29593
|
+
const runs = report.runs.map((run) => `<tr><td>${escapeHtml43(run.label)}</td><td class="${escapeHtml43(run.status)}">${escapeHtml43(run.status)}</td><td>${escapeHtml43(run.severity)}</td><td>${escapeHtml43(String(run.value ?? ""))}</td><td>${escapeHtml43(String(run.threshold ?? ""))}</td><td>${escapeHtml43(run.detail ?? "")}</td></tr>`).join("");
|
|
29594
|
+
const issues = report.issues.map((issue) => `<li><strong>${escapeHtml43(issue.label)}</strong> <span class="${escapeHtml43(issue.status)}">${escapeHtml43(issue.status)}</span> ${escapeHtml43(issue.detail ?? "")}</li>`).join("");
|
|
29595
|
+
const snippet = escapeHtml43(`app.use(createVoiceMonitorRoutes({
|
|
29278
29596
|
evidence,
|
|
29279
29597
|
issueStore,
|
|
29280
29598
|
monitors: [defineVoiceMonitor(...)]
|
|
29281
29599
|
}));`);
|
|
29282
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
29600
|
+
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:#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>${escapeHtml43(title)}</h1><p class="pill ${escapeHtml43(report.status)}">Status: ${escapeHtml43(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>`;
|
|
29283
29601
|
};
|
|
29284
29602
|
var actorFromRequest = async (request) => {
|
|
29285
29603
|
if (!request.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -29303,7 +29621,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
29303
29621
|
monitors: options.monitors,
|
|
29304
29622
|
now: options.now
|
|
29305
29623
|
});
|
|
29306
|
-
const routes = new
|
|
29624
|
+
const routes = new Elysia46({
|
|
29307
29625
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
29308
29626
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
29309
29627
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -29350,7 +29668,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
29350
29668
|
};
|
|
29351
29669
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
29352
29670
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
29353
|
-
return new
|
|
29671
|
+
return new Elysia46({
|
|
29354
29672
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
29355
29673
|
}).get(path, () => ({
|
|
29356
29674
|
isRunning: options.runner.isRunning()
|
|
@@ -29726,8 +30044,8 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
29726
30044
|
};
|
|
29727
30045
|
};
|
|
29728
30046
|
// src/providerStackRecommendations.ts
|
|
29729
|
-
import { Elysia as
|
|
29730
|
-
var
|
|
30047
|
+
import { Elysia as Elysia47 } from "elysia";
|
|
30048
|
+
var escapeHtml44 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
29731
30049
|
var profileProviderPriorities = {
|
|
29732
30050
|
"meeting-recorder": {
|
|
29733
30051
|
llm: ["openai", "anthropic", "gemini"],
|
|
@@ -29839,12 +30157,12 @@ var recommendVoiceProviderStack = (input) => {
|
|
|
29839
30157
|
};
|
|
29840
30158
|
};
|
|
29841
30159
|
var rollupContractStatus = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
|
|
29842
|
-
var
|
|
30160
|
+
var statusRank3 = {
|
|
29843
30161
|
pass: 0,
|
|
29844
30162
|
warn: 1,
|
|
29845
30163
|
fail: 2
|
|
29846
30164
|
};
|
|
29847
|
-
var statusExceeds = (actual, max) =>
|
|
30165
|
+
var statusExceeds = (actual, max) => statusRank3[actual] > statusRank3[max];
|
|
29848
30166
|
var buildVoiceProviderContractMatrix = (input) => {
|
|
29849
30167
|
const rows = input.contracts.map((contract) => {
|
|
29850
30168
|
const configured = contract.configured !== false;
|
|
@@ -30046,17 +30364,17 @@ var resolveProviderContractMatrixInput = async (matrix) => typeof matrix === "fu
|
|
|
30046
30364
|
var renderVoiceProviderContractMatrixHTML = (report, options = {}) => {
|
|
30047
30365
|
const title = options.title ?? "Voice Provider Contract Matrix";
|
|
30048
30366
|
const rows = report.rows.map((row) => {
|
|
30049
|
-
const checks = row.checks.map((check) => `<li class="${
|
|
30050
|
-
return `<article class="row ${
|
|
30367
|
+
const checks = row.checks.map((check) => `<li class="${escapeHtml44(check.status)}"><strong>${escapeHtml44(check.label)}</strong><span>${escapeHtml44(check.detail ?? check.status)}</span>${check.remediation ? `<em>${check.remediation.href ? `<a href="${escapeHtml44(check.remediation.href)}">${escapeHtml44(check.remediation.label)}</a>` : escapeHtml44(check.remediation.label)}: ${escapeHtml44(check.remediation.detail)}</em>` : ""}</li>`).join("");
|
|
30368
|
+
return `<article class="row ${escapeHtml44(row.status)}">
|
|
30051
30369
|
<div>
|
|
30052
|
-
<p class="eyebrow">${
|
|
30053
|
-
<h2>${
|
|
30054
|
-
<p class="status ${
|
|
30370
|
+
<p class="eyebrow">${escapeHtml44(row.kind)}${row.selected ? " \xB7 selected" : ""}</p>
|
|
30371
|
+
<h2>${escapeHtml44(row.provider)}</h2>
|
|
30372
|
+
<p class="status ${escapeHtml44(row.status)}">${escapeHtml44(row.status.toUpperCase())}</p>
|
|
30055
30373
|
</div>
|
|
30056
30374
|
<ul>${checks}</ul>
|
|
30057
30375
|
</article>`;
|
|
30058
30376
|
}).join("");
|
|
30059
|
-
const snippet =
|
|
30377
|
+
const snippet = escapeHtml44(`const providerContracts = () =>
|
|
30060
30378
|
createVoiceProviderContractMatrixPreset('phone-agent', {
|
|
30061
30379
|
env: process.env,
|
|
30062
30380
|
providers: {
|
|
@@ -30077,7 +30395,7 @@ createVoiceProductionReadinessRoutes({
|
|
|
30077
30395
|
providerContractMatrix: () =>
|
|
30078
30396
|
buildVoiceProviderContractMatrix(providerContracts())
|
|
30079
30397
|
});`);
|
|
30080
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30398
|
+
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:#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>${escapeHtml44(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>`;
|
|
30081
30399
|
};
|
|
30082
30400
|
var createVoiceProviderContractMatrixJSONHandler = (matrix) => async () => buildVoiceProviderContractMatrix(await resolveProviderContractMatrixInput(matrix));
|
|
30083
30401
|
var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
@@ -30092,7 +30410,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
30092
30410
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
30093
30411
|
const path = options.path ?? "/api/provider-contracts";
|
|
30094
30412
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
30095
|
-
const routes = new
|
|
30413
|
+
const routes = new Elysia47({
|
|
30096
30414
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
30097
30415
|
});
|
|
30098
30416
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -30210,7 +30528,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
30210
30528
|
return assertion;
|
|
30211
30529
|
};
|
|
30212
30530
|
// src/opsConsoleRoutes.ts
|
|
30213
|
-
import { Elysia as
|
|
30531
|
+
import { Elysia as Elysia48 } from "elysia";
|
|
30214
30532
|
var DEFAULT_LINKS = [
|
|
30215
30533
|
{
|
|
30216
30534
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -30245,7 +30563,7 @@ var DEFAULT_LINKS = [
|
|
|
30245
30563
|
label: "Handoffs"
|
|
30246
30564
|
}
|
|
30247
30565
|
];
|
|
30248
|
-
var
|
|
30566
|
+
var escapeHtml45 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30249
30567
|
var countProviderStatuses = (providers) => {
|
|
30250
30568
|
const degradedStatuses = new Set(["degraded", "rate-limited", "suppressed"]);
|
|
30251
30569
|
const healthy = providers.filter((provider) => provider.status === "healthy").length;
|
|
@@ -30314,20 +30632,20 @@ var buildVoiceOpsConsoleReport = async (options) => {
|
|
|
30314
30632
|
trace
|
|
30315
30633
|
};
|
|
30316
30634
|
};
|
|
30317
|
-
var renderMetricCard = (input) => `<article class="metric"><span>${
|
|
30635
|
+
var renderMetricCard = (input) => `<article class="metric"><span>${escapeHtml45(input.label)}</span><strong>${escapeHtml45(String(input.value))}</strong>${input.status ? `<p class="${escapeHtml45(input.status)}">${escapeHtml45(input.status)}</p>` : ""}${input.href ? `<a href="${escapeHtml45(input.href)}">Open</a>` : ""}</article>`;
|
|
30318
30636
|
var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
30319
30637
|
const links = report.links.map((link) => `<article class="surface">
|
|
30320
|
-
<div><h2>${
|
|
30321
|
-
<p><a href="${
|
|
30638
|
+
<div><h2>${escapeHtml45(link.label)}</h2>${link.description ? `<p>${escapeHtml45(link.description)}</p>` : ""}</div>
|
|
30639
|
+
<p><a href="${escapeHtml45(link.href)}">Open ${escapeHtml45(link.label)}</a>${link.statusHref ? ` \xB7 <a href="${escapeHtml45(link.statusHref)}">Status</a>` : ""}</p>
|
|
30322
30640
|
</article>`).join("");
|
|
30323
|
-
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${
|
|
30324
|
-
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${
|
|
30641
|
+
const sessions = report.recentSessions.length ? report.recentSessions.map((session) => `<tr><td>${escapeHtml45(session.sessionId)}</td><td>${escapeHtml45(session.status)}</td><td>${session.turnCount}</td><td>${session.errorCount}</td><td>${session.replayHref ? `<a href="${escapeHtml45(session.replayHref)}">Replay</a>` : ""}</td></tr>`).join("") : '<tr><td colspan="5">No sessions yet.</td></tr>';
|
|
30642
|
+
const routing = report.recentRoutingEvents.length ? report.recentRoutingEvents.map((event) => `<tr><td>${escapeHtml45(event.kind)}</td><td>${escapeHtml45(event.provider ?? "unknown")}</td><td>${escapeHtml45(event.status ?? "unknown")}</td><td>${event.elapsedMs ?? 0}ms</td><td>${escapeHtml45(event.sessionId)}</td></tr>`).join("") : '<tr><td colspan="5">No provider routing events yet.</td></tr>';
|
|
30325
30643
|
const title = options.title ?? "AbsoluteJS Voice Ops Console";
|
|
30326
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
30644
|
+
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;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>${escapeHtml45(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 ${escapeHtml45(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>`;
|
|
30327
30645
|
};
|
|
30328
30646
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
30329
30647
|
const path = options.path ?? "/ops-console";
|
|
30330
|
-
const routes = new
|
|
30648
|
+
const routes = new Elysia48({
|
|
30331
30649
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
30332
30650
|
});
|
|
30333
30651
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -30344,7 +30662,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
30344
30662
|
return routes;
|
|
30345
30663
|
};
|
|
30346
30664
|
// src/incidentBundle.ts
|
|
30347
|
-
import { Elysia as
|
|
30665
|
+
import { Elysia as Elysia49 } from "elysia";
|
|
30348
30666
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
30349
30667
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
30350
30668
|
return false;
|
|
@@ -30545,7 +30863,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
30545
30863
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
30546
30864
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
30547
30865
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
30548
|
-
const routes = new
|
|
30866
|
+
const routes = new Elysia49({
|
|
30549
30867
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
30550
30868
|
});
|
|
30551
30869
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -30746,19 +31064,19 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
30746
31064
|
};
|
|
30747
31065
|
};
|
|
30748
31066
|
// src/opsStatusRoutes.ts
|
|
30749
|
-
import { Elysia as
|
|
30750
|
-
var
|
|
31067
|
+
import { Elysia as Elysia50 } from "elysia";
|
|
31068
|
+
var escapeHtml46 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
30751
31069
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
30752
31070
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
30753
31071
|
const surfaces = Object.entries(report.surfaces).map(([key, surface]) => {
|
|
30754
31072
|
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;
|
|
30755
|
-
return `<article class="surface ${
|
|
31073
|
+
return `<article class="surface ${escapeHtml46(surface.status)}"><span>${escapeHtml46(surface.status.toUpperCase())}</span><h2>${escapeHtml46(key)}</h2><strong>${escapeHtml46(value)}</strong></article>`;
|
|
30756
31074
|
}).join("");
|
|
30757
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31075
|
+
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:#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>${escapeHtml46(title)}</h1><p>Compact pass/fail status for framework widgets, demos, and small customer-facing health badges.</p><p class="status ${escapeHtml46(report.status)}">Overall: ${escapeHtml46(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>`;
|
|
30758
31076
|
};
|
|
30759
31077
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
30760
31078
|
const path = options.path ?? "/api/voice/ops-status";
|
|
30761
|
-
const routes = new
|
|
31079
|
+
const routes = new Elysia50({
|
|
30762
31080
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
30763
31081
|
});
|
|
30764
31082
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -30823,11 +31141,11 @@ var withTimeout2 = async (input) => {
|
|
|
30823
31141
|
}
|
|
30824
31142
|
}
|
|
30825
31143
|
};
|
|
30826
|
-
var
|
|
31144
|
+
var isVoiceProviderRoutingPolicyPreset2 = (policy) => policy === "balanced" || policy === "cost-cap" || policy === "cost-first" || policy === "latency-first" || policy === "quality-first";
|
|
30827
31145
|
var createResolver = (options) => {
|
|
30828
31146
|
const providerIds = Object.keys(options.adapters);
|
|
30829
31147
|
const firstProvider = providerIds[0];
|
|
30830
|
-
const policy = typeof options.policy === "string" ?
|
|
31148
|
+
const policy = typeof options.policy === "string" ? isVoiceProviderRoutingPolicyPreset2(options.policy) ? resolveVoiceProviderRoutingPolicyPreset(options.policy) : {
|
|
30831
31149
|
strategy: options.policy
|
|
30832
31150
|
} : options.policy;
|
|
30833
31151
|
const strategy = policy?.strategy ?? "prefer-selected";
|
|
@@ -31191,8 +31509,8 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
31191
31509
|
};
|
|
31192
31510
|
};
|
|
31193
31511
|
// src/traceDeliveryRoutes.ts
|
|
31194
|
-
import { Elysia as
|
|
31195
|
-
var
|
|
31512
|
+
import { Elysia as Elysia51 } from "elysia";
|
|
31513
|
+
var escapeHtml47 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
31196
31514
|
var getString19 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
31197
31515
|
var getNumber11 = (value) => {
|
|
31198
31516
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -31273,14 +31591,14 @@ var renderSinkResults2 = (delivery) => {
|
|
|
31273
31591
|
if (entries.length === 0) {
|
|
31274
31592
|
return "<p>No sink delivery attempts recorded yet.</p>";
|
|
31275
31593
|
}
|
|
31276
|
-
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${
|
|
31594
|
+
return `<ul>${entries.map(([sinkId, result]) => `<li><strong>${escapeHtml47(sinkId)}</strong>: ${escapeHtml47(result.status)}${result.deliveredTo ? ` to ${escapeHtml47(result.deliveredTo)}` : ""}${result.error ? ` (${escapeHtml47(result.error)})` : ""}</li>`).join("")}</ul>`;
|
|
31277
31595
|
};
|
|
31278
|
-
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${
|
|
31596
|
+
var renderEventList2 = (delivery) => delivery.events.length === 0 ? "<p>No trace events in this delivery.</p>" : `<ul>${delivery.events.map((event) => `<li>${escapeHtml47(event.type)} <small>${escapeHtml47(event.id)}</small>${event.sessionId ? ` session=${escapeHtml47(event.sessionId)}` : ""}</li>`).join("")}</ul>`;
|
|
31279
31597
|
var renderVoiceTraceDeliveryHTML = (report, options = {}) => {
|
|
31280
31598
|
const title = options.title ?? "AbsoluteJS Voice Trace Deliveries";
|
|
31281
|
-
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${
|
|
31282
|
-
const rows = report.deliveries.map((delivery) => `<article class="delivery ${
|
|
31283
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>${
|
|
31599
|
+
const drainAction = options.workerPath === false ? "" : `<form method="post" action="${escapeHtml47(options.workerPath ?? "/api/voice-trace-deliveries/drain")}"><button type="submit">Drain trace deliveries</button></form>`;
|
|
31600
|
+
const rows = report.deliveries.map((delivery) => `<article class="delivery ${escapeHtml47(delivery.deliveryStatus)}"><div class="head"><div><span>${escapeHtml47(delivery.deliveryStatus)}</span><h2>${escapeHtml47(delivery.id)}</h2><p>${escapeHtml47(new Date(delivery.createdAt).toLocaleString())}${delivery.deliveredAt ? ` \xB7 delivered ${escapeHtml47(new Date(delivery.deliveredAt).toLocaleString())}` : ""}</p></div><strong>${String(delivery.deliveryAttempts ?? 0)} attempt(s)</strong></div>${delivery.deliveryError ? `<p class="error">${escapeHtml47(delivery.deliveryError)}</p>` : ""}<h3>Sinks</h3>${renderSinkResults2(delivery)}<h3>Events</h3>${renderEventList2(delivery)}</article>`).join("");
|
|
31601
|
+
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:#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>${escapeHtml47(title)}</h1><p>Checked ${escapeHtml47(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>`;
|
|
31284
31602
|
};
|
|
31285
31603
|
var createVoiceTraceDeliveryJSONHandler = (options) => async ({ query }) => buildVoiceTraceDeliveryReport(options, resolveVoiceTraceDeliveryFilter(query, options.filter));
|
|
31286
31604
|
var createVoiceTraceDeliveryHTMLHandler = (options) => async ({ query }) => {
|
|
@@ -31300,7 +31618,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
31300
31618
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
31301
31619
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
31302
31620
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
31303
|
-
const routes = new
|
|
31621
|
+
const routes = new Elysia51({
|
|
31304
31622
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
31305
31623
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
31306
31624
|
if (htmlPath !== false) {
|
|
@@ -31397,7 +31715,7 @@ var createVoiceMemoryStore = () => {
|
|
|
31397
31715
|
return { get, getOrCreate, list, remove, set };
|
|
31398
31716
|
};
|
|
31399
31717
|
// src/opsWebhook.ts
|
|
31400
|
-
import { Elysia as
|
|
31718
|
+
import { Elysia as Elysia52 } from "elysia";
|
|
31401
31719
|
var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
31402
31720
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
31403
31721
|
const encoder = new TextEncoder;
|
|
@@ -31527,7 +31845,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
31527
31845
|
};
|
|
31528
31846
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
31529
31847
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
31530
|
-
return new
|
|
31848
|
+
return new Elysia52().post(path, async ({ body, request, set }) => {
|
|
31531
31849
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
31532
31850
|
if (options.signingSecret) {
|
|
31533
31851
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -31982,7 +32300,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
31982
32300
|
};
|
|
31983
32301
|
};
|
|
31984
32302
|
// src/postCallAnalysis.ts
|
|
31985
|
-
import { Elysia as
|
|
32303
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
31986
32304
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
31987
32305
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
31988
32306
|
var getPathValue3 = (source, path) => {
|
|
@@ -32161,7 +32479,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
32161
32479
|
};
|
|
32162
32480
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
32163
32481
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
32164
|
-
const routes = new
|
|
32482
|
+
const routes = new Elysia53({
|
|
32165
32483
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
32166
32484
|
});
|
|
32167
32485
|
routes.get(path, async ({ query }) => {
|
|
@@ -32186,7 +32504,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
32186
32504
|
return routes;
|
|
32187
32505
|
};
|
|
32188
32506
|
// src/guardrails.ts
|
|
32189
|
-
import { Elysia as
|
|
32507
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
32190
32508
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
32191
32509
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
32192
32510
|
var matchesRule = async (rule, input) => {
|
|
@@ -32488,7 +32806,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
32488
32806
|
};
|
|
32489
32807
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
32490
32808
|
const path = options.path ?? "/api/voice/guardrails";
|
|
32491
|
-
const routes = new
|
|
32809
|
+
const routes = new Elysia54({
|
|
32492
32810
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
32493
32811
|
});
|
|
32494
32812
|
routes.all(path, async ({ request }) => {
|
|
@@ -33015,6 +33333,8 @@ export {
|
|
|
33015
33333
|
renderVoiceQualityHTML,
|
|
33016
33334
|
renderVoiceProviderSloMarkdown,
|
|
33017
33335
|
renderVoiceProviderSloHTML,
|
|
33336
|
+
renderVoiceProviderOrchestrationMarkdown,
|
|
33337
|
+
renderVoiceProviderOrchestrationHTML,
|
|
33018
33338
|
renderVoiceProviderHealthHTML,
|
|
33019
33339
|
renderVoiceProviderContractMatrixHTML,
|
|
33020
33340
|
renderVoiceProviderCapabilityHTML,
|
|
@@ -33231,6 +33551,8 @@ export {
|
|
|
33231
33551
|
createVoiceQualityRoutes,
|
|
33232
33552
|
createVoiceProviderSloRoutes,
|
|
33233
33553
|
createVoiceProviderRouter,
|
|
33554
|
+
createVoiceProviderOrchestrationRoutes,
|
|
33555
|
+
createVoiceProviderOrchestrationProfile,
|
|
33234
33556
|
createVoiceProviderHealthRoutes,
|
|
33235
33557
|
createVoiceProviderHealthJSONHandler,
|
|
33236
33558
|
createVoiceProviderHealthHTMLHandler,
|
|
@@ -33426,6 +33748,7 @@ export {
|
|
|
33426
33748
|
buildVoiceSloReadinessThresholdReport,
|
|
33427
33749
|
buildVoiceSloCalibrationReport,
|
|
33428
33750
|
buildVoiceProviderSloReport,
|
|
33751
|
+
buildVoiceProviderOrchestrationReport,
|
|
33429
33752
|
buildVoiceProviderContractMatrix,
|
|
33430
33753
|
buildVoiceProofTrendReport,
|
|
33431
33754
|
buildVoiceProductionReadinessReport,
|