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.
Files changed (102) hide show
  1. package/dist/src/agents/agents.example.js +21 -22
  2. package/dist/src/agents/authentication.js +1 -2
  3. package/dist/src/agents/prompts.d.ts +5 -4
  4. package/dist/src/agents/prompts.js +44 -87
  5. package/dist/src/agents/reducer.core.d.ts +24 -2
  6. package/dist/src/agents/reducer.core.js +125 -35
  7. package/dist/src/agents/reducer.loaders.d.ts +55 -1
  8. package/dist/src/agents/reducer.loaders.js +114 -1
  9. package/dist/src/agents/reducer.types.d.ts +45 -2
  10. package/dist/src/agents/semantic.js +1 -2
  11. package/dist/src/agents/simulator.d.ts +11 -3
  12. package/dist/src/agents/simulator.executor.d.ts +14 -4
  13. package/dist/src/agents/simulator.executor.js +81 -23
  14. package/dist/src/agents/simulator.js +128 -42
  15. package/dist/src/agents/simulator.prompts.d.ts +9 -7
  16. package/dist/src/agents/simulator.prompts.js +66 -86
  17. package/dist/src/agents/simulator.types.d.ts +23 -5
  18. package/dist/src/agents/simulator.utils.d.ts +7 -2
  19. package/dist/src/agents/simulator.utils.js +31 -11
  20. package/dist/src/agents/system.js +1 -2
  21. package/dist/src/execute/helpers.d.ts +75 -0
  22. package/dist/src/execute/helpers.js +139 -0
  23. package/dist/src/execute/index.d.ts +11 -0
  24. package/dist/src/execute/index.js +44 -0
  25. package/dist/src/execute/legacy.d.ts +46 -0
  26. package/dist/src/execute/legacy.js +460 -0
  27. package/dist/src/execute/modelconfig.d.ts +19 -0
  28. package/dist/src/execute/modelconfig.js +56 -0
  29. package/dist/src/execute/responses.d.ts +55 -0
  30. package/dist/src/execute/responses.js +594 -0
  31. package/dist/src/execute/shared.d.ts +83 -0
  32. package/dist/src/execute/shared.js +188 -0
  33. package/dist/src/index.d.ts +1 -1
  34. package/dist/src/index.js +2 -2
  35. package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
  36. package/dist/src/pricing.llm.js +255 -0
  37. package/dist/src/prompts.d.ts +13 -4
  38. package/dist/src/prompts.js +221 -114
  39. package/dist/src/rag/embeddings.d.ts +36 -18
  40. package/dist/src/rag/embeddings.js +131 -128
  41. package/dist/src/rag/index.d.ts +5 -5
  42. package/dist/src/rag/index.js +14 -17
  43. package/dist/src/rag/parser.d.ts +2 -1
  44. package/dist/src/rag/parser.js +11 -14
  45. package/dist/src/rag/rag.examples.d.ts +27 -0
  46. package/dist/src/rag/rag.examples.js +151 -0
  47. package/dist/src/rag/rag.manager.d.ts +383 -0
  48. package/dist/src/rag/rag.manager.js +1390 -0
  49. package/dist/src/rag/types.d.ts +128 -12
  50. package/dist/src/rag/types.js +100 -1
  51. package/dist/src/rag/usecase.d.ts +37 -0
  52. package/dist/src/rag/usecase.js +96 -7
  53. package/dist/src/rules/git/git.e2e.helper.js +22 -2
  54. package/dist/src/rules/git/git.health.d.ts +61 -2
  55. package/dist/src/rules/git/git.health.js +333 -11
  56. package/dist/src/rules/git/index.d.ts +2 -2
  57. package/dist/src/rules/git/index.js +13 -1
  58. package/dist/src/rules/git/repo.d.ts +160 -0
  59. package/dist/src/rules/git/repo.js +777 -0
  60. package/dist/src/rules/git/repo.pr.js +117 -13
  61. package/dist/src/rules/git/repo.tools.d.ts +22 -1
  62. package/dist/src/rules/git/repo.tools.js +50 -1
  63. package/dist/src/rules/types.d.ts +27 -14
  64. package/dist/src/rules/utils.matter.d.ts +0 -4
  65. package/dist/src/rules/utils.matter.js +35 -7
  66. package/dist/src/scrapper.d.ts +15 -22
  67. package/dist/src/scrapper.js +58 -110
  68. package/dist/src/stategraph/index.d.ts +1 -1
  69. package/dist/src/stategraph/stategraph.d.ts +56 -2
  70. package/dist/src/stategraph/stategraph.js +134 -6
  71. package/dist/src/stategraph/stategraph.storage.js +8 -0
  72. package/dist/src/stategraph/types.d.ts +27 -0
  73. package/dist/src/types.d.ts +46 -9
  74. package/dist/src/types.js +8 -7
  75. package/dist/src/usecase.d.ts +11 -2
  76. package/dist/src/usecase.js +27 -35
  77. package/dist/src/utils.d.ts +32 -18
  78. package/dist/src/utils.js +87 -129
  79. package/package.json +10 -3
  80. package/dist/src/agents/digestor.test.d.ts +0 -1
  81. package/dist/src/agents/digestor.test.js +0 -45
  82. package/dist/src/agents/reducer.example.d.ts +0 -28
  83. package/dist/src/agents/reducer.example.js +0 -118
  84. package/dist/src/agents/reducer.process.d.ts +0 -16
  85. package/dist/src/agents/reducer.process.js +0 -143
  86. package/dist/src/agents/reducer.tools.d.ts +0 -29
  87. package/dist/src/agents/reducer.tools.js +0 -157
  88. package/dist/src/agents/simpleExample.d.ts +0 -3
  89. package/dist/src/agents/simpleExample.js +0 -38
  90. package/dist/src/agents/system-review.d.ts +0 -5
  91. package/dist/src/agents/system-review.js +0 -181
  92. package/dist/src/agents/systemReview.d.ts +0 -4
  93. package/dist/src/agents/systemReview.js +0 -22
  94. package/dist/src/execute.d.ts +0 -49
  95. package/dist/src/execute.js +0 -564
  96. package/dist/src/princing.openai.js +0 -54
  97. package/dist/src/rag/tools.d.ts +0 -76
  98. package/dist/src/rag/tools.js +0 -196
  99. package/dist/src/rules/user.mapper.d.ts +0 -61
  100. package/dist/src/rules/user.mapper.js +0 -160
  101. package/dist/src/rules/utils/slug.d.ts +0 -22
  102. package/dist/src/rules/utils/slug.js +0 -35
@@ -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.callGPTForParsingPDF = callGPTForParsingPDF;
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 princing_openai_1 = require("./princing.openai");
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, princing_openai_1.calculateCost)(model, response.usage);
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 callGPTForParsingPDF(inputfile, pdfData, openai, links = []) {
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: callGPTForParsingPDF -- SYSTEM:', messages[0].content);
71
- // console.log('🌶️ DEBUG: callGPTForParsingPDF -- USER:', messages[1].content);
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 model = "gpt-4.1"; // "gpt-4.1";
74
- let response = await openai.chat.completions.create({
75
- model: 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
- let markdown = response.choices[0].message.content;
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
- let markdownWithoutThinking = markdown.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
97
- // const hragPrompt = await extractHRAGSections(markdownWithoutThinking, openai);
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 {any} openai - The OpenAI instance to use for the GPT API calls.
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, openai) {
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 callGPTForParsingPDF(file, html, openai);
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 GPT pour analyser la structure.
157
+ * 3. (Optionnellement) Le passage du contenu converti au modèle LLM pour analyser la structure.
230
158
  *
231
- * @param {string} file - Chemin vers le fichier PDF à analyser.
232
- * @param {any} openai - L'instance configurée pour appeler l'API OpenAI.
233
- * @returns {Promise<any>} - Le markdown structuré (issue de GPT) ou tout autre traitement souhaité.
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(folder, file, service, openai) {
236
- const filename = (0, utils_1.toSlug)(path_1.default.basename(file, path_1.default.extname(file)));
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(folder, `cleaned-${randomFile()}.pdf`);
239
- const tempOut = path_1.default.join(folder, `${filename}.txt`);
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(folder, `${(0, utils_1.toSlug)(service.toLocaleLowerCase())}-${filename}.md`);
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", file]);
191
+ // const { stdout } = await execFileAsync("python3", ["./bin/extract_text_with_links.py", pdf]);
248
192
  // const { text, links } = JSON.parse(stdout);
249
- await execAsync(`pdftotext -nodiag -nopgbrk "${file}" "${outputPath}"`);
250
- const links = await extractLinksFromPDF(file, folder);
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 callGPTForParsingPDF(file, text, openai, links);
253
- fs_1.default.writeFileSync(outputPath, markdown);
254
- return { markdown, cost, outputPath };
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 callGPTForParsingPDF(file, xmlContent, openai);
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, AgentStateGraph as IAgentStateGraph, ClientDiscussion } from './types';
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] = systemMessage;
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 tool
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 => msg.role !== 'system' && !msg.name)
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 */