@absolutejs/voice 0.0.22-beta.152 → 0.0.22-beta.154

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.
@@ -193,10 +193,224 @@ VoiceOpsStatusService = __decorateElement(_init, 0, "VoiceOpsStatusService", _de
193
193
  __runInitializers(_init, 1, VoiceOpsStatusService);
194
194
  __decoratorMetadata(_init, VoiceOpsStatusService);
195
195
  let _VoiceOpsStatusService = VoiceOpsStatusService;
196
- // src/angular/voice-delivery-runtime.service.ts
196
+ // src/angular/voice-ops-action-center.service.ts
197
197
  import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
198
198
 
199
+ // src/client/opsActionCenter.ts
200
+ var createVoiceOpsActionCenterActions = (options = {}) => {
201
+ const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
202
+ const actions = [];
203
+ if (options.includeProductionReadiness !== false) {
204
+ actions.push({
205
+ description: "Refresh the production readiness report.",
206
+ id: "production-readiness",
207
+ label: "Refresh readiness",
208
+ method: "GET",
209
+ path: options.productionReadinessPath ?? "/api/production-readiness"
210
+ });
211
+ }
212
+ if (options.includeDeliveryRuntime !== false) {
213
+ actions.push({
214
+ description: "Drain pending and failed audit/trace deliveries.",
215
+ id: "delivery-runtime.tick",
216
+ label: "Tick delivery workers",
217
+ method: "POST",
218
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
219
+ }, {
220
+ description: "Move reviewed dead letters back to live delivery queues.",
221
+ id: "delivery-runtime.requeue-dead-letters",
222
+ label: "Requeue dead letters",
223
+ method: "POST",
224
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
225
+ });
226
+ }
227
+ if (options.includeTurnLatencyProof !== false) {
228
+ actions.push({
229
+ description: "Run the synthetic turn latency proof.",
230
+ id: "turn-latency.proof",
231
+ label: "Run latency proof",
232
+ method: "POST",
233
+ path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
234
+ });
235
+ }
236
+ if (options.includeProviderSimulation !== false) {
237
+ const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
238
+ for (const provider of options.providers ?? []) {
239
+ actions.push({
240
+ description: `Simulate ${provider} provider failure.`,
241
+ id: `provider.${provider}.failure`,
242
+ label: `Simulate ${provider} failure`,
243
+ method: "POST",
244
+ path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
245
+ }, {
246
+ description: `Mark ${provider} provider recovered.`,
247
+ id: `provider.${provider}.recovery`,
248
+ label: `Recover ${provider}`,
249
+ method: "POST",
250
+ path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
251
+ });
252
+ }
253
+ }
254
+ return actions;
255
+ };
256
+ var runVoiceOpsAction = async (action, options = {}) => {
257
+ const fetchImpl = options.fetch ?? globalThis.fetch;
258
+ const response = await fetchImpl(action.path, {
259
+ method: action.method ?? "POST"
260
+ });
261
+ const body = await response.json().catch(() => null);
262
+ if (!response.ok) {
263
+ const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
264
+ throw new Error(message);
265
+ }
266
+ return {
267
+ actionId: action.id,
268
+ body,
269
+ ok: response.ok,
270
+ ranAt: Date.now(),
271
+ status: response.status
272
+ };
273
+ };
274
+ var createVoiceOpsActionCenterStore = (options = {}) => {
275
+ const listeners = new Set;
276
+ let closed = false;
277
+ let timer;
278
+ let snapshot = {
279
+ actions: options.actions ?? createVoiceOpsActionCenterActions(),
280
+ error: null,
281
+ isRunning: false
282
+ };
283
+ const emit = () => {
284
+ for (const listener of listeners) {
285
+ listener();
286
+ }
287
+ };
288
+ const setActions = (actions) => {
289
+ snapshot = { ...snapshot, actions, updatedAt: Date.now() };
290
+ emit();
291
+ };
292
+ const run = async (actionId) => {
293
+ if (closed) {
294
+ return snapshot.lastResult;
295
+ }
296
+ const action = snapshot.actions.find((item) => item.id === actionId);
297
+ if (!action) {
298
+ throw new Error(`Voice ops action "${actionId}" is not configured.`);
299
+ }
300
+ if (action.disabled) {
301
+ throw new Error(`Voice ops action "${actionId}" is disabled.`);
302
+ }
303
+ snapshot = {
304
+ ...snapshot,
305
+ error: null,
306
+ isRunning: true,
307
+ runningActionId: action.id
308
+ };
309
+ emit();
310
+ try {
311
+ const result = await runVoiceOpsAction(action, options);
312
+ snapshot = {
313
+ ...snapshot,
314
+ error: null,
315
+ isRunning: false,
316
+ lastResult: result,
317
+ runningActionId: undefined,
318
+ updatedAt: Date.now()
319
+ };
320
+ emit();
321
+ return result;
322
+ } catch (error) {
323
+ snapshot = {
324
+ ...snapshot,
325
+ error: error instanceof Error ? error.message : String(error),
326
+ isRunning: false,
327
+ runningActionId: undefined
328
+ };
329
+ emit();
330
+ throw error;
331
+ }
332
+ };
333
+ const close = () => {
334
+ closed = true;
335
+ if (timer) {
336
+ clearInterval(timer);
337
+ timer = undefined;
338
+ }
339
+ listeners.clear();
340
+ };
341
+ if (options.intervalMs && options.intervalMs > 0) {
342
+ timer = setInterval(() => {
343
+ emit();
344
+ }, options.intervalMs);
345
+ }
346
+ return {
347
+ close,
348
+ getServerSnapshot: () => snapshot,
349
+ getSnapshot: () => snapshot,
350
+ run,
351
+ setActions,
352
+ subscribe: (listener) => {
353
+ listeners.add(listener);
354
+ return () => {
355
+ listeners.delete(listener);
356
+ };
357
+ }
358
+ };
359
+ };
360
+
361
+ // src/angular/voice-ops-action-center.service.ts
362
+ var _dec = [
363
+ Injectable2({ providedIn: "root" })
364
+ ];
365
+ var _init = __decoratorStart(undefined);
366
+
367
+ class VoiceOpsActionCenterService {
368
+ connect(options = {}) {
369
+ const store = createVoiceOpsActionCenterStore(options);
370
+ const actionsSignal = signal2([]);
371
+ const errorSignal = signal2(null);
372
+ const isRunningSignal = signal2(false);
373
+ const lastResultSignal = signal2(undefined);
374
+ const runningActionIdSignal = signal2(undefined);
375
+ const sync = () => {
376
+ const snapshot = store.getSnapshot();
377
+ actionsSignal.set(snapshot.actions);
378
+ errorSignal.set(snapshot.error);
379
+ isRunningSignal.set(snapshot.isRunning);
380
+ lastResultSignal.set(snapshot.lastResult);
381
+ runningActionIdSignal.set(snapshot.runningActionId);
382
+ };
383
+ const unsubscribe = store.subscribe(sync);
384
+ sync();
385
+ return {
386
+ actions: computed2(() => actionsSignal()),
387
+ close: () => {
388
+ unsubscribe();
389
+ store.close();
390
+ },
391
+ error: computed2(() => errorSignal()),
392
+ isRunning: computed2(() => isRunningSignal()),
393
+ lastResult: computed2(() => lastResultSignal()),
394
+ run: store.run,
395
+ runningActionId: computed2(() => runningActionIdSignal()),
396
+ setActions: store.setActions
397
+ };
398
+ }
399
+ }
400
+ VoiceOpsActionCenterService = __decorateElement(_init, 0, "VoiceOpsActionCenterService", _dec, VoiceOpsActionCenterService);
401
+ __runInitializers(_init, 1, VoiceOpsActionCenterService);
402
+ __decoratorMetadata(_init, VoiceOpsActionCenterService);
403
+ let _VoiceOpsActionCenterService = VoiceOpsActionCenterService;
404
+ // src/angular/voice-delivery-runtime.service.ts
405
+ import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
406
+
199
407
  // src/client/deliveryRuntime.ts
408
+ var getDefaultActionPath = (path, action, options) => {
409
+ if (action === "tick") {
410
+ return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
411
+ }
412
+ return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
413
+ };
200
414
  var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
201
415
  const fetchImpl = options.fetch ?? globalThis.fetch;
202
416
  const response = await fetchImpl(path);
@@ -205,11 +419,29 @@ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", opt
205
419
  }
206
420
  return await response.json();
207
421
  };
422
+ var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
423
+ const fetchImpl = options.fetch ?? globalThis.fetch;
424
+ const response = await fetchImpl(getDefaultActionPath(path, action, options), {
425
+ method: "POST"
426
+ });
427
+ if (!response.ok) {
428
+ throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
429
+ }
430
+ const body = await response.json();
431
+ return {
432
+ action,
433
+ result: body.result,
434
+ summary: body.summary,
435
+ updatedAt: Date.now()
436
+ };
437
+ };
208
438
  var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
209
439
  const listeners = new Set;
210
440
  let closed = false;
211
441
  let timer;
212
442
  let snapshot = {
443
+ actionError: null,
444
+ actionStatus: "idle",
213
445
  error: null,
214
446
  isLoading: false
215
447
  };
@@ -231,6 +463,7 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
231
463
  try {
232
464
  const report = await fetchVoiceDeliveryRuntime(path, options);
233
465
  snapshot = {
466
+ ...snapshot,
234
467
  error: null,
235
468
  isLoading: false,
236
469
  report,
@@ -248,6 +481,37 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
248
481
  throw error;
249
482
  }
250
483
  };
484
+ const runAction = async (action) => {
485
+ if (closed) {
486
+ return snapshot.lastAction;
487
+ }
488
+ snapshot = {
489
+ ...snapshot,
490
+ actionError: null,
491
+ actionStatus: "running"
492
+ };
493
+ emit();
494
+ try {
495
+ const result = await runVoiceDeliveryRuntimeAction(action, path, options);
496
+ snapshot = {
497
+ ...snapshot,
498
+ actionError: null,
499
+ actionStatus: "completed",
500
+ lastAction: result
501
+ };
502
+ emit();
503
+ await refresh();
504
+ return result;
505
+ } catch (error) {
506
+ snapshot = {
507
+ ...snapshot,
508
+ actionError: error instanceof Error ? error.message : String(error),
509
+ actionStatus: "failed"
510
+ };
511
+ emit();
512
+ throw error;
513
+ }
514
+ };
251
515
  const close = () => {
252
516
  closed = true;
253
517
  if (timer) {
@@ -265,7 +529,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
265
529
  close,
266
530
  getServerSnapshot: () => snapshot,
267
531
  getSnapshot: () => snapshot,
532
+ requeueDeadLetters: () => runAction("requeue-dead-letters"),
268
533
  refresh,
534
+ tick: () => runAction("tick"),
269
535
  subscribe: (listener) => {
270
536
  listeners.add(listener);
271
537
  return () => {
@@ -277,19 +543,23 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
277
543
 
278
544
  // src/angular/voice-delivery-runtime.service.ts
279
545
  var _dec = [
280
- Injectable2({ providedIn: "root" })
546
+ Injectable3({ providedIn: "root" })
281
547
  ];
282
548
  var _init = __decoratorStart(undefined);
283
549
 
284
550
  class VoiceDeliveryRuntimeService {
285
551
  connect(path = "/api/voice-delivery-runtime", options = {}) {
286
552
  const store = createVoiceDeliveryRuntimeStore(path, options);
287
- const errorSignal = signal2(null);
288
- const isLoadingSignal = signal2(false);
289
- const reportSignal = signal2(undefined);
290
- const updatedAtSignal = signal2(undefined);
553
+ const actionErrorSignal = signal3(null);
554
+ const actionStatusSignal = signal3("idle");
555
+ const errorSignal = signal3(null);
556
+ const isLoadingSignal = signal3(false);
557
+ const reportSignal = signal3(undefined);
558
+ const updatedAtSignal = signal3(undefined);
291
559
  const sync = () => {
292
560
  const snapshot = store.getSnapshot();
561
+ actionErrorSignal.set(snapshot.actionError);
562
+ actionStatusSignal.set(snapshot.actionStatus);
293
563
  errorSignal.set(snapshot.error);
294
564
  isLoadingSignal.set(snapshot.isLoading);
295
565
  reportSignal.set(snapshot.report);
@@ -305,11 +575,15 @@ class VoiceDeliveryRuntimeService {
305
575
  unsubscribe();
306
576
  store.close();
307
577
  },
308
- error: computed2(() => errorSignal()),
309
- isLoading: computed2(() => isLoadingSignal()),
578
+ error: computed3(() => errorSignal()),
579
+ actionError: computed3(() => actionErrorSignal()),
580
+ actionStatus: computed3(() => actionStatusSignal()),
581
+ isLoading: computed3(() => isLoadingSignal()),
582
+ requeueDeadLetters: store.requeueDeadLetters,
310
583
  refresh: store.refresh,
311
- report: computed2(() => reportSignal()),
312
- updatedAt: computed2(() => updatedAtSignal())
584
+ report: computed3(() => reportSignal()),
585
+ tick: store.tick,
586
+ updatedAt: computed3(() => updatedAtSignal())
313
587
  };
314
588
  }
315
589
  }
@@ -318,7 +592,7 @@ __runInitializers(_init, 1, VoiceDeliveryRuntimeService);
318
592
  __decoratorMetadata(_init, VoiceDeliveryRuntimeService);
319
593
  let _VoiceDeliveryRuntimeService = VoiceDeliveryRuntimeService;
320
594
  // src/angular/voice-campaign-dialer-proof.service.ts
321
- import { computed as computed3, Injectable as Injectable3, signal as signal3 } from "@angular/core";
595
+ import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
322
596
 
323
597
  // src/client/campaignDialerProof.ts
324
598
  var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
@@ -440,18 +714,18 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
440
714
 
441
715
  // src/angular/voice-campaign-dialer-proof.service.ts
442
716
  var _dec = [
443
- Injectable3({ providedIn: "root" })
717
+ Injectable4({ providedIn: "root" })
444
718
  ];
445
719
  var _init = __decoratorStart(undefined);
446
720
 
447
721
  class VoiceCampaignDialerProofService {
448
722
  connect(path = "/api/voice/campaigns/dialer-proof", options = {}) {
449
723
  const store = createVoiceCampaignDialerProofStore(path, options);
450
- const errorSignal = signal3(null);
451
- const isLoadingSignal = signal3(false);
452
- const reportSignal = signal3(undefined);
453
- const statusSignal = signal3(undefined);
454
- const updatedAtSignal = signal3(undefined);
724
+ const errorSignal = signal4(null);
725
+ const isLoadingSignal = signal4(false);
726
+ const reportSignal = signal4(undefined);
727
+ const statusSignal = signal4(undefined);
728
+ const updatedAtSignal = signal4(undefined);
455
729
  const sync = () => {
456
730
  const snapshot = store.getSnapshot();
457
731
  errorSignal.set(snapshot.error);
@@ -468,13 +742,13 @@ class VoiceCampaignDialerProofService {
468
742
  unsubscribe();
469
743
  store.close();
470
744
  },
471
- error: computed3(() => errorSignal()),
472
- isLoading: computed3(() => isLoadingSignal()),
745
+ error: computed4(() => errorSignal()),
746
+ isLoading: computed4(() => isLoadingSignal()),
473
747
  refresh: store.refresh,
474
- report: computed3(() => reportSignal()),
748
+ report: computed4(() => reportSignal()),
475
749
  runProof: store.runProof,
476
- status: computed3(() => statusSignal()),
477
- updatedAt: computed3(() => updatedAtSignal())
750
+ status: computed4(() => statusSignal()),
751
+ updatedAt: computed4(() => updatedAtSignal())
478
752
  };
479
753
  }
480
754
  }
@@ -483,7 +757,7 @@ __runInitializers(_init, 1, VoiceCampaignDialerProofService);
483
757
  __decoratorMetadata(_init, VoiceCampaignDialerProofService);
484
758
  let _VoiceCampaignDialerProofService = VoiceCampaignDialerProofService;
485
759
  // src/angular/voice-stream.service.ts
486
- import { computed as computed4, Injectable as Injectable4, signal as signal4 } from "@angular/core";
760
+ import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
487
761
 
488
762
  // src/client/actions.ts
489
763
  var normalizeErrorMessage = (value) => {
@@ -1127,23 +1401,23 @@ var createVoiceStream = (path, options = {}) => {
1127
1401
 
1128
1402
  // src/angular/voice-stream.service.ts
1129
1403
  var _dec = [
1130
- Injectable4({ providedIn: "root" })
1404
+ Injectable5({ providedIn: "root" })
1131
1405
  ];
1132
1406
  var _init = __decoratorStart(undefined);
1133
1407
 
1134
1408
  class VoiceStreamService {
1135
1409
  connect(path, options = {}) {
1136
1410
  const stream = createVoiceStream(path, options);
1137
- const assistantAudioSignal = signal4([]);
1138
- const assistantTextsSignal = signal4([]);
1139
- const callSignal = signal4(null);
1140
- const errorSignal = signal4(null);
1141
- const isConnectedSignal = signal4(false);
1142
- const partialSignal = signal4("");
1143
- const reconnectSignal = signal4(stream.reconnect);
1144
- const sessionIdSignal = signal4(stream.sessionId);
1145
- const statusSignal = signal4(stream.status);
1146
- const turnsSignal = signal4([]);
1411
+ const assistantAudioSignal = signal5([]);
1412
+ const assistantTextsSignal = signal5([]);
1413
+ const callSignal = signal5(null);
1414
+ const errorSignal = signal5(null);
1415
+ const isConnectedSignal = signal5(false);
1416
+ const partialSignal = signal5("");
1417
+ const reconnectSignal = signal5(stream.reconnect);
1418
+ const sessionIdSignal = signal5(stream.sessionId);
1419
+ const statusSignal = signal5(stream.status);
1420
+ const turnsSignal = signal5([]);
1147
1421
  const sync = () => {
1148
1422
  assistantAudioSignal.set([...stream.assistantAudio]);
1149
1423
  assistantTextsSignal.set([...stream.assistantTexts]);
@@ -1159,23 +1433,23 @@ class VoiceStreamService {
1159
1433
  const unsubscribe = stream.subscribe(sync);
1160
1434
  sync();
1161
1435
  return {
1162
- assistantAudio: computed4(() => assistantAudioSignal()),
1163
- assistantTexts: computed4(() => assistantTextsSignal()),
1164
- call: computed4(() => callSignal()),
1436
+ assistantAudio: computed5(() => assistantAudioSignal()),
1437
+ assistantTexts: computed5(() => assistantTextsSignal()),
1438
+ call: computed5(() => callSignal()),
1165
1439
  callControl: (message) => stream.callControl(message),
1166
1440
  close: () => {
1167
1441
  unsubscribe();
1168
1442
  stream.close();
1169
1443
  },
1170
1444
  endTurn: () => stream.endTurn(),
1171
- error: computed4(() => errorSignal()),
1172
- isConnected: computed4(() => isConnectedSignal()),
1173
- partial: computed4(() => partialSignal()),
1174
- reconnect: computed4(() => reconnectSignal()),
1445
+ error: computed5(() => errorSignal()),
1446
+ isConnected: computed5(() => isConnectedSignal()),
1447
+ partial: computed5(() => partialSignal()),
1448
+ reconnect: computed5(() => reconnectSignal()),
1175
1449
  sendAudio: (audio) => stream.sendAudio(audio),
1176
- sessionId: computed4(() => sessionIdSignal()),
1177
- status: computed4(() => statusSignal()),
1178
- turns: computed4(() => turnsSignal())
1450
+ sessionId: computed5(() => sessionIdSignal()),
1451
+ status: computed5(() => statusSignal()),
1452
+ turns: computed5(() => turnsSignal())
1179
1453
  };
1180
1454
  }
1181
1455
  }
@@ -1184,7 +1458,7 @@ __runInitializers(_init, 1, VoiceStreamService);
1184
1458
  __decoratorMetadata(_init, VoiceStreamService);
1185
1459
  let _VoiceStreamService = VoiceStreamService;
1186
1460
  // src/angular/voice-controller.service.ts
1187
- import { computed as computed5, Injectable as Injectable5, signal as signal5 } from "@angular/core";
1461
+ import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
1188
1462
 
1189
1463
  // src/client/htmx.ts
1190
1464
  var DEFAULT_EVENT_NAME = "voice-refresh";
@@ -1829,24 +2103,24 @@ var createVoiceController = (path, options = {}) => {
1829
2103
 
1830
2104
  // src/angular/voice-controller.service.ts
1831
2105
  var _dec = [
1832
- Injectable5({ providedIn: "root" })
2106
+ Injectable6({ providedIn: "root" })
1833
2107
  ];
1834
2108
  var _init = __decoratorStart(undefined);
1835
2109
 
1836
2110
  class VoiceControllerService {
1837
2111
  connect(path, options = {}) {
1838
2112
  const controller = createVoiceController(path, options);
1839
- const assistantAudioSignal = signal5([]);
1840
- const assistantTextsSignal = signal5([]);
1841
- const errorSignal = signal5(null);
1842
- const isConnectedSignal = signal5(false);
1843
- const isRecordingSignal = signal5(false);
1844
- const partialSignal = signal5("");
1845
- const reconnectSignal = signal5(controller.reconnect);
1846
- const recordingErrorSignal = signal5(null);
1847
- const sessionIdSignal = signal5(controller.sessionId);
1848
- const statusSignal = signal5(controller.status);
1849
- const turnsSignal = signal5([]);
2113
+ const assistantAudioSignal = signal6([]);
2114
+ const assistantTextsSignal = signal6([]);
2115
+ const errorSignal = signal6(null);
2116
+ const isConnectedSignal = signal6(false);
2117
+ const isRecordingSignal = signal6(false);
2118
+ const partialSignal = signal6("");
2119
+ const reconnectSignal = signal6(controller.reconnect);
2120
+ const recordingErrorSignal = signal6(null);
2121
+ const sessionIdSignal = signal6(controller.sessionId);
2122
+ const statusSignal = signal6(controller.status);
2123
+ const turnsSignal = signal6([]);
1850
2124
  const sync = () => {
1851
2125
  assistantAudioSignal.set([...controller.assistantAudio]);
1852
2126
  assistantTextsSignal.set([...controller.assistantTexts]);
@@ -1863,27 +2137,27 @@ class VoiceControllerService {
1863
2137
  const unsubscribe = controller.subscribe(sync);
1864
2138
  sync();
1865
2139
  return {
1866
- assistantAudio: computed5(() => assistantAudioSignal()),
1867
- assistantTexts: computed5(() => assistantTextsSignal()),
2140
+ assistantAudio: computed6(() => assistantAudioSignal()),
2141
+ assistantTexts: computed6(() => assistantTextsSignal()),
1868
2142
  bindHTMX: controller.bindHTMX,
1869
2143
  close: () => {
1870
2144
  unsubscribe();
1871
2145
  controller.close();
1872
2146
  },
1873
2147
  endTurn: () => controller.endTurn(),
1874
- error: computed5(() => errorSignal()),
1875
- isConnected: computed5(() => isConnectedSignal()),
1876
- isRecording: computed5(() => isRecordingSignal()),
1877
- partial: computed5(() => partialSignal()),
1878
- reconnect: computed5(() => reconnectSignal()),
1879
- recordingError: computed5(() => recordingErrorSignal()),
2148
+ error: computed6(() => errorSignal()),
2149
+ isConnected: computed6(() => isConnectedSignal()),
2150
+ isRecording: computed6(() => isRecordingSignal()),
2151
+ partial: computed6(() => partialSignal()),
2152
+ reconnect: computed6(() => reconnectSignal()),
2153
+ recordingError: computed6(() => recordingErrorSignal()),
1880
2154
  sendAudio: (audio) => controller.sendAudio(audio),
1881
- sessionId: computed5(() => sessionIdSignal()),
2155
+ sessionId: computed6(() => sessionIdSignal()),
1882
2156
  startRecording: () => controller.startRecording(),
1883
- status: computed5(() => statusSignal()),
2157
+ status: computed6(() => statusSignal()),
1884
2158
  stopRecording: () => controller.stopRecording(),
1885
2159
  toggleRecording: () => controller.toggleRecording(),
1886
- turns: computed5(() => turnsSignal())
2160
+ turns: computed6(() => turnsSignal())
1887
2161
  };
1888
2162
  }
1889
2163
  }
@@ -1892,7 +2166,7 @@ __runInitializers(_init, 1, VoiceControllerService);
1892
2166
  __decoratorMetadata(_init, VoiceControllerService);
1893
2167
  let _VoiceControllerService = VoiceControllerService;
1894
2168
  // src/angular/voice-provider-capabilities.service.ts
1895
- import { computed as computed6, Injectable as Injectable6, signal as signal6 } from "@angular/core";
2169
+ import { computed as computed7, Injectable as Injectable7, signal as signal7 } from "@angular/core";
1896
2170
 
1897
2171
  // src/client/providerCapabilities.ts
1898
2172
  var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
@@ -1975,17 +2249,17 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
1975
2249
 
1976
2250
  // src/angular/voice-provider-capabilities.service.ts
1977
2251
  var _dec = [
1978
- Injectable6({ providedIn: "root" })
2252
+ Injectable7({ providedIn: "root" })
1979
2253
  ];
1980
2254
  var _init = __decoratorStart(undefined);
1981
2255
 
1982
2256
  class VoiceProviderCapabilitiesService {
1983
2257
  connect(path = "/api/provider-capabilities", options = {}) {
1984
2258
  const store = createVoiceProviderCapabilitiesStore(path, options);
1985
- const errorSignal = signal6(null);
1986
- const isLoadingSignal = signal6(false);
1987
- const reportSignal = signal6(undefined);
1988
- const updatedAtSignal = signal6(undefined);
2259
+ const errorSignal = signal7(null);
2260
+ const isLoadingSignal = signal7(false);
2261
+ const reportSignal = signal7(undefined);
2262
+ const updatedAtSignal = signal7(undefined);
1989
2263
  const sync = () => {
1990
2264
  const snapshot = store.getSnapshot();
1991
2265
  errorSignal.set(snapshot.error);
@@ -2001,11 +2275,11 @@ class VoiceProviderCapabilitiesService {
2001
2275
  unsubscribe();
2002
2276
  store.close();
2003
2277
  },
2004
- error: computed6(() => errorSignal()),
2005
- isLoading: computed6(() => isLoadingSignal()),
2278
+ error: computed7(() => errorSignal()),
2279
+ isLoading: computed7(() => isLoadingSignal()),
2006
2280
  refresh: store.refresh,
2007
- report: computed6(() => reportSignal()),
2008
- updatedAt: computed6(() => updatedAtSignal())
2281
+ report: computed7(() => reportSignal()),
2282
+ updatedAt: computed7(() => updatedAtSignal())
2009
2283
  };
2010
2284
  }
2011
2285
  }
@@ -2014,7 +2288,7 @@ __runInitializers(_init, 1, VoiceProviderCapabilitiesService);
2014
2288
  __decoratorMetadata(_init, VoiceProviderCapabilitiesService);
2015
2289
  let _VoiceProviderCapabilitiesService = VoiceProviderCapabilitiesService;
2016
2290
  // src/angular/voice-provider-status.service.ts
2017
- import { computed as computed7, Injectable as Injectable7, signal as signal7 } from "@angular/core";
2291
+ import { computed as computed8, Injectable as Injectable8, signal as signal8 } from "@angular/core";
2018
2292
 
2019
2293
  // src/client/providerStatus.ts
2020
2294
  var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
@@ -2098,17 +2372,17 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
2098
2372
 
2099
2373
  // src/angular/voice-provider-status.service.ts
2100
2374
  var _dec = [
2101
- Injectable7({ providedIn: "root" })
2375
+ Injectable8({ providedIn: "root" })
2102
2376
  ];
2103
2377
  var _init = __decoratorStart(undefined);
2104
2378
 
2105
2379
  class VoiceProviderStatusService {
2106
2380
  connect(path = "/api/provider-status", options = {}) {
2107
2381
  const store = createVoiceProviderStatusStore(path, options);
2108
- const errorSignal = signal7(null);
2109
- const isLoadingSignal = signal7(false);
2110
- const providersSignal = signal7([]);
2111
- const updatedAtSignal = signal7(undefined);
2382
+ const errorSignal = signal8(null);
2383
+ const isLoadingSignal = signal8(false);
2384
+ const providersSignal = signal8([]);
2385
+ const updatedAtSignal = signal8(undefined);
2112
2386
  const sync = () => {
2113
2387
  const snapshot = store.getSnapshot();
2114
2388
  errorSignal.set(snapshot.error);
@@ -2124,11 +2398,11 @@ class VoiceProviderStatusService {
2124
2398
  unsubscribe();
2125
2399
  store.close();
2126
2400
  },
2127
- error: computed7(() => errorSignal()),
2128
- isLoading: computed7(() => isLoadingSignal()),
2129
- providers: computed7(() => providersSignal()),
2401
+ error: computed8(() => errorSignal()),
2402
+ isLoading: computed8(() => isLoadingSignal()),
2403
+ providers: computed8(() => providersSignal()),
2130
2404
  refresh: store.refresh,
2131
- updatedAt: computed7(() => updatedAtSignal())
2405
+ updatedAt: computed8(() => updatedAtSignal())
2132
2406
  };
2133
2407
  }
2134
2408
  }
@@ -2137,7 +2411,7 @@ __runInitializers(_init, 1, VoiceProviderStatusService);
2137
2411
  __decoratorMetadata(_init, VoiceProviderStatusService);
2138
2412
  let _VoiceProviderStatusService = VoiceProviderStatusService;
2139
2413
  // src/angular/voice-routing-status.service.ts
2140
- import { Injectable as Injectable8, signal as signal8 } from "@angular/core";
2414
+ import { Injectable as Injectable9, signal as signal9 } from "@angular/core";
2141
2415
 
2142
2416
  // src/client/routingStatus.ts
2143
2417
  var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
@@ -2221,17 +2495,17 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
2221
2495
 
2222
2496
  // src/angular/voice-routing-status.service.ts
2223
2497
  var _dec = [
2224
- Injectable8({ providedIn: "root" })
2498
+ Injectable9({ providedIn: "root" })
2225
2499
  ];
2226
2500
  var _init = __decoratorStart(undefined);
2227
2501
 
2228
2502
  class VoiceRoutingStatusService {
2229
2503
  connect(path = "/api/routing/latest", options = {}) {
2230
2504
  const store = createVoiceRoutingStatusStore(path, options);
2231
- const decisionSignal = signal8(null);
2232
- const errorSignal = signal8(null);
2233
- const isLoadingSignal = signal8(false);
2234
- const updatedAtSignal = signal8(undefined);
2505
+ const decisionSignal = signal9(null);
2506
+ const errorSignal = signal9(null);
2507
+ const isLoadingSignal = signal9(false);
2508
+ const updatedAtSignal = signal9(undefined);
2235
2509
  const sync = () => {
2236
2510
  const snapshot = store.getSnapshot();
2237
2511
  decisionSignal.set(snapshot.decision);
@@ -2260,7 +2534,7 @@ __runInitializers(_init, 1, VoiceRoutingStatusService);
2260
2534
  __decoratorMetadata(_init, VoiceRoutingStatusService);
2261
2535
  let _VoiceRoutingStatusService = VoiceRoutingStatusService;
2262
2536
  // src/angular/voice-trace-timeline.service.ts
2263
- import { computed as computed8, Injectable as Injectable9, signal as signal9 } from "@angular/core";
2537
+ import { computed as computed9, Injectable as Injectable10, signal as signal10 } from "@angular/core";
2264
2538
 
2265
2539
  // src/client/traceTimeline.ts
2266
2540
  var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
@@ -2344,17 +2618,17 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
2344
2618
 
2345
2619
  // src/angular/voice-trace-timeline.service.ts
2346
2620
  var _dec = [
2347
- Injectable9({ providedIn: "root" })
2621
+ Injectable10({ providedIn: "root" })
2348
2622
  ];
2349
2623
  var _init = __decoratorStart(undefined);
2350
2624
 
2351
2625
  class VoiceTraceTimelineService {
2352
2626
  connect(path = "/api/voice-traces", options = {}) {
2353
2627
  const store = createVoiceTraceTimelineStore(path, options);
2354
- const errorSignal = signal9(null);
2355
- const isLoadingSignal = signal9(false);
2356
- const reportSignal = signal9(null);
2357
- const updatedAtSignal = signal9(undefined);
2628
+ const errorSignal = signal10(null);
2629
+ const isLoadingSignal = signal10(false);
2630
+ const reportSignal = signal10(null);
2631
+ const updatedAtSignal = signal10(undefined);
2358
2632
  const sync = () => {
2359
2633
  const snapshot = store.getSnapshot();
2360
2634
  errorSignal.set(snapshot.error);
@@ -2370,11 +2644,11 @@ class VoiceTraceTimelineService {
2370
2644
  unsubscribe();
2371
2645
  store.close();
2372
2646
  },
2373
- error: computed8(() => errorSignal()),
2374
- isLoading: computed8(() => isLoadingSignal()),
2647
+ error: computed9(() => errorSignal()),
2648
+ isLoading: computed9(() => isLoadingSignal()),
2375
2649
  refresh: store.refresh,
2376
- report: computed8(() => reportSignal()),
2377
- updatedAt: computed8(() => updatedAtSignal())
2650
+ report: computed9(() => reportSignal()),
2651
+ updatedAt: computed9(() => updatedAtSignal())
2378
2652
  };
2379
2653
  }
2380
2654
  }
@@ -2383,7 +2657,7 @@ __runInitializers(_init, 1, VoiceTraceTimelineService);
2383
2657
  __decoratorMetadata(_init, VoiceTraceTimelineService);
2384
2658
  let _VoiceTraceTimelineService = VoiceTraceTimelineService;
2385
2659
  // src/angular/voice-turn-latency.service.ts
2386
- import { computed as computed9, Injectable as Injectable10, signal as signal10 } from "@angular/core";
2660
+ import { computed as computed10, Injectable as Injectable11, signal as signal11 } from "@angular/core";
2387
2661
 
2388
2662
  // src/client/turnLatency.ts
2389
2663
  var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
@@ -2490,17 +2764,17 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
2490
2764
 
2491
2765
  // src/angular/voice-turn-latency.service.ts
2492
2766
  var _dec = [
2493
- Injectable10({ providedIn: "root" })
2767
+ Injectable11({ providedIn: "root" })
2494
2768
  ];
2495
2769
  var _init = __decoratorStart(undefined);
2496
2770
 
2497
2771
  class VoiceTurnLatencyService {
2498
2772
  connect(path = "/api/turn-latency", options = {}) {
2499
2773
  const store = createVoiceTurnLatencyStore(path, options);
2500
- const errorSignal = signal10(null);
2501
- const isLoadingSignal = signal10(false);
2502
- const reportSignal = signal10(undefined);
2503
- const updatedAtSignal = signal10(undefined);
2774
+ const errorSignal = signal11(null);
2775
+ const isLoadingSignal = signal11(false);
2776
+ const reportSignal = signal11(undefined);
2777
+ const updatedAtSignal = signal11(undefined);
2504
2778
  const sync = () => {
2505
2779
  const snapshot = store.getSnapshot();
2506
2780
  errorSignal.set(snapshot.error);
@@ -2516,12 +2790,12 @@ class VoiceTurnLatencyService {
2516
2790
  unsubscribe();
2517
2791
  store.close();
2518
2792
  },
2519
- error: computed9(() => errorSignal()),
2520
- isLoading: computed9(() => isLoadingSignal()),
2793
+ error: computed10(() => errorSignal()),
2794
+ isLoading: computed10(() => isLoadingSignal()),
2521
2795
  refresh: store.refresh,
2522
- report: computed9(() => reportSignal()),
2796
+ report: computed10(() => reportSignal()),
2523
2797
  runProof: store.runProof,
2524
- updatedAt: computed9(() => updatedAtSignal())
2798
+ updatedAt: computed10(() => updatedAtSignal())
2525
2799
  };
2526
2800
  }
2527
2801
  }
@@ -2530,7 +2804,7 @@ __runInitializers(_init, 1, VoiceTurnLatencyService);
2530
2804
  __decoratorMetadata(_init, VoiceTurnLatencyService);
2531
2805
  let _VoiceTurnLatencyService = VoiceTurnLatencyService;
2532
2806
  // src/angular/voice-turn-quality.service.ts
2533
- import { computed as computed10, Injectable as Injectable11, signal as signal11 } from "@angular/core";
2807
+ import { computed as computed11, Injectable as Injectable12, signal as signal12 } from "@angular/core";
2534
2808
 
2535
2809
  // src/client/turnQuality.ts
2536
2810
  var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
@@ -2613,17 +2887,17 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
2613
2887
 
2614
2888
  // src/angular/voice-turn-quality.service.ts
2615
2889
  var _dec = [
2616
- Injectable11({ providedIn: "root" })
2890
+ Injectable12({ providedIn: "root" })
2617
2891
  ];
2618
2892
  var _init = __decoratorStart(undefined);
2619
2893
 
2620
2894
  class VoiceTurnQualityService {
2621
2895
  connect(path = "/api/turn-quality", options = {}) {
2622
2896
  const store = createVoiceTurnQualityStore(path, options);
2623
- const errorSignal = signal11(null);
2624
- const isLoadingSignal = signal11(false);
2625
- const reportSignal = signal11(undefined);
2626
- const updatedAtSignal = signal11(undefined);
2897
+ const errorSignal = signal12(null);
2898
+ const isLoadingSignal = signal12(false);
2899
+ const reportSignal = signal12(undefined);
2900
+ const updatedAtSignal = signal12(undefined);
2627
2901
  const sync = () => {
2628
2902
  const snapshot = store.getSnapshot();
2629
2903
  errorSignal.set(snapshot.error);
@@ -2639,11 +2913,11 @@ class VoiceTurnQualityService {
2639
2913
  unsubscribe();
2640
2914
  store.close();
2641
2915
  },
2642
- error: computed10(() => errorSignal()),
2643
- isLoading: computed10(() => isLoadingSignal()),
2916
+ error: computed11(() => errorSignal()),
2917
+ isLoading: computed11(() => isLoadingSignal()),
2644
2918
  refresh: store.refresh,
2645
- report: computed10(() => reportSignal()),
2646
- updatedAt: computed10(() => updatedAtSignal())
2919
+ report: computed11(() => reportSignal()),
2920
+ updatedAt: computed11(() => updatedAtSignal())
2647
2921
  };
2648
2922
  }
2649
2923
  }
@@ -2652,7 +2926,7 @@ __runInitializers(_init, 1, VoiceTurnQualityService);
2652
2926
  __decoratorMetadata(_init, VoiceTurnQualityService);
2653
2927
  let _VoiceTurnQualityService = VoiceTurnQualityService;
2654
2928
  // src/angular/voice-workflow-status.service.ts
2655
- import { computed as computed11, Injectable as Injectable12, signal as signal12 } from "@angular/core";
2929
+ import { computed as computed12, Injectable as Injectable13, signal as signal13 } from "@angular/core";
2656
2930
 
2657
2931
  // src/client/workflowStatus.ts
2658
2932
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -2735,17 +3009,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
2735
3009
 
2736
3010
  // src/angular/voice-workflow-status.service.ts
2737
3011
  var _dec = [
2738
- Injectable12({ providedIn: "root" })
3012
+ Injectable13({ providedIn: "root" })
2739
3013
  ];
2740
3014
  var _init = __decoratorStart(undefined);
2741
3015
 
2742
3016
  class VoiceWorkflowStatusService {
2743
3017
  connect(path = "/evals/scenarios/json", options = {}) {
2744
3018
  const store = createVoiceWorkflowStatusStore(path, options);
2745
- const errorSignal = signal12(null);
2746
- const isLoadingSignal = signal12(false);
2747
- const reportSignal = signal12(undefined);
2748
- const updatedAtSignal = signal12(undefined);
3019
+ const errorSignal = signal13(null);
3020
+ const isLoadingSignal = signal13(false);
3021
+ const reportSignal = signal13(undefined);
3022
+ const updatedAtSignal = signal13(undefined);
2749
3023
  const sync = () => {
2750
3024
  const snapshot = store.getSnapshot();
2751
3025
  errorSignal.set(snapshot.error);
@@ -2763,11 +3037,11 @@ class VoiceWorkflowStatusService {
2763
3037
  unsubscribe();
2764
3038
  store.close();
2765
3039
  },
2766
- error: computed11(() => errorSignal()),
2767
- isLoading: computed11(() => isLoadingSignal()),
3040
+ error: computed12(() => errorSignal()),
3041
+ isLoading: computed12(() => isLoadingSignal()),
2768
3042
  refresh: store.refresh,
2769
- report: computed11(() => reportSignal()),
2770
- updatedAt: computed11(() => updatedAtSignal())
3043
+ report: computed12(() => reportSignal()),
3044
+ updatedAt: computed12(() => updatedAtSignal())
2771
3045
  };
2772
3046
  }
2773
3047
  }
@@ -2776,7 +3050,7 @@ __runInitializers(_init, 1, VoiceWorkflowStatusService);
2776
3050
  __decoratorMetadata(_init, VoiceWorkflowStatusService);
2777
3051
  let _VoiceWorkflowStatusService = VoiceWorkflowStatusService;
2778
3052
  // src/angular/voice-delivery-runtime.component.ts
2779
- import { Component, Input, signal as signal13 } from "@angular/core";
3053
+ import { Component, Input, signal as signal14 } from "@angular/core";
2780
3054
 
2781
3055
  // src/client/deliveryRuntimeWidget.ts
2782
3056
  var DEFAULT_TITLE = "Voice Delivery Runtime";
@@ -2817,6 +3091,8 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
2817
3091
  return {
2818
3092
  description: options.description ?? DEFAULT_DESCRIPTION,
2819
3093
  error: snapshot.error,
3094
+ actionError: snapshot.actionError,
3095
+ actionStatus: snapshot.actionStatus,
2820
3096
  isLoading: snapshot.isLoading,
2821
3097
  isRunning: Boolean(report?.isRunning),
2822
3098
  label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
@@ -2833,6 +3109,11 @@ var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
2833
3109
  <strong>${escapeHtml(surface.detail)}</strong>
2834
3110
  <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
2835
3111
  </li>`).join("");
3112
+ const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
3113
+ <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
3114
+ <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
3115
+ </div>`;
3116
+ const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.actionError)}</p>` : "";
2836
3117
  return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml(model.status)}">
2837
3118
  <header class="absolute-voice-delivery-runtime__header">
2838
3119
  <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml(model.title)}</span>
@@ -2840,20 +3121,38 @@ var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
2840
3121
  </header>
2841
3122
  <p class="absolute-voice-delivery-runtime__description">${escapeHtml(model.description)}</p>
2842
3123
  <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
3124
+ ${actions}
3125
+ ${actionError}
2843
3126
  ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.error)}</p>` : ""}
2844
3127
  </section>`;
2845
3128
  };
2846
- var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
3129
+ var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
2847
3130
  var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
2848
3131
  const store = createVoiceDeliveryRuntimeStore(path, options);
2849
3132
  const render = () => {
2850
3133
  element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
2851
3134
  };
2852
3135
  const unsubscribe = store.subscribe(render);
3136
+ const handleClick = (event) => {
3137
+ const target = event.target;
3138
+ if (!(target instanceof Element)) {
3139
+ return;
3140
+ }
3141
+ const action = target.closest("[data-absolute-voice-delivery-runtime-action]");
3142
+ const actionName = action?.getAttribute("data-absolute-voice-delivery-runtime-action");
3143
+ if (actionName === "tick") {
3144
+ store.tick().catch(() => {});
3145
+ }
3146
+ if (actionName === "requeue-dead-letters") {
3147
+ store.requeueDeadLetters().catch(() => {});
3148
+ }
3149
+ };
3150
+ element.addEventListener?.("click", handleClick);
2853
3151
  render();
2854
3152
  store.refresh().catch(() => {});
2855
3153
  return {
2856
3154
  close: () => {
3155
+ element.removeEventListener?.("click", handleClick);
2857
3156
  unsubscribe();
2858
3157
  store.close();
2859
3158
  },
@@ -2932,6 +3231,29 @@ var _dec = [
2932
3231
  </li>
2933
3232
  }
2934
3233
  </ul>
3234
+ <div class="absolute-voice-delivery-runtime__actions">
3235
+ <button
3236
+ type="button"
3237
+ [disabled]="model().actionStatus === 'running'"
3238
+ (click)="tick()"
3239
+ >
3240
+ {{ model().actionStatus === "running" ? "Working..." : "Tick workers" }}
3241
+ </button>
3242
+ <button
3243
+ type="button"
3244
+ [disabled]="
3245
+ model().actionStatus === 'running' || deadLettered() === 0
3246
+ "
3247
+ (click)="requeueDeadLetters()"
3248
+ >
3249
+ Requeue dead letters
3250
+ </button>
3251
+ </div>
3252
+ @if (model().actionError) {
3253
+ <p class="absolute-voice-delivery-runtime__error">
3254
+ {{ model().actionError }}
3255
+ </p>
3256
+ }
2935
3257
  @if (model().error) {
2936
3258
  <p class="absolute-voice-delivery-runtime__error">
2937
3259
  {{ model().error }}
@@ -2968,7 +3290,9 @@ class VoiceDeliveryRuntimeComponent {
2968
3290
  }
2969
3291
  cleanup = () => {};
2970
3292
  store;
2971
- model = signal13(createVoiceDeliveryRuntimeViewModel({
3293
+ model = signal14(createVoiceDeliveryRuntimeViewModel({
3294
+ actionError: null,
3295
+ actionStatus: "idle",
2972
3296
  error: null,
2973
3297
  isLoading: true
2974
3298
  }));
@@ -2988,6 +3312,15 @@ class VoiceDeliveryRuntimeComponent {
2988
3312
  this.cleanup();
2989
3313
  this.store?.close();
2990
3314
  }
3315
+ deadLettered() {
3316
+ return this.model().surfaces.reduce((total, surface) => total + surface.deadLettered, 0);
3317
+ }
3318
+ tick() {
3319
+ this.store?.tick().catch(() => {});
3320
+ }
3321
+ requeueDeadLetters() {
3322
+ this.store?.requeueDeadLetters().catch(() => {});
3323
+ }
2991
3324
  options() {
2992
3325
  return {
2993
3326
  description: this.description,
@@ -3014,6 +3347,7 @@ export {
3014
3347
  VoiceProviderStatusService,
3015
3348
  VoiceProviderCapabilitiesService,
3016
3349
  VoiceOpsStatusService,
3350
+ VoiceOpsActionCenterService,
3017
3351
  VoiceDeliveryRuntimeService,
3018
3352
  VoiceDeliveryRuntimeComponent,
3019
3353
  VoiceControllerService,