@absolutejs/voice 0.0.22-beta.167 → 0.0.22-beta.168
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +177 -58
- package/dist/angular/voice-provider-contracts.service.d.ts +12 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +228 -47
- package/dist/client/providerContracts.d.ts +19 -0
- package/dist/client/providerContractsWidget.d.ts +32 -0
- package/dist/react/VoiceProviderContracts.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +472 -195
- package/dist/react/useVoiceProviderContracts.d.ts +8 -0
- package/dist/svelte/createVoiceProviderContracts.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +264 -78
- package/dist/vue/VoiceProviderContracts.d.ts +21 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +446 -170
- package/dist/vue/useVoiceProviderContracts.d.ts +9 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -3156,6 +3156,80 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
3156
3156
|
}
|
|
3157
3157
|
};
|
|
3158
3158
|
};
|
|
3159
|
+
// src/client/providerContracts.ts
|
|
3160
|
+
var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
|
|
3161
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
3162
|
+
const response = await fetchImpl(path);
|
|
3163
|
+
if (!response.ok) {
|
|
3164
|
+
throw new Error(`Voice provider contracts failed: HTTP ${response.status}`);
|
|
3165
|
+
}
|
|
3166
|
+
return await response.json();
|
|
3167
|
+
};
|
|
3168
|
+
var createVoiceProviderContractsStore = (path = "/api/provider-contracts", options = {}) => {
|
|
3169
|
+
const listeners = new Set;
|
|
3170
|
+
let closed = false;
|
|
3171
|
+
let timer;
|
|
3172
|
+
let snapshot = {
|
|
3173
|
+
error: null,
|
|
3174
|
+
isLoading: false
|
|
3175
|
+
};
|
|
3176
|
+
const emit = () => {
|
|
3177
|
+
for (const listener of listeners) {
|
|
3178
|
+
listener();
|
|
3179
|
+
}
|
|
3180
|
+
};
|
|
3181
|
+
const refresh = async () => {
|
|
3182
|
+
if (closed) {
|
|
3183
|
+
return snapshot.report;
|
|
3184
|
+
}
|
|
3185
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
3186
|
+
emit();
|
|
3187
|
+
try {
|
|
3188
|
+
const report = await fetchVoiceProviderContracts(path, options);
|
|
3189
|
+
snapshot = {
|
|
3190
|
+
error: null,
|
|
3191
|
+
isLoading: false,
|
|
3192
|
+
report,
|
|
3193
|
+
updatedAt: Date.now()
|
|
3194
|
+
};
|
|
3195
|
+
emit();
|
|
3196
|
+
return report;
|
|
3197
|
+
} catch (error) {
|
|
3198
|
+
snapshot = {
|
|
3199
|
+
...snapshot,
|
|
3200
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3201
|
+
isLoading: false
|
|
3202
|
+
};
|
|
3203
|
+
emit();
|
|
3204
|
+
throw error;
|
|
3205
|
+
}
|
|
3206
|
+
};
|
|
3207
|
+
const close = () => {
|
|
3208
|
+
closed = true;
|
|
3209
|
+
if (timer) {
|
|
3210
|
+
clearInterval(timer);
|
|
3211
|
+
timer = undefined;
|
|
3212
|
+
}
|
|
3213
|
+
listeners.clear();
|
|
3214
|
+
};
|
|
3215
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
3216
|
+
timer = setInterval(() => {
|
|
3217
|
+
refresh().catch(() => {});
|
|
3218
|
+
}, options.intervalMs);
|
|
3219
|
+
}
|
|
3220
|
+
return {
|
|
3221
|
+
close,
|
|
3222
|
+
getServerSnapshot: () => snapshot,
|
|
3223
|
+
getSnapshot: () => snapshot,
|
|
3224
|
+
refresh,
|
|
3225
|
+
subscribe: (listener) => {
|
|
3226
|
+
listeners.add(listener);
|
|
3227
|
+
return () => {
|
|
3228
|
+
listeners.delete(listener);
|
|
3229
|
+
};
|
|
3230
|
+
}
|
|
3231
|
+
};
|
|
3232
|
+
};
|
|
3159
3233
|
// src/client/turnQuality.ts
|
|
3160
3234
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
3161
3235
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -3939,10 +4013,110 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
3939
4013
|
}
|
|
3940
4014
|
});
|
|
3941
4015
|
};
|
|
3942
|
-
// src/client/
|
|
3943
|
-
var DEFAULT_TITLE7 = "
|
|
3944
|
-
var DEFAULT_DESCRIPTION7 = "
|
|
4016
|
+
// src/client/providerContractsWidget.ts
|
|
4017
|
+
var DEFAULT_TITLE7 = "Provider Contracts";
|
|
4018
|
+
var DEFAULT_DESCRIPTION7 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
3945
4019
|
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4020
|
+
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
4021
|
+
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
4022
|
+
var contractDetail = (row) => {
|
|
4023
|
+
const failing = row.checks.filter((check) => check.status !== "pass");
|
|
4024
|
+
if (failing.length === 0) {
|
|
4025
|
+
return "Provider contract is production-ready.";
|
|
4026
|
+
}
|
|
4027
|
+
return failing.map((check) => `${check.label}: ${check.detail ?? check.status}`).join(" ");
|
|
4028
|
+
};
|
|
4029
|
+
var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
4030
|
+
const rows = (snapshot.report?.rows ?? []).map((row) => ({
|
|
4031
|
+
...row,
|
|
4032
|
+
detail: contractDetail(row),
|
|
4033
|
+
label: `${formatProvider3(row.provider)} ${row.kind.toUpperCase()}`,
|
|
4034
|
+
rows: [
|
|
4035
|
+
{ label: "Status", value: formatStatus3(row.status) },
|
|
4036
|
+
{ label: "Selected", value: row.selected ? "Yes" : "No" },
|
|
4037
|
+
{ label: "Configured", value: row.configured ? "Yes" : "No" },
|
|
4038
|
+
{
|
|
4039
|
+
label: "Checks",
|
|
4040
|
+
value: row.checks.map((check) => `${check.label}: ${formatStatus3(check.status)}`).join(", ")
|
|
4041
|
+
}
|
|
4042
|
+
]
|
|
4043
|
+
}));
|
|
4044
|
+
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
4045
|
+
return {
|
|
4046
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
4047
|
+
error: snapshot.error,
|
|
4048
|
+
isLoading: snapshot.isLoading,
|
|
4049
|
+
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
4050
|
+
rows,
|
|
4051
|
+
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
4052
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
4053
|
+
updatedAt: snapshot.updatedAt
|
|
4054
|
+
};
|
|
4055
|
+
};
|
|
4056
|
+
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
4057
|
+
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
4058
|
+
const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml9(row.status)}">
|
|
4059
|
+
<header>
|
|
4060
|
+
<strong>${escapeHtml9(row.label)}</strong>
|
|
4061
|
+
<span>${escapeHtml9(formatStatus3(row.status))}</span>
|
|
4062
|
+
</header>
|
|
4063
|
+
<p>${escapeHtml9(row.detail)}</p>
|
|
4064
|
+
<dl>${row.rows.map((item) => `<div>
|
|
4065
|
+
<dt>${escapeHtml9(item.label)}</dt>
|
|
4066
|
+
<dd>${escapeHtml9(item.value)}</dd>
|
|
4067
|
+
</div>`).join("")}</dl>
|
|
4068
|
+
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
4069
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml9(model.status)}">
|
|
4070
|
+
<header class="absolute-voice-provider-contracts__header">
|
|
4071
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml9(model.title)}</span>
|
|
4072
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml9(model.label)}</strong>
|
|
4073
|
+
</header>
|
|
4074
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml9(model.description)}</p>
|
|
4075
|
+
${rows}
|
|
4076
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
4077
|
+
</section>`;
|
|
4078
|
+
};
|
|
4079
|
+
var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
|
|
4080
|
+
var mountVoiceProviderContracts = (element, path = "/api/provider-contracts", options = {}) => {
|
|
4081
|
+
const store = createVoiceProviderContractsStore(path, options);
|
|
4082
|
+
const render = () => {
|
|
4083
|
+
element.innerHTML = renderVoiceProviderContractsHTML(store.getSnapshot(), options);
|
|
4084
|
+
};
|
|
4085
|
+
const unsubscribe = store.subscribe(render);
|
|
4086
|
+
render();
|
|
4087
|
+
store.refresh().catch(() => {});
|
|
4088
|
+
return {
|
|
4089
|
+
close: () => {
|
|
4090
|
+
unsubscribe();
|
|
4091
|
+
store.close();
|
|
4092
|
+
},
|
|
4093
|
+
refresh: store.refresh
|
|
4094
|
+
};
|
|
4095
|
+
};
|
|
4096
|
+
var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-contracts") => {
|
|
4097
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
4098
|
+
return;
|
|
4099
|
+
}
|
|
4100
|
+
customElements.define(tagName, class AbsoluteVoiceProviderContractsElement extends HTMLElement {
|
|
4101
|
+
mounted;
|
|
4102
|
+
connectedCallback() {
|
|
4103
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
4104
|
+
this.mounted = mountVoiceProviderContracts(this, this.getAttribute("path") ?? "/api/provider-contracts", {
|
|
4105
|
+
description: this.getAttribute("description") ?? undefined,
|
|
4106
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
4107
|
+
title: this.getAttribute("title") ?? undefined
|
|
4108
|
+
});
|
|
4109
|
+
}
|
|
4110
|
+
disconnectedCallback() {
|
|
4111
|
+
this.mounted?.close();
|
|
4112
|
+
this.mounted = undefined;
|
|
4113
|
+
}
|
|
4114
|
+
});
|
|
4115
|
+
};
|
|
4116
|
+
// src/client/turnQualityWidget.ts
|
|
4117
|
+
var DEFAULT_TITLE8 = "Turn Quality";
|
|
4118
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
4119
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3946
4120
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3947
4121
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3948
4122
|
var getTurnDetail = (turn) => {
|
|
@@ -3980,37 +4154,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3980
4154
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3981
4155
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3982
4156
|
return {
|
|
3983
|
-
description: options.description ??
|
|
4157
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
3984
4158
|
error: snapshot.error,
|
|
3985
4159
|
isLoading: snapshot.isLoading,
|
|
3986
4160
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3987
4161
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3988
|
-
title: options.title ??
|
|
4162
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
3989
4163
|
turns,
|
|
3990
4164
|
updatedAt: snapshot.updatedAt
|
|
3991
4165
|
};
|
|
3992
4166
|
};
|
|
3993
4167
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3994
4168
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3995
|
-
const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${
|
|
4169
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml10(turn.status)}">
|
|
3996
4170
|
<header>
|
|
3997
|
-
<strong>${
|
|
3998
|
-
<span>${
|
|
4171
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
4172
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
3999
4173
|
</header>
|
|
4000
|
-
<p>${
|
|
4174
|
+
<p>${escapeHtml10(turn.detail)}</p>
|
|
4001
4175
|
<dl>${turn.rows.map((row) => `<div>
|
|
4002
|
-
<dt>${
|
|
4003
|
-
<dd>${
|
|
4176
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
4177
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
4004
4178
|
</div>`).join("")}</dl>
|
|
4005
4179
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
4006
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
4180
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml10(model.status)}">
|
|
4007
4181
|
<header class="absolute-voice-turn-quality__header">
|
|
4008
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
4009
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
4182
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml10(model.title)}</span>
|
|
4183
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml10(model.label)}</strong>
|
|
4010
4184
|
</header>
|
|
4011
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
4185
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml10(model.description)}</p>
|
|
4012
4186
|
${turns}
|
|
4013
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
4187
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
4014
4188
|
</section>`;
|
|
4015
4189
|
};
|
|
4016
4190
|
var getVoiceTurnQualityCSS = () => `.absolute-voice-turn-quality{border:1px solid #e4d1a3;border-radius:20px;background:#fff9eb;color:#17120a;padding:18px;box-shadow:0 18px 40px rgba(73,48,14,.12);font-family:inherit}.absolute-voice-turn-quality--error,.absolute-voice-turn-quality--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-turn-quality__header,.absolute-voice-turn-quality__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-turn-quality__eyebrow{color:#8a5a0a;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-turn-quality__label{font-size:24px;line-height:1}.absolute-voice-turn-quality__description,.absolute-voice-turn-quality__turn p,.absolute-voice-turn-quality__turn dt,.absolute-voice-turn-quality__empty{color:#5a4930}.absolute-voice-turn-quality__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-turn-quality__turn{background:#fff;border:1px solid #f0dfba;border-radius:16px;padding:14px}.absolute-voice-turn-quality__turn--pass{border-color:#86efac}.absolute-voice-turn-quality__turn--warn,.absolute-voice-turn-quality__turn--unknown{border-color:#fbbf24}.absolute-voice-turn-quality__turn--fail{border-color:#f2a7a7}.absolute-voice-turn-quality__turn p{margin:10px 0}.absolute-voice-turn-quality__turn dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-turn-quality__turn div{background:#fff9eb;border:1px solid #f0dfba;border-radius:12px;padding:8px}.absolute-voice-turn-quality__turn dt{font-size:12px}.absolute-voice-turn-quality__turn dd{font-weight:800;margin:4px 0 0}.absolute-voice-turn-quality__empty{margin:14px 0 0}.absolute-voice-turn-quality__error{color:#9f1239;font-weight:700}`;
|
|
@@ -4051,10 +4225,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
4051
4225
|
});
|
|
4052
4226
|
};
|
|
4053
4227
|
// src/client/turnLatencyWidget.ts
|
|
4054
|
-
var
|
|
4055
|
-
var
|
|
4228
|
+
var DEFAULT_TITLE9 = "Turn Latency";
|
|
4229
|
+
var DEFAULT_DESCRIPTION9 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
4056
4230
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
4057
|
-
var
|
|
4231
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4058
4232
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
4059
4233
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
4060
4234
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -4068,39 +4242,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
4068
4242
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
4069
4243
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
4070
4244
|
return {
|
|
4071
|
-
description: options.description ??
|
|
4245
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
4072
4246
|
error: snapshot.error,
|
|
4073
4247
|
isLoading: snapshot.isLoading,
|
|
4074
4248
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
4075
4249
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
4076
4250
|
showProofAction: Boolean(options.proofPath),
|
|
4077
4251
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
4078
|
-
title: options.title ??
|
|
4252
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
4079
4253
|
turns,
|
|
4080
4254
|
updatedAt: snapshot.updatedAt
|
|
4081
4255
|
};
|
|
4082
4256
|
};
|
|
4083
4257
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
4084
4258
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
4085
|
-
const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${
|
|
4259
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml11(turn.status)}">
|
|
4086
4260
|
<header>
|
|
4087
|
-
<strong>${
|
|
4088
|
-
<span>${
|
|
4261
|
+
<strong>${escapeHtml11(turn.label)}</strong>
|
|
4262
|
+
<span>${escapeHtml11(turn.status)}</span>
|
|
4089
4263
|
</header>
|
|
4090
4264
|
<dl>${turn.rows.map((row) => `<div>
|
|
4091
|
-
<dt>${
|
|
4092
|
-
<dd>${
|
|
4265
|
+
<dt>${escapeHtml11(row.label)}</dt>
|
|
4266
|
+
<dd>${escapeHtml11(row.value)}</dd>
|
|
4093
4267
|
</div>`).join("")}</dl>
|
|
4094
4268
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
4095
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
4269
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml11(model.status)}">
|
|
4096
4270
|
<header class="absolute-voice-turn-latency__header">
|
|
4097
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
4098
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
4271
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml11(model.title)}</span>
|
|
4272
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml11(model.label)}</strong>
|
|
4099
4273
|
</header>
|
|
4100
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
4101
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
4274
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml11(model.description)}</p>
|
|
4275
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml11(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
4102
4276
|
${turns}
|
|
4103
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
4277
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
4104
4278
|
</section>`;
|
|
4105
4279
|
};
|
|
4106
4280
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -4150,9 +4324,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
4150
4324
|
});
|
|
4151
4325
|
};
|
|
4152
4326
|
// src/client/traceTimelineWidget.ts
|
|
4153
|
-
var
|
|
4154
|
-
var
|
|
4155
|
-
var
|
|
4327
|
+
var DEFAULT_TITLE10 = "Voice Traces";
|
|
4328
|
+
var DEFAULT_DESCRIPTION10 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
4329
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4156
4330
|
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
4157
4331
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
4158
4332
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -4166,34 +4340,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
4166
4340
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
4167
4341
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
4168
4342
|
return {
|
|
4169
|
-
description: options.description ??
|
|
4343
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
4170
4344
|
error: snapshot.error,
|
|
4171
4345
|
isLoading: snapshot.isLoading,
|
|
4172
4346
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
4173
4347
|
sessions,
|
|
4174
4348
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
4175
|
-
title: options.title ??
|
|
4349
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
4176
4350
|
updatedAt: snapshot.updatedAt
|
|
4177
4351
|
};
|
|
4178
4352
|
};
|
|
4179
4353
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
4180
4354
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
4181
|
-
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
4355
|
+
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml12(session.status)}">
|
|
4182
4356
|
<header>
|
|
4183
|
-
<strong>${
|
|
4184
|
-
<span>${
|
|
4357
|
+
<strong>${escapeHtml12(session.sessionId)}</strong>
|
|
4358
|
+
<span>${escapeHtml12(session.status)}</span>
|
|
4185
4359
|
</header>
|
|
4186
|
-
<p>${
|
|
4187
|
-
<a href="${
|
|
4360
|
+
<p>${escapeHtml12(session.label)} \xB7 ${escapeHtml12(session.durationLabel)} \xB7 ${escapeHtml12(session.providerLabel)}</p>
|
|
4361
|
+
<a href="${escapeHtml12(session.detailHref)}">Open timeline</a>
|
|
4188
4362
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
4189
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
4363
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml12(model.status)}">
|
|
4190
4364
|
<header class="absolute-voice-trace-timeline__header">
|
|
4191
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
4192
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
4365
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml12(model.title)}</span>
|
|
4366
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml12(model.label)}</strong>
|
|
4193
4367
|
</header>
|
|
4194
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
4368
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml12(model.description)}</p>
|
|
4195
4369
|
${sessions}
|
|
4196
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
4370
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
4197
4371
|
</section>`;
|
|
4198
4372
|
};
|
|
4199
4373
|
var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
|
|
@@ -4325,6 +4499,7 @@ export {
|
|
|
4325
4499
|
renderVoiceRoutingStatusHTML,
|
|
4326
4500
|
renderVoiceProviderStatusHTML,
|
|
4327
4501
|
renderVoiceProviderSimulationControlsHTML,
|
|
4502
|
+
renderVoiceProviderContractsHTML,
|
|
4328
4503
|
renderVoiceProviderCapabilitiesHTML,
|
|
4329
4504
|
renderVoiceOpsStatusHTML,
|
|
4330
4505
|
renderVoiceOpsActionHistoryWidgetHTML,
|
|
@@ -4337,6 +4512,7 @@ export {
|
|
|
4337
4512
|
mountVoiceRoutingStatus,
|
|
4338
4513
|
mountVoiceProviderStatus,
|
|
4339
4514
|
mountVoiceProviderSimulationControls,
|
|
4515
|
+
mountVoiceProviderContracts,
|
|
4340
4516
|
mountVoiceProviderCapabilities,
|
|
4341
4517
|
mountVoiceOpsStatus,
|
|
4342
4518
|
mountVoiceOpsActionHistory,
|
|
@@ -4346,6 +4522,7 @@ export {
|
|
|
4346
4522
|
getVoiceTraceTimelineCSS,
|
|
4347
4523
|
getVoiceRoutingStatusCSS,
|
|
4348
4524
|
getVoiceProviderStatusCSS,
|
|
4525
|
+
getVoiceProviderContractsCSS,
|
|
4349
4526
|
getVoiceProviderCapabilitiesCSS,
|
|
4350
4527
|
getVoiceOpsStatusLabel,
|
|
4351
4528
|
getVoiceOpsStatusCSS,
|
|
@@ -4358,6 +4535,7 @@ export {
|
|
|
4358
4535
|
fetchVoiceTraceTimeline,
|
|
4359
4536
|
fetchVoiceRoutingStatus,
|
|
4360
4537
|
fetchVoiceProviderStatus,
|
|
4538
|
+
fetchVoiceProviderContracts,
|
|
4361
4539
|
fetchVoiceProviderCapabilities,
|
|
4362
4540
|
fetchVoiceOpsStatus,
|
|
4363
4541
|
fetchVoiceOpsActionHistory,
|
|
@@ -4369,6 +4547,7 @@ export {
|
|
|
4369
4547
|
defineVoiceRoutingStatusElement,
|
|
4370
4548
|
defineVoiceProviderStatusElement,
|
|
4371
4549
|
defineVoiceProviderSimulationControlsElement,
|
|
4550
|
+
defineVoiceProviderContractsElement,
|
|
4372
4551
|
defineVoiceProviderCapabilitiesElement,
|
|
4373
4552
|
defineVoiceOpsStatusElement,
|
|
4374
4553
|
defineVoiceOpsActionCenterElement,
|
|
@@ -4388,6 +4567,8 @@ export {
|
|
|
4388
4567
|
createVoiceProviderStatusStore,
|
|
4389
4568
|
createVoiceProviderSimulationControlsViewModel,
|
|
4390
4569
|
createVoiceProviderSimulationControlsStore,
|
|
4570
|
+
createVoiceProviderContractsViewModel,
|
|
4571
|
+
createVoiceProviderContractsStore,
|
|
4391
4572
|
createVoiceProviderCapabilitiesViewModel,
|
|
4392
4573
|
createVoiceProviderCapabilitiesStore,
|
|
4393
4574
|
createVoiceOpsStatusViewModel,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { VoiceProviderContractMatrixReport } from '../providerStackRecommendations';
|
|
2
|
+
export type VoiceProviderContractsClientOptions = {
|
|
3
|
+
fetch?: typeof fetch;
|
|
4
|
+
intervalMs?: number;
|
|
5
|
+
};
|
|
6
|
+
export type VoiceProviderContractsSnapshot<TProvider extends string = string> = {
|
|
7
|
+
error: string | null;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
report?: VoiceProviderContractMatrixReport<TProvider>;
|
|
10
|
+
updatedAt?: number;
|
|
11
|
+
};
|
|
12
|
+
export declare const fetchVoiceProviderContracts: <TProvider extends string = string>(path?: string, options?: Pick<VoiceProviderContractsClientOptions, "fetch">) => Promise<VoiceProviderContractMatrixReport<TProvider>>;
|
|
13
|
+
export declare const createVoiceProviderContractsStore: <TProvider extends string = string>(path?: string, options?: VoiceProviderContractsClientOptions) => {
|
|
14
|
+
close: () => void;
|
|
15
|
+
getServerSnapshot: () => VoiceProviderContractsSnapshot<TProvider>;
|
|
16
|
+
getSnapshot: () => VoiceProviderContractsSnapshot<TProvider>;
|
|
17
|
+
refresh: () => Promise<VoiceProviderContractMatrixReport<TProvider> | undefined>;
|
|
18
|
+
subscribe: (listener: () => void) => () => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { VoiceProviderContractMatrixRow } from '../providerStackRecommendations';
|
|
2
|
+
import { type VoiceProviderContractsClientOptions, type VoiceProviderContractsSnapshot } from './providerContracts';
|
|
3
|
+
export type VoiceProviderContractRowView<TProvider extends string = string> = VoiceProviderContractMatrixRow<TProvider> & {
|
|
4
|
+
detail: string;
|
|
5
|
+
label: string;
|
|
6
|
+
rows: Array<{
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
export type VoiceProviderContractsViewModel<TProvider extends string = string> = {
|
|
12
|
+
description: string;
|
|
13
|
+
error: string | null;
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
label: string;
|
|
16
|
+
rows: VoiceProviderContractRowView<TProvider>[];
|
|
17
|
+
status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
|
|
18
|
+
title: string;
|
|
19
|
+
updatedAt?: number;
|
|
20
|
+
};
|
|
21
|
+
export type VoiceProviderContractsWidgetOptions = VoiceProviderContractsClientOptions & {
|
|
22
|
+
description?: string;
|
|
23
|
+
title?: string;
|
|
24
|
+
};
|
|
25
|
+
export declare const createVoiceProviderContractsViewModel: <TProvider extends string = string>(snapshot: VoiceProviderContractsSnapshot<TProvider>, options?: VoiceProviderContractsWidgetOptions) => VoiceProviderContractsViewModel<TProvider>;
|
|
26
|
+
export declare const renderVoiceProviderContractsHTML: <TProvider extends string = string>(snapshot: VoiceProviderContractsSnapshot<TProvider>, options?: VoiceProviderContractsWidgetOptions) => string;
|
|
27
|
+
export declare const getVoiceProviderContractsCSS: () => string;
|
|
28
|
+
export declare const mountVoiceProviderContracts: <TProvider extends string = string>(element: Element, path?: string, options?: VoiceProviderContractsWidgetOptions) => {
|
|
29
|
+
close: () => void;
|
|
30
|
+
refresh: () => Promise<import("..").VoiceProviderContractMatrixReport<TProvider> | undefined>;
|
|
31
|
+
};
|
|
32
|
+
export declare const defineVoiceProviderContractsElement: (tagName?: string) => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type VoiceProviderContractsWidgetOptions } from '../client/providerContractsWidget';
|
|
2
|
+
export type VoiceProviderContractsProps = VoiceProviderContractsWidgetOptions & {
|
|
3
|
+
className?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const VoiceProviderContracts: ({ className, path, ...options }: VoiceProviderContractsProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { VoiceOpsActionCenter } from './VoiceOpsActionCenter';
|
|
|
3
3
|
export { VoiceDeliveryRuntime } from './VoiceDeliveryRuntime';
|
|
4
4
|
export { VoiceProviderSimulationControls } from './VoiceProviderSimulationControls';
|
|
5
5
|
export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
|
|
6
|
+
export { VoiceProviderContracts } from './VoiceProviderContracts';
|
|
6
7
|
export { VoiceProviderStatus } from './VoiceProviderStatus';
|
|
7
8
|
export { VoiceRoutingStatus } from './VoiceRoutingStatus';
|
|
8
9
|
export { VoiceTraceTimeline } from './VoiceTraceTimeline';
|
|
@@ -16,6 +17,7 @@ export { useVoiceStream } from './useVoiceStream';
|
|
|
16
17
|
export { useVoiceController } from './useVoiceController';
|
|
17
18
|
export { useVoiceProviderStatus } from './useVoiceProviderStatus';
|
|
18
19
|
export { useVoiceProviderCapabilities } from './useVoiceProviderCapabilities';
|
|
20
|
+
export { useVoiceProviderContracts } from './useVoiceProviderContracts';
|
|
19
21
|
export { useVoiceProviderSimulationControls } from './useVoiceProviderSimulationControls';
|
|
20
22
|
export { useVoiceRoutingStatus } from './useVoiceRoutingStatus';
|
|
21
23
|
export { useVoiceTraceTimeline } from './useVoiceTraceTimeline';
|