@absolutejs/voice 0.0.22-beta.242 → 0.0.22-beta.244

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.
@@ -0,0 +1,19 @@
1
+ import type { VoiceProofTrendReport } from '../proofTrends';
2
+ export type VoiceProofTrendsClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceProofTrendsSnapshot = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ report?: VoiceProofTrendReport;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceProofTrends: (path?: string, options?: Pick<VoiceProofTrendsClientOptions, "fetch">) => Promise<VoiceProofTrendReport>;
13
+ export declare const createVoiceProofTrendsStore: (path?: string, options?: VoiceProofTrendsClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceProofTrendsSnapshot;
16
+ getSnapshot: () => VoiceProofTrendsSnapshot;
17
+ refresh: () => Promise<VoiceProofTrendReport | undefined>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,37 @@
1
+ import { type VoiceProofTrendReport } from '../proofTrends';
2
+ import { type VoiceProofTrendsClientOptions, type VoiceProofTrendsSnapshot } from './proofTrends';
3
+ export type VoiceProofTrendsMetricView = {
4
+ label: string;
5
+ value: string;
6
+ };
7
+ export type VoiceProofTrendsViewModel = {
8
+ description: string;
9
+ error: string | null;
10
+ isLoading: boolean;
11
+ label: string;
12
+ links: Array<{
13
+ href: string;
14
+ label: string;
15
+ }>;
16
+ metrics: VoiceProofTrendsMetricView[];
17
+ report?: VoiceProofTrendReport;
18
+ status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
19
+ title: string;
20
+ updatedAt?: number;
21
+ };
22
+ export type VoiceProofTrendsWidgetOptions = VoiceProofTrendsClientOptions & {
23
+ description?: string;
24
+ links?: Array<{
25
+ href: string;
26
+ label: string;
27
+ }>;
28
+ title?: string;
29
+ };
30
+ export declare const createVoiceProofTrendsViewModel: (snapshot: VoiceProofTrendsSnapshot, options?: VoiceProofTrendsWidgetOptions) => VoiceProofTrendsViewModel;
31
+ export declare const renderVoiceProofTrendsHTML: (snapshot: VoiceProofTrendsSnapshot, options?: VoiceProofTrendsWidgetOptions) => string;
32
+ export declare const getVoiceProofTrendsCSS: () => string;
33
+ export declare const mountVoiceProofTrends: (element: Element, path?: string, options?: VoiceProofTrendsWidgetOptions) => {
34
+ close: () => void;
35
+ refresh: () => Promise<VoiceProofTrendReport | undefined>;
36
+ };
37
+ export declare const defineVoiceProofTrendsElement: (tagName?: string) => void;
package/dist/index.d.ts CHANGED
@@ -83,6 +83,7 @@ export { createVoiceCallReviewFromSession, recordVoiceRuntimeOps } from './runti
83
83
  export { createVoiceOpsRuntime } from './opsRuntime';
84
84
  export { resolveVoiceOpsPreset } from './opsPresets';
85
85
  export { resolveVoiceOutcomeRecipe } from './outcomeRecipes';
86
+ export { buildVoicePostCallAnalysisReport, createVoicePostCallAnalysisRoutes, renderVoicePostCallAnalysisMarkdown } from './postCallAnalysis';
86
87
  export { createId, createVoiceSessionRecord } from './store';
87
88
  export { createVoiceSTTRoutingCorrectionHandler, resolveVoiceSTTRoutingStrategy } from './routing';
88
89
  export { applyRiskTieredPhraseHintCorrections, applyPhraseHintCorrections, createDomainLexicon, createDomainPhraseHints, createPhraseHintCorrectionHandler, createRiskyTurnCorrectionHandler } from './correction';
@@ -135,6 +136,7 @@ export type { VoiceToolContractCase, VoiceToolContractCaseReport, VoiceToolContr
135
136
  export type { VoiceOpsRuntime, VoiceOpsRuntimeConfig, VoiceOpsRuntimeSummary, VoiceOpsRuntimeSinkWorkerConfig, VoiceOpsRuntimeTaskWorkerConfig, VoiceOpsRuntimeTickResult, VoiceOpsRuntimeWebhookWorkerConfig } from './opsRuntime';
136
137
  export type { VoiceOpsPresetName, VoiceOpsPresetOverrides, VoiceResolvedOpsPreset } from './opsPresets';
137
138
  export type { VoiceOutcomeRecipe, VoiceOutcomeRecipeName, VoiceOutcomeRecipeOptions } from './outcomeRecipes';
139
+ export type { VoicePostCallAnalysisFieldRequirement, VoicePostCallAnalysisFieldResult, VoicePostCallAnalysisIssue, VoicePostCallAnalysisIssueCode, VoicePostCallAnalysisOptions, VoicePostCallAnalysisReport, VoicePostCallAnalysisRoutesOptions, VoicePostCallAnalysisStatus } from './postCallAnalysis';
138
140
  export type { VoiceCRMActivitySinkOptions, VoiceHubSpotTaskSinkOptions, VoiceHubSpotTaskUpdateSinkOptions, VoiceHelpdeskTicketSinkOptions, VoiceIntegrationHTTPSinkOptions, VoiceIntegrationSink, VoiceIntegrationSinkDeliveryResult, VoiceLinearIssueSinkOptions, VoiceLinearIssueUpdateSinkOptions, VoiceZendeskTicketSinkOptions, VoiceZendeskTicketUpdateSinkOptions } from './opsSinks';
139
141
  export type { VoiceOpsWebhookEnvelope, VoiceOpsWebhookEntity, VoiceOpsWebhookLinkResolver, VoiceOpsWebhookReceiverRoutesOptions, VoiceOpsWebhookSinkOptions, VoiceOpsWebhookVerificationResult } from './opsWebhook';
140
142
  export type { VoiceHandoffDelivery, VoiceHandoffDeliveryRecord, VoiceHandoffDeliveryRecordInput, VoiceHandoffFanoutResult, VoiceQueuedHandoffDeliveryOptions, VoiceTwilioRedirectHandoffAdapterOptions, VoiceWebhookHandoffAdapterOptions } from './handoff';
package/dist/index.js CHANGED
@@ -28727,6 +28727,210 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
28727
28727
  taskPolicies: mergePolicies(preset.taskPolicies, overrides.taskPolicies)
28728
28728
  };
28729
28729
  };
28730
+ // src/postCallAnalysis.ts
28731
+ import { Elysia as Elysia49 } from "elysia";
28732
+ var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
28733
+ var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
28734
+ var getPathValue3 = (source, path) => {
28735
+ const parts = path.split(".").filter(Boolean);
28736
+ let current = source;
28737
+ for (const part of parts) {
28738
+ if (!current || typeof current !== "object" || Array.isArray(current)) {
28739
+ return;
28740
+ }
28741
+ current = current[part];
28742
+ }
28743
+ return current;
28744
+ };
28745
+ var hasValue2 = (value) => {
28746
+ if (value === undefined || value === null) {
28747
+ return false;
28748
+ }
28749
+ if (typeof value === "string") {
28750
+ return value.trim().length > 0;
28751
+ }
28752
+ if (Array.isArray(value)) {
28753
+ return value.length > 0;
28754
+ }
28755
+ return true;
28756
+ };
28757
+ var matchesReview = (reviewId, id) => Boolean(reviewId && id && (id === reviewId || id.startsWith(`${reviewId}:`)));
28758
+ var matchesSession = (sessionId, event) => {
28759
+ const payloadSessionId = event.payload.sessionId;
28760
+ return Boolean(sessionId && (event.id === sessionId || event.id.startsWith(`${sessionId}:`) || payloadSessionId === sessionId));
28761
+ };
28762
+ var matchesIntegrationEvent = (input) => {
28763
+ const payloadReviewId = input.event.payload.reviewId;
28764
+ return matchesReview(input.reviewId, input.event.id) || payloadReviewId === input.reviewId || matchesSession(input.sessionId, input.event);
28765
+ };
28766
+ var normalizeOperationRecordHref = (basePath, sessionId) => {
28767
+ if (!basePath || !sessionId) {
28768
+ return;
28769
+ }
28770
+ return basePath.includes(":sessionId") ? basePath.replace(":sessionId", encodeURIComponent(sessionId)) : `${basePath.replace(/\/$/, "")}/${encodeURIComponent(sessionId)}`;
28771
+ };
28772
+ var isPostCallAnalysisReport = (value) => ("status" in value) && ("summary" in value) && Array.isArray(value.issues);
28773
+ var buildVoicePostCallAnalysisReport = async (options = {}) => {
28774
+ const reviews = await asArray(options.reviews);
28775
+ const review = options.review ?? reviews.find((candidate) => options.reviewId ? candidate.id === options.reviewId : options.sessionId ? candidate.id.startsWith(`${options.sessionId}:`) : false);
28776
+ const reviewId = options.reviewId ?? review?.id;
28777
+ const sessionId = options.sessionId ?? (reviewId?.endsWith(":review") ? reviewId.slice(0, -":review".length) : undefined);
28778
+ const allTasks = await asArray(options.tasks);
28779
+ const tasks = allTasks.filter((task) => reviewId ? task.reviewId === reviewId || task.intakeId === reviewId || matchesReview(reviewId, task.id) : false);
28780
+ const allIntegrationEvents = await asArray(options.integrationEvents);
28781
+ const integrationEvents = allIntegrationEvents.filter((event) => matchesIntegrationEvent({ event, reviewId, sessionId }));
28782
+ const fieldSource = {
28783
+ extractedFields: options.extractedFields ?? {},
28784
+ review
28785
+ };
28786
+ const fields = (options.fields ?? []).map((field) => {
28787
+ const value = getPathValue3(fieldSource.extractedFields, field.path) ?? getPathValue3(fieldSource, field.path);
28788
+ const required = field.required !== false;
28789
+ return {
28790
+ label: field.label ?? field.path,
28791
+ ok: !required || hasValue2(value),
28792
+ path: field.path,
28793
+ required,
28794
+ value
28795
+ };
28796
+ });
28797
+ const requiredTaskKinds = options.requiredTaskKinds ?? [];
28798
+ const missingTaskKinds = requiredTaskKinds.filter((kind) => !tasks.some((task) => task.kind === kind));
28799
+ const deliveredIntegrationEvents = integrationEvents.filter((event) => event.deliveryStatus === "delivered").length;
28800
+ const failedIntegrationEvents = integrationEvents.filter((event) => event.deliveryStatus === "failed").length;
28801
+ const issues = [];
28802
+ if (!review) {
28803
+ issues.push({
28804
+ code: "voice.post_call_analysis.review_missing",
28805
+ label: "Review missing",
28806
+ severity: "fail"
28807
+ });
28808
+ } else if (review.summary.pass === false) {
28809
+ issues.push({
28810
+ code: "voice.post_call_analysis.review_failed",
28811
+ detail: review.errors.join("; ") || review.summary.outcome,
28812
+ label: "Review failed",
28813
+ severity: "fail"
28814
+ });
28815
+ }
28816
+ for (const field of fields) {
28817
+ if (field.required && !field.ok) {
28818
+ issues.push({
28819
+ code: "voice.post_call_analysis.required_field_missing",
28820
+ detail: field.path,
28821
+ label: `Missing ${field.label}`,
28822
+ severity: "fail"
28823
+ });
28824
+ }
28825
+ }
28826
+ for (const kind of missingTaskKinds) {
28827
+ issues.push({
28828
+ code: "voice.post_call_analysis.required_task_missing",
28829
+ detail: kind,
28830
+ label: `Missing ${kind} task`,
28831
+ severity: "fail"
28832
+ });
28833
+ }
28834
+ if (options.requireDeliveredIntegrationEvent && deliveredIntegrationEvents === 0) {
28835
+ issues.push({
28836
+ code: "voice.post_call_analysis.integration_missing",
28837
+ label: "Delivered integration event missing",
28838
+ severity: "fail"
28839
+ });
28840
+ }
28841
+ if (failedIntegrationEvents > 0) {
28842
+ issues.push({
28843
+ code: "voice.post_call_analysis.integration_failed",
28844
+ detail: `${failedIntegrationEvents} failed integration event(s)`,
28845
+ label: "Integration delivery failed",
28846
+ severity: "warn"
28847
+ });
28848
+ }
28849
+ const status = issues.some((issue) => issue.severity === "fail") ? "fail" : issues.length > 0 ? "warn" : "pass";
28850
+ return {
28851
+ checkedAt: options.at ?? Date.now(),
28852
+ fields,
28853
+ integrationEvents,
28854
+ issues,
28855
+ operationRecordHref: normalizeOperationRecordHref(options.operationRecordBasePath, sessionId),
28856
+ review,
28857
+ reviewId,
28858
+ sessionId,
28859
+ status,
28860
+ summary: {
28861
+ deliveredIntegrationEvents,
28862
+ failedIntegrationEvents,
28863
+ fields: fields.length,
28864
+ missingRequiredFields: fields.filter((field) => field.required && !field.ok).length,
28865
+ missingRequiredTasks: missingTaskKinds.length,
28866
+ requiredFields: fields.filter((field) => field.required).length,
28867
+ requiredTaskKinds: requiredTaskKinds.length,
28868
+ tasks: tasks.length
28869
+ },
28870
+ tasks
28871
+ };
28872
+ };
28873
+ var renderVoicePostCallAnalysisMarkdown = (report) => {
28874
+ const lines = [
28875
+ "# Voice Post-Call Analysis",
28876
+ "",
28877
+ `Status: ${report.status}`,
28878
+ `Checked: ${new Date(report.checkedAt).toISOString()}`,
28879
+ report.reviewId ? `Review: ${report.reviewId}` : undefined,
28880
+ report.sessionId ? `Session: ${report.sessionId}` : undefined,
28881
+ report.operationRecordHref ? `Operations record: ${report.operationRecordHref}` : undefined,
28882
+ "",
28883
+ "## Summary",
28884
+ `- Fields: ${report.summary.fields}`,
28885
+ `- Missing required fields: ${report.summary.missingRequiredFields}`,
28886
+ `- Tasks: ${report.summary.tasks}`,
28887
+ `- Missing required tasks: ${report.summary.missingRequiredTasks}`,
28888
+ `- Delivered integration events: ${report.summary.deliveredIntegrationEvents}`,
28889
+ `- Failed integration events: ${report.summary.failedIntegrationEvents}`,
28890
+ "",
28891
+ "## Issues",
28892
+ ...report.issues.length ? report.issues.map((issue) => `- ${issue.severity}: ${issue.code} - ${issue.label}${issue.detail ? ` (${issue.detail})` : ""}`) : ["- none"]
28893
+ ].filter((line) => line !== undefined);
28894
+ return `${lines.join(`
28895
+ `)}
28896
+ `;
28897
+ };
28898
+ var resolvePostCallAnalysisReport = async (options, input) => {
28899
+ const source = options.source === undefined ? options : typeof options.source === "function" ? await options.source(input) : options.source;
28900
+ const merged = {
28901
+ ...options,
28902
+ ...source,
28903
+ reviewId: input.reviewId ?? source.reviewId ?? options.reviewId,
28904
+ sessionId: input.sessionId ?? source.sessionId ?? options.sessionId
28905
+ };
28906
+ return isPostCallAnalysisReport(merged) ? merged : buildVoicePostCallAnalysisReport(merged);
28907
+ };
28908
+ var createVoicePostCallAnalysisRoutes = (options = {}) => {
28909
+ const path = options.path ?? "/api/voice/post-call-analysis";
28910
+ const routes = new Elysia49({
28911
+ name: options.name ?? "absolutejs-voice-post-call-analysis"
28912
+ });
28913
+ routes.get(path, async ({ query }) => {
28914
+ const report = await resolvePostCallAnalysisReport(options, {
28915
+ reviewId: typeof query.reviewId === "string" ? query.reviewId : undefined,
28916
+ sessionId: typeof query.sessionId === "string" ? query.sessionId : undefined
28917
+ });
28918
+ return Response.json(report, { headers: options.headers });
28919
+ });
28920
+ routes.get(`${path}.md`, async ({ query }) => {
28921
+ const report = await resolvePostCallAnalysisReport(options, {
28922
+ reviewId: typeof query.reviewId === "string" ? query.reviewId : undefined,
28923
+ sessionId: typeof query.sessionId === "string" ? query.sessionId : undefined
28924
+ });
28925
+ return new Response(renderVoicePostCallAnalysisMarkdown(report), {
28926
+ headers: {
28927
+ "content-type": "text/markdown; charset=utf-8",
28928
+ ...options.headers
28929
+ }
28930
+ });
28931
+ });
28932
+ return routes;
28933
+ };
28730
28934
  // src/correction.ts
28731
28935
  var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
28732
28936
  var buildAliasMatcher = (alias) => new RegExp(`(?<![\\p{L}\\p{N}'])${escapeRegExp(alias)}(?![\\p{L}\\p{N}'])`, "giu");
@@ -29219,6 +29423,7 @@ export {
29219
29423
  renderVoiceProviderContractMatrixHTML,
29220
29424
  renderVoiceProviderCapabilityHTML,
29221
29425
  renderVoiceProductionReadinessHTML,
29426
+ renderVoicePostCallAnalysisMarkdown,
29222
29427
  renderVoicePhoneAgentProductionSmokeHTML,
29223
29428
  renderVoiceOutcomeContractHTML,
29224
29429
  renderVoiceOpsStatusHTML,
@@ -29414,6 +29619,7 @@ export {
29414
29619
  createVoicePostgresCampaignStore,
29415
29620
  createVoicePostgresAuditSinkDeliveryStore,
29416
29621
  createVoicePostgresAuditEventStore,
29622
+ createVoicePostCallAnalysisRoutes,
29417
29623
  createVoicePlivoCampaignDialer,
29418
29624
  createVoicePlatformCoverageRoutes,
29419
29625
  createVoicePhoneAgentProductionSmokeRoutes,
@@ -29570,6 +29776,7 @@ export {
29570
29776
  buildVoiceProofTrendReport,
29571
29777
  buildVoiceProductionReadinessReport,
29572
29778
  buildVoiceProductionReadinessGate,
29779
+ buildVoicePostCallAnalysisReport,
29573
29780
  buildVoicePlatformCoverageSummary,
29574
29781
  buildVoiceOpsTaskFromSLABreach,
29575
29782
  buildVoiceOpsTaskFromReview,
@@ -0,0 +1,98 @@
1
+ import { Elysia } from 'elysia';
2
+ import type { StoredVoiceIntegrationEvent, StoredVoiceOpsTask, VoiceIntegrationEventStore, VoiceOpsTaskKind, VoiceOpsTaskStore } from './ops';
3
+ import type { StoredVoiceCallReviewArtifact, VoiceCallReviewStore } from './testing/review';
4
+ export type VoicePostCallAnalysisStatus = 'fail' | 'pass' | 'warn';
5
+ export type VoicePostCallAnalysisFieldRequirement = {
6
+ label?: string;
7
+ path: string;
8
+ required?: boolean;
9
+ };
10
+ export type VoicePostCallAnalysisFieldResult = {
11
+ label: string;
12
+ ok: boolean;
13
+ path: string;
14
+ required: boolean;
15
+ value?: unknown;
16
+ };
17
+ export type VoicePostCallAnalysisIssueCode = 'voice.post_call_analysis.integration_failed' | 'voice.post_call_analysis.integration_missing' | 'voice.post_call_analysis.required_field_missing' | 'voice.post_call_analysis.required_task_missing' | 'voice.post_call_analysis.review_failed' | 'voice.post_call_analysis.review_missing';
18
+ export type VoicePostCallAnalysisIssue = {
19
+ code: VoicePostCallAnalysisIssueCode;
20
+ detail?: string;
21
+ label: string;
22
+ severity: Exclude<VoicePostCallAnalysisStatus, 'pass'>;
23
+ };
24
+ export type VoicePostCallAnalysisReport = {
25
+ checkedAt: number;
26
+ fields: VoicePostCallAnalysisFieldResult[];
27
+ integrationEvents: StoredVoiceIntegrationEvent[];
28
+ issues: VoicePostCallAnalysisIssue[];
29
+ operationRecordHref?: string;
30
+ review?: StoredVoiceCallReviewArtifact;
31
+ reviewId?: string;
32
+ sessionId?: string;
33
+ status: VoicePostCallAnalysisStatus;
34
+ summary: {
35
+ deliveredIntegrationEvents: number;
36
+ failedIntegrationEvents: number;
37
+ fields: number;
38
+ missingRequiredFields: number;
39
+ missingRequiredTasks: number;
40
+ requiredFields: number;
41
+ requiredTaskKinds: number;
42
+ tasks: number;
43
+ };
44
+ tasks: StoredVoiceOpsTask[];
45
+ };
46
+ export type VoicePostCallAnalysisOptions = {
47
+ at?: number;
48
+ extractedFields?: Record<string, unknown>;
49
+ fields?: VoicePostCallAnalysisFieldRequirement[];
50
+ integrationEvents?: StoredVoiceIntegrationEvent[] | VoiceIntegrationEventStore;
51
+ operationRecordBasePath?: string;
52
+ requireDeliveredIntegrationEvent?: boolean;
53
+ requiredTaskKinds?: VoiceOpsTaskKind[];
54
+ review?: StoredVoiceCallReviewArtifact;
55
+ reviewId?: string;
56
+ reviews?: StoredVoiceCallReviewArtifact[] | VoiceCallReviewStore;
57
+ sessionId?: string;
58
+ tasks?: StoredVoiceOpsTask[] | VoiceOpsTaskStore;
59
+ };
60
+ export type VoicePostCallAnalysisRoutesOptions = VoicePostCallAnalysisOptions & {
61
+ headers?: HeadersInit;
62
+ name?: string;
63
+ path?: string;
64
+ source?: ((input: {
65
+ reviewId?: string;
66
+ sessionId?: string;
67
+ }) => Promise<VoicePostCallAnalysisOptions | VoicePostCallAnalysisReport> | VoicePostCallAnalysisOptions | VoicePostCallAnalysisReport) | VoicePostCallAnalysisOptions | VoicePostCallAnalysisReport;
68
+ };
69
+ export declare const buildVoicePostCallAnalysisReport: (options?: VoicePostCallAnalysisOptions) => Promise<VoicePostCallAnalysisReport>;
70
+ export declare const renderVoicePostCallAnalysisMarkdown: (report: VoicePostCallAnalysisReport) => string;
71
+ export declare const createVoicePostCallAnalysisRoutes: (options?: VoicePostCallAnalysisRoutesOptions) => Elysia<"", {
72
+ decorator: {};
73
+ store: {};
74
+ derive: {};
75
+ resolve: {};
76
+ }, {
77
+ typebox: {};
78
+ error: {};
79
+ }, {
80
+ schema: {};
81
+ standaloneSchema: {};
82
+ macro: {};
83
+ macroFn: {};
84
+ parser: {};
85
+ response: {};
86
+ }, {}, {
87
+ derive: {};
88
+ resolve: {};
89
+ schema: {};
90
+ standaloneSchema: {};
91
+ response: {};
92
+ }, {
93
+ derive: {};
94
+ resolve: {};
95
+ schema: {};
96
+ standaloneSchema: {};
97
+ response: {};
98
+ }>;
@@ -0,0 +1,6 @@
1
+ import { type VoiceProofTrendsWidgetOptions } from '../client/proofTrendsWidget';
2
+ export type VoiceProofTrendsProps = VoiceProofTrendsWidgetOptions & {
3
+ className?: string;
4
+ path?: string;
5
+ };
6
+ export declare const VoiceProofTrends: ({ className, path, ...options }: VoiceProofTrendsProps) => import("react/jsx-runtime").JSX.Element;
@@ -2,6 +2,7 @@ export { VoiceOpsStatus } from './VoiceOpsStatus';
2
2
  export { VoiceOpsActionCenter } from './VoiceOpsActionCenter';
3
3
  export { VoiceDeliveryRuntime } from './VoiceDeliveryRuntime';
4
4
  export { VoicePlatformCoverage } from './VoicePlatformCoverage';
5
+ export { VoiceProofTrends } from './VoiceProofTrends';
5
6
  export { VoiceProviderSimulationControls } from './VoiceProviderSimulationControls';
6
7
  export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
7
8
  export { VoiceProviderContracts } from './VoiceProviderContracts';
@@ -13,6 +14,7 @@ export { VoiceTurnLatency } from './VoiceTurnLatency';
13
14
  export { VoiceTurnQuality } from './VoiceTurnQuality';
14
15
  export { useVoiceOpsStatus } from './useVoiceOpsStatus';
15
16
  export { useVoicePlatformCoverage } from './useVoicePlatformCoverage';
17
+ export { useVoiceProofTrends } from './useVoiceProofTrends';
16
18
  export { useVoiceOpsActionCenter } from './useVoiceOpsActionCenter';
17
19
  export { useVoiceLiveOps } from './useVoiceLiveOps';
18
20
  export { useVoiceDeliveryRuntime } from './useVoiceDeliveryRuntime';