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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -690,6 +690,19 @@ export function OperatorPanel() {
690
690
  }
691
691
  ```
692
692
 
693
+ Mount `createVoiceOpsActionAuditRoutes(...)` to make every action-center click auditable. The client posts successful and failed action results to `/api/voice/ops-actions/audit` by default, and the route records both `operator.action` audit events and `operator.action` trace events.
694
+
695
+ ```ts
696
+ import { createVoiceOpsActionAuditRoutes } from '@absolutejs/voice';
697
+
698
+ app.use(
699
+ createVoiceOpsActionAuditRoutes({
700
+ audit: runtimeStorage.audit,
701
+ trace: runtimeStorage.traces
702
+ })
703
+ );
704
+ ```
705
+
693
706
  For HTML or HTMX pages:
694
707
 
695
708
  ```html
@@ -197,6 +197,23 @@ let _VoiceOpsStatusService = VoiceOpsStatusService;
197
197
  import { computed as computed2, Injectable as Injectable2, signal as signal2 } from "@angular/core";
198
198
 
199
199
  // src/client/opsActionCenter.ts
200
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
201
+ if (options.auditPath === false) {
202
+ return;
203
+ }
204
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
205
+ const fetchImpl = options.fetch ?? globalThis.fetch;
206
+ const response = await fetchImpl(path, {
207
+ body: JSON.stringify(result),
208
+ headers: {
209
+ "Content-Type": "application/json"
210
+ },
211
+ method: "POST"
212
+ });
213
+ if (!response.ok) {
214
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
215
+ }
216
+ };
200
217
  var createVoiceOpsActionCenterActions = (options = {}) => {
201
218
  const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
202
219
  const actions = [];
@@ -309,6 +326,8 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
309
326
  emit();
310
327
  try {
311
328
  const result = await runVoiceOpsAction(action, options);
329
+ await options.onActionResult?.(result);
330
+ await recordVoiceOpsActionResult(result, options);
312
331
  snapshot = {
313
332
  ...snapshot,
314
333
  error: null,
@@ -320,6 +339,16 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
320
339
  emit();
321
340
  return result;
322
341
  } catch (error) {
342
+ const result = {
343
+ actionId: action.id,
344
+ body: null,
345
+ error: error instanceof Error ? error.message : String(error),
346
+ ok: false,
347
+ ranAt: Date.now(),
348
+ status: 0
349
+ };
350
+ await options.onActionResult?.(result);
351
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
323
352
  snapshot = {
324
353
  ...snapshot,
325
354
  error: error instanceof Error ? error.message : String(error),
@@ -8,7 +8,7 @@ export { createMicrophoneCapture } from './microphone';
8
8
  export { createVoiceBargeInMonitor } from './bargeInMonitor';
9
9
  export { createVoiceLiveTurnLatencyMonitor } from './liveTurnLatency';
10
10
  export { createVoiceOpsStatusStore, fetchVoiceOpsStatus } from './opsStatus';
11
- export { createVoiceOpsActionCenterActions, createVoiceOpsActionCenterStore, runVoiceOpsAction } from './opsActionCenter';
11
+ export { createVoiceOpsActionCenterActions, createVoiceOpsActionCenterStore, recordVoiceOpsActionResult, runVoiceOpsAction } from './opsActionCenter';
12
12
  export { createVoiceDeliveryRuntimeStore, fetchVoiceDeliveryRuntime, runVoiceDeliveryRuntimeAction } from './deliveryRuntime';
13
13
  export { createVoiceOpsStatusViewModel, defineVoiceOpsStatusElement, getVoiceOpsStatusCSS, getVoiceOpsStatusLabel, mountVoiceOpsStatus, renderVoiceOpsStatusHTML } from './opsStatusWidget';
14
14
  export { createVoiceOpsActionCenterViewModel, defineVoiceOpsActionCenterElement, getVoiceOpsActionCenterCSS, mountVoiceOpsActionCenter, renderVoiceOpsActionCenterHTML } from './opsActionCenterWidget';
@@ -2063,6 +2063,23 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
2063
2063
  };
2064
2064
  };
2065
2065
  // src/client/opsActionCenter.ts
2066
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
2067
+ if (options.auditPath === false) {
2068
+ return;
2069
+ }
2070
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
2071
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2072
+ const response = await fetchImpl(path, {
2073
+ body: JSON.stringify(result),
2074
+ headers: {
2075
+ "Content-Type": "application/json"
2076
+ },
2077
+ method: "POST"
2078
+ });
2079
+ if (!response.ok) {
2080
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
2081
+ }
2082
+ };
2066
2083
  var createVoiceOpsActionCenterActions = (options = {}) => {
2067
2084
  const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
2068
2085
  const actions = [];
@@ -2175,6 +2192,8 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
2175
2192
  emit();
2176
2193
  try {
2177
2194
  const result = await runVoiceOpsAction(action, options);
2195
+ await options.onActionResult?.(result);
2196
+ await recordVoiceOpsActionResult(result, options);
2178
2197
  snapshot = {
2179
2198
  ...snapshot,
2180
2199
  error: null,
@@ -2186,6 +2205,16 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
2186
2205
  emit();
2187
2206
  return result;
2188
2207
  } catch (error) {
2208
+ const result = {
2209
+ actionId: action.id,
2210
+ body: null,
2211
+ error: error instanceof Error ? error.message : String(error),
2212
+ ok: false,
2213
+ ranAt: Date.now(),
2214
+ status: 0
2215
+ };
2216
+ await options.onActionResult?.(result);
2217
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
2189
2218
  snapshot = {
2190
2219
  ...snapshot,
2191
2220
  error: error instanceof Error ? error.message : String(error),
@@ -4196,6 +4225,7 @@ export {
4196
4225
  renderVoiceOpsStatusHTML,
4197
4226
  renderVoiceOpsActionCenterHTML,
4198
4227
  renderVoiceDeliveryRuntimeHTML,
4228
+ recordVoiceOpsActionResult,
4199
4229
  mountVoiceTurnQuality,
4200
4230
  mountVoiceTurnLatency,
4201
4231
  mountVoiceTraceTimeline,
@@ -9,16 +9,20 @@ export type VoiceOpsActionDescriptor = {
9
9
  };
10
10
  export type VoiceOpsActionCenterClientOptions = {
11
11
  actions?: VoiceOpsActionDescriptor[];
12
+ auditPath?: false | string;
12
13
  fetch?: typeof fetch;
13
14
  intervalMs?: number;
15
+ onActionResult?: (result: VoiceOpsActionRunResult) => Promise<void> | void;
14
16
  };
15
17
  export type VoiceOpsActionRunResult = {
16
18
  actionId: string;
17
19
  body: unknown;
20
+ error?: string;
18
21
  ok: boolean;
19
22
  ranAt: number;
20
23
  status: number;
21
24
  };
25
+ export declare const recordVoiceOpsActionResult: (result: VoiceOpsActionRunResult, options?: VoiceOpsActionCenterClientOptions) => Promise<void>;
22
26
  export type VoiceOpsActionCenterSnapshot = {
23
27
  actions: VoiceOpsActionDescriptor[];
24
28
  error: string | null;
package/dist/index.d.ts CHANGED
@@ -13,11 +13,13 @@ export { createVoiceReconnectContractRoutes, renderVoiceReconnectContractHTML, s
13
13
  export { buildVoiceDiagnosticsMarkdown, createVoiceDiagnosticsRoutes, resolveVoiceDiagnosticsTraceFilter } from './diagnosticsRoutes';
14
14
  export { buildVoiceDemoReadyReport, createVoiceDemoReadyRoutes, renderVoiceDemoReadyHTML } from './demoReadyRoutes';
15
15
  export { buildVoiceDeliverySinkReport, createVoiceDeliverySinkDescriptor, createVoiceDeliverySinkPair, createVoiceDeliverySinkRoutes, createVoiceFileDeliverySink, createVoicePostgresDeliverySink, createVoiceS3DeliverySink, createVoiceSQLiteDeliverySink, createVoiceWebhookDeliverySink, renderVoiceDeliverySinkHTML } from './deliverySinkRoutes';
16
+ export { createVoiceOpsActionAuditRoutes, recordVoiceOpsActionAudit } from './opsActionAuditRoutes';
16
17
  export { buildVoiceDeliveryRuntimeReport, createVoiceDeliveryRuntime, createVoiceDeliveryRuntimePresetConfig, createVoiceDeliveryRuntimeRoutes, renderVoiceDeliveryRuntimeHTML } from './deliveryRuntime';
17
18
  export { applyVoiceDataRetentionPolicy, buildVoiceDataRetentionPlan } from './dataControl';
18
19
  export type { VoiceDataRetentionPolicy, VoiceDataRetentionReport, VoiceDataRetentionScope, VoiceDataRetentionScopeReport, VoiceDataRetentionStores } from './dataControl';
19
20
  export type { VoiceDemoReadyReport, VoiceDemoReadyRoutesOptions, VoiceDemoReadySection, VoiceDemoReadyStatus } from './demoReadyRoutes';
20
21
  export type { VoiceDeliverySinkDescriptor, VoiceDeliverySinkDescriptorInput, VoiceDeliverySinkKind, VoiceDeliverySinkPairOptions, VoiceDeliverySinkReport, VoiceDeliverySinkRoutesOptions, VoiceTraceDeliverySinkSurface } from './deliverySinkRoutes';
22
+ export type { VoiceOpsActionAuditRecord, VoiceOpsActionAuditRoutesOptions } from './opsActionAuditRoutes';
21
23
  export type { VoiceDeliveryRuntime, VoiceDeliveryRuntimeAuditConfig, VoiceDeliveryRuntimeConfig, VoiceDeliveryRuntimeFilePresetOptions, VoiceDeliveryRuntimePresetLeaseConfig, VoiceDeliveryRuntimePresetMode, VoiceDeliveryRuntimePresetOptions, VoiceDeliveryRuntimeReport, VoiceDeliveryRuntimeRoutesOptions, VoiceDeliveryRuntimeS3PresetOptions, VoiceDeliveryRuntimeSummary, VoiceDeliveryRuntimeTickResult, VoiceDeliveryRuntimeTraceConfig, VoiceDeliveryRuntimeWebhookPresetOptions } from './deliveryRuntime';
22
24
  export { compareVoiceEvalBaseline, createVoiceFileEvalBaselineStore, createVoiceFileScenarioFixtureStore, createVoiceEvalRoutes, renderVoiceEvalBaselineHTML, renderVoiceEvalHTML, renderVoiceScenarioEvalHTML, renderVoiceScenarioFixtureEvalHTML, runVoiceScenarioEvals, runVoiceScenarioFixtureEvals, runVoiceSessionEvals } from './evalRoutes';
23
25
  export { createVoiceSimulationSuiteRoutes, renderVoiceSimulationSuiteHTML, runVoiceSimulationSuite } from './simulationSuite';
package/dist/index.js CHANGED
@@ -11564,8 +11564,97 @@ var createVoiceDeliverySinkRoutes = (options) => {
11564
11564
  }
11565
11565
  return routes;
11566
11566
  };
11567
- // src/deliveryRuntime.ts
11567
+ // src/opsActionAuditRoutes.ts
11568
11568
  import { Elysia as Elysia12 } from "elysia";
11569
+ var readRecord = async (request) => {
11570
+ const body = await request.json().catch(() => null);
11571
+ if (!body || typeof body !== "object") {
11572
+ throw new Error("Voice ops action audit requires a JSON body.");
11573
+ }
11574
+ const record = body;
11575
+ if (!record.actionId || typeof record.actionId !== "string") {
11576
+ throw new Error("Voice ops action audit requires actionId.");
11577
+ }
11578
+ return {
11579
+ actionId: record.actionId,
11580
+ body: record.body,
11581
+ error: record.error,
11582
+ ok: Boolean(record.ok),
11583
+ ranAt: typeof record.ranAt === "number" ? record.ranAt : Date.now(),
11584
+ status: typeof record.status === "number" ? record.status : 0
11585
+ };
11586
+ };
11587
+ var recordVoiceOpsActionAudit = async (record, options) => {
11588
+ const traceId = `voice-ops-action:${record.actionId}:${record.ranAt}`;
11589
+ const outcome = record.ok ? "success" : "error";
11590
+ const [audit, trace] = await Promise.all([
11591
+ options.audit?.append(createVoiceAuditEvent({
11592
+ action: record.actionId,
11593
+ actor: {
11594
+ id: "voice-ops-action-center",
11595
+ kind: "operator",
11596
+ name: "Voice Ops Action Center"
11597
+ },
11598
+ at: record.ranAt,
11599
+ metadata: {
11600
+ source: "voice-ops-action-center"
11601
+ },
11602
+ outcome,
11603
+ payload: {
11604
+ body: record.body,
11605
+ error: record.error,
11606
+ status: record.status
11607
+ },
11608
+ resource: {
11609
+ id: record.actionId,
11610
+ type: "voice.ops.action"
11611
+ },
11612
+ sessionId: "voice-ops-action-center",
11613
+ traceId,
11614
+ type: "operator.action"
11615
+ })),
11616
+ options.trace?.append(createVoiceTraceEvent({
11617
+ at: record.ranAt,
11618
+ metadata: {
11619
+ source: "voice-ops-action-center"
11620
+ },
11621
+ payload: {
11622
+ actionId: record.actionId,
11623
+ body: record.body,
11624
+ error: record.error,
11625
+ ok: record.ok,
11626
+ status: record.status
11627
+ },
11628
+ sessionId: "voice-ops-action-center",
11629
+ traceId,
11630
+ type: "operator.action"
11631
+ }))
11632
+ ]);
11633
+ return {
11634
+ audit,
11635
+ ok: true,
11636
+ trace
11637
+ };
11638
+ };
11639
+ var createVoiceOpsActionAuditRoutes = (options) => {
11640
+ const path = options.path ?? "/api/voice/ops-actions/audit";
11641
+ return new Elysia12({
11642
+ name: options.name ?? "absolutejs-voice-ops-action-audit"
11643
+ }).post(path, async ({ request, set }) => {
11644
+ try {
11645
+ const record = await readRecord(request);
11646
+ return await recordVoiceOpsActionAudit(record, options);
11647
+ } catch (error) {
11648
+ set.status = 400;
11649
+ return {
11650
+ error: error instanceof Error ? error.message : String(error),
11651
+ ok: false
11652
+ };
11653
+ }
11654
+ });
11655
+ };
11656
+ // src/deliveryRuntime.ts
11657
+ import { Elysia as Elysia13 } from "elysia";
11569
11658
  import { mkdir } from "fs/promises";
11570
11659
  import { dirname, join } from "path";
11571
11660
  var escapeHtml15 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
@@ -11797,7 +11886,7 @@ var createVoiceDeliveryRuntimeRoutes = (options) => {
11797
11886
  const htmlPath = options.htmlPath === undefined ? "/delivery-runtime" : options.htmlPath;
11798
11887
  const tickPath = options.tickPath === undefined ? "/api/voice-delivery-runtime/tick" : options.tickPath;
11799
11888
  const requeueDeadLettersPath = options.requeueDeadLettersPath === undefined ? "/api/voice-delivery-runtime/requeue-dead-letters" : options.requeueDeadLettersPath;
11800
- const routes = new Elysia12({
11889
+ const routes = new Elysia13({
11801
11890
  name: options.name ?? "absolutejs-voice-delivery-runtime"
11802
11891
  }).get(path, () => buildVoiceDeliveryRuntimeReport(options.runtime));
11803
11892
  if (tickPath !== false) {
@@ -12035,15 +12124,15 @@ var applyVoiceDataRetentionPolicy = async (options) => {
12035
12124
  };
12036
12125
  var buildVoiceDataRetentionPlan = (options) => applyVoiceDataRetentionPolicy({ ...options, dryRun: true });
12037
12126
  // src/evalRoutes.ts
12038
- import { Elysia as Elysia15 } from "elysia";
12127
+ import { Elysia as Elysia16 } from "elysia";
12039
12128
  import { mkdir as mkdir2 } from "fs/promises";
12040
12129
  import { dirname as dirname2 } from "path";
12041
12130
 
12042
12131
  // src/qualityRoutes.ts
12043
- import { Elysia as Elysia14 } from "elysia";
12132
+ import { Elysia as Elysia15 } from "elysia";
12044
12133
 
12045
12134
  // src/handoffHealth.ts
12046
- import { Elysia as Elysia13 } from "elysia";
12135
+ import { Elysia as Elysia14 } from "elysia";
12047
12136
  var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
12048
12137
  var getString6 = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
12049
12138
  var isStatus = (value) => value === "delivered" || value === "failed" || value === "skipped";
@@ -12226,7 +12315,7 @@ var createVoiceHandoffHealthHTMLHandler = (options = {}) => async ({ query }) =>
12226
12315
  var createVoiceHandoffHealthRoutes = (options = {}) => {
12227
12316
  const path = options.path ?? "/api/voice-handoffs";
12228
12317
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
12229
- const routes = new Elysia13({
12318
+ const routes = new Elysia14({
12230
12319
  name: options.name ?? "absolutejs-voice-handoff-health"
12231
12320
  }).get(path, createVoiceHandoffHealthJSONHandler(options));
12232
12321
  if (htmlPath) {
@@ -12357,7 +12446,7 @@ var renderVoiceQualityHTML = (report, options = {}) => {
12357
12446
  };
12358
12447
  var createVoiceQualityRoutes = (options) => {
12359
12448
  const path = options.path ?? "/quality";
12360
- const routes = new Elysia14({
12449
+ const routes = new Elysia15({
12361
12450
  name: options.name ?? "absolutejs-voice-quality"
12362
12451
  });
12363
12452
  const getReport = () => evaluateVoiceQuality({
@@ -12732,7 +12821,7 @@ var renderVoiceScenarioFixtureEvalHTML = (report, options = {}) => {
12732
12821
  };
12733
12822
  var createVoiceEvalRoutes = (options) => {
12734
12823
  const path = options.path ?? "/evals";
12735
- const routes = new Elysia15({
12824
+ const routes = new Elysia16({
12736
12825
  name: options.name ?? "absolutejs-voice-evals"
12737
12826
  });
12738
12827
  const getReport = () => runVoiceSessionEvals({
@@ -12866,10 +12955,10 @@ var createVoiceEvalRoutes = (options) => {
12866
12955
  return routes;
12867
12956
  };
12868
12957
  // src/simulationSuite.ts
12869
- import { Elysia as Elysia18 } from "elysia";
12958
+ import { Elysia as Elysia19 } from "elysia";
12870
12959
 
12871
12960
  // src/outcomeContract.ts
12872
- import { Elysia as Elysia16 } from "elysia";
12961
+ import { Elysia as Elysia17 } from "elysia";
12873
12962
  var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
12874
12963
  var getPayloadString = (event, key) => typeof event.payload[key] === "string" ? event.payload[key] : undefined;
12875
12964
  var toList = async (input) => Array.isArray(input) ? input : await input?.list() ?? [];
@@ -13009,7 +13098,7 @@ var createVoiceOutcomeContractHTMLHandler = (options) => async () => {
13009
13098
  var createVoiceOutcomeContractRoutes = (options) => {
13010
13099
  const path = options.path ?? "/api/outcome-contracts";
13011
13100
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
13012
- const routes = new Elysia16({
13101
+ const routes = new Elysia17({
13013
13102
  name: options.name ?? "absolutejs-voice-outcome-contracts"
13014
13103
  }).get(path, createVoiceOutcomeContractJSONHandler(options));
13015
13104
  if (htmlPath) {
@@ -13019,7 +13108,7 @@ var createVoiceOutcomeContractRoutes = (options) => {
13019
13108
  };
13020
13109
 
13021
13110
  // src/toolContract.ts
13022
- import { Elysia as Elysia17 } from "elysia";
13111
+ import { Elysia as Elysia18 } from "elysia";
13023
13112
 
13024
13113
  // src/toolRuntime.ts
13025
13114
  var toErrorMessage4 = (error) => error instanceof Error ? error.message : String(error);
@@ -13433,7 +13522,7 @@ var createVoiceToolContractHTMLHandler = (options) => async () => {
13433
13522
  var createVoiceToolContractRoutes = (options) => {
13434
13523
  const path = options.path ?? "/api/tool-contracts";
13435
13524
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
13436
- const routes = new Elysia17({
13525
+ const routes = new Elysia18({
13437
13526
  name: options.name ?? "absolutejs-voice-tool-contracts"
13438
13527
  }).get(path, createVoiceToolContractJSONHandler(options));
13439
13528
  if (htmlPath) {
@@ -13592,7 +13681,7 @@ var renderVoiceSimulationSuiteHTML = (report, options = {}) => {
13592
13681
  var createVoiceSimulationSuiteRoutes = (options) => {
13593
13682
  const path = options.path ?? "/api/voice/simulations";
13594
13683
  const htmlPath = options.htmlPath === undefined ? "/voice/simulations" : options.htmlPath;
13595
- const app = new Elysia18({
13684
+ const app = new Elysia19({
13596
13685
  name: options.name ?? "absolutejs-voice-simulation-suite"
13597
13686
  }).get(path, () => runVoiceSimulationSuite(options));
13598
13687
  if (htmlPath) {
@@ -13904,7 +13993,7 @@ var createVoiceWorkflowContractHandler = (input) => {
13904
13993
  };
13905
13994
  };
13906
13995
  // src/sessionReplay.ts
13907
- import { Elysia as Elysia19 } from "elysia";
13996
+ import { Elysia as Elysia20 } from "elysia";
13908
13997
  var getString9 = (value) => typeof value === "string" ? value : undefined;
13909
13998
  var escapeHtml22 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
13910
13999
  var increment4 = (record, key) => {
@@ -14130,7 +14219,7 @@ var createVoiceSessionsHTMLHandler = (options = {}) => async ({ query }) => {
14130
14219
  var createVoiceSessionListRoutes = (options = {}) => {
14131
14220
  const path = options.path ?? "/api/voice-sessions";
14132
14221
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
14133
- const routes = new Elysia19({
14222
+ const routes = new Elysia20({
14134
14223
  name: options.name ?? "absolutejs-voice-session-list"
14135
14224
  }).get(path, createVoiceSessionsJSONHandler(options));
14136
14225
  if (htmlPath) {
@@ -14158,7 +14247,7 @@ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
14158
14247
  var createVoiceSessionReplayRoutes = (options) => {
14159
14248
  const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
14160
14249
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
14161
- const routes = new Elysia19({
14250
+ const routes = new Elysia20({
14162
14251
  name: options.name ?? "absolutejs-voice-session-replay"
14163
14252
  }).get(path, createVoiceSessionReplayJSONHandler(options));
14164
14253
  if (htmlPath) {
@@ -14325,7 +14414,7 @@ var assertVoiceAgentSquadContract = async (options) => {
14325
14414
  return report;
14326
14415
  };
14327
14416
  // src/turnLatency.ts
14328
- import { Elysia as Elysia20 } from "elysia";
14417
+ import { Elysia as Elysia21 } from "elysia";
14329
14418
  var DEFAULT_WARN_AFTER_MS = 1800;
14330
14419
  var DEFAULT_FAIL_AFTER_MS = 3200;
14331
14420
  var escapeHtml23 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
@@ -14463,7 +14552,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
14463
14552
  var createVoiceTurnLatencyRoutes = (options) => {
14464
14553
  const path = options.path ?? "/api/turn-latency";
14465
14554
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
14466
- const routes = new Elysia20({
14555
+ const routes = new Elysia21({
14467
14556
  name: options.name ?? "absolutejs-voice-turn-latency"
14468
14557
  }).get(path, createVoiceTurnLatencyJSONHandler(options));
14469
14558
  if (htmlPath) {
@@ -14472,7 +14561,7 @@ var createVoiceTurnLatencyRoutes = (options) => {
14472
14561
  return routes;
14473
14562
  };
14474
14563
  // src/liveLatency.ts
14475
- import { Elysia as Elysia21 } from "elysia";
14564
+ import { Elysia as Elysia22 } from "elysia";
14476
14565
  var escapeHtml24 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14477
14566
  var percentile = (values, percentileValue) => {
14478
14567
  if (values.length === 0) {
@@ -14527,7 +14616,7 @@ var renderVoiceLiveLatencyHTML = (report, options = {}) => {
14527
14616
  var createVoiceLiveLatencyRoutes = (options) => {
14528
14617
  const path = options.path ?? "/api/live-latency";
14529
14618
  const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
14530
- const routes = new Elysia21({
14619
+ const routes = new Elysia22({
14531
14620
  name: options.name ?? "absolutejs-voice-live-latency"
14532
14621
  }).get(path, () => summarizeVoiceLiveLatency(options));
14533
14622
  if (htmlPath) {
@@ -14544,7 +14633,7 @@ var createVoiceLiveLatencyRoutes = (options) => {
14544
14633
  return routes;
14545
14634
  };
14546
14635
  // src/turnQuality.ts
14547
- import { Elysia as Elysia22 } from "elysia";
14636
+ import { Elysia as Elysia23 } from "elysia";
14548
14637
  var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
14549
14638
  var escapeHtml25 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
14550
14639
  var getTurnLatencyMs = (turn) => {
@@ -14651,7 +14740,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
14651
14740
  var createVoiceTurnQualityRoutes = (options) => {
14652
14741
  const path = options.path ?? "/api/turn-quality";
14653
14742
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
14654
- const routes = new Elysia22({
14743
+ const routes = new Elysia23({
14655
14744
  name: options.name ?? "absolutejs-voice-turn-quality"
14656
14745
  }).get(path, createVoiceTurnQualityJSONHandler(options));
14657
14746
  if (htmlPath) {
@@ -14660,7 +14749,7 @@ var createVoiceTurnQualityRoutes = (options) => {
14660
14749
  return routes;
14661
14750
  };
14662
14751
  // src/telephonyOutcome.ts
14663
- import { Elysia as Elysia23 } from "elysia";
14752
+ import { Elysia as Elysia24 } from "elysia";
14664
14753
  var DEFAULT_COMPLETED_STATUSES = [
14665
14754
  "answered",
14666
14755
  "completed",
@@ -15310,7 +15399,7 @@ var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
15310
15399
  var createVoiceTelephonyWebhookRoutes = (options = {}) => {
15311
15400
  const path = options.path ?? "/api/voice/telephony/webhook";
15312
15401
  const handler = createVoiceTelephonyWebhookHandler(options);
15313
- return new Elysia23({
15402
+ return new Elysia24({
15314
15403
  name: options.name ?? "absolutejs-voice-telephony-webhooks"
15315
15404
  }).post(path, async ({ query, request }) => {
15316
15405
  try {
@@ -15331,11 +15420,11 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
15331
15420
  });
15332
15421
  };
15333
15422
  // src/phoneAgent.ts
15334
- import { Elysia as Elysia29 } from "elysia";
15423
+ import { Elysia as Elysia30 } from "elysia";
15335
15424
 
15336
15425
  // src/telephony/plivo.ts
15337
15426
  import { Buffer as Buffer5 } from "buffer";
15338
- import { Elysia as Elysia25 } from "elysia";
15427
+ import { Elysia as Elysia26 } from "elysia";
15339
15428
 
15340
15429
  // src/telephony/contract.ts
15341
15430
  var DEFAULT_REQUIREMENTS = [
@@ -15419,7 +15508,7 @@ var evaluateVoiceTelephonyContract = (input) => {
15419
15508
 
15420
15509
  // src/telephony/twilio.ts
15421
15510
  import { Buffer as Buffer4 } from "buffer";
15422
- import { Elysia as Elysia24 } from "elysia";
15511
+ import { Elysia as Elysia25 } from "elysia";
15423
15512
  var TWILIO_MULAW_SAMPLE_RATE = 8000;
15424
15513
  var VOICE_PCM_SAMPLE_RATE = 16000;
15425
15514
  var escapeXml2 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
@@ -15992,7 +16081,7 @@ var createTwilioVoiceRoutes = (options) => {
15992
16081
  const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/twilio/smoke";
15993
16082
  const bridges = new WeakMap;
15994
16083
  const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
15995
- const app = new Elysia24({
16084
+ const app = new Elysia25({
15996
16085
  name: options.name ?? "absolutejs-voice-twilio"
15997
16086
  }).get(twimlPath, async ({ query, request }) => {
15998
16087
  const streamUrl = await resolveTwilioStreamUrl(options, {
@@ -16489,7 +16578,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
16489
16578
  request: input.request
16490
16579
  }) : verificationUrl ?? input.request.url
16491
16580
  }) : undefined);
16492
- const app = new Elysia25({
16581
+ const app = new Elysia26({
16493
16582
  name: options.name ?? "absolutejs-voice-plivo"
16494
16583
  }).get(answerPath, async ({ query, request }) => {
16495
16584
  const streamUrl = await resolvePlivoStreamUrl(options, {
@@ -16600,7 +16689,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
16600
16689
 
16601
16690
  // src/telephony/telnyx.ts
16602
16691
  import { Buffer as Buffer6 } from "buffer";
16603
- import { Elysia as Elysia26 } from "elysia";
16692
+ import { Elysia as Elysia27 } from "elysia";
16604
16693
  var escapeXml4 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
16605
16694
  var escapeHtml28 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
16606
16695
  var joinUrlPath4 = (origin, path) => `${origin.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
@@ -16911,7 +17000,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
16911
17000
  publicKey: options.webhook?.publicKey,
16912
17001
  toleranceSeconds: options.webhook?.toleranceSeconds
16913
17002
  }) : undefined);
16914
- const app = new Elysia26({
17003
+ const app = new Elysia27({
16915
17004
  name: options.name ?? "absolutejs-voice-telnyx"
16916
17005
  }).get(texmlPath, async ({ query, request }) => {
16917
17006
  const streamUrl = await resolveTelnyxStreamUrl(options, {
@@ -17021,7 +17110,7 @@ var createTelnyxVoiceRoutes = (options = {}) => {
17021
17110
  };
17022
17111
 
17023
17112
  // src/telephony/matrix.ts
17024
- import { Elysia as Elysia27 } from "elysia";
17113
+ import { Elysia as Elysia28 } from "elysia";
17025
17114
  var escapeHtml29 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&#39;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
17026
17115
  var labelForProvider = (provider) => provider.split("-").map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
17027
17116
  var resolveEntryStatus = (contract, setup, smoke) => {
@@ -17105,7 +17194,7 @@ ${entry.issues.length ? `<ul style="margin:12px 0 0; padding-left:18px;">${entry
17105
17194
  </main>`;
17106
17195
  var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
17107
17196
  const path = options.path ?? "/api/voice/telephony/carriers";
17108
- return new Elysia27({
17197
+ return new Elysia28({
17109
17198
  name: options.name ?? "absolutejs-voice-telephony-carrier-matrix"
17110
17199
  }).get(path, async ({ query, request }) => {
17111
17200
  const providers = await options.load({ query, request });
@@ -17127,7 +17216,7 @@ var createVoiceTelephonyCarrierMatrixRoutes = (options) => {
17127
17216
  };
17128
17217
 
17129
17218
  // src/phoneAgentProductionSmoke.ts
17130
- import { Elysia as Elysia28 } from "elysia";
17219
+ import { Elysia as Elysia29 } from "elysia";
17131
17220
  var defaultRequirements = [
17132
17221
  "media-started",
17133
17222
  "transcript",
@@ -17270,7 +17359,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
17270
17359
  var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
17271
17360
  const path = options.path ?? "/api/voice/phone/smoke-contract";
17272
17361
  const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
17273
- const routes = new Elysia28({
17362
+ const routes = new Elysia29({
17274
17363
  name: options.name ?? "absolutejs-voice-phone-smoke-contract"
17275
17364
  }).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
17276
17365
  if (htmlPath) {
@@ -17393,7 +17482,7 @@ var createVoicePhoneAgent = (options) => {
17393
17482
  setupPath: resolveSetupPath(carrier),
17394
17483
  smokePath: resolveSmokePath(carrier)
17395
17484
  }));
17396
- const app = new Elysia29({
17485
+ const app = new Elysia30({
17397
17486
  name: options.name ?? "absolutejs-voice-phone-agent"
17398
17487
  });
17399
17488
  for (const carrier of options.carriers) {
@@ -19405,7 +19494,7 @@ var createOpenAIVoiceTTS = (options) => {
19405
19494
  };
19406
19495
  };
19407
19496
  // src/providerCapabilities.ts
19408
- import { Elysia as Elysia30 } from "elysia";
19497
+ import { Elysia as Elysia31 } from "elysia";
19409
19498
  var escapeHtml32 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
19410
19499
  var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
19411
19500
  configured: true,
@@ -19506,7 +19595,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
19506
19595
  var createVoiceProviderCapabilityRoutes = (options) => {
19507
19596
  const path = options.path ?? "/api/provider-capabilities";
19508
19597
  const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
19509
- const routes = new Elysia30({
19598
+ const routes = new Elysia31({
19510
19599
  name: options.name ?? "absolutejs-voice-provider-capabilities"
19511
19600
  }).get(path, createVoiceProviderCapabilityJSONHandler(options));
19512
19601
  if (htmlPath) {
@@ -19515,7 +19604,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
19515
19604
  return routes;
19516
19605
  };
19517
19606
  // src/resilienceRoutes.ts
19518
- import { Elysia as Elysia31 } from "elysia";
19607
+ import { Elysia as Elysia32 } from "elysia";
19519
19608
  var escapeHtml33 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
19520
19609
  var getString11 = (value) => typeof value === "string" ? value : undefined;
19521
19610
  var getNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
@@ -19916,7 +20005,7 @@ var registerSimulationRoutes = (routes, simulation, defaultPathPrefix) => {
19916
20005
  };
19917
20006
  var createVoiceResilienceRoutes = (options) => {
19918
20007
  const path = options.path ?? "/resilience";
19919
- const routes = new Elysia31({
20008
+ const routes = new Elysia32({
19920
20009
  name: options.name ?? "absolutejs-voice-resilience"
19921
20010
  }).get(path, async () => {
19922
20011
  const events = await options.store.list();
@@ -19994,7 +20083,7 @@ var assertVoiceProviderRoutingContract = async (options) => {
19994
20083
  return report;
19995
20084
  };
19996
20085
  // src/productionReadiness.ts
19997
- import { Elysia as Elysia32 } from "elysia";
20086
+ import { Elysia as Elysia33 } from "elysia";
19998
20087
  var escapeHtml34 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
19999
20088
  var rollupStatus2 = (checks) => checks.some((check) => check.status === "fail") ? "fail" : checks.some((check) => check.status === "warn") ? "warn" : "pass";
20000
20089
  var carrierStatus = (matrix) => matrix.summary.failing > 0 ? "fail" : matrix.summary.warnings > 0 || matrix.summary.ready < matrix.summary.providers ? "warn" : "pass";
@@ -20688,7 +20777,7 @@ var renderVoiceProductionReadinessHTML = (report, options = {}) => {
20688
20777
  var createVoiceProductionReadinessRoutes = (options) => {
20689
20778
  const path = options.path ?? "/api/production-readiness";
20690
20779
  const htmlPath = options.htmlPath ?? "/production-readiness";
20691
- const routes = new Elysia32({
20780
+ const routes = new Elysia33({
20692
20781
  name: options.name ?? "absolutejs-voice-production-readiness"
20693
20782
  });
20694
20783
  routes.get(path, async ({ query, request }) => buildVoiceProductionReadinessReport(options, { query, request }));
@@ -20710,7 +20799,7 @@ var createVoiceProductionReadinessRoutes = (options) => {
20710
20799
  return routes;
20711
20800
  };
20712
20801
  // src/opsConsoleRoutes.ts
20713
- import { Elysia as Elysia33 } from "elysia";
20802
+ import { Elysia as Elysia34 } from "elysia";
20714
20803
  var DEFAULT_LINKS = [
20715
20804
  {
20716
20805
  description: "Quality gates for CI, deploy checks, and production readiness.",
@@ -20827,7 +20916,7 @@ var renderVoiceOpsConsoleHTML = (report, options = {}) => {
20827
20916
  };
20828
20917
  var createVoiceOpsConsoleRoutes = (options) => {
20829
20918
  const path = options.path ?? "/ops-console";
20830
- const routes = new Elysia33({
20919
+ const routes = new Elysia34({
20831
20920
  name: options.name ?? "absolutejs-voice-ops-console"
20832
20921
  });
20833
20922
  const getReport = () => buildVoiceOpsConsoleReport(options);
@@ -21015,7 +21104,7 @@ var summarizeVoiceOpsStatus = async (options) => {
21015
21104
  };
21016
21105
  };
21017
21106
  // src/opsStatusRoutes.ts
21018
- import { Elysia as Elysia34 } from "elysia";
21107
+ import { Elysia as Elysia35 } from "elysia";
21019
21108
  var escapeHtml36 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21020
21109
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
21021
21110
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
@@ -21027,7 +21116,7 @@ var renderVoiceOpsStatusHTML = (report, options = {}) => {
21027
21116
  };
21028
21117
  var createVoiceOpsStatusRoutes = (options) => {
21029
21118
  const path = options.path ?? "/api/voice/ops-status";
21030
- const routes = new Elysia34({
21119
+ const routes = new Elysia35({
21031
21120
  name: options.name ?? "absolutejs-voice-ops-status"
21032
21121
  });
21033
21122
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -21460,7 +21549,7 @@ var createVoiceTTSProviderRouter = (options) => {
21460
21549
  };
21461
21550
  };
21462
21551
  // src/traceDeliveryRoutes.ts
21463
- import { Elysia as Elysia35 } from "elysia";
21552
+ import { Elysia as Elysia36 } from "elysia";
21464
21553
  var escapeHtml37 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21465
21554
  var getString12 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
21466
21555
  var getNumber7 = (value) => {
@@ -21569,7 +21658,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
21569
21658
  const path = options.path ?? "/api/voice-trace-deliveries";
21570
21659
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
21571
21660
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
21572
- const routes = new Elysia35({
21661
+ const routes = new Elysia36({
21573
21662
  name: options.name ?? "absolutejs-voice-trace-deliveries"
21574
21663
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
21575
21664
  if (htmlPath !== false) {
@@ -21587,7 +21676,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
21587
21676
  return routes;
21588
21677
  };
21589
21678
  // src/traceTimeline.ts
21590
- import { Elysia as Elysia36 } from "elysia";
21679
+ import { Elysia as Elysia37 } from "elysia";
21591
21680
  var escapeHtml38 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
21592
21681
  var getString13 = (value) => typeof value === "string" && value.trim() ? value : undefined;
21593
21682
  var getNumber8 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
@@ -21769,7 +21858,7 @@ var createVoiceTraceTimelineRoutes = (options) => {
21769
21858
  const path = options.path ?? "/api/voice-traces";
21770
21859
  const htmlPath = options.htmlPath ?? "/traces";
21771
21860
  const title = options.title ?? "AbsoluteJS Voice Trace Timelines";
21772
- const routes = new Elysia36({
21861
+ const routes = new Elysia37({
21773
21862
  name: options.name ?? "absolutejs-voice-trace-timelines"
21774
21863
  });
21775
21864
  const buildReport = async () => summarizeVoiceTraceTimeline(await options.store.list(), {
@@ -22422,7 +22511,7 @@ var createVoiceMemoryStore = () => {
22422
22511
  return { get, getOrCreate, list, remove, set };
22423
22512
  };
22424
22513
  // src/opsWebhook.ts
22425
- import { Elysia as Elysia37 } from "elysia";
22514
+ import { Elysia as Elysia38 } from "elysia";
22426
22515
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
22427
22516
  var signVoiceOpsWebhookBody = async (input) => {
22428
22517
  const encoder = new TextEncoder;
@@ -22552,7 +22641,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
22552
22641
  };
22553
22642
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
22554
22643
  const path = options.path ?? "/api/voice-ops/webhook";
22555
- return new Elysia37().post(path, async ({ body, request, set }) => {
22644
+ return new Elysia38().post(path, async ({ body, request, set }) => {
22556
22645
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
22557
22646
  if (options.signingSecret) {
22558
22647
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -23518,6 +23607,7 @@ export {
23518
23607
  recordVoiceRuntimeOps,
23519
23608
  recordVoiceRetentionAuditEvent,
23520
23609
  recordVoiceProviderAuditEvent,
23610
+ recordVoiceOpsActionAudit,
23521
23611
  recordVoiceOperatorAuditEvent,
23522
23612
  recordVoiceHandoffAuditEvent,
23523
23613
  recordVoiceAuditEvent,
@@ -23669,6 +23759,7 @@ export {
23669
23759
  createVoiceOpsStatusRoutes,
23670
23760
  createVoiceOpsRuntime,
23671
23761
  createVoiceOpsConsoleRoutes,
23762
+ createVoiceOpsActionAuditRoutes,
23672
23763
  createVoiceMemoryTraceSinkDeliveryStore,
23673
23764
  createVoiceMemoryTraceEventStore,
23674
23765
  createVoiceMemoryStore,
@@ -0,0 +1,79 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type VoiceAuditEventStore } from './audit';
3
+ import { type VoiceTraceEventStore } from './trace';
4
+ export type VoiceOpsActionAuditRecord = {
5
+ actionId: string;
6
+ body?: unknown;
7
+ error?: string;
8
+ ok: boolean;
9
+ ranAt: number;
10
+ status: number;
11
+ };
12
+ export type VoiceOpsActionAuditRoutesOptions = {
13
+ audit?: VoiceAuditEventStore;
14
+ name?: string;
15
+ path?: string;
16
+ trace?: VoiceTraceEventStore;
17
+ };
18
+ export declare const recordVoiceOpsActionAudit: (record: VoiceOpsActionAuditRecord, options: Pick<VoiceOpsActionAuditRoutesOptions, "audit" | "trace">) => Promise<{
19
+ audit: import("./audit").StoredVoiceAuditEvent<Record<string, unknown>> | (Omit<import("./audit").VoiceAuditEvent<Record<string, unknown>>, "at" | "id"> & {
20
+ at: number;
21
+ id: string;
22
+ }) | undefined;
23
+ ok: boolean;
24
+ trace: (import("./trace").VoiceTraceEvent<Record<string, unknown>> & {
25
+ id: string;
26
+ }) | undefined;
27
+ }>;
28
+ export declare const createVoiceOpsActionAuditRoutes: (options: VoiceOpsActionAuditRoutesOptions) => Elysia<"", {
29
+ decorator: {};
30
+ store: {};
31
+ derive: {};
32
+ resolve: {};
33
+ }, {
34
+ typebox: {};
35
+ error: {};
36
+ }, {
37
+ schema: {};
38
+ standaloneSchema: {};
39
+ macro: {};
40
+ macroFn: {};
41
+ parser: {};
42
+ response: {};
43
+ }, {
44
+ [x: string]: {
45
+ post: {
46
+ body: unknown;
47
+ params: {};
48
+ query: unknown;
49
+ headers: unknown;
50
+ response: {
51
+ 200: {
52
+ audit: import("./audit").StoredVoiceAuditEvent<Record<string, unknown>> | (Omit<import("./audit").VoiceAuditEvent<Record<string, unknown>>, "at" | "id"> & {
53
+ at: number;
54
+ id: string;
55
+ }) | undefined;
56
+ ok: boolean;
57
+ trace: (import("./trace").VoiceTraceEvent<Record<string, unknown>> & {
58
+ id: string;
59
+ }) | undefined;
60
+ } | {
61
+ error: string;
62
+ ok: boolean;
63
+ };
64
+ };
65
+ };
66
+ };
67
+ }, {
68
+ derive: {};
69
+ resolve: {};
70
+ schema: {};
71
+ standaloneSchema: {};
72
+ response: {};
73
+ }, {
74
+ derive: {};
75
+ resolve: {};
76
+ schema: {};
77
+ standaloneSchema: {};
78
+ response: {};
79
+ }>;
@@ -388,6 +388,23 @@ var VoiceOpsStatus = ({
388
388
  }, undefined, true, undefined, this);
389
389
  };
390
390
  // src/client/opsActionCenter.ts
391
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
392
+ if (options.auditPath === false) {
393
+ return;
394
+ }
395
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
396
+ const fetchImpl = options.fetch ?? globalThis.fetch;
397
+ const response = await fetchImpl(path, {
398
+ body: JSON.stringify(result),
399
+ headers: {
400
+ "Content-Type": "application/json"
401
+ },
402
+ method: "POST"
403
+ });
404
+ if (!response.ok) {
405
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
406
+ }
407
+ };
391
408
  var createVoiceOpsActionCenterActions = (options = {}) => {
392
409
  const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
393
410
  const actions = [];
@@ -500,6 +517,8 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
500
517
  emit();
501
518
  try {
502
519
  const result = await runVoiceOpsAction(action, options);
520
+ await options.onActionResult?.(result);
521
+ await recordVoiceOpsActionResult(result, options);
503
522
  snapshot = {
504
523
  ...snapshot,
505
524
  error: null,
@@ -511,6 +530,16 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
511
530
  emit();
512
531
  return result;
513
532
  } catch (error) {
533
+ const result = {
534
+ actionId: action.id,
535
+ body: null,
536
+ error: error instanceof Error ? error.message : String(error),
537
+ ok: false,
538
+ ranAt: Date.now(),
539
+ status: 0
540
+ };
541
+ await options.onActionResult?.(result);
542
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
514
543
  snapshot = {
515
544
  ...snapshot,
516
545
  error: error instanceof Error ? error.message : String(error),
@@ -469,6 +469,23 @@ var createVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options
469
469
  };
470
470
  };
471
471
  // src/client/opsActionCenter.ts
472
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
473
+ if (options.auditPath === false) {
474
+ return;
475
+ }
476
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
477
+ const fetchImpl = options.fetch ?? globalThis.fetch;
478
+ const response = await fetchImpl(path, {
479
+ body: JSON.stringify(result),
480
+ headers: {
481
+ "Content-Type": "application/json"
482
+ },
483
+ method: "POST"
484
+ });
485
+ if (!response.ok) {
486
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
487
+ }
488
+ };
472
489
  var createVoiceOpsActionCenterActions = (options = {}) => {
473
490
  const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
474
491
  const actions = [];
@@ -581,6 +598,8 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
581
598
  emit();
582
599
  try {
583
600
  const result = await runVoiceOpsAction(action, options);
601
+ await options.onActionResult?.(result);
602
+ await recordVoiceOpsActionResult(result, options);
584
603
  snapshot = {
585
604
  ...snapshot,
586
605
  error: null,
@@ -592,6 +611,16 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
592
611
  emit();
593
612
  return result;
594
613
  } catch (error) {
614
+ const result = {
615
+ actionId: action.id,
616
+ body: null,
617
+ error: error instanceof Error ? error.message : String(error),
618
+ ok: false,
619
+ ranAt: Date.now(),
620
+ status: 0
621
+ };
622
+ await options.onActionResult?.(result);
623
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
595
624
  snapshot = {
596
625
  ...snapshot,
597
626
  error: error instanceof Error ? error.message : String(error),
package/dist/trace.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { S3Client, S3Options } from 'bun';
2
- export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'client.live_latency' | 'client.reconnect' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn_latency.stage' | 'turn.transcript' | 'workflow.contract';
2
+ export type VoiceTraceEventType = 'assistant.guardrail' | 'assistant.memory' | 'assistant.run' | 'agent.handoff' | 'agent.model' | 'agent.result' | 'agent.tool' | 'call.handoff' | 'call.lifecycle' | 'client.barge_in' | 'client.live_latency' | 'client.reconnect' | 'operator.action' | 'session.error' | 'turn.assistant' | 'turn.committed' | 'turn.cost' | 'turn_latency.stage' | 'turn.transcript' | 'workflow.contract';
3
3
  export type VoiceTraceEvent<TPayload extends Record<string, unknown> = Record<string, unknown>> = {
4
4
  at: number;
5
5
  id?: string;
package/dist/vue/index.js CHANGED
@@ -378,6 +378,23 @@ var VoiceOpsStatus = defineComponent({
378
378
  import { defineComponent as defineComponent2, h as h2 } from "vue";
379
379
 
380
380
  // src/client/opsActionCenter.ts
381
+ var recordVoiceOpsActionResult = async (result, options = {}) => {
382
+ if (options.auditPath === false) {
383
+ return;
384
+ }
385
+ const path = options.auditPath ?? "/api/voice/ops-actions/audit";
386
+ const fetchImpl = options.fetch ?? globalThis.fetch;
387
+ const response = await fetchImpl(path, {
388
+ body: JSON.stringify(result),
389
+ headers: {
390
+ "Content-Type": "application/json"
391
+ },
392
+ method: "POST"
393
+ });
394
+ if (!response.ok) {
395
+ throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
396
+ }
397
+ };
381
398
  var createVoiceOpsActionCenterActions = (options = {}) => {
382
399
  const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
383
400
  const actions = [];
@@ -490,6 +507,8 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
490
507
  emit();
491
508
  try {
492
509
  const result = await runVoiceOpsAction(action, options);
510
+ await options.onActionResult?.(result);
511
+ await recordVoiceOpsActionResult(result, options);
493
512
  snapshot = {
494
513
  ...snapshot,
495
514
  error: null,
@@ -501,6 +520,16 @@ var createVoiceOpsActionCenterStore = (options = {}) => {
501
520
  emit();
502
521
  return result;
503
522
  } catch (error) {
523
+ const result = {
524
+ actionId: action.id,
525
+ body: null,
526
+ error: error instanceof Error ? error.message : String(error),
527
+ ok: false,
528
+ ranAt: Date.now(),
529
+ status: 0
530
+ };
531
+ await options.onActionResult?.(result);
532
+ await recordVoiceOpsActionResult(result, options).catch(() => {});
504
533
  snapshot = {
505
534
  ...snapshot,
506
535
  error: error instanceof Error ? error.message : String(error),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.154",
3
+ "version": "0.0.22-beta.155",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",