@absolutejs/voice 0.0.22-beta.260 → 0.0.22-beta.262

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.
@@ -6,6 +6,6 @@ export declare class VoiceLiveOpsService {
6
6
  isRunning: import("@angular/core").Signal<boolean>;
7
7
  lastResult: import("@angular/core").Signal<VoiceLiveOpsActionResult | undefined>;
8
8
  run: (input: import("..").VoiceLiveOpsActionInput) => Promise<VoiceLiveOpsActionResult | undefined>;
9
- runningAction: import("@angular/core").Signal<"assign" | "create-task" | "escalate" | "force-handoff" | "inject-instruction" | "operator-takeover" | "pause-assistant" | "resume-assistant" | "tag" | undefined>;
9
+ runningAction: import("@angular/core").Signal<"escalate" | "assign" | "create-task" | "force-handoff" | "inject-instruction" | "operator-takeover" | "pause-assistant" | "resume-assistant" | "tag" | undefined>;
10
10
  };
11
11
  }
@@ -4206,6 +4206,99 @@ var VOICE_LIVE_OPS_ACTIONS = [
4206
4206
  ];
4207
4207
  var isVoiceLiveOpsAction = (value) => typeof value === "string" && VOICE_LIVE_OPS_ACTIONS.includes(value);
4208
4208
  var toStringValue = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
4209
+ var uniqueSorted = (values) => Array.from(new Set(values)).sort();
4210
+ var findMissing = (values, required) => {
4211
+ if (!required?.length) {
4212
+ return [];
4213
+ }
4214
+ const valueSet = new Set(values);
4215
+ return required.filter((value) => !valueSet.has(value));
4216
+ };
4217
+ var evaluateVoiceLiveOpsEvidence = (input = {}) => {
4218
+ const issues = [];
4219
+ const actionHistory = input.actionHistory;
4220
+ const opsRecovery = input.opsRecovery;
4221
+ const opsStatus = input.opsStatus;
4222
+ const operationsRecord = input.operationsRecord;
4223
+ const historyActions = uniqueSorted(actionHistory?.entries.map((entry) => entry.actionId) ?? []);
4224
+ const interventionActions = uniqueSorted(opsRecovery?.interventions.events.map((event) => event.action).filter((action) => Boolean(action)) ?? []);
4225
+ const requireActionHistory = input.requireActionHistory ?? true;
4226
+ const requireOperationsRecord = input.requireOperationsRecord ?? true;
4227
+ const requireOpsRecovery = input.requireOpsRecovery ?? true;
4228
+ const requireOpsRecoveryStatus = input.requireOpsRecoveryStatus ?? "pass";
4229
+ const requireOpsStatus = input.requireOpsStatus ?? true;
4230
+ const requireOpsStatusPass = input.requireOpsStatusPass ?? true;
4231
+ if (requireActionHistory && !actionHistory) {
4232
+ issues.push("Expected live-ops action history report to be present.");
4233
+ }
4234
+ if (requireOpsRecovery && !opsRecovery) {
4235
+ issues.push("Expected ops recovery report to be present.");
4236
+ }
4237
+ if (requireOpsStatus && !opsStatus) {
4238
+ issues.push("Expected ops status report to be present.");
4239
+ }
4240
+ if (requireOperationsRecord && !operationsRecord) {
4241
+ issues.push("Expected operations record to be present.");
4242
+ }
4243
+ if (opsRecovery && opsRecovery.status !== requireOpsRecoveryStatus) {
4244
+ issues.push(`Expected ops recovery status ${requireOpsRecoveryStatus}, found ${opsRecovery.status}.`);
4245
+ }
4246
+ if (opsRecovery && input.maxOpsRecoveryIssues !== undefined && opsRecovery.issues.length > input.maxOpsRecoveryIssues) {
4247
+ issues.push(`Expected at most ${String(input.maxOpsRecoveryIssues)} ops recovery issue(s), found ${String(opsRecovery.issues.length)}.`);
4248
+ }
4249
+ if (opsRecovery && input.minInterventions !== undefined && opsRecovery.interventions.total < input.minInterventions) {
4250
+ issues.push(`Expected at least ${String(input.minInterventions)} live-ops intervention(s), found ${String(opsRecovery.interventions.total)}.`);
4251
+ }
4252
+ for (const action of findMissing(interventionActions, input.requiredInterventionActions)) {
4253
+ issues.push(`Missing live-ops intervention action: ${action}.`);
4254
+ }
4255
+ if (opsStatus && requireOpsStatusPass && opsStatus.status !== "pass") {
4256
+ issues.push(`Expected ops status pass, found ${opsStatus.status}.`);
4257
+ }
4258
+ if (actionHistory && input.minActionHistoryEntries !== undefined && actionHistory.total < input.minActionHistoryEntries) {
4259
+ issues.push(`Expected at least ${String(input.minActionHistoryEntries)} operator action history entrie(s), found ${String(actionHistory.total)}.`);
4260
+ }
4261
+ if (actionHistory && input.maxActionHistoryFailures !== undefined && actionHistory.failed > input.maxActionHistoryFailures) {
4262
+ issues.push(`Expected at most ${String(input.maxActionHistoryFailures)} failed operator action(s), found ${String(actionHistory.failed)}.`);
4263
+ }
4264
+ for (const action of findMissing(historyActions, input.requiredHistoryActions)) {
4265
+ issues.push(`Missing operator action history action: ${action}.`);
4266
+ }
4267
+ if (operationsRecord && input.requireOperationsRecordHealthy !== false && operationsRecord.status === "failed") {
4268
+ issues.push("Expected operations record not to be failed.");
4269
+ }
4270
+ if (operationsRecord && input.requireOperationsRecordAudit && !operationsRecord.audit) {
4271
+ issues.push("Expected operations record audit summary to be present.");
4272
+ }
4273
+ if (operationsRecord && input.minOperationsRecordHandoffs !== undefined && operationsRecord.handoffs.length < input.minOperationsRecordHandoffs) {
4274
+ issues.push(`Expected at least ${String(input.minOperationsRecordHandoffs)} operations-record handoff(s), found ${String(operationsRecord.handoffs.length)}.`);
4275
+ }
4276
+ if (operationsRecord && input.minOperationsRecordTasks !== undefined && (operationsRecord.tasks?.total ?? 0) < input.minOperationsRecordTasks) {
4277
+ issues.push(`Expected at least ${String(input.minOperationsRecordTasks)} operations-record task(s), found ${String(operationsRecord.tasks?.total ?? 0)}.`);
4278
+ }
4279
+ return {
4280
+ actionHistoryFailed: actionHistory?.failed,
4281
+ actionHistoryTotal: actionHistory?.total,
4282
+ historyActions,
4283
+ interventionActions,
4284
+ interventions: opsRecovery?.interventions.total,
4285
+ issues,
4286
+ ok: issues.length === 0,
4287
+ operationsRecordHandoffs: operationsRecord?.handoffs.length,
4288
+ operationsRecordStatus: operationsRecord?.status,
4289
+ operationsRecordTasks: operationsRecord?.tasks?.total,
4290
+ opsRecoveryIssues: opsRecovery?.issues.length,
4291
+ opsRecoveryStatus: opsRecovery?.status,
4292
+ opsStatus: opsStatus?.status
4293
+ };
4294
+ };
4295
+ var assertVoiceLiveOpsEvidence = (input = {}) => {
4296
+ const assertion = evaluateVoiceLiveOpsEvidence(input);
4297
+ if (!assertion.ok) {
4298
+ throw new Error(`Voice live-ops evidence assertion failed: ${assertion.issues.join(" ")}`);
4299
+ }
4300
+ return assertion;
4301
+ };
4209
4302
  var createVoiceMemoryLiveOpsControlStore = () => {
4210
4303
  const states = new Map;
4211
4304
  return {
package/dist/index.d.ts CHANGED
@@ -18,8 +18,8 @@ export { assertVoicePlatformCoverage, buildVoicePlatformCoverageSummary, createV
18
18
  export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertionReport, VoicePlatformCoverageEvidence, VoicePlatformCoverageRoutesOptions, VoicePlatformCoverageStatus, VoicePlatformCoverageSummary, VoicePlatformCoverageSummaryInput, VoicePlatformCoverageSurface } from './platformCoverage';
19
19
  export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendReport, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile } from './proofTrends';
20
20
  export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
21
- export { buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
22
- export type { VoiceLiveOpsAction, VoiceLiveOpsActionInput, VoiceLiveOpsActionResult, VoiceLiveOpsControllerOptions, VoiceLiveOpsControlState, VoiceLiveOpsControlStatus, VoiceLiveOpsControlStore, VoiceLiveOpsRoutesOptions } from './liveOps';
21
+ export { assertVoiceLiveOpsEvidence, buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, evaluateVoiceLiveOpsEvidence, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
22
+ export type { VoiceLiveOpsAction, VoiceLiveOpsActionInput, VoiceLiveOpsActionResult, VoiceLiveOpsControllerOptions, VoiceLiveOpsControlState, VoiceLiveOpsControlStatus, VoiceLiveOpsControlStore, VoiceLiveOpsEvidenceInput, VoiceLiveOpsEvidenceReport, VoiceLiveOpsRoutesOptions } from './liveOps';
23
23
  export { buildVoiceDeliveryRuntimeReport, createVoiceDeliveryRuntime, createVoiceDeliveryRuntimePresetConfig, createVoiceDeliveryRuntimeRoutes, renderVoiceDeliveryRuntimeHTML } from './deliveryRuntime';
24
24
  export { applyVoiceDataRetentionPolicy, assertVoiceDataControlEvidence, buildVoiceDataControlReport, buildVoiceDataRetentionPlan, createVoiceDataControlRoutes, createVoiceZeroRetentionPolicy, evaluateVoiceDataControlEvidence, renderVoiceDataControlHTML, renderVoiceDataControlMarkdown, voiceComplianceRedactionDefaults } from './dataControl';
25
25
  export type { VoiceDataControlAssertionInput, VoiceDataControlAssertionReport, VoiceDataControlProviderKeySurface, VoiceDataControlReport, VoiceDataControlRoutesOptions, VoiceDataControlStorageSurface, VoiceDataRetentionPolicy, VoiceDataRetentionReport, VoiceDataRetentionScope, VoiceDataRetentionScopeReport, VoiceDataRetentionStores } from './dataControl';
package/dist/index.js CHANGED
@@ -12235,8 +12235,7 @@ var createVoiceDeliverySinkRoutes = (options) => {
12235
12235
  };
12236
12236
  // src/opsActionAuditRoutes.ts
12237
12237
  import { Elysia as Elysia12 } from "elysia";
12238
- var readRecord = async (request) => {
12239
- const body = await request.json().catch(() => null);
12238
+ var readRecordBody = (body) => {
12240
12239
  if (!body || typeof body !== "object") {
12241
12240
  throw new Error("Voice ops action audit requires a JSON body.");
12242
12241
  }
@@ -12253,6 +12252,7 @@ var readRecord = async (request) => {
12253
12252
  status: typeof record.status === "number" ? record.status : 0
12254
12253
  };
12255
12254
  };
12255
+ var readRecord = async (request) => readRecordBody(await request.json().catch(() => null));
12256
12256
  var recordVoiceOpsActionAudit = async (record, options) => {
12257
12257
  const traceId = `voice-ops-action:${record.actionId}:${record.ranAt}`;
12258
12258
  const outcome = record.ok ? "success" : "error";
@@ -12311,9 +12311,9 @@ var createVoiceOpsActionAuditRoutes = (options) => {
12311
12311
  const historyHtmlPath = options.historyHtmlPath === undefined ? "/voice/ops-actions" : options.historyHtmlPath;
12312
12312
  const routes = new Elysia12({
12313
12313
  name: options.name ?? "absolutejs-voice-ops-action-audit"
12314
- }).post(path, async ({ request, set }) => {
12314
+ }).post(path, async ({ body, request, set }) => {
12315
12315
  try {
12316
- const record = await readRecord(request);
12316
+ const record = body === undefined ? await readRecord(request) : readRecordBody(body);
12317
12317
  return await recordVoiceOpsActionAudit(record, options);
12318
12318
  } catch (error) {
12319
12319
  set.status = 400;
@@ -12636,6 +12636,99 @@ var VOICE_LIVE_OPS_ACTIONS = [
12636
12636
  ];
12637
12637
  var isVoiceLiveOpsAction = (value) => typeof value === "string" && VOICE_LIVE_OPS_ACTIONS.includes(value);
12638
12638
  var toStringValue = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
12639
+ var uniqueSorted = (values) => Array.from(new Set(values)).sort();
12640
+ var findMissing = (values, required) => {
12641
+ if (!required?.length) {
12642
+ return [];
12643
+ }
12644
+ const valueSet = new Set(values);
12645
+ return required.filter((value) => !valueSet.has(value));
12646
+ };
12647
+ var evaluateVoiceLiveOpsEvidence = (input = {}) => {
12648
+ const issues = [];
12649
+ const actionHistory = input.actionHistory;
12650
+ const opsRecovery = input.opsRecovery;
12651
+ const opsStatus = input.opsStatus;
12652
+ const operationsRecord = input.operationsRecord;
12653
+ const historyActions = uniqueSorted(actionHistory?.entries.map((entry) => entry.actionId) ?? []);
12654
+ const interventionActions = uniqueSorted(opsRecovery?.interventions.events.map((event) => event.action).filter((action) => Boolean(action)) ?? []);
12655
+ const requireActionHistory = input.requireActionHistory ?? true;
12656
+ const requireOperationsRecord = input.requireOperationsRecord ?? true;
12657
+ const requireOpsRecovery = input.requireOpsRecovery ?? true;
12658
+ const requireOpsRecoveryStatus = input.requireOpsRecoveryStatus ?? "pass";
12659
+ const requireOpsStatus = input.requireOpsStatus ?? true;
12660
+ const requireOpsStatusPass = input.requireOpsStatusPass ?? true;
12661
+ if (requireActionHistory && !actionHistory) {
12662
+ issues.push("Expected live-ops action history report to be present.");
12663
+ }
12664
+ if (requireOpsRecovery && !opsRecovery) {
12665
+ issues.push("Expected ops recovery report to be present.");
12666
+ }
12667
+ if (requireOpsStatus && !opsStatus) {
12668
+ issues.push("Expected ops status report to be present.");
12669
+ }
12670
+ if (requireOperationsRecord && !operationsRecord) {
12671
+ issues.push("Expected operations record to be present.");
12672
+ }
12673
+ if (opsRecovery && opsRecovery.status !== requireOpsRecoveryStatus) {
12674
+ issues.push(`Expected ops recovery status ${requireOpsRecoveryStatus}, found ${opsRecovery.status}.`);
12675
+ }
12676
+ if (opsRecovery && input.maxOpsRecoveryIssues !== undefined && opsRecovery.issues.length > input.maxOpsRecoveryIssues) {
12677
+ issues.push(`Expected at most ${String(input.maxOpsRecoveryIssues)} ops recovery issue(s), found ${String(opsRecovery.issues.length)}.`);
12678
+ }
12679
+ if (opsRecovery && input.minInterventions !== undefined && opsRecovery.interventions.total < input.minInterventions) {
12680
+ issues.push(`Expected at least ${String(input.minInterventions)} live-ops intervention(s), found ${String(opsRecovery.interventions.total)}.`);
12681
+ }
12682
+ for (const action of findMissing(interventionActions, input.requiredInterventionActions)) {
12683
+ issues.push(`Missing live-ops intervention action: ${action}.`);
12684
+ }
12685
+ if (opsStatus && requireOpsStatusPass && opsStatus.status !== "pass") {
12686
+ issues.push(`Expected ops status pass, found ${opsStatus.status}.`);
12687
+ }
12688
+ if (actionHistory && input.minActionHistoryEntries !== undefined && actionHistory.total < input.minActionHistoryEntries) {
12689
+ issues.push(`Expected at least ${String(input.minActionHistoryEntries)} operator action history entrie(s), found ${String(actionHistory.total)}.`);
12690
+ }
12691
+ if (actionHistory && input.maxActionHistoryFailures !== undefined && actionHistory.failed > input.maxActionHistoryFailures) {
12692
+ issues.push(`Expected at most ${String(input.maxActionHistoryFailures)} failed operator action(s), found ${String(actionHistory.failed)}.`);
12693
+ }
12694
+ for (const action of findMissing(historyActions, input.requiredHistoryActions)) {
12695
+ issues.push(`Missing operator action history action: ${action}.`);
12696
+ }
12697
+ if (operationsRecord && input.requireOperationsRecordHealthy !== false && operationsRecord.status === "failed") {
12698
+ issues.push("Expected operations record not to be failed.");
12699
+ }
12700
+ if (operationsRecord && input.requireOperationsRecordAudit && !operationsRecord.audit) {
12701
+ issues.push("Expected operations record audit summary to be present.");
12702
+ }
12703
+ if (operationsRecord && input.minOperationsRecordHandoffs !== undefined && operationsRecord.handoffs.length < input.minOperationsRecordHandoffs) {
12704
+ issues.push(`Expected at least ${String(input.minOperationsRecordHandoffs)} operations-record handoff(s), found ${String(operationsRecord.handoffs.length)}.`);
12705
+ }
12706
+ if (operationsRecord && input.minOperationsRecordTasks !== undefined && (operationsRecord.tasks?.total ?? 0) < input.minOperationsRecordTasks) {
12707
+ issues.push(`Expected at least ${String(input.minOperationsRecordTasks)} operations-record task(s), found ${String(operationsRecord.tasks?.total ?? 0)}.`);
12708
+ }
12709
+ return {
12710
+ actionHistoryFailed: actionHistory?.failed,
12711
+ actionHistoryTotal: actionHistory?.total,
12712
+ historyActions,
12713
+ interventionActions,
12714
+ interventions: opsRecovery?.interventions.total,
12715
+ issues,
12716
+ ok: issues.length === 0,
12717
+ operationsRecordHandoffs: operationsRecord?.handoffs.length,
12718
+ operationsRecordStatus: operationsRecord?.status,
12719
+ operationsRecordTasks: operationsRecord?.tasks?.total,
12720
+ opsRecoveryIssues: opsRecovery?.issues.length,
12721
+ opsRecoveryStatus: opsRecovery?.status,
12722
+ opsStatus: opsStatus?.status
12723
+ };
12724
+ };
12725
+ var assertVoiceLiveOpsEvidence = (input = {}) => {
12726
+ const assertion = evaluateVoiceLiveOpsEvidence(input);
12727
+ if (!assertion.ok) {
12728
+ throw new Error(`Voice live-ops evidence assertion failed: ${assertion.issues.join(" ")}`);
12729
+ }
12730
+ return assertion;
12731
+ };
12639
12732
  var createVoiceMemoryLiveOpsControlStore = () => {
12640
12733
  const states = new Map;
12641
12734
  return {
@@ -13422,8 +13515,8 @@ var defaultProviderKeys = [
13422
13515
  }
13423
13516
  ];
13424
13517
  var resolveDataControlRedaction = (redact) => redact === false ? undefined : redact === true || redact === undefined ? voiceComplianceRedactionDefaults : redact;
13425
- var uniqueSorted = (values) => Array.from(new Set(values)).sort();
13426
- var findMissing = (values, required) => {
13518
+ var uniqueSorted2 = (values) => Array.from(new Set(values)).sort();
13519
+ var findMissing2 = (values, required) => {
13427
13520
  if (!required?.length) {
13428
13521
  return [];
13429
13522
  }
@@ -13434,10 +13527,10 @@ var evaluateVoiceDataControlEvidence = (report, input = {}) => {
13434
13527
  const issues = [];
13435
13528
  const configuredStorage = report.storage.filter((surface) => surface.configured).map((surface) => surface.name);
13436
13529
  const selfHostedConfiguredStorage = report.storage.filter((surface) => surface.configured && surface.selfHosted).map((surface) => surface.name);
13437
- const controls = uniqueSorted(report.storage.filter((surface) => surface.configured).map((surface) => surface.control));
13438
- const retentionScopes = uniqueSorted(report.retentionPlan.scopes.map((scope) => scope.scope));
13439
- const deletionScopes = uniqueSorted(report.deletionProof?.scopes.map((scope) => scope.scope) ?? []);
13440
- const providerKeys = uniqueSorted(report.providerKeys.map((key) => key.name.toLowerCase()));
13530
+ const controls = uniqueSorted2(report.storage.filter((surface) => surface.configured).map((surface) => surface.control));
13531
+ const retentionScopes = uniqueSorted2(report.retentionPlan.scopes.map((scope) => scope.scope));
13532
+ const deletionScopes = uniqueSorted2(report.deletionProof?.scopes.map((scope) => scope.scope) ?? []);
13533
+ const providerKeys = uniqueSorted2(report.providerKeys.map((key) => key.name.toLowerCase()));
13441
13534
  const auditExportEvents = report.auditExport?.events.length ?? 0;
13442
13535
  const deletionDeleted = report.deletionProof?.deletedCount ?? 0;
13443
13536
  const maxRetentionDeleted = input.maxRetentionDeleted;
@@ -13485,14 +13578,14 @@ var evaluateVoiceDataControlEvidence = (report, input = {}) => {
13485
13578
  issues.push(`Expected configured storage to be self-hosted, found ${String(nonSelfHostedConfigured)} non-self-hosted surfaces.`);
13486
13579
  }
13487
13580
  }
13488
- const missingConfiguredStorage = findMissing(configuredStorage, input.requiredStorage);
13581
+ const missingConfiguredStorage = findMissing2(configuredStorage, input.requiredStorage);
13489
13582
  if (missingConfiguredStorage.length > (input.maxMissingConfiguredStorage ?? 0)) {
13490
13583
  issues.push(`Missing configured storage surfaces: ${missingConfiguredStorage.join(", ")}.`);
13491
13584
  }
13492
- for (const control of findMissing(controls, input.requiredControls)) {
13585
+ for (const control of findMissing2(controls, input.requiredControls)) {
13493
13586
  issues.push(`Missing configured storage control: ${control}.`);
13494
13587
  }
13495
- for (const scope of findMissing(retentionScopes, input.requiredRetentionScopes)) {
13588
+ for (const scope of findMissing2(retentionScopes, input.requiredRetentionScopes)) {
13496
13589
  issues.push(`Missing retention scope: ${scope}.`);
13497
13590
  }
13498
13591
  for (const scope of input.requiredRetentionScopes ?? []) {
@@ -13501,7 +13594,7 @@ var evaluateVoiceDataControlEvidence = (report, input = {}) => {
13501
13594
  issues.push(`Retention scope ${scope} was skipped: ${retentionScope.skippedReason}.`);
13502
13595
  }
13503
13596
  }
13504
- for (const scope of findMissing(deletionScopes, input.requiredDeletionScopes)) {
13597
+ for (const scope of findMissing2(deletionScopes, input.requiredDeletionScopes)) {
13505
13598
  issues.push(`Missing deletion-proof scope: ${scope}.`);
13506
13599
  }
13507
13600
  for (const scope of input.requiredDeletionScopes ?? []) {
@@ -19875,8 +19968,8 @@ var loadCarrierMatrixInputs = async (input) => {
19875
19968
  };
19876
19969
  var carrierAnswerLabel = (provider) => provider === "telnyx" ? "TeXML URL" : provider === "plivo" ? "Answer URL" : "TwiML URL";
19877
19970
  var findCarrierMatrixEntry = (matrix, carrier) => matrix?.entries.find((candidate) => candidate.provider === carrier.provider && (candidate.name === carrier.name || candidate.name === (carrier.name ?? carrier.provider)));
19878
- var uniqueSorted2 = (values) => Array.from(new Set(values)).sort();
19879
- var findMissing2 = (values, required) => {
19971
+ var uniqueSorted3 = (values) => Array.from(new Set(values)).sort();
19972
+ var findMissing3 = (values, required) => {
19880
19973
  if (!required?.length) {
19881
19974
  return [];
19882
19975
  }
@@ -19885,8 +19978,8 @@ var findMissing2 = (values, required) => {
19885
19978
  };
19886
19979
  var evaluateVoicePhoneAssistantEvidence = (report, input = {}) => {
19887
19980
  const issues = [];
19888
- const providers = uniqueSorted2(report.carriers.map((carrier) => carrier.provider));
19889
- const lifecycleStages = uniqueSorted2(report.lifecycleStages);
19981
+ const providers = uniqueSorted3(report.carriers.map((carrier) => carrier.provider));
19982
+ const lifecycleStages = uniqueSorted3(report.lifecycleStages);
19890
19983
  const carrierSummary = report.matrix?.summary;
19891
19984
  const carrierFailures = carrierSummary?.failing ?? 0;
19892
19985
  const carrierWarnings = carrierSummary?.warnings ?? 0;
@@ -19926,10 +20019,10 @@ var evaluateVoicePhoneAssistantEvidence = (report, input = {}) => {
19926
20019
  if (input.maxCarrierWarnings !== undefined && carrierWarnings > input.maxCarrierWarnings) {
19927
20020
  issues.push(`Expected at most ${String(input.maxCarrierWarnings)} phone carrier warning(s), found ${String(carrierWarnings)}.`);
19928
20021
  }
19929
- for (const provider of findMissing2(providers, input.requiredProviders)) {
20022
+ for (const provider of findMissing3(providers, input.requiredProviders)) {
19930
20023
  issues.push(`Missing phone carrier provider: ${provider}.`);
19931
20024
  }
19932
- for (const stage of findMissing2(lifecycleStages, input.requiredLifecycleStages)) {
20025
+ for (const stage of findMissing3(lifecycleStages, input.requiredLifecycleStages)) {
19933
20026
  issues.push(`Missing phone lifecycle stage: ${stage}.`);
19934
20027
  }
19935
20028
  const dialer = input.dialerProof ? evaluateVoiceCampaignDialerProofEvidence(input.dialerProof, {
@@ -22900,7 +22993,7 @@ var statusRank = {
22900
22993
  var escapeHtml36 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
22901
22994
  var roundMetric3 = (value) => Math.round(value * 1e4) / 1e4;
22902
22995
  var rate3 = (count, total) => count / Math.max(1, total);
22903
- var uniqueSorted3 = (values) => [
22996
+ var uniqueSorted4 = (values) => [
22904
22997
  ...new Set(values.filter((value) => typeof value === "string"))
22905
22998
  ].sort();
22906
22999
  var percentile3 = (values, rank) => {
@@ -23083,7 +23176,7 @@ var buildVoiceProviderSloReport = async (options = {}) => {
23083
23176
  var evaluateVoiceProviderSloEvidence = (report, input = {}) => {
23084
23177
  const issues = [];
23085
23178
  const kindReports = Object.values(report.kinds);
23086
- const providers = uniqueSorted3(kindReports.flatMap((kind) => kind.providers));
23179
+ const providers = uniqueSorted4(kindReports.flatMap((kind) => kind.providers));
23087
23180
  const kinds = providerKinds.filter((kind) => report.kinds[kind].events > 0);
23088
23181
  const fallbacks = kindReports.reduce((total, kind) => total + kind.fallbacks, 0);
23089
23182
  const timeouts = kindReports.reduce((total, kind) => total + kind.timeouts, 0);
@@ -23804,7 +23897,7 @@ var hasPayloadValue = (payload, key, values) => {
23804
23897
  return typeof value === "string" && values.has(value);
23805
23898
  };
23806
23899
  var countIntegrationDeliveryStatus = (events, status) => events.filter((event) => event.deliveryStatus === status).length;
23807
- var uniqueSorted4 = (values) => [
23900
+ var uniqueSorted5 = (values) => [
23808
23901
  ...new Set(values.filter((value) => typeof value === "string"))
23809
23902
  ].sort();
23810
23903
  var pushMissingValuesIssue = (input) => {
@@ -23983,11 +24076,11 @@ var buildVoiceOperationsRecord = async (options) => {
23983
24076
  var evaluateVoiceOperationsRecordGuardrails = (record, input = {}) => {
23984
24077
  const issues = [];
23985
24078
  const decisions = record.guardrails.decisions;
23986
- const proofs = uniqueSorted4(decisions.map((decision) => decision.proof));
23987
- const ruleIds = uniqueSorted4(decisions.flatMap((decision) => decision.findings.map((finding) => finding.ruleId)));
23988
- const stages = uniqueSorted4(decisions.map((decision) => decision.stage));
23989
- const statuses = uniqueSorted4(decisions.map((decision) => decision.status));
23990
- const toolNames = uniqueSorted4(decisions.map((decision) => decision.toolName));
24079
+ const proofs = uniqueSorted5(decisions.map((decision) => decision.proof));
24080
+ const ruleIds = uniqueSorted5(decisions.flatMap((decision) => decision.findings.map((finding) => finding.ruleId)));
24081
+ const stages = uniqueSorted5(decisions.map((decision) => decision.stage));
24082
+ const statuses = uniqueSorted5(decisions.map((decision) => decision.status));
24083
+ const toolNames = uniqueSorted5(decisions.map((decision) => decision.toolName));
23991
24084
  const minDecisions = input.minDecisions ?? 1;
23992
24085
  if (record.guardrails.total < minDecisions) {
23993
24086
  issues.push(`Expected at least ${String(minDecisions)} guardrail decisions, found ${String(record.guardrails.total)}.`);
@@ -31240,6 +31333,7 @@ export {
31240
31333
  evaluateVoiceOperationsRecordGuardrails,
31241
31334
  evaluateVoiceObservabilityExportReplayEvidence,
31242
31335
  evaluateVoiceObservabilityExportDeliveryEvidence,
31336
+ evaluateVoiceLiveOpsEvidence,
31243
31337
  evaluateVoiceGuardrailPolicy,
31244
31338
  evaluateVoiceDataControlEvidence,
31245
31339
  evaluateVoiceCampaignReadinessEvidence,
@@ -31573,6 +31667,7 @@ export {
31573
31667
  assertVoiceObservabilityExportReplayEvidence,
31574
31668
  assertVoiceObservabilityExportRecord,
31575
31669
  assertVoiceObservabilityExportDeliveryEvidence,
31670
+ assertVoiceLiveOpsEvidence,
31576
31671
  assertVoiceLatencySLOGate,
31577
31672
  assertVoiceDataControlEvidence,
31578
31673
  assertVoiceCampaignReadinessEvidence,
package/dist/liveOps.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import { type VoiceAuditEventStore } from './audit';
3
3
  import { type VoiceTraceEventStore } from './trace';
4
+ import type { VoiceOperationsRecord } from './operationsRecord';
5
+ import type { VoiceOpsActionHistoryReport } from './opsActionAuditRoutes';
6
+ import type { VoiceOpsRecoveryReport, VoiceOpsRecoveryStatus } from './opsRecovery';
7
+ import type { VoiceOpsStatusReport } from './opsStatus';
4
8
  export declare const VOICE_LIVE_OPS_ACTIONS: readonly ["assign", "create-task", "escalate", "force-handoff", "inject-instruction", "operator-takeover", "pause-assistant", "resume-assistant", "tag"];
5
9
  export type VoiceLiveOpsAction = (typeof VOICE_LIVE_OPS_ACTIONS)[number];
6
10
  export type VoiceLiveOpsControlStatus = 'assistant-paused' | 'assistant-resumed' | 'handoff-forced' | 'instruction-injected' | 'operator-takeover' | 'recorded';
@@ -28,6 +32,43 @@ export type VoiceLiveOpsActionResult = {
28
32
  ok: true;
29
33
  sessionId: string;
30
34
  };
35
+ export type VoiceLiveOpsEvidenceInput = {
36
+ actionHistory?: VoiceOpsActionHistoryReport;
37
+ maxActionHistoryFailures?: number;
38
+ maxOpsRecoveryIssues?: number;
39
+ minActionHistoryEntries?: number;
40
+ minInterventions?: number;
41
+ minOperationsRecordHandoffs?: number;
42
+ minOperationsRecordTasks?: number;
43
+ operationsRecord?: VoiceOperationsRecord;
44
+ opsRecovery?: VoiceOpsRecoveryReport;
45
+ opsStatus?: VoiceOpsStatusReport;
46
+ requireActionHistory?: boolean;
47
+ requireOperationsRecord?: boolean;
48
+ requireOperationsRecordAudit?: boolean;
49
+ requireOperationsRecordHealthy?: boolean;
50
+ requireOpsRecovery?: boolean;
51
+ requireOpsRecoveryStatus?: VoiceOpsRecoveryStatus;
52
+ requireOpsStatus?: boolean;
53
+ requireOpsStatusPass?: boolean;
54
+ requiredHistoryActions?: string[];
55
+ requiredInterventionActions?: string[];
56
+ };
57
+ export type VoiceLiveOpsEvidenceReport = {
58
+ actionHistoryFailed?: number;
59
+ actionHistoryTotal?: number;
60
+ historyActions: string[];
61
+ interventionActions: string[];
62
+ interventions?: number;
63
+ issues: string[];
64
+ ok: boolean;
65
+ operationsRecordHandoffs?: number;
66
+ operationsRecordStatus?: VoiceOperationsRecord['status'];
67
+ operationsRecordTasks?: number;
68
+ opsRecoveryIssues?: number;
69
+ opsRecoveryStatus?: VoiceOpsRecoveryStatus;
70
+ opsStatus?: VoiceOpsStatusReport['status'];
71
+ };
31
72
  export type VoiceLiveOpsControlStore = {
32
73
  get: (sessionId: string) => Promise<VoiceLiveOpsControlState | undefined> | VoiceLiveOpsControlState | undefined;
33
74
  set: (sessionId: string, state: VoiceLiveOpsControlState) => Promise<void> | void;
@@ -50,6 +91,8 @@ export type VoiceLiveOpsRoutesOptions = VoiceLiveOpsControllerOptions & {
50
91
  name?: string;
51
92
  path?: string;
52
93
  };
94
+ export declare const evaluateVoiceLiveOpsEvidence: (input?: VoiceLiveOpsEvidenceInput) => VoiceLiveOpsEvidenceReport;
95
+ export declare const assertVoiceLiveOpsEvidence: (input?: VoiceLiveOpsEvidenceInput) => VoiceLiveOpsEvidenceReport;
53
96
  export declare const createVoiceMemoryLiveOpsControlStore: () => VoiceLiveOpsControlStore;
54
97
  export declare const getVoiceLiveOpsControlStatus: (action: VoiceLiveOpsAction) => VoiceLiveOpsControlStatus;
55
98
  export declare const buildVoiceLiveOpsControlState: (input: VoiceLiveOpsActionInput & {
@@ -1744,6 +1744,99 @@ var VOICE_LIVE_OPS_ACTIONS = [
1744
1744
  ];
1745
1745
  var isVoiceLiveOpsAction = (value) => typeof value === "string" && VOICE_LIVE_OPS_ACTIONS.includes(value);
1746
1746
  var toStringValue = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
1747
+ var uniqueSorted = (values) => Array.from(new Set(values)).sort();
1748
+ var findMissing = (values, required) => {
1749
+ if (!required?.length) {
1750
+ return [];
1751
+ }
1752
+ const valueSet = new Set(values);
1753
+ return required.filter((value) => !valueSet.has(value));
1754
+ };
1755
+ var evaluateVoiceLiveOpsEvidence = (input = {}) => {
1756
+ const issues = [];
1757
+ const actionHistory = input.actionHistory;
1758
+ const opsRecovery = input.opsRecovery;
1759
+ const opsStatus = input.opsStatus;
1760
+ const operationsRecord = input.operationsRecord;
1761
+ const historyActions = uniqueSorted(actionHistory?.entries.map((entry) => entry.actionId) ?? []);
1762
+ const interventionActions = uniqueSorted(opsRecovery?.interventions.events.map((event) => event.action).filter((action) => Boolean(action)) ?? []);
1763
+ const requireActionHistory = input.requireActionHistory ?? true;
1764
+ const requireOperationsRecord = input.requireOperationsRecord ?? true;
1765
+ const requireOpsRecovery = input.requireOpsRecovery ?? true;
1766
+ const requireOpsRecoveryStatus = input.requireOpsRecoveryStatus ?? "pass";
1767
+ const requireOpsStatus = input.requireOpsStatus ?? true;
1768
+ const requireOpsStatusPass = input.requireOpsStatusPass ?? true;
1769
+ if (requireActionHistory && !actionHistory) {
1770
+ issues.push("Expected live-ops action history report to be present.");
1771
+ }
1772
+ if (requireOpsRecovery && !opsRecovery) {
1773
+ issues.push("Expected ops recovery report to be present.");
1774
+ }
1775
+ if (requireOpsStatus && !opsStatus) {
1776
+ issues.push("Expected ops status report to be present.");
1777
+ }
1778
+ if (requireOperationsRecord && !operationsRecord) {
1779
+ issues.push("Expected operations record to be present.");
1780
+ }
1781
+ if (opsRecovery && opsRecovery.status !== requireOpsRecoveryStatus) {
1782
+ issues.push(`Expected ops recovery status ${requireOpsRecoveryStatus}, found ${opsRecovery.status}.`);
1783
+ }
1784
+ if (opsRecovery && input.maxOpsRecoveryIssues !== undefined && opsRecovery.issues.length > input.maxOpsRecoveryIssues) {
1785
+ issues.push(`Expected at most ${String(input.maxOpsRecoveryIssues)} ops recovery issue(s), found ${String(opsRecovery.issues.length)}.`);
1786
+ }
1787
+ if (opsRecovery && input.minInterventions !== undefined && opsRecovery.interventions.total < input.minInterventions) {
1788
+ issues.push(`Expected at least ${String(input.minInterventions)} live-ops intervention(s), found ${String(opsRecovery.interventions.total)}.`);
1789
+ }
1790
+ for (const action of findMissing(interventionActions, input.requiredInterventionActions)) {
1791
+ issues.push(`Missing live-ops intervention action: ${action}.`);
1792
+ }
1793
+ if (opsStatus && requireOpsStatusPass && opsStatus.status !== "pass") {
1794
+ issues.push(`Expected ops status pass, found ${opsStatus.status}.`);
1795
+ }
1796
+ if (actionHistory && input.minActionHistoryEntries !== undefined && actionHistory.total < input.minActionHistoryEntries) {
1797
+ issues.push(`Expected at least ${String(input.minActionHistoryEntries)} operator action history entrie(s), found ${String(actionHistory.total)}.`);
1798
+ }
1799
+ if (actionHistory && input.maxActionHistoryFailures !== undefined && actionHistory.failed > input.maxActionHistoryFailures) {
1800
+ issues.push(`Expected at most ${String(input.maxActionHistoryFailures)} failed operator action(s), found ${String(actionHistory.failed)}.`);
1801
+ }
1802
+ for (const action of findMissing(historyActions, input.requiredHistoryActions)) {
1803
+ issues.push(`Missing operator action history action: ${action}.`);
1804
+ }
1805
+ if (operationsRecord && input.requireOperationsRecordHealthy !== false && operationsRecord.status === "failed") {
1806
+ issues.push("Expected operations record not to be failed.");
1807
+ }
1808
+ if (operationsRecord && input.requireOperationsRecordAudit && !operationsRecord.audit) {
1809
+ issues.push("Expected operations record audit summary to be present.");
1810
+ }
1811
+ if (operationsRecord && input.minOperationsRecordHandoffs !== undefined && operationsRecord.handoffs.length < input.minOperationsRecordHandoffs) {
1812
+ issues.push(`Expected at least ${String(input.minOperationsRecordHandoffs)} operations-record handoff(s), found ${String(operationsRecord.handoffs.length)}.`);
1813
+ }
1814
+ if (operationsRecord && input.minOperationsRecordTasks !== undefined && (operationsRecord.tasks?.total ?? 0) < input.minOperationsRecordTasks) {
1815
+ issues.push(`Expected at least ${String(input.minOperationsRecordTasks)} operations-record task(s), found ${String(operationsRecord.tasks?.total ?? 0)}.`);
1816
+ }
1817
+ return {
1818
+ actionHistoryFailed: actionHistory?.failed,
1819
+ actionHistoryTotal: actionHistory?.total,
1820
+ historyActions,
1821
+ interventionActions,
1822
+ interventions: opsRecovery?.interventions.total,
1823
+ issues,
1824
+ ok: issues.length === 0,
1825
+ operationsRecordHandoffs: operationsRecord?.handoffs.length,
1826
+ operationsRecordStatus: operationsRecord?.status,
1827
+ operationsRecordTasks: operationsRecord?.tasks?.total,
1828
+ opsRecoveryIssues: opsRecovery?.issues.length,
1829
+ opsRecoveryStatus: opsRecovery?.status,
1830
+ opsStatus: opsStatus?.status
1831
+ };
1832
+ };
1833
+ var assertVoiceLiveOpsEvidence = (input = {}) => {
1834
+ const assertion = evaluateVoiceLiveOpsEvidence(input);
1835
+ if (!assertion.ok) {
1836
+ throw new Error(`Voice live-ops evidence assertion failed: ${assertion.issues.join(" ")}`);
1837
+ }
1838
+ return assertion;
1839
+ };
1747
1840
  var createVoiceMemoryLiveOpsControlStore = () => {
1748
1841
  const states = new Map;
1749
1842
  return {
@@ -4,6 +4,6 @@ export declare function useVoiceLiveOps(options?: VoiceLiveOpsClientOptions): {
4
4
  isRunning: import("vue").Ref<boolean, boolean>;
5
5
  lastResult: import("vue").ShallowRef<VoiceLiveOpsActionResult | undefined, VoiceLiveOpsActionResult | undefined>;
6
6
  run: (input: import("..").VoiceLiveOpsActionInput) => Promise<VoiceLiveOpsActionResult | undefined>;
7
- runningAction: import("vue").Ref<"assign" | "create-task" | "escalate" | "force-handoff" | "inject-instruction" | "operator-takeover" | "pause-assistant" | "resume-assistant" | "tag" | undefined, "assign" | "create-task" | "escalate" | "force-handoff" | "inject-instruction" | "operator-takeover" | "pause-assistant" | "resume-assistant" | "tag" | undefined>;
7
+ runningAction: import("vue").Ref<"escalate" | "assign" | "create-task" | "force-handoff" | "inject-instruction" | "operator-takeover" | "pause-assistant" | "resume-assistant" | "tag" | undefined, "escalate" | "assign" | "create-task" | "force-handoff" | "inject-instruction" | "operator-takeover" | "pause-assistant" | "resume-assistant" | "tag" | undefined>;
8
8
  updatedAt: import("vue").Ref<number | undefined, number | undefined>;
9
9
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.260",
3
+ "version": "0.0.22-beta.262",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",