supafone-labs 0.6.3 → 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 CHANGED
@@ -52,47 +52,36 @@ silent directive, and the exact primitive for each, is in
52
52
 
53
53
  ## Supported frameworks
54
54
 
55
- Silent injection feeds the live agent hidden guidance it acts on but never
56
- speaks. Two mechanisms cover every supported framework:
57
-
58
- - **Mode A — native silent event:** speech-to-speech models take a vendor event
59
- that adds context without triggering speech.
60
- - **Mode B — own the LLM:** for STT→LLM→TTS pipelines, Supafone plugs in as the
61
- LLM and splices a `system`/`developer` message into the prompt.
62
-
63
- **Possible — 10 frameworks**, each with a real injection door:
64
-
65
- | Framework | Mode | Exact primitive |
66
- | --- | :--: | --- |
67
- | Ultravox | A | `send_data_message` (`urgency:"later"`) — **live/proven today** |
68
- | OpenAI Realtime | A | `conversation.item.create` (role `system`, no `response.create`) |
69
- | Grok (xAI) | A | OpenAI-Realtime-compatible item inject |
70
- | Gemini Live | A | `clientContent` (`turnComplete:false`, role `user`) |
71
- | ElevenLabs | A | `contextual_update` |
72
- | Inworld | A | OpenAI-Realtime-compatible item inject |
73
- | Vapi | A+B | `add-message` (`triggerResponseEnabled:false`) or custom-LLM splice |
74
- | Retell | B | `system` message into the custom-LLM turn |
75
- | Deepgram | A+B | `UpdatePrompt`, or own the `think` LLM |
76
- | LiveKit | B | inject into `chat_ctx` in-process |
77
-
78
- **Impossible — Bland:** its live-call API is stop/listen/transfer only, with no
79
- mid-call inject channel and no custom-LLM. Observe and score it, but you cannot
80
- whisper to it live — a permanent vendor limitation, not a Supafone gap.
81
- **Cartesia** (a TTS voice) and **Pipecat** (a DIY framework you own end to end)
82
- are not conversational agents, so there is nothing to inject into.
83
-
84
- Injection is *possible* for all 10, but managed delivery is wired end-to-end
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
88
- needs that vendor's key — free/trial tiers exist for all except OpenAI Realtime
89
- (paid, no free tier). Full matrix:
90
- [gitbook/framework-support.md](../gitbook/framework-support.md). *(The npm
91
- package-page copy updates on the next release.)*
55
+ Supervisor delivers approved guidance through the control surface exposed by
56
+ the selected adapter. The standalone SDK and hosted Agent Factory have separate
57
+ capability contracts:
58
+
59
+ - **Native control adapters:** Supafone/Ultravox, OpenAI Realtime, Grok,
60
+ Vapi, ElevenLabs Agents, Deepgram Voice Agent and Inworld Realtime.
61
+ For example, Ultravox uses a deferred data message; Grok uses
62
+ `response.create.instructions`, with `response.created` followed by
63
+ `response.done` as protocol acknowledgement.
64
+ - **Developer-owned conversation context:** Retell custom LLM, LiveKit Agents
65
+ and Pipecat apply guidance inside the loop the integrator controls.
66
+ - **Observation-only by default:** Gemini Developer Live and Bland emit no
67
+ hidden instruction through the default standalone adapter. Ordinary Gemini
68
+ `clientContent` is conversation history, not privileged system control.
69
+ Cartesia Line needs an explicit custom-event hook in the target agent.
70
+
71
+ Hosted Agent Factory supports coaching across Ultravox, OpenAI, Gemini, Grok
72
+ and Hydra through its managed call paths. Native calls use `check_guidance`
73
+ tool results; Hydra's live observations are model-reported because it supplies
74
+ no native transcript stream. This does not change the standalone adapter's
75
+ capabilities or prove that a model followed the guidance.
76
+
77
+ See the [framework matrix](../gitbook/framework-support.md) and
78
+ [provider contracts](../docs/providers.md) for delivery and acceptance details.
79
+ Live validation requires configured provider access; local contract tests do
80
+ not certify a production call.
92
81
 
93
82
  ## One S2S interface, five providers
94
83
 
95
- Version 0.6.3 exports `SupafoneS2S`, the shared parent of `UltravoxS2S`,
84
+ Since version 0.6.3, the SDK exports `SupafoneS2S`, the shared parent of `UltravoxS2S`,
96
85
  `OpenAIS2S`, `GeminiS2S`, `GrokS2S`, and `HydraS2S`. These classes use
97
86
  Supafone's hosted Agent Factory. Supafone handles the audio adapter, tools,
98
87
  stages, and supported phone transport behind one API.
@@ -130,7 +119,8 @@ agent and does not implicitly switch providers. The same constructors and
130
119
  | Smallest AI | `hydra-v1.0` | `sterling` |
131
120
 
132
121
  The existing `realtime: { provider, model, voice }` API remains supported.
133
- Native models use the fixed intake → booking → confirmation flow. The phone
122
+ All five speaking families use the shared generated/custom stage plan, Manager
123
+ and specialist consultations. The phone
134
124
  paths are Supafone-managed numbers, BYO Twilio, Telnyx, Plivo, and SIP through
135
125
  LiveKit. Carrier provisioning and credentials still determine call readiness.
136
126
 
@@ -140,12 +130,23 @@ provider key when Supafone has one configured. Missing keys produce an
140
130
  unavailable preview instead of a live provider call.
141
131
 
142
132
  Hydra supports English audio and tools, without transcript events or mutable
143
- mid-session persona/voice. Supafone supplies its fixed stages at session start
133
+ mid-session persona/voice. Supafone supplies the frozen call plan at session start
144
134
  and advances the stage using tool results. Hydra 1.1 uses 16 kHz input / 24 kHz
145
135
  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.
136
+ support opt-in recording, public widgets, configured carrier controls and
137
+ allowed-model handoff. A handoff opens a replacement session; a carrier transfer
138
+ acknowledgement does not mean a human answered. Hydra has no live transcript
139
+ stream; optional post-call transcription needs a recording and server Deepgram
140
+ credentials. Ultravox retains compatible external TTS and its profile router.
141
+ All five hosted speaking families support optional Supervisor coaching. Native
142
+ models receive guidance through `check_guidance`; Hydra supplies explicitly
143
+ labeled model-reported context rather than transcripts.
147
144
  See the [unified S2S guide](https://labs.supafone.ai/docs/unified-s2s/) and
148
145
  [capability matrix](https://labs.supafone.ai/docs/realtime-agent-factory/).
146
+ See [Shared runtime, Manager and teams](https://labs.supafone.ai/docs/shared-agent-runtime/)
147
+ for `manager`, `agentTeam`, structured stage requirements, `recording` and
148
+ `runtimeRouting`. Both SDKs preserve explicit empty stage-tool and edge arrays.
149
+
149
150
  ## Spawn a hosted Supafone agent
150
151
 
151
152
  Use the same package to create finished Supafone agents from code. This hits the
@@ -229,7 +230,7 @@ import { Supafone } from "supafone-labs";
229
230
  const supafone = new Supafone({
230
231
  apiKey: process.env.SUPAFONE_LABS_API_KEY || process.env.SUPAFONE_API_KEY!,
231
232
  supafoneApiKey: process.env.SUPAFONE_API_KEY!,
232
- // Supafone Supervisor is on by default for live guidance, QA, and scoring.
233
+ // Requests Supervisor by default; its model credentials must also be configured.
233
234
  // Set false only when you intentionally need an unsupervised agent.
234
235
  supervisor: true,
235
236
  // Defaults to https://api.supafone.ai. Override for staging/local tests.
@@ -257,11 +258,7 @@ const inbound = await supafone.labs.agents.createInboundWithNumber({
257
258
  },
258
259
  recording: {
259
260
  enabled: true,
260
- recordAudio: true,
261
- consentRequired: true,
262
- announcement: "This call may be recorded for quality and training.",
263
- retentionDays: 30,
264
- redactPii: true,
261
+ transcribe: true,
265
262
  },
266
263
  transcription: {
267
264
  enabled: true,
@@ -384,37 +381,40 @@ agent; fetches it back; verifies `runtime.telephony.mode` is `supafone_managed`
384
381
  and the runtime is managed (`runtime.managed === true`, no developer Ultravox key
385
382
  required); and prints the returned widget snippet.
386
383
 
387
- ## Hosted voices
384
+ ## Hosted voices: Ultravox + custom TTS
388
385
 
389
- Select a current provider voice from plain-language intent:
386
+ The managed Ultravox option remains part of the shared S2S offering. Its
387
+ conversation runtime and compatible TTS voice are separate choices:
390
388
 
391
389
  ```ts
392
- const matches = await supafone.labs.voices.recommend({
393
- description: "calm Spanish customer-support voice",
394
- language: "es-MX",
395
- configuredOnly: true,
396
- });
390
+ import { UltravoxS2S } from "supafone-labs";
397
391
 
398
- const voice = matches.matches[0].voice;
399
- await supafone.labs.agents.createInbound({
392
+ const catalog = await supafone.labs.voices.list({ provider: "cartesia" });
393
+ console.log(catalog.voices);
394
+
395
+ await new UltravoxS2S(supafone).create({
400
396
  name: "Spanish support",
401
- voice: supafone.labs.voices.selection(voice),
397
+ voice: { provider: "cartesia", voiceId: process.env.CARTESIA_VOICE_ID! },
402
398
  });
403
399
  ```
404
400
 
405
- The hosted catalog refreshes Ultravox, Cartesia, ElevenLabs, and Inworld and
406
- normalizes names, languages, gender, accent, voice type, model limits, and the
407
- Ultravox-compatible language intersection. Full reference:
408
- [Dynamic Voice Catalog and Selection](../gitbook/voice-catalog-and-selection.md).
409
-
410
- Labs Cloud also exposes direct hosted TTS and STT:
411
-
412
- ```ts
413
- const wav = await supafone.tts("You're all set — talk soon!", "supafone-labs-calm-en");
414
- // wav: Uint8Array
415
-
416
- const text = await supafone.stt(audioBytes, { language: "en" });
417
- ```
401
+ Use a real, configured catalog voice. Compatible Ultravox, Cartesia, ElevenLabs,
402
+ and Inworld voices can supply the managed agent's speech. Native OpenAI,
403
+ Gemini, Grok, and Hydra use their own model voices; external TTS is not a
404
+ universal override. Deepgram is preview-only in the current hosted Ultravox
405
+ integration. Custom TTS backends are for developer-owned synthesis unless a
406
+ hosted runtime bridge explicitly supports them.
407
+
408
+ The published SDK 0.7.0 exposes `labs.voices.list`, `listAll`, `capabilities`,
409
+ `recommend`, `preview`, and `selection`. Use `listAll` for automatic catalog
410
+ pagination, then pass `selection(voice)` into managed agent creation. These
411
+ helpers query the hosted voice catalog; they do not enable external TTS on
412
+ native OpenAI, Gemini, Grok, or Hydra sessions.
413
+ See [voice-output choices](https://labs.supafone.ai/docs/voice-output-modes/) and
414
+ [the voice catalog](https://labs.supafone.ai/docs/voice-catalog-and-selection/).
415
+
416
+ Labs Cloud's standalone `tts` and `stt` methods remain separate synthesis and
417
+ transcription tools; using them does not change a saved agent's speaking model.
418
418
 
419
419
  ## Live multilingual transcription
420
420
 
@@ -199,8 +199,74 @@ export interface LabsCallStage {
199
199
  temperature?: number;
200
200
  nextStages?: string[];
201
201
  next_stages?: string[];
202
+ /** Server-enforced exit gates, independent of conversational exit criteria. */
203
+ requirements?: LabsStageRequirements;
204
+ role?: string;
205
+ specialistId?: string;
206
+ specialist_id?: string;
202
207
  metadata?: Record<string, unknown>;
203
208
  }
209
+ export interface LabsStageRequirements {
210
+ requiredFields?: string[];
211
+ required_fields?: string[];
212
+ successfulTools?: string[];
213
+ successful_tools?: string[];
214
+ }
215
+ export interface LabsManagerConfig {
216
+ enabled?: boolean;
217
+ /** Reuse the existing encrypted Supervisor profile, or use managed reasoning. */
218
+ reasoning?: "managed" | "supervisor";
219
+ model?: "supafone-manager" | "supafone-manager-pro";
220
+ maxTasks?: number;
221
+ max_tasks?: number;
222
+ maxParallel?: number;
223
+ max_parallel?: number;
224
+ timeoutSeconds?: number;
225
+ timeout_seconds?: number;
226
+ }
227
+ export interface LabsSpecialist {
228
+ id: string;
229
+ role?: string;
230
+ label?: string;
231
+ description?: string;
232
+ instructions?: string;
233
+ enabled?: boolean;
234
+ stageKeys?: string[];
235
+ stage_keys?: string[];
236
+ tools?: string[];
237
+ }
238
+ export interface LabsAgentTeam {
239
+ enabled?: boolean;
240
+ routingMode?: "auto" | "sequential";
241
+ routing_mode?: "auto" | "sequential";
242
+ fallbackMemberId?: string;
243
+ fallback_member_id?: string;
244
+ members?: LabsSpecialist[];
245
+ routingRules?: Array<{
246
+ intent: string;
247
+ member_id: string;
248
+ priority?: string;
249
+ action?: string;
250
+ }>;
251
+ routing_rules?: Array<{
252
+ intent: string;
253
+ member_id: string;
254
+ priority?: string;
255
+ action?: string;
256
+ }>;
257
+ }
258
+ export interface LabsRuntimeRoutingConfig {
259
+ enabled?: boolean;
260
+ allowedModels?: LabsRealtimeSelection[];
261
+ allowed_models?: LabsRealtimeSelection[];
262
+ /** Server-supported range is 1–3 handoffs per call. */
263
+ maxHandoffs?: number;
264
+ max_handoffs?: number;
265
+ recoverOnDisconnect?: boolean;
266
+ recover_on_disconnect?: boolean;
267
+ allowedLanguages?: string[];
268
+ allowed_languages?: string[];
269
+ }
204
270
  export type LabsStageGeneration = "managed" | "template" | "off" | "oracle";
205
271
  export interface LabsCallPlan {
206
272
  version: "supafone_call_plan_v1" | string;
@@ -646,6 +712,8 @@ export interface LabsEmailConfig {
646
712
  }
647
713
  export interface LabsRecordingConfig {
648
714
  enabled?: boolean;
715
+ /** Request post-call transcription of the recording where configured. */
716
+ transcribe?: boolean;
649
717
  recordAudio?: boolean;
650
718
  record_audio?: boolean;
651
719
  consentRequired?: boolean;
@@ -885,6 +953,17 @@ export interface CreateLabsAgentRequest {
885
953
  presetKey?: string;
886
954
  preset_key?: string;
887
955
  realtime?: LabsRealtimeSelection;
956
+ manager?: boolean | LabsManagerConfig;
957
+ agentTeam?: LabsAgentTeam;
958
+ agent_team?: LabsAgentTeam;
959
+ runtimeRouting?: LabsRuntimeRoutingConfig;
960
+ runtime_routing?: LabsRuntimeRoutingConfig;
961
+ captureFields?: string[];
962
+ capture_fields?: string[];
963
+ timezone?: string;
964
+ businessTimezone?: string;
965
+ timeAwareness?: boolean;
966
+ time_awareness?: boolean;
888
967
  runtimeMode?: LabsRuntimeMode;
889
968
  runtime_mode?: LabsRuntimeMode;
890
969
  /** Defaults to Supafone's hosted planner; model credentials remain server-side. */
@@ -927,7 +1006,7 @@ export interface CreateLabsAgentRequest {
927
1006
  customSip?: LabsCustomSipConfig;
928
1007
  custom_sip?: LabsCustomSipConfig;
929
1008
  sip?: LabsCustomSipConfig;
930
- recording?: LabsRecordingConfig;
1009
+ recording?: boolean | LabsRecordingConfig;
931
1010
  transcription?: LabsTranscriptionConfig;
932
1011
  artifacts?: LabsArtifactsConfig;
933
1012
  compliance?: Record<string, unknown>;
package/dist/cjs/index.js CHANGED
@@ -2015,6 +2015,40 @@ function outboundCallModeRequiredCapabilities(payload) {
2015
2015
  required.push("observability");
2016
2016
  return required;
2017
2017
  }
2018
+ function managerPayload(input) {
2019
+ if (typeof input !== "object" || input === null)
2020
+ return input;
2021
+ return compact({
2022
+ enabled: input.enabled, reasoning: input.reasoning, model: input.model,
2023
+ max_tasks: input.max_tasks ?? input.maxTasks,
2024
+ max_parallel: input.max_parallel ?? input.maxParallel,
2025
+ timeout_seconds: input.timeout_seconds ?? input.timeoutSeconds,
2026
+ });
2027
+ }
2028
+ function agentTeamPayload(input) {
2029
+ if (!input)
2030
+ return undefined;
2031
+ return compact({
2032
+ enabled: input.enabled, routing_mode: input.routing_mode ?? input.routingMode,
2033
+ fallback_member_id: input.fallback_member_id ?? input.fallbackMemberId,
2034
+ routing_rules: input.routing_rules ?? input.routingRules,
2035
+ members: input.members?.map((member) => compact({
2036
+ id: member.id, role: member.role, label: member.label, description: member.description,
2037
+ instructions: member.instructions, enabled: member.enabled, tools: member.tools,
2038
+ stage_keys: member.stage_keys ?? member.stageKeys,
2039
+ })),
2040
+ });
2041
+ }
2042
+ function runtimeRoutingPayload(input) {
2043
+ if (!input)
2044
+ return undefined;
2045
+ return compact({
2046
+ enabled: input.enabled, allowed_models: input.allowed_models ?? input.allowedModels,
2047
+ max_handoffs: input.max_handoffs ?? input.maxHandoffs,
2048
+ recover_on_disconnect: input.recover_on_disconnect ?? input.recoverOnDisconnect,
2049
+ allowed_languages: input.allowed_languages ?? input.allowedLanguages,
2050
+ });
2051
+ }
2018
2052
  function labsAgentMetadataPayload(input) {
2019
2053
  const metadata = { ...(input.metadata ?? {}) };
2020
2054
  const mode = input.outboundCallMode ?? input.outbound_call_mode;
@@ -2056,6 +2090,12 @@ function labsAgentPayload(input) {
2056
2090
  preset_key: input.preset_key ?? input.presetKey,
2057
2091
  runtime_mode: input.runtime_mode ?? input.runtimeMode,
2058
2092
  realtime: input.realtime,
2093
+ manager: managerPayload(input.manager),
2094
+ agent_team: agentTeamPayload(input.agent_team ?? input.agentTeam),
2095
+ runtime_routing: runtimeRoutingPayload(input.runtime_routing ?? input.runtimeRouting),
2096
+ capture_fields: input.capture_fields ?? input.captureFields,
2097
+ timezone: input.timezone ?? input.businessTimezone,
2098
+ time_awareness: input.time_awareness ?? input.timeAwareness,
2059
2099
  call_stages: callStagesPayload(input),
2060
2100
  stage_generation: input.stage_generation ?? input.stageGeneration,
2061
2101
  stage_count: input.stage_count ?? input.stageCount,
@@ -2073,7 +2113,7 @@ function labsAgentPayload(input) {
2073
2113
  byok: input.byok ? byokPayload(input.byok) : undefined,
2074
2114
  telephony: input.telephony ? telephonyPayload(input.telephony) : undefined,
2075
2115
  custom_sip: customSipPayload(input.custom_sip ?? input.customSip ?? input.sip),
2076
- recording: input.recording ? recordingPayload(input.recording) : undefined,
2116
+ recording: input.recording !== undefined ? recordingPayload(input.recording) : undefined,
2077
2117
  transcription: input.transcription ? transcriptionPayload(input.transcription) : undefined,
2078
2118
  artifacts: input.artifacts ? artifactsPayload(input.artifacts) : undefined,
2079
2119
  compliance: input.compliance,
@@ -2217,9 +2257,6 @@ function callStagesPayload(input) {
2217
2257
  return explicit;
2218
2258
  if (explicit === "oracle")
2219
2259
  return "managed";
2220
- // The S2S backend owns its validated intake → booking → confirmation flow.
2221
- if (input.realtime)
2222
- return undefined;
2223
2260
  // Omitted means the private Supafone API generates and compiles the plan.
2224
2261
  return undefined;
2225
2262
  }
@@ -2236,8 +2273,7 @@ function stagePlanPayload(input) {
2236
2273
  system_prompt: input.system_prompt ?? input.systemPrompt,
2237
2274
  tools: input.tools ? toolsPayload(input.tools) : undefined,
2238
2275
  call_stages: Array.isArray(input.call_stages ?? input.callStages ?? input.stages)
2239
- ? (input.call_stages ?? input.callStages ?? input.stages)
2240
- : undefined,
2276
+ ? callStagesPayload(input) : undefined,
2241
2277
  stage_generation: input.stage_generation ?? input.stageGeneration,
2242
2278
  stage_count: input.stage_count ?? input.stageCount,
2243
2279
  stage_detail: input.stage_detail ?? input.stageDetail,
@@ -2253,6 +2289,12 @@ function callStagePayload(input) {
2253
2289
  tools: input.tools,
2254
2290
  temperature: input.temperature,
2255
2291
  next_stages: input.next_stages ?? input.nextStages,
2292
+ requirements: input.requirements ? compact({
2293
+ required_fields: input.requirements.required_fields ?? input.requirements.requiredFields,
2294
+ successful_tools: input.requirements.successful_tools ?? input.requirements.successfulTools,
2295
+ }) : undefined,
2296
+ role: input.role,
2297
+ specialist_id: input.specialist_id ?? input.specialistId,
2256
2298
  metadata: input.metadata,
2257
2299
  });
2258
2300
  }
@@ -2471,8 +2513,11 @@ function emailPayload(input) {
2471
2513
  });
2472
2514
  }
2473
2515
  function recordingPayload(input) {
2516
+ if (typeof input === "boolean")
2517
+ return input;
2474
2518
  return compact({
2475
2519
  enabled: input.enabled,
2520
+ transcribe: input.transcribe,
2476
2521
  record_audio: input.record_audio ?? input.recordAudio,
2477
2522
  consent_required: input.consent_required ?? input.consentRequired,
2478
2523
  announcement: input.announcement,
package/dist/index.d.ts CHANGED
@@ -199,8 +199,74 @@ export interface LabsCallStage {
199
199
  temperature?: number;
200
200
  nextStages?: string[];
201
201
  next_stages?: string[];
202
+ /** Server-enforced exit gates, independent of conversational exit criteria. */
203
+ requirements?: LabsStageRequirements;
204
+ role?: string;
205
+ specialistId?: string;
206
+ specialist_id?: string;
202
207
  metadata?: Record<string, unknown>;
203
208
  }
209
+ export interface LabsStageRequirements {
210
+ requiredFields?: string[];
211
+ required_fields?: string[];
212
+ successfulTools?: string[];
213
+ successful_tools?: string[];
214
+ }
215
+ export interface LabsManagerConfig {
216
+ enabled?: boolean;
217
+ /** Reuse the existing encrypted Supervisor profile, or use managed reasoning. */
218
+ reasoning?: "managed" | "supervisor";
219
+ model?: "supafone-manager" | "supafone-manager-pro";
220
+ maxTasks?: number;
221
+ max_tasks?: number;
222
+ maxParallel?: number;
223
+ max_parallel?: number;
224
+ timeoutSeconds?: number;
225
+ timeout_seconds?: number;
226
+ }
227
+ export interface LabsSpecialist {
228
+ id: string;
229
+ role?: string;
230
+ label?: string;
231
+ description?: string;
232
+ instructions?: string;
233
+ enabled?: boolean;
234
+ stageKeys?: string[];
235
+ stage_keys?: string[];
236
+ tools?: string[];
237
+ }
238
+ export interface LabsAgentTeam {
239
+ enabled?: boolean;
240
+ routingMode?: "auto" | "sequential";
241
+ routing_mode?: "auto" | "sequential";
242
+ fallbackMemberId?: string;
243
+ fallback_member_id?: string;
244
+ members?: LabsSpecialist[];
245
+ routingRules?: Array<{
246
+ intent: string;
247
+ member_id: string;
248
+ priority?: string;
249
+ action?: string;
250
+ }>;
251
+ routing_rules?: Array<{
252
+ intent: string;
253
+ member_id: string;
254
+ priority?: string;
255
+ action?: string;
256
+ }>;
257
+ }
258
+ export interface LabsRuntimeRoutingConfig {
259
+ enabled?: boolean;
260
+ allowedModels?: LabsRealtimeSelection[];
261
+ allowed_models?: LabsRealtimeSelection[];
262
+ /** Server-supported range is 1–3 handoffs per call. */
263
+ maxHandoffs?: number;
264
+ max_handoffs?: number;
265
+ recoverOnDisconnect?: boolean;
266
+ recover_on_disconnect?: boolean;
267
+ allowedLanguages?: string[];
268
+ allowed_languages?: string[];
269
+ }
204
270
  export type LabsStageGeneration = "managed" | "template" | "off" | "oracle";
205
271
  export interface LabsCallPlan {
206
272
  version: "supafone_call_plan_v1" | string;
@@ -646,6 +712,8 @@ export interface LabsEmailConfig {
646
712
  }
647
713
  export interface LabsRecordingConfig {
648
714
  enabled?: boolean;
715
+ /** Request post-call transcription of the recording where configured. */
716
+ transcribe?: boolean;
649
717
  recordAudio?: boolean;
650
718
  record_audio?: boolean;
651
719
  consentRequired?: boolean;
@@ -885,6 +953,17 @@ export interface CreateLabsAgentRequest {
885
953
  presetKey?: string;
886
954
  preset_key?: string;
887
955
  realtime?: LabsRealtimeSelection;
956
+ manager?: boolean | LabsManagerConfig;
957
+ agentTeam?: LabsAgentTeam;
958
+ agent_team?: LabsAgentTeam;
959
+ runtimeRouting?: LabsRuntimeRoutingConfig;
960
+ runtime_routing?: LabsRuntimeRoutingConfig;
961
+ captureFields?: string[];
962
+ capture_fields?: string[];
963
+ timezone?: string;
964
+ businessTimezone?: string;
965
+ timeAwareness?: boolean;
966
+ time_awareness?: boolean;
888
967
  runtimeMode?: LabsRuntimeMode;
889
968
  runtime_mode?: LabsRuntimeMode;
890
969
  /** Defaults to Supafone's hosted planner; model credentials remain server-side. */
@@ -927,7 +1006,7 @@ export interface CreateLabsAgentRequest {
927
1006
  customSip?: LabsCustomSipConfig;
928
1007
  custom_sip?: LabsCustomSipConfig;
929
1008
  sip?: LabsCustomSipConfig;
930
- recording?: LabsRecordingConfig;
1009
+ recording?: boolean | LabsRecordingConfig;
931
1010
  transcription?: LabsTranscriptionConfig;
932
1011
  artifacts?: LabsArtifactsConfig;
933
1012
  compliance?: Record<string, unknown>;