supafone-labs 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -7
- package/dist/cjs/index.d.ts +88 -27
- package/dist/cjs/index.js +32 -18
- package/dist/index.d.ts +88 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +126 -44
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A dependency-free TypeScript client for creating hosted Supafone agents
|
|
5
5
|
* through the Supafone API, including managed phone numbers, voices, stages,
|
|
6
|
-
* tools, recordings, transcripts, widgets, and Supafone
|
|
6
|
+
* tools, recordings, transcripts, widgets, and Supafone Supervisor. It also
|
|
7
7
|
* includes the Labs cloud sidecar oracle, hosted TTS/STT, live multilingual
|
|
8
8
|
* transcription, telemetry, agent builder, and objective-driven optimizer.
|
|
9
9
|
*
|
|
@@ -54,15 +54,13 @@ export interface SupafoneLabsOptions {
|
|
|
54
54
|
* fall back to the plain zero-billed report.
|
|
55
55
|
*/
|
|
56
56
|
postCallAnalysis?: boolean;
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* agent with no watcher. `voice_watcher` (snake) and the deprecated `labs`
|
|
61
|
-
* are accepted aliases, resolved voiceWatcher > voice_watcher > labs > true.
|
|
62
|
-
*/
|
|
57
|
+
/** Enable Supafone Supervisor live guidance, QA, and scoring (default true). */
|
|
58
|
+
supervisor?: boolean;
|
|
59
|
+
/** @deprecated Use supervisor. */
|
|
63
60
|
voiceWatcher?: boolean;
|
|
61
|
+
/** @deprecated Use supervisor. */
|
|
64
62
|
voice_watcher?: boolean;
|
|
65
|
-
/** @deprecated
|
|
63
|
+
/** @deprecated Use supervisor. */
|
|
66
64
|
labs?: boolean;
|
|
67
65
|
}
|
|
68
66
|
|
|
@@ -93,7 +91,10 @@ export interface WhisperOptions {
|
|
|
93
91
|
temperature?: number;
|
|
94
92
|
}
|
|
95
93
|
|
|
96
|
-
export type
|
|
94
|
+
export type SupervisorDirectiveKind = "empathy" | "tactical" | "guardrail" | "mixed";
|
|
95
|
+
|
|
96
|
+
/** @deprecated Use SupervisorDirectiveKind. */
|
|
97
|
+
export type SecondMindDirectiveKind = SupervisorDirectiveKind;
|
|
97
98
|
|
|
98
99
|
export interface DirectiveTextControl {
|
|
99
100
|
enabled?: boolean;
|
|
@@ -111,7 +112,7 @@ export interface DirectiveListControl {
|
|
|
111
112
|
item_max_chars?: number;
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
/** Serializable controls for each field generated by
|
|
115
|
+
/** Serializable controls for each field generated by Supafone Supervisor. */
|
|
115
116
|
export interface DirectiveContract {
|
|
116
117
|
empathyDirective?: DirectiveTextControl;
|
|
117
118
|
empathy_directive?: DirectiveTextControl;
|
|
@@ -124,31 +125,34 @@ export interface DirectiveContract {
|
|
|
124
125
|
language_mode?: "caller" | "model" | "fixed";
|
|
125
126
|
fixedLanguage?: string;
|
|
126
127
|
fixed_language?: string;
|
|
127
|
-
allowedKinds?:
|
|
128
|
-
allowed_kinds?:
|
|
128
|
+
allowedKinds?: SupervisorDirectiveKind[];
|
|
129
|
+
allowed_kinds?: SupervisorDirectiveKind[];
|
|
129
130
|
confidenceThreshold?: number;
|
|
130
131
|
confidence_threshold?: number;
|
|
131
132
|
operatorGuardrails?: string[];
|
|
132
133
|
operator_guardrails?: string[];
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
export interface
|
|
136
|
+
export interface SupervisorDirective {
|
|
136
137
|
empathy_directive: string;
|
|
137
138
|
tactical_directive: string;
|
|
138
139
|
surface_facts: string[];
|
|
139
140
|
guardrails: string[];
|
|
140
141
|
language: string;
|
|
141
142
|
confidence: number;
|
|
142
|
-
kind:
|
|
143
|
+
kind: SupervisorDirectiveKind;
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
/** @deprecated Use SupervisorDirective. */
|
|
147
|
+
export type SecondMindDirective = SupervisorDirective;
|
|
148
|
+
|
|
145
149
|
export interface StructuredWhisperOptions extends WhisperOptions {
|
|
146
150
|
directiveContract?: DirectiveContract;
|
|
147
151
|
directive_contract?: DirectiveContract;
|
|
148
152
|
/** Local final say: revise or suppress the generated directive before use. */
|
|
149
153
|
transform?: (
|
|
150
|
-
directive:
|
|
151
|
-
) =>
|
|
154
|
+
directive: SupervisorDirective,
|
|
155
|
+
) => SupervisorDirective | null | Promise<SupervisorDirective | null>;
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
export interface Balance {
|
|
@@ -574,8 +578,60 @@ export interface LabsToolsConfig {
|
|
|
574
578
|
voicemail?: boolean;
|
|
575
579
|
emergencyEscalation?: boolean;
|
|
576
580
|
emergency_escalation?: boolean;
|
|
577
|
-
|
|
578
|
-
|
|
581
|
+
/** Makes the native DTMF tool available for bounded phone-tree navigation. */
|
|
582
|
+
ivrNavigation?: boolean;
|
|
583
|
+
ivr_navigation?: boolean;
|
|
584
|
+
/** Executable customer-owned HTTPS tools, proxied by Supafone at call time. */
|
|
585
|
+
customTools?: LabsCustomToolDefinition[];
|
|
586
|
+
custom_tools?: LabsCustomToolDefinition[];
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export type LabsCustomToolParameterType = "string" | "number" | "integer" | "boolean";
|
|
590
|
+
|
|
591
|
+
export interface LabsCustomToolParameter {
|
|
592
|
+
name: string;
|
|
593
|
+
description?: string;
|
|
594
|
+
type?: LabsCustomToolParameterType;
|
|
595
|
+
required?: boolean;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export interface LabsCustomToolDefinition {
|
|
599
|
+
/** Stable id returned by Supafone. Omit it when creating a tool. */
|
|
600
|
+
id?: string;
|
|
601
|
+
/** Lowercase model tool name, such as lookup_order. */
|
|
602
|
+
name: string;
|
|
603
|
+
description?: string;
|
|
604
|
+
/** HTTPS endpoint called by Supafone's guarded server-side proxy. */
|
|
605
|
+
url: string;
|
|
606
|
+
/** Optional secret header name. Defaults to Authorization: Bearer <apiKey>. */
|
|
607
|
+
header?: string;
|
|
608
|
+
apiKey?: string;
|
|
609
|
+
api_key?: string;
|
|
610
|
+
/** Set false on update to remove a previously stored secret. */
|
|
611
|
+
apiKeySet?: boolean;
|
|
612
|
+
api_key_set?: boolean;
|
|
613
|
+
params?: LabsCustomToolParameter[];
|
|
614
|
+
parameters?: LabsCustomToolParameter[];
|
|
615
|
+
/** Optional call-stage keys where this tool is available. Empty means every stage. */
|
|
616
|
+
stages?: string[];
|
|
617
|
+
allowedStages?: string[];
|
|
618
|
+
allowed_stages?: string[];
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export interface LabsEmailConfig {
|
|
622
|
+
enabled?: boolean;
|
|
623
|
+
fromEmail?: string;
|
|
624
|
+
from_email?: string;
|
|
625
|
+
smtpHost?: string;
|
|
626
|
+
smtp_host?: string;
|
|
627
|
+
smtpPort?: number;
|
|
628
|
+
smtp_port?: number;
|
|
629
|
+
smtpUser?: string;
|
|
630
|
+
smtp_user?: string;
|
|
631
|
+
/** Encrypted by Supafone and never returned. */
|
|
632
|
+
smtpPassword?: string;
|
|
633
|
+
smtp_password?: string;
|
|
634
|
+
smtp_pass?: string;
|
|
579
635
|
}
|
|
580
636
|
|
|
581
637
|
export interface LabsRecordingConfig {
|
|
@@ -618,9 +674,12 @@ export interface LabsArtifactsConfig {
|
|
|
618
674
|
metadata?: Record<string, unknown>;
|
|
619
675
|
}
|
|
620
676
|
|
|
621
|
-
export interface
|
|
677
|
+
export interface LabsSupervisorConfig {
|
|
622
678
|
enabled?: boolean;
|
|
679
|
+
supervisor?: boolean;
|
|
680
|
+
/** @deprecated Use supervisor. */
|
|
623
681
|
voiceWatcher?: boolean;
|
|
682
|
+
/** @deprecated Use supervisor. */
|
|
624
683
|
voice_watcher?: boolean;
|
|
625
684
|
apiKey?: string;
|
|
626
685
|
api_key?: string;
|
|
@@ -636,6 +695,9 @@ export interface LabsWatcherConfig {
|
|
|
636
695
|
label?: string;
|
|
637
696
|
}
|
|
638
697
|
|
|
698
|
+
/** @deprecated Use LabsSupervisorConfig. */
|
|
699
|
+
export type LabsWatcherConfig = LabsSupervisorConfig;
|
|
700
|
+
|
|
639
701
|
export interface LabsUltravoxRuntime {
|
|
640
702
|
model?: string;
|
|
641
703
|
temperature?: number;
|
|
@@ -948,9 +1010,14 @@ export interface CreateLabsAgentRequest {
|
|
|
948
1010
|
artifacts?: LabsArtifactsConfig;
|
|
949
1011
|
compliance?: Record<string, unknown>;
|
|
950
1012
|
tools?: LabsToolsConfig;
|
|
951
|
-
|
|
1013
|
+
/** Optional per-agent SMTP sender used by the callable send_email tool. */
|
|
1014
|
+
email?: LabsEmailConfig;
|
|
1015
|
+
labs?: LabsSupervisorConfig;
|
|
952
1016
|
ultravox?: LabsUltravoxRuntime;
|
|
1017
|
+
supervisor?: boolean;
|
|
1018
|
+
/** @deprecated Use supervisor. */
|
|
953
1019
|
voiceWatcher?: boolean;
|
|
1020
|
+
/** @deprecated Use supervisor. */
|
|
954
1021
|
voice_watcher?: boolean;
|
|
955
1022
|
voiceWatcherModel?: string;
|
|
956
1023
|
voice_watcher_model?: string;
|
|
@@ -1722,13 +1789,13 @@ const DEFAULT_BASE = "https://api.labs.supafone.ai";
|
|
|
1722
1789
|
const DEFAULT_SUPAFONE_API_BASE = "https://api.supafone.ai";
|
|
1723
1790
|
|
|
1724
1791
|
const COACH_SYSTEM =
|
|
1725
|
-
"You are the coaching core of a
|
|
1792
|
+
"You are the coaching core of a supervisor for a live voice agent. Read the " +
|
|
1726
1793
|
"conversation and return ONE short, silent directive the agent reads but never " +
|
|
1727
1794
|
"speaks aloud — a correction or nudge, phrased imperatively. If nothing needs " +
|
|
1728
1795
|
"correcting, return an empty string.";
|
|
1729
1796
|
|
|
1730
1797
|
const STRUCTURED_COACH_SYSTEM =
|
|
1731
|
-
"You are the coaching core of a
|
|
1798
|
+
"You are the coaching core of a supervisor for a live voice agent. Read the " +
|
|
1732
1799
|
"conversation and return ONLY one JSON object with exactly these keys: " +
|
|
1733
1800
|
"empathy_directive (string), tactical_directive (string), surface_facts (string[]), " +
|
|
1734
1801
|
"guardrails (string[]), language (short code), confidence (0-1), and kind " +
|
|
@@ -1747,7 +1814,7 @@ interface NormalizedDirectiveContract {
|
|
|
1747
1814
|
};
|
|
1748
1815
|
language_mode: "caller" | "model" | "fixed";
|
|
1749
1816
|
fixed_language: string;
|
|
1750
|
-
allowed_kinds:
|
|
1817
|
+
allowed_kinds: SupervisorDirectiveKind[];
|
|
1751
1818
|
confidence_threshold: number;
|
|
1752
1819
|
operator_guardrails: string[];
|
|
1753
1820
|
}
|
|
@@ -1787,7 +1854,7 @@ function normalizeDirectiveContract(input: DirectiveContract = {}): NormalizedDi
|
|
|
1787
1854
|
guardrails: listControl(input.guardrails),
|
|
1788
1855
|
language_mode: languageMode,
|
|
1789
1856
|
fixed_language: String(input.fixed_language ?? input.fixedLanguage ?? "").trim(),
|
|
1790
|
-
allowed_kinds: allowed.filter((kind): kind is
|
|
1857
|
+
allowed_kinds: allowed.filter((kind): kind is SupervisorDirectiveKind =>
|
|
1791
1858
|
["empathy", "tactical", "guardrail", "mixed"].includes(kind),
|
|
1792
1859
|
),
|
|
1793
1860
|
confidence_threshold: Number.isFinite(threshold) ? Math.max(0, Math.min(1, threshold)) : 0.5,
|
|
@@ -1832,8 +1899,8 @@ function clipList(value: unknown, maxItems: number, itemMaxChars: number): strin
|
|
|
1832
1899
|
function normalizeStructuredDirective(
|
|
1833
1900
|
raw: Record<string, unknown>,
|
|
1834
1901
|
contract: NormalizedDirectiveContract,
|
|
1835
|
-
):
|
|
1836
|
-
const kind = String(raw.kind ?? "mixed") as
|
|
1902
|
+
): SupervisorDirective | null {
|
|
1903
|
+
const kind = String(raw.kind ?? "mixed") as SupervisorDirectiveKind;
|
|
1837
1904
|
if (!["empathy", "tactical", "guardrail", "mixed"].includes(kind)) return null;
|
|
1838
1905
|
const parsedConfidence = Number(raw.confidence ?? 0);
|
|
1839
1906
|
const confidence = Number.isFinite(parsedConfidence) ? Math.max(0, Math.min(1, parsedConfidence)) : 0;
|
|
@@ -1869,7 +1936,9 @@ export class SupafoneLabs {
|
|
|
1869
1936
|
private readonly supafoneApiKey: string;
|
|
1870
1937
|
private readonly timeoutMs: number;
|
|
1871
1938
|
private readonly postCallAnalysis: boolean;
|
|
1872
|
-
/** Client default for
|
|
1939
|
+
/** Client default for Supafone Supervisor (live guidance + QA + scoring). */
|
|
1940
|
+
readonly supervisor: boolean;
|
|
1941
|
+
/** @deprecated Use supervisor. */
|
|
1873
1942
|
readonly voiceWatcher: boolean;
|
|
1874
1943
|
private sessionToken?: string;
|
|
1875
1944
|
private accountToken?: string;
|
|
@@ -1898,8 +1967,9 @@ export class SupafoneLabs {
|
|
|
1898
1967
|
this.appUrl = (opts.appUrl ?? "https://app.supafone.ai").replace(/\/$/, "");
|
|
1899
1968
|
this.timeoutMs = opts.timeoutMs ?? 30_000;
|
|
1900
1969
|
this.postCallAnalysis = opts.postCallAnalysis ?? false;
|
|
1901
|
-
// Precedence:
|
|
1902
|
-
this.
|
|
1970
|
+
// Precedence: supervisor > legacy aliases > true.
|
|
1971
|
+
this.supervisor = opts.supervisor ?? opts.voiceWatcher ?? opts.voice_watcher ?? opts.labs ?? true;
|
|
1972
|
+
this.voiceWatcher = this.supervisor;
|
|
1903
1973
|
this.sessionToken = opts.sessionToken;
|
|
1904
1974
|
this.accountToken = opts.accountToken;
|
|
1905
1975
|
this.accountEmail = opts.accountEmail;
|
|
@@ -2259,14 +2329,14 @@ export class SupafoneLabs {
|
|
|
2259
2329
|
}
|
|
2260
2330
|
|
|
2261
2331
|
/**
|
|
2262
|
-
* Structured
|
|
2332
|
+
* Structured Supafone Supervisor guidance with developer-controlled field policy.
|
|
2263
2333
|
* Returns null when JSON is invalid, evidence misses the confidence gate,
|
|
2264
2334
|
* the generated kind is disallowed, or the local transform suppresses it.
|
|
2265
2335
|
*/
|
|
2266
2336
|
async whisperStructured(
|
|
2267
2337
|
transcript: string,
|
|
2268
2338
|
opts: StructuredWhisperOptions = {},
|
|
2269
|
-
): Promise<
|
|
2339
|
+
): Promise<SupervisorDirective | null> {
|
|
2270
2340
|
const contract = normalizeDirectiveContract(
|
|
2271
2341
|
opts.directive_contract ?? opts.directiveContract ?? {},
|
|
2272
2342
|
);
|
|
@@ -2300,7 +2370,7 @@ export class SupafoneLabs {
|
|
|
2300
2370
|
directive(
|
|
2301
2371
|
transcript: string,
|
|
2302
2372
|
opts: StructuredWhisperOptions = {},
|
|
2303
|
-
): Promise<
|
|
2373
|
+
): Promise<SupervisorDirective | null> {
|
|
2304
2374
|
return this.whisperStructured(transcript, opts);
|
|
2305
2375
|
}
|
|
2306
2376
|
|
|
@@ -3097,7 +3167,7 @@ class LabsAgentsNamespace {
|
|
|
3097
3167
|
return this.sm.requestSupafoneApi<CreateLabsAgentResponse>(
|
|
3098
3168
|
"POST",
|
|
3099
3169
|
"/api/v1/labs/agents",
|
|
3100
|
-
labsAgentPayload(this.
|
|
3170
|
+
labsAgentPayload(this.withSupervisor(input)),
|
|
3101
3171
|
);
|
|
3102
3172
|
}
|
|
3103
3173
|
|
|
@@ -3114,17 +3184,16 @@ class LabsAgentsNamespace {
|
|
|
3114
3184
|
return this.plan(input);
|
|
3115
3185
|
}
|
|
3116
3186
|
|
|
3117
|
-
/** Default the agent onto the client's
|
|
3118
|
-
*
|
|
3119
|
-
|
|
3120
|
-
private withVoiceWatcher(input: CreateLabsAgentRequest): CreateLabsAgentRequest {
|
|
3187
|
+
/** Default the agent onto the client's Supafone Supervisor setting unless the
|
|
3188
|
+
* caller set it explicitly. Legacy wire fields remain unchanged. */
|
|
3189
|
+
private withSupervisor(input: CreateLabsAgentRequest): CreateLabsAgentRequest {
|
|
3121
3190
|
const out: CreateLabsAgentRequest = { ...input };
|
|
3122
|
-
if (out.voice_watcher === undefined && out.voiceWatcher === undefined) {
|
|
3123
|
-
out.
|
|
3191
|
+
if (out.supervisor === undefined && out.voice_watcher === undefined && out.voiceWatcher === undefined) {
|
|
3192
|
+
out.supervisor = this.sm.supervisor;
|
|
3124
3193
|
}
|
|
3125
3194
|
const labs = out.labs;
|
|
3126
|
-
if (labs && labs.voice_watcher === undefined && labs.voiceWatcher === undefined) {
|
|
3127
|
-
out.labs = { ...labs,
|
|
3195
|
+
if (labs && labs.supervisor === undefined && labs.voice_watcher === undefined && labs.voiceWatcher === undefined) {
|
|
3196
|
+
out.labs = { ...labs, supervisor: this.sm.supervisor };
|
|
3128
3197
|
}
|
|
3129
3198
|
return out;
|
|
3130
3199
|
}
|
|
@@ -4099,9 +4168,10 @@ function labsAgentPayload(input: CreateLabsAgentRequest): Record<string, unknown
|
|
|
4099
4168
|
artifacts: input.artifacts ? artifactsPayload(input.artifacts) : undefined,
|
|
4100
4169
|
compliance: input.compliance,
|
|
4101
4170
|
tools: input.tools ? toolsPayload(input.tools) : undefined,
|
|
4171
|
+
email: input.email ? emailPayload(input.email) : undefined,
|
|
4102
4172
|
labs: input.labs ? labsPayload(input.labs) : undefined,
|
|
4103
4173
|
ultravox: input.ultravox ? ultravoxPayload(input.ultravox) : undefined,
|
|
4104
|
-
voice_watcher: input.voice_watcher ?? input.voiceWatcher,
|
|
4174
|
+
voice_watcher: input.supervisor ?? input.voice_watcher ?? input.voiceWatcher,
|
|
4105
4175
|
voice_watcher_model: input.voice_watcher_model ?? input.voiceWatcherModel,
|
|
4106
4176
|
metadata: labsAgentMetadataPayload(input),
|
|
4107
4177
|
});
|
|
@@ -4490,10 +4560,22 @@ function toolsPayload(input: LabsToolsConfig): Record<string, unknown> {
|
|
|
4490
4560
|
existing_client_lookup: input.existing_client_lookup ?? input.existingClientLookup,
|
|
4491
4561
|
voicemail: input.voicemail,
|
|
4492
4562
|
emergency_escalation: input.emergency_escalation ?? input.emergencyEscalation,
|
|
4563
|
+
ivr_navigation: input.ivr_navigation ?? input.ivrNavigation,
|
|
4493
4564
|
custom_tools: input.custom_tools ?? input.customTools,
|
|
4494
4565
|
});
|
|
4495
4566
|
}
|
|
4496
4567
|
|
|
4568
|
+
function emailPayload(input: LabsEmailConfig): Record<string, unknown> {
|
|
4569
|
+
return compact({
|
|
4570
|
+
enabled: input.enabled,
|
|
4571
|
+
from_email: input.from_email ?? input.fromEmail,
|
|
4572
|
+
smtp_host: input.smtp_host ?? input.smtpHost,
|
|
4573
|
+
smtp_port: input.smtp_port ?? input.smtpPort,
|
|
4574
|
+
smtp_user: input.smtp_user ?? input.smtpUser,
|
|
4575
|
+
smtp_pass: input.smtp_pass ?? input.smtp_password ?? input.smtpPassword,
|
|
4576
|
+
});
|
|
4577
|
+
}
|
|
4578
|
+
|
|
4497
4579
|
function recordingPayload(input: LabsRecordingConfig): Record<string, unknown> {
|
|
4498
4580
|
return compact({
|
|
4499
4581
|
enabled: input.enabled,
|
|
@@ -4533,10 +4615,10 @@ function artifactsPayload(input: LabsArtifactsConfig): Record<string, unknown> {
|
|
|
4533
4615
|
});
|
|
4534
4616
|
}
|
|
4535
4617
|
|
|
4536
|
-
function labsPayload(input:
|
|
4618
|
+
function labsPayload(input: LabsSupervisorConfig): Record<string, unknown> {
|
|
4537
4619
|
return compact({
|
|
4538
4620
|
enabled: input.enabled,
|
|
4539
|
-
voice_watcher: input.voice_watcher ?? input.voiceWatcher,
|
|
4621
|
+
voice_watcher: input.supervisor ?? input.voice_watcher ?? input.voiceWatcher,
|
|
4540
4622
|
api_key: input.api_key ?? input.apiKey,
|
|
4541
4623
|
model: input.model,
|
|
4542
4624
|
mode: input.mode,
|