agentic-api 2.0.31 → 2.0.491
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/src/agents/agents.example.js +21 -22
- package/dist/src/agents/authentication.js +1 -2
- package/dist/src/agents/prompts.d.ts +5 -4
- package/dist/src/agents/prompts.js +44 -87
- package/dist/src/agents/reducer.core.d.ts +24 -2
- package/dist/src/agents/reducer.core.js +125 -35
- package/dist/src/agents/reducer.loaders.d.ts +55 -1
- package/dist/src/agents/reducer.loaders.js +114 -1
- package/dist/src/agents/reducer.types.d.ts +45 -2
- package/dist/src/agents/semantic.js +1 -2
- package/dist/src/agents/simulator.d.ts +11 -3
- package/dist/src/agents/simulator.executor.d.ts +14 -4
- package/dist/src/agents/simulator.executor.js +81 -23
- package/dist/src/agents/simulator.js +128 -42
- package/dist/src/agents/simulator.prompts.d.ts +9 -7
- package/dist/src/agents/simulator.prompts.js +66 -86
- package/dist/src/agents/simulator.types.d.ts +23 -5
- package/dist/src/agents/simulator.utils.d.ts +7 -2
- package/dist/src/agents/simulator.utils.js +31 -11
- package/dist/src/agents/system.js +1 -2
- package/dist/src/execute/helpers.d.ts +75 -0
- package/dist/src/execute/helpers.js +139 -0
- package/dist/src/execute/index.d.ts +11 -0
- package/dist/src/execute/index.js +44 -0
- package/dist/src/execute/legacy.d.ts +46 -0
- package/dist/src/execute/legacy.js +460 -0
- package/dist/src/execute/modelconfig.d.ts +19 -0
- package/dist/src/execute/modelconfig.js +56 -0
- package/dist/src/execute/responses.d.ts +55 -0
- package/dist/src/execute/responses.js +594 -0
- package/dist/src/execute/shared.d.ts +83 -0
- package/dist/src/execute/shared.js +188 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
- package/dist/src/pricing.llm.js +255 -0
- package/dist/src/prompts.d.ts +13 -4
- package/dist/src/prompts.js +221 -114
- package/dist/src/rag/embeddings.d.ts +36 -18
- package/dist/src/rag/embeddings.js +131 -128
- package/dist/src/rag/index.d.ts +5 -5
- package/dist/src/rag/index.js +14 -17
- package/dist/src/rag/parser.d.ts +2 -1
- package/dist/src/rag/parser.js +11 -14
- package/dist/src/rag/rag.examples.d.ts +27 -0
- package/dist/src/rag/rag.examples.js +151 -0
- package/dist/src/rag/rag.manager.d.ts +383 -0
- package/dist/src/rag/rag.manager.js +1390 -0
- package/dist/src/rag/types.d.ts +128 -12
- package/dist/src/rag/types.js +100 -1
- package/dist/src/rag/usecase.d.ts +37 -0
- package/dist/src/rag/usecase.js +96 -7
- package/dist/src/rules/git/git.e2e.helper.js +22 -2
- package/dist/src/rules/git/git.health.d.ts +61 -2
- package/dist/src/rules/git/git.health.js +333 -11
- package/dist/src/rules/git/index.d.ts +2 -2
- package/dist/src/rules/git/index.js +13 -1
- package/dist/src/rules/git/repo.d.ts +160 -0
- package/dist/src/rules/git/repo.js +777 -0
- package/dist/src/rules/git/repo.pr.js +117 -13
- package/dist/src/rules/git/repo.tools.d.ts +22 -1
- package/dist/src/rules/git/repo.tools.js +50 -1
- package/dist/src/rules/types.d.ts +27 -14
- package/dist/src/rules/utils.matter.d.ts +0 -4
- package/dist/src/rules/utils.matter.js +35 -7
- package/dist/src/scrapper.d.ts +15 -22
- package/dist/src/scrapper.js +58 -110
- package/dist/src/stategraph/index.d.ts +1 -1
- package/dist/src/stategraph/stategraph.d.ts +56 -2
- package/dist/src/stategraph/stategraph.js +134 -6
- package/dist/src/stategraph/stategraph.storage.js +8 -0
- package/dist/src/stategraph/types.d.ts +27 -0
- package/dist/src/types.d.ts +46 -9
- package/dist/src/types.js +8 -7
- package/dist/src/usecase.d.ts +11 -2
- package/dist/src/usecase.js +27 -35
- package/dist/src/utils.d.ts +32 -18
- package/dist/src/utils.js +87 -129
- package/package.json +10 -3
- package/dist/src/agents/digestor.test.d.ts +0 -1
- package/dist/src/agents/digestor.test.js +0 -45
- package/dist/src/agents/reducer.example.d.ts +0 -28
- package/dist/src/agents/reducer.example.js +0 -118
- package/dist/src/agents/reducer.process.d.ts +0 -16
- package/dist/src/agents/reducer.process.js +0 -143
- package/dist/src/agents/reducer.tools.d.ts +0 -29
- package/dist/src/agents/reducer.tools.js +0 -157
- package/dist/src/agents/simpleExample.d.ts +0 -3
- package/dist/src/agents/simpleExample.js +0 -38
- package/dist/src/agents/system-review.d.ts +0 -5
- package/dist/src/agents/system-review.js +0 -181
- package/dist/src/agents/systemReview.d.ts +0 -4
- package/dist/src/agents/systemReview.js +0 -22
- package/dist/src/execute.d.ts +0 -49
- package/dist/src/execute.js +0 -564
- package/dist/src/princing.openai.js +0 -54
- package/dist/src/rag/tools.d.ts +0 -76
- package/dist/src/rag/tools.js +0 -196
- package/dist/src/rules/user.mapper.d.ts +0 -61
- package/dist/src/rules/user.mapper.js +0 -160
- package/dist/src/rules/utils/slug.d.ts +0 -22
- package/dist/src/rules/utils/slug.js +0 -35
package/dist/src/scrapper.js
CHANGED
|
@@ -4,8 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.extractCaptcha = extractCaptcha;
|
|
7
|
-
exports.
|
|
8
|
-
exports.callGPTForParsingHTML = callGPTForParsingHTML;
|
|
7
|
+
exports.callLLMForParsingPDF = callLLMForParsingPDF;
|
|
9
8
|
exports.html2markdown = html2markdown;
|
|
10
9
|
exports.pdf2markdown = pdf2markdown;
|
|
11
10
|
const child_process_1 = require("child_process");
|
|
@@ -14,9 +13,11 @@ const path_1 = __importDefault(require("path"));
|
|
|
14
13
|
const fs_1 = __importDefault(require("fs"));
|
|
15
14
|
const jsdom_1 = require("jsdom");
|
|
16
15
|
const readability_1 = require("@mozilla/readability");
|
|
17
|
-
const
|
|
16
|
+
const pricing_llm_1 = require("./pricing.llm");
|
|
18
17
|
const prompts_1 = require("./prompts");
|
|
19
18
|
const utils_1 = require("./utils");
|
|
19
|
+
const execute_1 = require("./execute");
|
|
20
|
+
const utils_matter_1 = require("./rules/utils.matter");
|
|
20
21
|
// Promisify exec for easier async/await usage
|
|
21
22
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
22
23
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
@@ -36,7 +37,7 @@ async function extractCaptcha(base64Image, openai) {
|
|
|
36
37
|
messages: [{ role: "user", content }],
|
|
37
38
|
max_completion_tokens: 50,
|
|
38
39
|
});
|
|
39
|
-
const cost = (0,
|
|
40
|
+
const cost = (0, pricing_llm_1.calculateCost)(model, response.usage);
|
|
40
41
|
// Récupérer la réponse markdown
|
|
41
42
|
const number = response.choices[0].message.content;
|
|
42
43
|
return { number, cost };
|
|
@@ -46,11 +47,11 @@ async function extractCaptcha(base64Image, openai) {
|
|
|
46
47
|
*
|
|
47
48
|
* @param {string} inputfile - The name of the PDF file being processed
|
|
48
49
|
* @param {any} pdfData - The extracted content from the PDF file
|
|
49
|
-
* @param {any} openai - The OpenAI client instance
|
|
50
50
|
* @param {any[]} links - Optional array of links extracted from the PDF to be integrated into the markdown
|
|
51
|
+
* @param {string} model - The model to use for parsing (default: "MEDIUM-fast")
|
|
51
52
|
* @returns {Promise<{markdown: string, cost: number}>} - The parsed markdown content and the cost of the API call
|
|
52
53
|
*/
|
|
53
|
-
async function
|
|
54
|
+
async function callLLMForParsingPDF(inputfile, pdfData, links = [], model = "MEDIUM-fast") {
|
|
54
55
|
// Convertir le contenu en chaîne de caractères (attention à la taille potentielle !)
|
|
55
56
|
const pdfDataAsString = JSON.stringify(pdfData, null, 2);
|
|
56
57
|
// Format: YYYY-MM-DD
|
|
@@ -62,57 +63,25 @@ async function callGPTForParsingPDF(inputfile, pdfData, openai, links = []) {
|
|
|
62
63
|
// Créer le prompt pour décrire la tâche au LLM
|
|
63
64
|
const messages = [
|
|
64
65
|
{ role: "system",
|
|
65
|
-
content: prompts_1.htmlToMarkdownPrompt }
|
|
66
|
-
{ role: "user",
|
|
67
|
-
content: `Structure le contenu exhaustif en Markdown sans rien inventer, et avec les liens intégrés correctement.\n Nous sommes le ${today}.\n${linkPrefix}\nLe contenu du document est:\n${pdfDataAsString}`
|
|
68
|
-
}
|
|
66
|
+
content: prompts_1.htmlToMarkdownPrompt }
|
|
69
67
|
];
|
|
70
|
-
// console.log('🌶️ DEBUG:
|
|
71
|
-
// console.log('🌶️ DEBUG:
|
|
68
|
+
// console.log('🌶️ DEBUG: callLLMForParsingPDF -- SYSTEM:', messages[0].content);
|
|
69
|
+
// console.log('🌶️ DEBUG: callLLMForParsingPDF -- USER:', messages[1].content);
|
|
72
70
|
// WARNING: o3-mini is buggy with "Marche à suivre nouveau bail.pdf"
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
model
|
|
71
|
+
const response = await (0, execute_1.executeQuery)({
|
|
72
|
+
query: `Structure le contenu exhaustif en Markdown sans rien inventer, et avec les liens intégrés correctement.\n Nous sommes le ${today}.\n${linkPrefix}\nLe contenu du document est:\n${pdfDataAsString}`,
|
|
73
|
+
model,
|
|
76
74
|
messages,
|
|
75
|
+
stdout: execute_1.DummyWritable,
|
|
76
|
+
verbose: false
|
|
77
77
|
});
|
|
78
|
-
// response_format: { type: "json_object" }
|
|
79
|
-
let cost = (0, princing_openai_1.calculateCost)(model, response.usage);
|
|
80
|
-
// messages.push({
|
|
81
|
-
// role: "user",
|
|
82
|
-
// content: `Maintenant génère le contenu Markdown détaillé et exhaustif correspondant à chaque section avec les liens intégrés correctement.`
|
|
83
|
-
// });
|
|
84
|
-
// response = await openai.chat.completions.create({
|
|
85
|
-
// model: model,
|
|
86
|
-
// messages,
|
|
87
|
-
// max_completion_tokens: 15192,
|
|
88
|
-
// reasoning_effort:"low",
|
|
89
|
-
// stop:"|<|james|>|"
|
|
90
|
-
// });
|
|
91
78
|
// Récupérer la réponse markdown
|
|
92
|
-
|
|
93
|
-
console.log(`Markdown 💰 cost: ${cost}`);
|
|
79
|
+
const markdown = response.content;
|
|
80
|
+
console.log(`Markdown 💰 cost: ${response.usage.cost}`);
|
|
94
81
|
//
|
|
95
82
|
// add a regex to extract the markdown content between <thinking></thinking> tags
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// messages.push({
|
|
99
|
-
// role: "user",
|
|
100
|
-
// content: hragPrompt
|
|
101
|
-
// });
|
|
102
|
-
// response = await openai.chat.completions.create({
|
|
103
|
-
// model: model,
|
|
104
|
-
// messages,
|
|
105
|
-
// max_completion_tokens: 15192,
|
|
106
|
-
// reasoning_effort:"low",
|
|
107
|
-
// stop:"|<|james|>|"
|
|
108
|
-
// });
|
|
109
|
-
// // Récupérer la réponse markdown
|
|
110
|
-
// markdown = response.choices[0].message.content;
|
|
111
|
-
// cost += calculateCost(model, response.usage);
|
|
112
|
-
// //
|
|
113
|
-
// // add a regex to extract the markdown content between <thinking></thinking> tags
|
|
114
|
-
// markdownWithoutThinking = markdown.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
|
|
115
|
-
return { markdown: markdownWithoutThinking, cost };
|
|
83
|
+
const markdownWithoutThinking = markdown.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
|
|
84
|
+
return { markdown: markdownWithoutThinking, cost: response.usage.cost };
|
|
116
85
|
}
|
|
117
86
|
/**
|
|
118
87
|
* Extracts hyperlinks from a PDF file by converting it to HTML and parsing the links.
|
|
@@ -156,47 +125,6 @@ async function extractLinksFromPDF(pdfPath, output) {
|
|
|
156
125
|
}
|
|
157
126
|
}
|
|
158
127
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Convertit un document HTML en markdown en appelant le modèle GPT (ex: gpt-4.1)
|
|
161
|
-
* pour analyser et reformater le document.
|
|
162
|
-
*
|
|
163
|
-
* @param {any} htmlData - Le document HTML à transformer en markdown.
|
|
164
|
-
* @param {any} openai - L'instance OpenAI configurée pour appeler l'API.
|
|
165
|
-
* @param {boolean} simple - Si true, utilise un prompt simplifié.
|
|
166
|
-
* @returns {Promise<Object>} - Le contenu markdown structuré créé par le modèle LLM.
|
|
167
|
-
*/
|
|
168
|
-
async function callGPTForParsingHTML(html, openai) {
|
|
169
|
-
const htmlDataAsString = html;
|
|
170
|
-
// Créer le prompt pour décrire la tâche au LLM
|
|
171
|
-
const messages = [
|
|
172
|
-
{
|
|
173
|
-
role: "system",
|
|
174
|
-
content: prompts_1.htmlToMarkdownPrompt
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
role: "user",
|
|
178
|
-
content: `Voici le document HTML à transformer en markdown : \n${htmlDataAsString}`
|
|
179
|
-
}
|
|
180
|
-
];
|
|
181
|
-
// Appel à l'API ChatCompletion
|
|
182
|
-
const response = await openai.chat.completions.create({
|
|
183
|
-
model: "gpt-4.1",
|
|
184
|
-
messages,
|
|
185
|
-
max_completion_tokens: 15192,
|
|
186
|
-
temperature: 0,
|
|
187
|
-
frequency_penalty: 0.0,
|
|
188
|
-
presence_penalty: 0.0,
|
|
189
|
-
});
|
|
190
|
-
const cost = (0, princing_openai_1.calculateCost)("gpt-4.1", response.usage);
|
|
191
|
-
console.log(`Markdown 💰 cost: ${cost}`);
|
|
192
|
-
// Récupérer la réponse markdown
|
|
193
|
-
const markdown = response.choices[0].message.content;
|
|
194
|
-
if (!markdown)
|
|
195
|
-
throw new Error("No markdown found");
|
|
196
|
-
// Extraction et suppression des balises <thinking></thinking>
|
|
197
|
-
const markdownWithoutThinking = markdown.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
|
|
198
|
-
return markdownWithoutThinking;
|
|
199
|
-
}
|
|
200
128
|
function cleanHTML(html) {
|
|
201
129
|
const dom = new jsdom_1.JSDOM(html);
|
|
202
130
|
// Instancie Readability avec le document
|
|
@@ -210,15 +138,15 @@ function cleanHTML(html) {
|
|
|
210
138
|
* @param {string} output - The directory path where the output markdown file will be saved.
|
|
211
139
|
* @param {string} file - The path to the HTML file to be parsed.
|
|
212
140
|
* @param {string} service - The service name used as part of the output filename output.
|
|
213
|
-
* @param {
|
|
141
|
+
* @param {string} model - The model to use for parsing (default: "MEDIUM-fast")
|
|
214
142
|
* @returns {Promise<{markdown: string, cost: number}>} - The generated markdown content and the cost of the GPT API call.
|
|
215
143
|
*/
|
|
216
|
-
async function html2markdown(output, file, service,
|
|
144
|
+
async function html2markdown(output, file, service, model = "MEDIUM-fast") {
|
|
217
145
|
const filename = (0, utils_1.toSlug)(path_1.default.basename(file, path_1.default.extname(file)));
|
|
218
146
|
const htmlraw = fs_1.default.readFileSync(file, "utf8");
|
|
219
147
|
const html = cleanHTML(htmlraw);
|
|
220
148
|
const outputfile = html.indexOf('Please sign in') > -1 ? 'unauthorized-' : (service.toLocaleLowerCase() + '-');
|
|
221
|
-
const { markdown, cost } = await
|
|
149
|
+
const { markdown, cost } = await callLLMForParsingPDF(file, html, [], model);
|
|
222
150
|
fs_1.default.writeFileSync(path_1.default.join(output, `${outputfile + filename}.md`), markdown, { encoding: 'utf8', flag: 'w' });
|
|
223
151
|
return { markdown, cost };
|
|
224
152
|
}
|
|
@@ -226,32 +154,52 @@ async function html2markdown(output, file, service, openai) {
|
|
|
226
154
|
* Parse un PDF en effectuant :
|
|
227
155
|
* 1. Le nettoyage du PDF avec Ghostscript.
|
|
228
156
|
* 2. Sa conversion en XML via pdftohtml.
|
|
229
|
-
* 3. (Optionnellement) Le passage du contenu converti au modèle
|
|
157
|
+
* 3. (Optionnellement) Le passage du contenu converti au modèle LLM pour analyser la structure.
|
|
230
158
|
*
|
|
231
|
-
* @param {string}
|
|
232
|
-
* @param {
|
|
233
|
-
* @
|
|
159
|
+
* @param {string} outputDir - Dossier de sortie pour le fichier markdown.
|
|
160
|
+
* @param {string} pdf - Chemin vers le fichier PDF à analyser.
|
|
161
|
+
* @param {FrontMatter|null} matter - Métadonnées du document (title, service, author, role). Si null, utilise le nom du PDF pour le titre.
|
|
162
|
+
* @param {string} model - Le modèle à utiliser (défaut: "MEDIUM-fast").
|
|
163
|
+
* @returns {Promise<{markdown: string, cost: number, outputPath: string}>} - Le markdown structuré, le coût et le chemin du fichier de sortie.
|
|
234
164
|
*/
|
|
235
|
-
async function pdf2markdown(
|
|
236
|
-
|
|
165
|
+
async function pdf2markdown(outputDir, pdf, matter, model = "MEDIUM-fast") {
|
|
166
|
+
//
|
|
167
|
+
// Extract matter values with defaults
|
|
168
|
+
const service = matter?.service || 'unknown';
|
|
169
|
+
const title = matter?.title || path_1.default.basename(pdf, path_1.default.extname(pdf));
|
|
170
|
+
//
|
|
171
|
+
// Build complete FrontMatter with defaults
|
|
172
|
+
const frontMatter = {
|
|
173
|
+
title,
|
|
174
|
+
service,
|
|
175
|
+
author: matter?.author || '',
|
|
176
|
+
role: matter?.role || 'rule',
|
|
177
|
+
};
|
|
178
|
+
//
|
|
179
|
+
// Use title for filename
|
|
180
|
+
const filename = (0, utils_1.toSlug)(title);
|
|
237
181
|
// Créez des noms de fichiers temporaires pour le PDF nettoyé et le XML généré.
|
|
238
|
-
const tempPdf = path_1.default.join(
|
|
239
|
-
const tempOut = path_1.default.join(
|
|
182
|
+
const tempPdf = path_1.default.join(outputDir, `cleaned-${randomFile()}.pdf`);
|
|
183
|
+
const tempOut = path_1.default.join(outputDir, `${filename}.txt`);
|
|
240
184
|
//
|
|
241
185
|
// generated folder path
|
|
242
|
-
const outputPath = path_1.default.join(
|
|
186
|
+
const outputPath = path_1.default.join(outputDir, `${(0, utils_1.toSlug)(service.toLocaleLowerCase())}-${filename}.md`);
|
|
243
187
|
try {
|
|
244
188
|
//
|
|
245
189
|
// replace pdftotext with python script PyMuPDF
|
|
246
190
|
// Ca ne marche pas mieux que pdftotext
|
|
247
|
-
// const { stdout } = await execFileAsync("python3", ["./bin/extract_text_with_links.py",
|
|
191
|
+
// const { stdout } = await execFileAsync("python3", ["./bin/extract_text_with_links.py", pdf]);
|
|
248
192
|
// const { text, links } = JSON.parse(stdout);
|
|
249
|
-
|
|
250
|
-
|
|
193
|
+
// `pdftotext -f 1 -l 2 -layout -eol unix -nodiag "${pdf}" "${outputPath}"`;
|
|
194
|
+
await execAsync(`pdftotext -nodiag -nopgbrk "${pdf}" "${outputPath}"`);
|
|
195
|
+
const links = await extractLinksFromPDF(pdf, outputDir);
|
|
251
196
|
const text = fs_1.default.readFileSync(outputPath, "utf8");
|
|
252
|
-
const { markdown, cost } = await
|
|
253
|
-
|
|
254
|
-
|
|
197
|
+
const { markdown, cost } = await callLLMForParsingPDF(pdf, text, links, model);
|
|
198
|
+
//
|
|
199
|
+
// Add frontmatter to the markdown before saving
|
|
200
|
+
const markdownWithMatter = (0, utils_matter_1.matterSerialize)(markdown, frontMatter);
|
|
201
|
+
fs_1.default.writeFileSync(outputPath, markdownWithMatter);
|
|
202
|
+
return { markdown: markdownWithMatter, cost, outputPath };
|
|
255
203
|
/**
|
|
256
204
|
|
|
257
205
|
// STEP 1: Clean the PDF using Ghostscript.
|
|
@@ -271,7 +219,7 @@ async function pdf2markdown(folder, file, service, openai) {
|
|
|
271
219
|
|
|
272
220
|
// (OPTIONNEL) STEP 3: Utilisez GPT pour analyser la structure du contenu XML.
|
|
273
221
|
// Vous pouvez adapter le traitement en fonction du contenu généré par pdftohtml.
|
|
274
|
-
const {markdown,cost} = await
|
|
222
|
+
const {markdown,cost} = await callLLMForParsingPDF(file, xmlContent, [], model);
|
|
275
223
|
fs.writeFileSync(outputPath, markdown);
|
|
276
224
|
return {markdown,cost}; */
|
|
277
225
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @fileoverview Point d'entrée du module AgentStateGraph
|
|
3
3
|
* Exports principaux pour le système de gestion des discussions par agent
|
|
4
4
|
*/
|
|
5
|
-
export type { AgentMessage, TokenUsage, AgentDiscussion,
|
|
5
|
+
export type { AgentMessage, TokenUsage, AgentDiscussion, ClientDiscussion } from './types';
|
|
6
6
|
export { getSpecializedAgent } from './types';
|
|
7
7
|
export { AgentStateGraph } from './stategraph';
|
|
8
8
|
export { sessionStateGraphGet, sessionStateGraphSet, sessionStateGraphClear, sessionStateGraphExists, sessionStateGraphSize, migrateFromLegacySession } from './stategraph.storage';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @fileoverview Implémentation du système AgentStateGraph
|
|
3
3
|
* Classe principale pour gérer les discussions par agent
|
|
4
4
|
*/
|
|
5
|
-
import { AgentStateGraph as IAgentStateGraph, AgentDiscussion, AgentMessage, TokenUsage, ClientDiscussion } from './types';
|
|
5
|
+
import { AgentStateGraph as IAgentStateGraph, AgentDiscussion, AgentMessage, TokenUsage, ClientDiscussion, StepTrail } from './types';
|
|
6
6
|
/**
|
|
7
7
|
* Implémentation du StateGraph pour la gestion des discussions par agent
|
|
8
8
|
* Remplace AgenticMemoryManager avec une architecture simplifiée
|
|
@@ -17,6 +17,14 @@ export declare class AgentStateGraph implements IAgentStateGraph {
|
|
|
17
17
|
createOrRestore(agentName: string, description?: string): AgentDiscussion;
|
|
18
18
|
/**
|
|
19
19
|
* Ajoute un message à la discussion d'un agent
|
|
20
|
+
* Gère tous types de messages : user, assistant, system, tool, function_call_output, etc.
|
|
21
|
+
*
|
|
22
|
+
* Utilisée par:
|
|
23
|
+
* - readCompletionsStream (responses.ts) : messages assistant avec tool_calls, content
|
|
24
|
+
* - batchProcessToolCalls (helpers.ts) : messages function_call_output
|
|
25
|
+
* - executeAgentSet (responses.ts) : messages user
|
|
26
|
+
* - stategraph.storage.ts : migration ancien format
|
|
27
|
+
*
|
|
20
28
|
* @param agentName Nom de l'agent
|
|
21
29
|
* @param message Message sans ID ni timestamp (auto-générés)
|
|
22
30
|
*/
|
|
@@ -24,10 +32,39 @@ export declare class AgentStateGraph implements IAgentStateGraph {
|
|
|
24
32
|
/**
|
|
25
33
|
* Écrase le message system de la discussion avec un nouvel agent
|
|
26
34
|
* Le message system est toujours messages[0] avec role: "system"
|
|
27
|
-
* @param agentName Nom de l'agent
|
|
35
|
+
* @param agentName Nom de l'agent (clé de discussion, reste fixe)
|
|
28
36
|
* @param content Nouveau contenu du message system
|
|
29
37
|
*/
|
|
30
38
|
set(agentName: string, content: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Ajoute une étape au CONTEXT TRAIL et met à jour le message system
|
|
41
|
+
* Injecte automatiquement le trail dans le system message via updateSystemMessage()
|
|
42
|
+
*
|
|
43
|
+
* Utilisée par:
|
|
44
|
+
* - readCompletionsStream (responses.ts) : après chaque tool call exécuté
|
|
45
|
+
* - Tests d'intégration pour validation du context trail
|
|
46
|
+
*
|
|
47
|
+
* @param agentName Nom de l'agent
|
|
48
|
+
* @param step Étape à ajouter au trail (tool, context, reason, id optionnel)
|
|
49
|
+
*/
|
|
50
|
+
addStep(agentName: string, step: StepTrail): void;
|
|
51
|
+
/**
|
|
52
|
+
* Retourne tous les steps du CONTEXT TRAIL pour une discussion
|
|
53
|
+
* @param agentName Nom de l'agent
|
|
54
|
+
* @returns Liste des steps enregistrés pour cette discussion
|
|
55
|
+
*/
|
|
56
|
+
steps(agentName: string): StepTrail[];
|
|
57
|
+
/**
|
|
58
|
+
* Formate le CONTEXT TRAIL d'une discussion pour injection dans system instructions
|
|
59
|
+
* @param discussion Discussion à formater
|
|
60
|
+
* @returns Trail formaté ou message par défaut
|
|
61
|
+
*/
|
|
62
|
+
private formatTrailPrompt;
|
|
63
|
+
/**
|
|
64
|
+
* Met à jour le message system avec le nouveau trail via regexp
|
|
65
|
+
* @param agentName Nom de l'agent
|
|
66
|
+
*/
|
|
67
|
+
private updateSystemMessage;
|
|
31
68
|
/**
|
|
32
69
|
* Additionne l'usage des tokens pour un agent
|
|
33
70
|
* @param agentName Nom de l'agent
|
|
@@ -37,6 +74,17 @@ export declare class AgentStateGraph implements IAgentStateGraph {
|
|
|
37
74
|
/**
|
|
38
75
|
* Retourne une vue filtrée pour le client
|
|
39
76
|
* Supprime les messages system et les métadonnées d'outils
|
|
77
|
+
*
|
|
78
|
+
* Filtre appliqué:
|
|
79
|
+
* - Exclut: system, tool, messages avec name (Chat Completions function results)
|
|
80
|
+
* - Exclut: function_call_output (Responses API)
|
|
81
|
+
* - Exclut: messages assistant avec tool_calls mais sans content
|
|
82
|
+
* - Nettoie: <memories> tags dans le content
|
|
83
|
+
*
|
|
84
|
+
* Utilisée par:
|
|
85
|
+
* - ctrl/agent.ts (agentic-server) : ctrlGetHistory, ctrlExecuteAgent
|
|
86
|
+
* - Tests d'intégration pour validation
|
|
87
|
+
*
|
|
40
88
|
* @param agentName Nom de l'agent
|
|
41
89
|
* @returns Discussion filtrée pour l'affichage client
|
|
42
90
|
*/
|
|
@@ -78,6 +126,12 @@ export declare class AgentStateGraph implements IAgentStateGraph {
|
|
|
78
126
|
* @returns Nom de l'agent spécialisé
|
|
79
127
|
*/
|
|
80
128
|
getSpecializedAgent(agentName: string): string;
|
|
129
|
+
/**
|
|
130
|
+
* Charge une discussion en remplaçant l'existante ou en créant une nouvelle
|
|
131
|
+
* Recherche par id en priorité, sinon par startAgent
|
|
132
|
+
* @param discussion Discussion à charger
|
|
133
|
+
*/
|
|
134
|
+
load(discussion: AgentDiscussion): void;
|
|
81
135
|
/**
|
|
82
136
|
* Sérialise le StateGraph en JSON
|
|
83
137
|
* @returns Représentation JSON
|
|
@@ -30,6 +30,7 @@ class AgentStateGraph {
|
|
|
30
30
|
description: description,
|
|
31
31
|
messages: [],
|
|
32
32
|
usage: { prompt: 0, completion: 0, total: 0, cost: 0 },
|
|
33
|
+
trailSteps: [], // ✅ Chaque discussion a son propre trail
|
|
33
34
|
createdAt: new Date(),
|
|
34
35
|
updatedAt: new Date(),
|
|
35
36
|
startAgent: agentName
|
|
@@ -40,6 +41,14 @@ class AgentStateGraph {
|
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
42
43
|
* Ajoute un message à la discussion d'un agent
|
|
44
|
+
* Gère tous types de messages : user, assistant, system, tool, function_call_output, etc.
|
|
45
|
+
*
|
|
46
|
+
* Utilisée par:
|
|
47
|
+
* - readCompletionsStream (responses.ts) : messages assistant avec tool_calls, content
|
|
48
|
+
* - batchProcessToolCalls (helpers.ts) : messages function_call_output
|
|
49
|
+
* - executeAgentSet (responses.ts) : messages user
|
|
50
|
+
* - stategraph.storage.ts : migration ancien format
|
|
51
|
+
*
|
|
43
52
|
* @param agentName Nom de l'agent
|
|
44
53
|
* @param message Message sans ID ni timestamp (auto-générés)
|
|
45
54
|
*/
|
|
@@ -56,7 +65,7 @@ class AgentStateGraph {
|
|
|
56
65
|
/**
|
|
57
66
|
* Écrase le message system de la discussion avec un nouvel agent
|
|
58
67
|
* Le message system est toujours messages[0] avec role: "system"
|
|
59
|
-
* @param agentName Nom de l'agent
|
|
68
|
+
* @param agentName Nom de l'agent (clé de discussion, reste fixe)
|
|
60
69
|
* @param content Nouveau contenu du message system
|
|
61
70
|
*/
|
|
62
71
|
set(agentName, content) {
|
|
@@ -64,8 +73,8 @@ class AgentStateGraph {
|
|
|
64
73
|
const systemMessage = {
|
|
65
74
|
id: (0, crypto_1.randomUUID)(),
|
|
66
75
|
role: 'system',
|
|
67
|
-
content,
|
|
68
|
-
agent: agentName,
|
|
76
|
+
content: content,
|
|
77
|
+
agent: agentName, // Tag avec la clé de discussion
|
|
69
78
|
timestamp: new Date()
|
|
70
79
|
};
|
|
71
80
|
// Écraser ou créer le message system (toujours en position 0)
|
|
@@ -73,8 +82,75 @@ class AgentStateGraph {
|
|
|
73
82
|
discussion.messages.push(systemMessage);
|
|
74
83
|
}
|
|
75
84
|
else {
|
|
76
|
-
discussion.messages[0] =
|
|
85
|
+
discussion.messages[0].content = content;
|
|
86
|
+
discussion.messages[0].agent = systemMessage.agent;
|
|
87
|
+
discussion.messages[0].timestamp = new Date();
|
|
77
88
|
}
|
|
89
|
+
this.updateSystemMessage(discussion);
|
|
90
|
+
discussion.updatedAt = new Date();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Ajoute une étape au CONTEXT TRAIL et met à jour le message system
|
|
94
|
+
* Injecte automatiquement le trail dans le system message via updateSystemMessage()
|
|
95
|
+
*
|
|
96
|
+
* Utilisée par:
|
|
97
|
+
* - readCompletionsStream (responses.ts) : après chaque tool call exécuté
|
|
98
|
+
* - Tests d'intégration pour validation du context trail
|
|
99
|
+
*
|
|
100
|
+
* @param agentName Nom de l'agent
|
|
101
|
+
* @param step Étape à ajouter au trail (tool, context, reason, id optionnel)
|
|
102
|
+
*/
|
|
103
|
+
addStep(agentName, step) {
|
|
104
|
+
const discussion = this.discussions.find(d => d.startAgent === agentName);
|
|
105
|
+
if (!discussion)
|
|
106
|
+
return;
|
|
107
|
+
discussion.trailSteps.push(step);
|
|
108
|
+
this.updateSystemMessage(discussion);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Retourne tous les steps du CONTEXT TRAIL pour une discussion
|
|
112
|
+
* @param agentName Nom de l'agent
|
|
113
|
+
* @returns Liste des steps enregistrés pour cette discussion
|
|
114
|
+
*/
|
|
115
|
+
steps(agentName) {
|
|
116
|
+
const discussion = this.discussions.find(d => d.startAgent === agentName);
|
|
117
|
+
// console.log(`🔍 steps: ${agentName} has ${discussion?.trailSteps.length} steps`);
|
|
118
|
+
return discussion ? [...discussion.trailSteps] : [];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Formate le CONTEXT TRAIL d'une discussion pour injection dans system instructions
|
|
122
|
+
* @param discussion Discussion à formater
|
|
123
|
+
* @returns Trail formaté ou message par défaut
|
|
124
|
+
*/
|
|
125
|
+
formatTrailPrompt(discussion) {
|
|
126
|
+
if (discussion.trailSteps.length === 0) {
|
|
127
|
+
return '(No actions yet)';
|
|
128
|
+
}
|
|
129
|
+
return discussion.trailSteps.map(s => {
|
|
130
|
+
const idPart = s.id ? ` [id: ${s.id}]` : '';
|
|
131
|
+
return `- ${s.tool}: ${s.context} "${s.reason}"${idPart}`;
|
|
132
|
+
}).join('\n');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Met à jour le message system avec le nouveau trail via regexp
|
|
136
|
+
* @param agentName Nom de l'agent
|
|
137
|
+
*/
|
|
138
|
+
updateSystemMessage(discussion) {
|
|
139
|
+
const systemMessage = discussion.messages.find((m) => m.role === 'system');
|
|
140
|
+
if (!systemMessage)
|
|
141
|
+
return;
|
|
142
|
+
const trail = this.formatTrailPrompt(discussion);
|
|
143
|
+
const trailBlock = `<context-trail>\n${trail}\n</context-trail>`;
|
|
144
|
+
const hasTag = systemMessage.content.includes('<context-trail>');
|
|
145
|
+
// Remplacement via regexp du tag <context-trail>
|
|
146
|
+
if (hasTag) {
|
|
147
|
+
systemMessage.content = systemMessage.content.replace(/<context-trail>[\s\S]*?<\/context-trail>/, trailBlock);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Ajouter le tag si absent
|
|
151
|
+
systemMessage.content += `\n\n${trailBlock}`;
|
|
152
|
+
}
|
|
153
|
+
systemMessage.timestamp = new Date();
|
|
78
154
|
discussion.updatedAt = new Date();
|
|
79
155
|
}
|
|
80
156
|
/**
|
|
@@ -96,6 +172,17 @@ class AgentStateGraph {
|
|
|
96
172
|
/**
|
|
97
173
|
* Retourne une vue filtrée pour le client
|
|
98
174
|
* Supprime les messages system et les métadonnées d'outils
|
|
175
|
+
*
|
|
176
|
+
* Filtre appliqué:
|
|
177
|
+
* - Exclut: system, tool, messages avec name (Chat Completions function results)
|
|
178
|
+
* - Exclut: function_call_output (Responses API)
|
|
179
|
+
* - Exclut: messages assistant avec tool_calls mais sans content
|
|
180
|
+
* - Nettoie: <memories> tags dans le content
|
|
181
|
+
*
|
|
182
|
+
* Utilisée par:
|
|
183
|
+
* - ctrl/agent.ts (agentic-server) : ctrlGetHistory, ctrlExecuteAgent
|
|
184
|
+
* - Tests d'intégration pour validation
|
|
185
|
+
*
|
|
99
186
|
* @param agentName Nom de l'agent
|
|
100
187
|
* @returns Discussion filtrée pour l'affichage client
|
|
101
188
|
*/
|
|
@@ -107,9 +194,24 @@ class AgentStateGraph {
|
|
|
107
194
|
}
|
|
108
195
|
return content;
|
|
109
196
|
};
|
|
110
|
-
// Filtrer les messages pour le client - exclure system et
|
|
197
|
+
// Filtrer les messages pour le client - exclure system, tool et messages avec name
|
|
198
|
+
// ✅ Exclure aussi les messages Responses API (type: "function_call_output") et tool_calls sans content
|
|
111
199
|
const clientMessages = discussion.messages
|
|
112
|
-
.filter(msg =>
|
|
200
|
+
.filter((msg) => {
|
|
201
|
+
// Exclure system et tool
|
|
202
|
+
if (msg.role === 'system' || msg.role === 'tool')
|
|
203
|
+
return false;
|
|
204
|
+
// Exclure messages avec name (Chat Completions function results)
|
|
205
|
+
if (msg.name)
|
|
206
|
+
return false;
|
|
207
|
+
// Exclure messages Responses API: function_call_output
|
|
208
|
+
if (msg.type === 'function_call_output')
|
|
209
|
+
return false;
|
|
210
|
+
// Exclure messages assistant avec tool_calls mais sans content (métadonnées de tools)
|
|
211
|
+
if (msg.tool_calls && msg.tool_calls.length > 0 && !msg.content)
|
|
212
|
+
return false;
|
|
213
|
+
return true;
|
|
214
|
+
})
|
|
113
215
|
.map(msg => ({
|
|
114
216
|
id: msg.id,
|
|
115
217
|
role: msg.role,
|
|
@@ -122,6 +224,7 @@ class AgentStateGraph {
|
|
|
122
224
|
description: discussion.description,
|
|
123
225
|
agent: agentName,
|
|
124
226
|
messages: clientMessages,
|
|
227
|
+
steps: [...discussion.trailSteps],
|
|
125
228
|
usage: discussion.usage,
|
|
126
229
|
createdAt: discussion.createdAt,
|
|
127
230
|
updatedAt: discussion.updatedAt
|
|
@@ -162,6 +265,7 @@ class AgentStateGraph {
|
|
|
162
265
|
discussion.messages = [];
|
|
163
266
|
}
|
|
164
267
|
// Réinitialiser l'usage
|
|
268
|
+
discussion.trailSteps = [];
|
|
165
269
|
discussion.usage = { prompt: 0, completion: 0, total: 0, cost: 0 };
|
|
166
270
|
discussion.updatedAt = new Date();
|
|
167
271
|
}
|
|
@@ -211,6 +315,29 @@ class AgentStateGraph {
|
|
|
211
315
|
}
|
|
212
316
|
return agentName;
|
|
213
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* Charge une discussion en remplaçant l'existante ou en créant une nouvelle
|
|
320
|
+
* Recherche par id en priorité, sinon par startAgent
|
|
321
|
+
* @param discussion Discussion à charger
|
|
322
|
+
*/
|
|
323
|
+
load(discussion) {
|
|
324
|
+
// Chercher discussion existante par id OU par startAgent
|
|
325
|
+
const index = this.discussions.findIndex(d => d.id === discussion.id || d.startAgent === discussion.startAgent);
|
|
326
|
+
if (index >= 0) {
|
|
327
|
+
// Remplacer l'existante
|
|
328
|
+
this.discussions[index] = {
|
|
329
|
+
...discussion,
|
|
330
|
+
updatedAt: new Date()
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
// Créer nouvelle
|
|
335
|
+
this.discussions.push({
|
|
336
|
+
...discussion,
|
|
337
|
+
updatedAt: new Date()
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
214
341
|
/**
|
|
215
342
|
* Sérialise le StateGraph en JSON
|
|
216
343
|
* @returns Représentation JSON
|
|
@@ -230,6 +357,7 @@ class AgentStateGraph {
|
|
|
230
357
|
...d,
|
|
231
358
|
createdAt: new Date(d.createdAt),
|
|
232
359
|
updatedAt: new Date(d.updatedAt),
|
|
360
|
+
trailSteps: d.trailSteps || [], // ✅ Rétrocompatibilité : initialiser vide si absent
|
|
233
361
|
messages: d.messages.map((m) => ({
|
|
234
362
|
...m,
|
|
235
363
|
timestamp: new Date(m.timestamp)
|
|
@@ -22,6 +22,10 @@ const SESSION_STATEGRAPH_KEY = 'agentStateGraph';
|
|
|
22
22
|
* @returns StateGraph existant ou nouveau
|
|
23
23
|
*/
|
|
24
24
|
function sessionStateGraphGet(context) {
|
|
25
|
+
// ✅ Si un stateGraph est passé directement dans le contexte (mode sans session)
|
|
26
|
+
if (context.stateGraph && context.stateGraph instanceof stategraph_1.AgentStateGraph) {
|
|
27
|
+
return context.stateGraph;
|
|
28
|
+
}
|
|
25
29
|
const session = context.session;
|
|
26
30
|
if (!session) {
|
|
27
31
|
// Pour les tests, retourner un nouveau StateGraph si pas de session
|
|
@@ -71,6 +75,10 @@ function sessionStateGraphSet(context, stateGraph) {
|
|
|
71
75
|
const compressed = (0, zlib_1.gzipSync)(Buffer.from(jsonData, 'utf8'));
|
|
72
76
|
// Stocker en base64 dans la session
|
|
73
77
|
session[SESSION_STATEGRAPH_KEY] = compressed.toString('base64');
|
|
78
|
+
// Force express-session à marquer la session comme modifiée
|
|
79
|
+
if (typeof session.touch === 'function') {
|
|
80
|
+
session.touch();
|
|
81
|
+
}
|
|
74
82
|
// Logging pour debug (taille avant/après compression)
|
|
75
83
|
if (process.env.NODE_ENV === 'development') {
|
|
76
84
|
const originalSize = Buffer.byteLength(jsonData, 'utf8');
|
|
@@ -19,6 +19,9 @@ export interface AgentMessage {
|
|
|
19
19
|
agent?: string;
|
|
20
20
|
/** Timestamp de création */
|
|
21
21
|
timestamp: Date;
|
|
22
|
+
type?: string;
|
|
23
|
+
tool_call_id?: string;
|
|
24
|
+
output?: string;
|
|
22
25
|
}
|
|
23
26
|
/**
|
|
24
27
|
* Usage des tokens et coût
|
|
@@ -33,6 +36,20 @@ export interface TokenUsage {
|
|
|
33
36
|
/** Coût estimé en USD (optionnel) */
|
|
34
37
|
cost?: number;
|
|
35
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Step du CONTEXT TRAIL - trace une action significative
|
|
41
|
+
* Utilisé pour maintenir une mémoire de travail des actions effectuées par les outils
|
|
42
|
+
*/
|
|
43
|
+
export interface StepTrail {
|
|
44
|
+
/** Nom de l'outil (ex: "transferAgents", "database") */
|
|
45
|
+
tool: string;
|
|
46
|
+
/** Contexte de l'action (ex: "orientation → guess-word") */
|
|
47
|
+
context: string;
|
|
48
|
+
/** Justification/raison de l'action */
|
|
49
|
+
reason: string;
|
|
50
|
+
/** ID optionnel pour détection de boucles */
|
|
51
|
+
id?: string;
|
|
52
|
+
}
|
|
36
53
|
/**
|
|
37
54
|
* Discussion d'agent - thread de messages pour un agent spécifique
|
|
38
55
|
* Remplace l'ancienne AgenticMemorySession
|
|
@@ -48,6 +65,8 @@ export interface AgentDiscussion {
|
|
|
48
65
|
messages: AgentMessage[];
|
|
49
66
|
/** Usage des tokens pour cette discussion */
|
|
50
67
|
usage: TokenUsage;
|
|
68
|
+
/** CONTEXT TRAIL - steps des actions significatives */
|
|
69
|
+
trailSteps: StepTrail[];
|
|
51
70
|
/** Date de création */
|
|
52
71
|
createdAt: Date;
|
|
53
72
|
/** Date de dernière mise à jour */
|
|
@@ -104,6 +123,12 @@ export interface AgentStateGraph {
|
|
|
104
123
|
* @returns true si le message a été supprimé, false s'il n'a pas été trouvé
|
|
105
124
|
*/
|
|
106
125
|
deleteMessage(agentName: string, messageId: string): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Charge une discussion en remplaçant l'existante ou en créant une nouvelle
|
|
128
|
+
* Cherche par id OU par startAgent
|
|
129
|
+
* @param discussion Discussion à charger
|
|
130
|
+
*/
|
|
131
|
+
load(discussion: AgentDiscussion): void;
|
|
107
132
|
}
|
|
108
133
|
/**
|
|
109
134
|
* Vue client d'une discussion (filtrée)
|
|
@@ -124,6 +149,8 @@ export interface ClientDiscussion {
|
|
|
124
149
|
content: string;
|
|
125
150
|
timestamp: Date;
|
|
126
151
|
}>;
|
|
152
|
+
/** Context trail steps (actions effectuées) */
|
|
153
|
+
steps: StepTrail[];
|
|
127
154
|
/** Usage des tokens */
|
|
128
155
|
usage: TokenUsage;
|
|
129
156
|
/** Dates */
|