supafone-labs 0.6.1 → 0.6.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
@@ -82,13 +82,70 @@ whisper to it live — a permanent vendor limitation, not a Supafone gap.
82
82
  are not conversational agents, so there is nothing to inject into.
83
83
 
84
84
  Injection is *possible* for all 10, but managed delivery is wired end-to-end
85
- **only for Ultravox today**; the other nine are supported via their native
86
- primitive with managed delivery rolling out / BYO. A live test against any vendor
85
+ **only for the legacy managed Supervisor delivery path**; the other nine are
86
+ supported via their native primitive with managed delivery rolling out / BYO.
87
+ Native realtime Agent Factory delivery is a separate first-class path. A live test against any vendor
87
88
  needs that vendor's key — free/trial tiers exist for all except OpenAI Realtime
88
89
  (paid, no free tier). Full matrix:
89
90
  [gitbook/framework-support.md](../gitbook/framework-support.md). *(The npm
90
91
  package-page copy updates on the next release.)*
91
92
 
93
+ ## One S2S interface, five providers
94
+
95
+ Version 0.6.3 exports `SupafoneS2S`, the shared parent of `UltravoxS2S`,
96
+ `OpenAIS2S`, `GeminiS2S`, `GrokS2S`, and `HydraS2S`. These classes use
97
+ Supafone's hosted Agent Factory. Supafone handles the audio adapter, tools,
98
+ stages, and supported phone transport behind one API.
99
+
100
+ ```ts
101
+ import { Supafone, HydraS2S, OpenAIS2S, UltravoxS2S } from "supafone-labs";
102
+
103
+ const client = new Supafone({ apiKey: process.env.SUPAFONE_API_KEY! });
104
+ const hydra = new HydraS2S(client, { model: "hydra-v1.1", voice: "maya" });
105
+ const created = await hydra.create({
106
+ name: "Intake", goal: "Collect the caller's details and book a consultation",
107
+ telephony: { mode: "supafone_managed", provider: "supafone" },
108
+ });
109
+ const agentKey = created.agent.agent_key!;
110
+ await hydra.testCall(agentKey);
111
+
112
+ // Switch the same agent for its next call, preserving its assigned number.
113
+ await new OpenAIS2S(client, { model: "gpt-realtime-2.1", voice: "marin" }).apply(agentKey);
114
+ // Return to the existing default Ultravox runtime.
115
+ await new UltravoxS2S(client).apply(agentKey);
116
+ ```
117
+
118
+ `apply` saves a selection for subsequent calls. `testCall` previews the saved
119
+ agent and does not implicitly switch providers. The same constructors and
120
+ `create`, `apply`, and `test_call` methods are available in Python.
121
+
122
+ | Provider family | Selection | Default voice |
123
+ | --- | --- | --- |
124
+ | Ultravox | Default hosted runtime (`realtime: null` resets it) | Agent voice settings |
125
+ | OpenAI | `gpt-realtime-2.1` | `marin` |
126
+ | OpenAI | `gpt-live-1` | `marin` |
127
+ | Google | `gemini-3.1-flash-live-preview` | `Puck` |
128
+ | xAI | `grok-voice-latest` | `eve` |
129
+ | Smallest AI | `hydra-v1.1` | `maya` |
130
+ | Smallest AI | `hydra-v1.0` | `sterling` |
131
+
132
+ The existing `realtime: { provider, model, voice }` API remains supported.
133
+ Native models use the fixed intake → booking → confirmation flow. The phone
134
+ paths are Supafone-managed numbers, BYO Twilio, Telnyx, Plivo, and SIP through
135
+ LiveKit. Carrier provisioning and credentials still determine call readiness.
136
+
137
+ Supafone's configured server-side provider keys are used by default. An
138
+ existing encrypted account key takes priority; customers do not need to add a
139
+ provider key when Supafone has one configured. Missing keys produce an
140
+ unavailable preview instead of a live provider call.
141
+
142
+ Hydra supports English audio and tools, without transcript events or mutable
143
+ mid-session persona/voice. Supafone supplies its fixed stages at session start
144
+ and advances the stage using tool results. Hydra 1.1 uses 16 kHz input / 24 kHz
145
+ output; 1.0 uses 16 kHz / 48 kHz and a different voice roster. Native sessions
146
+ do not claim Ultravox's recording, Supervisor, transfer, or agent-team parity.
147
+ See the [unified S2S guide](https://labs.supafone.ai/docs/unified-s2s/) and
148
+ [capability matrix](https://labs.supafone.ai/docs/realtime-agent-factory/).
92
149
  ## Spawn a hosted Supafone agent
93
150
 
94
151
  Use the same package to create finished Supafone agents from code. This hits the
@@ -1,3 +1,5 @@
1
+ export { SupafoneS2S, UltravoxS2S, OpenAIS2S, GeminiS2S, GrokS2S, HydraS2S } from "./s2s.js";
2
+ export type { S2SProviderName, S2SModelOptions, S2SOptions } from "./s2s.js";
1
3
  /**
2
4
  * Supafone Labs — the agent framework behind Supafone.
3
5
  *
@@ -353,7 +355,7 @@ export interface LabsVoicePreference {
353
355
  }
354
356
  /** Direct speech-to-speech configuration for browser previews and carrier phone calls. */
355
357
  export interface LabsRealtimeSelection {
356
- provider: "openai" | "google" | "xai";
358
+ provider: "openai" | "google" | "xai" | "smallest";
357
359
  model?: string;
358
360
  voice?: string;
359
361
  }
@@ -369,10 +371,21 @@ export interface LabsBrowserTestSession {
369
371
  provider: string;
370
372
  transport: "ultravox" | "supafone_realtime";
371
373
  join_url?: string | null;
372
- websocket_url?: string;
373
- token?: string;
374
+ websocket_url?: string | null;
375
+ token?: string | null;
374
376
  input_sample_rate?: number;
375
377
  output_sample_rate?: number;
378
+ capabilities?: {
379
+ stages?: boolean;
380
+ tools?: boolean;
381
+ transcripts?: boolean;
382
+ recording?: boolean;
383
+ supervisor?: boolean;
384
+ transfer?: boolean;
385
+ mutable_instructions?: boolean;
386
+ stage_update_mode?: string;
387
+ languages?: string[];
388
+ };
376
389
  };
377
390
  }
378
391
  export interface LabsProviderKeys {
@@ -449,6 +462,9 @@ export interface LabsProviderKeys {
449
462
  xai?: string;
450
463
  xaiApiKey?: string;
451
464
  xai_api_key?: string;
465
+ smallest?: string;
466
+ smallestApiKey?: string;
467
+ smallest_api_key?: string;
452
468
  [extra: string]: unknown;
453
469
  }
454
470
  export interface LabsCustomSipConfig {
@@ -959,7 +975,10 @@ export interface LabsAgentReadiness {
959
975
  checks?: Array<Record<string, unknown>>;
960
976
  [extra: string]: unknown;
961
977
  }
962
- export type UpdateLabsAgentRequest = Partial<CreateLabsAgentRequest>;
978
+ export type UpdateLabsAgentRequest = Omit<Partial<CreateLabsAgentRequest>, "realtime"> & {
979
+ /** Select another native model, or null to return to the default Ultravox runtime. */
980
+ realtime?: LabsRealtimeSelection | null;
981
+ };
963
982
  export interface LabsAgentLifecycleResponse {
964
983
  success?: boolean;
965
984
  agent?: LabsAgentResponse;
@@ -2214,7 +2233,7 @@ declare class LabsBillingNamespace {
2214
2233
  declare class LabsAgentsNamespace {
2215
2234
  private sm;
2216
2235
  constructor(sm: SupafoneLabs);
2217
- /** Spawn a durable hosted Supafone agent backed by Ultravox and Supafone-managed providers. */
2236
+ /** Create a hosted Supafone agent with the default Ultravox runtime or a selected native S2S model. */
2218
2237
  create(input: CreateLabsAgentRequest): Promise<CreateLabsAgentResponse>;
2219
2238
  /** Preview the exact validated call-plan contract the Supafone runtime executes. */
2220
2239
  plan(input: CreateLabsAgentRequest & {
package/dist/cjs/index.js CHANGED
@@ -1,30 +1,16 @@
1
1
  "use strict";
2
- /**
3
- * Supafone Labs — the agent framework behind Supafone.
4
- *
5
- * A dependency-free TypeScript client for creating hosted Supafone agents
6
- * through the Supafone API, including managed phone numbers, voices, stages,
7
- * tools, recordings, transcripts, widgets, and Supafone Supervisor. It also
8
- * includes Supafone Supervisor, hosted TTS/STT, live multilingual
9
- * transcription, telemetry, agent builder, and objective-driven optimizer.
10
- *
11
- * Works in Node 18+ (native fetch/WebSocket) and the browser.
12
- *
13
- * npm i supafone-labs
14
- *
15
- * import { Supafone } from "supafone-labs";
16
- * const supafone = new Supafone({ apiKey: process.env.SUPAFONE_API_KEY! });
17
- * const agent = await supafone.labs.agents.createInboundWithNumber({
18
- * agentKey: "northline-intake",
19
- * name: "Northline intake",
20
- * number: { search: { areaCode: "415" } },
21
- * });
22
- */
23
2
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.Supafone = exports.SupafoneLabs = exports.SupafoneLabsError = exports.OUTBOUND_CALL_MODE_PROVIDER_MATRIX = exports.OUTBOUND_CALL_MODE_DEFAULTS = exports.OUTBOUND_CALL_MODE_BOUNDS = void 0;
3
+ exports.Supafone = exports.SupafoneLabs = exports.SupafoneLabsError = exports.OUTBOUND_CALL_MODE_PROVIDER_MATRIX = exports.OUTBOUND_CALL_MODE_DEFAULTS = exports.OUTBOUND_CALL_MODE_BOUNDS = exports.HydraS2S = exports.GrokS2S = exports.GeminiS2S = exports.OpenAIS2S = exports.UltravoxS2S = exports.SupafoneS2S = void 0;
25
4
  exports.outboundCallModeProviderProfile = outboundCallModeProviderProfile;
26
5
  exports.outboundCallModeReadiness = outboundCallModeReadiness;
27
6
  exports.generateCallStages = generateCallStages;
7
+ var s2s_js_1 = require("./s2s.js");
8
+ Object.defineProperty(exports, "SupafoneS2S", { enumerable: true, get: function () { return s2s_js_1.SupafoneS2S; } });
9
+ Object.defineProperty(exports, "UltravoxS2S", { enumerable: true, get: function () { return s2s_js_1.UltravoxS2S; } });
10
+ Object.defineProperty(exports, "OpenAIS2S", { enumerable: true, get: function () { return s2s_js_1.OpenAIS2S; } });
11
+ Object.defineProperty(exports, "GeminiS2S", { enumerable: true, get: function () { return s2s_js_1.GeminiS2S; } });
12
+ Object.defineProperty(exports, "GrokS2S", { enumerable: true, get: function () { return s2s_js_1.GrokS2S; } });
13
+ Object.defineProperty(exports, "HydraS2S", { enumerable: true, get: function () { return s2s_js_1.HydraS2S; } });
28
14
  exports.OUTBOUND_CALL_MODE_BOUNDS = {
29
15
  maxDurationSeconds: { default: 180, min: 30, max: 900 },
30
16
  maxKeypresses: { default: 12, min: 1, max: 64 },
@@ -1202,7 +1188,7 @@ class LabsAgentsNamespace {
1202
1188
  constructor(sm) {
1203
1189
  this.sm = sm;
1204
1190
  }
1205
- /** Spawn a durable hosted Supafone agent backed by Ultravox and Supafone-managed providers. */
1191
+ /** Create a hosted Supafone agent with the default Ultravox runtime or a selected native S2S model. */
1206
1192
  create(input) {
1207
1193
  return this.sm.requestSupafoneApi("POST", "/api/v1/labs/agents", labsAgentPayload(this.withSupervisor(input)));
1208
1194
  }
@@ -2037,7 +2023,10 @@ function labsAgentMetadataPayload(input) {
2037
2023
  return Object.keys(metadata).length ? metadata : undefined;
2038
2024
  }
2039
2025
  function labsAgentUpdatePayload(input) {
2040
- return labsAgentPayload(input);
2026
+ const payload = labsAgentPayload(input);
2027
+ if (input.realtime === null)
2028
+ payload.realtime = null;
2029
+ return payload;
2041
2030
  }
2042
2031
  function campaignSettingsPayload(settings, mode) {
2043
2032
  const payload = { ...(settings ?? {}) };
@@ -2405,6 +2394,8 @@ function providerKeysPayload(input) {
2405
2394
  openai_api_key: input.openai_api_key ?? input.openaiApiKey,
2406
2395
  xai: input.xai,
2407
2396
  xai_api_key: input.xai_api_key ?? input.xaiApiKey,
2397
+ smallest: input.smallest,
2398
+ smallest_api_key: input.smallest_api_key ?? input.smallestApiKey,
2408
2399
  });
2409
2400
  }
2410
2401
  function byokPayload(input) {
@@ -0,0 +1,41 @@
1
+ import type { CreateLabsAgentRequest, GetLabsAgentOptions, LabsRealtimeSelection, SupafoneLabs } from "./index.js";
2
+ export type S2SProviderName = "ultravox" | "openai" | "google" | "xai" | "smallest";
3
+ export interface S2SModelOptions {
4
+ model?: string;
5
+ voice?: string;
6
+ }
7
+ export interface S2SOptions extends S2SModelOptions {
8
+ provider?: S2SProviderName;
9
+ }
10
+ /** Shared parent for Supafone-hosted S2S agents. Vendor keys stay on the server. */
11
+ export declare class SupafoneS2S {
12
+ protected readonly client: SupafoneLabs;
13
+ readonly provider: S2SProviderName;
14
+ private readonly selection;
15
+ constructor(client: SupafoneLabs, options?: S2SOptions);
16
+ /** A fresh wire selection; null explicitly restores the default Ultravox runtime. */
17
+ get realtime(): LabsRealtimeSelection | null;
18
+ /** Create through the normal hosted agent factory with this provider. */
19
+ create(input: Omit<CreateLabsAgentRequest, "realtime">): Promise<import("./index.js").CreateLabsAgentResponse>;
20
+ /** Change the saved selection for subsequent calls, preserving the agent and number. */
21
+ apply(agentKey: string, options?: GetLabsAgentOptions): Promise<import("./index.js").LabsAgentLifecycleResponse>;
22
+ /** Preview the saved agent. Call apply first when switching providers. */
23
+ testCall(agentKey: string, options?: GetLabsAgentOptions): Promise<import("./index.js").LabsBrowserTestSession>;
24
+ private checkAgentKey;
25
+ }
26
+ export declare class UltravoxS2S extends SupafoneS2S {
27
+ constructor(client: SupafoneLabs);
28
+ }
29
+ export declare class OpenAIS2S extends SupafoneS2S {
30
+ constructor(client: SupafoneLabs, options?: S2SModelOptions);
31
+ }
32
+ export declare class GeminiS2S extends SupafoneS2S {
33
+ constructor(client: SupafoneLabs, options?: S2SModelOptions);
34
+ }
35
+ export declare class GrokS2S extends SupafoneS2S {
36
+ constructor(client: SupafoneLabs, options?: S2SModelOptions);
37
+ }
38
+ /** Smallest AI Hydra: full-duplex audio, without transcript events. */
39
+ export declare class HydraS2S extends SupafoneS2S {
40
+ constructor(client: SupafoneLabs, options?: S2SModelOptions);
41
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HydraS2S = exports.GrokS2S = exports.GeminiS2S = exports.OpenAIS2S = exports.UltravoxS2S = exports.SupafoneS2S = void 0;
4
+ /** Shared parent for Supafone-hosted S2S agents. Vendor keys stay on the server. */
5
+ class SupafoneS2S {
6
+ client;
7
+ provider;
8
+ selection;
9
+ constructor(client, options = {}) {
10
+ this.client = client;
11
+ const provider = options.provider ?? "ultravox";
12
+ if (!["ultravox", "openai", "google", "xai", "smallest"].includes(provider)) {
13
+ throw new Error("Unsupported Supafone S2S provider");
14
+ }
15
+ if (provider === "ultravox" && (options.model !== undefined || options.voice !== undefined)) {
16
+ throw new Error("Configure Ultravox voices through the agent's voice settings");
17
+ }
18
+ for (const field of ["model", "voice"]) {
19
+ const value = options[field];
20
+ if (value !== undefined && (typeof value !== "string" || !value.trim())) {
21
+ throw new Error(`${field} must be a non-empty string`);
22
+ }
23
+ }
24
+ this.provider = provider;
25
+ this.selection = provider === "ultravox" ? null : {
26
+ provider,
27
+ ...(options.model !== undefined ? { model: options.model.trim() } : {}),
28
+ ...(options.voice !== undefined ? { voice: options.voice.trim() } : {}),
29
+ };
30
+ }
31
+ /** A fresh wire selection; null explicitly restores the default Ultravox runtime. */
32
+ get realtime() {
33
+ return this.selection ? { ...this.selection } : null;
34
+ }
35
+ /** Create through the normal hosted agent factory with this provider. */
36
+ create(input) {
37
+ if ("realtime" in input) {
38
+ throw new Error("Set provider/model/voice on the S2S adapter, not create({realtime: ...})");
39
+ }
40
+ return this.client.labs.agents.create({
41
+ ...input,
42
+ ...(this.realtime ? { realtime: this.realtime } : {}),
43
+ });
44
+ }
45
+ /** Change the saved selection for subsequent calls, preserving the agent and number. */
46
+ apply(agentKey, options = {}) {
47
+ this.checkAgentKey(agentKey);
48
+ return this.client.labs.agents.update(agentKey, { realtime: this.realtime }, options);
49
+ }
50
+ /** Preview the saved agent. Call apply first when switching providers. */
51
+ testCall(agentKey, options = {}) {
52
+ this.checkAgentKey(agentKey);
53
+ return this.client.labs.agents.testCall(agentKey, options);
54
+ }
55
+ checkAgentKey(agentKey) {
56
+ if (typeof agentKey !== "string" || !agentKey.trim())
57
+ throw new Error("agentKey is required");
58
+ }
59
+ }
60
+ exports.SupafoneS2S = SupafoneS2S;
61
+ class UltravoxS2S extends SupafoneS2S {
62
+ constructor(client) { super(client, { provider: "ultravox" }); }
63
+ }
64
+ exports.UltravoxS2S = UltravoxS2S;
65
+ class OpenAIS2S extends SupafoneS2S {
66
+ constructor(client, options = {}) {
67
+ super(client, { ...options, provider: "openai" });
68
+ }
69
+ }
70
+ exports.OpenAIS2S = OpenAIS2S;
71
+ class GeminiS2S extends SupafoneS2S {
72
+ constructor(client, options = {}) {
73
+ super(client, { ...options, provider: "google" });
74
+ }
75
+ }
76
+ exports.GeminiS2S = GeminiS2S;
77
+ class GrokS2S extends SupafoneS2S {
78
+ constructor(client, options = {}) {
79
+ super(client, { ...options, provider: "xai" });
80
+ }
81
+ }
82
+ exports.GrokS2S = GrokS2S;
83
+ /** Smallest AI Hydra: full-duplex audio, without transcript events. */
84
+ class HydraS2S extends SupafoneS2S {
85
+ constructor(client, options = {}) {
86
+ super(client, { ...options, provider: "smallest" });
87
+ }
88
+ }
89
+ exports.HydraS2S = HydraS2S;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { SupafoneS2S, UltravoxS2S, OpenAIS2S, GeminiS2S, GrokS2S, HydraS2S } from "./s2s.js";
2
+ export type { S2SProviderName, S2SModelOptions, S2SOptions } from "./s2s.js";
1
3
  /**
2
4
  * Supafone Labs — the agent framework behind Supafone.
3
5
  *
@@ -353,7 +355,7 @@ export interface LabsVoicePreference {
353
355
  }
354
356
  /** Direct speech-to-speech configuration for browser previews and carrier phone calls. */
355
357
  export interface LabsRealtimeSelection {
356
- provider: "openai" | "google" | "xai";
358
+ provider: "openai" | "google" | "xai" | "smallest";
357
359
  model?: string;
358
360
  voice?: string;
359
361
  }
@@ -369,10 +371,21 @@ export interface LabsBrowserTestSession {
369
371
  provider: string;
370
372
  transport: "ultravox" | "supafone_realtime";
371
373
  join_url?: string | null;
372
- websocket_url?: string;
373
- token?: string;
374
+ websocket_url?: string | null;
375
+ token?: string | null;
374
376
  input_sample_rate?: number;
375
377
  output_sample_rate?: number;
378
+ capabilities?: {
379
+ stages?: boolean;
380
+ tools?: boolean;
381
+ transcripts?: boolean;
382
+ recording?: boolean;
383
+ supervisor?: boolean;
384
+ transfer?: boolean;
385
+ mutable_instructions?: boolean;
386
+ stage_update_mode?: string;
387
+ languages?: string[];
388
+ };
376
389
  };
377
390
  }
378
391
  export interface LabsProviderKeys {
@@ -449,6 +462,9 @@ export interface LabsProviderKeys {
449
462
  xai?: string;
450
463
  xaiApiKey?: string;
451
464
  xai_api_key?: string;
465
+ smallest?: string;
466
+ smallestApiKey?: string;
467
+ smallest_api_key?: string;
452
468
  [extra: string]: unknown;
453
469
  }
454
470
  export interface LabsCustomSipConfig {
@@ -959,7 +975,10 @@ export interface LabsAgentReadiness {
959
975
  checks?: Array<Record<string, unknown>>;
960
976
  [extra: string]: unknown;
961
977
  }
962
- export type UpdateLabsAgentRequest = Partial<CreateLabsAgentRequest>;
978
+ export type UpdateLabsAgentRequest = Omit<Partial<CreateLabsAgentRequest>, "realtime"> & {
979
+ /** Select another native model, or null to return to the default Ultravox runtime. */
980
+ realtime?: LabsRealtimeSelection | null;
981
+ };
963
982
  export interface LabsAgentLifecycleResponse {
964
983
  success?: boolean;
965
984
  agent?: LabsAgentResponse;
@@ -2214,7 +2233,7 @@ declare class LabsBillingNamespace {
2214
2233
  declare class LabsAgentsNamespace {
2215
2234
  private sm;
2216
2235
  constructor(sm: SupafoneLabs);
2217
- /** Spawn a durable hosted Supafone agent backed by Ultravox and Supafone-managed providers. */
2236
+ /** Create a hosted Supafone agent with the default Ultravox runtime or a selected native S2S model. */
2218
2237
  create(input: CreateLabsAgentRequest): Promise<CreateLabsAgentResponse>;
2219
2238
  /** Preview the exact validated call-plan contract the Supafone runtime executes. */
2220
2239
  plan(input: CreateLabsAgentRequest & {