supafone-labs 0.5.4 → 0.6.0
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 +25 -6
- package/dist/cjs/index.d.ts +107 -19
- package/dist/cjs/index.js +129 -33
- package/dist/index.d.ts +107 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +129 -33
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +277 -45
package/dist/cjs/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* A dependency-free TypeScript client for creating hosted Supafone agents
|
|
6
6
|
* through the Supafone API, including managed phone numbers, voices, stages,
|
|
7
7
|
* tools, recordings, transcripts, widgets, and Supafone Supervisor. It also
|
|
8
|
-
* includes
|
|
8
|
+
* includes Supafone Supervisor, hosted TTS/STT, live multilingual
|
|
9
9
|
* transcription, telemetry, agent builder, and objective-driven optimizer.
|
|
10
10
|
*
|
|
11
11
|
* Works in Node 18+ (native fetch/WebSocket) and the browser.
|
|
@@ -157,6 +157,19 @@ class SupafoneLabsError extends Error {
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
exports.SupafoneLabsError = SupafoneLabsError;
|
|
160
|
+
function errorDetailMessage(detail, fallback) {
|
|
161
|
+
if (detail && typeof detail === "object" && !Array.isArray(detail)) {
|
|
162
|
+
const value = detail;
|
|
163
|
+
for (const key of ["message", "detail", "error", "code"]) {
|
|
164
|
+
const candidate = value[key];
|
|
165
|
+
if (typeof candidate === "string" && candidate.trim())
|
|
166
|
+
return candidate.trim();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (typeof detail === "string" && detail.trim())
|
|
170
|
+
return detail.trim();
|
|
171
|
+
return fallback;
|
|
172
|
+
}
|
|
160
173
|
const DEFAULT_BASE = "https://api.labs.supafone.ai";
|
|
161
174
|
const DEFAULT_SUPAFONE_API_BASE = "https://api.supafone.ai";
|
|
162
175
|
const COACH_SYSTEM = "You are the coaching core of a supervisor for a live voice agent. Read the " +
|
|
@@ -358,8 +371,8 @@ class SupafoneLabs {
|
|
|
358
371
|
const text = await res.text();
|
|
359
372
|
const parsed = text ? safeJson(text) : {};
|
|
360
373
|
if (!res.ok) {
|
|
361
|
-
const detail = parsed?.detail ?? text
|
|
362
|
-
throw new SupafoneLabsError(`${method} ${path}: ${detail}`, res.status, parsed);
|
|
374
|
+
const detail = parsed?.detail ?? text;
|
|
375
|
+
throw new SupafoneLabsError(`${method} ${path}: ${errorDetailMessage(detail, `HTTP ${res.status}`)}`, res.status, parsed);
|
|
363
376
|
}
|
|
364
377
|
return parsed;
|
|
365
378
|
}
|
|
@@ -381,8 +394,8 @@ class SupafoneLabs {
|
|
|
381
394
|
const text = await res.text();
|
|
382
395
|
const parsed = text ? safeJson(text) : {};
|
|
383
396
|
if (!res.ok) {
|
|
384
|
-
const detail = parsed?.detail ?? text
|
|
385
|
-
throw new SupafoneLabsError(`${method} ${path}: ${detail}`, res.status, parsed);
|
|
397
|
+
const detail = parsed?.detail ?? text;
|
|
398
|
+
throw new SupafoneLabsError(`${method} ${path}: ${errorDetailMessage(detail, `HTTP ${res.status}`)}`, res.status, parsed);
|
|
386
399
|
}
|
|
387
400
|
return parsed;
|
|
388
401
|
}
|
|
@@ -408,8 +421,8 @@ class SupafoneLabs {
|
|
|
408
421
|
const text = await res.text();
|
|
409
422
|
const parsed = text ? safeJson(text) : {};
|
|
410
423
|
if (!res.ok) {
|
|
411
|
-
const detail = parsed?.detail ?? text
|
|
412
|
-
throw new SupafoneLabsError(`POST ${path}: ${detail}`, res.status, parsed);
|
|
424
|
+
const detail = parsed?.detail ?? text;
|
|
425
|
+
throw new SupafoneLabsError(`POST ${path}: ${errorDetailMessage(detail, `HTTP ${res.status}`)}`, res.status, parsed);
|
|
413
426
|
}
|
|
414
427
|
return parsed;
|
|
415
428
|
}
|
|
@@ -430,8 +443,8 @@ class SupafoneLabs {
|
|
|
430
443
|
if (!res.ok) {
|
|
431
444
|
const text = await res.text();
|
|
432
445
|
const parsed = text ? safeJson(text) : {};
|
|
433
|
-
const detail = parsed?.detail ?? text
|
|
434
|
-
throw new SupafoneLabsError(`GET ${path}: ${detail}`, res.status, parsed);
|
|
446
|
+
const detail = parsed?.detail ?? text;
|
|
447
|
+
throw new SupafoneLabsError(`GET ${path}: ${errorDetailMessage(detail, `HTTP ${res.status}`)}`, res.status, parsed);
|
|
435
448
|
}
|
|
436
449
|
return {
|
|
437
450
|
content: await res.arrayBuffer(),
|
|
@@ -494,8 +507,8 @@ class SupafoneLabs {
|
|
|
494
507
|
const text = await res.text();
|
|
495
508
|
const parsed = text ? safeJson(text) : {};
|
|
496
509
|
if (!res.ok) {
|
|
497
|
-
const detail = parsed?.detail ?? text
|
|
498
|
-
throw new SupafoneLabsError(`POST ${path}: ${detail}`, res.status, parsed);
|
|
510
|
+
const detail = parsed?.detail ?? text;
|
|
511
|
+
throw new SupafoneLabsError(`POST ${path}: ${errorDetailMessage(detail, `HTTP ${res.status}`)}`, res.status, parsed);
|
|
499
512
|
}
|
|
500
513
|
return parsed;
|
|
501
514
|
};
|
|
@@ -528,8 +541,8 @@ class SupafoneLabs {
|
|
|
528
541
|
const text = await res.text();
|
|
529
542
|
const parsed = text ? safeJson(text) : {};
|
|
530
543
|
if (!res.ok) {
|
|
531
|
-
const detail = parsed?.detail ?? text
|
|
532
|
-
throw new SupafoneLabsError(`${method} ${path}: ${detail}`, res.status, parsed);
|
|
544
|
+
const detail = parsed?.detail ?? text;
|
|
545
|
+
throw new SupafoneLabsError(`${method} ${path}: ${errorDetailMessage(detail, `HTTP ${res.status}`)}`, res.status, parsed);
|
|
533
546
|
}
|
|
534
547
|
return parsed;
|
|
535
548
|
}
|
|
@@ -604,22 +617,26 @@ class SupafoneLabs {
|
|
|
604
617
|
}
|
|
605
618
|
return this.requestAccountApi("POST", "/api/v1/agents/generate-intake", payload);
|
|
606
619
|
}
|
|
607
|
-
/** Raw
|
|
608
|
-
async
|
|
609
|
-
return this.request("POST", "/v1/
|
|
620
|
+
/** Raw Supervisor completion with either Supafone-managed or BYOK inference. */
|
|
621
|
+
async completeWithSupervisor(req) {
|
|
622
|
+
return this.request("POST", "/v1/supervisor/complete", {
|
|
610
623
|
messages: req.messages,
|
|
611
|
-
model: req.model ?? "supafone-
|
|
624
|
+
model: req.model ?? "supafone-supervisor",
|
|
612
625
|
max_tokens: req.maxTokens ?? 256,
|
|
613
626
|
...(req.temperature !== undefined ? { temperature: req.temperature } : {}),
|
|
614
627
|
});
|
|
615
628
|
}
|
|
629
|
+
/** @deprecated Use completeWithSupervisor(). */
|
|
630
|
+
async oracle(req) {
|
|
631
|
+
return this.completeWithSupervisor(req);
|
|
632
|
+
}
|
|
616
633
|
/**
|
|
617
634
|
* The one-liner: hand it the running transcript, get back a silent directive
|
|
618
635
|
* (empty string when the agent is doing fine).
|
|
619
636
|
*/
|
|
620
637
|
async whisper(transcript, opts = {}) {
|
|
621
638
|
const system = opts.guardrails ? `${COACH_SYSTEM}\n\nOperator rules:\n${opts.guardrails}` : COACH_SYSTEM;
|
|
622
|
-
const out = await this.
|
|
639
|
+
const out = await this.completeWithSupervisor({
|
|
623
640
|
model: opts.model,
|
|
624
641
|
maxTokens: opts.maxTokens ?? 120,
|
|
625
642
|
...(opts.temperature !== undefined ? { temperature: opts.temperature } : {}),
|
|
@@ -645,7 +662,7 @@ class SupafoneLabs {
|
|
|
645
662
|
directiveContractPrompt(contract),
|
|
646
663
|
operatorRules.length ? `Operator rules:\n${operatorRules.join("\n")}` : "",
|
|
647
664
|
].filter(Boolean).join("\n\n");
|
|
648
|
-
const out = await this.
|
|
665
|
+
const out = await this.completeWithSupervisor({
|
|
649
666
|
model: opts.model,
|
|
650
667
|
maxTokens: opts.maxTokens ?? 320,
|
|
651
668
|
...(opts.temperature !== undefined ? { temperature: opts.temperature } : {}),
|
|
@@ -728,7 +745,7 @@ class SupafoneLabs {
|
|
|
728
745
|
balance() {
|
|
729
746
|
return this.request("GET", "/v1/billing/balance");
|
|
730
747
|
}
|
|
731
|
-
/** Today's usage
|
|
748
|
+
/** Today's usage across Supervisor, TTS, STT, and managed runtime meters. */
|
|
732
749
|
usage() {
|
|
733
750
|
return this.request("GET", "/v1/usage");
|
|
734
751
|
}
|
|
@@ -795,7 +812,7 @@ class SupafoneLabs {
|
|
|
795
812
|
*
|
|
796
813
|
* With `postCallAnalysis: true` on the client and a transcript (or
|
|
797
814
|
* messages) present, the call is automatically classified first: the
|
|
798
|
-
*
|
|
815
|
+
* Supervisor labels it against the agent's objective (achieved/missed,
|
|
799
816
|
* per-criterion verdicts, failure reasons) and files the enriched report
|
|
800
817
|
* server-side. The generated labels come back on `analysis`. Analysis is
|
|
801
818
|
* best-effort — on any failure the plain zero-billed report still lands.
|
|
@@ -828,7 +845,7 @@ class SupafoneLabs {
|
|
|
828
845
|
* objective and get labels back — achieved/missed, per-criterion verdicts,
|
|
829
846
|
* failure reasons, and the blended objective value. Files an enriched call
|
|
830
847
|
* report server-side (feeding optimizer.improve() and objective stats).
|
|
831
|
-
* Billed one
|
|
848
|
+
* Billed one Supervisor inference.
|
|
832
849
|
*/
|
|
833
850
|
classifyCall(input) {
|
|
834
851
|
return this.request("POST", "/v1/calls/classify", compact({
|
|
@@ -840,7 +857,7 @@ class SupafoneLabs {
|
|
|
840
857
|
nudges: input.nudges,
|
|
841
858
|
}));
|
|
842
859
|
}
|
|
843
|
-
/** Available
|
|
860
|
+
/** Available managed and BYOK Supervisor model ids. */
|
|
844
861
|
async models() {
|
|
845
862
|
const d = await this.request("GET", "/v1/models");
|
|
846
863
|
return d.models.map((m) => (typeof m === "string" ? m : m.id));
|
|
@@ -1145,6 +1162,10 @@ class LabsBillingNamespace {
|
|
|
1145
1162
|
}
|
|
1146
1163
|
/** Start hosted Stripe Checkout. MCP callers should render checkout_url as a link. */
|
|
1147
1164
|
checkout(input = {}) {
|
|
1165
|
+
const sku = input.sku ?? input.packageSku ?? input.package_sku;
|
|
1166
|
+
if (sku) {
|
|
1167
|
+
return this.sm.request("POST", "/v1/billing/checkout", { sku });
|
|
1168
|
+
}
|
|
1148
1169
|
return this.sm.request("POST", "/v1/billing/checkout", compact({
|
|
1149
1170
|
kind: input.kind ?? "plan",
|
|
1150
1171
|
plan_key: input.plan_key ?? input.planKey,
|
|
@@ -1155,6 +1176,12 @@ class LabsBillingNamespace {
|
|
|
1155
1176
|
cancel_url: input.cancel_url ?? input.cancelUrl,
|
|
1156
1177
|
}));
|
|
1157
1178
|
}
|
|
1179
|
+
/** Start Stripe Checkout for one prepaid managed-minute package. */
|
|
1180
|
+
topUp(sku = "sf_voice_minutes_400_v1") {
|
|
1181
|
+
if (!sku.trim())
|
|
1182
|
+
return Promise.reject(new SupafoneLabsError("sku is required"));
|
|
1183
|
+
return this.checkout({ sku });
|
|
1184
|
+
}
|
|
1158
1185
|
status(checkoutSessionId) {
|
|
1159
1186
|
if (!checkoutSessionId?.trim())
|
|
1160
1187
|
throw new SupafoneLabsError("checkoutSessionId is required");
|
|
@@ -1644,6 +1671,37 @@ class LabsPhoneNumbersNamespace {
|
|
|
1644
1671
|
const suffix = q.toString() ? `?${q}` : "";
|
|
1645
1672
|
return this.sm.requestSupafoneApi("GET", `/api/v1/labs/phone-numbers${suffix}`);
|
|
1646
1673
|
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Read the explicitly enrolled shared developer-number pool. This inventory
|
|
1676
|
+
* never infers customer or merely-unassigned numbers into the response.
|
|
1677
|
+
*/
|
|
1678
|
+
pool() {
|
|
1679
|
+
return this.sm.requestSupafoneApi("GET", "/api/v1/labs/phone-numbers/pool");
|
|
1680
|
+
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Connect to realtime pool state using a short-lived pool-only token. The
|
|
1683
|
+
* Supafone API key is never placed in the WebSocket URL.
|
|
1684
|
+
*/
|
|
1685
|
+
async connectPool(opts = {}) {
|
|
1686
|
+
const snapshot = await this.pool();
|
|
1687
|
+
const stream = snapshot.stream;
|
|
1688
|
+
if (!stream?.url || !stream.token) {
|
|
1689
|
+
throw new SupafoneLabsError("Phone-pool response did not include stream metadata");
|
|
1690
|
+
}
|
|
1691
|
+
const WS = opts.WebSocketImpl ?? globalThis.WebSocket;
|
|
1692
|
+
if (!WS) {
|
|
1693
|
+
throw new SupafoneLabsError("No WebSocket available - pass opts.WebSocketImpl (for example, the ws package)");
|
|
1694
|
+
}
|
|
1695
|
+
const url = new URL(stream.url, `${this.sm.supafoneApiBaseUrl}/`);
|
|
1696
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
1697
|
+
url.searchParams.set("token", stream.token);
|
|
1698
|
+
const socket = new WS(url.toString(), stream.protocol || "developer_phone_pool_v1");
|
|
1699
|
+
await new Promise((resolve, reject) => {
|
|
1700
|
+
socket.addEventListener("open", () => resolve(), { once: true });
|
|
1701
|
+
socket.addEventListener("error", () => reject(new SupafoneLabsError("Could not connect to the phone-pool stream")), { once: true });
|
|
1702
|
+
});
|
|
1703
|
+
return socket;
|
|
1704
|
+
}
|
|
1647
1705
|
/** Search Supafone-managed inventory. This uses Supafone's master telephony account. */
|
|
1648
1706
|
search(opts = {}) {
|
|
1649
1707
|
return this.sm.requestSupafoneApi("POST", "/api/v1/labs/phone-numbers/search", phoneNumberSearchPayload(opts));
|
|
@@ -1702,21 +1760,31 @@ class LabsPhoneNumbersNamespace {
|
|
|
1702
1760
|
* it to the supplied agent. This is the zero-Twilio-account happy path.
|
|
1703
1761
|
*/
|
|
1704
1762
|
async buyAndAssign(input) {
|
|
1763
|
+
const strategy = input.number_strategy ?? input.numberStrategy ?? (input.premium ? "premium" : "default_pool");
|
|
1705
1764
|
let phoneNumber = input.phoneNumber ?? input.phone_number ?? "";
|
|
1706
1765
|
if (!phoneNumber) {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1766
|
+
if (strategy === "default_pool") {
|
|
1767
|
+
const found = await this.pool();
|
|
1768
|
+
const areaCode = String(input.search?.areaCode ?? input.search?.area_code ?? "");
|
|
1769
|
+
phoneNumber = found.numbers.find((number) => number.available && (!areaCode || number.phone_number.startsWith(`+1${areaCode}`)))?.phone_number ?? "";
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1772
|
+
const found = await this.search({
|
|
1773
|
+
...(input.search ?? {}),
|
|
1774
|
+
agencyId: input.agencyId ?? input.agency_id ?? input.search?.agencyId,
|
|
1775
|
+
limit: input.search?.limit ?? 1,
|
|
1776
|
+
});
|
|
1777
|
+
phoneNumber = found.numbers[0]?.phone_number ?? "";
|
|
1778
|
+
}
|
|
1713
1779
|
if (!phoneNumber) {
|
|
1714
|
-
|
|
1780
|
+
const source = strategy === "default_pool" ? "shared developer" : "Supafone-managed";
|
|
1781
|
+
throw new SupafoneLabsError(`No ${source} phone numbers matched the request`);
|
|
1715
1782
|
}
|
|
1716
1783
|
}
|
|
1717
1784
|
return this.buy({
|
|
1718
1785
|
...input,
|
|
1719
1786
|
phoneNumber,
|
|
1787
|
+
numberStrategy: strategy,
|
|
1720
1788
|
telephony: input.telephony ?? { mode: "supafone_managed", provider: "supafone" },
|
|
1721
1789
|
});
|
|
1722
1790
|
}
|
|
@@ -1974,6 +2042,7 @@ function campaignSettingsPayload(settings, mode) {
|
|
|
1974
2042
|
}
|
|
1975
2043
|
function labsAgentPayload(input) {
|
|
1976
2044
|
const fixedLanguage = input.preferred_language ?? input.preferredLanguage ?? input.language;
|
|
2045
|
+
const supervisor = input.supervisor;
|
|
1977
2046
|
return compact({
|
|
1978
2047
|
agency_id: input.agency_id ?? input.agencyId,
|
|
1979
2048
|
agent_key: input.agent_key ?? input.agentKey,
|
|
@@ -2017,7 +2086,12 @@ function labsAgentPayload(input) {
|
|
|
2017
2086
|
email: input.email ? emailPayload(input.email) : undefined,
|
|
2018
2087
|
labs: input.labs ? labsPayload(input.labs) : undefined,
|
|
2019
2088
|
ultravox: input.ultravox ? ultravoxPayload(input.ultravox) : undefined,
|
|
2020
|
-
|
|
2089
|
+
supervisor: supervisor && typeof supervisor === "object" ? supervisorPayload(supervisor) : undefined,
|
|
2090
|
+
voice_watcher: typeof supervisor === "boolean"
|
|
2091
|
+
? supervisor
|
|
2092
|
+
: supervisor && typeof supervisor === "object"
|
|
2093
|
+
? supervisor.enabled ?? true
|
|
2094
|
+
: input.voice_watcher ?? input.voiceWatcher,
|
|
2021
2095
|
voice_watcher_model: input.voice_watcher_model ?? input.voiceWatcherModel,
|
|
2022
2096
|
metadata: labsAgentMetadataPayload(input),
|
|
2023
2097
|
});
|
|
@@ -2144,8 +2218,10 @@ function callStagesPayload(input) {
|
|
|
2144
2218
|
return explicit.map(callStagePayload);
|
|
2145
2219
|
if (explicit === false || auto === false)
|
|
2146
2220
|
return false;
|
|
2147
|
-
if (explicit === "
|
|
2221
|
+
if (explicit === "managed" || explicit === "template" || explicit === "off")
|
|
2148
2222
|
return explicit;
|
|
2223
|
+
if (explicit === "oracle")
|
|
2224
|
+
return "managed";
|
|
2149
2225
|
// Omitted means the private Supafone API generates and compiles the plan.
|
|
2150
2226
|
return undefined;
|
|
2151
2227
|
}
|
|
@@ -2427,9 +2503,19 @@ function artifactsPayload(input) {
|
|
|
2427
2503
|
});
|
|
2428
2504
|
}
|
|
2429
2505
|
function labsPayload(input) {
|
|
2506
|
+
const nestedSupervisor = input.supervisor && typeof input.supervisor === "object"
|
|
2507
|
+
? input.supervisor
|
|
2508
|
+
: input.provider
|
|
2509
|
+
? input
|
|
2510
|
+
: undefined;
|
|
2430
2511
|
return compact({
|
|
2431
2512
|
enabled: input.enabled,
|
|
2432
|
-
|
|
2513
|
+
supervisor: nestedSupervisor ? supervisorPayload(nestedSupervisor) : undefined,
|
|
2514
|
+
voice_watcher: typeof input.supervisor === "boolean"
|
|
2515
|
+
? input.supervisor
|
|
2516
|
+
: nestedSupervisor
|
|
2517
|
+
? nestedSupervisor.enabled ?? true
|
|
2518
|
+
: input.voice_watcher ?? input.voiceWatcher,
|
|
2433
2519
|
api_key: input.api_key ?? input.apiKey,
|
|
2434
2520
|
model: input.model,
|
|
2435
2521
|
mode: input.mode,
|
|
@@ -2441,6 +2527,16 @@ function labsPayload(input) {
|
|
|
2441
2527
|
label: input.label,
|
|
2442
2528
|
});
|
|
2443
2529
|
}
|
|
2530
|
+
function supervisorPayload(input) {
|
|
2531
|
+
return compact({
|
|
2532
|
+
enabled: input.enabled,
|
|
2533
|
+
mode: input.mode,
|
|
2534
|
+
provider: input.provider,
|
|
2535
|
+
model: input.model,
|
|
2536
|
+
api_key: input.api_key ?? input.apiKey,
|
|
2537
|
+
api_key_configured: input.api_key_configured ?? input.apiKeyConfigured,
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2444
2540
|
function ultravoxPayload(input) {
|
|
2445
2541
|
return compact({
|
|
2446
2542
|
model: input.model,
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
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
6
|
* tools, recordings, transcripts, widgets, and Supafone Supervisor. It also
|
|
7
|
-
* includes
|
|
7
|
+
* includes Supafone Supervisor, hosted TTS/STT, live multilingual
|
|
8
8
|
* transcription, telemetry, agent builder, and objective-driven optimizer.
|
|
9
9
|
*
|
|
10
10
|
* Works in Node 18+ (native fetch/WebSocket) and the browser.
|
|
@@ -49,7 +49,7 @@ export interface SupafoneLabsOptions {
|
|
|
49
49
|
* (or structured messages) first classifies the finished call against the
|
|
50
50
|
* agent's objective — generating labels (achieved/missed, per-criterion
|
|
51
51
|
* verdicts, failure reasons) — and files the enriched report server-side.
|
|
52
|
-
* Billed one
|
|
52
|
+
* Billed one Supervisor inference per analyzed call; reports without a transcript
|
|
53
53
|
* fall back to the plain zero-billed report.
|
|
54
54
|
*/
|
|
55
55
|
postCallAnalysis?: boolean;
|
|
@@ -66,18 +66,22 @@ export interface ChatMessage {
|
|
|
66
66
|
role: "system" | "user" | "assistant";
|
|
67
67
|
content: string;
|
|
68
68
|
}
|
|
69
|
-
export interface
|
|
69
|
+
export interface SupervisorRequest {
|
|
70
70
|
messages: ChatMessage[];
|
|
71
|
-
/** Any
|
|
71
|
+
/** Any supported managed/BYOK model id, or the alias "supafone-supervisor". */
|
|
72
72
|
model?: string;
|
|
73
73
|
maxTokens?: number;
|
|
74
74
|
temperature?: number;
|
|
75
75
|
}
|
|
76
|
-
export interface
|
|
76
|
+
export interface SupervisorResult {
|
|
77
77
|
text: string;
|
|
78
78
|
model: string;
|
|
79
79
|
usage?: Record<string, number>;
|
|
80
80
|
}
|
|
81
|
+
/** @deprecated Use SupervisorRequest. */
|
|
82
|
+
export type OracleRequest = SupervisorRequest;
|
|
83
|
+
/** @deprecated Use SupervisorResult. */
|
|
84
|
+
export type OracleResult = SupervisorResult;
|
|
81
85
|
export interface WhisperOptions {
|
|
82
86
|
model?: string;
|
|
83
87
|
/** Extra operator rules folded into the coaching system prompt. */
|
|
@@ -195,7 +199,7 @@ export interface LabsCallStage {
|
|
|
195
199
|
next_stages?: string[];
|
|
196
200
|
metadata?: Record<string, unknown>;
|
|
197
201
|
}
|
|
198
|
-
export type LabsStageGeneration = "
|
|
202
|
+
export type LabsStageGeneration = "managed" | "template" | "off" | "oracle";
|
|
199
203
|
export interface LabsCallPlan {
|
|
200
204
|
version: "supafone_call_plan_v1" | string;
|
|
201
205
|
summary: string;
|
|
@@ -440,6 +444,8 @@ export interface LabsProviderByokConfig {
|
|
|
440
444
|
provider?: string;
|
|
441
445
|
apiKey?: string;
|
|
442
446
|
api_key?: string;
|
|
447
|
+
apiKeyConfigured?: boolean;
|
|
448
|
+
api_key_configured?: boolean;
|
|
443
449
|
credentials?: Record<string, unknown>;
|
|
444
450
|
settings?: Record<string, unknown>;
|
|
445
451
|
model?: string;
|
|
@@ -629,15 +635,29 @@ export interface LabsArtifactsConfig {
|
|
|
629
635
|
retention_days?: number;
|
|
630
636
|
metadata?: Record<string, unknown>;
|
|
631
637
|
}
|
|
638
|
+
export type LabsSupervisorProvider = "anthropic" | "claude" | "openai" | "gemini" | "google" | "openrouter" | "groq" | "cerebras";
|
|
639
|
+
export interface LabsByokSupervisorConfig {
|
|
640
|
+
enabled?: boolean;
|
|
641
|
+
mode?: "managed" | "supafone_managed" | "byok";
|
|
642
|
+
provider?: LabsSupervisorProvider;
|
|
643
|
+
model?: string;
|
|
644
|
+
apiKey?: string;
|
|
645
|
+
api_key?: string;
|
|
646
|
+
apiKeyConfigured?: boolean;
|
|
647
|
+
api_key_configured?: boolean;
|
|
648
|
+
}
|
|
632
649
|
export interface LabsSupervisorConfig {
|
|
633
650
|
enabled?: boolean;
|
|
634
|
-
supervisor?: boolean;
|
|
651
|
+
supervisor?: boolean | LabsByokSupervisorConfig;
|
|
635
652
|
/** @deprecated Use supervisor. */
|
|
636
653
|
voiceWatcher?: boolean;
|
|
637
654
|
/** @deprecated Use supervisor. */
|
|
638
655
|
voice_watcher?: boolean;
|
|
639
656
|
apiKey?: string;
|
|
640
657
|
api_key?: string;
|
|
658
|
+
apiKeyConfigured?: boolean;
|
|
659
|
+
api_key_configured?: boolean;
|
|
660
|
+
provider?: LabsSupervisorProvider;
|
|
641
661
|
model?: string;
|
|
642
662
|
mode?: "supafone_managed" | "byok" | string;
|
|
643
663
|
managedInfrastructure?: boolean;
|
|
@@ -869,7 +889,7 @@ export interface CreateLabsAgentRequest {
|
|
|
869
889
|
email?: LabsEmailConfig;
|
|
870
890
|
labs?: LabsSupervisorConfig;
|
|
871
891
|
ultravox?: LabsUltravoxRuntime;
|
|
872
|
-
supervisor?: boolean;
|
|
892
|
+
supervisor?: boolean | LabsByokSupervisorConfig;
|
|
873
893
|
/** @deprecated Use supervisor. */
|
|
874
894
|
voiceWatcher?: boolean;
|
|
875
895
|
/** @deprecated Use supervisor. */
|
|
@@ -1192,6 +1212,44 @@ export interface LabsPhoneNumberListResponse {
|
|
|
1192
1212
|
numbers: LabsPhoneNumberRecord[];
|
|
1193
1213
|
telephony?: Record<string, unknown>;
|
|
1194
1214
|
}
|
|
1215
|
+
export type LabsSharedPhonePoolStatus = "available" | "in_use" | "cooldown" | "reserved" | "unavailable";
|
|
1216
|
+
export interface LabsSharedPhonePoolNumber {
|
|
1217
|
+
id: string;
|
|
1218
|
+
pool_id: string;
|
|
1219
|
+
pool_name: string;
|
|
1220
|
+
phone_number: string;
|
|
1221
|
+
display_name: string;
|
|
1222
|
+
provider: string;
|
|
1223
|
+
status: LabsSharedPhonePoolStatus;
|
|
1224
|
+
status_color: "green" | "red";
|
|
1225
|
+
available: boolean;
|
|
1226
|
+
reason: string;
|
|
1227
|
+
health: string;
|
|
1228
|
+
capabilities: string[];
|
|
1229
|
+
cooldown_until?: string | null;
|
|
1230
|
+
updated_at: string;
|
|
1231
|
+
}
|
|
1232
|
+
export interface LabsSharedPhonePoolSnapshot {
|
|
1233
|
+
version: "developer_phone_pool_v1" | string;
|
|
1234
|
+
revision: string;
|
|
1235
|
+
counts: {
|
|
1236
|
+
total: number;
|
|
1237
|
+
available: number;
|
|
1238
|
+
in_use: number;
|
|
1239
|
+
unavailable: number;
|
|
1240
|
+
};
|
|
1241
|
+
numbers: LabsSharedPhonePoolNumber[];
|
|
1242
|
+
stream?: {
|
|
1243
|
+
url: string;
|
|
1244
|
+
token: string;
|
|
1245
|
+
expires_in_seconds: number;
|
|
1246
|
+
protocol: "developer_phone_pool_v1" | string;
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
export interface LabsPhonePoolStreamOptions {
|
|
1250
|
+
/** Inject a WebSocket implementation for Node versions without a global WebSocket. */
|
|
1251
|
+
WebSocketImpl?: typeof WebSocket;
|
|
1252
|
+
}
|
|
1195
1253
|
export interface LabsPhoneNumberProvisionRequest {
|
|
1196
1254
|
agencyId?: string;
|
|
1197
1255
|
agency_id?: string;
|
|
@@ -1414,6 +1472,8 @@ export interface BuilderChatResult {
|
|
|
1414
1472
|
emotion?: string;
|
|
1415
1473
|
language?: string;
|
|
1416
1474
|
intent?: string;
|
|
1475
|
+
supervisor_ms?: number;
|
|
1476
|
+
/** @deprecated Use supervisor_ms. */
|
|
1417
1477
|
oracle_ms?: number;
|
|
1418
1478
|
standing_version?: number;
|
|
1419
1479
|
}
|
|
@@ -1455,7 +1515,9 @@ export interface QASuiteResult {
|
|
|
1455
1515
|
passed: number;
|
|
1456
1516
|
avg_ssr_score: number;
|
|
1457
1517
|
ssr_histogram: Record<SSRLabel, number>;
|
|
1458
|
-
|
|
1518
|
+
supervisor_inferences_billed?: number;
|
|
1519
|
+
/** @deprecated Legacy server field. */
|
|
1520
|
+
oracle_calls_billed?: number;
|
|
1459
1521
|
};
|
|
1460
1522
|
}
|
|
1461
1523
|
export interface QAResult {
|
|
@@ -1484,7 +1546,9 @@ export interface QAResult {
|
|
|
1484
1546
|
passed_supervised: number;
|
|
1485
1547
|
passed_unsupervised: number;
|
|
1486
1548
|
avg_lift: number;
|
|
1487
|
-
|
|
1549
|
+
supervisor_inferences_billed?: number;
|
|
1550
|
+
/** @deprecated Legacy server field. */
|
|
1551
|
+
oracle_calls_billed?: number;
|
|
1488
1552
|
};
|
|
1489
1553
|
}
|
|
1490
1554
|
export type TesterScenario = "price_probe" | "false_booking" | "language_switch" | "distressed";
|
|
@@ -1677,8 +1741,10 @@ export declare class SupafoneLabs {
|
|
|
1677
1741
|
industry?: string;
|
|
1678
1742
|
apply?: boolean;
|
|
1679
1743
|
}): Promise<GenerateIntakeResult>;
|
|
1680
|
-
/** Raw
|
|
1681
|
-
|
|
1744
|
+
/** Raw Supervisor completion with either Supafone-managed or BYOK inference. */
|
|
1745
|
+
completeWithSupervisor(req: SupervisorRequest): Promise<SupervisorResult>;
|
|
1746
|
+
/** @deprecated Use completeWithSupervisor(). */
|
|
1747
|
+
oracle(req: SupervisorRequest): Promise<SupervisorResult>;
|
|
1682
1748
|
/**
|
|
1683
1749
|
* The one-liner: hand it the running transcript, get back a silent directive
|
|
1684
1750
|
* (empty string when the agent is doing fine).
|
|
@@ -1709,7 +1775,7 @@ export declare class SupafoneLabs {
|
|
|
1709
1775
|
liveTranscribe(opts?: LiveTranscribeOptions): LiveTranscription;
|
|
1710
1776
|
/** Remaining prepaid balance. */
|
|
1711
1777
|
balance(): Promise<Balance>;
|
|
1712
|
-
/** Today's usage
|
|
1778
|
+
/** Today's usage across Supervisor, TTS, STT, and managed runtime meters. */
|
|
1713
1779
|
usage(): Promise<UsageToday>;
|
|
1714
1780
|
/** The auditable whisper/billing log. */
|
|
1715
1781
|
logs(limit?: number): Promise<{
|
|
@@ -1732,7 +1798,7 @@ export declare class SupafoneLabs {
|
|
|
1732
1798
|
*
|
|
1733
1799
|
* With `postCallAnalysis: true` on the client and a transcript (or
|
|
1734
1800
|
* messages) present, the call is automatically classified first: the
|
|
1735
|
-
*
|
|
1801
|
+
* Supervisor labels it against the agent's objective (achieved/missed,
|
|
1736
1802
|
* per-criterion verdicts, failure reasons) and files the enriched report
|
|
1737
1803
|
* server-side. The generated labels come back on `analysis`. Analysis is
|
|
1738
1804
|
* best-effort — on any failure the plain zero-billed report still lands.
|
|
@@ -1743,10 +1809,10 @@ export declare class SupafoneLabs {
|
|
|
1743
1809
|
* objective and get labels back — achieved/missed, per-criterion verdicts,
|
|
1744
1810
|
* failure reasons, and the blended objective value. Files an enriched call
|
|
1745
1811
|
* report server-side (feeding optimizer.improve() and objective stats).
|
|
1746
|
-
* Billed one
|
|
1812
|
+
* Billed one Supervisor inference.
|
|
1747
1813
|
*/
|
|
1748
1814
|
classifyCall(input: ClassifyCallInput): Promise<CallClassification>;
|
|
1749
|
-
/** Available
|
|
1815
|
+
/** Available managed and BYOK Supervisor model ids. */
|
|
1750
1816
|
models(): Promise<string[]>;
|
|
1751
1817
|
/** Available TTS voice ids. */
|
|
1752
1818
|
voices(): Promise<string[]>;
|
|
@@ -2065,6 +2131,10 @@ declare class LabsNamespace {
|
|
|
2065
2131
|
}
|
|
2066
2132
|
export type LabsBillingCheckoutKind = "plan" | "credits" | "number_addon";
|
|
2067
2133
|
export interface LabsBillingCheckoutInput {
|
|
2134
|
+
/** Current prepaid managed-minute package SKU. */
|
|
2135
|
+
sku?: string;
|
|
2136
|
+
packageSku?: string;
|
|
2137
|
+
package_sku?: string;
|
|
2068
2138
|
kind?: LabsBillingCheckoutKind;
|
|
2069
2139
|
planKey?: "developer" | "growth" | "scale" | string;
|
|
2070
2140
|
plan_key?: string;
|
|
@@ -2079,10 +2149,16 @@ export interface LabsBillingCheckoutInput {
|
|
|
2079
2149
|
cancel_url?: string;
|
|
2080
2150
|
}
|
|
2081
2151
|
export interface LabsBillingCheckoutResponse {
|
|
2082
|
-
status
|
|
2083
|
-
checkout_session_id
|
|
2152
|
+
status?: "requires_payment" | "pending" | "paid" | string;
|
|
2153
|
+
checkout_session_id?: string;
|
|
2084
2154
|
checkout_url?: string;
|
|
2085
|
-
|
|
2155
|
+
/** Canonical minute-top-up Checkout URL. */
|
|
2156
|
+
url?: string;
|
|
2157
|
+
kind?: LabsBillingCheckoutKind | string;
|
|
2158
|
+
sku?: string;
|
|
2159
|
+
minutes?: number;
|
|
2160
|
+
amount_cents?: number;
|
|
2161
|
+
purchase_id?: string;
|
|
2086
2162
|
plan_key?: string | null;
|
|
2087
2163
|
number_strategy?: string | null;
|
|
2088
2164
|
phone_number?: string | null;
|
|
@@ -2095,6 +2171,8 @@ declare class LabsBillingNamespace {
|
|
|
2095
2171
|
constructor(sm: SupafoneLabs);
|
|
2096
2172
|
/** Start hosted Stripe Checkout. MCP callers should render checkout_url as a link. */
|
|
2097
2173
|
checkout(input?: LabsBillingCheckoutInput): Promise<LabsBillingCheckoutResponse>;
|
|
2174
|
+
/** Start Stripe Checkout for one prepaid managed-minute package. */
|
|
2175
|
+
topUp(sku?: string): Promise<LabsBillingCheckoutResponse>;
|
|
2098
2176
|
status(checkoutSessionId: string): Promise<LabsBillingCheckoutResponse>;
|
|
2099
2177
|
portal(): Promise<{
|
|
2100
2178
|
url: string;
|
|
@@ -2267,6 +2345,16 @@ declare class LabsPhoneNumbersNamespace {
|
|
|
2267
2345
|
constructor(sm: SupafoneLabs);
|
|
2268
2346
|
/** List numbers already owned by this Supafone account. */
|
|
2269
2347
|
list(opts?: LabsPhoneNumberListOptions): Promise<LabsPhoneNumberListResponse>;
|
|
2348
|
+
/**
|
|
2349
|
+
* Read the explicitly enrolled shared developer-number pool. This inventory
|
|
2350
|
+
* never infers customer or merely-unassigned numbers into the response.
|
|
2351
|
+
*/
|
|
2352
|
+
pool(): Promise<LabsSharedPhonePoolSnapshot>;
|
|
2353
|
+
/**
|
|
2354
|
+
* Connect to realtime pool state using a short-lived pool-only token. The
|
|
2355
|
+
* Supafone API key is never placed in the WebSocket URL.
|
|
2356
|
+
*/
|
|
2357
|
+
connectPool(opts?: LabsPhonePoolStreamOptions): Promise<WebSocket>;
|
|
2270
2358
|
/** Search Supafone-managed inventory. This uses Supafone's master telephony account. */
|
|
2271
2359
|
search(opts?: LabsPhoneNumberSearchOptions): Promise<LabsPhoneNumberSearchResponse>;
|
|
2272
2360
|
/**
|