data-primals-engine 1.6.2-rc1 → 1.6.2
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/README.md +969 -968
- package/package.json +145 -142
- package/src/client.js +4 -0
- package/src/modules/assistant/assistant.js +38 -56
- package/src/modules/assistant/providers.js +38 -0
- package/src/modules/data/data.history.js +2 -5
- package/src/modules/data/data.operations.js +11 -2
- package/src/modules/workflow.js +2 -2
- package/test/assistant.test.js +207 -0
- package/test/config.test.js +41 -0
- package/test/data.history.integration.test.js +4 -4
package/package.json
CHANGED
|
@@ -1,142 +1,145 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "data-primals-engine",
|
|
3
|
-
"version": "1.6.2
|
|
4
|
-
"description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
|
|
5
|
-
"main": "src/engine.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"preinstall": "npx force-resolutions",
|
|
9
|
-
"dev": "concurrently \"npm:client\" \"npm:devserver\"",
|
|
10
|
-
"prod": "npm run build-server && npm run server",
|
|
11
|
-
"client": "cd client && npm run dev",
|
|
12
|
-
"build-server": "vite build client --config client/vite.config.js --outDir dist",
|
|
13
|
-
"build-client": "cd client && npm run build",
|
|
14
|
-
"server": "cross-env NODE_ENV=production node server.js",
|
|
15
|
-
"devserver": "npm run build-server && cross-env NODE_ENV=development PORT=7633 node server.js",
|
|
16
|
-
"lint": "eslint .",
|
|
17
|
-
"format": "prettier --write .",
|
|
18
|
-
"clean": "rm -rf node_modules package-lock.json",
|
|
19
|
-
"test": "cross-env MONGO_DB_URL=\"mongodb://localhost:27017\" PORT=7635 vitest --no-file-parallelism --no-watch",
|
|
20
|
-
"audit": "npm audit --audit-level=high",
|
|
21
|
-
"migrate:create": "node src/migrate.js create",
|
|
22
|
-
"migrate:up": "node src/migrate.js up",
|
|
23
|
-
"migrate:down": "node src/migrate.js down",
|
|
24
|
-
"migrate:revert": "node src/migrate.js revert",
|
|
25
|
-
"migrate:status": "node src/migrate.js status"
|
|
26
|
-
},
|
|
27
|
-
"optionalDependencies": {
|
|
28
|
-
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
|
29
|
-
},
|
|
30
|
-
"resolutions": {
|
|
31
|
-
"on-headers": "1.1.0",
|
|
32
|
-
"brace-expansion": "2.0.2",
|
|
33
|
-
"prismjs": "1.30.0",
|
|
34
|
-
"xml2js": ">=0.5.0",
|
|
35
|
-
"tar-fs": ">=3.1.1",
|
|
36
|
-
"vite": ">=7.0.8"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
"./client": "./client
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"express-
|
|
77
|
-
"express-
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"@langchain/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"@
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
"eslint": "^9.32.0",
|
|
124
|
-
"
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
"
|
|
128
|
-
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "data-primals-engine",
|
|
3
|
+
"version": "1.6.2",
|
|
4
|
+
"description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
|
|
5
|
+
"main": "src/engine.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"preinstall": "npx force-resolutions",
|
|
9
|
+
"dev": "concurrently \"npm:client\" \"npm:devserver\"",
|
|
10
|
+
"prod": "npm run build-server && npm run server",
|
|
11
|
+
"client": "cd client && npm run dev",
|
|
12
|
+
"build-server": "vite build client --config client/vite.config.js --outDir dist",
|
|
13
|
+
"build-client": "cd client && npm run build",
|
|
14
|
+
"server": "cross-env NODE_ENV=production node server.js",
|
|
15
|
+
"devserver": "npm run build-server && cross-env NODE_ENV=development PORT=7633 node server.js",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"format": "prettier --write .",
|
|
18
|
+
"clean": "rm -rf node_modules package-lock.json",
|
|
19
|
+
"test": "cross-env MONGO_DB_URL=\"mongodb://localhost:27017\" PORT=7635 vitest --no-file-parallelism --no-watch",
|
|
20
|
+
"audit": "npm audit --audit-level=high",
|
|
21
|
+
"migrate:create": "node src/migrate.js create",
|
|
22
|
+
"migrate:up": "node src/migrate.js up",
|
|
23
|
+
"migrate:down": "node src/migrate.js down",
|
|
24
|
+
"migrate:revert": "node src/migrate.js revert",
|
|
25
|
+
"migrate:status": "node src/migrate.js status"
|
|
26
|
+
},
|
|
27
|
+
"optionalDependencies": {
|
|
28
|
+
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
|
29
|
+
},
|
|
30
|
+
"resolutions": {
|
|
31
|
+
"on-headers": "1.1.0",
|
|
32
|
+
"brace-expansion": "2.0.2",
|
|
33
|
+
"prismjs": "1.30.0",
|
|
34
|
+
"xml2js": ">=0.5.0",
|
|
35
|
+
"tar-fs": ">=3.1.1",
|
|
36
|
+
"vite": ">=7.0.8",
|
|
37
|
+
"node-forge": ">=1.3.2",
|
|
38
|
+
"js-yaml": ">=4.1.1"
|
|
39
|
+
},
|
|
40
|
+
"overrides": {
|
|
41
|
+
"react-syntax-highlighter": {
|
|
42
|
+
"prismjs": "1.30.0"
|
|
43
|
+
},
|
|
44
|
+
"react-code-blocks": {
|
|
45
|
+
"prismjs": "1.30.0"
|
|
46
|
+
},
|
|
47
|
+
"refractor": {
|
|
48
|
+
"prismjs": "1.30.0"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/anonympins/data-primals-engine.git"
|
|
54
|
+
},
|
|
55
|
+
"exports": {
|
|
56
|
+
".": "./src/index.js",
|
|
57
|
+
"./client-only": "./src/client.js",
|
|
58
|
+
"./modules/*.js": "./src/modules/*.js",
|
|
59
|
+
"./modules/*": "./src/modules/*/index.js",
|
|
60
|
+
"./client": "./client/index.js",
|
|
61
|
+
"./*": "./src/*.js"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@langchain/core": "^0.3.79",
|
|
65
|
+
"archiver": "^7.0.1",
|
|
66
|
+
"aws-sdk": "^2.1692.0",
|
|
67
|
+
"bcrypt": "^6.0.0",
|
|
68
|
+
"body-parser": "^2.2.1",
|
|
69
|
+
"chalk": "^5.4.1",
|
|
70
|
+
"check-disk-space": "^3.4.0",
|
|
71
|
+
"compression": "^1.8.1",
|
|
72
|
+
"cookie-parser": "^1.4.7",
|
|
73
|
+
"cronstrue": "^3.2.0",
|
|
74
|
+
"csv-parse": "^6.1.0",
|
|
75
|
+
"date-fns": "^4.1.0",
|
|
76
|
+
"express-csrf-double-submit-cookie": "^2.0.0",
|
|
77
|
+
"express-formidable": "^1.2.0",
|
|
78
|
+
"express-mongo-sanitize": "^2.2.0",
|
|
79
|
+
"express-rate-limit": "^8.0.1",
|
|
80
|
+
"express-session": "^1.18.2",
|
|
81
|
+
"handlebars": "^4.7.8",
|
|
82
|
+
"i18next-browser-languagedetector": "^8.2.0",
|
|
83
|
+
"isolated-vm": "^5.0.4",
|
|
84
|
+
"juice": "^11.0.3",
|
|
85
|
+
"mathjs": "^15.1.0",
|
|
86
|
+
"mongodb": "^6.18.0",
|
|
87
|
+
"node-cache": "^5.1.2",
|
|
88
|
+
"node-schedule": "^2.1.1",
|
|
89
|
+
"nodemailer": "^7.0.10",
|
|
90
|
+
"openai": "^6.9.1",
|
|
91
|
+
"passport": "^0.7.0",
|
|
92
|
+
"passport-saml-encrypted": "^0.1.13",
|
|
93
|
+
"process": "^0.11.10",
|
|
94
|
+
"prop-types": "^15.8.1",
|
|
95
|
+
"randomcolor": "^0.6.2",
|
|
96
|
+
"react-markdown": "^10.1.0",
|
|
97
|
+
"read-excel-file": "^6.0.1",
|
|
98
|
+
"request-ip": "^3.3.0",
|
|
99
|
+
"safe-regex": "^2.1.1",
|
|
100
|
+
"sanitize-html": "^2.17.0",
|
|
101
|
+
"sirv": "^3.0.2",
|
|
102
|
+
"stripe": "^20.0.0",
|
|
103
|
+
"swagger-ui-express": "^5.0.1",
|
|
104
|
+
"tar": "^7.5.2",
|
|
105
|
+
"tinycolor2": "^1.6.0",
|
|
106
|
+
"uniqid": "^5.4.0",
|
|
107
|
+
"vitest": "^3.2.4",
|
|
108
|
+
"yaml": "^2.8.1"
|
|
109
|
+
},
|
|
110
|
+
"peerDependencies": {
|
|
111
|
+
"express": "^5.1.0",
|
|
112
|
+
"passport-azure-ad": "^4.3.5",
|
|
113
|
+
"passport-google-oauth20": "^2.0.0",
|
|
114
|
+
"react": "18.3.1",
|
|
115
|
+
"react-i18next": "^16.3.4",
|
|
116
|
+
"react-query": "^3.39.3",
|
|
117
|
+
"@langchain/anthropic": "^0.3.33",
|
|
118
|
+
"@langchain/deepseek": "^0.1.0",
|
|
119
|
+
"@langchain/google-genai": "^0.2.18",
|
|
120
|
+
"@langchain/openai": "^0.6.16"
|
|
121
|
+
},
|
|
122
|
+
"devDependencies": {
|
|
123
|
+
"@eslint/js": "^9.32.0",
|
|
124
|
+
"concurrently": "^9.2.0",
|
|
125
|
+
"cross-env": "^10.0.0",
|
|
126
|
+
"eslint": "^9.32.0",
|
|
127
|
+
"globals": "^16.3.0"
|
|
128
|
+
},
|
|
129
|
+
"subPackages": [
|
|
130
|
+
"client"
|
|
131
|
+
],
|
|
132
|
+
"keywords": [
|
|
133
|
+
"data-driven engine",
|
|
134
|
+
"headless CMS",
|
|
135
|
+
"backend",
|
|
136
|
+
"automation",
|
|
137
|
+
"AWS S3",
|
|
138
|
+
"MongoDB"
|
|
139
|
+
],
|
|
140
|
+
"author": "anonympins",
|
|
141
|
+
"license": "MIT",
|
|
142
|
+
"engines": {
|
|
143
|
+
"node": ">=20.0.0"
|
|
144
|
+
}
|
|
145
|
+
}
|
package/src/client.js
ADDED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getCollectionForUser, modelsCollection } from "../mongodb.js";
|
|
2
2
|
import { Logger } from "../../gameObject.js";
|
|
3
3
|
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
4
|
-
import {searchData,
|
|
4
|
+
import { searchData, patchData, deleteData, insertData } from "../data/index.js";
|
|
5
|
+
import { getAIProvider } from "./providers.js";
|
|
5
6
|
import {providers} from "./constants.js";
|
|
6
7
|
import {Config} from "../../config.js";
|
|
7
8
|
import { Event } from "../../events.js";
|
|
@@ -13,38 +14,6 @@ import {parseSafeJSON} from "../../core.js";
|
|
|
13
14
|
|
|
14
15
|
let logger = null;
|
|
15
16
|
|
|
16
|
-
export const getAIProvider= async (aiProvider, aiModel, apiKey)=>{
|
|
17
|
-
const maxTokens = Config.Get('assistant.maxTokens', assistantConfig.maxTokens);
|
|
18
|
-
try {
|
|
19
|
-
switch (aiProvider) {
|
|
20
|
-
case 'OpenAI': {
|
|
21
|
-
const { ChatOpenAI } = await import("@langchain/openai");
|
|
22
|
-
return new ChatOpenAI({apiKey, model: aiModel, temperature: 0.7, maxTokens});
|
|
23
|
-
}
|
|
24
|
-
case 'Google': {
|
|
25
|
-
const { ChatGoogleGenerativeAI } = await import("@langchain/google-genai");
|
|
26
|
-
return new ChatGoogleGenerativeAI({apiKey, model: aiModel, temperature: 0.7, maxTokens});
|
|
27
|
-
}
|
|
28
|
-
case 'DeepSeek': {
|
|
29
|
-
const { ChatDeepSeek } = await import("@langchain/deepseek");
|
|
30
|
-
return new ChatDeepSeek({apiKey, model: aiModel, temperature: 0.7, maxTokens});
|
|
31
|
-
}
|
|
32
|
-
case 'Anthropic': {
|
|
33
|
-
const { ChatAnthropic } = await import("@langchain/anthropic");
|
|
34
|
-
return new ChatAnthropic({apiKey, model: aiModel, temperature: 0.7, maxTokens});
|
|
35
|
-
}
|
|
36
|
-
default:
|
|
37
|
-
throw new Error(`Unsupported AI provider: ${aiProvider}`);
|
|
38
|
-
}
|
|
39
|
-
} catch (e) {
|
|
40
|
-
if (e.code === 'ERR_MODULE_NOT_FOUND') {
|
|
41
|
-
logger.error(`[Assistant] The package for the '${aiProvider}' provider is not installed. Please run 'npm install @langchain/${aiProvider.toLowerCase()}' to use this provider.`);
|
|
42
|
-
throw new Error(`The AI provider '${aiProvider}' is not installed. Please ask the administrator to install the corresponding package.`);
|
|
43
|
-
}
|
|
44
|
-
logger.error(`[Assistant] Error initializing AI provider '${aiProvider}': ${e.message}`);
|
|
45
|
-
throw e; // Re-throw other errors
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
17
|
export const assistantGlobalLimiter = rateLimit({
|
|
49
18
|
windowMs: 15 * 60 * 1000, // Fenêtre de 15 minutes
|
|
50
19
|
max: 100, // Limite à 100 requêtes globales pour l'assistant pendant la fenêtre (vous pouvez ajuster cette valeur)
|
|
@@ -101,7 +70,7 @@ const createSystemPrompt = (modelDefs, lang) => {
|
|
|
101
70
|
|
|
102
71
|
const date = new Date();
|
|
103
72
|
const dt = date.toISOString();
|
|
104
|
-
return `
|
|
73
|
+
return Config.Get('systemPrompt', `
|
|
105
74
|
Tu es "Prior", un assistant expert en analyse de données pour le moteur data-primals-engine..
|
|
106
75
|
Ta mission est d'aider l'utilisateur en répondant à ses questions sur ses données.
|
|
107
76
|
|
|
@@ -333,7 +302,7 @@ Ma question: Bonjour, je voudrais les requêtes effectuées aujourd'hui sur le m
|
|
|
333
302
|
Ta réponse: [
|
|
334
303
|
{ "action" : "search_models", "params": { "query": "request" } },
|
|
335
304
|
{ "action" : "search", "params" : { "model": "request", "filter": { "$and": [{"$gte": ["$createdAt", "${dt}"]}, {"$regexMatch": { "input": "$url", "regex": "content"}}] }, "limit" : 10, "sort" : "_id:DESC" } }
|
|
336
|
-
]
|
|
305
|
+
]`);
|
|
337
306
|
}
|
|
338
307
|
|
|
339
308
|
/**
|
|
@@ -475,7 +444,7 @@ export async function handleChatRequest(params, user, sendEvent = null) {
|
|
|
475
444
|
return errorResult;
|
|
476
445
|
}
|
|
477
446
|
|
|
478
|
-
const systemPrompt = await Event.Trigger('OnSystemPrompt', 'event', 'user', user);
|
|
447
|
+
const systemPrompt = (await Event.Trigger('OnSystemPrompt', 'event', 'user', user)) || createSystemPrompt([], user.lang || 'en');
|
|
479
448
|
|
|
480
449
|
const conversationHistory = (history || [])
|
|
481
450
|
.filter(msg => msg.text && !(msg.from === 'bot' && msg.text.startsWith(i18n.t('assistant.welcome'))))
|
|
@@ -559,11 +528,12 @@ export async function handleChatRequest(params, user, sendEvent = null) {
|
|
|
559
528
|
return result;
|
|
560
529
|
}
|
|
561
530
|
|
|
562
|
-
|
|
531
|
+
const toolResults = [];
|
|
532
|
+
let finalActionResult = null;
|
|
533
|
+
|
|
563
534
|
for (const command of commands) {
|
|
564
535
|
logger.debug(`[Assistant] Action décidée par l'IA: ${command.action}`, command);
|
|
565
536
|
if (sendEvent) sendEvent('action', { action: command.action, params: command.params });
|
|
566
|
-
conversationHistory.push(new SystemMessage(JSON.stringify(command)));
|
|
567
537
|
|
|
568
538
|
const { action, params: parsedParams } = command;
|
|
569
539
|
|
|
@@ -576,40 +546,52 @@ export async function handleChatRequest(params, user, sendEvent = null) {
|
|
|
576
546
|
// Outils pour le raisonnement interne de l'IA
|
|
577
547
|
if (['search_models'].includes(action)) {
|
|
578
548
|
const toolResult = await executeTool(action, parsedParams, user, allModels);
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
hasContinued = true; // On indique qu'on doit continuer la boucle principale
|
|
582
|
-
continue; // On passe à la commande suivante dans la liste de l'IA
|
|
549
|
+
toolResults.push({ action, result: toolResult });
|
|
550
|
+
continue; // Passe à la commande suivante sans vérifier si c'est une action finale
|
|
583
551
|
}
|
|
584
552
|
|
|
585
553
|
// Actions finales
|
|
586
|
-
const res = await Event.Trigger('OnChatAction', 'event', 'user', action,
|
|
554
|
+
const res = await Event.Trigger('OnChatAction', 'event', 'user', action, parsedParams, command, llmOptions, user, params);
|
|
587
555
|
|
|
588
|
-
if (
|
|
556
|
+
if (res) {
|
|
557
|
+
// On a trouvé une action finale. On la stocke et on arrête de chercher.
|
|
558
|
+
finalActionResult = res;
|
|
559
|
+
break; // Sort de la boucle des commandes
|
|
560
|
+
} else {
|
|
589
561
|
// Si l'action n'est reconnue par aucune des logiques ci-dessus
|
|
590
562
|
logger.warn(`[Assistant] Action non reconnue reçue de l'IA: ${action}`);
|
|
591
|
-
|
|
563
|
+
finalActionResult = {
|
|
592
564
|
success: true,
|
|
593
565
|
displayMessage: i18n.t('assistant.unknownAction', "Désolé, je ne comprends pas la commande '{{action}}'.", { action })
|
|
594
566
|
};
|
|
595
|
-
|
|
596
|
-
sendEvent('final_result', result);
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
return result;
|
|
567
|
+
break; // Sortir de la boucle des commandes
|
|
600
568
|
}
|
|
601
|
-
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Si une action finale a été exécutée, on retourne son résultat.
|
|
572
|
+
if (finalActionResult) {
|
|
602
573
|
if (sendEvent) {
|
|
603
|
-
sendEvent('final_result',
|
|
574
|
+
sendEvent('final_result', finalActionResult);
|
|
604
575
|
return;
|
|
605
576
|
}
|
|
606
|
-
return
|
|
577
|
+
return finalActionResult;
|
|
607
578
|
}
|
|
608
579
|
|
|
609
|
-
// Si on a
|
|
610
|
-
if (
|
|
580
|
+
// Si on a uniquement des résultats d'outils, on les ajoute à l'historique et on continue la boucle.
|
|
581
|
+
if (toolResults.length > 0) {
|
|
582
|
+
let toolResponse = "";
|
|
583
|
+
for (const tool of toolResults) {
|
|
584
|
+
if (sendEvent) sendEvent('tool_result', { action: tool.action, result: tool.result });
|
|
585
|
+
toolResponse += `Résultat de l'outil '${tool.action}':\n${tool.result}\n\n`;
|
|
586
|
+
}
|
|
587
|
+
conversationHistory.push(new SystemMessage(toolResponse));
|
|
611
588
|
continue;
|
|
612
589
|
}
|
|
590
|
+
|
|
591
|
+
// Si l'IA ne retourne ni outil ni action finale reconnue, on arrête.
|
|
592
|
+
if (commands.length > 0) {
|
|
593
|
+
logger.warn(`[Assistant] L'IA a retourné des commandes mais aucune n'était un outil ou une action finale reconnue. Commandes:`, commands);
|
|
594
|
+
}
|
|
613
595
|
}
|
|
614
596
|
|
|
615
597
|
// Si la boucle se termine sans une action finale
|
|
@@ -656,7 +638,7 @@ async function executeConfirmedAction(action, params, user) {
|
|
|
656
638
|
* @param {object} user - L'objet utilisateur.
|
|
657
639
|
* @returns {Promise<object|boolean>} - L'objet de réponse final ou false si l'action n'est pas reconnue.
|
|
658
640
|
*/
|
|
659
|
-
async function handleFinalChatAction(action, params, parsedResponse, user) {
|
|
641
|
+
async function handleFinalChatAction(action, params, parsedResponse, llmOptions, user) {
|
|
660
642
|
// Action de génération de graphique, gérée par le front-end
|
|
661
643
|
if (action === 'generateChart') {
|
|
662
644
|
return {success: true, chartConfig: params};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Config } from "../../config.js";
|
|
2
|
+
import { assistantConfig } from "../../constants.js";
|
|
3
|
+
import { Logger } from "../../gameObject.js";
|
|
4
|
+
|
|
5
|
+
const logger = new Logger("AssistantProviders");
|
|
6
|
+
|
|
7
|
+
export const getAIProvider = async (aiProvider, aiModel, apiKey) => {
|
|
8
|
+
const maxTokens = Config.Get('assistant.maxTokens', assistantConfig.maxTokens);
|
|
9
|
+
try {
|
|
10
|
+
switch (aiProvider) {
|
|
11
|
+
case 'OpenAI': {
|
|
12
|
+
const { ChatOpenAI } = await import("@langchain/openai");
|
|
13
|
+
return new ChatOpenAI({ apiKey, model: aiModel, temperature: 0.7, maxTokens });
|
|
14
|
+
}
|
|
15
|
+
case 'Google': {
|
|
16
|
+
const { ChatGoogleGenerativeAI } = await import("@langchain/google-genai");
|
|
17
|
+
return new ChatGoogleGenerativeAI({ apiKey, model: aiModel, temperature: 0.7, maxTokens });
|
|
18
|
+
}
|
|
19
|
+
case 'DeepSeek': {
|
|
20
|
+
const { ChatDeepSeek } = await import("@langchain/deepseek");
|
|
21
|
+
return new ChatDeepSeek({ apiKey, model: aiModel, temperature: 0.7, maxTokens });
|
|
22
|
+
}
|
|
23
|
+
case 'Anthropic': {
|
|
24
|
+
const { ChatAnthropic } = await import("@langchain/anthropic");
|
|
25
|
+
return new ChatAnthropic({ apiKey, model: aiModel, temperature: 0.7, maxTokens });
|
|
26
|
+
}
|
|
27
|
+
default:
|
|
28
|
+
throw new Error(`Unsupported AI provider: ${aiProvider}`);
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
if (e.code === 'ERR_MODULE_NOT_FOUND') {
|
|
32
|
+
logger.error(`[Assistant] The package for the '${aiProvider}' provider is not installed. Please run 'npm install @langchain/${aiProvider.toLowerCase()}' to use this provider.`);
|
|
33
|
+
throw new Error(`The AI provider '${aiProvider}' is not installed. Please ask the administrator to install the corresponding package.`);
|
|
34
|
+
}
|
|
35
|
+
logger.error(`[Assistant] Error initializing AI provider '${aiProvider}': ${e.message}`);
|
|
36
|
+
throw e; // Re-throw other errors
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -323,17 +323,14 @@ export function onInit(defaultEngine) {
|
|
|
323
323
|
engine.post('/api/data/history/:modelName/:recordId/revert/:version', [middlewareAuthenticator, userInitiator], handleRevertToRevisionRequest);
|
|
324
324
|
|
|
325
325
|
// --- Écouteur pour la CRÉATION de données (Version 1 - Snapshot) ---
|
|
326
|
-
Event.Listen("OnDataAdded", async (engine, { modelName,
|
|
326
|
+
Event.Listen("OnDataAdded", async (engine, { modelName, insertedDocs, user }) => {
|
|
327
327
|
try {
|
|
328
328
|
const model = await getModel(modelName, user);
|
|
329
329
|
if (!model?.history?.enabled) return;
|
|
330
330
|
|
|
331
|
-
const dataCollection = await getCollectionForUser(user);
|
|
332
331
|
const historyCollection = getCollection('history');
|
|
333
332
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
for (const doc of newDocs) {
|
|
333
|
+
for (const doc of insertedDocs) {
|
|
337
334
|
await historyCollection.insertOne({
|
|
338
335
|
documentId: doc._id,
|
|
339
336
|
model: modelName,
|
|
@@ -817,7 +817,7 @@ export const insertData = async (modelName, data, files, user, triggerWorkflow =
|
|
|
817
817
|
}
|
|
818
818
|
|
|
819
819
|
// System specific event
|
|
820
|
-
const eventPayload = {modelName,
|
|
820
|
+
const eventPayload = {modelName, insertedDocs, user};
|
|
821
821
|
await Event.Trigger("OnDataAdded", "event", "system", engine, eventPayload);
|
|
822
822
|
|
|
823
823
|
// User specific event
|
|
@@ -829,7 +829,10 @@ export const insertData = async (modelName, data, files, user, triggerWorkflow =
|
|
|
829
829
|
// --- CORRECTION ---
|
|
830
830
|
// On renvoie l'objet complet du premier document inséré (cas le plus courant pour l'undo)
|
|
831
831
|
// et la liste complète des IDs pour les cas de bulk insert.
|
|
832
|
-
|
|
832
|
+
let firstInsertedDoc = insertedDocs.length > 0 ? { ...insertedDocs[0] } : null;
|
|
833
|
+
if (firstInsertedDoc?._id) {
|
|
834
|
+
firstInsertedDoc._id = firstInsertedDoc._id.toString();
|
|
835
|
+
}
|
|
833
836
|
return {success: true, data: firstInsertedDoc, insertedIds: insertedIds.map(id => id.toString())};
|
|
834
837
|
|
|
835
838
|
} catch (error) { // Attrape les erreurs de permission ou de pushDataUnsecure
|
|
@@ -1419,6 +1422,12 @@ const internalEditOrPatchData = async (modelName, filter, data, files, user, isP
|
|
|
1419
1422
|
before: existingDocs, // Documents avant la modification
|
|
1420
1423
|
after: updatedDocs // Documents après la modification
|
|
1421
1424
|
});
|
|
1425
|
+
await Event.Trigger("OnDataEdited", "event", "user", engine, {
|
|
1426
|
+
modelName,
|
|
1427
|
+
user,
|
|
1428
|
+
before: existingDocs, // Documents avant la modification
|
|
1429
|
+
after: updatedDocs // Documents après la modification
|
|
1430
|
+
});
|
|
1422
1431
|
}
|
|
1423
1432
|
|
|
1424
1433
|
// 11. Tâches post-mise à jour (schedules, workflows) (inchangé)
|
package/src/modules/workflow.js
CHANGED
|
@@ -17,8 +17,8 @@ import {isConditionMet} from "../filter.js";
|
|
|
17
17
|
import { services } from '../services/index.js';
|
|
18
18
|
import {getEnv, getSmtpConfig} from "./user.js";
|
|
19
19
|
import {getHost} from "../constants.js";
|
|
20
|
-
import {providers} from "./assistant/constants.js";
|
|
21
|
-
import {getAIProvider} from "./assistant/
|
|
20
|
+
import { providers } from "./assistant/constants.js";
|
|
21
|
+
import { getAIProvider } from "./assistant/providers.js";
|
|
22
22
|
import {parseSafeJSON, safeAssignObject} from "../core.js";
|
|
23
23
|
import {Config} from "../config.js";
|
|
24
24
|
|