@unboundcx/sdk 4.13.96 → 4.13.98

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.13.96",
3
+ "version": "4.13.98",
4
4
  "description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,18 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Platform model catalog — product names only (no vendor provider/model).
5
+ */
6
+ export class ModelsService {
7
+ constructor(sdk) {
8
+ this.sdk = sdk;
9
+ }
10
+
11
+ /**
12
+ * List platform models available to this account.
13
+ * @returns {Promise<Object>} { models, features, recommended }
14
+ */
15
+ async list() {
16
+ return internalRequest(this.sdk, '/ai/models', 'GET');
17
+ }
18
+ }
@@ -0,0 +1,155 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Text-to-speech. `sdk.ai.tts.*`.
5
+ *
6
+ * @see app1-api src/services/ai/routes/tts.js
7
+ */
8
+ export class TextToSpeechService {
9
+ constructor(sdk) {
10
+ this.sdk = sdk;
11
+ }
12
+
13
+ /**
14
+ * Render text to speech and get back a storage id/url (buffered — waits
15
+ * for the whole file). For low-latency playback (e.g. a voice bot) use
16
+ * `stream()` instead.
17
+ * @param {Object} params
18
+ * @param {string} params.text
19
+ * @param {string} [params.voice]
20
+ * @param {string} [params.languageCode]
21
+ * @param {string} [params.ssmlGender]
22
+ * @param {string} [params.audioEncoding]
23
+ * @param {number} [params.speakingRate]
24
+ * @param {number} [params.pitch]
25
+ * @param {number} [params.volumeGainDb]
26
+ * @param {string[]} [params.effectsProfileIds]
27
+ * @param {boolean} [params.createAccessKey]
28
+ * @returns {Promise<Object>} `{ id, storageId, url? }`
29
+ */
30
+ async create({
31
+ text,
32
+ voice,
33
+ languageCode,
34
+ ssmlGender,
35
+ audioEncoding,
36
+ speakingRate,
37
+ pitch,
38
+ volumeGainDb,
39
+ effectsProfileIds,
40
+ createAccessKey,
41
+ }) {
42
+ this.sdk.validateParams(
43
+ {
44
+ text,
45
+ voice,
46
+ languageCode,
47
+ ssmlGender,
48
+ audioEncoding,
49
+ speakingRate,
50
+ pitch,
51
+ volumeGainDb,
52
+ effectsProfileIds,
53
+ createAccessKey,
54
+ },
55
+ {
56
+ text: { type: 'string', required: true },
57
+ voice: { type: 'string', required: false },
58
+ languageCode: { type: 'string', required: false },
59
+ ssmlGender: { type: 'string', required: false },
60
+ audioEncoding: { type: 'string', required: false },
61
+ speakingRate: { type: 'number', required: false },
62
+ pitch: { type: 'number', required: false },
63
+ volumeGainDb: { type: 'number', required: false },
64
+ effectsProfileIds: { type: 'array', required: false },
65
+ createAccessKey: { type: 'boolean', required: false },
66
+ },
67
+ );
68
+
69
+ const ttsData = { text };
70
+ if (voice) ttsData.voice = voice;
71
+ if (languageCode) ttsData.languageCode = languageCode;
72
+ if (ssmlGender) ttsData.ssmlGender = ssmlGender;
73
+ if (audioEncoding) ttsData.audioEncoding = audioEncoding;
74
+ if (speakingRate) ttsData.speakingRate = speakingRate;
75
+ if (pitch) ttsData.pitch = pitch;
76
+ if (volumeGainDb) ttsData.volumeGainDb = volumeGainDb;
77
+ if (effectsProfileIds) ttsData.effectsProfileIds = effectsProfileIds;
78
+ if (createAccessKey) ttsData.createAccessKey = createAccessKey;
79
+
80
+ const params = {
81
+ body: ttsData,
82
+ };
83
+
84
+ const result = await internalRequest(this.sdk, '/ai/tts', 'POST', params);
85
+ return result;
86
+ }
87
+
88
+ /**
89
+ * List available TTS voices
90
+ * @returns {Promise<Object>} { voices: Array, count: number, supportedEncodings: Array, supportedLanguages: Array }
91
+ */
92
+ async list() {
93
+ const result = await internalRequest(this.sdk, '/ai/tts', 'GET');
94
+ return result;
95
+ }
96
+
97
+ /**
98
+ * Stream TTS audio as it's generated — first bytes can arrive well before
99
+ * the whole utterance finishes rendering (Groq voices: TTFB ~0.2s).
100
+ * Always renders wav; shares its cache with `create()` when
101
+ * audioEncoding:'wav' is used there.
102
+ *
103
+ * Node: wrap the result in `Readable.fromWeb(result.body)` to get a
104
+ * normal Node stream (e.g. to pipe into ffmpeg). Browser: `result.body`
105
+ * is already a web ReadableStream you can read directly or hand to
106
+ * `new Response(result.body)` / a `<audio>` element via a Blob.
107
+ *
108
+ * Response headers of note: `x-tts-cache` (`hit`|`miss`) and `x-tts-id`
109
+ * (set on a cache hit, when the id is already known).
110
+ *
111
+ * @param {Object} params
112
+ * @param {string} params.text
113
+ * @param {string} [params.voice]
114
+ * @param {string} [params.languageCode]
115
+ * @returns {Promise<{body: ReadableStream, headers: Headers, status: number}>}
116
+ * @example
117
+ * const result = await sdk.ai.tts.stream({ text: 'Hi there', voice: 'hannah' });
118
+ * const nodeStream = Readable.fromWeb(result.body);
119
+ * nodeStream.pipe(ffmpegProcess.stdin);
120
+ */
121
+ async stream({ text, voice, languageCode }) {
122
+ this.sdk.validateParams(
123
+ { text, voice, languageCode },
124
+ {
125
+ text: { type: 'string', required: true },
126
+ voice: { type: 'string', required: false },
127
+ languageCode: { type: 'string', required: false },
128
+ },
129
+ );
130
+
131
+ const ttsData = { text };
132
+ if (voice) ttsData.voice = voice;
133
+ if (languageCode) ttsData.languageCode = languageCode;
134
+
135
+ const params = {
136
+ body: ttsData,
137
+ returnRawResponse: true,
138
+ };
139
+
140
+ // forceFetch: true — NATS transport can't carry a streamed body.
141
+ const response = await internalRequest(
142
+ this.sdk,
143
+ '/ai/tts/stream',
144
+ 'POST',
145
+ params,
146
+ true,
147
+ );
148
+
149
+ return {
150
+ body: response.body,
151
+ headers: response.headers,
152
+ status: response.status,
153
+ };
154
+ }
155
+ }
package/services/ai.js CHANGED
@@ -4,6 +4,8 @@ import { BattleCardsService } from './ai/battleCards.js';
4
4
  import { AssistService } from './ai/assist.js';
5
5
  import { VocabularyService } from './ai/vocabulary.js';
6
6
  import { EmailService } from './ai/email.js';
7
+ import { ModelsService } from './ai/models.js';
8
+ import { TextToSpeechService } from './ai/tts.js';
7
9
  import { translate as translateItems } from './ai/translate.js';
8
10
  import {
9
11
  getSettings as getAiSettings,
@@ -22,6 +24,7 @@ export class AIService {
22
24
  this.assist = new AssistService(sdk);
23
25
  this.vocabulary = new VocabularyService(sdk);
24
26
  this.email = new EmailService(sdk);
27
+ this.models = new ModelsService(sdk);
25
28
  }
26
29
 
27
30
  /**
@@ -485,79 +488,6 @@ export class GenerativeService {
485
488
  // }
486
489
  }
487
490
 
488
- export class TextToSpeechService {
489
- constructor(sdk) {
490
- this.sdk = sdk;
491
- }
492
-
493
- async create({
494
- text,
495
- voice,
496
- languageCode,
497
- ssmlGender,
498
- audioEncoding,
499
- speakingRate,
500
- pitch,
501
- volumeGainDb,
502
- effectsProfileIds,
503
- createAccessKey,
504
- }) {
505
- this.sdk.validateParams(
506
- {
507
- text,
508
- voice,
509
- languageCode,
510
- ssmlGender,
511
- audioEncoding,
512
- speakingRate,
513
- pitch,
514
- volumeGainDb,
515
- effectsProfileIds,
516
- createAccessKey,
517
- },
518
- {
519
- text: { type: 'string', required: true },
520
- voice: { type: 'string', required: false },
521
- languageCode: { type: 'string', required: false },
522
- ssmlGender: { type: 'string', required: false },
523
- audioEncoding: { type: 'string', required: false },
524
- speakingRate: { type: 'number', required: false },
525
- pitch: { type: 'number', required: false },
526
- volumeGainDb: { type: 'number', required: false },
527
- effectsProfileIds: { type: 'array', required: false },
528
- createAccessKey: { type: 'boolean', required: false },
529
- },
530
- );
531
-
532
- const ttsData = { text };
533
- if (voice) ttsData.voice = voice;
534
- if (languageCode) ttsData.languageCode = languageCode;
535
- if (ssmlGender) ttsData.ssmlGender = ssmlGender;
536
- if (audioEncoding) ttsData.audioEncoding = audioEncoding;
537
- if (speakingRate) ttsData.speakingRate = speakingRate;
538
- if (pitch) ttsData.pitch = pitch;
539
- if (volumeGainDb) ttsData.volumeGainDb = volumeGainDb;
540
- if (effectsProfileIds) ttsData.effectsProfileIds = effectsProfileIds;
541
- if (createAccessKey) ttsData.createAccessKey = createAccessKey;
542
-
543
- const params = {
544
- body: ttsData,
545
- };
546
-
547
- const result = await internalRequest(this.sdk, '/ai/tts', 'POST', params);
548
- return result;
549
- }
550
-
551
- /**
552
- * List available TTS voices
553
- * @returns {Promise<Object>} { voices: Array, count: number, supportedEncodings: Array, supportedLanguages: Array }
554
- */
555
- async list() {
556
- const result = await internalRequest(this.sdk, '/ai/tts', 'GET');
557
- return result;
558
- }
559
- }
560
-
561
491
  export class SpeechToTextService {
562
492
  constructor(sdk) {
563
493
  this.sdk = sdk;
@@ -30,6 +30,7 @@ export class CcBotsService {
30
30
  * @param {string} params.name
31
31
  * @param {string} params.slug
32
32
  * @param {string} [params.soulMd]
33
+ * @param {string} [params.modelId] platform catalog id
33
34
  * @param {string} [params.provider]
34
35
  * @param {string} [params.model]
35
36
  * @param {string} [params.queueId]
@@ -40,6 +41,7 @@ export class CcBotsService {
40
41
  name,
41
42
  slug,
42
43
  soulMd,
44
+ modelId,
43
45
  provider,
44
46
  model,
45
47
  queueId,
@@ -54,6 +56,7 @@ export class CcBotsService {
54
56
  );
55
57
  const body = { name, slug };
56
58
  if (soulMd !== undefined) body.soulMd = soulMd;
59
+ if (modelId !== undefined) body.modelId = modelId;
57
60
  if (provider !== undefined) body.provider = provider;
58
61
  if (model !== undefined) body.model = model;
59
62
  if (queueId !== undefined) body.queueId = queueId;
@@ -86,6 +89,7 @@ export class CcBotsService {
86
89
  'additionalDetails',
87
90
  'provider',
88
91
  'model',
92
+ 'modelId',
89
93
  'mediaProvider',
90
94
  'mediaModel',
91
95
  'voiceId',
@@ -187,6 +191,7 @@ export class CcBotsService {
187
191
  'soulMd',
188
192
  'provider',
189
193
  'model',
194
+ 'modelId',
190
195
  'mediaProvider',
191
196
  'mediaModel',
192
197
  'voiceId',