@absolutejs/voice 0.0.22-beta.51 → 0.0.22-beta.53
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 +300 -37
- package/dist/angular/voice-ops-status.component.d.ts +15 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +130 -0
- package/dist/client/opsStatusWidget.d.ts +40 -0
- package/dist/react/VoiceOpsStatus.d.ts +6 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +222 -1
- package/dist/svelte/createVoiceOpsStatus.d.ts +9 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +138 -0
- package/dist/vue/VoiceOpsStatus.d.ts +30 -0
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +196 -3
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -167,6 +167,226 @@ var useVoiceAppKitStatus = (path = "/app-kit/status", options = {}) => {
|
|
|
167
167
|
refresh: store.refresh
|
|
168
168
|
};
|
|
169
169
|
};
|
|
170
|
+
|
|
171
|
+
// src/client/opsStatusWidget.ts
|
|
172
|
+
var DEFAULT_TITLE = "Voice Ops Status";
|
|
173
|
+
var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from the AbsoluteJS voice app kit.";
|
|
174
|
+
var SURFACE_LABELS = {
|
|
175
|
+
handoffs: "Handoffs",
|
|
176
|
+
providers: "Providers",
|
|
177
|
+
quality: "Quality",
|
|
178
|
+
sessions: "Sessions",
|
|
179
|
+
workflows: "Workflows"
|
|
180
|
+
};
|
|
181
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
182
|
+
var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
|
|
183
|
+
var surfaceDetail = (surface) => {
|
|
184
|
+
const total = readNumber(surface, "total");
|
|
185
|
+
const failed = readNumber(surface, "failed");
|
|
186
|
+
const degraded = readNumber(surface, "degraded");
|
|
187
|
+
const source = surface && typeof surface === "object" && "source" in surface && typeof surface.source === "string" ? ` from ${surface.source}` : "";
|
|
188
|
+
if (degraded > 0) {
|
|
189
|
+
return `${degraded} degraded of ${total}`;
|
|
190
|
+
}
|
|
191
|
+
if (failed > 0) {
|
|
192
|
+
return `${failed} failing of ${total}${source}`;
|
|
193
|
+
}
|
|
194
|
+
return total > 0 ? `${total} passing${source}` : `No failures${source}`;
|
|
195
|
+
};
|
|
196
|
+
var getVoiceOpsStatusLabel = (report, error) => {
|
|
197
|
+
if (error) {
|
|
198
|
+
return "Unavailable";
|
|
199
|
+
}
|
|
200
|
+
if (!report) {
|
|
201
|
+
return "Checking";
|
|
202
|
+
}
|
|
203
|
+
return report.status === "pass" ? "Passing" : "Needs attention";
|
|
204
|
+
};
|
|
205
|
+
var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
206
|
+
const report = snapshot.report;
|
|
207
|
+
const surfaces = Object.entries(report?.surfaces ?? {}).map(([id, surface]) => {
|
|
208
|
+
const failed = readNumber(surface, "failed") || readNumber(surface, "degraded");
|
|
209
|
+
const total = readNumber(surface, "total");
|
|
210
|
+
const status = surface && typeof surface === "object" && "status" in surface ? surface.status ?? "pass" : "pass";
|
|
211
|
+
return {
|
|
212
|
+
detail: surfaceDetail(surface),
|
|
213
|
+
failed,
|
|
214
|
+
id,
|
|
215
|
+
label: SURFACE_LABELS[id] ?? id,
|
|
216
|
+
status,
|
|
217
|
+
total
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
222
|
+
error: snapshot.error,
|
|
223
|
+
isLoading: snapshot.isLoading,
|
|
224
|
+
label: getVoiceOpsStatusLabel(report, snapshot.error),
|
|
225
|
+
links: options.includeLinks === false ? [] : report?.links ?? [],
|
|
226
|
+
passed: report?.passed ?? 0,
|
|
227
|
+
status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
|
|
228
|
+
surfaces,
|
|
229
|
+
title: options.title ?? DEFAULT_TITLE,
|
|
230
|
+
total: report?.total ?? 0,
|
|
231
|
+
updatedAt: snapshot.updatedAt
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
|
|
235
|
+
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
236
|
+
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
|
|
237
|
+
<span>${escapeHtml(surface.label)}</span>
|
|
238
|
+
<strong>${escapeHtml(surface.detail)}</strong>
|
|
239
|
+
</li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
|
|
240
|
+
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</nav>` : "";
|
|
241
|
+
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml(model.status)}">
|
|
242
|
+
<header class="absolute-voice-ops-status__header">
|
|
243
|
+
<span class="absolute-voice-ops-status__eyebrow">${escapeHtml(model.title)}</span>
|
|
244
|
+
<strong class="absolute-voice-ops-status__label">${escapeHtml(model.label)}</strong>
|
|
245
|
+
</header>
|
|
246
|
+
<p class="absolute-voice-ops-status__description">${escapeHtml(model.description)}</p>
|
|
247
|
+
<div class="absolute-voice-ops-status__summary">
|
|
248
|
+
<span>${model.passed} passing</span>
|
|
249
|
+
<span>${Math.max(model.total - model.passed, 0)} failing</span>
|
|
250
|
+
<span>${model.total} checks</span>
|
|
251
|
+
</div>
|
|
252
|
+
<ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
|
|
253
|
+
${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml(model.error)}</p>` : ""}
|
|
254
|
+
${links}
|
|
255
|
+
</section>`;
|
|
256
|
+
};
|
|
257
|
+
var getVoiceOpsStatusCSS = () => `.absolute-voice-ops-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-ops-status--fail,.absolute-voice-ops-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-status__label{font-size:28px;line-height:1}.absolute-voice-ops-status__description{color:#514733;margin:12px 0 0}.absolute-voice-ops-status__summary,.absolute-voice-ops-status__links{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-status__summary span,.absolute-voice-ops-status__links a{border:1px solid #e6ddca;border-radius:999px;color:inherit;padding:6px 10px;text-decoration:none}.absolute-voice-ops-status__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-ops-status__surface{align-items:center;background:#fff;border:1px solid #eee4d2;border-radius:14px;display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.absolute-voice-ops-status__surface--fail{border-color:#f2a7a7}.absolute-voice-ops-status__surface span{color:#655944}.absolute-voice-ops-status__error{color:#9f1239;font-weight:700}`;
|
|
258
|
+
var mountVoiceOpsStatus = (element, path = "/app-kit/status", options = {}) => {
|
|
259
|
+
const store = createVoiceAppKitStatusStore(path, options);
|
|
260
|
+
const render = () => {
|
|
261
|
+
element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
|
|
262
|
+
};
|
|
263
|
+
const unsubscribe = store.subscribe(render);
|
|
264
|
+
render();
|
|
265
|
+
store.refresh().catch(() => {});
|
|
266
|
+
return {
|
|
267
|
+
close: () => {
|
|
268
|
+
unsubscribe();
|
|
269
|
+
store.close();
|
|
270
|
+
},
|
|
271
|
+
refresh: store.refresh
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
275
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
|
|
279
|
+
mounted;
|
|
280
|
+
connectedCallback() {
|
|
281
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
282
|
+
this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/app-kit/status", {
|
|
283
|
+
description: this.getAttribute("description") ?? undefined,
|
|
284
|
+
includeLinks: this.getAttribute("include-links") !== "false",
|
|
285
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
286
|
+
title: this.getAttribute("title") ?? undefined
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
disconnectedCallback() {
|
|
290
|
+
this.mounted?.close();
|
|
291
|
+
this.mounted = undefined;
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
// src/react/VoiceOpsStatus.tsx
|
|
297
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
298
|
+
var VoiceOpsStatus = ({
|
|
299
|
+
className,
|
|
300
|
+
path = "/app-kit/status",
|
|
301
|
+
...options
|
|
302
|
+
}) => {
|
|
303
|
+
const snapshot = useVoiceAppKitStatus(path, options);
|
|
304
|
+
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
305
|
+
return /* @__PURE__ */ jsxDEV("section", {
|
|
306
|
+
className: [
|
|
307
|
+
"absolute-voice-ops-status",
|
|
308
|
+
`absolute-voice-ops-status--${model.status}`,
|
|
309
|
+
className
|
|
310
|
+
].filter(Boolean).join(" "),
|
|
311
|
+
children: [
|
|
312
|
+
/* @__PURE__ */ jsxDEV("header", {
|
|
313
|
+
className: "absolute-voice-ops-status__header",
|
|
314
|
+
children: [
|
|
315
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
316
|
+
className: "absolute-voice-ops-status__eyebrow",
|
|
317
|
+
children: model.title
|
|
318
|
+
}, undefined, false, undefined, this),
|
|
319
|
+
/* @__PURE__ */ jsxDEV("strong", {
|
|
320
|
+
className: "absolute-voice-ops-status__label",
|
|
321
|
+
children: model.label
|
|
322
|
+
}, undefined, false, undefined, this)
|
|
323
|
+
]
|
|
324
|
+
}, undefined, true, undefined, this),
|
|
325
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
326
|
+
className: "absolute-voice-ops-status__description",
|
|
327
|
+
children: model.description
|
|
328
|
+
}, undefined, false, undefined, this),
|
|
329
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
330
|
+
className: "absolute-voice-ops-status__summary",
|
|
331
|
+
children: [
|
|
332
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
333
|
+
children: [
|
|
334
|
+
model.passed,
|
|
335
|
+
" passing"
|
|
336
|
+
]
|
|
337
|
+
}, undefined, true, undefined, this),
|
|
338
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
339
|
+
children: [
|
|
340
|
+
Math.max(model.total - model.passed, 0),
|
|
341
|
+
" failing"
|
|
342
|
+
]
|
|
343
|
+
}, undefined, true, undefined, this),
|
|
344
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
345
|
+
children: [
|
|
346
|
+
model.total,
|
|
347
|
+
" checks"
|
|
348
|
+
]
|
|
349
|
+
}, undefined, true, undefined, this)
|
|
350
|
+
]
|
|
351
|
+
}, undefined, true, undefined, this),
|
|
352
|
+
/* @__PURE__ */ jsxDEV("ul", {
|
|
353
|
+
className: "absolute-voice-ops-status__surfaces",
|
|
354
|
+
children: model.surfaces.length > 0 ? model.surfaces.map((surface) => /* @__PURE__ */ jsxDEV("li", {
|
|
355
|
+
className: `absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${surface.status}`,
|
|
356
|
+
children: [
|
|
357
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
358
|
+
children: surface.label
|
|
359
|
+
}, undefined, false, undefined, this),
|
|
360
|
+
/* @__PURE__ */ jsxDEV("strong", {
|
|
361
|
+
children: surface.detail
|
|
362
|
+
}, undefined, false, undefined, this)
|
|
363
|
+
]
|
|
364
|
+
}, surface.id, true, undefined, this)) : /* @__PURE__ */ jsxDEV("li", {
|
|
365
|
+
className: "absolute-voice-ops-status__surface",
|
|
366
|
+
children: [
|
|
367
|
+
/* @__PURE__ */ jsxDEV("span", {
|
|
368
|
+
children: "Status"
|
|
369
|
+
}, undefined, false, undefined, this),
|
|
370
|
+
/* @__PURE__ */ jsxDEV("strong", {
|
|
371
|
+
children: "Waiting for first check"
|
|
372
|
+
}, undefined, false, undefined, this)
|
|
373
|
+
]
|
|
374
|
+
}, undefined, true, undefined, this)
|
|
375
|
+
}, undefined, false, undefined, this),
|
|
376
|
+
model.error ? /* @__PURE__ */ jsxDEV("p", {
|
|
377
|
+
className: "absolute-voice-ops-status__error",
|
|
378
|
+
children: model.error
|
|
379
|
+
}, undefined, false, undefined, this) : null,
|
|
380
|
+
model.links.length > 0 ? /* @__PURE__ */ jsxDEV("nav", {
|
|
381
|
+
className: "absolute-voice-ops-status__links",
|
|
382
|
+
children: model.links.slice(0, 4).map((link) => /* @__PURE__ */ jsxDEV("a", {
|
|
383
|
+
href: link.href,
|
|
384
|
+
children: link.label
|
|
385
|
+
}, `${link.label}:${link.href}`, false, undefined, this))
|
|
386
|
+
}, undefined, false, undefined, this) : null
|
|
387
|
+
]
|
|
388
|
+
}, undefined, true, undefined, this);
|
|
389
|
+
};
|
|
170
390
|
// src/react/useVoiceStream.tsx
|
|
171
391
|
import { useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
172
392
|
|
|
@@ -1580,5 +1800,6 @@ export {
|
|
|
1580
1800
|
useVoiceStream,
|
|
1581
1801
|
useVoiceProviderStatus,
|
|
1582
1802
|
useVoiceController,
|
|
1583
|
-
useVoiceAppKitStatus
|
|
1803
|
+
useVoiceAppKitStatus,
|
|
1804
|
+
VoiceOpsStatus
|
|
1584
1805
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type VoiceOpsStatusWidgetOptions } from '../client/opsStatusWidget';
|
|
2
|
+
export declare const createVoiceOpsStatus: (path?: string, options?: VoiceOpsStatusWidgetOptions) => {
|
|
3
|
+
close: () => void;
|
|
4
|
+
getHTML: () => string;
|
|
5
|
+
getSnapshot: () => import("../client").VoiceAppKitStatusSnapshot;
|
|
6
|
+
getViewModel: () => import("../client").VoiceOpsStatusViewModel;
|
|
7
|
+
refresh: () => Promise<import("..").VoiceAppKitStatusReport | undefined>;
|
|
8
|
+
subscribe: (listener: () => void) => () => void;
|
|
9
|
+
};
|
package/dist/svelte/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createVoiceAppKitStatus } from './createVoiceAppKitStatus';
|
|
2
|
+
export { createVoiceOpsStatus } from './createVoiceOpsStatus';
|
|
2
3
|
export { createVoiceStream } from './createVoiceStream';
|
|
3
4
|
export { createVoiceProviderStatus } from './createVoiceProviderStatus';
|
|
4
5
|
export { createVoiceWorkflowStatus } from './createVoiceWorkflowStatus';
|
package/dist/svelte/index.js
CHANGED
|
@@ -150,6 +150,143 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
|
|
|
150
150
|
|
|
151
151
|
// src/svelte/createVoiceAppKitStatus.ts
|
|
152
152
|
var createVoiceAppKitStatus = (path = "/app-kit/status", options = {}) => createVoiceAppKitStatusStore(path, options);
|
|
153
|
+
// src/client/opsStatusWidget.ts
|
|
154
|
+
var DEFAULT_TITLE = "Voice Ops Status";
|
|
155
|
+
var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from the AbsoluteJS voice app kit.";
|
|
156
|
+
var SURFACE_LABELS = {
|
|
157
|
+
handoffs: "Handoffs",
|
|
158
|
+
providers: "Providers",
|
|
159
|
+
quality: "Quality",
|
|
160
|
+
sessions: "Sessions",
|
|
161
|
+
workflows: "Workflows"
|
|
162
|
+
};
|
|
163
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
164
|
+
var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
|
|
165
|
+
var surfaceDetail = (surface) => {
|
|
166
|
+
const total = readNumber(surface, "total");
|
|
167
|
+
const failed = readNumber(surface, "failed");
|
|
168
|
+
const degraded = readNumber(surface, "degraded");
|
|
169
|
+
const source = surface && typeof surface === "object" && "source" in surface && typeof surface.source === "string" ? ` from ${surface.source}` : "";
|
|
170
|
+
if (degraded > 0) {
|
|
171
|
+
return `${degraded} degraded of ${total}`;
|
|
172
|
+
}
|
|
173
|
+
if (failed > 0) {
|
|
174
|
+
return `${failed} failing of ${total}${source}`;
|
|
175
|
+
}
|
|
176
|
+
return total > 0 ? `${total} passing${source}` : `No failures${source}`;
|
|
177
|
+
};
|
|
178
|
+
var getVoiceOpsStatusLabel = (report, error) => {
|
|
179
|
+
if (error) {
|
|
180
|
+
return "Unavailable";
|
|
181
|
+
}
|
|
182
|
+
if (!report) {
|
|
183
|
+
return "Checking";
|
|
184
|
+
}
|
|
185
|
+
return report.status === "pass" ? "Passing" : "Needs attention";
|
|
186
|
+
};
|
|
187
|
+
var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
188
|
+
const report = snapshot.report;
|
|
189
|
+
const surfaces = Object.entries(report?.surfaces ?? {}).map(([id, surface]) => {
|
|
190
|
+
const failed = readNumber(surface, "failed") || readNumber(surface, "degraded");
|
|
191
|
+
const total = readNumber(surface, "total");
|
|
192
|
+
const status = surface && typeof surface === "object" && "status" in surface ? surface.status ?? "pass" : "pass";
|
|
193
|
+
return {
|
|
194
|
+
detail: surfaceDetail(surface),
|
|
195
|
+
failed,
|
|
196
|
+
id,
|
|
197
|
+
label: SURFACE_LABELS[id] ?? id,
|
|
198
|
+
status,
|
|
199
|
+
total
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
return {
|
|
203
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
204
|
+
error: snapshot.error,
|
|
205
|
+
isLoading: snapshot.isLoading,
|
|
206
|
+
label: getVoiceOpsStatusLabel(report, snapshot.error),
|
|
207
|
+
links: options.includeLinks === false ? [] : report?.links ?? [],
|
|
208
|
+
passed: report?.passed ?? 0,
|
|
209
|
+
status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
|
|
210
|
+
surfaces,
|
|
211
|
+
title: options.title ?? DEFAULT_TITLE,
|
|
212
|
+
total: report?.total ?? 0,
|
|
213
|
+
updatedAt: snapshot.updatedAt
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
|
|
217
|
+
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
218
|
+
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
|
|
219
|
+
<span>${escapeHtml(surface.label)}</span>
|
|
220
|
+
<strong>${escapeHtml(surface.detail)}</strong>
|
|
221
|
+
</li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
|
|
222
|
+
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</nav>` : "";
|
|
223
|
+
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml(model.status)}">
|
|
224
|
+
<header class="absolute-voice-ops-status__header">
|
|
225
|
+
<span class="absolute-voice-ops-status__eyebrow">${escapeHtml(model.title)}</span>
|
|
226
|
+
<strong class="absolute-voice-ops-status__label">${escapeHtml(model.label)}</strong>
|
|
227
|
+
</header>
|
|
228
|
+
<p class="absolute-voice-ops-status__description">${escapeHtml(model.description)}</p>
|
|
229
|
+
<div class="absolute-voice-ops-status__summary">
|
|
230
|
+
<span>${model.passed} passing</span>
|
|
231
|
+
<span>${Math.max(model.total - model.passed, 0)} failing</span>
|
|
232
|
+
<span>${model.total} checks</span>
|
|
233
|
+
</div>
|
|
234
|
+
<ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
|
|
235
|
+
${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml(model.error)}</p>` : ""}
|
|
236
|
+
${links}
|
|
237
|
+
</section>`;
|
|
238
|
+
};
|
|
239
|
+
var getVoiceOpsStatusCSS = () => `.absolute-voice-ops-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-ops-status--fail,.absolute-voice-ops-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-status__label{font-size:28px;line-height:1}.absolute-voice-ops-status__description{color:#514733;margin:12px 0 0}.absolute-voice-ops-status__summary,.absolute-voice-ops-status__links{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-status__summary span,.absolute-voice-ops-status__links a{border:1px solid #e6ddca;border-radius:999px;color:inherit;padding:6px 10px;text-decoration:none}.absolute-voice-ops-status__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-ops-status__surface{align-items:center;background:#fff;border:1px solid #eee4d2;border-radius:14px;display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.absolute-voice-ops-status__surface--fail{border-color:#f2a7a7}.absolute-voice-ops-status__surface span{color:#655944}.absolute-voice-ops-status__error{color:#9f1239;font-weight:700}`;
|
|
240
|
+
var mountVoiceOpsStatus = (element, path = "/app-kit/status", options = {}) => {
|
|
241
|
+
const store = createVoiceAppKitStatusStore(path, options);
|
|
242
|
+
const render = () => {
|
|
243
|
+
element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
|
|
244
|
+
};
|
|
245
|
+
const unsubscribe = store.subscribe(render);
|
|
246
|
+
render();
|
|
247
|
+
store.refresh().catch(() => {});
|
|
248
|
+
return {
|
|
249
|
+
close: () => {
|
|
250
|
+
unsubscribe();
|
|
251
|
+
store.close();
|
|
252
|
+
},
|
|
253
|
+
refresh: store.refresh
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
257
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
|
|
261
|
+
mounted;
|
|
262
|
+
connectedCallback() {
|
|
263
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
264
|
+
this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/app-kit/status", {
|
|
265
|
+
description: this.getAttribute("description") ?? undefined,
|
|
266
|
+
includeLinks: this.getAttribute("include-links") !== "false",
|
|
267
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
268
|
+
title: this.getAttribute("title") ?? undefined
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
disconnectedCallback() {
|
|
272
|
+
this.mounted?.close();
|
|
273
|
+
this.mounted = undefined;
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/svelte/createVoiceOpsStatus.ts
|
|
279
|
+
var createVoiceOpsStatus = (path = "/app-kit/status", options = {}) => {
|
|
280
|
+
const store = createVoiceAppKitStatusStore(path, options);
|
|
281
|
+
return {
|
|
282
|
+
close: store.close,
|
|
283
|
+
getHTML: () => renderVoiceOpsStatusHTML(store.getSnapshot(), options),
|
|
284
|
+
getSnapshot: store.getSnapshot,
|
|
285
|
+
getViewModel: () => createVoiceOpsStatusViewModel(store.getSnapshot(), options),
|
|
286
|
+
refresh: store.refresh,
|
|
287
|
+
subscribe: store.subscribe
|
|
288
|
+
};
|
|
289
|
+
};
|
|
153
290
|
// src/client/actions.ts
|
|
154
291
|
var normalizeErrorMessage = (value) => {
|
|
155
292
|
if (typeof value === "string" && value.trim()) {
|
|
@@ -1461,6 +1598,7 @@ export {
|
|
|
1461
1598
|
createVoiceWorkflowStatus,
|
|
1462
1599
|
createVoiceStream2 as createVoiceStream,
|
|
1463
1600
|
createVoiceProviderStatus,
|
|
1601
|
+
createVoiceOpsStatus,
|
|
1464
1602
|
createVoiceController,
|
|
1465
1603
|
createVoiceAppKitStatus
|
|
1466
1604
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const VoiceOpsStatus: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
+
description: StringConstructor;
|
|
3
|
+
includeLinks: {
|
|
4
|
+
default: boolean;
|
|
5
|
+
type: BooleanConstructor;
|
|
6
|
+
};
|
|
7
|
+
intervalMs: NumberConstructor;
|
|
8
|
+
path: {
|
|
9
|
+
default: string;
|
|
10
|
+
type: StringConstructor;
|
|
11
|
+
};
|
|
12
|
+
title: StringConstructor;
|
|
13
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
16
|
+
description: StringConstructor;
|
|
17
|
+
includeLinks: {
|
|
18
|
+
default: boolean;
|
|
19
|
+
type: BooleanConstructor;
|
|
20
|
+
};
|
|
21
|
+
intervalMs: NumberConstructor;
|
|
22
|
+
path: {
|
|
23
|
+
default: string;
|
|
24
|
+
type: StringConstructor;
|
|
25
|
+
};
|
|
26
|
+
title: StringConstructor;
|
|
27
|
+
}>> & Readonly<{}>, {
|
|
28
|
+
path: string;
|
|
29
|
+
includeLinks: boolean;
|
|
30
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vue/index.d.ts
CHANGED
package/dist/vue/index.js
CHANGED
|
@@ -69,8 +69,8 @@ var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
|
69
69
|
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
// src/vue/
|
|
73
|
-
import {
|
|
72
|
+
// src/vue/VoiceOpsStatus.ts
|
|
73
|
+
import { defineComponent, h } from "vue";
|
|
74
74
|
|
|
75
75
|
// src/client/appKitStatus.ts
|
|
76
76
|
var fetchVoiceAppKitStatus = async (path = "/app-kit/status", options = {}) => {
|
|
@@ -151,7 +151,133 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
|
|
|
151
151
|
};
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
+
// src/client/opsStatusWidget.ts
|
|
155
|
+
var DEFAULT_TITLE = "Voice Ops Status";
|
|
156
|
+
var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from the AbsoluteJS voice app kit.";
|
|
157
|
+
var SURFACE_LABELS = {
|
|
158
|
+
handoffs: "Handoffs",
|
|
159
|
+
providers: "Providers",
|
|
160
|
+
quality: "Quality",
|
|
161
|
+
sessions: "Sessions",
|
|
162
|
+
workflows: "Workflows"
|
|
163
|
+
};
|
|
164
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
165
|
+
var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
|
|
166
|
+
var surfaceDetail = (surface) => {
|
|
167
|
+
const total = readNumber(surface, "total");
|
|
168
|
+
const failed = readNumber(surface, "failed");
|
|
169
|
+
const degraded = readNumber(surface, "degraded");
|
|
170
|
+
const source = surface && typeof surface === "object" && "source" in surface && typeof surface.source === "string" ? ` from ${surface.source}` : "";
|
|
171
|
+
if (degraded > 0) {
|
|
172
|
+
return `${degraded} degraded of ${total}`;
|
|
173
|
+
}
|
|
174
|
+
if (failed > 0) {
|
|
175
|
+
return `${failed} failing of ${total}${source}`;
|
|
176
|
+
}
|
|
177
|
+
return total > 0 ? `${total} passing${source}` : `No failures${source}`;
|
|
178
|
+
};
|
|
179
|
+
var getVoiceOpsStatusLabel = (report, error) => {
|
|
180
|
+
if (error) {
|
|
181
|
+
return "Unavailable";
|
|
182
|
+
}
|
|
183
|
+
if (!report) {
|
|
184
|
+
return "Checking";
|
|
185
|
+
}
|
|
186
|
+
return report.status === "pass" ? "Passing" : "Needs attention";
|
|
187
|
+
};
|
|
188
|
+
var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
189
|
+
const report = snapshot.report;
|
|
190
|
+
const surfaces = Object.entries(report?.surfaces ?? {}).map(([id, surface]) => {
|
|
191
|
+
const failed = readNumber(surface, "failed") || readNumber(surface, "degraded");
|
|
192
|
+
const total = readNumber(surface, "total");
|
|
193
|
+
const status = surface && typeof surface === "object" && "status" in surface ? surface.status ?? "pass" : "pass";
|
|
194
|
+
return {
|
|
195
|
+
detail: surfaceDetail(surface),
|
|
196
|
+
failed,
|
|
197
|
+
id,
|
|
198
|
+
label: SURFACE_LABELS[id] ?? id,
|
|
199
|
+
status,
|
|
200
|
+
total
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
205
|
+
error: snapshot.error,
|
|
206
|
+
isLoading: snapshot.isLoading,
|
|
207
|
+
label: getVoiceOpsStatusLabel(report, snapshot.error),
|
|
208
|
+
links: options.includeLinks === false ? [] : report?.links ?? [],
|
|
209
|
+
passed: report?.passed ?? 0,
|
|
210
|
+
status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
|
|
211
|
+
surfaces,
|
|
212
|
+
title: options.title ?? DEFAULT_TITLE,
|
|
213
|
+
total: report?.total ?? 0,
|
|
214
|
+
updatedAt: snapshot.updatedAt
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
|
|
218
|
+
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
219
|
+
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
|
|
220
|
+
<span>${escapeHtml(surface.label)}</span>
|
|
221
|
+
<strong>${escapeHtml(surface.detail)}</strong>
|
|
222
|
+
</li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
|
|
223
|
+
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml(link.href)}">${escapeHtml(link.label)}</a>`).join("")}</nav>` : "";
|
|
224
|
+
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml(model.status)}">
|
|
225
|
+
<header class="absolute-voice-ops-status__header">
|
|
226
|
+
<span class="absolute-voice-ops-status__eyebrow">${escapeHtml(model.title)}</span>
|
|
227
|
+
<strong class="absolute-voice-ops-status__label">${escapeHtml(model.label)}</strong>
|
|
228
|
+
</header>
|
|
229
|
+
<p class="absolute-voice-ops-status__description">${escapeHtml(model.description)}</p>
|
|
230
|
+
<div class="absolute-voice-ops-status__summary">
|
|
231
|
+
<span>${model.passed} passing</span>
|
|
232
|
+
<span>${Math.max(model.total - model.passed, 0)} failing</span>
|
|
233
|
+
<span>${model.total} checks</span>
|
|
234
|
+
</div>
|
|
235
|
+
<ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
|
|
236
|
+
${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml(model.error)}</p>` : ""}
|
|
237
|
+
${links}
|
|
238
|
+
</section>`;
|
|
239
|
+
};
|
|
240
|
+
var getVoiceOpsStatusCSS = () => `.absolute-voice-ops-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-ops-status--fail,.absolute-voice-ops-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-status__label{font-size:28px;line-height:1}.absolute-voice-ops-status__description{color:#514733;margin:12px 0 0}.absolute-voice-ops-status__summary,.absolute-voice-ops-status__links{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-status__summary span,.absolute-voice-ops-status__links a{border:1px solid #e6ddca;border-radius:999px;color:inherit;padding:6px 10px;text-decoration:none}.absolute-voice-ops-status__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-ops-status__surface{align-items:center;background:#fff;border:1px solid #eee4d2;border-radius:14px;display:flex;gap:12px;justify-content:space-between;padding:10px 12px}.absolute-voice-ops-status__surface--fail{border-color:#f2a7a7}.absolute-voice-ops-status__surface span{color:#655944}.absolute-voice-ops-status__error{color:#9f1239;font-weight:700}`;
|
|
241
|
+
var mountVoiceOpsStatus = (element, path = "/app-kit/status", options = {}) => {
|
|
242
|
+
const store = createVoiceAppKitStatusStore(path, options);
|
|
243
|
+
const render = () => {
|
|
244
|
+
element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
|
|
245
|
+
};
|
|
246
|
+
const unsubscribe = store.subscribe(render);
|
|
247
|
+
render();
|
|
248
|
+
store.refresh().catch(() => {});
|
|
249
|
+
return {
|
|
250
|
+
close: () => {
|
|
251
|
+
unsubscribe();
|
|
252
|
+
store.close();
|
|
253
|
+
},
|
|
254
|
+
refresh: store.refresh
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
258
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
|
|
262
|
+
mounted;
|
|
263
|
+
connectedCallback() {
|
|
264
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
265
|
+
this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/app-kit/status", {
|
|
266
|
+
description: this.getAttribute("description") ?? undefined,
|
|
267
|
+
includeLinks: this.getAttribute("include-links") !== "false",
|
|
268
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
269
|
+
title: this.getAttribute("title") ?? undefined
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
disconnectedCallback() {
|
|
273
|
+
this.mounted?.close();
|
|
274
|
+
this.mounted = undefined;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
|
|
154
279
|
// src/vue/useVoiceAppKitStatus.ts
|
|
280
|
+
import { onUnmounted, ref, shallowRef } from "vue";
|
|
155
281
|
var useVoiceAppKitStatus = (path = "/app-kit/status", options = {}) => {
|
|
156
282
|
const store = createVoiceAppKitStatusStore(path, options);
|
|
157
283
|
const error = ref(null);
|
|
@@ -182,6 +308,72 @@ var useVoiceAppKitStatus = (path = "/app-kit/status", options = {}) => {
|
|
|
182
308
|
updatedAt
|
|
183
309
|
};
|
|
184
310
|
};
|
|
311
|
+
|
|
312
|
+
// src/vue/VoiceOpsStatus.ts
|
|
313
|
+
var VoiceOpsStatus = defineComponent({
|
|
314
|
+
name: "VoiceOpsStatus",
|
|
315
|
+
props: {
|
|
316
|
+
description: String,
|
|
317
|
+
includeLinks: {
|
|
318
|
+
default: true,
|
|
319
|
+
type: Boolean
|
|
320
|
+
},
|
|
321
|
+
intervalMs: Number,
|
|
322
|
+
path: {
|
|
323
|
+
default: "/app-kit/status",
|
|
324
|
+
type: String
|
|
325
|
+
},
|
|
326
|
+
title: String
|
|
327
|
+
},
|
|
328
|
+
setup(props) {
|
|
329
|
+
const options = {
|
|
330
|
+
description: props.description,
|
|
331
|
+
includeLinks: props.includeLinks,
|
|
332
|
+
intervalMs: props.intervalMs,
|
|
333
|
+
title: props.title
|
|
334
|
+
};
|
|
335
|
+
const status = useVoiceAppKitStatus(props.path, options);
|
|
336
|
+
return () => {
|
|
337
|
+
const model = createVoiceOpsStatusViewModel({
|
|
338
|
+
error: status.error.value,
|
|
339
|
+
isLoading: status.isLoading.value,
|
|
340
|
+
report: status.report.value,
|
|
341
|
+
updatedAt: status.updatedAt.value
|
|
342
|
+
}, options);
|
|
343
|
+
return h("section", {
|
|
344
|
+
class: [
|
|
345
|
+
"absolute-voice-ops-status",
|
|
346
|
+
`absolute-voice-ops-status--${model.status}`
|
|
347
|
+
]
|
|
348
|
+
}, [
|
|
349
|
+
h("header", { class: "absolute-voice-ops-status__header" }, [
|
|
350
|
+
h("span", { class: "absolute-voice-ops-status__eyebrow" }, model.title),
|
|
351
|
+
h("strong", { class: "absolute-voice-ops-status__label" }, model.label)
|
|
352
|
+
]),
|
|
353
|
+
h("p", { class: "absolute-voice-ops-status__description" }, model.description),
|
|
354
|
+
h("div", { class: "absolute-voice-ops-status__summary" }, [
|
|
355
|
+
h("span", `${model.passed} passing`),
|
|
356
|
+
h("span", `${Math.max(model.total - model.passed, 0)} failing`),
|
|
357
|
+
h("span", `${model.total} checks`)
|
|
358
|
+
]),
|
|
359
|
+
h("ul", { class: "absolute-voice-ops-status__surfaces" }, model.surfaces.length > 0 ? model.surfaces.map((surface) => h("li", {
|
|
360
|
+
class: [
|
|
361
|
+
"absolute-voice-ops-status__surface",
|
|
362
|
+
`absolute-voice-ops-status__surface--${surface.status}`
|
|
363
|
+
],
|
|
364
|
+
key: surface.id
|
|
365
|
+
}, [h("span", surface.label), h("strong", surface.detail)])) : [
|
|
366
|
+
h("li", { class: "absolute-voice-ops-status__surface" }, [
|
|
367
|
+
h("span", "Status"),
|
|
368
|
+
h("strong", "Waiting for first check")
|
|
369
|
+
])
|
|
370
|
+
]),
|
|
371
|
+
model.error ? h("p", { class: "absolute-voice-ops-status__error" }, model.error) : null,
|
|
372
|
+
model.links.length > 0 ? h("nav", { class: "absolute-voice-ops-status__links" }, model.links.slice(0, 4).map((link) => h("a", { href: link.href, key: link.href }, link.label))) : null
|
|
373
|
+
]);
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
});
|
|
185
377
|
// src/vue/useVoiceStream.ts
|
|
186
378
|
import { onUnmounted as onUnmounted2, ref as ref2, shallowRef as shallowRef2 } from "vue";
|
|
187
379
|
|
|
@@ -1659,5 +1851,6 @@ export {
|
|
|
1659
1851
|
useVoiceStream,
|
|
1660
1852
|
useVoiceProviderStatus,
|
|
1661
1853
|
useVoiceController,
|
|
1662
|
-
useVoiceAppKitStatus
|
|
1854
|
+
useVoiceAppKitStatus,
|
|
1855
|
+
VoiceOpsStatus
|
|
1663
1856
|
};
|