@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.
- package/dist/agents/DraxAgent.js +2 -0
- package/dist/controllers/AIGenericController.js +22 -0
- package/dist/controllers/DraxAgentController.js +22 -0
- package/dist/index.js +4 -2
- package/dist/providers/ai/GoogleAiProvider.js +4 -1
- package/dist/providers/ai/OllamaAiProvider.js +4 -1
- package/dist/providers/ai/OpenAiProvider.js +4 -1
- package/dist/services/PromptAudioService.js +68 -0
- package/dist/tools/BuildContextTool.js +267 -0
- package/package.json +3 -3
- package/src/agents/DraxAgent.ts +2 -0
- package/src/controllers/AIGenericController.ts +24 -0
- package/src/controllers/DraxAgentController.ts +24 -0
- package/src/index.ts +16 -0
- package/src/interfaces/IAIProvider.ts +38 -1
- package/src/interfaces/IDraxAgent.ts +4 -0
- package/src/providers/ai/GoogleAiProvider.ts +4 -1
- package/src/providers/ai/OllamaAiProvider.ts +4 -1
- package/src/providers/ai/OpenAiProvider.ts +4 -1
- package/src/services/PromptAudioService.ts +87 -0
- package/src/tools/BuildContextTool.ts +388 -0
- package/test/BuildContextTool.test.ts +183 -0
- package/test/DraxAgent.test.ts +64 -0
- package/test/PromptAudioService.test.ts +115 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/types/agents/DraxAgent.d.ts.map +1 -1
- package/types/controllers/AIGenericController.d.ts.map +1 -1
- package/types/controllers/DraxAgentController.d.ts.map +1 -1
- package/types/index.d.ts +6 -3
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/IAIProvider.d.ts +32 -1
- package/types/interfaces/IAIProvider.d.ts.map +1 -1
- package/types/interfaces/IDraxAgent.d.ts +3 -1
- package/types/interfaces/IDraxAgent.d.ts.map +1 -1
- package/types/providers/ai/GoogleAiProvider.d.ts.map +1 -1
- package/types/providers/ai/OllamaAiProvider.d.ts.map +1 -1
- package/types/providers/ai/OpenAiProvider.d.ts.map +1 -1
- package/types/services/PromptAudioService.d.ts +9 -0
- package/types/services/PromptAudioService.d.ts.map +1 -0
- package/types/tools/BuildContextTool.d.ts +33 -0
- package/types/tools/BuildContextTool.d.ts.map +1 -0
package/dist/agents/DraxAgent.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
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": "
|
|
49
|
+
"gitHead": "4ba7a86c8b28bba3156bd124a76f3150ba0f676e"
|
|
50
50
|
}
|
package/src/agents/DraxAgent.ts
CHANGED
|
@@ -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 {
|