supafone-labs 0.5.3 → 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 CHANGED
@@ -6,7 +6,7 @@ Use this package to create hosted Supafone agents from code: inbound
6
6
  receptionists, outbound sales agents, web agents, Supafone-managed phone
7
7
  numbers, built-in stages, tools, recordings, transcripts, widgets, and Supafone
8
8
  Pro watcher. It also includes the [Supafone Labs cloud](https://labs.supafone.ai)
9
- sidecar oracle, hosted TTS/STT, live multilingual transcription, the builder,
9
+ Supervisor, hosted TTS/STT, live multilingual transcription, the builder,
10
10
  and the adversarial QA suite.
11
11
 
12
12
  Dependency-free. Works in Node 18+ and the browser (native `fetch` / `WebSocket`).
@@ -21,7 +21,7 @@ The SDK talks to two related APIs:
21
21
 
22
22
  | Environment variable | Key shape | Used for |
23
23
  | --- | --- | --- |
24
- | `SUPAFONE_LABS_API_KEY` | `sl_live_...` | Labs cloud oracle, hosted TTS/STT, logs, usage, QA, optimizer |
24
+ | `SUPAFONE_LABS_API_KEY` | `sl_live_...` | Labs Cloud Supervisor, hosted TTS/STT, logs, usage, QA, optimizer |
25
25
  | `SUPAFONE_API_KEY` | `sf_live_...` | Hosted Supafone agents on `/api/v1/labs/*` |
26
26
 
27
27
  If you only use hosted-agent methods, `SUPAFONE_API_KEY` is enough. If you use
@@ -114,6 +114,12 @@ 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
 
117
+ The canonical packet separates interpersonal guidance, the next operational
118
+ move, observed evidence, policy/tool-truth boundaries, language, confidence,
119
+ and guidance kind. See
120
+ [Programmable Supervisor Directives](../gitbook/programmable-supervisor-directives.md)
121
+ for the human-supervisor mapping and field controls.
122
+
117
123
  Agent Factory can opt into managed live language and matching-voice routing
118
124
  with one field. It remains absent and disabled for existing agents:
119
125
 
@@ -407,7 +413,7 @@ const { analysis } = await supafone.reportCall({
407
413
  ```
408
414
 
409
415
  The enriched report is filed server-side (feeding `optimizer.improve()` and
410
- `/v1/optimizer/objective/stats`); billed one oracle call per analyzed call.
416
+ `/v1/optimizer/objective/stats`); billed one Supervisor inference per analyzed call.
411
417
  Reports without a transcript — or any analysis failure — fall back to the
412
418
  plain zero-billed report. You can also classify explicitly with
413
419
  `supafone.classifyCall({ transcript, agent })`.
@@ -539,11 +545,12 @@ and `const { Supafone } = require("supafone-labs")` both work, with full types.
539
545
  | `labs.agents.syncKnowledge/detachWebsiteKnowledge/reindexKnowledge` | Managed website corpus lifecycle using `agent.id` |
540
546
  | `labs.agents.uploadKnowledgeDocument/deleteKnowledgeDocument/chatKnowledge` | Account-isolated document and grounded-query methods |
541
547
  | `labs.phoneNumbers.search/buy/assign/list/buyAndAssign` | `/api/v1/labs/phone-numbers*` |
548
+ | `labs.phoneNumbers.pool/connectPool` | Safe shared developer-number snapshot and scoped realtime stream |
542
549
  | `labs.billing.checkout/status/portal` | Stripe-hosted Checkout, payment polling, and Customer Portal |
543
550
  | `labs.telephony.get/configure/useSupafoneManaged` | `/api/v1/labs/telephony` |
544
551
  | `labs.presets.list()` · `labs.tools.list()` · `labs.voices.list()` | Supafone hosted-agent discovery |
545
- | `whisper(transcript, opts?)` | convenience over the oracle |
546
- | `oracle({ messages, model?, ... })` | `POST /v1/oracle/complete` |
552
+ | `whisper(transcript, opts?)` | Convenience over Supervisor completion and directive extraction |
553
+ | `completeWithSupervisor({ messages, model?, ... })` | `POST /v1/supervisor/complete` |
547
554
  | `tts(text, voice?)` | `POST /v1/tts` |
548
555
  | `stt(audio, opts?)` | `POST /v1/stt` |
549
556
  | `liveTranscribe(opts?)` | `WS /v1/stt/live` |
@@ -553,7 +560,19 @@ and `const { Supafone } = require("supafone-labs")` both work, with full types.
553
560
  | `qa.run/generate/suite/history` | `/v1/qa/*` |
554
561
  | `optimizer.improve/standing` | `/v1/optimizer/*` |
555
562
 
556
- Get a key (5 free minutes, no card): <https://labs.supafone.ai/get-key.html>
563
+ Get a key (five account-wide managed-runtime minutes, no card):
564
+ <https://labs.supafone.ai/get-key.html>
565
+
566
+ That allowance is shared by every key, agent, WebRTC tab, PSTN call, SDK, CLI,
567
+ and MCP client linked to the account. Managed calls reserve time atomically
568
+ before provider startup; settlement refunds unused held seconds. HTTP 402
569
+ responses expose `detail.code=managed_minutes_exhausted` and a
570
+ `checkout_endpoint`. Create Checkout with `labs.billing.checkout()`, open the
571
+ returned `checkout_url`, poll `labs.billing.status()`, and retry after payment.
572
+
573
+ The older `oracle()` method and `POST /v1/oracle/complete` route remain only as
574
+ deprecated compatibility aliases. New integrations should use
575
+ `completeWithSupervisor()` and `POST /v1/supervisor/complete`.
557
576
 
558
577
  For `dedicated` or `premium`, `labs.phoneNumbers.buy()` first returns a public
559
578
  `checkout_url`. Open it, poll `labs.billing.status()`, then call `buy()` again
@@ -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 the Labs cloud sidecar oracle, hosted TTS/STT, live multilingual
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 oracle call per analyzed call; reports without a transcript
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 OracleRequest {
69
+ export interface SupervisorRequest {
70
70
  messages: ChatMessage[];
71
- /** Any claude-* / gpt-* / grok-* id, or the alias "supafone-labs-oracle". */
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 OracleResult {
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 = "oracle" | "template" | "off";
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;
@@ -541,8 +547,56 @@ export interface LabsToolsConfig {
541
547
  voicemail?: boolean;
542
548
  emergencyEscalation?: boolean;
543
549
  emergency_escalation?: boolean;
544
- customTools?: Array<Record<string, unknown>>;
545
- custom_tools?: Array<Record<string, unknown>>;
550
+ /** Makes the native DTMF tool available for bounded phone-tree navigation. */
551
+ ivrNavigation?: boolean;
552
+ ivr_navigation?: boolean;
553
+ /** Executable customer-owned HTTPS tools, proxied by Supafone at call time. */
554
+ customTools?: LabsCustomToolDefinition[];
555
+ custom_tools?: LabsCustomToolDefinition[];
556
+ }
557
+ export type LabsCustomToolParameterType = "string" | "number" | "integer" | "boolean";
558
+ export interface LabsCustomToolParameter {
559
+ name: string;
560
+ description?: string;
561
+ type?: LabsCustomToolParameterType;
562
+ required?: boolean;
563
+ }
564
+ export interface LabsCustomToolDefinition {
565
+ /** Stable id returned by Supafone. Omit it when creating a tool. */
566
+ id?: string;
567
+ /** Lowercase model tool name, such as lookup_order. */
568
+ name: string;
569
+ description?: string;
570
+ /** HTTPS endpoint called by Supafone's guarded server-side proxy. */
571
+ url: string;
572
+ /** Optional secret header name. Defaults to Authorization: Bearer <apiKey>. */
573
+ header?: string;
574
+ apiKey?: string;
575
+ api_key?: string;
576
+ /** Set false on update to remove a previously stored secret. */
577
+ apiKeySet?: boolean;
578
+ api_key_set?: boolean;
579
+ params?: LabsCustomToolParameter[];
580
+ parameters?: LabsCustomToolParameter[];
581
+ /** Optional call-stage keys where this tool is available. Empty means every stage. */
582
+ stages?: string[];
583
+ allowedStages?: string[];
584
+ allowed_stages?: string[];
585
+ }
586
+ export interface LabsEmailConfig {
587
+ enabled?: boolean;
588
+ fromEmail?: string;
589
+ from_email?: string;
590
+ smtpHost?: string;
591
+ smtp_host?: string;
592
+ smtpPort?: number;
593
+ smtp_port?: number;
594
+ smtpUser?: string;
595
+ smtp_user?: string;
596
+ /** Encrypted by Supafone and never returned. */
597
+ smtpPassword?: string;
598
+ smtp_password?: string;
599
+ smtp_pass?: string;
546
600
  }
547
601
  export interface LabsRecordingConfig {
548
602
  enabled?: boolean;
@@ -581,15 +635,29 @@ export interface LabsArtifactsConfig {
581
635
  retention_days?: number;
582
636
  metadata?: Record<string, unknown>;
583
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
+ }
584
649
  export interface LabsSupervisorConfig {
585
650
  enabled?: boolean;
586
- supervisor?: boolean;
651
+ supervisor?: boolean | LabsByokSupervisorConfig;
587
652
  /** @deprecated Use supervisor. */
588
653
  voiceWatcher?: boolean;
589
654
  /** @deprecated Use supervisor. */
590
655
  voice_watcher?: boolean;
591
656
  apiKey?: string;
592
657
  api_key?: string;
658
+ apiKeyConfigured?: boolean;
659
+ api_key_configured?: boolean;
660
+ provider?: LabsSupervisorProvider;
593
661
  model?: string;
594
662
  mode?: "supafone_managed" | "byok" | string;
595
663
  managedInfrastructure?: boolean;
@@ -817,9 +885,11 @@ export interface CreateLabsAgentRequest {
817
885
  artifacts?: LabsArtifactsConfig;
818
886
  compliance?: Record<string, unknown>;
819
887
  tools?: LabsToolsConfig;
888
+ /** Optional per-agent SMTP sender used by the callable send_email tool. */
889
+ email?: LabsEmailConfig;
820
890
  labs?: LabsSupervisorConfig;
821
891
  ultravox?: LabsUltravoxRuntime;
822
- supervisor?: boolean;
892
+ supervisor?: boolean | LabsByokSupervisorConfig;
823
893
  /** @deprecated Use supervisor. */
824
894
  voiceWatcher?: boolean;
825
895
  /** @deprecated Use supervisor. */
@@ -1142,6 +1212,44 @@ export interface LabsPhoneNumberListResponse {
1142
1212
  numbers: LabsPhoneNumberRecord[];
1143
1213
  telephony?: Record<string, unknown>;
1144
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
+ }
1145
1253
  export interface LabsPhoneNumberProvisionRequest {
1146
1254
  agencyId?: string;
1147
1255
  agency_id?: string;
@@ -1364,6 +1472,8 @@ export interface BuilderChatResult {
1364
1472
  emotion?: string;
1365
1473
  language?: string;
1366
1474
  intent?: string;
1475
+ supervisor_ms?: number;
1476
+ /** @deprecated Use supervisor_ms. */
1367
1477
  oracle_ms?: number;
1368
1478
  standing_version?: number;
1369
1479
  }
@@ -1405,7 +1515,9 @@ export interface QASuiteResult {
1405
1515
  passed: number;
1406
1516
  avg_ssr_score: number;
1407
1517
  ssr_histogram: Record<SSRLabel, number>;
1408
- oracle_calls_billed: number;
1518
+ supervisor_inferences_billed?: number;
1519
+ /** @deprecated Legacy server field. */
1520
+ oracle_calls_billed?: number;
1409
1521
  };
1410
1522
  }
1411
1523
  export interface QAResult {
@@ -1434,7 +1546,9 @@ export interface QAResult {
1434
1546
  passed_supervised: number;
1435
1547
  passed_unsupervised: number;
1436
1548
  avg_lift: number;
1437
- oracle_calls_billed: number;
1549
+ supervisor_inferences_billed?: number;
1550
+ /** @deprecated Legacy server field. */
1551
+ oracle_calls_billed?: number;
1438
1552
  };
1439
1553
  }
1440
1554
  export type TesterScenario = "price_probe" | "false_booking" | "language_switch" | "distressed";
@@ -1627,8 +1741,10 @@ export declare class SupafoneLabs {
1627
1741
  industry?: string;
1628
1742
  apply?: boolean;
1629
1743
  }): Promise<GenerateIntakeResult>;
1630
- /** Raw oracle completion full control over messages and model. */
1631
- oracle(req: OracleRequest): Promise<OracleResult>;
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>;
1632
1748
  /**
1633
1749
  * The one-liner: hand it the running transcript, get back a silent directive
1634
1750
  * (empty string when the agent is doing fine).
@@ -1659,7 +1775,7 @@ export declare class SupafoneLabs {
1659
1775
  liveTranscribe(opts?: LiveTranscribeOptions): LiveTranscription;
1660
1776
  /** Remaining prepaid balance. */
1661
1777
  balance(): Promise<Balance>;
1662
- /** Today's usage against your plan caps (oracle/tts/stt/…). */
1778
+ /** Today's usage across Supervisor, TTS, STT, and managed runtime meters. */
1663
1779
  usage(): Promise<UsageToday>;
1664
1780
  /** The auditable whisper/billing log. */
1665
1781
  logs(limit?: number): Promise<{
@@ -1682,7 +1798,7 @@ export declare class SupafoneLabs {
1682
1798
  *
1683
1799
  * With `postCallAnalysis: true` on the client and a transcript (or
1684
1800
  * messages) present, the call is automatically classified first: the
1685
- * oracle labels it against the agent's objective (achieved/missed,
1801
+ * Supervisor labels it against the agent's objective (achieved/missed,
1686
1802
  * per-criterion verdicts, failure reasons) and files the enriched report
1687
1803
  * server-side. The generated labels come back on `analysis`. Analysis is
1688
1804
  * best-effort — on any failure the plain zero-billed report still lands.
@@ -1693,10 +1809,10 @@ export declare class SupafoneLabs {
1693
1809
  * objective and get labels back — achieved/missed, per-criterion verdicts,
1694
1810
  * failure reasons, and the blended objective value. Files an enriched call
1695
1811
  * report server-side (feeding optimizer.improve() and objective stats).
1696
- * Billed one oracle call.
1812
+ * Billed one Supervisor inference.
1697
1813
  */
1698
1814
  classifyCall(input: ClassifyCallInput): Promise<CallClassification>;
1699
- /** Available oracle model ids (live vendor catalog). */
1815
+ /** Available managed and BYOK Supervisor model ids. */
1700
1816
  models(): Promise<string[]>;
1701
1817
  /** Available TTS voice ids. */
1702
1818
  voices(): Promise<string[]>;
@@ -2015,6 +2131,10 @@ declare class LabsNamespace {
2015
2131
  }
2016
2132
  export type LabsBillingCheckoutKind = "plan" | "credits" | "number_addon";
2017
2133
  export interface LabsBillingCheckoutInput {
2134
+ /** Current prepaid managed-minute package SKU. */
2135
+ sku?: string;
2136
+ packageSku?: string;
2137
+ package_sku?: string;
2018
2138
  kind?: LabsBillingCheckoutKind;
2019
2139
  planKey?: "developer" | "growth" | "scale" | string;
2020
2140
  plan_key?: string;
@@ -2029,10 +2149,16 @@ export interface LabsBillingCheckoutInput {
2029
2149
  cancel_url?: string;
2030
2150
  }
2031
2151
  export interface LabsBillingCheckoutResponse {
2032
- status: "requires_payment" | "pending" | "paid" | string;
2033
- checkout_session_id: string;
2152
+ status?: "requires_payment" | "pending" | "paid" | string;
2153
+ checkout_session_id?: string;
2034
2154
  checkout_url?: string;
2035
- kind: LabsBillingCheckoutKind | string;
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;
2036
2162
  plan_key?: string | null;
2037
2163
  number_strategy?: string | null;
2038
2164
  phone_number?: string | null;
@@ -2045,6 +2171,8 @@ declare class LabsBillingNamespace {
2045
2171
  constructor(sm: SupafoneLabs);
2046
2172
  /** Start hosted Stripe Checkout. MCP callers should render checkout_url as a link. */
2047
2173
  checkout(input?: LabsBillingCheckoutInput): Promise<LabsBillingCheckoutResponse>;
2174
+ /** Start Stripe Checkout for one prepaid managed-minute package. */
2175
+ topUp(sku?: string): Promise<LabsBillingCheckoutResponse>;
2048
2176
  status(checkoutSessionId: string): Promise<LabsBillingCheckoutResponse>;
2049
2177
  portal(): Promise<{
2050
2178
  url: string;
@@ -2217,6 +2345,16 @@ declare class LabsPhoneNumbersNamespace {
2217
2345
  constructor(sm: SupafoneLabs);
2218
2346
  /** List numbers already owned by this Supafone account. */
2219
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>;
2220
2358
  /** Search Supafone-managed inventory. This uses Supafone's master telephony account. */
2221
2359
  search(opts?: LabsPhoneNumberSearchOptions): Promise<LabsPhoneNumberSearchResponse>;
2222
2360
  /**