supafone-labs 0.6.3 → 0.7.2

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/src/index.ts CHANGED
@@ -224,9 +224,70 @@ export interface LabsCallStage {
224
224
  temperature?: number;
225
225
  nextStages?: string[];
226
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;
227
232
  metadata?: Record<string, unknown>;
228
233
  }
229
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
+
230
291
  export type LabsStageGeneration = "managed" | "template" | "off" | "oracle";
231
292
 
232
293
  export interface LabsCallPlan {
@@ -692,6 +753,8 @@ export interface LabsEmailConfig {
692
753
 
693
754
  export interface LabsRecordingConfig {
694
755
  enabled?: boolean;
756
+ /** Request post-call transcription of the recording where configured. */
757
+ transcribe?: boolean;
695
758
  recordAudio?: boolean;
696
759
  record_audio?: boolean;
697
760
  consentRequired?: boolean;
@@ -1044,6 +1107,17 @@ export interface CreateLabsAgentRequest {
1044
1107
  presetKey?: string;
1045
1108
  preset_key?: string;
1046
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;
1047
1121
  runtimeMode?: LabsRuntimeMode;
1048
1122
  runtime_mode?: LabsRuntimeMode;
1049
1123
  /** Defaults to Supafone's hosted planner; model credentials remain server-side. */
@@ -1086,7 +1160,7 @@ export interface CreateLabsAgentRequest {
1086
1160
  customSip?: LabsCustomSipConfig;
1087
1161
  custom_sip?: LabsCustomSipConfig;
1088
1162
  sip?: LabsCustomSipConfig;
1089
- recording?: LabsRecordingConfig;
1163
+ recording?: boolean | LabsRecordingConfig;
1090
1164
  transcription?: LabsTranscriptionConfig;
1091
1165
  artifacts?: LabsArtifactsConfig;
1092
1166
  compliance?: Record<string, unknown>;
@@ -1308,12 +1382,25 @@ export interface LabsVoicePreview {
1308
1382
  export interface LabsRuntimeResponse {
1309
1383
  account_id: string;
1310
1384
  provider: "ultravox" | string;
1311
- managed: boolean;
1312
- byok_connected: boolean;
1385
+ /** Optional for compatibility with earlier hosted API deployments. */
1386
+ managed?: boolean;
1387
+ byok_connected?: boolean;
1388
+ configured?: boolean;
1389
+ connected?: boolean;
1390
+ source?: "account" | "platform" | "none" | "invalid";
1313
1391
  base_url?: string;
1314
1392
  updated_at?: string;
1315
1393
  }
1316
1394
 
1395
+ export interface LabsRuntimeConfig {
1396
+ agencyId?: string;
1397
+ agency_id?: string;
1398
+ provider?: string;
1399
+ /** Account-wide: managed removes this provider's saved key for future calls. */
1400
+ mode?: "supafone_managed" | "byok";
1401
+ credentials?: { apiKey?: string; api_key?: string; baseUrl?: string; base_url?: string };
1402
+ }
1403
+
1317
1404
  export interface LabsCallListOptions {
1318
1405
  agencyId?: string;
1319
1406
  agency_id?: string;
@@ -3764,25 +3851,34 @@ class LabsVoicesNamespace {
3764
3851
  class LabsRuntimeNamespace {
3765
3852
  constructor(private sm: SupafoneLabs) {}
3766
3853
 
3767
- get(opts: { agencyId?: string; agency_id?: string } = {}): Promise<LabsRuntimeResponse> {
3854
+ get(opts: { agencyId?: string; agency_id?: string; provider?: string } = {}): Promise<LabsRuntimeResponse> {
3768
3855
  const q = new URLSearchParams();
3769
3856
  const agencyId = opts.agency_id ?? opts.agencyId;
3770
3857
  if (agencyId) q.set("agency_id", agencyId);
3858
+ if (opts.provider) q.set("provider", opts.provider);
3771
3859
  const suffix = q.toString() ? `?${q}` : "";
3772
3860
  return this.sm.requestSupafoneApi<LabsRuntimeResponse>("GET", `/api/v1/labs/runtime${suffix}`);
3773
3861
  }
3774
3862
 
3775
- configure(input: {
3776
- agencyId?: string;
3777
- agency_id?: string;
3778
- provider?: "ultravox" | string;
3779
- credentials?: { apiKey?: string; api_key?: string; baseUrl?: string; base_url?: string };
3780
- }): Promise<LabsRuntimeResponse> {
3863
+ /** Set an account speaking key, or restore the selected provider's platform default. */
3864
+ configure(input: LabsRuntimeConfig): Promise<LabsRuntimeResponse> {
3865
+ if (input.mode !== undefined && !["supafone_managed", "byok"].includes(input.mode)) {
3866
+ throw new Error("runtime mode must be supafone_managed or byok");
3867
+ }
3781
3868
  const credentials = input.credentials ?? {};
3869
+ if (typeof credentials !== "object" || Array.isArray(credentials)) {
3870
+ throw new Error("runtime credentials must be an object");
3871
+ }
3872
+ if (input.mode === "supafone_managed" && Object.values(credentials).some(
3873
+ value => typeof value === "string" ? Boolean(value.trim()) : Boolean(value),
3874
+ )) {
3875
+ throw new Error("managed runtime mode cannot include credentials");
3876
+ }
3782
3877
  return this.sm.requestSupafoneApi<LabsRuntimeResponse>("PUT", "/api/v1/labs/runtime", compact({
3783
3878
  agency_id: input.agency_id ?? input.agencyId,
3784
3879
  provider: input.provider ?? "ultravox",
3785
- credentials: compact({
3880
+ mode: input.mode,
3881
+ credentials: input.mode === "supafone_managed" ? undefined : compact({
3786
3882
  api_key: credentials.api_key ?? credentials.apiKey,
3787
3883
  base_url: credentials.base_url ?? credentials.baseUrl,
3788
3884
  }),
@@ -4363,6 +4459,40 @@ function outboundCallModeRequiredCapabilities(payload: Record<string, unknown>):
4363
4459
  return required;
4364
4460
  }
4365
4461
 
4462
+ function managerPayload(input?: boolean | LabsManagerConfig): boolean | Record<string, unknown> | undefined {
4463
+ if (typeof input !== "object" || input === null) return input;
4464
+ return compact({
4465
+ enabled: input.enabled, reasoning: input.reasoning, model: input.model,
4466
+ max_tasks: input.max_tasks ?? input.maxTasks,
4467
+ max_parallel: input.max_parallel ?? input.maxParallel,
4468
+ timeout_seconds: input.timeout_seconds ?? input.timeoutSeconds,
4469
+ });
4470
+ }
4471
+
4472
+ function agentTeamPayload(input?: LabsAgentTeam): Record<string, unknown> | undefined {
4473
+ if (!input) return undefined;
4474
+ return compact({
4475
+ enabled: input.enabled, routing_mode: input.routing_mode ?? input.routingMode,
4476
+ fallback_member_id: input.fallback_member_id ?? input.fallbackMemberId,
4477
+ routing_rules: input.routing_rules ?? input.routingRules,
4478
+ members: input.members?.map((member) => compact({
4479
+ id: member.id, role: member.role, label: member.label, description: member.description,
4480
+ instructions: member.instructions, enabled: member.enabled, tools: member.tools,
4481
+ stage_keys: member.stage_keys ?? member.stageKeys,
4482
+ })),
4483
+ });
4484
+ }
4485
+
4486
+ function runtimeRoutingPayload(input?: LabsRuntimeRoutingConfig): Record<string, unknown> | undefined {
4487
+ if (!input) return undefined;
4488
+ return compact({
4489
+ enabled: input.enabled, allowed_models: input.allowed_models ?? input.allowedModels,
4490
+ max_handoffs: input.max_handoffs ?? input.maxHandoffs,
4491
+ recover_on_disconnect: input.recover_on_disconnect ?? input.recoverOnDisconnect,
4492
+ allowed_languages: input.allowed_languages ?? input.allowedLanguages,
4493
+ });
4494
+ }
4495
+
4366
4496
  function labsAgentMetadataPayload(input: CreateLabsAgentRequest): Record<string, unknown> | undefined {
4367
4497
  const metadata = { ...(input.metadata ?? {}) };
4368
4498
  const mode = input.outboundCallMode ?? input.outbound_call_mode;
@@ -4407,6 +4537,12 @@ function labsAgentPayload(input: CreateLabsAgentRequest): Record<string, unknown
4407
4537
  preset_key: input.preset_key ?? input.presetKey,
4408
4538
  runtime_mode: input.runtime_mode ?? input.runtimeMode,
4409
4539
  realtime: input.realtime,
4540
+ manager: managerPayload(input.manager),
4541
+ agent_team: agentTeamPayload(input.agent_team ?? input.agentTeam),
4542
+ runtime_routing: runtimeRoutingPayload(input.runtime_routing ?? input.runtimeRouting),
4543
+ capture_fields: input.capture_fields ?? input.captureFields,
4544
+ timezone: input.timezone ?? input.businessTimezone,
4545
+ time_awareness: input.time_awareness ?? input.timeAwareness,
4410
4546
  call_stages: callStagesPayload(input),
4411
4547
  stage_generation: input.stage_generation ?? input.stageGeneration,
4412
4548
  stage_count: input.stage_count ?? input.stageCount,
@@ -4427,7 +4563,7 @@ function labsAgentPayload(input: CreateLabsAgentRequest): Record<string, unknown
4427
4563
  byok: input.byok ? byokPayload(input.byok) : undefined,
4428
4564
  telephony: input.telephony ? telephonyPayload(input.telephony) : undefined,
4429
4565
  custom_sip: customSipPayload(input.custom_sip ?? input.customSip ?? input.sip),
4430
- recording: input.recording ? recordingPayload(input.recording) : undefined,
4566
+ recording: input.recording !== undefined ? recordingPayload(input.recording) : undefined,
4431
4567
  transcription: input.transcription ? transcriptionPayload(input.transcription) : undefined,
4432
4568
  artifacts: input.artifacts ? artifactsPayload(input.artifacts) : undefined,
4433
4569
  compliance: input.compliance,
@@ -4575,8 +4711,6 @@ function callStagesPayload(
4575
4711
  if (explicit === false || auto === false) return false;
4576
4712
  if (explicit === "managed" || explicit === "template" || explicit === "off") return explicit;
4577
4713
  if (explicit === "oracle") return "managed";
4578
- // The S2S backend owns its validated intake → booking → confirmation flow.
4579
- if (input.realtime) return undefined;
4580
4714
  // Omitted means the private Supafone API generates and compiles the plan.
4581
4715
  return undefined;
4582
4716
  }
@@ -4596,8 +4730,7 @@ function stagePlanPayload(
4596
4730
  system_prompt: input.system_prompt ?? input.systemPrompt,
4597
4731
  tools: input.tools ? toolsPayload(input.tools) : undefined,
4598
4732
  call_stages: Array.isArray(input.call_stages ?? input.callStages ?? input.stages)
4599
- ? (input.call_stages ?? input.callStages ?? input.stages)
4600
- : undefined,
4733
+ ? callStagesPayload(input) : undefined,
4601
4734
  stage_generation: input.stage_generation ?? input.stageGeneration,
4602
4735
  stage_count: input.stage_count ?? input.stageCount,
4603
4736
  stage_detail: input.stage_detail ?? input.stageDetail,
@@ -4614,6 +4747,12 @@ function callStagePayload(input: LabsCallStage): Record<string, unknown> {
4614
4747
  tools: input.tools,
4615
4748
  temperature: input.temperature,
4616
4749
  next_stages: input.next_stages ?? input.nextStages,
4750
+ requirements: input.requirements ? compact({
4751
+ required_fields: input.requirements.required_fields ?? input.requirements.requiredFields,
4752
+ successful_tools: input.requirements.successful_tools ?? input.requirements.successfulTools,
4753
+ }) : undefined,
4754
+ role: input.role,
4755
+ specialist_id: input.specialist_id ?? input.specialistId,
4617
4756
  metadata: input.metadata,
4618
4757
  });
4619
4758
  }
@@ -4856,9 +4995,11 @@ function emailPayload(input: LabsEmailConfig): Record<string, unknown> {
4856
4995
  });
4857
4996
  }
4858
4997
 
4859
- function recordingPayload(input: LabsRecordingConfig): Record<string, unknown> {
4998
+ function recordingPayload(input: LabsRecordingConfig | boolean): Record<string, unknown> | boolean {
4999
+ if (typeof input === "boolean") return input;
4860
5000
  return compact({
4861
5001
  enabled: input.enabled,
5002
+ transcribe: input.transcribe,
4862
5003
  record_audio: input.record_audio ?? input.recordAudio,
4863
5004
  consent_required: input.consent_required ?? input.consentRequired,
4864
5005
  announcement: input.announcement,