supafone-labs 0.6.2 → 0.7.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 +117 -86
- package/dist/cjs/index.d.ts +98 -3
- package/dist/cjs/index.js +62 -29
- package/dist/cjs/s2s.d.ts +41 -0
- package/dist/cjs/s2s.js +89 -0
- package/dist/index.d.ts +98 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -28
- package/dist/index.js.map +1 -1
- package/dist/s2s.d.ts +42 -0
- package/dist/s2s.d.ts.map +1 -0
- package/dist/s2s.js +81 -0
- package/dist/s2s.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +147 -9
- package/src/s2s.ts +100 -0
package/dist/s2s.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
}
|
|
42
|
+
//# sourceMappingURL=s2s.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s2s.d.ts","sourceRoot":"","sources":["../src/s2s.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,UAAU,CAAC;AACpF,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,UAAW,SAAQ,eAAe;IACjD,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,oFAAoF;AACpF,qBAAa,WAAW;IAIV,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY;IAHnD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;gBAE1B,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,UAAe;IAsB7E,qFAAqF;IACrF,IAAI,QAAQ,IAAI,qBAAqB,GAAG,IAAI,CAE3C;IAED,yEAAyE;IACzE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,UAAU,CAAC;IAUtD,wFAAwF;IACxF,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB;IAKzD,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB;IAK5D,OAAO,CAAC,aAAa;CAGtB;AAED,qBAAa,WAAY,SAAQ,WAAW;gBAC9B,MAAM,EAAE,YAAY;CACjC;AACD,qBAAa,SAAU,SAAQ,WAAW;gBAC5B,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,eAAoB;CAGhE;AACD,qBAAa,SAAU,SAAQ,WAAW;gBAC5B,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,eAAoB;CAGhE;AACD,qBAAa,OAAQ,SAAQ,WAAW;gBAC1B,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,eAAoB;CAGhE;AACD,uEAAuE;AACvE,qBAAa,QAAS,SAAQ,WAAW;gBAC3B,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,eAAoB;CAGhE"}
|
package/dist/s2s.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** Shared parent for Supafone-hosted S2S agents. Vendor keys stay on the server. */
|
|
2
|
+
export class SupafoneS2S {
|
|
3
|
+
client;
|
|
4
|
+
provider;
|
|
5
|
+
selection;
|
|
6
|
+
constructor(client, options = {}) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
const provider = options.provider ?? "ultravox";
|
|
9
|
+
if (!["ultravox", "openai", "google", "xai", "smallest"].includes(provider)) {
|
|
10
|
+
throw new Error("Unsupported Supafone S2S provider");
|
|
11
|
+
}
|
|
12
|
+
if (provider === "ultravox" && (options.model !== undefined || options.voice !== undefined)) {
|
|
13
|
+
throw new Error("Configure Ultravox voices through the agent's voice settings");
|
|
14
|
+
}
|
|
15
|
+
for (const field of ["model", "voice"]) {
|
|
16
|
+
const value = options[field];
|
|
17
|
+
if (value !== undefined && (typeof value !== "string" || !value.trim())) {
|
|
18
|
+
throw new Error(`${field} must be a non-empty string`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
this.provider = provider;
|
|
22
|
+
this.selection = provider === "ultravox" ? null : {
|
|
23
|
+
provider,
|
|
24
|
+
...(options.model !== undefined ? { model: options.model.trim() } : {}),
|
|
25
|
+
...(options.voice !== undefined ? { voice: options.voice.trim() } : {}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** A fresh wire selection; null explicitly restores the default Ultravox runtime. */
|
|
29
|
+
get realtime() {
|
|
30
|
+
return this.selection ? { ...this.selection } : null;
|
|
31
|
+
}
|
|
32
|
+
/** Create through the normal hosted agent factory with this provider. */
|
|
33
|
+
create(input) {
|
|
34
|
+
if ("realtime" in input) {
|
|
35
|
+
throw new Error("Set provider/model/voice on the S2S adapter, not create({realtime: ...})");
|
|
36
|
+
}
|
|
37
|
+
return this.client.labs.agents.create({
|
|
38
|
+
...input,
|
|
39
|
+
...(this.realtime ? { realtime: this.realtime } : {}),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** Change the saved selection for subsequent calls, preserving the agent and number. */
|
|
43
|
+
apply(agentKey, options = {}) {
|
|
44
|
+
this.checkAgentKey(agentKey);
|
|
45
|
+
return this.client.labs.agents.update(agentKey, { realtime: this.realtime }, options);
|
|
46
|
+
}
|
|
47
|
+
/** Preview the saved agent. Call apply first when switching providers. */
|
|
48
|
+
testCall(agentKey, options = {}) {
|
|
49
|
+
this.checkAgentKey(agentKey);
|
|
50
|
+
return this.client.labs.agents.testCall(agentKey, options);
|
|
51
|
+
}
|
|
52
|
+
checkAgentKey(agentKey) {
|
|
53
|
+
if (typeof agentKey !== "string" || !agentKey.trim())
|
|
54
|
+
throw new Error("agentKey is required");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class UltravoxS2S extends SupafoneS2S {
|
|
58
|
+
constructor(client) { super(client, { provider: "ultravox" }); }
|
|
59
|
+
}
|
|
60
|
+
export class OpenAIS2S extends SupafoneS2S {
|
|
61
|
+
constructor(client, options = {}) {
|
|
62
|
+
super(client, { ...options, provider: "openai" });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export class GeminiS2S extends SupafoneS2S {
|
|
66
|
+
constructor(client, options = {}) {
|
|
67
|
+
super(client, { ...options, provider: "google" });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export class GrokS2S extends SupafoneS2S {
|
|
71
|
+
constructor(client, options = {}) {
|
|
72
|
+
super(client, { ...options, provider: "xai" });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Smallest AI Hydra: full-duplex audio, without transcript events. */
|
|
76
|
+
export class HydraS2S extends SupafoneS2S {
|
|
77
|
+
constructor(client, options = {}) {
|
|
78
|
+
super(client, { ...options, provider: "smallest" });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=s2s.js.map
|
package/dist/s2s.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s2s.js","sourceRoot":"","sources":["../src/s2s.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export { SupafoneS2S, UltravoxS2S, OpenAIS2S, GeminiS2S, GrokS2S, HydraS2S } from "./s2s.js";
|
|
2
|
+
export type { S2SProviderName, S2SModelOptions, S2SOptions } from "./s2s.js";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Supafone Labs — the agent framework behind Supafone.
|
|
3
6
|
*
|
|
@@ -221,9 +224,70 @@ export interface LabsCallStage {
|
|
|
221
224
|
temperature?: number;
|
|
222
225
|
nextStages?: string[];
|
|
223
226
|
next_stages?: string[];
|
|
227
|
+
/** Server-enforced exit gates, independent of conversational exit criteria. */
|
|
228
|
+
requirements?: LabsStageRequirements;
|
|
229
|
+
role?: string;
|
|
230
|
+
specialistId?: string;
|
|
231
|
+
specialist_id?: string;
|
|
224
232
|
metadata?: Record<string, unknown>;
|
|
225
233
|
}
|
|
226
234
|
|
|
235
|
+
export interface LabsStageRequirements {
|
|
236
|
+
requiredFields?: string[];
|
|
237
|
+
required_fields?: string[];
|
|
238
|
+
successfulTools?: string[];
|
|
239
|
+
successful_tools?: string[];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface LabsManagerConfig {
|
|
243
|
+
enabled?: boolean;
|
|
244
|
+
/** Reuse the existing encrypted Supervisor profile, or use managed reasoning. */
|
|
245
|
+
reasoning?: "managed" | "supervisor";
|
|
246
|
+
model?: "supafone-manager" | "supafone-manager-pro";
|
|
247
|
+
maxTasks?: number;
|
|
248
|
+
max_tasks?: number;
|
|
249
|
+
maxParallel?: number;
|
|
250
|
+
max_parallel?: number;
|
|
251
|
+
timeoutSeconds?: number;
|
|
252
|
+
timeout_seconds?: number;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export interface LabsSpecialist {
|
|
256
|
+
id: string;
|
|
257
|
+
role?: string;
|
|
258
|
+
label?: string;
|
|
259
|
+
description?: string;
|
|
260
|
+
instructions?: string;
|
|
261
|
+
enabled?: boolean;
|
|
262
|
+
stageKeys?: string[];
|
|
263
|
+
stage_keys?: string[];
|
|
264
|
+
tools?: string[];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export interface LabsAgentTeam {
|
|
268
|
+
enabled?: boolean;
|
|
269
|
+
routingMode?: "auto" | "sequential";
|
|
270
|
+
routing_mode?: "auto" | "sequential";
|
|
271
|
+
fallbackMemberId?: string;
|
|
272
|
+
fallback_member_id?: string;
|
|
273
|
+
members?: LabsSpecialist[];
|
|
274
|
+
routingRules?: Array<{ intent: string; member_id: string; priority?: string; action?: string }>;
|
|
275
|
+
routing_rules?: Array<{ intent: string; member_id: string; priority?: string; action?: string }>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export interface LabsRuntimeRoutingConfig {
|
|
279
|
+
enabled?: boolean;
|
|
280
|
+
allowedModels?: LabsRealtimeSelection[];
|
|
281
|
+
allowed_models?: LabsRealtimeSelection[];
|
|
282
|
+
/** Server-supported range is 1–3 handoffs per call. */
|
|
283
|
+
maxHandoffs?: number;
|
|
284
|
+
max_handoffs?: number;
|
|
285
|
+
recoverOnDisconnect?: boolean;
|
|
286
|
+
recover_on_disconnect?: boolean;
|
|
287
|
+
allowedLanguages?: string[];
|
|
288
|
+
allowed_languages?: string[];
|
|
289
|
+
}
|
|
290
|
+
|
|
227
291
|
export type LabsStageGeneration = "managed" | "template" | "off" | "oracle";
|
|
228
292
|
|
|
229
293
|
export interface LabsCallPlan {
|
|
@@ -385,7 +449,7 @@ export interface LabsVoicePreference {
|
|
|
385
449
|
|
|
386
450
|
/** Direct speech-to-speech configuration for browser previews and carrier phone calls. */
|
|
387
451
|
export interface LabsRealtimeSelection {
|
|
388
|
-
provider: "openai" | "google" | "xai";
|
|
452
|
+
provider: "openai" | "google" | "xai" | "smallest";
|
|
389
453
|
model?: string;
|
|
390
454
|
voice?: string;
|
|
391
455
|
}
|
|
@@ -406,6 +470,17 @@ export interface LabsBrowserTestSession {
|
|
|
406
470
|
token?: string | null;
|
|
407
471
|
input_sample_rate?: number;
|
|
408
472
|
output_sample_rate?: number;
|
|
473
|
+
capabilities?: {
|
|
474
|
+
stages?: boolean;
|
|
475
|
+
tools?: boolean;
|
|
476
|
+
transcripts?: boolean;
|
|
477
|
+
recording?: boolean;
|
|
478
|
+
supervisor?: boolean;
|
|
479
|
+
transfer?: boolean;
|
|
480
|
+
mutable_instructions?: boolean;
|
|
481
|
+
stage_update_mode?: string;
|
|
482
|
+
languages?: string[];
|
|
483
|
+
};
|
|
409
484
|
};
|
|
410
485
|
}
|
|
411
486
|
|
|
@@ -483,6 +558,9 @@ export interface LabsProviderKeys {
|
|
|
483
558
|
xai?: string;
|
|
484
559
|
xaiApiKey?: string;
|
|
485
560
|
xai_api_key?: string;
|
|
561
|
+
smallest?: string;
|
|
562
|
+
smallestApiKey?: string;
|
|
563
|
+
smallest_api_key?: string;
|
|
486
564
|
[extra: string]: unknown;
|
|
487
565
|
}
|
|
488
566
|
|
|
@@ -675,6 +753,8 @@ export interface LabsEmailConfig {
|
|
|
675
753
|
|
|
676
754
|
export interface LabsRecordingConfig {
|
|
677
755
|
enabled?: boolean;
|
|
756
|
+
/** Request post-call transcription of the recording where configured. */
|
|
757
|
+
transcribe?: boolean;
|
|
678
758
|
recordAudio?: boolean;
|
|
679
759
|
record_audio?: boolean;
|
|
680
760
|
consentRequired?: boolean;
|
|
@@ -1027,6 +1107,17 @@ export interface CreateLabsAgentRequest {
|
|
|
1027
1107
|
presetKey?: string;
|
|
1028
1108
|
preset_key?: string;
|
|
1029
1109
|
realtime?: LabsRealtimeSelection;
|
|
1110
|
+
manager?: boolean | LabsManagerConfig;
|
|
1111
|
+
agentTeam?: LabsAgentTeam;
|
|
1112
|
+
agent_team?: LabsAgentTeam;
|
|
1113
|
+
runtimeRouting?: LabsRuntimeRoutingConfig;
|
|
1114
|
+
runtime_routing?: LabsRuntimeRoutingConfig;
|
|
1115
|
+
captureFields?: string[];
|
|
1116
|
+
capture_fields?: string[];
|
|
1117
|
+
timezone?: string;
|
|
1118
|
+
businessTimezone?: string;
|
|
1119
|
+
timeAwareness?: boolean;
|
|
1120
|
+
time_awareness?: boolean;
|
|
1030
1121
|
runtimeMode?: LabsRuntimeMode;
|
|
1031
1122
|
runtime_mode?: LabsRuntimeMode;
|
|
1032
1123
|
/** Defaults to Supafone's hosted planner; model credentials remain server-side. */
|
|
@@ -1069,7 +1160,7 @@ export interface CreateLabsAgentRequest {
|
|
|
1069
1160
|
customSip?: LabsCustomSipConfig;
|
|
1070
1161
|
custom_sip?: LabsCustomSipConfig;
|
|
1071
1162
|
sip?: LabsCustomSipConfig;
|
|
1072
|
-
recording?: LabsRecordingConfig;
|
|
1163
|
+
recording?: boolean | LabsRecordingConfig;
|
|
1073
1164
|
transcription?: LabsTranscriptionConfig;
|
|
1074
1165
|
artifacts?: LabsArtifactsConfig;
|
|
1075
1166
|
compliance?: Record<string, unknown>;
|
|
@@ -3343,7 +3434,7 @@ class LabsBillingNamespace {
|
|
|
3343
3434
|
class LabsAgentsNamespace {
|
|
3344
3435
|
constructor(private sm: SupafoneLabs) {}
|
|
3345
3436
|
|
|
3346
|
-
/**
|
|
3437
|
+
/** Create a hosted Supafone agent with the default Ultravox runtime or a selected native S2S model. */
|
|
3347
3438
|
create(input: CreateLabsAgentRequest): Promise<CreateLabsAgentResponse> {
|
|
3348
3439
|
return this.sm.requestSupafoneApi<CreateLabsAgentResponse>(
|
|
3349
3440
|
"POST",
|
|
@@ -4346,6 +4437,40 @@ function outboundCallModeRequiredCapabilities(payload: Record<string, unknown>):
|
|
|
4346
4437
|
return required;
|
|
4347
4438
|
}
|
|
4348
4439
|
|
|
4440
|
+
function managerPayload(input?: boolean | LabsManagerConfig): boolean | Record<string, unknown> | undefined {
|
|
4441
|
+
if (typeof input !== "object" || input === null) return input;
|
|
4442
|
+
return compact({
|
|
4443
|
+
enabled: input.enabled, reasoning: input.reasoning, model: input.model,
|
|
4444
|
+
max_tasks: input.max_tasks ?? input.maxTasks,
|
|
4445
|
+
max_parallel: input.max_parallel ?? input.maxParallel,
|
|
4446
|
+
timeout_seconds: input.timeout_seconds ?? input.timeoutSeconds,
|
|
4447
|
+
});
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4450
|
+
function agentTeamPayload(input?: LabsAgentTeam): Record<string, unknown> | undefined {
|
|
4451
|
+
if (!input) return undefined;
|
|
4452
|
+
return compact({
|
|
4453
|
+
enabled: input.enabled, routing_mode: input.routing_mode ?? input.routingMode,
|
|
4454
|
+
fallback_member_id: input.fallback_member_id ?? input.fallbackMemberId,
|
|
4455
|
+
routing_rules: input.routing_rules ?? input.routingRules,
|
|
4456
|
+
members: input.members?.map((member) => compact({
|
|
4457
|
+
id: member.id, role: member.role, label: member.label, description: member.description,
|
|
4458
|
+
instructions: member.instructions, enabled: member.enabled, tools: member.tools,
|
|
4459
|
+
stage_keys: member.stage_keys ?? member.stageKeys,
|
|
4460
|
+
})),
|
|
4461
|
+
});
|
|
4462
|
+
}
|
|
4463
|
+
|
|
4464
|
+
function runtimeRoutingPayload(input?: LabsRuntimeRoutingConfig): Record<string, unknown> | undefined {
|
|
4465
|
+
if (!input) return undefined;
|
|
4466
|
+
return compact({
|
|
4467
|
+
enabled: input.enabled, allowed_models: input.allowed_models ?? input.allowedModels,
|
|
4468
|
+
max_handoffs: input.max_handoffs ?? input.maxHandoffs,
|
|
4469
|
+
recover_on_disconnect: input.recover_on_disconnect ?? input.recoverOnDisconnect,
|
|
4470
|
+
allowed_languages: input.allowed_languages ?? input.allowedLanguages,
|
|
4471
|
+
});
|
|
4472
|
+
}
|
|
4473
|
+
|
|
4349
4474
|
function labsAgentMetadataPayload(input: CreateLabsAgentRequest): Record<string, unknown> | undefined {
|
|
4350
4475
|
const metadata = { ...(input.metadata ?? {}) };
|
|
4351
4476
|
const mode = input.outboundCallMode ?? input.outbound_call_mode;
|
|
@@ -4390,6 +4515,12 @@ function labsAgentPayload(input: CreateLabsAgentRequest): Record<string, unknown
|
|
|
4390
4515
|
preset_key: input.preset_key ?? input.presetKey,
|
|
4391
4516
|
runtime_mode: input.runtime_mode ?? input.runtimeMode,
|
|
4392
4517
|
realtime: input.realtime,
|
|
4518
|
+
manager: managerPayload(input.manager),
|
|
4519
|
+
agent_team: agentTeamPayload(input.agent_team ?? input.agentTeam),
|
|
4520
|
+
runtime_routing: runtimeRoutingPayload(input.runtime_routing ?? input.runtimeRouting),
|
|
4521
|
+
capture_fields: input.capture_fields ?? input.captureFields,
|
|
4522
|
+
timezone: input.timezone ?? input.businessTimezone,
|
|
4523
|
+
time_awareness: input.time_awareness ?? input.timeAwareness,
|
|
4393
4524
|
call_stages: callStagesPayload(input),
|
|
4394
4525
|
stage_generation: input.stage_generation ?? input.stageGeneration,
|
|
4395
4526
|
stage_count: input.stage_count ?? input.stageCount,
|
|
@@ -4410,7 +4541,7 @@ function labsAgentPayload(input: CreateLabsAgentRequest): Record<string, unknown
|
|
|
4410
4541
|
byok: input.byok ? byokPayload(input.byok) : undefined,
|
|
4411
4542
|
telephony: input.telephony ? telephonyPayload(input.telephony) : undefined,
|
|
4412
4543
|
custom_sip: customSipPayload(input.custom_sip ?? input.customSip ?? input.sip),
|
|
4413
|
-
recording: input.recording ? recordingPayload(input.recording) : undefined,
|
|
4544
|
+
recording: input.recording !== undefined ? recordingPayload(input.recording) : undefined,
|
|
4414
4545
|
transcription: input.transcription ? transcriptionPayload(input.transcription) : undefined,
|
|
4415
4546
|
artifacts: input.artifacts ? artifactsPayload(input.artifacts) : undefined,
|
|
4416
4547
|
compliance: input.compliance,
|
|
@@ -4558,8 +4689,6 @@ function callStagesPayload(
|
|
|
4558
4689
|
if (explicit === false || auto === false) return false;
|
|
4559
4690
|
if (explicit === "managed" || explicit === "template" || explicit === "off") return explicit;
|
|
4560
4691
|
if (explicit === "oracle") return "managed";
|
|
4561
|
-
// The S2S backend owns its validated intake → booking → confirmation flow.
|
|
4562
|
-
if (input.realtime) return undefined;
|
|
4563
4692
|
// Omitted means the private Supafone API generates and compiles the plan.
|
|
4564
4693
|
return undefined;
|
|
4565
4694
|
}
|
|
@@ -4579,8 +4708,7 @@ function stagePlanPayload(
|
|
|
4579
4708
|
system_prompt: input.system_prompt ?? input.systemPrompt,
|
|
4580
4709
|
tools: input.tools ? toolsPayload(input.tools) : undefined,
|
|
4581
4710
|
call_stages: Array.isArray(input.call_stages ?? input.callStages ?? input.stages)
|
|
4582
|
-
? (input
|
|
4583
|
-
: undefined,
|
|
4711
|
+
? callStagesPayload(input) : undefined,
|
|
4584
4712
|
stage_generation: input.stage_generation ?? input.stageGeneration,
|
|
4585
4713
|
stage_count: input.stage_count ?? input.stageCount,
|
|
4586
4714
|
stage_detail: input.stage_detail ?? input.stageDetail,
|
|
@@ -4597,6 +4725,12 @@ function callStagePayload(input: LabsCallStage): Record<string, unknown> {
|
|
|
4597
4725
|
tools: input.tools,
|
|
4598
4726
|
temperature: input.temperature,
|
|
4599
4727
|
next_stages: input.next_stages ?? input.nextStages,
|
|
4728
|
+
requirements: input.requirements ? compact({
|
|
4729
|
+
required_fields: input.requirements.required_fields ?? input.requirements.requiredFields,
|
|
4730
|
+
successful_tools: input.requirements.successful_tools ?? input.requirements.successfulTools,
|
|
4731
|
+
}) : undefined,
|
|
4732
|
+
role: input.role,
|
|
4733
|
+
specialist_id: input.specialist_id ?? input.specialistId,
|
|
4600
4734
|
metadata: input.metadata,
|
|
4601
4735
|
});
|
|
4602
4736
|
}
|
|
@@ -4757,6 +4891,8 @@ function providerKeysPayload(input: LabsProviderKeys): Record<string, unknown> {
|
|
|
4757
4891
|
openai_api_key: input.openai_api_key ?? input.openaiApiKey,
|
|
4758
4892
|
xai: input.xai,
|
|
4759
4893
|
xai_api_key: input.xai_api_key ?? input.xaiApiKey,
|
|
4894
|
+
smallest: input.smallest,
|
|
4895
|
+
smallest_api_key: input.smallest_api_key ?? input.smallestApiKey,
|
|
4760
4896
|
});
|
|
4761
4897
|
}
|
|
4762
4898
|
|
|
@@ -4837,9 +4973,11 @@ function emailPayload(input: LabsEmailConfig): Record<string, unknown> {
|
|
|
4837
4973
|
});
|
|
4838
4974
|
}
|
|
4839
4975
|
|
|
4840
|
-
function recordingPayload(input: LabsRecordingConfig): Record<string, unknown> {
|
|
4976
|
+
function recordingPayload(input: LabsRecordingConfig | boolean): Record<string, unknown> | boolean {
|
|
4977
|
+
if (typeof input === "boolean") return input;
|
|
4841
4978
|
return compact({
|
|
4842
4979
|
enabled: input.enabled,
|
|
4980
|
+
transcribe: input.transcribe,
|
|
4843
4981
|
record_audio: input.record_audio ?? input.recordAudio,
|
|
4844
4982
|
consent_required: input.consent_required ?? input.consentRequired,
|
|
4845
4983
|
announcement: input.announcement,
|
package/src/s2s.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreateLabsAgentRequest,
|
|
3
|
+
GetLabsAgentOptions,
|
|
4
|
+
LabsRealtimeSelection,
|
|
5
|
+
SupafoneLabs,
|
|
6
|
+
} from "./index.js";
|
|
7
|
+
|
|
8
|
+
export type S2SProviderName = "ultravox" | "openai" | "google" | "xai" | "smallest";
|
|
9
|
+
export interface S2SModelOptions {
|
|
10
|
+
model?: string;
|
|
11
|
+
voice?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface S2SOptions extends S2SModelOptions {
|
|
14
|
+
provider?: S2SProviderName;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Shared parent for Supafone-hosted S2S agents. Vendor keys stay on the server. */
|
|
18
|
+
export class SupafoneS2S {
|
|
19
|
+
readonly provider: S2SProviderName;
|
|
20
|
+
private readonly selection: LabsRealtimeSelection | null;
|
|
21
|
+
|
|
22
|
+
constructor(protected readonly client: SupafoneLabs, options: S2SOptions = {}) {
|
|
23
|
+
const provider = options.provider ?? "ultravox";
|
|
24
|
+
if (!["ultravox", "openai", "google", "xai", "smallest"].includes(provider)) {
|
|
25
|
+
throw new Error("Unsupported Supafone S2S provider");
|
|
26
|
+
}
|
|
27
|
+
if (provider === "ultravox" && (options.model !== undefined || options.voice !== undefined)) {
|
|
28
|
+
throw new Error("Configure Ultravox voices through the agent's voice settings");
|
|
29
|
+
}
|
|
30
|
+
for (const field of ["model", "voice"] as const) {
|
|
31
|
+
const value = options[field];
|
|
32
|
+
if (value !== undefined && (typeof value !== "string" || !value.trim())) {
|
|
33
|
+
throw new Error(`${field} must be a non-empty string`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
this.provider = provider;
|
|
37
|
+
this.selection = provider === "ultravox" ? null : {
|
|
38
|
+
provider,
|
|
39
|
+
...(options.model !== undefined ? { model: options.model.trim() } : {}),
|
|
40
|
+
...(options.voice !== undefined ? { voice: options.voice.trim() } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** A fresh wire selection; null explicitly restores the default Ultravox runtime. */
|
|
45
|
+
get realtime(): LabsRealtimeSelection | null {
|
|
46
|
+
return this.selection ? { ...this.selection } : null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Create through the normal hosted agent factory with this provider. */
|
|
50
|
+
create(input: Omit<CreateLabsAgentRequest, "realtime">) {
|
|
51
|
+
if ("realtime" in input) {
|
|
52
|
+
throw new Error("Set provider/model/voice on the S2S adapter, not create({realtime: ...})");
|
|
53
|
+
}
|
|
54
|
+
return this.client.labs.agents.create({
|
|
55
|
+
...input,
|
|
56
|
+
...(this.realtime ? { realtime: this.realtime } : {}),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Change the saved selection for subsequent calls, preserving the agent and number. */
|
|
61
|
+
apply(agentKey: string, options: GetLabsAgentOptions = {}) {
|
|
62
|
+
this.checkAgentKey(agentKey);
|
|
63
|
+
return this.client.labs.agents.update(agentKey, { realtime: this.realtime }, options);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Preview the saved agent. Call apply first when switching providers. */
|
|
67
|
+
testCall(agentKey: string, options: GetLabsAgentOptions = {}) {
|
|
68
|
+
this.checkAgentKey(agentKey);
|
|
69
|
+
return this.client.labs.agents.testCall(agentKey, options);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private checkAgentKey(agentKey: string): void {
|
|
73
|
+
if (typeof agentKey !== "string" || !agentKey.trim()) throw new Error("agentKey is required");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class UltravoxS2S extends SupafoneS2S {
|
|
78
|
+
constructor(client: SupafoneLabs) { super(client, { provider: "ultravox" }); }
|
|
79
|
+
}
|
|
80
|
+
export class OpenAIS2S extends SupafoneS2S {
|
|
81
|
+
constructor(client: SupafoneLabs, options: S2SModelOptions = {}) {
|
|
82
|
+
super(client, { ...options, provider: "openai" });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export class GeminiS2S extends SupafoneS2S {
|
|
86
|
+
constructor(client: SupafoneLabs, options: S2SModelOptions = {}) {
|
|
87
|
+
super(client, { ...options, provider: "google" });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export class GrokS2S extends SupafoneS2S {
|
|
91
|
+
constructor(client: SupafoneLabs, options: S2SModelOptions = {}) {
|
|
92
|
+
super(client, { ...options, provider: "xai" });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Smallest AI Hydra: full-duplex audio, without transcript events. */
|
|
96
|
+
export class HydraS2S extends SupafoneS2S {
|
|
97
|
+
constructor(client: SupafoneLabs, options: S2SModelOptions = {}) {
|
|
98
|
+
super(client, { ...options, provider: "smallest" });
|
|
99
|
+
}
|
|
100
|
+
}
|