supafone-labs 0.4.12 → 0.4.13

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
@@ -107,6 +107,13 @@ Supafone Labs has two main features:
107
107
  - **Self-healing watcher**: enable `labs.enabled` to attach the Supafone Labs
108
108
  second mind to a hosted or BYOK agent.
109
109
 
110
+ The daily developer workflow is documented in
111
+ [Developer Workflows](../gitbook/developer-workflows.md): one normalized live
112
+ voice catalog, fixed BCP-47 language selection, automatic voice compatibility
113
+ filtering, structured SecondMind directives, and the same configuration model
114
+ across TypeScript and Python. Fixed language selection does not enable
115
+ mid-call language or voice switching.
116
+
110
117
  BYOK is advanced and split into three independent lanes:
111
118
 
112
119
  | Lane | Examples |
@@ -279,6 +286,29 @@ required); and prints the returned widget snippet.
279
286
 
280
287
  ## Hosted voices
281
288
 
289
+ Select a current provider voice from plain-language intent:
290
+
291
+ ```ts
292
+ const matches = await supafone.labs.voices.recommend({
293
+ description: "calm Spanish customer-support voice",
294
+ language: "es-MX",
295
+ configuredOnly: true,
296
+ });
297
+
298
+ const voice = matches.matches[0].voice;
299
+ await supafone.labs.agents.createInbound({
300
+ name: "Spanish support",
301
+ voice: supafone.labs.voices.selection(voice),
302
+ });
303
+ ```
304
+
305
+ The hosted catalog refreshes Ultravox, Cartesia, ElevenLabs, and Inworld and
306
+ normalizes names, languages, gender, accent, voice type, model limits, and the
307
+ Ultravox-compatible language intersection. Full reference:
308
+ [Dynamic Voice Catalog and Selection](../gitbook/voice-catalog-and-selection.md).
309
+
310
+ Labs Cloud also exposes direct hosted TTS and STT:
311
+
282
312
  ```ts
283
313
  const wav = await supafone.tts("You're all set — talk soon!", "supafone-labs-calm-en");
284
314
  // wav: Uint8Array
@@ -87,6 +87,56 @@ export interface WhisperOptions {
87
87
  maxTokens?: number;
88
88
  temperature?: number;
89
89
  }
90
+ export type SecondMindDirectiveKind = "empathy" | "tactical" | "guardrail" | "mixed";
91
+ export interface DirectiveTextControl {
92
+ enabled?: boolean;
93
+ instructions?: string;
94
+ maxChars?: number;
95
+ max_chars?: number;
96
+ }
97
+ export interface DirectiveListControl {
98
+ enabled?: boolean;
99
+ instructions?: string;
100
+ maxItems?: number;
101
+ max_items?: number;
102
+ itemMaxChars?: number;
103
+ item_max_chars?: number;
104
+ }
105
+ /** Serializable controls for each field generated by SecondMind. */
106
+ export interface DirectiveContract {
107
+ empathyDirective?: DirectiveTextControl;
108
+ empathy_directive?: DirectiveTextControl;
109
+ tacticalDirective?: DirectiveTextControl;
110
+ tactical_directive?: DirectiveTextControl;
111
+ surfaceFacts?: DirectiveListControl;
112
+ surface_facts?: DirectiveListControl;
113
+ guardrails?: DirectiveListControl;
114
+ languageMode?: "caller" | "model" | "fixed";
115
+ language_mode?: "caller" | "model" | "fixed";
116
+ fixedLanguage?: string;
117
+ fixed_language?: string;
118
+ allowedKinds?: SecondMindDirectiveKind[];
119
+ allowed_kinds?: SecondMindDirectiveKind[];
120
+ confidenceThreshold?: number;
121
+ confidence_threshold?: number;
122
+ operatorGuardrails?: string[];
123
+ operator_guardrails?: string[];
124
+ }
125
+ export interface SecondMindDirective {
126
+ empathy_directive: string;
127
+ tactical_directive: string;
128
+ surface_facts: string[];
129
+ guardrails: string[];
130
+ language: string;
131
+ confidence: number;
132
+ kind: SecondMindDirectiveKind;
133
+ }
134
+ export interface StructuredWhisperOptions extends WhisperOptions {
135
+ directiveContract?: DirectiveContract;
136
+ directive_contract?: DirectiveContract;
137
+ /** Local final say: revise or suppress the generated directive before use. */
138
+ transform?: (directive: SecondMindDirective) => SecondMindDirective | null | Promise<SecondMindDirective | null>;
139
+ }
90
140
  export interface Balance {
91
141
  plan: string;
92
142
  seconds_remaining: number;
@@ -160,6 +210,113 @@ export interface LabsVoiceSelection {
160
210
  voice_id?: string;
161
211
  model?: string;
162
212
  }
213
+ export type LabsVoiceGender = "female" | "male" | "neutral";
214
+ export interface LabsVoiceLanguage {
215
+ code: string;
216
+ locale: string;
217
+ name: string;
218
+ native_name: string;
219
+ aliases?: string[];
220
+ routing_supported?: boolean;
221
+ }
222
+ export interface LabsVoiceLanguageSupport {
223
+ provider: string;
224
+ model?: string | null;
225
+ known: boolean;
226
+ language_codes: string[];
227
+ /** Number of language codes Supafone can enumerate from provider docs. */
228
+ enumerated_language_count: number;
229
+ generally_available_language_codes: string[];
230
+ experimental_language_codes: string[];
231
+ documented_language_count: number;
232
+ documented_language_count_is_minimum: boolean;
233
+ support_tier: string;
234
+ cross_lingual: boolean | null;
235
+ documentation_url?: string | null;
236
+ verified_at: string;
237
+ native_language_codes: string[];
238
+ ultravox_routing_language_codes: string[];
239
+ primary_language_support_tier: "generally_available" | "experimental" | "unknown";
240
+ }
241
+ export interface LabsVoiceProviderTraits {
242
+ countries: string[];
243
+ accents: string[];
244
+ age_groups: string[];
245
+ categories: string[];
246
+ use_cases: string[];
247
+ descriptors: string[];
248
+ native_locales: string[];
249
+ created_at?: string | number | null;
250
+ is_public?: boolean | null;
251
+ is_owner?: boolean | null;
252
+ }
253
+ export interface LabsVoiceCatalogItem {
254
+ /** Stable runtime reference, including provider prefix when required. */
255
+ id: string;
256
+ voice_id: string;
257
+ /** Human-readable provider display name. */
258
+ provider: string;
259
+ /** Canonical SDK/runtime provider key. */
260
+ provider_key: string;
261
+ /** Runtime adapter used to place the voice on an Ultravox call. */
262
+ runtime_provider_key: string;
263
+ /** Actual TTS engine behind the voice (can differ for Ultravox built-ins). */
264
+ synthesis_provider_key: string;
265
+ /** Raw identifier used by the provider API. */
266
+ provider_voice_id: string;
267
+ name: string;
268
+ label: string;
269
+ description: string;
270
+ style: string;
271
+ model?: string | null;
272
+ language: string;
273
+ language_code: string;
274
+ language_locale: string;
275
+ language_name: string;
276
+ native_language_name: string;
277
+ languages: LabsVoiceLanguage[];
278
+ native_language_codes: string[];
279
+ model_language_codes: string[];
280
+ runtime_supported_language_codes: string[];
281
+ routing_supported: boolean;
282
+ language_support: LabsVoiceLanguageSupport;
283
+ gender: LabsVoiceGender;
284
+ accent: string;
285
+ age: string;
286
+ provider_traits: LabsVoiceProviderTraits;
287
+ voice_types: string[];
288
+ primary_voice_type: string;
289
+ tags: string[];
290
+ /** Sanitized provider-native fields retained for forward-compatible filtering. */
291
+ provider_metadata: Record<string, unknown>;
292
+ provider_metadata_fields: string[];
293
+ preview_url?: string | null;
294
+ preview_available: boolean;
295
+ source: string;
296
+ ownership?: string | null;
297
+ configured: boolean;
298
+ recommended: boolean;
299
+ premium?: boolean;
300
+ is_custom: boolean;
301
+ runtime: {
302
+ provider: string;
303
+ voice_id: string;
304
+ model?: string;
305
+ };
306
+ [extra: string]: unknown;
307
+ }
308
+ export interface LabsVoicePreference {
309
+ description: string;
310
+ language?: string;
311
+ provider?: string;
312
+ gender?: LabsVoiceGender;
313
+ voiceType?: string;
314
+ voice_type?: string;
315
+ model?: string;
316
+ configuredOnly?: boolean;
317
+ configured_only?: boolean;
318
+ premium?: boolean;
319
+ }
163
320
  export interface LabsProviderKeys {
164
321
  /** Agent runtime/platform providers. */
165
322
  ultravox?: string;
@@ -507,8 +664,14 @@ export interface CreateLabsAgentRequest {
507
664
  greeting?: string;
508
665
  systemPrompt?: string;
509
666
  system_prompt?: string;
667
+ /** Fixed language for the full call. Does not enable mid-call switching. */
510
668
  language?: string;
669
+ preferredLanguage?: string;
670
+ preferred_language?: string;
511
671
  voice?: LabsVoiceSelection;
672
+ /** Resolve a real current catalog voice from this plain-language preference. */
673
+ voicePreference?: LabsVoicePreference;
674
+ voice_preference?: LabsVoicePreference;
512
675
  providerKeys?: LabsProviderKeys;
513
676
  provider_keys?: LabsProviderKeys;
514
677
  byok?: LabsProviderKeys | LabsByokConfig;
@@ -569,16 +732,98 @@ export interface LabsToolListResponse {
569
732
  export interface LabsVoiceListOptions {
570
733
  provider?: string;
571
734
  search?: string;
735
+ /** Native/accent language advertised for the individual voice. */
572
736
  language?: string;
737
+ /** Language that the provider model and Ultravox can both run live. */
738
+ compatibleLanguage?: string;
739
+ compatible_language?: string;
740
+ gender?: LabsVoiceGender;
741
+ voiceType?: string;
742
+ voice_type?: string;
743
+ model?: string;
744
+ runtimeProvider?: string;
745
+ runtime_provider?: string;
746
+ configuredOnly?: boolean;
747
+ configured_only?: boolean;
573
748
  cursor?: number;
574
749
  limit?: number;
750
+ agencyId?: string;
751
+ agency_id?: string;
575
752
  }
576
753
  export interface LabsVoiceListResponse {
577
- voices: Array<Record<string, unknown>>;
754
+ account_id?: string;
755
+ voices: LabsVoiceCatalogItem[];
578
756
  total: number;
579
- providers: Array<Record<string, unknown>>;
757
+ cursor?: number;
758
+ next_cursor?: number | null;
759
+ providers: Array<{
760
+ id: string;
761
+ label: string;
762
+ configured: boolean;
763
+ voice_count: number;
764
+ error?: string | null;
765
+ }>;
580
766
  provider_accounts?: Record<string, unknown>;
581
767
  errors?: Record<string, string>;
768
+ catalog?: {
769
+ dynamic: boolean;
770
+ source: string;
771
+ normalization_schema_version: number;
772
+ cache_ttl_seconds: number;
773
+ capabilities_url?: string;
774
+ };
775
+ }
776
+ export interface LabsVoiceModelCapability {
777
+ provider: string;
778
+ model?: string | null;
779
+ known: boolean;
780
+ language_codes: string[];
781
+ enumerated_language_count: number;
782
+ generally_available_language_codes: string[];
783
+ experimental_language_codes: string[];
784
+ documented_language_count: number;
785
+ documented_language_count_is_minimum: boolean;
786
+ support_tier: string;
787
+ cross_lingual: boolean | null;
788
+ documentation_url?: string | null;
789
+ verified_at: string;
790
+ ultravox_routing_language_codes: string[];
791
+ ultravox_routing_language_count: number;
792
+ }
793
+ export interface LabsVoiceProviderCapability {
794
+ provider: string;
795
+ label: string;
796
+ ultravox_integration: "native" | "named_external" | string;
797
+ default_model?: string | null;
798
+ models: LabsVoiceModelCapability[];
799
+ }
800
+ export interface LabsVoiceCapabilitiesResponse {
801
+ runtime: "ultravox" | string;
802
+ runtime_spoken_languages: LabsVoiceLanguage[];
803
+ runtime_spoken_language_count: number;
804
+ providers: LabsVoiceProviderCapability[];
805
+ selection_rule: Record<string, string>;
806
+ normalization_schema_version: number;
807
+ }
808
+ export interface LabsVoiceRecommendOptions extends LabsVoicePreference {
809
+ limit?: number;
810
+ agencyId?: string;
811
+ agency_id?: string;
812
+ }
813
+ export interface LabsVoiceRecommendation {
814
+ voice: LabsVoiceCatalogItem;
815
+ score: number;
816
+ reasons: string[];
817
+ }
818
+ export interface LabsVoiceRecommendResponse {
819
+ account_id?: string;
820
+ description: string;
821
+ matches: LabsVoiceRecommendation[];
822
+ total_considered: number;
823
+ }
824
+ export interface LabsVoicePreview {
825
+ content: ArrayBuffer;
826
+ mediaType: string;
582
827
  }
583
828
  export interface LabsRuntimeResponse {
584
829
  account_id: string;
@@ -590,9 +835,11 @@ export interface LabsRuntimeResponse {
590
835
  }
591
836
  export interface LabsCallListOptions {
592
837
  agencyId?: string;
838
+ agency_id?: string;
593
839
  agentKey?: string;
594
840
  agent_key?: string;
595
841
  limit?: number;
842
+ offset?: number;
596
843
  }
597
844
  export interface LabsCallArtifact {
598
845
  id?: string;
@@ -602,7 +849,11 @@ export interface LabsCallArtifact {
602
849
  started_at?: string;
603
850
  duration_seconds?: number;
604
851
  recording_url?: string;
852
+ recording_download_url?: string;
853
+ recording_archived?: boolean;
605
854
  transcript_url?: string;
855
+ watcher_events?: LabsDeveloperActivityEvent[];
856
+ watcher_event_count?: number;
606
857
  [extra: string]: unknown;
607
858
  }
608
859
  export interface LabsCallListResponse {
@@ -625,6 +876,37 @@ export interface LabsTranscriptListResponse {
625
876
  transcripts: Array<Record<string, unknown>>;
626
877
  [extra: string]: unknown;
627
878
  }
879
+ export interface LabsDeveloperActivityEvent {
880
+ id: string;
881
+ account_id: string;
882
+ event_type: string;
883
+ resource_type: string;
884
+ resource_id: string;
885
+ source?: string;
886
+ detail?: Record<string, unknown>;
887
+ created_at: string;
888
+ [extra: string]: unknown;
889
+ }
890
+ export interface LabsActivityListOptions {
891
+ accountId?: string;
892
+ account_id?: string;
893
+ agencyId?: string;
894
+ agency_id?: string;
895
+ eventType?: string;
896
+ event_type?: string;
897
+ resourceType?: string;
898
+ resource_type?: string;
899
+ resourceId?: string;
900
+ resource_id?: string;
901
+ limit?: number;
902
+ offset?: number;
903
+ }
904
+ export interface LabsActivityListResponse {
905
+ events: LabsDeveloperActivityEvent[];
906
+ count: number;
907
+ next_offset?: number | null;
908
+ account_id?: string;
909
+ }
628
910
  export interface LabsPhoneNumberSearchOptions {
629
911
  agencyId?: string;
630
912
  agency_id?: string;
@@ -1086,6 +1368,8 @@ export declare class SupafoneLabs {
1086
1368
  request<T>(method: string, path: string, body?: unknown, useSession?: boolean): Promise<T>;
1087
1369
  /** @internal Authenticated JSON request to the Supafone app API (`/api/v1/labs/*`). */
1088
1370
  requestSupafoneApi<T>(method: string, path: string, body?: unknown): Promise<T>;
1371
+ /** @internal Authenticated binary request to the Supafone app API. */
1372
+ requestSupafoneBinary(path: string): Promise<LabsVoicePreview>;
1089
1373
  /**
1090
1374
  * Exchange the account email/password for a product-API JWT (the same login
1091
1375
  * as app.supafone.ai). Called lazily by campaigns/calls — call directly only
@@ -1154,6 +1438,14 @@ export declare class SupafoneLabs {
1154
1438
  * (empty string when the agent is doing fine).
1155
1439
  */
1156
1440
  whisper(transcript: string, opts?: WhisperOptions): Promise<string>;
1441
+ /**
1442
+ * Structured SecondMind guidance with developer-controlled field policy.
1443
+ * Returns null when JSON is invalid, evidence misses the confidence gate,
1444
+ * the generated kind is disallowed, or the local transform suppresses it.
1445
+ */
1446
+ whisperStructured(transcript: string, opts?: StructuredWhisperOptions): Promise<SecondMindDirective | null>;
1447
+ /** Alias that reads naturally in applications building their own watcher loop. */
1448
+ directive(transcript: string, opts?: StructuredWhisperOptions): Promise<SecondMindDirective | null>;
1157
1449
  /** Hosted TTS — returns raw audio bytes (WAV/PCM per voice). */
1158
1450
  tts(text: string, voice?: string): Promise<Uint8Array>;
1159
1451
  /** Convenience alias for voice preview UI/buttons. */
@@ -1513,6 +1805,8 @@ declare class LabsNamespace {
1513
1805
  readonly phoneNumbers: LabsPhoneNumbersNamespace;
1514
1806
  readonly telephony: LabsTelephonyNamespace;
1515
1807
  readonly calls: LabsCallsNamespace;
1808
+ readonly activity: LabsActivityNamespace;
1809
+ readonly plans: LabsPlansNamespace;
1516
1810
  readonly recordings: LabsRecordingsNamespace;
1517
1811
  readonly transcripts: LabsTranscriptsNamespace;
1518
1812
  constructor(sm: SupafoneLabs);
@@ -1610,8 +1904,24 @@ declare class LabsToolsNamespace {
1610
1904
  declare class LabsVoicesNamespace {
1611
1905
  private sm;
1612
1906
  constructor(sm: SupafoneLabs);
1613
- /** Supafone-managed Cartesia voices. Other TTS engines remain explicit BYOK choices. */
1907
+ /** Live normalized catalog from every connected/managed TTS provider. */
1614
1908
  list(opts?: LabsVoiceListOptions): Promise<LabsVoiceListResponse>;
1909
+ /** Provider/model language limits and their Ultravox-compatible intersection. */
1910
+ capabilities(): Promise<LabsVoiceCapabilitiesResponse>;
1911
+ /** Page through the complete normalized catalog. */
1912
+ listAll(opts?: Omit<LabsVoiceListOptions, "cursor" | "limit"> & {
1913
+ pageSize?: number;
1914
+ maxPages?: number;
1915
+ }): Promise<LabsVoiceListResponse>;
1916
+ /** Rank real current voices from a plain-language description. */
1917
+ recommend(opts: LabsVoiceRecommendOptions): Promise<LabsVoiceRecommendResponse>;
1918
+ /** Download an authenticated voice preview. */
1919
+ preview(voiceId: string, opts?: {
1920
+ agencyId?: string;
1921
+ agency_id?: string;
1922
+ }): Promise<LabsVoicePreview>;
1923
+ /** Convert a catalog row into the exact Agent Factory voice field. */
1924
+ selection(voice: LabsVoiceCatalogItem): LabsVoiceSelection;
1615
1925
  }
1616
1926
  declare class LabsRuntimeNamespace {
1617
1927
  private sm;
@@ -1638,8 +1948,25 @@ declare class LabsCallsNamespace {
1638
1948
  list(opts?: LabsCallListOptions): Promise<LabsCallListResponse>;
1639
1949
  get(callId: string, opts?: {
1640
1950
  agencyId?: string;
1951
+ agency_id?: string;
1952
+ }): Promise<{
1953
+ call: LabsCallArtifact;
1954
+ }>;
1955
+ delete(callId: string, opts?: {
1956
+ agencyId?: string;
1957
+ agency_id?: string;
1641
1958
  }): Promise<Record<string, unknown>>;
1642
1959
  }
1960
+ declare class LabsActivityNamespace {
1961
+ private sm;
1962
+ constructor(sm: SupafoneLabs);
1963
+ list(opts?: LabsActivityListOptions): Promise<LabsActivityListResponse>;
1964
+ }
1965
+ declare class LabsPlansNamespace {
1966
+ private sm;
1967
+ constructor(sm: SupafoneLabs);
1968
+ list(opts?: Omit<LabsActivityListOptions, "eventType" | "event_type" | "resourceType" | "resource_type">): Promise<LabsActivityListResponse>;
1969
+ }
1643
1970
  declare class LabsRecordingsNamespace {
1644
1971
  private sm;
1645
1972
  constructor(sm: SupafoneLabs);