supafone-labs 0.5.0 → 0.5.3
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 +10 -7
- package/dist/cjs/index.d.ts +100 -25
- package/dist/cjs/index.js +78 -18
- package/dist/index.d.ts +100 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +210 -42
package/README.md
CHANGED
|
@@ -104,13 +104,13 @@ Supafone Labs has two main features:
|
|
|
104
104
|
|
|
105
105
|
- **Agent Factory**: create the complete hosted agent with managed provider
|
|
106
106
|
defaults and one Supafone API key.
|
|
107
|
-
- **
|
|
108
|
-
|
|
107
|
+
- **Supafone Supervisor**: attach live guidance, call scoring, and QA to a
|
|
108
|
+
hosted or BYOK agent.
|
|
109
109
|
|
|
110
110
|
The daily developer workflow is documented in
|
|
111
111
|
[Developer Workflows](../gitbook/developer-workflows.md): one normalized live
|
|
112
112
|
voice catalog, fixed BCP-47 language selection, automatic voice compatibility
|
|
113
|
-
filtering, structured
|
|
113
|
+
filtering, structured Supervisor directives, and the same configuration model
|
|
114
114
|
across TypeScript and Python. Fixed language selection does not enable
|
|
115
115
|
mid-call language or voice switching.
|
|
116
116
|
|
|
@@ -166,10 +166,9 @@ import { Supafone } from "supafone-labs";
|
|
|
166
166
|
const supafone = new Supafone({
|
|
167
167
|
apiKey: process.env.SUPAFONE_LABS_API_KEY || process.env.SUPAFONE_API_KEY!,
|
|
168
168
|
supafoneApiKey: process.env.SUPAFONE_API_KEY!,
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
voiceWatcher: true,
|
|
169
|
+
// Supafone Supervisor is on by default for live guidance, QA, and scoring.
|
|
170
|
+
// Set false only when you intentionally need an unsupervised agent.
|
|
171
|
+
supervisor: true,
|
|
173
172
|
// Defaults to https://api.supafone.ai. Override for staging/local tests.
|
|
174
173
|
// supafoneApiBaseUrl: "http://localhost:8000",
|
|
175
174
|
});
|
|
@@ -535,6 +534,10 @@ and `const { Supafone } = require("supafone-labs")` both work, with full types.
|
|
|
535
534
|
| `labs.capabilities()` | `GET /api/v1/labs/capabilities` on the Supafone API |
|
|
536
535
|
| `labs.agents.create/createInbound/createOutbound/list/get` | `/api/v1/labs/agents*` on the Supafone API |
|
|
537
536
|
| `labs.agents.createInboundWithNumber/createOutboundWithNumber` | Agent creation plus Supafone-managed number buy/assign |
|
|
537
|
+
| `labs.agents.update/readiness/activate/pause/delete` | Durable agent lifecycle using `agent_key` |
|
|
538
|
+
| `labs.agents.startWebRtcCall` | Browser voice test using the durable `agent.id` |
|
|
539
|
+
| `labs.agents.syncKnowledge/detachWebsiteKnowledge/reindexKnowledge` | Managed website corpus lifecycle using `agent.id` |
|
|
540
|
+
| `labs.agents.uploadKnowledgeDocument/deleteKnowledgeDocument/chatKnowledge` | Account-isolated document and grounded-query methods |
|
|
538
541
|
| `labs.phoneNumbers.search/buy/assign/list/buyAndAssign` | `/api/v1/labs/phone-numbers*` |
|
|
539
542
|
| `labs.billing.checkout/status/portal` | Stripe-hosted Checkout, payment polling, and Customer Portal |
|
|
540
543
|
| `labs.telephony.get/configure/useSupafoneManaged` | `/api/v1/labs/telephony` |
|
package/dist/cjs/index.d.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
|
*
|
|
@@ -53,15 +53,13 @@ export interface SupafoneLabsOptions {
|
|
|
53
53
|
* fall back to the plain zero-billed report.
|
|
54
54
|
*/
|
|
55
55
|
postCallAnalysis?: boolean;
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
* agent with no watcher. `voice_watcher` (snake) and the deprecated `labs`
|
|
60
|
-
* are accepted aliases, resolved voiceWatcher > voice_watcher > labs > true.
|
|
61
|
-
*/
|
|
56
|
+
/** Enable Supafone Supervisor live guidance, QA, and scoring (default true). */
|
|
57
|
+
supervisor?: boolean;
|
|
58
|
+
/** @deprecated Use supervisor. */
|
|
62
59
|
voiceWatcher?: boolean;
|
|
60
|
+
/** @deprecated Use supervisor. */
|
|
63
61
|
voice_watcher?: boolean;
|
|
64
|
-
/** @deprecated
|
|
62
|
+
/** @deprecated Use supervisor. */
|
|
65
63
|
labs?: boolean;
|
|
66
64
|
}
|
|
67
65
|
export interface ChatMessage {
|
|
@@ -87,7 +85,9 @@ export interface WhisperOptions {
|
|
|
87
85
|
maxTokens?: number;
|
|
88
86
|
temperature?: number;
|
|
89
87
|
}
|
|
90
|
-
export type
|
|
88
|
+
export type SupervisorDirectiveKind = "empathy" | "tactical" | "guardrail" | "mixed";
|
|
89
|
+
/** @deprecated Use SupervisorDirectiveKind. */
|
|
90
|
+
export type SecondMindDirectiveKind = SupervisorDirectiveKind;
|
|
91
91
|
export interface DirectiveTextControl {
|
|
92
92
|
enabled?: boolean;
|
|
93
93
|
instructions?: string;
|
|
@@ -102,7 +102,7 @@ export interface DirectiveListControl {
|
|
|
102
102
|
itemMaxChars?: number;
|
|
103
103
|
item_max_chars?: number;
|
|
104
104
|
}
|
|
105
|
-
/** Serializable controls for each field generated by
|
|
105
|
+
/** Serializable controls for each field generated by Supafone Supervisor. */
|
|
106
106
|
export interface DirectiveContract {
|
|
107
107
|
empathyDirective?: DirectiveTextControl;
|
|
108
108
|
empathy_directive?: DirectiveTextControl;
|
|
@@ -115,27 +115,29 @@ export interface DirectiveContract {
|
|
|
115
115
|
language_mode?: "caller" | "model" | "fixed";
|
|
116
116
|
fixedLanguage?: string;
|
|
117
117
|
fixed_language?: string;
|
|
118
|
-
allowedKinds?:
|
|
119
|
-
allowed_kinds?:
|
|
118
|
+
allowedKinds?: SupervisorDirectiveKind[];
|
|
119
|
+
allowed_kinds?: SupervisorDirectiveKind[];
|
|
120
120
|
confidenceThreshold?: number;
|
|
121
121
|
confidence_threshold?: number;
|
|
122
122
|
operatorGuardrails?: string[];
|
|
123
123
|
operator_guardrails?: string[];
|
|
124
124
|
}
|
|
125
|
-
export interface
|
|
125
|
+
export interface SupervisorDirective {
|
|
126
126
|
empathy_directive: string;
|
|
127
127
|
tactical_directive: string;
|
|
128
128
|
surface_facts: string[];
|
|
129
129
|
guardrails: string[];
|
|
130
130
|
language: string;
|
|
131
131
|
confidence: number;
|
|
132
|
-
kind:
|
|
132
|
+
kind: SupervisorDirectiveKind;
|
|
133
133
|
}
|
|
134
|
+
/** @deprecated Use SupervisorDirective. */
|
|
135
|
+
export type SecondMindDirective = SupervisorDirective;
|
|
134
136
|
export interface StructuredWhisperOptions extends WhisperOptions {
|
|
135
137
|
directiveContract?: DirectiveContract;
|
|
136
138
|
directive_contract?: DirectiveContract;
|
|
137
139
|
/** Local final say: revise or suppress the generated directive before use. */
|
|
138
|
-
transform?: (directive:
|
|
140
|
+
transform?: (directive: SupervisorDirective) => SupervisorDirective | null | Promise<SupervisorDirective | null>;
|
|
139
141
|
}
|
|
140
142
|
export interface Balance {
|
|
141
143
|
plan: string;
|
|
@@ -257,16 +259,37 @@ export interface LabsVoiceProviderTraits {
|
|
|
257
259
|
is_public?: boolean | null;
|
|
258
260
|
is_owner?: boolean | null;
|
|
259
261
|
}
|
|
262
|
+
/** Stable provider presentation metadata returned by the hosted catalog. */
|
|
263
|
+
export interface LabsVoiceProviderBrand {
|
|
264
|
+
/** Canonical provider key used for filtering and grouping. */
|
|
265
|
+
key: string;
|
|
266
|
+
/** Human-readable provider/company name. */
|
|
267
|
+
name: string;
|
|
268
|
+
/** Stable local asset slug when Supafone has an official provider mark. */
|
|
269
|
+
logo_slug?: string | null;
|
|
270
|
+
/** Absolute, browser-ready provider logo URL. */
|
|
271
|
+
logo_url?: string | null;
|
|
272
|
+
/** Provider's official product or company website. */
|
|
273
|
+
website_url?: string | null;
|
|
274
|
+
}
|
|
260
275
|
export interface LabsVoiceCatalogItem {
|
|
261
276
|
/** Stable runtime reference, including provider prefix when required. */
|
|
262
277
|
id: string;
|
|
263
278
|
voice_id: string;
|
|
264
279
|
/** Human-readable provider display name. */
|
|
265
280
|
provider: string;
|
|
281
|
+
/** Canonical brand display name for the synthesis provider. */
|
|
282
|
+
provider_label?: string;
|
|
283
|
+
/** Browser-ready official provider mark, or null for an unknown provider. */
|
|
284
|
+
provider_logo_url?: string | null;
|
|
285
|
+
/** Branding for the provider that renders the voice. */
|
|
286
|
+
provider_brand?: LabsVoiceProviderBrand;
|
|
266
287
|
/** Canonical SDK/runtime provider key. */
|
|
267
288
|
provider_key: string;
|
|
268
289
|
/** Runtime adapter used to place the voice on an Ultravox call. */
|
|
269
290
|
runtime_provider_key: string;
|
|
291
|
+
/** Branding for the realtime runtime, which can differ from synthesis. */
|
|
292
|
+
runtime_provider_brand?: LabsVoiceProviderBrand;
|
|
270
293
|
/** Actual TTS engine behind the voice (can differ for Ultravox built-ins). */
|
|
271
294
|
synthesis_provider_key: string;
|
|
272
295
|
/** Raw identifier used by the provider API. */
|
|
@@ -558,9 +581,12 @@ export interface LabsArtifactsConfig {
|
|
|
558
581
|
retention_days?: number;
|
|
559
582
|
metadata?: Record<string, unknown>;
|
|
560
583
|
}
|
|
561
|
-
export interface
|
|
584
|
+
export interface LabsSupervisorConfig {
|
|
562
585
|
enabled?: boolean;
|
|
586
|
+
supervisor?: boolean;
|
|
587
|
+
/** @deprecated Use supervisor. */
|
|
563
588
|
voiceWatcher?: boolean;
|
|
589
|
+
/** @deprecated Use supervisor. */
|
|
564
590
|
voice_watcher?: boolean;
|
|
565
591
|
apiKey?: string;
|
|
566
592
|
api_key?: string;
|
|
@@ -575,6 +601,8 @@ export interface LabsWatcherConfig {
|
|
|
575
601
|
provider_keys?: Record<string, unknown>;
|
|
576
602
|
label?: string;
|
|
577
603
|
}
|
|
604
|
+
/** @deprecated Use LabsSupervisorConfig. */
|
|
605
|
+
export type LabsWatcherConfig = LabsSupervisorConfig;
|
|
578
606
|
export interface LabsUltravoxRuntime {
|
|
579
607
|
model?: string;
|
|
580
608
|
temperature?: number;
|
|
@@ -789,9 +817,12 @@ export interface CreateLabsAgentRequest {
|
|
|
789
817
|
artifacts?: LabsArtifactsConfig;
|
|
790
818
|
compliance?: Record<string, unknown>;
|
|
791
819
|
tools?: LabsToolsConfig;
|
|
792
|
-
labs?:
|
|
820
|
+
labs?: LabsSupervisorConfig;
|
|
793
821
|
ultravox?: LabsUltravoxRuntime;
|
|
822
|
+
supervisor?: boolean;
|
|
823
|
+
/** @deprecated Use supervisor. */
|
|
794
824
|
voiceWatcher?: boolean;
|
|
825
|
+
/** @deprecated Use supervisor. */
|
|
795
826
|
voice_watcher?: boolean;
|
|
796
827
|
voiceWatcherModel?: string;
|
|
797
828
|
voice_watcher_model?: string;
|
|
@@ -835,6 +866,26 @@ export interface LabsAgentLifecycleResponse {
|
|
|
835
866
|
readiness?: LabsAgentReadiness;
|
|
836
867
|
[extra: string]: unknown;
|
|
837
868
|
}
|
|
869
|
+
export interface LabsKnowledgeSyncRequest {
|
|
870
|
+
websiteUrl?: string;
|
|
871
|
+
website_url?: string;
|
|
872
|
+
url?: string;
|
|
873
|
+
}
|
|
874
|
+
export interface LabsKnowledgeSyncResponse {
|
|
875
|
+
agent: LabsAgentResponse;
|
|
876
|
+
chunks_indexed?: number;
|
|
877
|
+
scraped_ok?: boolean;
|
|
878
|
+
last_error?: string | null;
|
|
879
|
+
website_detached?: boolean;
|
|
880
|
+
}
|
|
881
|
+
export interface LabsKnowledgeChatTurn {
|
|
882
|
+
role: "user" | "assistant";
|
|
883
|
+
content: string;
|
|
884
|
+
}
|
|
885
|
+
export interface LabsKnowledgeChatResponse {
|
|
886
|
+
reply: string;
|
|
887
|
+
sources: string[];
|
|
888
|
+
}
|
|
838
889
|
export interface LabsCapabilitiesResponse {
|
|
839
890
|
product: string;
|
|
840
891
|
api_namespace: string;
|
|
@@ -885,7 +936,10 @@ export interface LabsVoiceListResponse {
|
|
|
885
936
|
configured: boolean;
|
|
886
937
|
voice_count: number;
|
|
887
938
|
error?: string | null;
|
|
939
|
+
brand?: LabsVoiceProviderBrand;
|
|
888
940
|
}>;
|
|
941
|
+
/** Distinct synthesis-provider brands represented in the complete result. */
|
|
942
|
+
provider_brands?: LabsVoiceProviderBrand[];
|
|
889
943
|
provider_accounts?: Record<string, unknown>;
|
|
890
944
|
errors?: Record<string, string>;
|
|
891
945
|
catalog?: {
|
|
@@ -1474,7 +1528,9 @@ export declare class SupafoneLabs {
|
|
|
1474
1528
|
private readonly supafoneApiKey;
|
|
1475
1529
|
private readonly timeoutMs;
|
|
1476
1530
|
private readonly postCallAnalysis;
|
|
1477
|
-
/** Client default for
|
|
1531
|
+
/** Client default for Supafone Supervisor (live guidance + QA + scoring). */
|
|
1532
|
+
readonly supervisor: boolean;
|
|
1533
|
+
/** @deprecated Use supervisor. */
|
|
1478
1534
|
readonly voiceWatcher: boolean;
|
|
1479
1535
|
private sessionToken?;
|
|
1480
1536
|
private accountToken?;
|
|
@@ -1506,6 +1562,8 @@ export declare class SupafoneLabs {
|
|
|
1506
1562
|
request<T>(method: string, path: string, body?: unknown, useSession?: boolean): Promise<T>;
|
|
1507
1563
|
/** @internal Authenticated JSON request to the Supafone app API (`/api/v1/labs/*`). */
|
|
1508
1564
|
requestSupafoneApi<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
1565
|
+
/** @internal Multipart upload to the Supafone product API with the Labs key. */
|
|
1566
|
+
requestSupafoneUpload<T>(path: string, file: Uint8Array | ArrayBuffer | Blob, filename: string): Promise<T>;
|
|
1509
1567
|
/** @internal Authenticated binary request to the Supafone app API. */
|
|
1510
1568
|
requestSupafoneBinary(path: string): Promise<LabsVoicePreview>;
|
|
1511
1569
|
/**
|
|
@@ -1577,13 +1635,13 @@ export declare class SupafoneLabs {
|
|
|
1577
1635
|
*/
|
|
1578
1636
|
whisper(transcript: string, opts?: WhisperOptions): Promise<string>;
|
|
1579
1637
|
/**
|
|
1580
|
-
* Structured
|
|
1638
|
+
* Structured Supafone Supervisor guidance with developer-controlled field policy.
|
|
1581
1639
|
* Returns null when JSON is invalid, evidence misses the confidence gate,
|
|
1582
1640
|
* the generated kind is disallowed, or the local transform suppresses it.
|
|
1583
1641
|
*/
|
|
1584
|
-
whisperStructured(transcript: string, opts?: StructuredWhisperOptions): Promise<
|
|
1642
|
+
whisperStructured(transcript: string, opts?: StructuredWhisperOptions): Promise<SupervisorDirective | null>;
|
|
1585
1643
|
/** Alias that reads naturally in applications building their own watcher loop. */
|
|
1586
|
-
directive(transcript: string, opts?: StructuredWhisperOptions): Promise<
|
|
1644
|
+
directive(transcript: string, opts?: StructuredWhisperOptions): Promise<SupervisorDirective | null>;
|
|
1587
1645
|
/** Hosted TTS — returns raw audio bytes (WAV/PCM per voice). */
|
|
1588
1646
|
tts(text: string, voice?: string): Promise<Uint8Array>;
|
|
1589
1647
|
/** Convenience alias for voice preview UI/buttons. */
|
|
@@ -2006,10 +2064,9 @@ declare class LabsAgentsNamespace {
|
|
|
2006
2064
|
generateCallStages(input: CreateLabsAgentRequest & {
|
|
2007
2065
|
description?: string;
|
|
2008
2066
|
}): Promise<LabsCallPlan>;
|
|
2009
|
-
/** Default the agent onto the client's
|
|
2010
|
-
*
|
|
2011
|
-
|
|
2012
|
-
private withVoiceWatcher;
|
|
2067
|
+
/** Default the agent onto the client's Supafone Supervisor setting unless the
|
|
2068
|
+
* caller set it explicitly. Legacy wire fields remain unchanged. */
|
|
2069
|
+
private withSupervisor;
|
|
2013
2070
|
/** Create an inbound receptionist/intake agent. No Twilio account is required. */
|
|
2014
2071
|
createInbound(input: CreateLabsAgentRequest): Promise<CreateLabsAgentResponse>;
|
|
2015
2072
|
/** Create an outbound sales/speed-to-lead/campaign agent. No Twilio account is required. */
|
|
@@ -2030,12 +2087,30 @@ declare class LabsAgentsNamespace {
|
|
|
2030
2087
|
get(agentKey: string, opts?: GetLabsAgentOptions): Promise<GetLabsAgentResponse>;
|
|
2031
2088
|
/** Update an existing durable agent without changing omitted fields. */
|
|
2032
2089
|
update(agentKey: string, input: UpdateLabsAgentRequest, opts?: GetLabsAgentOptions): Promise<LabsAgentLifecycleResponse>;
|
|
2090
|
+
/** Scrape a website and rebuild this agent's managed knowledge corpus. */
|
|
2091
|
+
syncKnowledge(agentId: string, input?: LabsKnowledgeSyncRequest): Promise<LabsKnowledgeSyncResponse>;
|
|
2092
|
+
/** Remove website knowledge while preserving uploaded documents and notes. */
|
|
2093
|
+
detachWebsiteKnowledge(agentId: string): Promise<LabsKnowledgeSyncResponse>;
|
|
2033
2094
|
/** Ask the managed server whether this agent is ready to activate. */
|
|
2034
2095
|
readiness(agentKey: string, opts?: GetLabsAgentOptions): Promise<LabsAgentReadiness>;
|
|
2035
2096
|
/** Activate a ready hosted agent. */
|
|
2036
2097
|
activate(agentKey: string, opts?: GetLabsAgentOptions): Promise<LabsAgentLifecycleResponse>;
|
|
2037
2098
|
/** Pause a hosted agent without deleting it. */
|
|
2038
2099
|
pause(agentKey: string, opts?: GetLabsAgentOptions): Promise<LabsAgentLifecycleResponse>;
|
|
2100
|
+
/** Start the native provider-neutral browser voice session for this agent. */
|
|
2101
|
+
startWebRtcCall(agentId: string): Promise<WebRtcCallResult>;
|
|
2102
|
+
/** Rebuild retrieval data from the agent's already saved knowledge sources. */
|
|
2103
|
+
reindexKnowledge(agentId: string): Promise<Record<string, unknown>>;
|
|
2104
|
+
/** Upload and index a txt, md, csv, or PDF knowledge document. */
|
|
2105
|
+
uploadKnowledgeDocument(agentId: string, file: Uint8Array | ArrayBuffer | Blob, filename: string): Promise<{
|
|
2106
|
+
agent: LabsAgentResponse;
|
|
2107
|
+
}>;
|
|
2108
|
+
/** Delete one document and rebuild the agent's managed corpus. */
|
|
2109
|
+
deleteKnowledgeDocument(agentId: string, documentId: string): Promise<{
|
|
2110
|
+
agent: LabsAgentResponse;
|
|
2111
|
+
}>;
|
|
2112
|
+
/** Ask a grounded question against the same corpus used during calls. */
|
|
2113
|
+
chatKnowledge(agentId: string, message: string, history?: LabsKnowledgeChatTurn[]): Promise<LabsKnowledgeChatResponse>;
|
|
2039
2114
|
/** Delete an agent. Optionally ask the backend to release assigned numbers. */
|
|
2040
2115
|
delete(agentKey: string, opts?: DeleteLabsAgentOptions): Promise<DeleteLabsAgentResponse>;
|
|
2041
2116
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
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
|
-
* tools, recordings, transcripts, widgets, and Supafone
|
|
7
|
+
* tools, recordings, transcripts, widgets, and Supafone Supervisor. It also
|
|
8
8
|
* includes the Labs cloud sidecar oracle, hosted TTS/STT, live multilingual
|
|
9
9
|
* transcription, telemetry, agent builder, and objective-driven optimizer.
|
|
10
10
|
*
|
|
@@ -159,11 +159,11 @@ class SupafoneLabsError extends Error {
|
|
|
159
159
|
exports.SupafoneLabsError = SupafoneLabsError;
|
|
160
160
|
const DEFAULT_BASE = "https://api.labs.supafone.ai";
|
|
161
161
|
const DEFAULT_SUPAFONE_API_BASE = "https://api.supafone.ai";
|
|
162
|
-
const COACH_SYSTEM = "You are the coaching core of a
|
|
162
|
+
const COACH_SYSTEM = "You are the coaching core of a supervisor for a live voice agent. Read the " +
|
|
163
163
|
"conversation and return ONE short, silent directive the agent reads but never " +
|
|
164
164
|
"speaks aloud — a correction or nudge, phrased imperatively. If nothing needs " +
|
|
165
165
|
"correcting, return an empty string.";
|
|
166
|
-
const STRUCTURED_COACH_SYSTEM = "You are the coaching core of a
|
|
166
|
+
const STRUCTURED_COACH_SYSTEM = "You are the coaching core of a supervisor for a live voice agent. Read the " +
|
|
167
167
|
"conversation and return ONLY one JSON object with exactly these keys: " +
|
|
168
168
|
"empathy_directive (string), tactical_directive (string), surface_facts (string[]), " +
|
|
169
169
|
"guardrails (string[]), language (short code), confidence (0-1), and kind " +
|
|
@@ -273,7 +273,9 @@ class SupafoneLabs {
|
|
|
273
273
|
supafoneApiKey;
|
|
274
274
|
timeoutMs;
|
|
275
275
|
postCallAnalysis;
|
|
276
|
-
/** Client default for
|
|
276
|
+
/** Client default for Supafone Supervisor (live guidance + QA + scoring). */
|
|
277
|
+
supervisor;
|
|
278
|
+
/** @deprecated Use supervisor. */
|
|
277
279
|
voiceWatcher;
|
|
278
280
|
sessionToken;
|
|
279
281
|
accountToken;
|
|
@@ -298,8 +300,9 @@ class SupafoneLabs {
|
|
|
298
300
|
this.appUrl = (opts.appUrl ?? "https://app.supafone.ai").replace(/\/$/, "");
|
|
299
301
|
this.timeoutMs = opts.timeoutMs ?? 30_000;
|
|
300
302
|
this.postCallAnalysis = opts.postCallAnalysis ?? false;
|
|
301
|
-
// Precedence:
|
|
302
|
-
this.
|
|
303
|
+
// Precedence: supervisor > legacy aliases > true.
|
|
304
|
+
this.supervisor = opts.supervisor ?? opts.voiceWatcher ?? opts.voice_watcher ?? opts.labs ?? true;
|
|
305
|
+
this.voiceWatcher = this.supervisor;
|
|
303
306
|
this.sessionToken = opts.sessionToken;
|
|
304
307
|
this.accountToken = opts.accountToken;
|
|
305
308
|
this.accountEmail = opts.accountEmail;
|
|
@@ -387,6 +390,33 @@ class SupafoneLabs {
|
|
|
387
390
|
clearTimeout(timer);
|
|
388
391
|
}
|
|
389
392
|
}
|
|
393
|
+
/** @internal Multipart upload to the Supafone product API with the Labs key. */
|
|
394
|
+
async requestSupafoneUpload(path, file, filename) {
|
|
395
|
+
const ctrl = new AbortController();
|
|
396
|
+
const timer = setTimeout(() => ctrl.abort(), Math.max(this.timeoutMs, 120_000));
|
|
397
|
+
try {
|
|
398
|
+
const safeFilename = filename.replace(/["\\\r\n]/g, "").slice(0, 120) || "document.txt";
|
|
399
|
+
const blob = file instanceof Blob ? file : new Blob([file]);
|
|
400
|
+
const form = new FormData();
|
|
401
|
+
form.append("file", blob, safeFilename);
|
|
402
|
+
const res = await fetch(this.supafoneApiBaseUrl + path, {
|
|
403
|
+
method: "POST",
|
|
404
|
+
signal: ctrl.signal,
|
|
405
|
+
headers: { Authorization: `Bearer ${this.supafoneApiKey}` },
|
|
406
|
+
body: form,
|
|
407
|
+
});
|
|
408
|
+
const text = await res.text();
|
|
409
|
+
const parsed = text ? safeJson(text) : {};
|
|
410
|
+
if (!res.ok) {
|
|
411
|
+
const detail = parsed?.detail ?? text ?? `HTTP ${res.status}`;
|
|
412
|
+
throw new SupafoneLabsError(`POST ${path}: ${detail}`, res.status, parsed);
|
|
413
|
+
}
|
|
414
|
+
return parsed;
|
|
415
|
+
}
|
|
416
|
+
finally {
|
|
417
|
+
clearTimeout(timer);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
390
420
|
/** @internal Authenticated binary request to the Supafone app API. */
|
|
391
421
|
async requestSupafoneBinary(path) {
|
|
392
422
|
const ctrl = new AbortController();
|
|
@@ -601,7 +631,7 @@ class SupafoneLabs {
|
|
|
601
631
|
return out.text.trim();
|
|
602
632
|
}
|
|
603
633
|
/**
|
|
604
|
-
* Structured
|
|
634
|
+
* Structured Supafone Supervisor guidance with developer-controlled field policy.
|
|
605
635
|
* Returns null when JSON is invalid, evidence misses the confidence gate,
|
|
606
636
|
* the generated kind is disallowed, or the local transform suppresses it.
|
|
607
637
|
*/
|
|
@@ -1147,7 +1177,7 @@ class LabsAgentsNamespace {
|
|
|
1147
1177
|
}
|
|
1148
1178
|
/** Spawn a durable hosted Supafone agent backed by Ultravox and Supafone-managed providers. */
|
|
1149
1179
|
create(input) {
|
|
1150
|
-
return this.sm.requestSupafoneApi("POST", "/api/v1/labs/agents", labsAgentPayload(this.
|
|
1180
|
+
return this.sm.requestSupafoneApi("POST", "/api/v1/labs/agents", labsAgentPayload(this.withSupervisor(input)));
|
|
1151
1181
|
}
|
|
1152
1182
|
/** Preview the exact validated call-plan contract the Supafone runtime executes. */
|
|
1153
1183
|
plan(input) {
|
|
@@ -1156,17 +1186,16 @@ class LabsAgentsNamespace {
|
|
|
1156
1186
|
generateCallStages(input) {
|
|
1157
1187
|
return this.plan(input);
|
|
1158
1188
|
}
|
|
1159
|
-
/** Default the agent onto the client's
|
|
1160
|
-
*
|
|
1161
|
-
|
|
1162
|
-
withVoiceWatcher(input) {
|
|
1189
|
+
/** Default the agent onto the client's Supafone Supervisor setting unless the
|
|
1190
|
+
* caller set it explicitly. Legacy wire fields remain unchanged. */
|
|
1191
|
+
withSupervisor(input) {
|
|
1163
1192
|
const out = { ...input };
|
|
1164
|
-
if (out.voice_watcher === undefined && out.voiceWatcher === undefined) {
|
|
1165
|
-
out.
|
|
1193
|
+
if (out.supervisor === undefined && out.voice_watcher === undefined && out.voiceWatcher === undefined) {
|
|
1194
|
+
out.supervisor = this.sm.supervisor;
|
|
1166
1195
|
}
|
|
1167
1196
|
const labs = out.labs;
|
|
1168
|
-
if (labs && labs.voice_watcher === undefined && labs.voiceWatcher === undefined) {
|
|
1169
|
-
out.labs = { ...labs,
|
|
1197
|
+
if (labs && labs.supervisor === undefined && labs.voice_watcher === undefined && labs.voiceWatcher === undefined) {
|
|
1198
|
+
out.labs = { ...labs, supervisor: this.sm.supervisor };
|
|
1170
1199
|
}
|
|
1171
1200
|
return out;
|
|
1172
1201
|
}
|
|
@@ -1258,6 +1287,14 @@ class LabsAgentsNamespace {
|
|
|
1258
1287
|
const suffix = q.toString() ? `?${q}` : "";
|
|
1259
1288
|
return this.sm.requestSupafoneApi("PATCH", `/api/v1/labs/agents/${encodeURIComponent(agentKey)}${suffix}`, labsAgentUpdatePayload(input));
|
|
1260
1289
|
}
|
|
1290
|
+
/** Scrape a website and rebuild this agent's managed knowledge corpus. */
|
|
1291
|
+
syncKnowledge(agentId, input = {}) {
|
|
1292
|
+
return this.sm.requestSupafoneApi("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/sync-knowledge`, { url: input.url ?? input.website_url ?? input.websiteUrl ?? "" });
|
|
1293
|
+
}
|
|
1294
|
+
/** Remove website knowledge while preserving uploaded documents and notes. */
|
|
1295
|
+
detachWebsiteKnowledge(agentId) {
|
|
1296
|
+
return this.sm.requestSupafoneApi("DELETE", `/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/website`);
|
|
1297
|
+
}
|
|
1261
1298
|
/** Ask the managed server whether this agent is ready to activate. */
|
|
1262
1299
|
readiness(agentKey, opts = {}) {
|
|
1263
1300
|
const q = new URLSearchParams();
|
|
@@ -1282,6 +1319,26 @@ class LabsAgentsNamespace {
|
|
|
1282
1319
|
const suffix = q.toString() ? `?${q}` : "";
|
|
1283
1320
|
return this.sm.requestSupafoneApi("POST", `/api/v1/labs/agents/${encodeURIComponent(agentKey)}/pause${suffix}`);
|
|
1284
1321
|
}
|
|
1322
|
+
/** Start the native provider-neutral browser voice session for this agent. */
|
|
1323
|
+
startWebRtcCall(agentId) {
|
|
1324
|
+
return this.sm.startWebRtcCall({ agentId });
|
|
1325
|
+
}
|
|
1326
|
+
/** Rebuild retrieval data from the agent's already saved knowledge sources. */
|
|
1327
|
+
reindexKnowledge(agentId) {
|
|
1328
|
+
return this.sm.requestSupafoneApi("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/reindex`);
|
|
1329
|
+
}
|
|
1330
|
+
/** Upload and index a txt, md, csv, or PDF knowledge document. */
|
|
1331
|
+
uploadKnowledgeDocument(agentId, file, filename) {
|
|
1332
|
+
return this.sm.requestSupafoneUpload(`/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/upload`, file, filename);
|
|
1333
|
+
}
|
|
1334
|
+
/** Delete one document and rebuild the agent's managed corpus. */
|
|
1335
|
+
deleteKnowledgeDocument(agentId, documentId) {
|
|
1336
|
+
return this.sm.requestSupafoneApi("DELETE", `/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/docs/${encodeURIComponent(documentId)}`);
|
|
1337
|
+
}
|
|
1338
|
+
/** Ask a grounded question against the same corpus used during calls. */
|
|
1339
|
+
chatKnowledge(agentId, message, history = []) {
|
|
1340
|
+
return this.sm.requestSupafoneApi("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/knowledge-chat`, { message, history });
|
|
1341
|
+
}
|
|
1285
1342
|
/** Delete an agent. Optionally ask the backend to release assigned numbers. */
|
|
1286
1343
|
delete(agentKey, opts = {}) {
|
|
1287
1344
|
const q = new URLSearchParams();
|
|
@@ -1959,7 +2016,7 @@ function labsAgentPayload(input) {
|
|
|
1959
2016
|
tools: input.tools ? toolsPayload(input.tools) : undefined,
|
|
1960
2017
|
labs: input.labs ? labsPayload(input.labs) : undefined,
|
|
1961
2018
|
ultravox: input.ultravox ? ultravoxPayload(input.ultravox) : undefined,
|
|
1962
|
-
voice_watcher: input.voice_watcher ?? input.voiceWatcher,
|
|
2019
|
+
voice_watcher: input.supervisor ?? input.voice_watcher ?? input.voiceWatcher,
|
|
1963
2020
|
voice_watcher_model: input.voice_watcher_model ?? input.voiceWatcherModel,
|
|
1964
2021
|
metadata: labsAgentMetadataPayload(input),
|
|
1965
2022
|
});
|
|
@@ -2192,6 +2249,9 @@ function voicePayload(input) {
|
|
|
2192
2249
|
function languageProfilesPayload(input) {
|
|
2193
2250
|
if (!Array.isArray(input))
|
|
2194
2251
|
return undefined;
|
|
2252
|
+
if (input.length > 4) {
|
|
2253
|
+
throw new SupafoneLabsError("languageProfiles supports at most four profiles");
|
|
2254
|
+
}
|
|
2195
2255
|
const profiles = input.map((profile) => compact({
|
|
2196
2256
|
language: profile.language,
|
|
2197
2257
|
language_hint: profile.language_hint ?? profile.languageHint,
|
|
@@ -2357,7 +2417,7 @@ function artifactsPayload(input) {
|
|
|
2357
2417
|
function labsPayload(input) {
|
|
2358
2418
|
return compact({
|
|
2359
2419
|
enabled: input.enabled,
|
|
2360
|
-
voice_watcher: input.voice_watcher ?? input.voiceWatcher,
|
|
2420
|
+
voice_watcher: input.supervisor ?? input.voice_watcher ?? input.voiceWatcher,
|
|
2361
2421
|
api_key: input.api_key ?? input.apiKey,
|
|
2362
2422
|
model: input.model,
|
|
2363
2423
|
mode: input.mode,
|