@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/angular/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { VoiceOpsStatusComponent } from './voice-ops-status.component';
|
|
1
2
|
export { VoiceAppKitStatusService } from './voice-app-kit-status.service';
|
|
2
3
|
export { VoiceStreamService } from './voice-stream.service';
|
|
3
4
|
export { VoiceControllerService } from './voice-controller.service';
|
package/dist/angular/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/angular/voice-
|
|
73
|
-
import {
|
|
72
|
+
// src/angular/voice-ops-status.component.ts
|
|
73
|
+
import { Component, Input, signal } from "@angular/core";
|
|
74
74
|
|
|
75
75
|
// src/client/appKitStatus.ts
|
|
76
76
|
var fetchVoiceAppKitStatus = async (path = "/app-kit/status", options = {}) => {
|
|
@@ -151,7 +151,269 @@ 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
|
+
|
|
279
|
+
// src/angular/voice-ops-status.component.ts
|
|
280
|
+
var _dec = [
|
|
281
|
+
Component({
|
|
282
|
+
selector: "absolute-voice-ops-status",
|
|
283
|
+
standalone: true,
|
|
284
|
+
template: `
|
|
285
|
+
<section
|
|
286
|
+
class="absolute-voice-ops-status"
|
|
287
|
+
[class.absolute-voice-ops-status--pass]="model().status === 'pass'"
|
|
288
|
+
[class.absolute-voice-ops-status--fail]="model().status === 'fail'"
|
|
289
|
+
[class.absolute-voice-ops-status--loading]="model().status === 'loading'"
|
|
290
|
+
[class.absolute-voice-ops-status--error]="model().status === 'error'"
|
|
291
|
+
>
|
|
292
|
+
<header class="absolute-voice-ops-status__header">
|
|
293
|
+
<span class="absolute-voice-ops-status__eyebrow">{{
|
|
294
|
+
model().title
|
|
295
|
+
}}</span>
|
|
296
|
+
<strong class="absolute-voice-ops-status__label">{{
|
|
297
|
+
model().label
|
|
298
|
+
}}</strong>
|
|
299
|
+
</header>
|
|
300
|
+
<p class="absolute-voice-ops-status__description">
|
|
301
|
+
{{ model().description }}
|
|
302
|
+
</p>
|
|
303
|
+
<div class="absolute-voice-ops-status__summary">
|
|
304
|
+
<span>{{ model().passed }} passing</span>
|
|
305
|
+
<span>{{ model().total - model().passed }} failing</span>
|
|
306
|
+
<span>{{ model().total }} checks</span>
|
|
307
|
+
</div>
|
|
308
|
+
<ul class="absolute-voice-ops-status__surfaces">
|
|
309
|
+
@if (model().surfaces.length > 0) {
|
|
310
|
+
@for (surface of model().surfaces; track surface.id) {
|
|
311
|
+
<li
|
|
312
|
+
class="absolute-voice-ops-status__surface"
|
|
313
|
+
[class.absolute-voice-ops-status__surface--pass]="
|
|
314
|
+
surface.status === 'pass'
|
|
315
|
+
"
|
|
316
|
+
[class.absolute-voice-ops-status__surface--fail]="
|
|
317
|
+
surface.status === 'fail'
|
|
318
|
+
"
|
|
319
|
+
>
|
|
320
|
+
<span>{{ surface.label }}</span>
|
|
321
|
+
<strong>{{ surface.detail }}</strong>
|
|
322
|
+
</li>
|
|
323
|
+
}
|
|
324
|
+
} @else {
|
|
325
|
+
<li class="absolute-voice-ops-status__surface">
|
|
326
|
+
<span>Status</span>
|
|
327
|
+
<strong>Waiting for first check</strong>
|
|
328
|
+
</li>
|
|
329
|
+
}
|
|
330
|
+
</ul>
|
|
331
|
+
@if (model().error) {
|
|
332
|
+
<p class="absolute-voice-ops-status__error">{{ model().error }}</p>
|
|
333
|
+
}
|
|
334
|
+
@if (model().links.length > 0) {
|
|
335
|
+
<nav class="absolute-voice-ops-status__links">
|
|
336
|
+
@for (link of model().links.slice(0, 4); track link.href) {
|
|
337
|
+
<a [href]="link.href">{{ link.label }}</a>
|
|
338
|
+
}
|
|
339
|
+
</nav>
|
|
340
|
+
}
|
|
341
|
+
</section>
|
|
342
|
+
`
|
|
343
|
+
})
|
|
344
|
+
];
|
|
345
|
+
var _dec2 = [
|
|
346
|
+
Input()
|
|
347
|
+
];
|
|
348
|
+
var _dec3 = [
|
|
349
|
+
Input()
|
|
350
|
+
];
|
|
351
|
+
var _dec4 = [
|
|
352
|
+
Input()
|
|
353
|
+
];
|
|
354
|
+
var _dec5 = [
|
|
355
|
+
Input()
|
|
356
|
+
];
|
|
357
|
+
var _dec6 = [
|
|
358
|
+
Input()
|
|
359
|
+
];
|
|
360
|
+
var _init = __decoratorStart(undefined);
|
|
361
|
+
|
|
362
|
+
class VoiceOpsStatusComponent {
|
|
363
|
+
constructor() {
|
|
364
|
+
this.description = __runInitializers(_init, 8, this);
|
|
365
|
+
__runInitializers(_init, 11, this);
|
|
366
|
+
this.includeLinks = __runInitializers(_init, 12, this, true);
|
|
367
|
+
__runInitializers(_init, 15, this);
|
|
368
|
+
this.intervalMs = __runInitializers(_init, 16, this);
|
|
369
|
+
__runInitializers(_init, 19, this);
|
|
370
|
+
this.path = __runInitializers(_init, 20, this, "/app-kit/status");
|
|
371
|
+
__runInitializers(_init, 23, this);
|
|
372
|
+
this.title = __runInitializers(_init, 24, this);
|
|
373
|
+
__runInitializers(_init, 27, this);
|
|
374
|
+
}
|
|
375
|
+
cleanup = () => {};
|
|
376
|
+
store;
|
|
377
|
+
model = signal(createVoiceOpsStatusViewModel({
|
|
378
|
+
error: null,
|
|
379
|
+
isLoading: true
|
|
380
|
+
}));
|
|
381
|
+
ngOnInit() {
|
|
382
|
+
const options = this.options();
|
|
383
|
+
this.store = createVoiceAppKitStatusStore(this.path, options);
|
|
384
|
+
const sync = () => {
|
|
385
|
+
this.model.set(createVoiceOpsStatusViewModel(this.store.getSnapshot(), options));
|
|
386
|
+
};
|
|
387
|
+
this.cleanup = this.store.subscribe(sync);
|
|
388
|
+
sync();
|
|
389
|
+
if (typeof window !== "undefined") {
|
|
390
|
+
this.store.refresh().catch(() => {});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
ngOnDestroy() {
|
|
394
|
+
this.cleanup();
|
|
395
|
+
this.store?.close();
|
|
396
|
+
}
|
|
397
|
+
options() {
|
|
398
|
+
return {
|
|
399
|
+
description: this.description,
|
|
400
|
+
includeLinks: this.includeLinks,
|
|
401
|
+
intervalMs: this.intervalMs,
|
|
402
|
+
title: this.title
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
__decorateElement(_init, 5, "description", _dec2, VoiceOpsStatusComponent);
|
|
407
|
+
__decorateElement(_init, 5, "includeLinks", _dec3, VoiceOpsStatusComponent);
|
|
408
|
+
__decorateElement(_init, 5, "intervalMs", _dec4, VoiceOpsStatusComponent);
|
|
409
|
+
__decorateElement(_init, 5, "path", _dec5, VoiceOpsStatusComponent);
|
|
410
|
+
__decorateElement(_init, 5, "title", _dec6, VoiceOpsStatusComponent);
|
|
411
|
+
VoiceOpsStatusComponent = __decorateElement(_init, 0, "VoiceOpsStatusComponent", _dec, VoiceOpsStatusComponent);
|
|
412
|
+
__runInitializers(_init, 1, VoiceOpsStatusComponent);
|
|
413
|
+
__decoratorMetadata(_init, VoiceOpsStatusComponent);
|
|
414
|
+
let _VoiceOpsStatusComponent = VoiceOpsStatusComponent;
|
|
154
415
|
// src/angular/voice-app-kit-status.service.ts
|
|
416
|
+
import { computed, Injectable, signal as signal2 } from "@angular/core";
|
|
155
417
|
var _dec = [
|
|
156
418
|
Injectable({ providedIn: "root" })
|
|
157
419
|
];
|
|
@@ -160,10 +422,10 @@ var _init = __decoratorStart(undefined);
|
|
|
160
422
|
class VoiceAppKitStatusService {
|
|
161
423
|
connect(path = "/app-kit/status", options = {}) {
|
|
162
424
|
const store = createVoiceAppKitStatusStore(path, options);
|
|
163
|
-
const errorSignal =
|
|
164
|
-
const isLoadingSignal =
|
|
165
|
-
const reportSignal =
|
|
166
|
-
const updatedAtSignal =
|
|
425
|
+
const errorSignal = signal2(null);
|
|
426
|
+
const isLoadingSignal = signal2(false);
|
|
427
|
+
const reportSignal = signal2(undefined);
|
|
428
|
+
const updatedAtSignal = signal2(undefined);
|
|
167
429
|
const sync = () => {
|
|
168
430
|
const snapshot = store.getSnapshot();
|
|
169
431
|
errorSignal.set(snapshot.error);
|
|
@@ -194,7 +456,7 @@ __runInitializers(_init, 1, VoiceAppKitStatusService);
|
|
|
194
456
|
__decoratorMetadata(_init, VoiceAppKitStatusService);
|
|
195
457
|
let _VoiceAppKitStatusService = VoiceAppKitStatusService;
|
|
196
458
|
// src/angular/voice-stream.service.ts
|
|
197
|
-
import { computed as computed2, Injectable as Injectable2, signal as
|
|
459
|
+
import { computed as computed2, Injectable as Injectable2, signal as signal3 } from "@angular/core";
|
|
198
460
|
|
|
199
461
|
// src/client/actions.ts
|
|
200
462
|
var normalizeErrorMessage = (value) => {
|
|
@@ -718,15 +980,15 @@ var _init = __decoratorStart(undefined);
|
|
|
718
980
|
class VoiceStreamService {
|
|
719
981
|
connect(path, options = {}) {
|
|
720
982
|
const stream = createVoiceStream(path, options);
|
|
721
|
-
const assistantAudioSignal =
|
|
722
|
-
const assistantTextsSignal =
|
|
723
|
-
const callSignal =
|
|
724
|
-
const errorSignal =
|
|
725
|
-
const isConnectedSignal =
|
|
726
|
-
const partialSignal =
|
|
727
|
-
const sessionIdSignal =
|
|
728
|
-
const statusSignal =
|
|
729
|
-
const turnsSignal =
|
|
983
|
+
const assistantAudioSignal = signal3([]);
|
|
984
|
+
const assistantTextsSignal = signal3([]);
|
|
985
|
+
const callSignal = signal3(null);
|
|
986
|
+
const errorSignal = signal3(null);
|
|
987
|
+
const isConnectedSignal = signal3(false);
|
|
988
|
+
const partialSignal = signal3("");
|
|
989
|
+
const sessionIdSignal = signal3(stream.sessionId);
|
|
990
|
+
const statusSignal = signal3(stream.status);
|
|
991
|
+
const turnsSignal = signal3([]);
|
|
730
992
|
const sync = () => {
|
|
731
993
|
assistantAudioSignal.set([...stream.assistantAudio]);
|
|
732
994
|
assistantTextsSignal.set([...stream.assistantTexts]);
|
|
@@ -765,7 +1027,7 @@ __runInitializers(_init, 1, VoiceStreamService);
|
|
|
765
1027
|
__decoratorMetadata(_init, VoiceStreamService);
|
|
766
1028
|
let _VoiceStreamService = VoiceStreamService;
|
|
767
1029
|
// src/angular/voice-controller.service.ts
|
|
768
|
-
import { computed as computed3, Injectable as Injectable3, signal as
|
|
1030
|
+
import { computed as computed3, Injectable as Injectable3, signal as signal4 } from "@angular/core";
|
|
769
1031
|
|
|
770
1032
|
// src/client/htmx.ts
|
|
771
1033
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -1406,16 +1668,16 @@ var _init = __decoratorStart(undefined);
|
|
|
1406
1668
|
class VoiceControllerService {
|
|
1407
1669
|
connect(path, options = {}) {
|
|
1408
1670
|
const controller = createVoiceController(path, options);
|
|
1409
|
-
const assistantAudioSignal =
|
|
1410
|
-
const assistantTextsSignal =
|
|
1411
|
-
const errorSignal =
|
|
1412
|
-
const isConnectedSignal =
|
|
1413
|
-
const isRecordingSignal =
|
|
1414
|
-
const partialSignal =
|
|
1415
|
-
const recordingErrorSignal =
|
|
1416
|
-
const sessionIdSignal =
|
|
1417
|
-
const statusSignal =
|
|
1418
|
-
const turnsSignal =
|
|
1671
|
+
const assistantAudioSignal = signal4([]);
|
|
1672
|
+
const assistantTextsSignal = signal4([]);
|
|
1673
|
+
const errorSignal = signal4(null);
|
|
1674
|
+
const isConnectedSignal = signal4(false);
|
|
1675
|
+
const isRecordingSignal = signal4(false);
|
|
1676
|
+
const partialSignal = signal4("");
|
|
1677
|
+
const recordingErrorSignal = signal4(null);
|
|
1678
|
+
const sessionIdSignal = signal4(controller.sessionId);
|
|
1679
|
+
const statusSignal = signal4(controller.status);
|
|
1680
|
+
const turnsSignal = signal4([]);
|
|
1419
1681
|
const sync = () => {
|
|
1420
1682
|
assistantAudioSignal.set([...controller.assistantAudio]);
|
|
1421
1683
|
assistantTextsSignal.set([...controller.assistantTexts]);
|
|
@@ -1459,7 +1721,7 @@ __runInitializers(_init, 1, VoiceControllerService);
|
|
|
1459
1721
|
__decoratorMetadata(_init, VoiceControllerService);
|
|
1460
1722
|
let _VoiceControllerService = VoiceControllerService;
|
|
1461
1723
|
// src/angular/voice-provider-status.service.ts
|
|
1462
|
-
import { computed as computed4, Injectable as Injectable4, signal as
|
|
1724
|
+
import { computed as computed4, Injectable as Injectable4, signal as signal5 } from "@angular/core";
|
|
1463
1725
|
|
|
1464
1726
|
// src/client/providerStatus.ts
|
|
1465
1727
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -1550,10 +1812,10 @@ var _init = __decoratorStart(undefined);
|
|
|
1550
1812
|
class VoiceProviderStatusService {
|
|
1551
1813
|
connect(path = "/api/provider-status", options = {}) {
|
|
1552
1814
|
const store = createVoiceProviderStatusStore(path, options);
|
|
1553
|
-
const errorSignal =
|
|
1554
|
-
const isLoadingSignal =
|
|
1555
|
-
const providersSignal =
|
|
1556
|
-
const updatedAtSignal =
|
|
1815
|
+
const errorSignal = signal5(null);
|
|
1816
|
+
const isLoadingSignal = signal5(false);
|
|
1817
|
+
const providersSignal = signal5([]);
|
|
1818
|
+
const updatedAtSignal = signal5(undefined);
|
|
1557
1819
|
const sync = () => {
|
|
1558
1820
|
const snapshot = store.getSnapshot();
|
|
1559
1821
|
errorSignal.set(snapshot.error);
|
|
@@ -1582,7 +1844,7 @@ __runInitializers(_init, 1, VoiceProviderStatusService);
|
|
|
1582
1844
|
__decoratorMetadata(_init, VoiceProviderStatusService);
|
|
1583
1845
|
let _VoiceProviderStatusService = VoiceProviderStatusService;
|
|
1584
1846
|
// src/angular/voice-workflow-status.service.ts
|
|
1585
|
-
import { computed as computed5, Injectable as Injectable5, signal as
|
|
1847
|
+
import { computed as computed5, Injectable as Injectable5, signal as signal6 } from "@angular/core";
|
|
1586
1848
|
|
|
1587
1849
|
// src/client/workflowStatus.ts
|
|
1588
1850
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -1672,10 +1934,10 @@ var _init = __decoratorStart(undefined);
|
|
|
1672
1934
|
class VoiceWorkflowStatusService {
|
|
1673
1935
|
connect(path = "/evals/scenarios/json", options = {}) {
|
|
1674
1936
|
const store = createVoiceWorkflowStatusStore(path, options);
|
|
1675
|
-
const errorSignal =
|
|
1676
|
-
const isLoadingSignal =
|
|
1677
|
-
const reportSignal =
|
|
1678
|
-
const updatedAtSignal =
|
|
1937
|
+
const errorSignal = signal6(null);
|
|
1938
|
+
const isLoadingSignal = signal6(false);
|
|
1939
|
+
const reportSignal = signal6(undefined);
|
|
1940
|
+
const updatedAtSignal = signal6(undefined);
|
|
1679
1941
|
const sync = () => {
|
|
1680
1942
|
const snapshot = store.getSnapshot();
|
|
1681
1943
|
errorSignal.set(snapshot.error);
|
|
@@ -1709,6 +1971,7 @@ export {
|
|
|
1709
1971
|
VoiceWorkflowStatusService,
|
|
1710
1972
|
VoiceStreamService,
|
|
1711
1973
|
VoiceProviderStatusService,
|
|
1974
|
+
VoiceOpsStatusComponent,
|
|
1712
1975
|
VoiceControllerService,
|
|
1713
1976
|
VoiceAppKitStatusService
|
|
1714
1977
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { OnDestroy, OnInit } from '@angular/core';
|
|
2
|
+
import { type VoiceOpsStatusViewModel } from '../client/opsStatusWidget';
|
|
3
|
+
export declare class VoiceOpsStatusComponent implements OnDestroy, OnInit {
|
|
4
|
+
description?: string;
|
|
5
|
+
includeLinks: boolean;
|
|
6
|
+
intervalMs?: number;
|
|
7
|
+
path: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
private cleanup;
|
|
10
|
+
private store?;
|
|
11
|
+
model: import("@angular/core").WritableSignal<VoiceOpsStatusViewModel>;
|
|
12
|
+
ngOnInit(): void;
|
|
13
|
+
ngOnDestroy(): void;
|
|
14
|
+
private options;
|
|
15
|
+
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -6,8 +6,10 @@ export { bindVoiceBargeIn, createVoiceDuplexController } from './duplex';
|
|
|
6
6
|
export { bindVoiceHTMX } from './htmx';
|
|
7
7
|
export { createMicrophoneCapture } from './microphone';
|
|
8
8
|
export { createVoiceAppKitStatusStore, fetchVoiceAppKitStatus } from './appKitStatus';
|
|
9
|
+
export { createVoiceOpsStatusViewModel, defineVoiceOpsStatusElement, getVoiceOpsStatusCSS, getVoiceOpsStatusLabel, mountVoiceOpsStatus, renderVoiceOpsStatusHTML } from './opsStatusWidget';
|
|
9
10
|
export { createVoiceProviderStatusStore, fetchVoiceProviderStatus } from './providerStatus';
|
|
10
11
|
export { createVoiceWorkflowStatusStore, fetchVoiceWorkflowStatus } from './workflowStatus';
|
|
11
12
|
export type { VoiceAppKitStatusClientOptions, VoiceAppKitStatusSnapshot } from './appKitStatus';
|
|
13
|
+
export type { VoiceOpsStatusSurfaceView, VoiceOpsStatusViewModel, VoiceOpsStatusWidgetOptions } from './opsStatusWidget';
|
|
12
14
|
export type { VoiceProviderStatusClientOptions, VoiceProviderStatusSnapshot } from './providerStatus';
|
|
13
15
|
export type { VoiceWorkflowStatusClientOptions, VoiceWorkflowStatusSnapshot } from './workflowStatus';
|
package/dist/client/index.js
CHANGED
|
@@ -1701,6 +1701,130 @@ var createVoiceAppKitStatusStore = (path = "/app-kit/status", options = {}) => {
|
|
|
1701
1701
|
}
|
|
1702
1702
|
};
|
|
1703
1703
|
};
|
|
1704
|
+
// src/client/opsStatusWidget.ts
|
|
1705
|
+
var DEFAULT_TITLE = "Voice Ops Status";
|
|
1706
|
+
var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from the AbsoluteJS voice app kit.";
|
|
1707
|
+
var SURFACE_LABELS = {
|
|
1708
|
+
handoffs: "Handoffs",
|
|
1709
|
+
providers: "Providers",
|
|
1710
|
+
quality: "Quality",
|
|
1711
|
+
sessions: "Sessions",
|
|
1712
|
+
workflows: "Workflows"
|
|
1713
|
+
};
|
|
1714
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1715
|
+
var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
|
|
1716
|
+
var surfaceDetail = (surface) => {
|
|
1717
|
+
const total = readNumber(surface, "total");
|
|
1718
|
+
const failed = readNumber(surface, "failed");
|
|
1719
|
+
const degraded = readNumber(surface, "degraded");
|
|
1720
|
+
const source = surface && typeof surface === "object" && "source" in surface && typeof surface.source === "string" ? ` from ${surface.source}` : "";
|
|
1721
|
+
if (degraded > 0) {
|
|
1722
|
+
return `${degraded} degraded of ${total}`;
|
|
1723
|
+
}
|
|
1724
|
+
if (failed > 0) {
|
|
1725
|
+
return `${failed} failing of ${total}${source}`;
|
|
1726
|
+
}
|
|
1727
|
+
return total > 0 ? `${total} passing${source}` : `No failures${source}`;
|
|
1728
|
+
};
|
|
1729
|
+
var getVoiceOpsStatusLabel = (report, error) => {
|
|
1730
|
+
if (error) {
|
|
1731
|
+
return "Unavailable";
|
|
1732
|
+
}
|
|
1733
|
+
if (!report) {
|
|
1734
|
+
return "Checking";
|
|
1735
|
+
}
|
|
1736
|
+
return report.status === "pass" ? "Passing" : "Needs attention";
|
|
1737
|
+
};
|
|
1738
|
+
var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
1739
|
+
const report = snapshot.report;
|
|
1740
|
+
const surfaces = Object.entries(report?.surfaces ?? {}).map(([id, surface]) => {
|
|
1741
|
+
const failed = readNumber(surface, "failed") || readNumber(surface, "degraded");
|
|
1742
|
+
const total = readNumber(surface, "total");
|
|
1743
|
+
const status = surface && typeof surface === "object" && "status" in surface ? surface.status ?? "pass" : "pass";
|
|
1744
|
+
return {
|
|
1745
|
+
detail: surfaceDetail(surface),
|
|
1746
|
+
failed,
|
|
1747
|
+
id,
|
|
1748
|
+
label: SURFACE_LABELS[id] ?? id,
|
|
1749
|
+
status,
|
|
1750
|
+
total
|
|
1751
|
+
};
|
|
1752
|
+
});
|
|
1753
|
+
return {
|
|
1754
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
1755
|
+
error: snapshot.error,
|
|
1756
|
+
isLoading: snapshot.isLoading,
|
|
1757
|
+
label: getVoiceOpsStatusLabel(report, snapshot.error),
|
|
1758
|
+
links: options.includeLinks === false ? [] : report?.links ?? [],
|
|
1759
|
+
passed: report?.passed ?? 0,
|
|
1760
|
+
status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
|
|
1761
|
+
surfaces,
|
|
1762
|
+
title: options.title ?? DEFAULT_TITLE,
|
|
1763
|
+
total: report?.total ?? 0,
|
|
1764
|
+
updatedAt: snapshot.updatedAt
|
|
1765
|
+
};
|
|
1766
|
+
};
|
|
1767
|
+
var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
|
|
1768
|
+
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
1769
|
+
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml(surface.status)}">
|
|
1770
|
+
<span>${escapeHtml(surface.label)}</span>
|
|
1771
|
+
<strong>${escapeHtml(surface.detail)}</strong>
|
|
1772
|
+
</li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
|
|
1773
|
+
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>` : "";
|
|
1774
|
+
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml(model.status)}">
|
|
1775
|
+
<header class="absolute-voice-ops-status__header">
|
|
1776
|
+
<span class="absolute-voice-ops-status__eyebrow">${escapeHtml(model.title)}</span>
|
|
1777
|
+
<strong class="absolute-voice-ops-status__label">${escapeHtml(model.label)}</strong>
|
|
1778
|
+
</header>
|
|
1779
|
+
<p class="absolute-voice-ops-status__description">${escapeHtml(model.description)}</p>
|
|
1780
|
+
<div class="absolute-voice-ops-status__summary">
|
|
1781
|
+
<span>${model.passed} passing</span>
|
|
1782
|
+
<span>${Math.max(model.total - model.passed, 0)} failing</span>
|
|
1783
|
+
<span>${model.total} checks</span>
|
|
1784
|
+
</div>
|
|
1785
|
+
<ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
|
|
1786
|
+
${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml(model.error)}</p>` : ""}
|
|
1787
|
+
${links}
|
|
1788
|
+
</section>`;
|
|
1789
|
+
};
|
|
1790
|
+
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}`;
|
|
1791
|
+
var mountVoiceOpsStatus = (element, path = "/app-kit/status", options = {}) => {
|
|
1792
|
+
const store = createVoiceAppKitStatusStore(path, options);
|
|
1793
|
+
const render = () => {
|
|
1794
|
+
element.innerHTML = renderVoiceOpsStatusHTML(store.getSnapshot(), options);
|
|
1795
|
+
};
|
|
1796
|
+
const unsubscribe = store.subscribe(render);
|
|
1797
|
+
render();
|
|
1798
|
+
store.refresh().catch(() => {});
|
|
1799
|
+
return {
|
|
1800
|
+
close: () => {
|
|
1801
|
+
unsubscribe();
|
|
1802
|
+
store.close();
|
|
1803
|
+
},
|
|
1804
|
+
refresh: store.refresh
|
|
1805
|
+
};
|
|
1806
|
+
};
|
|
1807
|
+
var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
1808
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
customElements.define(tagName, class AbsoluteVoiceOpsStatusElement extends HTMLElement {
|
|
1812
|
+
mounted;
|
|
1813
|
+
connectedCallback() {
|
|
1814
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
1815
|
+
this.mounted = mountVoiceOpsStatus(this, this.getAttribute("path") ?? "/app-kit/status", {
|
|
1816
|
+
description: this.getAttribute("description") ?? undefined,
|
|
1817
|
+
includeLinks: this.getAttribute("include-links") !== "false",
|
|
1818
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
1819
|
+
title: this.getAttribute("title") ?? undefined
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
disconnectedCallback() {
|
|
1823
|
+
this.mounted?.close();
|
|
1824
|
+
this.mounted = undefined;
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
};
|
|
1704
1828
|
// src/client/providerStatus.ts
|
|
1705
1829
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
1706
1830
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -1859,13 +1983,19 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
1859
1983
|
};
|
|
1860
1984
|
};
|
|
1861
1985
|
export {
|
|
1986
|
+
renderVoiceOpsStatusHTML,
|
|
1987
|
+
mountVoiceOpsStatus,
|
|
1988
|
+
getVoiceOpsStatusLabel,
|
|
1989
|
+
getVoiceOpsStatusCSS,
|
|
1862
1990
|
fetchVoiceWorkflowStatus,
|
|
1863
1991
|
fetchVoiceProviderStatus,
|
|
1864
1992
|
fetchVoiceAppKitStatus,
|
|
1993
|
+
defineVoiceOpsStatusElement,
|
|
1865
1994
|
decodeVoiceAudioChunk,
|
|
1866
1995
|
createVoiceWorkflowStatusStore,
|
|
1867
1996
|
createVoiceStream,
|
|
1868
1997
|
createVoiceProviderStatusStore,
|
|
1998
|
+
createVoiceOpsStatusViewModel,
|
|
1869
1999
|
createVoiceDuplexController,
|
|
1870
2000
|
createVoiceController,
|
|
1871
2001
|
createVoiceConnection,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { VoiceAppKitStatusReport } from '../appKit';
|
|
2
|
+
import { type VoiceAppKitStatusClientOptions, type VoiceAppKitStatusSnapshot } from './appKitStatus';
|
|
3
|
+
export type VoiceOpsStatusSurfaceView = {
|
|
4
|
+
detail: string;
|
|
5
|
+
failed: number;
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
status: 'pass' | 'fail';
|
|
9
|
+
total: number;
|
|
10
|
+
};
|
|
11
|
+
export type VoiceOpsStatusViewModel = {
|
|
12
|
+
description: string;
|
|
13
|
+
error: string | null;
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
label: string;
|
|
16
|
+
links: Array<{
|
|
17
|
+
href: string;
|
|
18
|
+
label: string;
|
|
19
|
+
}>;
|
|
20
|
+
passed: number;
|
|
21
|
+
status: 'pass' | 'fail' | 'loading' | 'error';
|
|
22
|
+
surfaces: VoiceOpsStatusSurfaceView[];
|
|
23
|
+
title: string;
|
|
24
|
+
total: number;
|
|
25
|
+
updatedAt?: number;
|
|
26
|
+
};
|
|
27
|
+
export type VoiceOpsStatusWidgetOptions = VoiceAppKitStatusClientOptions & {
|
|
28
|
+
description?: string;
|
|
29
|
+
includeLinks?: boolean;
|
|
30
|
+
title?: string;
|
|
31
|
+
};
|
|
32
|
+
export declare const getVoiceOpsStatusLabel: (report?: VoiceAppKitStatusReport | null, error?: string | null) => "Unavailable" | "Checking" | "Passing" | "Needs attention";
|
|
33
|
+
export declare const createVoiceOpsStatusViewModel: (snapshot: VoiceAppKitStatusSnapshot, options?: VoiceOpsStatusWidgetOptions) => VoiceOpsStatusViewModel;
|
|
34
|
+
export declare const renderVoiceOpsStatusHTML: (snapshot: VoiceAppKitStatusSnapshot, options?: VoiceOpsStatusWidgetOptions) => string;
|
|
35
|
+
export declare const getVoiceOpsStatusCSS: () => string;
|
|
36
|
+
export declare const mountVoiceOpsStatus: (element: Element, path?: string, options?: VoiceOpsStatusWidgetOptions) => {
|
|
37
|
+
close: () => void;
|
|
38
|
+
refresh: () => Promise<VoiceAppKitStatusReport | undefined>;
|
|
39
|
+
};
|
|
40
|
+
export declare const defineVoiceOpsStatusElement: (tagName?: string) => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type VoiceOpsStatusWidgetOptions } from '../client/opsStatusWidget';
|
|
2
|
+
export type VoiceOpsStatusProps = VoiceOpsStatusWidgetOptions & {
|
|
3
|
+
className?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const VoiceOpsStatus: ({ className, path, ...options }: VoiceOpsStatusProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/react/index.d.ts
CHANGED