@drax/ai-back 3.42.0 → 3.44.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 (41) hide show
  1. package/dist/agents/DraxAgent.js +2 -0
  2. package/dist/controllers/AIGenericController.js +22 -0
  3. package/dist/controllers/DraxAgentController.js +22 -0
  4. package/dist/index.js +4 -2
  5. package/dist/providers/ai/GoogleAiProvider.js +4 -1
  6. package/dist/providers/ai/OllamaAiProvider.js +4 -1
  7. package/dist/providers/ai/OpenAiProvider.js +4 -1
  8. package/dist/services/PromptAudioService.js +68 -0
  9. package/dist/tools/BuildContextTool.js +267 -0
  10. package/package.json +3 -3
  11. package/src/agents/DraxAgent.ts +2 -0
  12. package/src/controllers/AIGenericController.ts +24 -0
  13. package/src/controllers/DraxAgentController.ts +24 -0
  14. package/src/index.ts +16 -0
  15. package/src/interfaces/IAIProvider.ts +38 -1
  16. package/src/interfaces/IDraxAgent.ts +4 -0
  17. package/src/providers/ai/GoogleAiProvider.ts +4 -1
  18. package/src/providers/ai/OllamaAiProvider.ts +4 -1
  19. package/src/providers/ai/OpenAiProvider.ts +4 -1
  20. package/src/services/PromptAudioService.ts +87 -0
  21. package/src/tools/BuildContextTool.ts +388 -0
  22. package/test/BuildContextTool.test.ts +183 -0
  23. package/test/DraxAgent.test.ts +64 -0
  24. package/test/PromptAudioService.test.ts +115 -0
  25. package/tsconfig.tsbuildinfo +1 -1
  26. package/types/agents/DraxAgent.d.ts.map +1 -1
  27. package/types/controllers/AIGenericController.d.ts.map +1 -1
  28. package/types/controllers/DraxAgentController.d.ts.map +1 -1
  29. package/types/index.d.ts +6 -3
  30. package/types/index.d.ts.map +1 -1
  31. package/types/interfaces/IAIProvider.d.ts +32 -1
  32. package/types/interfaces/IAIProvider.d.ts.map +1 -1
  33. package/types/interfaces/IDraxAgent.d.ts +3 -1
  34. package/types/interfaces/IDraxAgent.d.ts.map +1 -1
  35. package/types/providers/ai/GoogleAiProvider.d.ts.map +1 -1
  36. package/types/providers/ai/OllamaAiProvider.d.ts.map +1 -1
  37. package/types/providers/ai/OpenAiProvider.d.ts.map +1 -1
  38. package/types/services/PromptAudioService.d.ts +9 -0
  39. package/types/services/PromptAudioService.d.ts.map +1 -0
  40. package/types/tools/BuildContextTool.d.ts +33 -0
  41. package/types/tools/BuildContextTool.d.ts.map +1 -0
@@ -78,6 +78,7 @@ class DraxAgent {
78
78
  userAgent: input.userAgent,
79
79
  tenant: input.tenantId ?? session.tenantId ?? null,
80
80
  user: input.userId ?? session.userId ?? null,
81
+ audioResponse: input.audioResponse,
81
82
  });
82
83
  const assistantMessage = this.normalizeOutput(response.output);
83
84
  const now = new Date();
@@ -100,6 +101,7 @@ class DraxAgent {
100
101
  inputTokens: response.inputTokens,
101
102
  outputTokens: response.outputTokens,
102
103
  time: response.time,
104
+ ...(response.audio ? { audio: response.audio } : {}),
103
105
  };
104
106
  }
105
107
  async createSession(input = {}) {
@@ -35,6 +35,27 @@ const PromptInputFileSchema = z.object({
35
35
  mimetype: z.string().optional(),
36
36
  url: z.string().optional(),
37
37
  });
38
+ const PromptAudioVoiceSettingsSchema = z.object({
39
+ stability: z.number().min(0).max(1).optional(),
40
+ similarityBoost: z.number().min(0).max(1).optional(),
41
+ style: z.number().min(0).max(1).optional(),
42
+ useSpeakerBoost: z.boolean().optional(),
43
+ speed: z.number().positive().optional(),
44
+ });
45
+ const PromptAudioParamsSchema = z.object({
46
+ enabled: z.boolean().optional(),
47
+ provider: z.string().optional(),
48
+ voiceId: z.string().optional(),
49
+ model: z.string().optional(),
50
+ outputFormat: z.string().optional(),
51
+ voiceSettings: PromptAudioVoiceSettingsSchema.optional(),
52
+ previousText: z.string().optional(),
53
+ nextText: z.string().optional(),
54
+ languageCode: z.string().optional(),
55
+ seed: z.number().int().optional(),
56
+ operationTitle: z.string().optional(),
57
+ operationGroup: z.string().optional(),
58
+ });
38
59
  const GenericPromptRequestSchema = z.object({
39
60
  systemPrompt: z.string().min(1),
40
61
  userInput: z.string().optional(),
@@ -50,6 +71,7 @@ const GenericPromptRequestSchema = z.object({
50
71
  model: z.string().optional(),
51
72
  operationTitle: z.string().optional(),
52
73
  operationGroup: z.string().optional(),
74
+ audioResponse: z.union([z.boolean(), PromptAudioParamsSchema]).optional(),
53
75
  });
54
76
  class AIGenericController extends CommonController {
55
77
  async prompt(request, reply) {
@@ -28,6 +28,27 @@ const PromptInputFileSchema = z.object({
28
28
  mimetype: z.string().optional(),
29
29
  url: z.string().optional(),
30
30
  });
31
+ const PromptAudioVoiceSettingsSchema = z.object({
32
+ stability: z.number().min(0).max(1).optional(),
33
+ similarityBoost: z.number().min(0).max(1).optional(),
34
+ style: z.number().min(0).max(1).optional(),
35
+ useSpeakerBoost: z.boolean().optional(),
36
+ speed: z.number().positive().optional(),
37
+ });
38
+ const PromptAudioParamsSchema = z.object({
39
+ enabled: z.boolean().optional(),
40
+ provider: z.string().optional(),
41
+ voiceId: z.string().optional(),
42
+ model: z.string().optional(),
43
+ outputFormat: z.string().optional(),
44
+ voiceSettings: PromptAudioVoiceSettingsSchema.optional(),
45
+ previousText: z.string().optional(),
46
+ nextText: z.string().optional(),
47
+ languageCode: z.string().optional(),
48
+ seed: z.number().int().optional(),
49
+ operationTitle: z.string().optional(),
50
+ operationGroup: z.string().optional(),
51
+ });
31
52
  const AgentSessionRequestSchema = z.object({
32
53
  identifier: z.string().min(1).optional(),
33
54
  sessionId: z.string().optional(),
@@ -47,6 +68,7 @@ const AgentMessageRequestSchema = AgentSessionRequestSchema.extend({
47
68
  toolMaxIterations: z.number().optional(),
48
69
  operationTitle: z.string().optional(),
49
70
  operationGroup: z.string().optional(),
71
+ audioResponse: z.union([z.boolean(), PromptAudioParamsSchema]).optional(),
50
72
  });
51
73
  class DraxAgentController extends CommonController {
52
74
  constructor(options = {}) {
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ import { BuilderTool } from "./tools/BuilderTool.js";
26
26
  import { KnowledgeService } from "./services/KnowledgeService.js";
27
27
  import { AILogService } from "./services/AILogService.js";
28
28
  import { TTSGenericService } from "./services/TTSGenericService.js";
29
+ import { PromptAudioService } from "./services/PromptAudioService.js";
29
30
  import AILogPermissions from "./permissions/AILogPermissions.js";
30
31
  import AgentPermissions from "./permissions/AgentPermissions.js";
31
32
  import AgentSessionPermissions from "./permissions/AgentSessionPermissions.js";
@@ -43,9 +44,10 @@ import TTSRoutes from "./routes/TTSRoutes.js";
43
44
  import DraxAgentRoutes from "./routes/DraxAgentRoutes.js";
44
45
  import AgentSessionRoutes from "./routes/AgentSessionRoutes.js";
45
46
  import { DraxAgent } from "./agents/DraxAgent.js";
46
- export { OpenAiConfig, GoogleAiConfig, OllamaAiConfig, DeepSeekConfig, ElevenLabsTTSConfig, AILogSchema, AILogBaseSchema, TTSRequestSchema, TTSVoiceSettingsSchema, AILogModel, AILogMongoRepository, AILogSqliteRepository, OpenAiProviderFactory, GoogleAiProviderFactory, OllamaAiProviderFactory, DeepSeekAiProviderFactory, AiProviderFactory, ElevenLabsTTSProviderFactory, TTSProviderFactory, DraxAgentFactory, AILogServiceFactory, OpenAiProvider, GoogleAiProvider, OllamaAiProvider, DeepSeekAiProvider, ElevenLabsTTSProvider, BuilderTool,
47
+ import { BuildContextTool } from "./tools/BuildContextTool.js";
48
+ export { OpenAiConfig, GoogleAiConfig, OllamaAiConfig, DeepSeekConfig, ElevenLabsTTSConfig, AILogSchema, AILogBaseSchema, TTSRequestSchema, TTSVoiceSettingsSchema, AILogModel, AILogMongoRepository, AILogSqliteRepository, OpenAiProviderFactory, GoogleAiProviderFactory, OllamaAiProviderFactory, DeepSeekAiProviderFactory, AiProviderFactory, ElevenLabsTTSProviderFactory, TTSProviderFactory, DraxAgentFactory, AILogServiceFactory, OpenAiProvider, GoogleAiProvider, OllamaAiProvider, DeepSeekAiProvider, ElevenLabsTTSProvider, BuilderTool, BuildContextTool,
47
49
  //Service
48
- KnowledgeService, AILogService, TTSGenericService,
50
+ KnowledgeService, AILogService, TTSGenericService, PromptAudioService,
49
51
  //Permissions
50
52
  AILogPermissions, AgentPermissions, AIPermissions, TTSPermissions, AgentSessionPermissions,
51
53
  //Controllers
@@ -1,5 +1,6 @@
1
1
  import { GoogleGenAI } from "@google/genai";
2
2
  import { toJSONSchema } from "zod";
3
+ import PromptAudioService from "../../services/PromptAudioService.js";
3
4
  class GoogleAiProvider {
4
5
  constructor(apiKey, model, visionModel, aiLogService) {
5
6
  if (!apiKey) {
@@ -330,6 +331,7 @@ class GoogleAiProvider {
330
331
  const endTime = performance.now();
331
332
  const time = endTime - startTime;
332
333
  const endedAt = new Date();
334
+ const audio = await PromptAudioService.build(input, output);
333
335
  await this.registerPromptLog(input, {
334
336
  model,
335
337
  systemPrompt,
@@ -346,7 +348,8 @@ class GoogleAiProvider {
346
348
  tokens,
347
349
  inputTokens,
348
350
  outputTokens,
349
- time
351
+ time,
352
+ ...(audio ? { audio } : {}),
350
353
  };
351
354
  }
352
355
  catch (e) {
@@ -1,4 +1,5 @@
1
1
  import { toJSONSchema } from "zod";
2
+ import PromptAudioService from "../../services/PromptAudioService.js";
2
3
  class OllamaAiProvider {
3
4
  constructor(baseUrl, model, visionModel, embeddingModel, aiLogService) {
4
5
  if (!baseUrl) {
@@ -305,6 +306,7 @@ class OllamaAiProvider {
305
306
  const endTime = performance.now();
306
307
  const time = endTime - startTime;
307
308
  const endedAt = new Date();
309
+ const audio = await PromptAudioService.build(input, output);
308
310
  await this.registerPromptLog(input, {
309
311
  model,
310
312
  systemPrompt,
@@ -321,7 +323,8 @@ class OllamaAiProvider {
321
323
  tokens,
322
324
  inputTokens,
323
325
  outputTokens,
324
- time
326
+ time,
327
+ ...(audio ? { audio } : {}),
325
328
  };
326
329
  }
327
330
  catch (e) {
@@ -1,5 +1,6 @@
1
1
  import OpenAI from "openai";
2
2
  import { zodResponseFormat } from "openai/helpers/zod";
3
+ import PromptAudioService from "../../services/PromptAudioService.js";
3
4
  class OpenAiProvider {
4
5
  constructor(apiKey, model, visionModel, aiLogService) {
5
6
  if (!apiKey) {
@@ -265,6 +266,7 @@ class OpenAiProvider {
265
266
  const endTime = performance.now();
266
267
  const time = endTime - startTime;
267
268
  const endedAt = new Date();
269
+ const audio = await PromptAudioService.build(input, output);
268
270
  await this.registerPromptLog(input, {
269
271
  model,
270
272
  systemPrompt,
@@ -281,7 +283,8 @@ class OpenAiProvider {
281
283
  tokens,
282
284
  inputTokens,
283
285
  outputTokens,
284
- time
286
+ time,
287
+ ...(audio ? { audio } : {}),
285
288
  };
286
289
  }
287
290
  catch (e) {
@@ -0,0 +1,68 @@
1
+ import TTSProviderFactory from "../factory/tts/TTSProviderFactory.js";
2
+ class PromptAudioService {
3
+ static audioParams(input) {
4
+ if (!input.audioResponse) {
5
+ return null;
6
+ }
7
+ if (input.audioResponse === true) {
8
+ return {};
9
+ }
10
+ if (input.audioResponse.enabled === false) {
11
+ return null;
12
+ }
13
+ return input.audioResponse;
14
+ }
15
+ static outputToText(output) {
16
+ if (typeof output === "string") {
17
+ return output;
18
+ }
19
+ if (output === null || output === undefined) {
20
+ return "";
21
+ }
22
+ return JSON.stringify(output);
23
+ }
24
+ static async build(input, output) {
25
+ const audioParams = PromptAudioService.audioParams(input);
26
+ if (!audioParams) {
27
+ return undefined;
28
+ }
29
+ const text = PromptAudioService.outputToText(output).trim();
30
+ if (!text) {
31
+ return undefined;
32
+ }
33
+ const providerName = audioParams.provider ?? "ElevenLabs";
34
+ const ttsProvider = TTSProviderFactory.instance(providerName);
35
+ const response = await ttsProvider.textToSpeech({
36
+ text,
37
+ voiceId: audioParams.voiceId,
38
+ model: audioParams.model,
39
+ outputFormat: audioParams.outputFormat,
40
+ voiceSettings: audioParams.voiceSettings,
41
+ previousText: audioParams.previousText,
42
+ nextText: audioParams.nextText,
43
+ languageCode: audioParams.languageCode,
44
+ seed: audioParams.seed,
45
+ operationTitle: audioParams.operationTitle ?? input.operationTitle,
46
+ operationGroup: audioParams.operationGroup ?? input.operationGroup,
47
+ ip: input.ip,
48
+ userAgent: input.userAgent,
49
+ tenant: input.tenant,
50
+ user: input.user,
51
+ });
52
+ return {
53
+ audio: response.audio.toString("base64"),
54
+ contentType: response.contentType,
55
+ encoding: "base64",
56
+ meta: {
57
+ provider: response.provider,
58
+ model: response.model,
59
+ voiceId: response.voiceId,
60
+ outputFormat: response.outputFormat,
61
+ size: response.size,
62
+ time: response.time,
63
+ },
64
+ };
65
+ }
66
+ }
67
+ export default PromptAudioService;
68
+ export { PromptAudioService, };
@@ -0,0 +1,267 @@
1
+ import { setNestedValue, UnauthorizedError } from "@drax/common-back";
2
+ import { BuilderTool } from "./BuilderTool.js";
3
+ class BuildContextTool extends BuilderTool {
4
+ constructor(options) {
5
+ super({
6
+ ...options,
7
+ service: BuildContextTool.createContextService(options),
8
+ });
9
+ }
10
+ static fromPromptContext(options, promptContext) {
11
+ return new BuildContextTool({
12
+ ...options,
13
+ context: {
14
+ userId: promptContext.input?.userId ?? promptContext.session.userId ?? null,
15
+ tenantId: promptContext.input?.tenantId ?? promptContext.session.tenantId ?? null,
16
+ },
17
+ });
18
+ }
19
+ static createContextService(options) {
20
+ const service = options.service;
21
+ const helper = new BuildContextToolServiceHelper(options);
22
+ const contextService = { ...service };
23
+ if (typeof service.create === "function") {
24
+ contextService.create = async (data) => service.create?.(helper.applySetters(helper.clonePayload(data)));
25
+ }
26
+ if (typeof service.update === "function") {
27
+ contextService.update = async (id, data) => {
28
+ const preItem = await service.findById?.(id);
29
+ helper.assertWritable(preItem, "update");
30
+ const payload = helper.removeSetterFields(helper.clonePayload(data));
31
+ return service.update?.(id, payload);
32
+ };
33
+ }
34
+ if (typeof service.updatePartial === "function") {
35
+ contextService.updatePartial = async (id, data) => {
36
+ const preItem = await service.findById?.(id);
37
+ helper.assertWritable(preItem, "update");
38
+ const payload = helper.removeSetterFields(helper.clonePayload(data));
39
+ return service.updatePartial?.(id, payload);
40
+ };
41
+ }
42
+ if (typeof service.delete === "function") {
43
+ contextService.delete = async (id) => {
44
+ const item = await service.findById?.(id);
45
+ helper.assertWritable(item, "delete");
46
+ return service.delete?.(id);
47
+ };
48
+ }
49
+ if (typeof service.findById === "function") {
50
+ contextService.findById = async (id) => {
51
+ const item = await service.findById?.(id);
52
+ helper.assertReadable(item);
53
+ return item;
54
+ };
55
+ }
56
+ if (typeof service.findByIds === "function") {
57
+ contextService.findByIds = async (ids) => {
58
+ const items = await service.findByIds?.(ids);
59
+ helper.assertReadableItems(items);
60
+ return items;
61
+ };
62
+ }
63
+ if (typeof service.findOneBy === "function") {
64
+ contextService.findOneBy = async (field, value, filters = []) => service.findOneBy?.(field, value, helper.applyReadFilters(filters));
65
+ }
66
+ if (typeof service.findOne === "function") {
67
+ contextService.findOne = async (findOptions) => service.findOne?.({
68
+ ...findOptions,
69
+ filters: helper.applyReadFilters(findOptions?.filters ?? []),
70
+ });
71
+ }
72
+ if (typeof service.findBy === "function") {
73
+ contextService.findBy = async (field, value, limit = helper.defaultLimit, filters = []) => service.findBy?.(field, value, limit, helper.applyReadFilters(filters));
74
+ }
75
+ if (typeof service.fetchAll === "function") {
76
+ contextService.fetchAll = async () => {
77
+ const filters = helper.applyReadFilters([]);
78
+ if (filters.length > 0 && typeof service.find === "function") {
79
+ return service.find({
80
+ search: "",
81
+ filters,
82
+ order: false,
83
+ orderBy: "",
84
+ limit: helper.defaultLimit,
85
+ });
86
+ }
87
+ return service.fetchAll?.();
88
+ };
89
+ }
90
+ if (typeof service.findFirst === "function") {
91
+ contextService.findFirst = async (quantity, filters = []) => service.findFirst?.(quantity, helper.applyReadFilters(filters));
92
+ }
93
+ if (typeof service.findLast === "function") {
94
+ contextService.findLast = async (quantity, filters = []) => service.findLast?.(quantity, helper.applyReadFilters(filters));
95
+ }
96
+ if (typeof service.search === "function") {
97
+ contextService.search = async (value, limit = helper.defaultLimit, filters = []) => service.search?.(value, limit, helper.applyReadFilters(filters));
98
+ }
99
+ if (typeof service.find === "function") {
100
+ contextService.find = async (findOptions) => service.find?.({
101
+ ...findOptions,
102
+ filters: helper.applyReadFilters(findOptions?.filters ?? []),
103
+ });
104
+ }
105
+ if (typeof service.paginate === "function") {
106
+ contextService.paginate = async (paginateOptions) => service.paginate?.({
107
+ ...paginateOptions,
108
+ filters: helper.applyReadFilters(paginateOptions?.filters ?? []),
109
+ });
110
+ }
111
+ if (typeof service.groupBy === "function") {
112
+ contextService.groupBy = async (groupByOptions) => service.groupBy?.({
113
+ ...groupByOptions,
114
+ filters: helper.applyReadFilters(groupByOptions?.filters ?? []),
115
+ });
116
+ }
117
+ return contextService;
118
+ }
119
+ }
120
+ class BuildContextToolServiceHelper {
121
+ constructor(options) {
122
+ this.context = options.context ?? {};
123
+ this.permission = options.permission;
124
+ this.tenantField = options.tenantField ?? "tenant";
125
+ this.userField = options.userField ?? "user";
126
+ this.tenantFilter = options.tenantFilter ?? false;
127
+ this.tenantSetter = options.tenantSetter ?? false;
128
+ this.tenantAssert = options.tenantAssert ?? false;
129
+ this.userFilter = options.userFilter ?? false;
130
+ this.userSetter = options.userSetter ?? false;
131
+ this.userAssert = options.userAssert ?? false;
132
+ this.defaultLimit = options.defaultLimit ?? 1000;
133
+ }
134
+ clonePayload(payload) {
135
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
136
+ return payload;
137
+ }
138
+ return { ...payload };
139
+ }
140
+ applySetters(payload) {
141
+ if (!payload || typeof payload !== "object") {
142
+ return payload;
143
+ }
144
+ if (this.tenantSetter && this.context.tenantId) {
145
+ setNestedValue(payload, this.tenantField, this.context.tenantId);
146
+ }
147
+ if (this.userSetter && this.context.userId) {
148
+ setNestedValue(payload, this.userField, this.context.userId);
149
+ }
150
+ return payload;
151
+ }
152
+ removeSetterFields(payload) {
153
+ if (!payload || typeof payload !== "object") {
154
+ return payload;
155
+ }
156
+ if (this.tenantSetter) {
157
+ this.deleteNestedValue(payload, this.tenantField);
158
+ }
159
+ if (this.userSetter) {
160
+ this.deleteNestedValue(payload, this.userField);
161
+ }
162
+ return payload;
163
+ }
164
+ applyReadFilters(filters = []) {
165
+ const nextFilters = [...filters];
166
+ if (this.tenantFilter && this.context.tenantId) {
167
+ nextFilters.push({ field: this.tenantField, operator: "eq", value: this.context.tenantId });
168
+ }
169
+ if (this.userFilter &&
170
+ this.context.userId &&
171
+ !this.hasSomePermission([this.permission?.All, this.permission?.ViewAll])) {
172
+ nextFilters.push({ field: this.userField, operator: "eq", value: this.context.userId });
173
+ }
174
+ return nextFilters;
175
+ }
176
+ assertReadable(item) {
177
+ if (this.hasSomePermission([this.permission?.All, this.permission?.ViewAll])) {
178
+ this.assertTenant(item);
179
+ return;
180
+ }
181
+ this.assertTenant(item);
182
+ this.assertUser(item);
183
+ }
184
+ assertReadableItems(items) {
185
+ if (!Array.isArray(items)) {
186
+ return;
187
+ }
188
+ items.forEach(item => this.assertReadable(item));
189
+ }
190
+ assertWritable(item, operation) {
191
+ const allPermission = this.permission?.All;
192
+ const operationAllPermission = operation === "update"
193
+ ? this.permission?.UpdateAll
194
+ : this.permission?.DeleteAll;
195
+ if (!this.hasSomePermission([allPermission, operationAllPermission])) {
196
+ this.assertUser(item);
197
+ }
198
+ this.assertTenant(item);
199
+ }
200
+ assertTenant(item) {
201
+ if (!this.tenantAssert || !this.context.tenantId) {
202
+ return;
203
+ }
204
+ const tenantId = this.resolveItemFieldId(item, this.tenantField);
205
+ if (tenantId) {
206
+ this.assertId(this.context.tenantId, tenantId);
207
+ }
208
+ }
209
+ assertUser(item) {
210
+ if (!this.userAssert || !this.context.userId) {
211
+ return;
212
+ }
213
+ const userId = this.resolveItemFieldId(item, this.userField);
214
+ if (userId) {
215
+ this.assertId(this.context.userId, userId);
216
+ }
217
+ }
218
+ assertId(expectedId, actualId) {
219
+ if (expectedId !== actualId) {
220
+ throw new UnauthorizedError();
221
+ }
222
+ }
223
+ hasSomePermission(permissions) {
224
+ const requiredPermissions = permissions.filter((permission) => !!permission);
225
+ if (requiredPermissions.length === 0) {
226
+ return false;
227
+ }
228
+ if (this.context.hasSomePermission?.(requiredPermissions)) {
229
+ return true;
230
+ }
231
+ return requiredPermissions.some(permission => this.context.permissions?.includes(permission));
232
+ }
233
+ resolveItemFieldId(item, field) {
234
+ const value = this.getNestedValue(item, field);
235
+ return this.stringifyRelationId(value);
236
+ }
237
+ getNestedValue(item, path) {
238
+ return path.split(".").reduce((value, key) => value?.[key], item);
239
+ }
240
+ stringifyRelationId(value) {
241
+ if (value === null || value === undefined || value === "") {
242
+ return null;
243
+ }
244
+ const id = value?._id ?? value?.id ?? value;
245
+ if (typeof id === "string" || typeof id === "number" || typeof id === "boolean") {
246
+ return String(id);
247
+ }
248
+ if (typeof id?.toString === "function") {
249
+ const stringId = id.toString();
250
+ return stringId && stringId !== "[object Object]" ? stringId : null;
251
+ }
252
+ return null;
253
+ }
254
+ deleteNestedValue(payload, path) {
255
+ const keys = path.split(".");
256
+ const lastKey = keys.pop();
257
+ if (!lastKey) {
258
+ return;
259
+ }
260
+ const parent = keys.reduce((value, key) => value?.[key], payload);
261
+ if (parent && typeof parent === "object") {
262
+ delete parent[lastKey];
263
+ }
264
+ }
265
+ }
266
+ export default BuildContextTool;
267
+ export { BuildContextTool };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "3.42.0",
6
+ "version": "3.44.0",
7
7
  "description": "Ai utils",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -18,7 +18,7 @@
18
18
  "author": "Cristian Incarnato & Drax Team",
19
19
  "license": "ISC",
20
20
  "dependencies": {
21
- "@drax/ai-share": "^3.31.0",
21
+ "@drax/ai-share": "^3.43.0",
22
22
  "@drax/crud-back": "^3.39.0",
23
23
  "mongoose": "^8.23.0",
24
24
  "mongoose-paginate-v2": "^1.8.3"
@@ -46,5 +46,5 @@
46
46
  "typescript": "^5.9.3",
47
47
  "vitest": "^3.0.8"
48
48
  },
49
- "gitHead": "30b8ca8c49adb16b4617e61c497b554389c49dd1"
49
+ "gitHead": "4ba7a86c8b28bba3156bd124a76f3150ba0f676e"
50
50
  }
@@ -110,6 +110,7 @@ class DraxAgent {
110
110
  userAgent: input.userAgent,
111
111
  tenant: input.tenantId ?? session.tenantId ?? null,
112
112
  user: input.userId ?? session.userId ?? null,
113
+ audioResponse: input.audioResponse,
113
114
  });
114
115
 
115
116
  const assistantMessage = this.normalizeOutput(response.output);
@@ -134,6 +135,7 @@ class DraxAgent {
134
135
  inputTokens: response.inputTokens,
135
136
  outputTokens: response.outputTokens,
136
137
  time: response.time,
138
+ ...(response.audio ? {audio: response.audio} : {}),
137
139
  };
138
140
  }
139
141
 
@@ -42,6 +42,29 @@ const PromptInputFileSchema = z.object({
42
42
  url: z.string().optional(),
43
43
  })
44
44
 
45
+ const PromptAudioVoiceSettingsSchema = z.object({
46
+ stability: z.number().min(0).max(1).optional(),
47
+ similarityBoost: z.number().min(0).max(1).optional(),
48
+ style: z.number().min(0).max(1).optional(),
49
+ useSpeakerBoost: z.boolean().optional(),
50
+ speed: z.number().positive().optional(),
51
+ })
52
+
53
+ const PromptAudioParamsSchema = z.object({
54
+ enabled: z.boolean().optional(),
55
+ provider: z.string().optional(),
56
+ voiceId: z.string().optional(),
57
+ model: z.string().optional(),
58
+ outputFormat: z.string().optional(),
59
+ voiceSettings: PromptAudioVoiceSettingsSchema.optional(),
60
+ previousText: z.string().optional(),
61
+ nextText: z.string().optional(),
62
+ languageCode: z.string().optional(),
63
+ seed: z.number().int().optional(),
64
+ operationTitle: z.string().optional(),
65
+ operationGroup: z.string().optional(),
66
+ })
67
+
45
68
  const GenericPromptRequestSchema = z.object({
46
69
  systemPrompt: z.string().min(1),
47
70
  userInput: z.string().optional(),
@@ -57,6 +80,7 @@ const GenericPromptRequestSchema = z.object({
57
80
  model: z.string().optional(),
58
81
  operationTitle: z.string().optional(),
59
82
  operationGroup: z.string().optional(),
83
+ audioResponse: z.union([z.boolean(), PromptAudioParamsSchema]).optional(),
60
84
  })
61
85
 
62
86
  class AIGenericController extends CommonController {
@@ -35,6 +35,29 @@ const PromptInputFileSchema = z.object({
35
35
  url: z.string().optional(),
36
36
  });
37
37
 
38
+ const PromptAudioVoiceSettingsSchema = z.object({
39
+ stability: z.number().min(0).max(1).optional(),
40
+ similarityBoost: z.number().min(0).max(1).optional(),
41
+ style: z.number().min(0).max(1).optional(),
42
+ useSpeakerBoost: z.boolean().optional(),
43
+ speed: z.number().positive().optional(),
44
+ });
45
+
46
+ const PromptAudioParamsSchema = z.object({
47
+ enabled: z.boolean().optional(),
48
+ provider: z.string().optional(),
49
+ voiceId: z.string().optional(),
50
+ model: z.string().optional(),
51
+ outputFormat: z.string().optional(),
52
+ voiceSettings: PromptAudioVoiceSettingsSchema.optional(),
53
+ previousText: z.string().optional(),
54
+ nextText: z.string().optional(),
55
+ languageCode: z.string().optional(),
56
+ seed: z.number().int().optional(),
57
+ operationTitle: z.string().optional(),
58
+ operationGroup: z.string().optional(),
59
+ });
60
+
38
61
  const AgentSessionRequestSchema = z.object({
39
62
  identifier: z.string().min(1).optional(),
40
63
  sessionId: z.string().optional(),
@@ -55,6 +78,7 @@ const AgentMessageRequestSchema = AgentSessionRequestSchema.extend({
55
78
  toolMaxIterations: z.number().optional(),
56
79
  operationTitle: z.string().optional(),
57
80
  operationGroup: z.string().optional(),
81
+ audioResponse: z.union([z.boolean(), PromptAudioParamsSchema]).optional(),
58
82
  });
59
83
 
60
84
  class DraxAgentController extends CommonController {