@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 +1 -1
- package/services/ai/models.js +18 -0
- package/services/ai/tts.js +155 -0
- package/services/ai.js +3 -73
- package/services/taskRouter/CcBotsService.js +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unboundcx/sdk",
|
|
3
|
-
"version": "4.13.
|
|
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',
|