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 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
- - **Self-healing watcher**: enable `labs.enabled` to attach the Supafone Labs
108
- second mind to a hosted or BYOK agent.
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 SecondMind directives, and the same configuration model
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
- // voiceWatcher is on by default (also accepts voice_watcher; deprecated: labs).
170
- // Every provisioned agent runs under the Voice Watcher framework (live
171
- // supervision + QA + call scoring). Set false for a raw agent.
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` |
@@ -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 Pro watcher. It also
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
- * Run provisioned agents under Supafone's Voice Watcher framework — live
58
- * supervision, QA, and call scoring (default true). Set false for a raw
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 alias for voiceWatcher. */
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 SecondMindDirectiveKind = "empathy" | "tactical" | "guardrail" | "mixed";
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 SecondMind. */
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?: SecondMindDirectiveKind[];
119
- allowed_kinds?: SecondMindDirectiveKind[];
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 SecondMindDirective {
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: SecondMindDirectiveKind;
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: SecondMindDirective) => SecondMindDirective | null | Promise<SecondMindDirective | null>;
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 LabsWatcherConfig {
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?: LabsWatcherConfig;
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 the Voice Watcher framework (supervision + QA + scoring). */
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 SecondMind guidance with developer-controlled field policy.
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<SecondMindDirective | null>;
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<SecondMindDirective | null>;
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 Voice Watcher setting (live supervision
2010
- * + QA + scoring) unless the caller set it explicitly; mirror into
2011
- * labs.voice_watcher when a labs block exists. Never overwrites a caller value. */
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 Pro watcher. It also
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 second mind for a live voice agent. Read the " +
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 second mind for a live voice agent. Read the " +
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 the Voice Watcher framework (supervision + QA + scoring). */
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: explicit voiceWatcher > voice_watcher (snake) > labs (deprecated) > true.
302
- this.voiceWatcher = opts.voiceWatcher ?? opts.voice_watcher ?? opts.labs ?? true;
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 SecondMind guidance with developer-controlled field policy.
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.withVoiceWatcher(input)));
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 Voice Watcher setting (live supervision
1160
- * + QA + scoring) unless the caller set it explicitly; mirror into
1161
- * labs.voice_watcher when a labs block exists. Never overwrites a caller value. */
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.voice_watcher = this.sm.voiceWatcher;
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, voice_watcher: this.sm.voiceWatcher };
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,