@drax/ai-back 3.41.0 → 3.43.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.
Files changed (117) hide show
  1. package/dist/agents/DraxAgent.js +3 -1
  2. package/dist/config/ElevenLabsTTSConfig.js +10 -0
  3. package/dist/controllers/AICrudController.js +1 -1
  4. package/dist/controllers/AIGenericController.js +23 -1
  5. package/dist/controllers/DraxAgentController.js +22 -0
  6. package/dist/controllers/TTSGenericController.js +61 -0
  7. package/dist/factory/ElevenLabsTTSProviderFactory.js +13 -0
  8. package/dist/factory/TTSProviderFactory.js +27 -0
  9. package/dist/factory/ai/AiProviderFactory.js +30 -0
  10. package/dist/factory/ai/DeepSeekAiProviderFactory.js +14 -0
  11. package/dist/factory/ai/GoogleAiProviderFactory.js +14 -0
  12. package/dist/factory/ai/OllamaAiProviderFactory.js +14 -0
  13. package/dist/factory/ai/OpenAiProviderFactory.js +14 -0
  14. package/dist/factory/tts/ElevenLabsTTSProviderFactory.js +13 -0
  15. package/dist/factory/tts/TTSProviderFactory.js +27 -0
  16. package/dist/index.js +23 -13
  17. package/dist/interfaces/ITTSProvider.js +1 -0
  18. package/dist/permissions/TTSPermissions.js +6 -0
  19. package/dist/providers/ElevenLabsTTSProvider.js +108 -0
  20. package/dist/providers/ai/DeepSeekAiProvider.js +34 -0
  21. package/dist/providers/ai/GoogleAiProvider.js +370 -0
  22. package/dist/providers/ai/OllamaAiProvider.js +345 -0
  23. package/dist/providers/ai/OpenAiProvider.js +305 -0
  24. package/dist/providers/tts/ElevenLabsTTSProvider.js +108 -0
  25. package/dist/routes/TTSRoutes.js +8 -0
  26. package/dist/schemas/TTSRequestSchema.js +24 -0
  27. package/dist/services/PromptAudioService.js +68 -0
  28. package/dist/services/TTSGenericService.js +21 -0
  29. package/package.json +3 -3
  30. package/src/agents/DraxAgent.ts +3 -1
  31. package/src/config/ElevenLabsTTSConfig.ts +13 -0
  32. package/src/controllers/AICrudController.ts +1 -1
  33. package/src/controllers/AIGenericController.ts +25 -1
  34. package/src/controllers/DraxAgentController.ts +24 -0
  35. package/src/controllers/TTSGenericController.ts +70 -0
  36. package/src/factory/{AiProviderFactory.ts → ai/AiProviderFactory.ts} +3 -3
  37. package/src/factory/ai/DeepSeekAiProviderFactory.ts +27 -0
  38. package/src/factory/{GoogleAiProviderFactory.ts → ai/GoogleAiProviderFactory.ts} +4 -4
  39. package/src/factory/{OllamaAiProviderFactory.ts → ai/OllamaAiProviderFactory.ts} +4 -4
  40. package/src/factory/{OpenAiProviderFactory.ts → ai/OpenAiProviderFactory.ts} +4 -4
  41. package/src/factory/tts/ElevenLabsTTSProviderFactory.ts +26 -0
  42. package/src/factory/tts/TTSProviderFactory.ts +42 -0
  43. package/src/index.ts +60 -11
  44. package/src/interfaces/IAIProvider.ts +38 -1
  45. package/src/interfaces/IDraxAgent.ts +4 -0
  46. package/src/interfaces/ITTSProvider.ts +47 -0
  47. package/src/permissions/AIPermissions.ts +0 -1
  48. package/src/permissions/TTSPermissions.ts +8 -0
  49. package/src/providers/{DeepSeekProvider.ts → ai/DeepSeekAiProvider.ts} +5 -5
  50. package/src/providers/{GoogleAiProvider.ts → ai/GoogleAiProvider.ts} +6 -3
  51. package/src/providers/{OllamaAiProvider.ts → ai/OllamaAiProvider.ts} +6 -3
  52. package/src/providers/{OpenAiProvider.ts → ai/OpenAiProvider.ts} +6 -3
  53. package/src/providers/tts/ElevenLabsTTSProvider.ts +132 -0
  54. package/src/routes/TTSRoutes.ts +13 -0
  55. package/src/schemas/TTSRequestSchema.ts +38 -0
  56. package/src/services/PromptAudioService.ts +87 -0
  57. package/src/services/TTSGenericService.ts +41 -0
  58. package/test/DeepSeekProvider.test.ts +4 -4
  59. package/test/DraxAgent.test.ts +64 -0
  60. package/test/PromptAudioService.test.ts +115 -0
  61. package/tsconfig.tsbuildinfo +1 -1
  62. package/types/agents/DraxAgent.d.ts.map +1 -1
  63. package/types/config/ElevenLabsTTSConfig.d.ts +10 -0
  64. package/types/config/ElevenLabsTTSConfig.d.ts.map +1 -0
  65. package/types/controllers/AIGenericController.d.ts.map +1 -1
  66. package/types/controllers/DraxAgentController.d.ts.map +1 -1
  67. package/types/controllers/TTSGenericController.d.ts +11 -0
  68. package/types/controllers/TTSGenericController.d.ts.map +1 -0
  69. package/types/factory/ElevenLabsTTSProviderFactory.d.ts +8 -0
  70. package/types/factory/ElevenLabsTTSProviderFactory.d.ts.map +1 -0
  71. package/types/factory/TTSProviderFactory.d.ts +15 -0
  72. package/types/factory/TTSProviderFactory.d.ts.map +1 -0
  73. package/types/factory/ai/AiProviderFactory.d.ts +8 -0
  74. package/types/factory/ai/AiProviderFactory.d.ts.map +1 -0
  75. package/types/factory/ai/DeepSeekAiProviderFactory.d.ts +8 -0
  76. package/types/factory/ai/DeepSeekAiProviderFactory.d.ts.map +1 -0
  77. package/types/factory/ai/GoogleAiProviderFactory.d.ts +8 -0
  78. package/types/factory/ai/GoogleAiProviderFactory.d.ts.map +1 -0
  79. package/types/factory/ai/OllamaAiProviderFactory.d.ts +8 -0
  80. package/types/factory/ai/OllamaAiProviderFactory.d.ts.map +1 -0
  81. package/types/factory/ai/OpenAiProviderFactory.d.ts +8 -0
  82. package/types/factory/ai/OpenAiProviderFactory.d.ts.map +1 -0
  83. package/types/factory/tts/ElevenLabsTTSProviderFactory.d.ts +8 -0
  84. package/types/factory/tts/ElevenLabsTTSProviderFactory.d.ts.map +1 -0
  85. package/types/factory/tts/TTSProviderFactory.d.ts +15 -0
  86. package/types/factory/tts/TTSProviderFactory.d.ts.map +1 -0
  87. package/types/index.d.ts +26 -12
  88. package/types/index.d.ts.map +1 -1
  89. package/types/interfaces/IAIProvider.d.ts +32 -1
  90. package/types/interfaces/IAIProvider.d.ts.map +1 -1
  91. package/types/interfaces/IDraxAgent.d.ts +3 -1
  92. package/types/interfaces/IDraxAgent.d.ts.map +1 -1
  93. package/types/interfaces/ITTSProvider.d.ts +39 -0
  94. package/types/interfaces/ITTSProvider.d.ts.map +1 -0
  95. package/types/permissions/TTSPermissions.d.ts +6 -0
  96. package/types/permissions/TTSPermissions.d.ts.map +1 -0
  97. package/types/providers/ElevenLabsTTSProvider.d.ts +38 -0
  98. package/types/providers/ElevenLabsTTSProvider.d.ts.map +1 -0
  99. package/types/providers/ai/DeepSeekAiProvider.d.ts +24 -0
  100. package/types/providers/ai/DeepSeekAiProvider.d.ts.map +1 -0
  101. package/types/providers/ai/GoogleAiProvider.d.ts +63 -0
  102. package/types/providers/ai/GoogleAiProvider.d.ts.map +1 -0
  103. package/types/providers/ai/OllamaAiProvider.d.ts +78 -0
  104. package/types/providers/ai/OllamaAiProvider.d.ts.map +1 -0
  105. package/types/providers/ai/OpenAiProvider.d.ts +97 -0
  106. package/types/providers/ai/OpenAiProvider.d.ts.map +1 -0
  107. package/types/providers/tts/ElevenLabsTTSProvider.d.ts +38 -0
  108. package/types/providers/tts/ElevenLabsTTSProvider.d.ts.map +1 -0
  109. package/types/routes/TTSRoutes.d.ts +4 -0
  110. package/types/routes/TTSRoutes.d.ts.map +1 -0
  111. package/types/schemas/TTSRequestSchema.d.ts +37 -0
  112. package/types/schemas/TTSRequestSchema.d.ts.map +1 -0
  113. package/types/services/PromptAudioService.d.ts +9 -0
  114. package/types/services/PromptAudioService.d.ts.map +1 -0
  115. package/types/services/TTSGenericService.d.ts +17 -0
  116. package/types/services/TTSGenericService.d.ts.map +1 -0
  117. package/src/factory/DeepSeekProviderFactory.ts +0 -27
@@ -0,0 +1,87 @@
1
+ import TTSProviderFactory from "../factory/tts/TTSProviderFactory.js";
2
+ import type {IPromptAudioParams, IPromptAudioResponse, IPromptParams} from "../interfaces/IAIProvider.js";
3
+
4
+ class PromptAudioService {
5
+
6
+ static audioParams(input: IPromptParams): IPromptAudioParams | null {
7
+ if(!input.audioResponse){
8
+ return null
9
+ }
10
+
11
+ if(input.audioResponse === true){
12
+ return {}
13
+ }
14
+
15
+ if(input.audioResponse.enabled === false){
16
+ return null
17
+ }
18
+
19
+ return input.audioResponse
20
+ }
21
+
22
+ static outputToText(output: unknown): string {
23
+ if(typeof output === "string"){
24
+ return output
25
+ }
26
+
27
+ if(output === null || output === undefined){
28
+ return ""
29
+ }
30
+
31
+ return JSON.stringify(output)
32
+ }
33
+
34
+ static async build(input: IPromptParams, output: unknown): Promise<IPromptAudioResponse | undefined> {
35
+ const audioParams = PromptAudioService.audioParams(input)
36
+
37
+ if(!audioParams){
38
+ return undefined
39
+ }
40
+
41
+ const text = PromptAudioService.outputToText(output).trim()
42
+
43
+ if(!text){
44
+ return undefined
45
+ }
46
+
47
+ const providerName = audioParams.provider ?? "ElevenLabs"
48
+ const ttsProvider = TTSProviderFactory.instance(providerName)
49
+ const response = await ttsProvider.textToSpeech({
50
+ text,
51
+ voiceId: audioParams.voiceId,
52
+ model: audioParams.model,
53
+ outputFormat: audioParams.outputFormat,
54
+ voiceSettings: audioParams.voiceSettings,
55
+ previousText: audioParams.previousText,
56
+ nextText: audioParams.nextText,
57
+ languageCode: audioParams.languageCode,
58
+ seed: audioParams.seed,
59
+ operationTitle: audioParams.operationTitle ?? input.operationTitle,
60
+ operationGroup: audioParams.operationGroup ?? input.operationGroup,
61
+ ip: input.ip,
62
+ userAgent: input.userAgent,
63
+ tenant: input.tenant,
64
+ user: input.user,
65
+ })
66
+
67
+ return {
68
+ audio: response.audio.toString("base64"),
69
+ contentType: response.contentType,
70
+ encoding: "base64",
71
+ meta: {
72
+ provider: response.provider,
73
+ model: response.model,
74
+ voiceId: response.voiceId,
75
+ outputFormat: response.outputFormat,
76
+ size: response.size,
77
+ time: response.time,
78
+ },
79
+ }
80
+ }
81
+
82
+ }
83
+
84
+ export default PromptAudioService
85
+ export {
86
+ PromptAudioService,
87
+ }
@@ -0,0 +1,41 @@
1
+ import TTSProviderFactory from "../factory/tts/TTSProviderFactory.js";
2
+ import type {TTSProviderInfo} from "../factory/tts/TTSProviderFactory.js";
3
+ import type {ITTSParams, ITTSResponse} from "../interfaces/ITTSProvider.js";
4
+ import type {TTSRequest} from "../schemas/TTSRequestSchema.js";
5
+
6
+ type TTSRequestContext = {
7
+ ip?: string;
8
+ userAgent?: string;
9
+ tenant?: string | null;
10
+ user?: string | null;
11
+ }
12
+
13
+ class TTSGenericService {
14
+
15
+ availableProviders(): TTSProviderInfo[] {
16
+ return TTSProviderFactory.availableProviders()
17
+ }
18
+
19
+ async textToSpeech(input: TTSRequest, context: TTSRequestContext = {}): Promise<ITTSResponse> {
20
+ const ttsProvider = TTSProviderFactory.instance(input.provider)
21
+ const ttsInput: ITTSParams = {
22
+ ...(input as ITTSParams),
23
+ operationTitle: input.operationTitle ?? "generic-tts",
24
+ operationGroup: input.operationGroup ?? "generic-tts",
25
+ ip: context.ip,
26
+ userAgent: context.userAgent,
27
+ tenant: context.tenant ?? null,
28
+ user: context.user ?? null,
29
+ }
30
+
31
+ return ttsProvider.textToSpeech(ttsInput)
32
+ }
33
+ }
34
+
35
+ export default TTSGenericService;
36
+ export {
37
+ TTSGenericService,
38
+ }
39
+ export type {
40
+ TTSRequestContext,
41
+ }
@@ -1,5 +1,5 @@
1
1
  import {describe, expect, test} from "vitest";
2
- import {AiProviderFactory, DeepSeekProvider} from "../src";
2
+ import {AiProviderFactory, DeepSeekAiProvider} from "../src";
3
3
  import {IPromptTool} from "../src/interfaces/IAIProvider";
4
4
 
5
5
  describe("DeepSeekProvider Test", () => {
@@ -7,7 +7,7 @@ describe("DeepSeekProvider Test", () => {
7
7
  test("DeepSeek prompt uses OpenAI-compatible chat completions", async () => {
8
8
  let request: any
9
9
 
10
- class MockedDeepSeekProvider extends DeepSeekProvider {
10
+ class MockedDeepSeekProvider extends DeepSeekAiProvider {
11
11
  constructor() {
12
12
  super("test-key", "deepseek-chat")
13
13
  this._client = {
@@ -61,7 +61,7 @@ describe("DeepSeekProvider Test", () => {
61
61
  execute: async ({city}) => ({city, temperature: 21})
62
62
  }
63
63
 
64
- class MockedDeepSeekProvider extends DeepSeekProvider {
64
+ class MockedDeepSeekProvider extends DeepSeekAiProvider {
65
65
  constructor() {
66
66
  super("test-key", "deepseek-chat")
67
67
  this._client = {
@@ -141,6 +141,6 @@ describe("DeepSeekProvider Test", () => {
141
141
  process.env.DRAX_DB_ENGINE = "mongo"
142
142
 
143
143
  const deepSeek = AiProviderFactory.instance("DeepSeek")
144
- expect(deepSeek).toBeInstanceOf(DeepSeekProvider)
144
+ expect(deepSeek).toBeInstanceOf(DeepSeekAiProvider)
145
145
  })
146
146
  })
@@ -144,6 +144,70 @@ describe("DraxAgent", () => {
144
144
  ]);
145
145
  });
146
146
 
147
+ test("passes audioResponse to provider and returns prompt audio", async () => {
148
+ class AudioMockProvider extends MockProvider {
149
+ async prompt(input: IPromptParams): Promise<IPromptResponse> {
150
+ this.requests.push(input);
151
+
152
+ return {
153
+ output: "respuesta hablada",
154
+ tokens: 10,
155
+ inputTokens: 6,
156
+ outputTokens: 4,
157
+ time: 12,
158
+ audio: {
159
+ audio: Buffer.from("audio").toString("base64"),
160
+ contentType: "audio/mpeg",
161
+ encoding: "base64",
162
+ meta: {
163
+ provider: "elevenlabs",
164
+ model: "eleven_multilingual_v2",
165
+ voiceId: "voice-1",
166
+ size: 5,
167
+ time: 20,
168
+ },
169
+ },
170
+ };
171
+ }
172
+ }
173
+
174
+ const provider = new AudioMockProvider();
175
+ const agent = new DraxAgent().configure({
176
+ provider,
177
+ systemPrompt: "Sos un asistente.",
178
+ sessionService: false,
179
+ toolBuilders: undefined,
180
+ tools: undefined,
181
+ });
182
+
183
+ const response = await agent.sendMessage({
184
+ userId: "user-1",
185
+ message: "Hola",
186
+ audioResponse: {
187
+ provider: "ElevenLabs",
188
+ languageCode: "es",
189
+ },
190
+ });
191
+
192
+ expect(provider.requests[0].audioResponse).toEqual({
193
+ provider: "ElevenLabs",
194
+ languageCode: "es",
195
+ });
196
+ expect(response.message).toBe("respuesta hablada");
197
+ expect(response.audio).toEqual({
198
+ audio: Buffer.from("audio").toString("base64"),
199
+ contentType: "audio/mpeg",
200
+ encoding: "base64",
201
+ meta: {
202
+ provider: "elevenlabs",
203
+ model: "eleven_multilingual_v2",
204
+ voiceId: "voice-1",
205
+ size: 5,
206
+ time: 20,
207
+ },
208
+ });
209
+ });
210
+
147
211
  test("returns a navigation path from tool execution metadata", async () => {
148
212
  const provider = new MockProvider();
149
213
  const agent = new DraxAgent().configure({
@@ -0,0 +1,115 @@
1
+ import {afterEach, describe, expect, test, vi} from "vitest";
2
+ import {PromptAudioService, TTSProviderFactory} from "../src";
3
+
4
+ describe("PromptAudioService Test", () => {
5
+
6
+ afterEach(() => {
7
+ vi.restoreAllMocks()
8
+ })
9
+
10
+ test("does not generate audio when audioResponse is not requested", async () => {
11
+ const instanceSpy = vi.spyOn(TTSProviderFactory, "instance")
12
+
13
+ const audio = await PromptAudioService.build({
14
+ systemPrompt: "You are an assistant.",
15
+ }, "Hola")
16
+
17
+ expect(audio).toBeUndefined()
18
+ expect(instanceSpy).not.toHaveBeenCalled()
19
+ })
20
+
21
+ test("generates base64 prompt audio with default ElevenLabs provider", async () => {
22
+ const textToSpeech = vi.fn(async () => ({
23
+ audio: Buffer.from("audio-bytes"),
24
+ contentType: "audio/mpeg",
25
+ size: 11,
26
+ time: 25,
27
+ provider: "elevenlabs",
28
+ model: "eleven_multilingual_v2",
29
+ voiceId: "voice-1",
30
+ outputFormat: "mp3_44100_128",
31
+ }))
32
+ const instanceSpy = vi.spyOn(TTSProviderFactory, "instance").mockReturnValue({
33
+ textToSpeech,
34
+ })
35
+
36
+ const audio = await PromptAudioService.build({
37
+ systemPrompt: "You are an assistant.",
38
+ audioResponse: true,
39
+ operationTitle: "prompt-title",
40
+ operationGroup: "prompt-group",
41
+ ip: "127.0.0.1",
42
+ userAgent: "vitest",
43
+ tenant: "tenant-1",
44
+ user: "user-1",
45
+ }, "Hola mundo")
46
+
47
+ expect(instanceSpy).toHaveBeenCalledWith("ElevenLabs")
48
+ expect(textToSpeech).toHaveBeenCalledWith({
49
+ text: "Hola mundo",
50
+ voiceId: undefined,
51
+ model: undefined,
52
+ outputFormat: undefined,
53
+ voiceSettings: undefined,
54
+ previousText: undefined,
55
+ nextText: undefined,
56
+ languageCode: undefined,
57
+ seed: undefined,
58
+ operationTitle: "prompt-title",
59
+ operationGroup: "prompt-group",
60
+ ip: "127.0.0.1",
61
+ userAgent: "vitest",
62
+ tenant: "tenant-1",
63
+ user: "user-1",
64
+ })
65
+ expect(audio).toEqual({
66
+ audio: Buffer.from("audio-bytes").toString("base64"),
67
+ contentType: "audio/mpeg",
68
+ encoding: "base64",
69
+ meta: {
70
+ provider: "elevenlabs",
71
+ model: "eleven_multilingual_v2",
72
+ voiceId: "voice-1",
73
+ outputFormat: "mp3_44100_128",
74
+ size: 11,
75
+ time: 25,
76
+ },
77
+ })
78
+ })
79
+
80
+ test("supports custom TTS provider params", async () => {
81
+ const textToSpeech = vi.fn(async () => ({
82
+ audio: Buffer.from("custom-audio"),
83
+ contentType: "audio/ogg",
84
+ size: 12,
85
+ time: 31,
86
+ provider: "custom",
87
+ model: "custom-model",
88
+ voiceId: "voice-2",
89
+ }))
90
+ const instanceSpy = vi.spyOn(TTSProviderFactory, "instance").mockReturnValue({
91
+ textToSpeech,
92
+ })
93
+
94
+ await PromptAudioService.build({
95
+ systemPrompt: "You are an assistant.",
96
+ audioResponse: {
97
+ provider: "CustomTTS",
98
+ voiceId: "voice-2",
99
+ model: "custom-model",
100
+ languageCode: "es",
101
+ operationTitle: "tts-title",
102
+ },
103
+ }, {message: "Hola"})
104
+
105
+ expect(instanceSpy).toHaveBeenCalledWith("CustomTTS")
106
+ expect(textToSpeech).toHaveBeenCalledWith(expect.objectContaining({
107
+ text: "{\"message\":\"Hola\"}",
108
+ voiceId: "voice-2",
109
+ model: "custom-model",
110
+ languageCode: "es",
111
+ operationTitle: "tts-title",
112
+ }))
113
+ })
114
+
115
+ })