@absolutejs/voice 0.0.22-beta.510 → 0.0.22-beta.512
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/angular/index.js +13 -0
- package/dist/bookingFlow.d.ts +43 -0
- package/dist/calendarAdapter.d.ts +47 -0
- package/dist/calendarSlots.d.ts +35 -0
- package/dist/client/index.js +13 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +930 -0
- package/dist/liveCoach.d.ts +43 -0
- package/dist/noShowPredictor.d.ts +46 -0
- package/dist/react/index.js +13 -0
- package/dist/reminderScheduler.d.ts +43 -0
- package/dist/supervisorPermissions.d.ts +33 -0
- package/dist/supervisorPresence.d.ts +49 -0
- package/dist/svelte/index.js +13 -0
- package/dist/testing/index.js +13 -0
- package/dist/transcriptAnnotator.d.ts +41 -0
- package/dist/vue/index.js +13 -0
- package/dist/whisperChannel.d.ts +50 -0
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type VoiceCoachNudgeKind = "hint" | "correction" | "warning" | "script-line" | "knowledge";
|
|
2
|
+
export type VoiceCoachNudge = {
|
|
3
|
+
id: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
supervisorId: string;
|
|
6
|
+
kind: VoiceCoachNudgeKind;
|
|
7
|
+
text: string;
|
|
8
|
+
createdAt: number;
|
|
9
|
+
injected: boolean;
|
|
10
|
+
injectedAt?: number;
|
|
11
|
+
acknowledged: boolean;
|
|
12
|
+
acknowledgedAt?: number;
|
|
13
|
+
expiresAt?: number;
|
|
14
|
+
};
|
|
15
|
+
export type VoiceCoachNudgeInjection = {
|
|
16
|
+
role: "system" | "developer";
|
|
17
|
+
content: string;
|
|
18
|
+
metadata: {
|
|
19
|
+
nudgeId: string;
|
|
20
|
+
supervisorId: string;
|
|
21
|
+
kind: VoiceCoachNudgeKind;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type CreateVoiceLiveCoachOptions = {
|
|
25
|
+
sessionId: string;
|
|
26
|
+
injectionRole?: "system" | "developer";
|
|
27
|
+
templateForKind?: Partial<Record<VoiceCoachNudgeKind, string>>;
|
|
28
|
+
defaultExpiryMs?: number;
|
|
29
|
+
generateId?: () => string;
|
|
30
|
+
now?: () => number;
|
|
31
|
+
};
|
|
32
|
+
export declare const createVoiceLiveCoach: (options: CreateVoiceLiveCoachOptions) => {
|
|
33
|
+
acknowledge: (id: string) => boolean;
|
|
34
|
+
consumeForInjection: () => VoiceCoachNudgeInjection[];
|
|
35
|
+
history: () => VoiceCoachNudge[];
|
|
36
|
+
pending: () => VoiceCoachNudge[];
|
|
37
|
+
push: (input: Omit<VoiceCoachNudge, "id" | "createdAt" | "injected" | "acknowledged" | "sessionId"> & {
|
|
38
|
+
id?: string;
|
|
39
|
+
}) => VoiceCoachNudge;
|
|
40
|
+
sessionId: string;
|
|
41
|
+
subscribe(listener: (nudge: VoiceCoachNudge) => void): () => void;
|
|
42
|
+
};
|
|
43
|
+
export type VoiceLiveCoach = ReturnType<typeof createVoiceLiveCoach>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type VoiceNoShowHistoricalRecord = {
|
|
2
|
+
appointmentId: string;
|
|
3
|
+
scheduledStartMs: number;
|
|
4
|
+
outcome: "kept" | "no-show" | "cancelled" | "rescheduled";
|
|
5
|
+
};
|
|
6
|
+
export type VoiceNoShowSignal = {
|
|
7
|
+
kind: "lead-time-hours";
|
|
8
|
+
value: number;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "weekday";
|
|
11
|
+
value: number;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "hour-of-day";
|
|
14
|
+
value: number;
|
|
15
|
+
} | {
|
|
16
|
+
kind: "prior-no-show-count";
|
|
17
|
+
value: number;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "prior-kept-count";
|
|
20
|
+
value: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "reminder-confirmed";
|
|
23
|
+
value: boolean;
|
|
24
|
+
} | {
|
|
25
|
+
kind: "callback-distance-hours";
|
|
26
|
+
value: number;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "weather-disruption";
|
|
29
|
+
value: boolean;
|
|
30
|
+
};
|
|
31
|
+
export type VoiceNoShowScoreInput = {
|
|
32
|
+
appointmentStartMs: number;
|
|
33
|
+
bookedAtMs: number;
|
|
34
|
+
history?: VoiceNoShowHistoricalRecord[];
|
|
35
|
+
reminderConfirmed?: boolean;
|
|
36
|
+
weatherDisruption?: boolean;
|
|
37
|
+
callbackDistanceHours?: number;
|
|
38
|
+
now?: () => number;
|
|
39
|
+
};
|
|
40
|
+
export type VoiceNoShowVerdict = {
|
|
41
|
+
score: number;
|
|
42
|
+
band: "low" | "moderate" | "high";
|
|
43
|
+
drivers: VoiceNoShowSignal[];
|
|
44
|
+
};
|
|
45
|
+
export declare const scoreVoiceNoShowRisk: (input: VoiceNoShowScoreInput) => VoiceNoShowVerdict;
|
|
46
|
+
export declare const summarizeVoiceNoShowVerdict: (verdict: VoiceNoShowVerdict) => string;
|
package/dist/react/index.js
CHANGED
|
@@ -10,6 +10,19 @@ var __name = (target, name) => {
|
|
|
10
10
|
});
|
|
11
11
|
return target;
|
|
12
12
|
};
|
|
13
|
+
var __returnValue = (v) => v;
|
|
14
|
+
function __exportSetter(name, newValue) {
|
|
15
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
16
|
+
}
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
set: __exportSetter.bind(all, name)
|
|
24
|
+
});
|
|
25
|
+
};
|
|
13
26
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
14
27
|
var __typeError = (msg) => {
|
|
15
28
|
throw TypeError(msg);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type VoiceReminderChannel = "call" | "sms" | "email";
|
|
2
|
+
export type VoiceReminderTrigger = {
|
|
3
|
+
id: string;
|
|
4
|
+
channel: VoiceReminderChannel;
|
|
5
|
+
offsetMinutesBeforeStart: number;
|
|
6
|
+
templateId?: string;
|
|
7
|
+
retryOnFailure?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type VoiceReminderJob = {
|
|
10
|
+
id: string;
|
|
11
|
+
appointmentId: string;
|
|
12
|
+
triggerId: string;
|
|
13
|
+
channel: VoiceReminderChannel;
|
|
14
|
+
scheduledAtMs: number;
|
|
15
|
+
status: "pending" | "in-flight" | "sent" | "skipped" | "failed" | "cancelled";
|
|
16
|
+
attempts: number;
|
|
17
|
+
lastError?: string;
|
|
18
|
+
metadata?: Record<string, string>;
|
|
19
|
+
};
|
|
20
|
+
export type ScheduleVoiceRemindersInput = {
|
|
21
|
+
appointmentId: string;
|
|
22
|
+
appointmentStartMs: number;
|
|
23
|
+
triggers: VoiceReminderTrigger[];
|
|
24
|
+
metadata?: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
export type CreateVoiceReminderSchedulerOptions = {
|
|
27
|
+
generateJobId?: () => string;
|
|
28
|
+
now?: () => number;
|
|
29
|
+
defaultTriggers?: VoiceReminderTrigger[];
|
|
30
|
+
maxAttempts?: number;
|
|
31
|
+
};
|
|
32
|
+
export declare const DEFAULT_VOICE_REMINDER_TRIGGERS: VoiceReminderTrigger[];
|
|
33
|
+
export declare const createVoiceReminderScheduler: (options?: CreateVoiceReminderSchedulerOptions) => {
|
|
34
|
+
cancelForAppointment: (appointmentId: string) => number;
|
|
35
|
+
due: (at?: number) => VoiceReminderJob[];
|
|
36
|
+
list: (appointmentId?: string) => VoiceReminderJob[];
|
|
37
|
+
markFailed: (jobId: string, error: string) => boolean;
|
|
38
|
+
markInFlight: (jobId: string) => boolean;
|
|
39
|
+
markSent: (jobId: string) => boolean;
|
|
40
|
+
schedule: (input: ScheduleVoiceRemindersInput) => VoiceReminderJob[];
|
|
41
|
+
subscribe(listener: (job: VoiceReminderJob) => void): () => void;
|
|
42
|
+
};
|
|
43
|
+
export type VoiceReminderScheduler = ReturnType<typeof createVoiceReminderScheduler>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type VoiceSupervisorCapability = "monitor" | "annotate" | "coach" | "whisper" | "barge" | "takeover" | "release" | "end-call" | "view-pii" | "export-recording";
|
|
2
|
+
export type VoiceSupervisorTier = "monitor-only" | "annotate" | "coach" | "whisper" | "full-control";
|
|
3
|
+
export type VoiceSupervisorPermission = {
|
|
4
|
+
supervisorId: string;
|
|
5
|
+
tier: VoiceSupervisorTier;
|
|
6
|
+
extraCapabilities?: VoiceSupervisorCapability[];
|
|
7
|
+
deniedCapabilities?: VoiceSupervisorCapability[];
|
|
8
|
+
expiresAt?: number;
|
|
9
|
+
};
|
|
10
|
+
export type VoiceSupervisorPermissionCheck = {
|
|
11
|
+
allowed: boolean;
|
|
12
|
+
reason?: "no-permission" | "expired" | "denied" | "tier-too-low";
|
|
13
|
+
};
|
|
14
|
+
export type CreateVoiceSupervisorPermissionsOptions = {
|
|
15
|
+
defaultTier?: VoiceSupervisorTier;
|
|
16
|
+
permissions?: VoiceSupervisorPermission[];
|
|
17
|
+
now?: () => number;
|
|
18
|
+
};
|
|
19
|
+
export declare const createVoiceSupervisorPermissions: (options?: CreateVoiceSupervisorPermissionsOptions) => {
|
|
20
|
+
can: (supervisorId: string, capability: VoiceSupervisorCapability) => VoiceSupervisorPermissionCheck;
|
|
21
|
+
capabilitiesFor: (supervisorId: string) => VoiceSupervisorCapability[];
|
|
22
|
+
enforce: (supervisorId: string, capability: VoiceSupervisorCapability) => void;
|
|
23
|
+
get: (supervisorId: string) => VoiceSupervisorPermission | null;
|
|
24
|
+
grant: (supervisorId: string, tier: VoiceSupervisorTier, options?: {
|
|
25
|
+
extraCapabilities?: VoiceSupervisorCapability[];
|
|
26
|
+
deniedCapabilities?: VoiceSupervisorCapability[];
|
|
27
|
+
expiresAt?: number;
|
|
28
|
+
}) => VoiceSupervisorPermission;
|
|
29
|
+
revoke: (supervisorId: string) => boolean;
|
|
30
|
+
tiers: () => VoiceSupervisorTier[];
|
|
31
|
+
};
|
|
32
|
+
export type VoiceSupervisorPermissions = ReturnType<typeof createVoiceSupervisorPermissions>;
|
|
33
|
+
export declare const VOICE_SUPERVISOR_TIER_CAPABILITIES: Record<VoiceSupervisorTier, VoiceSupervisorCapability[]>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type VoiceSupervisorRole = "viewer" | "coach" | "whisperer" | "owner";
|
|
2
|
+
export type VoiceSupervisorWatcher = {
|
|
3
|
+
supervisorId: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
joinedAt: number;
|
|
6
|
+
lastSeenAt: number;
|
|
7
|
+
role: VoiceSupervisorRole;
|
|
8
|
+
displayName?: string;
|
|
9
|
+
};
|
|
10
|
+
export type VoiceSupervisorPresenceEvent = {
|
|
11
|
+
type: "join";
|
|
12
|
+
watcher: VoiceSupervisorWatcher;
|
|
13
|
+
} | {
|
|
14
|
+
type: "leave";
|
|
15
|
+
supervisorId: string;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
at: number;
|
|
18
|
+
} | {
|
|
19
|
+
type: "role-change";
|
|
20
|
+
supervisorId: string;
|
|
21
|
+
sessionId: string;
|
|
22
|
+
from: VoiceSupervisorRole;
|
|
23
|
+
to: VoiceSupervisorRole;
|
|
24
|
+
at: number;
|
|
25
|
+
} | {
|
|
26
|
+
type: "heartbeat";
|
|
27
|
+
supervisorId: string;
|
|
28
|
+
sessionId: string;
|
|
29
|
+
at: number;
|
|
30
|
+
};
|
|
31
|
+
export type CreateVoiceSupervisorPresenceOptions = {
|
|
32
|
+
staleAfterMs?: number;
|
|
33
|
+
now?: () => number;
|
|
34
|
+
};
|
|
35
|
+
export declare const createVoiceSupervisorPresence: (options?: CreateVoiceSupervisorPresenceOptions) => {
|
|
36
|
+
heartbeat: (sessionId: string, supervisorId: string) => boolean;
|
|
37
|
+
join: (input: {
|
|
38
|
+
supervisorId: string;
|
|
39
|
+
sessionId: string;
|
|
40
|
+
role?: VoiceSupervisorRole;
|
|
41
|
+
displayName?: string;
|
|
42
|
+
}) => VoiceSupervisorWatcher;
|
|
43
|
+
leave: (sessionId: string, supervisorId: string) => boolean;
|
|
44
|
+
list: (sessionId: string) => VoiceSupervisorWatcher[];
|
|
45
|
+
setRole: (sessionId: string, supervisorId: string, role: VoiceSupervisorRole) => boolean;
|
|
46
|
+
sessionsWatchedBy(supervisorId: string): string[];
|
|
47
|
+
subscribe(listener: (event: VoiceSupervisorPresenceEvent) => void): () => void;
|
|
48
|
+
};
|
|
49
|
+
export type VoiceSupervisorPresence = ReturnType<typeof createVoiceSupervisorPresence>;
|
package/dist/svelte/index.js
CHANGED
|
@@ -10,6 +10,19 @@ var __name = (target, name) => {
|
|
|
10
10
|
});
|
|
11
11
|
return target;
|
|
12
12
|
};
|
|
13
|
+
var __returnValue = (v) => v;
|
|
14
|
+
function __exportSetter(name, newValue) {
|
|
15
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
16
|
+
}
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
set: __exportSetter.bind(all, name)
|
|
24
|
+
});
|
|
25
|
+
};
|
|
13
26
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
14
27
|
var __typeError = (msg) => {
|
|
15
28
|
throw TypeError(msg);
|
package/dist/testing/index.js
CHANGED
|
@@ -10,6 +10,19 @@ var __name = (target, name) => {
|
|
|
10
10
|
});
|
|
11
11
|
return target;
|
|
12
12
|
};
|
|
13
|
+
var __returnValue = (v) => v;
|
|
14
|
+
function __exportSetter(name, newValue) {
|
|
15
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
16
|
+
}
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
set: __exportSetter.bind(all, name)
|
|
24
|
+
});
|
|
25
|
+
};
|
|
13
26
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
14
27
|
var __typeError = (msg) => {
|
|
15
28
|
throw TypeError(msg);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type VoiceTranscriptAnnotationKind = "great-recovery" | "missed-objection" | "compliance-concern" | "tone-issue" | "knowledge-gap" | "follow-up-needed" | "custom";
|
|
2
|
+
export type VoiceTranscriptAnnotation = {
|
|
3
|
+
id: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
supervisorId: string;
|
|
6
|
+
kind: VoiceTranscriptAnnotationKind;
|
|
7
|
+
customLabel?: string;
|
|
8
|
+
text?: string;
|
|
9
|
+
turnId?: string;
|
|
10
|
+
rangeStartMs: number;
|
|
11
|
+
rangeEndMs?: number;
|
|
12
|
+
createdAt: number;
|
|
13
|
+
severity: "info" | "minor" | "major";
|
|
14
|
+
};
|
|
15
|
+
export type CreateVoiceTranscriptAnnotatorOptions = {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
generateId?: () => string;
|
|
18
|
+
now?: () => number;
|
|
19
|
+
};
|
|
20
|
+
export declare const DEFAULT_VOICE_ANNOTATION_KIND_SEVERITY: Record<VoiceTranscriptAnnotationKind, VoiceTranscriptAnnotation["severity"]>;
|
|
21
|
+
export declare const createVoiceTranscriptAnnotator: (options: CreateVoiceTranscriptAnnotatorOptions) => {
|
|
22
|
+
add: (input: Omit<VoiceTranscriptAnnotation, "id" | "createdAt" | "sessionId" | "severity"> & {
|
|
23
|
+
severity?: VoiceTranscriptAnnotation["severity"];
|
|
24
|
+
id?: string;
|
|
25
|
+
}) => VoiceTranscriptAnnotation;
|
|
26
|
+
list: (filter?: {
|
|
27
|
+
kind?: VoiceTranscriptAnnotationKind;
|
|
28
|
+
supervisorId?: string;
|
|
29
|
+
severity?: VoiceTranscriptAnnotation["severity"];
|
|
30
|
+
fromMs?: number;
|
|
31
|
+
toMs?: number;
|
|
32
|
+
}) => VoiceTranscriptAnnotation[];
|
|
33
|
+
remove: (id: string) => boolean;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
summarize: () => {
|
|
36
|
+
byKind: Partial<Record<VoiceTranscriptAnnotationKind, number>>;
|
|
37
|
+
bySeverity: Record<"info" | "minor" | "major", number>;
|
|
38
|
+
total: number;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export type VoiceTranscriptAnnotator = ReturnType<typeof createVoiceTranscriptAnnotator>;
|
package/dist/vue/index.js
CHANGED
|
@@ -10,6 +10,19 @@ var __name = (target, name) => {
|
|
|
10
10
|
});
|
|
11
11
|
return target;
|
|
12
12
|
};
|
|
13
|
+
var __returnValue = (v) => v;
|
|
14
|
+
function __exportSetter(name, newValue) {
|
|
15
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
16
|
+
}
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
set: __exportSetter.bind(all, name)
|
|
24
|
+
});
|
|
25
|
+
};
|
|
13
26
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
14
27
|
var __typeError = (msg) => {
|
|
15
28
|
throw TypeError(msg);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export type VoiceWhisperFrame = {
|
|
2
|
+
sessionId: string;
|
|
3
|
+
supervisorId: string;
|
|
4
|
+
pcm: ArrayBuffer | Uint8Array;
|
|
5
|
+
sampleRate: number;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
};
|
|
8
|
+
export type VoiceWhisperRoute = "agent-only" | "agent-and-caller" | "drop";
|
|
9
|
+
export type VoiceWhisperEvent = {
|
|
10
|
+
type: "started";
|
|
11
|
+
supervisorId: string;
|
|
12
|
+
at: number;
|
|
13
|
+
} | {
|
|
14
|
+
type: "stopped";
|
|
15
|
+
supervisorId: string;
|
|
16
|
+
at: number;
|
|
17
|
+
} | {
|
|
18
|
+
type: "frame";
|
|
19
|
+
frame: VoiceWhisperFrame;
|
|
20
|
+
} | {
|
|
21
|
+
type: "ducked";
|
|
22
|
+
supervisorId: string;
|
|
23
|
+
level: number;
|
|
24
|
+
at: number;
|
|
25
|
+
};
|
|
26
|
+
export type CreateVoiceWhisperChannelOptions = {
|
|
27
|
+
sessionId: string;
|
|
28
|
+
defaultRoute?: VoiceWhisperRoute;
|
|
29
|
+
duckCallerToLevel?: number;
|
|
30
|
+
maxConcurrentWhispers?: number;
|
|
31
|
+
now?: () => number;
|
|
32
|
+
};
|
|
33
|
+
type ActiveWhisper = {
|
|
34
|
+
supervisorId: string;
|
|
35
|
+
route: VoiceWhisperRoute;
|
|
36
|
+
startedAt: number;
|
|
37
|
+
};
|
|
38
|
+
export declare const createVoiceWhisperChannel: (options: CreateVoiceWhisperChannelOptions) => {
|
|
39
|
+
activeSupervisors: () => string[];
|
|
40
|
+
isWhispering: (supervisorId: string) => boolean;
|
|
41
|
+
pushFrame: (frame: VoiceWhisperFrame) => VoiceWhisperRoute;
|
|
42
|
+
routeFor: (supervisorId: string) => VoiceWhisperRoute | null;
|
|
43
|
+
sessionId: string;
|
|
44
|
+
setRoute(supervisorId: string, route: VoiceWhisperRoute): boolean;
|
|
45
|
+
start: (supervisorId: string, route?: VoiceWhisperRoute) => ActiveWhisper | undefined;
|
|
46
|
+
stop: (supervisorId: string) => boolean;
|
|
47
|
+
subscribe(listener: (event: VoiceWhisperEvent) => void): () => void;
|
|
48
|
+
};
|
|
49
|
+
export type VoiceWhisperChannel = ReturnType<typeof createVoiceWhisperChannel>;
|
|
50
|
+
export {};
|