@absolutejs/voice 0.0.22-beta.394 → 0.0.22-beta.395

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertio
33
33
  export { assertVoiceProofTrendEvidence, appendVoiceRealCallProfileRecoveryEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReportFromRealCallProfiles, buildVoiceProofTrendReport, buildVoiceRealCallProfileEvidenceFromTraceEvents, buildVoiceRealCallProfileDefaults, buildVoiceRealCallProfileHistoryReport, buildVoiceRealCallProfileReadinessCheck, buildVoiceRealCallProfileRecoveryJobHistoryCheck, buildVoiceRealCallProfileRecoveryActions, createVoiceInMemoryRealCallProfileRecoveryJobStore, createVoiceRealCallProfileTraceCollector, createVoiceSQLiteRealCallProfileRecoveryJobStore, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, createVoiceRealCallProfileHistoryRoutes, createVoiceRealCallProfileRecoveryActionRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, loadVoiceRealCallProfileEvidenceFromTraceStore, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown, renderVoiceRealCallProfileHistoryHTML, renderVoiceRealCallProfileHistoryMarkdown, runVoiceRealCallProfileRecoveryLoop, resolveVoiceRealCallProfileProviderRoute } from './proofTrends';
34
34
  export { createVoiceEvidenceAssertion, createVoiceProofAssertion, summarizeVoiceProofAssertions } from './proofAssertions';
35
35
  export type { VoiceEvidenceAssertionInput, VoiceProofAssertionInput, VoiceProofAssertionResult, VoiceProofAssertionSummary } from './proofAssertions';
36
+ export { fetchVoiceProofTarget, getVoiceProofTargetLogicalFailure, mapVoiceProofTargetsWithConcurrency, runVoiceProofTargets } from './proofRunner';
37
+ export type { VoiceProofTarget, VoiceProofTargetMethod, VoiceProofTargetResult, VoiceProofTargetRunnerOptions, VoiceProofTargetRunOptions } from './proofRunner';
36
38
  export { applyVoiceProfileSwitchGuard, buildVoiceProfileSwitchReadinessReport, buildVoiceProfileSwitchLiveDecisionReport, createVoiceProfileSwitchLiveDecisionRoutes, createVoiceProfileSwitchPolicyProofRoutes, createVoiceProfileSwitchReadinessRoutes, recommendVoiceProfileSwitch, renderVoiceProfileSwitchLiveDecisionHTML, renderVoiceProfileSwitchPolicyProofHTML, renderVoiceProfileSwitchReadinessHTML, runVoiceProfileSwitchPolicyProof } from './profileSwitchRecommendation';
37
39
  export type { VoiceProfileSwitchGuardAction, VoiceProfileSwitchGuardDecision, VoiceProfileSwitchGuardMode, VoiceProfileSwitchGuardOptions, VoiceProfileSwitchObservedSignals, VoiceProfileSwitchLiveDecisionEvidence, VoiceProfileSwitchLiveDecisionReport, VoiceProfileSwitchLiveDecisionReportOptions, VoiceProfileSwitchLiveDecisionRoutesOptions, VoiceProfileSwitchLiveDecisionSession, VoiceProfileSwitchPolicyProofCase, VoiceProfileSwitchPolicyProofCaseResult, VoiceProfileSwitchPolicyProofOptions, VoiceProfileSwitchPolicyProofReport, VoiceProfileSwitchPolicyProofRoutesOptions, VoiceProfileSwitchReadinessIssue, VoiceProfileSwitchReadinessOptions, VoiceProfileSwitchReadinessReport, VoiceProfileSwitchReadinessRoutesOptions, VoiceProfileSwitchReadinessStatus, VoiceProfileSwitchRecommendation, VoiceProfileSwitchRecommendationOptions } from './profileSwitchRecommendation';
38
40
  export { buildVoiceProviderDecisionTraceReport, createVoiceProviderDecisionTraceEvent, createVoiceProviderDecisionTraceRoutes, listVoiceProviderDecisionTraces, renderVoiceProviderDecisionTraceHTML, renderVoiceProviderDecisionTraceMarkdown } from './providerDecisionTraces';
package/dist/index.js CHANGED
@@ -18385,6 +18385,170 @@ var summarizeVoiceProofAssertions = (assertions) => {
18385
18385
  total: assertions.length
18386
18386
  };
18387
18387
  };
18388
+ // src/proofRunner.ts
18389
+ var encoder = new TextEncoder;
18390
+ var trimBaseUrl = (baseUrl) => baseUrl.replace(/\/$/, "");
18391
+ var safeArtifactName = (name) => name.replace(/[^a-z0-9_.-]/gi, "-");
18392
+ var summarizeValue = (value) => {
18393
+ if (Array.isArray(value)) {
18394
+ return { count: value.length };
18395
+ }
18396
+ if (!value || typeof value !== "object") {
18397
+ return value;
18398
+ }
18399
+ const record = value;
18400
+ const preferredKeys = [
18401
+ "status",
18402
+ "ok",
18403
+ "pass",
18404
+ "ready",
18405
+ "proof",
18406
+ "total",
18407
+ "passed",
18408
+ "failed",
18409
+ "issues",
18410
+ "summary",
18411
+ "links",
18412
+ "actions",
18413
+ "checks",
18414
+ "campaigns",
18415
+ "recipients",
18416
+ "attempts",
18417
+ "telephonyMedia",
18418
+ "operationsRecordHref",
18419
+ "sentEvents",
18420
+ "tasks",
18421
+ "reviews",
18422
+ "events",
18423
+ "eventsWithLatency",
18424
+ "observabilityExportReplay",
18425
+ "validationIssues",
18426
+ "deliveryDestinations",
18427
+ "failedDeliveryDestinations",
18428
+ "failedArtifacts",
18429
+ "artifacts",
18430
+ "kinds",
18431
+ "redaction",
18432
+ "retentionPlan",
18433
+ "zeroRetentionAvailable"
18434
+ ];
18435
+ const summary = {};
18436
+ for (const key of preferredKeys) {
18437
+ if (key in record) {
18438
+ summary[key] = summarizeValue(record[key]);
18439
+ }
18440
+ }
18441
+ return Object.keys(summary).length > 0 ? summary : {
18442
+ keys: Object.keys(record).slice(0, 12)
18443
+ };
18444
+ };
18445
+ var getVoiceProofTargetLogicalFailure = (value) => {
18446
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
18447
+ return;
18448
+ }
18449
+ const record = value;
18450
+ if (record.status === "fail") {
18451
+ return 'Response status is "fail".';
18452
+ }
18453
+ if (record.pass === false) {
18454
+ return "Response pass is false.";
18455
+ }
18456
+ if (record.ok === false) {
18457
+ return "Response ok is false.";
18458
+ }
18459
+ return;
18460
+ };
18461
+ var mapVoiceProofTargetsWithConcurrency = async (items, limit, mapper) => {
18462
+ const results = new Array(items.length);
18463
+ let nextIndex = 0;
18464
+ const workerCount = Math.min(Math.max(1, limit), items.length);
18465
+ const workers = Array.from({ length: workerCount }, async () => {
18466
+ while (nextIndex < items.length) {
18467
+ const index = nextIndex;
18468
+ nextIndex += 1;
18469
+ const item = items[index];
18470
+ if (item !== undefined) {
18471
+ results[index] = await mapper(item);
18472
+ }
18473
+ }
18474
+ });
18475
+ await Promise.all(workers);
18476
+ return results;
18477
+ };
18478
+ var fetchVoiceProofTarget = async (target, options) => {
18479
+ const method = target.method ?? "GET";
18480
+ const baseUrl = trimBaseUrl(options.baseUrl);
18481
+ const url = `${baseUrl}${target.path}`;
18482
+ const fetcher = options.fetch ?? globalThis.fetch;
18483
+ const now = options.now ?? performance.now.bind(performance);
18484
+ const startedAt = now();
18485
+ const controller = new AbortController;
18486
+ const timeout = options.timeoutMs && options.timeoutMs > 0 ? setTimeout(() => controller.abort(), options.timeoutMs) : undefined;
18487
+ try {
18488
+ const response = await fetcher(url, {
18489
+ body: target.body === undefined ? undefined : JSON.stringify(target.body),
18490
+ headers: {
18491
+ accept: target.accept ?? (target.kind === "json" ? "application/json" : "text/markdown,text/plain,*/*"),
18492
+ ...target.body === undefined ? {} : { "content-type": "application/json" }
18493
+ },
18494
+ method,
18495
+ signal: controller.signal
18496
+ });
18497
+ const text = await response.text();
18498
+ const bytes = encoder.encode(text).byteLength;
18499
+ let body = text;
18500
+ let parseError;
18501
+ if (target.kind === "json" && text.trim()) {
18502
+ try {
18503
+ body = JSON.parse(text);
18504
+ } catch (error) {
18505
+ parseError = error instanceof Error ? error.message : String(error);
18506
+ }
18507
+ }
18508
+ const missingText = target.kind === "text" ? (target.requiredText ?? []).filter((item) => !text.includes(item)) : [];
18509
+ const logicalFailure = target.kind === "json" && !parseError && !target.allowLogicalFail ? getVoiceProofTargetLogicalFailure(body) : undefined;
18510
+ await options.writeArtifact?.({
18511
+ content: target.kind === "json" ? `${JSON.stringify(parseError ? { parseError, text } : body, null, 2)}
18512
+ ` : text,
18513
+ name: `${safeArtifactName(target.name)}.${target.kind === "json" ? "json" : "md"}`,
18514
+ target
18515
+ });
18516
+ return {
18517
+ body,
18518
+ bytes,
18519
+ elapsedMs: Math.round(now() - startedAt),
18520
+ error: parseError ?? logicalFailure ?? (missingText.length > 0 ? `Missing required text: ${missingText.join(", ")}` : undefined),
18521
+ kind: target.kind,
18522
+ method,
18523
+ name: target.name,
18524
+ ok: response.ok && !parseError && !logicalFailure && missingText.length === 0,
18525
+ path: target.path,
18526
+ status: response.status,
18527
+ summary: parseError ? { bytes, parseError } : target.kind === "json" ? summarizeValue(body) : {
18528
+ bytes,
18529
+ requiredTextFound: missingText.length === 0
18530
+ },
18531
+ url
18532
+ };
18533
+ } catch (error) {
18534
+ return {
18535
+ bytes: 0,
18536
+ elapsedMs: Math.round(now() - startedAt),
18537
+ error: error instanceof Error ? error.message : String(error),
18538
+ kind: target.kind,
18539
+ method,
18540
+ name: target.name,
18541
+ ok: false,
18542
+ path: target.path,
18543
+ url
18544
+ };
18545
+ } finally {
18546
+ if (timeout) {
18547
+ clearTimeout(timeout);
18548
+ }
18549
+ }
18550
+ };
18551
+ var runVoiceProofTargets = (targets, options) => mapVoiceProofTargetsWithConcurrency(targets, options.concurrency ?? 2, (target) => fetchVoiceProofTarget(target, options));
18388
18552
  // src/providerRouterTraces.ts
18389
18553
  var buildVoiceProviderRouterTraceEvent = (options) => ({
18390
18554
  at: options.at ?? options.event.at,
@@ -23690,9 +23854,9 @@ var flattenPayload = (value) => {
23690
23854
  };
23691
23855
  var toBase64 = (bytes) => Buffer.from(new Uint8Array(bytes)).toString("base64");
23692
23856
  var timingSafeEqual = (left, right) => {
23693
- const encoder = new TextEncoder;
23694
- const leftBytes = encoder.encode(left);
23695
- const rightBytes = encoder.encode(right);
23857
+ const encoder2 = new TextEncoder;
23858
+ const leftBytes = encoder2.encode(left);
23859
+ const rightBytes = encoder2.encode(right);
23696
23860
  if (leftBytes.length !== rightBytes.length) {
23697
23861
  return false;
23698
23862
  }
@@ -23703,12 +23867,12 @@ var timingSafeEqual = (left, right) => {
23703
23867
  return diff === 0;
23704
23868
  };
23705
23869
  var signHmacSHA1Base64 = async (secret, payload) => {
23706
- const encoder = new TextEncoder;
23707
- const key = await crypto.subtle.importKey("raw", encoder.encode(secret), {
23870
+ const encoder2 = new TextEncoder;
23871
+ const key = await crypto.subtle.importKey("raw", encoder2.encode(secret), {
23708
23872
  hash: "SHA-1",
23709
23873
  name: "HMAC"
23710
23874
  }, false, ["sign"]);
23711
- const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(payload));
23875
+ const signature = await crypto.subtle.sign("HMAC", key, encoder2.encode(payload));
23712
23876
  return toBase64(signature);
23713
23877
  };
23714
23878
  var sortedParamsForSignature = (body) => Object.entries(flattenPayload(body)).filter(([, value]) => value !== undefined && value !== null).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}${String(value)}`).join("");
@@ -25308,9 +25472,9 @@ var createPlivoMediaStreamBridge = (socket, options) => {
25308
25472
  };
25309
25473
  var toBase642 = (bytes) => Buffer5.from(new Uint8Array(bytes)).toString("base64");
25310
25474
  var timingSafeEqual2 = (left, right) => {
25311
- const encoder = new TextEncoder;
25312
- const leftBytes = encoder.encode(left);
25313
- const rightBytes = encoder.encode(right);
25475
+ const encoder2 = new TextEncoder;
25476
+ const leftBytes = encoder2.encode(left);
25477
+ const rightBytes = encoder2.encode(right);
25314
25478
  if (leftBytes.length !== rightBytes.length) {
25315
25479
  return false;
25316
25480
  }
@@ -25321,12 +25485,12 @@ var timingSafeEqual2 = (left, right) => {
25321
25485
  return diff === 0;
25322
25486
  };
25323
25487
  var signHmacSHA256Base64 = async (secret, payload) => {
25324
- const encoder = new TextEncoder;
25325
- const key = await crypto.subtle.importKey("raw", encoder.encode(secret), {
25488
+ const encoder2 = new TextEncoder;
25489
+ const key = await crypto.subtle.importKey("raw", encoder2.encode(secret), {
25326
25490
  hash: "SHA-256",
25327
25491
  name: "HMAC"
25328
25492
  }, false, ["sign"]);
25329
- const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(payload));
25493
+ const signature = await crypto.subtle.sign("HMAC", key, encoder2.encode(payload));
25330
25494
  return toBase642(signature);
25331
25495
  };
25332
25496
  var sortedParamsForSignature2 = (body) => {
@@ -37449,18 +37613,18 @@ var createVoiceMemoryStore = () => {
37449
37613
  import { Elysia as Elysia61 } from "elysia";
37450
37614
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
37451
37615
  var signVoiceOpsWebhookBody = async (input) => {
37452
- const encoder = new TextEncoder;
37453
- const key = await crypto.subtle.importKey("raw", encoder.encode(input.secret), {
37616
+ const encoder2 = new TextEncoder;
37617
+ const key = await crypto.subtle.importKey("raw", encoder2.encode(input.secret), {
37454
37618
  hash: "SHA-256",
37455
37619
  name: "HMAC"
37456
37620
  }, false, ["sign"]);
37457
- const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(`${input.timestamp}.${input.body}`));
37621
+ const signature = await crypto.subtle.sign("HMAC", key, encoder2.encode(`${input.timestamp}.${input.body}`));
37458
37622
  return `sha256=${toHex6(new Uint8Array(signature))}`;
37459
37623
  };
37460
37624
  var timingSafeEqual3 = (left, right) => {
37461
- const encoder = new TextEncoder;
37462
- const leftBytes = encoder.encode(left);
37463
- const rightBytes = encoder.encode(right);
37625
+ const encoder2 = new TextEncoder;
37626
+ const leftBytes = encoder2.encode(left);
37627
+ const rightBytes = encoder2.encode(right);
37464
37628
  if (leftBytes.length !== rightBytes.length) {
37465
37629
  return false;
37466
37630
  }
@@ -39384,6 +39548,7 @@ export {
39384
39548
  runVoiceReconnectContract,
39385
39549
  runVoiceRealCallProfileRecoveryLoop,
39386
39550
  runVoiceProviderRoutingContract,
39551
+ runVoiceProofTargets,
39387
39552
  runVoiceProfileSwitchPolicyProof,
39388
39553
  runVoicePhoneAgentProductionSmokeContract,
39389
39554
  runVoiceOutcomeContractSuite,
@@ -39522,6 +39687,7 @@ export {
39522
39687
  muteVoiceMonitorIssue,
39523
39688
  matchesVoiceOpsTaskAssignmentRule,
39524
39689
  markVoiceOpsTaskSLABreached,
39690
+ mapVoiceProofTargetsWithConcurrency,
39525
39691
  loadVoiceRealCallProfileEvidenceFromTraceStore,
39526
39692
  loadVoiceObservabilityExportReplaySource,
39527
39693
  listVoiceRoutingEvents,
@@ -39531,6 +39697,7 @@ export {
39531
39697
  importVoiceCampaignRecipients,
39532
39698
  heartbeatVoiceOpsTask,
39533
39699
  hasVoiceOpsTaskSLABreach,
39700
+ getVoiceProofTargetLogicalFailure,
39534
39701
  getVoiceLiveOpsControlStatus,
39535
39702
  getVoiceCampaignDialerProofStatus,
39536
39703
  getLatestVoiceTelephonyMediaReport,
@@ -39539,6 +39706,7 @@ export {
39539
39706
  formatVoiceProofTrendAge,
39540
39707
  filterVoiceTraceEvents,
39541
39708
  filterVoiceAuditEvents,
39709
+ fetchVoiceProofTarget,
39542
39710
  failVoiceOpsTask,
39543
39711
  exportVoiceTrace,
39544
39712
  exportVoiceAuditTrail,
@@ -0,0 +1,43 @@
1
+ export type VoiceProofTargetMethod = 'GET' | 'POST';
2
+ export type VoiceProofTarget = {
3
+ accept?: string;
4
+ allowLogicalFail?: boolean;
5
+ body?: unknown;
6
+ kind: 'json' | 'text';
7
+ method?: VoiceProofTargetMethod;
8
+ name: string;
9
+ path: string;
10
+ requiredText?: string[];
11
+ };
12
+ export type VoiceProofTargetResult = {
13
+ body?: unknown;
14
+ bytes: number;
15
+ elapsedMs: number;
16
+ error?: string;
17
+ kind: VoiceProofTarget['kind'];
18
+ method: VoiceProofTargetMethod;
19
+ name: string;
20
+ ok: boolean;
21
+ path: string;
22
+ status?: number;
23
+ summary?: Record<string, unknown>;
24
+ url: string;
25
+ };
26
+ export type VoiceProofTargetRunnerOptions = {
27
+ baseUrl: string;
28
+ fetch?: typeof fetch;
29
+ now?: () => number;
30
+ timeoutMs?: number;
31
+ writeArtifact?: (input: {
32
+ content: string;
33
+ name: string;
34
+ target: VoiceProofTarget;
35
+ }) => Promise<void> | void;
36
+ };
37
+ export type VoiceProofTargetRunOptions = VoiceProofTargetRunnerOptions & {
38
+ concurrency?: number;
39
+ };
40
+ export declare const getVoiceProofTargetLogicalFailure: (value: unknown) => "Response status is \"fail\"." | "Response pass is false." | "Response ok is false." | undefined;
41
+ export declare const mapVoiceProofTargetsWithConcurrency: <TInput, TOutput>(items: TInput[], limit: number, mapper: (item: TInput) => Promise<TOutput>) => Promise<TOutput[]>;
42
+ export declare const fetchVoiceProofTarget: (target: VoiceProofTarget, options: VoiceProofTargetRunnerOptions) => Promise<VoiceProofTargetResult>;
43
+ export declare const runVoiceProofTargets: (targets: VoiceProofTarget[], options: VoiceProofTargetRunOptions) => Promise<VoiceProofTargetResult[]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.394",
3
+ "version": "0.0.22-beta.395",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",