agentic-api 2.0.31 → 2.0.314

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 (89) 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 +42 -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 +4 -0
  12. package/dist/src/agents/simulator.executor.d.ts +5 -1
  13. package/dist/src/agents/simulator.executor.js +41 -9
  14. package/dist/src/agents/simulator.js +86 -28
  15. package/dist/src/agents/simulator.prompts.d.ts +3 -2
  16. package/dist/src/agents/simulator.prompts.js +52 -78
  17. package/dist/src/agents/simulator.types.d.ts +20 -5
  18. package/dist/src/agents/simulator.utils.d.ts +7 -2
  19. package/dist/src/agents/simulator.utils.js +33 -11
  20. package/dist/src/agents/system.js +1 -2
  21. package/dist/src/execute.d.ts +17 -3
  22. package/dist/src/execute.js +156 -158
  23. package/dist/src/index.d.ts +1 -1
  24. package/dist/src/index.js +1 -1
  25. package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
  26. package/dist/src/pricing.llm.js +234 -0
  27. package/dist/src/prompts.d.ts +13 -4
  28. package/dist/src/prompts.js +221 -114
  29. package/dist/src/rag/embeddings.d.ts +36 -18
  30. package/dist/src/rag/embeddings.js +125 -128
  31. package/dist/src/rag/index.d.ts +5 -5
  32. package/dist/src/rag/index.js +14 -17
  33. package/dist/src/rag/parser.d.ts +2 -1
  34. package/dist/src/rag/parser.js +11 -14
  35. package/dist/src/rag/rag.examples.d.ts +27 -0
  36. package/dist/src/rag/rag.examples.js +151 -0
  37. package/dist/src/rag/rag.manager.d.ts +383 -0
  38. package/dist/src/rag/rag.manager.js +1378 -0
  39. package/dist/src/rag/types.d.ts +128 -12
  40. package/dist/src/rag/types.js +100 -1
  41. package/dist/src/rag/usecase.d.ts +37 -0
  42. package/dist/src/rag/usecase.js +96 -7
  43. package/dist/src/rules/git/git.e2e.helper.js +1 -0
  44. package/dist/src/rules/git/git.health.d.ts +57 -0
  45. package/dist/src/rules/git/git.health.js +281 -1
  46. package/dist/src/rules/git/index.d.ts +2 -2
  47. package/dist/src/rules/git/index.js +12 -1
  48. package/dist/src/rules/git/repo.d.ts +117 -0
  49. package/dist/src/rules/git/repo.js +536 -0
  50. package/dist/src/rules/git/repo.tools.d.ts +22 -1
  51. package/dist/src/rules/git/repo.tools.js +50 -1
  52. package/dist/src/rules/types.d.ts +16 -14
  53. package/dist/src/rules/utils.matter.d.ts +0 -4
  54. package/dist/src/rules/utils.matter.js +26 -7
  55. package/dist/src/scrapper.d.ts +15 -22
  56. package/dist/src/scrapper.js +57 -110
  57. package/dist/src/stategraph/index.d.ts +1 -1
  58. package/dist/src/stategraph/stategraph.d.ts +31 -2
  59. package/dist/src/stategraph/stategraph.js +93 -6
  60. package/dist/src/stategraph/stategraph.storage.js +4 -0
  61. package/dist/src/stategraph/types.d.ts +22 -0
  62. package/dist/src/types.d.ts +4 -2
  63. package/dist/src/types.js +1 -1
  64. package/dist/src/usecase.d.ts +11 -2
  65. package/dist/src/usecase.js +27 -35
  66. package/dist/src/utils.d.ts +32 -18
  67. package/dist/src/utils.js +60 -126
  68. package/package.json +7 -2
  69. package/dist/src/agents/digestor.test.d.ts +0 -1
  70. package/dist/src/agents/digestor.test.js +0 -45
  71. package/dist/src/agents/reducer.example.d.ts +0 -28
  72. package/dist/src/agents/reducer.example.js +0 -118
  73. package/dist/src/agents/reducer.process.d.ts +0 -16
  74. package/dist/src/agents/reducer.process.js +0 -143
  75. package/dist/src/agents/reducer.tools.d.ts +0 -29
  76. package/dist/src/agents/reducer.tools.js +0 -157
  77. package/dist/src/agents/simpleExample.d.ts +0 -3
  78. package/dist/src/agents/simpleExample.js +0 -38
  79. package/dist/src/agents/system-review.d.ts +0 -5
  80. package/dist/src/agents/system-review.js +0 -181
  81. package/dist/src/agents/systemReview.d.ts +0 -4
  82. package/dist/src/agents/systemReview.js +0 -22
  83. package/dist/src/princing.openai.js +0 -54
  84. package/dist/src/rag/tools.d.ts +0 -76
  85. package/dist/src/rag/tools.js +0 -196
  86. package/dist/src/rules/user.mapper.d.ts +0 -61
  87. package/dist/src/rules/user.mapper.js +0 -160
  88. package/dist/src/rules/utils/slug.d.ts +0 -22
  89. package/dist/src/rules/utils/slug.js +0 -35
@@ -3,8 +3,9 @@
3
3
  * Native Loaders for MapLLM
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.StringNativeLoader = exports.FileNativeLoader = void 0;
6
+ exports.TaskListLoader = exports.StringNativeLoader = exports.FileNativeLoader = void 0;
7
7
  const fs_1 = require("fs");
8
+ const crypto_1 = require("crypto");
8
9
  /**
9
10
  * FileNativeLoader - Loader pour fichiers avec chunking par lignes
10
11
  */
@@ -120,3 +121,115 @@ class StringNativeLoader {
120
121
  }
121
122
  }
122
123
  exports.StringNativeLoader = StringNativeLoader;
124
+ /**
125
+ * TaskListLoader - Loader pour exécution séquentielle de tâches
126
+ * Compatible avec NativeLoader pour réutiliser la logique de MapLLM
127
+ * Job = TaskListLoader (pas de type séparé)
128
+ */
129
+ class TaskListLoader {
130
+ /**
131
+ * Constructeur principal - crée un nouveau Job avec ID auto-généré
132
+ * @param tasks Liste des tâches
133
+ * @param agents Liste des agents matérialisés
134
+ * @param description Description du Job (optionnel)
135
+ */
136
+ constructor(tasks, agents, description) {
137
+ this._id = (0, crypto_1.randomUUID)();
138
+ this._tasks = tasks;
139
+ this._agents = agents;
140
+ this._description = description || '';
141
+ }
142
+ /**
143
+ * ✅ Restaure depuis Job avec liste d'agents matérialisés
144
+ * @param job Job sérialisé (agents = string[])
145
+ * @param availableAgents Liste d'agents matérialisés pour reconstruction
146
+ */
147
+ static fromJob(job, availableAgents) {
148
+ //
149
+ // Reconstruire AgentConfig[] depuis job.agents (string[])
150
+ const agents = job.agents
151
+ .map(name => availableAgents.find(a => a.name === name))
152
+ .filter(Boolean);
153
+ if (agents.length === 0) {
154
+ throw new Error('No matching agents found for Job');
155
+ }
156
+ const instance = new TaskListLoader(job.tasks, agents, job.description);
157
+ instance._id = job.id; // ✅ Préserver l'ID
158
+ return instance;
159
+ }
160
+ /**
161
+ * ✅ Méthode static pour charger depuis OneDrive
162
+ * @param credential Token credential
163
+ * @param jobId ID du Job à charger
164
+ * @param availableAgents Liste d'agents matérialisés
165
+ */
166
+ static async loadJob(credential, jobId, availableAgents) {
167
+ //
168
+ // Import dynamique pour éviter dépendance circulaire
169
+ // getJobsFromOneDrive sera fourni par job.service.ts (agentic-server)
170
+ const jobs = await getJobsFromOneDrive(credential);
171
+ const job = jobs.find(j => j.id === jobId);
172
+ if (!job)
173
+ return null;
174
+ return TaskListLoader.fromJob(job, availableAgents);
175
+ }
176
+ /**
177
+ * Getters
178
+ */
179
+ get id() { return this._id; }
180
+ get tasks() { return this._tasks; }
181
+ get agents() { return this._agents; }
182
+ get description() { return this._description; }
183
+ get label() { return this._description; }
184
+ /**
185
+ * Ajoute une tâche (agent et model optionnels)
186
+ * @param task Tâche sans ID (auto-généré)
187
+ */
188
+ addTask(task) {
189
+ const newTask = {
190
+ ...task,
191
+ id: (0, crypto_1.randomUUID)(),
192
+ agentName: task.agentName || this._agents[0]?.name
193
+ };
194
+ this._tasks.push(newTask);
195
+ }
196
+ /**
197
+ * ✅ Retourne Job sérialisable (AgentConfig → string[])
198
+ */
199
+ toJob() {
200
+ return {
201
+ id: this._id,
202
+ tasks: this._tasks,
203
+ agents: this._agents.map(a => a.name), // ✅ Seulement les noms
204
+ description: this._description,
205
+ discussions: [],
206
+ createdAt: new Date(),
207
+ updatedAt: new Date()
208
+ };
209
+ }
210
+ async loadNativeChunk(position) {
211
+ if (position >= this._tasks.length) {
212
+ throw new Error(`Task position ${position} out of bounds (total: ${this._tasks.length})`);
213
+ }
214
+ const task = this._tasks[position];
215
+ //
216
+ // Serialize task as JSON string (compatible avec content: string)
217
+ const content = JSON.stringify(task);
218
+ const nextPosition = position + 1;
219
+ const eof = nextPosition >= this._tasks.length;
220
+ return {
221
+ content,
222
+ eof,
223
+ position: nextPosition
224
+ };
225
+ }
226
+ }
227
+ exports.TaskListLoader = TaskListLoader;
228
+ /**
229
+ * Helper pour TaskListLoader.loadJob
230
+ * Sera fourni par job.service.ts pour éviter import circulaire
231
+ */
232
+ async function getJobsFromOneDrive(credential) {
233
+ // Placeholder - implémenté dans agentic-server/src/pinned/job.service.ts
234
+ return [];
235
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Types for the MapLLM reducer functionality
3
3
  */
4
- import type { AgentModel } from '../types';
4
+ import { Writable } from 'stream';
5
5
  export interface NativeLoader {
6
6
  loadNativeChunk(position: number): Promise<{
7
7
  content: string;
@@ -16,6 +16,10 @@ export interface StatefulReducerConfig {
16
16
  reducePrompt: string;
17
17
  /** Modulo for reducing the digest */
18
18
  reduceModulo?: number;
19
+ /** ✅ Context pour exécution (optionnel - accès credential, session, etc.) */
20
+ context?: any;
21
+ /** ✅ Stdout pour feedback streaming (optionnel) */
22
+ stdout?: any;
19
23
  }
20
24
  export interface StructuredOutputFormat {
21
25
  /** Schema name for the structured output */
@@ -28,12 +32,15 @@ export interface StructuredOutputFormat {
28
32
  export interface MapLLMReduceResult {
29
33
  /** Accumulator - string for text mode, object for structured output */
30
34
  acc: string | Record<string, any>;
35
+ stdout?: Writable;
31
36
  continue?: boolean;
32
37
  maxIterations?: boolean;
38
+ /** ✅ Configuration déplacée ici (plus dans params reduce) */
39
+ config?: StatefulReducerConfig;
33
40
  /** OpenAI structured output format configuration */
34
41
  format?: StructuredOutputFormat;
35
42
  /** Model configuration */
36
- model?: AgentModel;
43
+ model?: string;
37
44
  verbose?: boolean;
38
45
  /** Processing metadata */
39
46
  metadata?: {
@@ -48,3 +55,39 @@ export interface ChunkStrategy {
48
55
  size: number;
49
56
  overlap?: number;
50
57
  }
58
+ /**
59
+ * Task definition for Plan-Executor
60
+ */
61
+ export interface Task {
62
+ /** Unique task identifier */
63
+ id: string;
64
+ /** Task prompt/query to execute */
65
+ prompt: string;
66
+ /** Optional: Agent name to use (if not specified, uses default) */
67
+ agentName?: string;
68
+ /** Optional: Force model to use for this task */
69
+ model?: string;
70
+ /** Optional: Tools to add/override for this task */
71
+ tools?: any[];
72
+ /** Optional: Metadata for tracking */
73
+ meta?: Record<string, any>;
74
+ }
75
+ /**
76
+ * Job sérialisable (stocké en OneDrive)
77
+ * Les agents sont stockés comme string[] (noms) car AgentConfig n'est pas sérialisable
78
+ */
79
+ export interface Job {
80
+ /** Identifiant unique du Job */
81
+ id: string;
82
+ /** Liste des tâches */
83
+ tasks: Task[];
84
+ /** Noms des agents (sérialisable - AgentConfig n'est pas sérialisable) */
85
+ agents: string[];
86
+ /** Description du Job */
87
+ description?: string;
88
+ /** IDs des discussions liées à ce Job */
89
+ discussions: string[];
90
+ /** Dates */
91
+ createdAt: Date;
92
+ updatedAt: Date;
93
+ }
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.semantic = void 0;
4
- const execute_1 = require("../execute");
5
4
  const utils_1 = require("../utils");
6
5
  const prompts_1 = require("./prompts");
7
6
  exports.semantic = {
8
7
  name: "semantic",
9
- model: (0, execute_1.modelConfig)("LOW"),
8
+ model: "LOW",
10
9
  publicDescription: "Agent spécialisé dans l’extraction sémantique structurée",
11
10
  instructions: prompts_1.semanticPrompt,
12
11
  tools: [],
@@ -44,4 +44,8 @@ export declare class AgentSimulator {
44
44
  * Générer le rapport final en cas de timeout
45
45
  */
46
46
  private generateTimeoutReport;
47
+ /**
48
+ * Valider que les outils attendus ont été appelés le bon nombre de fois
49
+ */
50
+ private validateExpectedTools;
47
51
  }
@@ -2,7 +2,11 @@ import { SimulatorConfig, ExecutionContext } from './simulator.types';
2
2
  export declare class AgentExecutor {
3
3
  private config;
4
4
  private simulatorAgent;
5
- constructor(config: SimulatorConfig);
5
+ private mockCacheInitializer?;
6
+ private ragManager?;
7
+ constructor(config: SimulatorConfig & {
8
+ mockCacheInitializer?: (sessionId: string) => Promise<void>;
9
+ });
6
10
  /**
7
11
  * Initialiser les contextes agent et simulateur
8
12
  */
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AgentExecutor = void 0;
4
- const types_1 = require("../types");
4
+ const rag_1 = require("../rag");
5
5
  const stategraph_1 = require("../stategraph");
6
6
  const execute_1 = require("../execute");
7
7
  const simulator_prompts_1 = require("./simulator.prompts");
@@ -11,16 +11,34 @@ class AgentExecutor {
11
11
  // Construire les instructions complètes du simulateur
12
12
  const fullInstructions = simulator_prompts_1.GENERIC_SIMULATOR_PROMPT +
13
13
  (config.instructionEx ? `\n\n${config.instructionEx}` : '') +
14
- '\n\n**CRITICAL**: Your response after [SIMULATION_COMPLETE] must be valid JSON format only.';
14
+ '\n\n**CRITICAL**: Your response after [DONE] must be valid JSON format only.';
15
+ // console.log('---- DBG simulator fullInstructions',fullInstructions);
15
16
  // Agent simulateur simple pour éviter les dépendances complexes du ClientSimulator
16
17
  this.simulatorAgent = {
17
18
  name: "simple-simulator",
18
- model: (0, execute_1.modelConfig)("MEDIUM-fast"), // JSON sera forcé via les instructions du prompt
19
+ model: ("MEDIUM-fast"), // JSON sera forcé via les instructions du prompt
19
20
  publicDescription: "Simulateur simple pour tests - TOUJOURS retourner JSON valide",
21
+ cancelMemory: true,
20
22
  instructions: fullInstructions,
21
23
  tools: [],
22
24
  downstreamAgents: []
23
25
  };
26
+ //
27
+ // ✅ Annuler la mémoire pour tous les agents en simulation
28
+ config.agents.forEach(agent => {
29
+ agent.cancelMemory = true;
30
+ });
31
+ this.mockCacheInitializer = config.mockCacheInitializer;
32
+ // ✅ Initialiser le RAGManager si la configuration est fournie
33
+ if (config.ragConfig) {
34
+ try {
35
+ this.ragManager = rag_1.RAGManager.get(config.ragConfig);
36
+ console.log(`✅ RAGManager initialisé pour le simulateur (default: ${this.ragManager.getDefault()})`);
37
+ }
38
+ catch (error) {
39
+ console.warn('⚠️ Impossible d\'initialiser le RAGManager pour le simulateur:', error);
40
+ }
41
+ }
24
42
  }
25
43
  /**
26
44
  * Initialiser les contextes agent et simulateur
@@ -31,7 +49,9 @@ class AgentExecutor {
31
49
  user: { id: `test-user`, role: 'user', uid: `test-${sessionId}` },
32
50
  credential: { test: true, sessionId: `agent-${sessionId}` },
33
51
  verbose: this.config.verbose,
34
- session: { id: `agent-${sessionId}`, data: {}, messages: [] }
52
+ session: { id: `agent-${sessionId}`, data: {}, messages: [] },
53
+ // ✅ Ajouter customRag au contexte si le RAG est configuré
54
+ ...(this.ragManager ? { customRag: this.ragManager.getDefault() } : {})
35
55
  };
36
56
  const simulatorContext = {
37
57
  user: { id: `simulator-user`, role: 'user', uid: `sim-${sessionId}` },
@@ -39,6 +59,10 @@ class AgentExecutor {
39
59
  verbose: this.config.verbose,
40
60
  session: { id: `sim-${sessionId}`, data: {}, messages: [] }
41
61
  };
62
+ // ✅ Initialiser le cache mock si fourni (pour les tests SGC avec M-Files)
63
+ if (this.mockCacheInitializer) {
64
+ await this.mockCacheInitializer(agentContext.session.id);
65
+ }
42
66
  return {
43
67
  agentContext,
44
68
  simulatorContext,
@@ -62,16 +86,23 @@ class AgentExecutor {
62
86
  const execResult = await (0, execute_1.executeAgentSet)(this.config.agents, context.agentContext, {
63
87
  query,
64
88
  home: this.config.start,
65
- stdout: { write: () => { }, end: () => { }, writableEnded: false },
89
+ stdout: execute_1.DummyWritable,
66
90
  verbose: this.config.verbose,
67
91
  debug: false
68
92
  });
93
+ // Accumuler seulement l'usage, pas les actions
69
94
  if (context.lastExecution) {
70
- context.lastExecution = (0, types_1.executionResultMerge)(context.lastExecution, execResult);
71
- }
72
- else {
73
- context.lastExecution = execResult;
95
+ context.lastExecution.usage.prompt += execResult.usage.prompt;
96
+ context.lastExecution.usage.completion += execResult.usage.completion;
97
+ context.lastExecution.usage.total += execResult.usage.total;
98
+ context.lastExecution.usage.cost += execResult.usage.cost;
74
99
  }
100
+ context.lastExecution = execResult;
101
+ // if (context.lastExecution) {
102
+ // context.lastExecution = executionResultMerge(context.lastExecution, execResult);
103
+ // } else {
104
+ // context.lastExecution = execResult;
105
+ // }
75
106
  context.exchangeCount++;
76
107
  // ✅ Extraire et retourner le dernier message de l'agent (logique de getLastPRSolverMessage)
77
108
  return this.getLastAgentMessage(context.agentContext);
@@ -99,6 +130,7 @@ class AgentExecutor {
99
130
  getLastAgentMessage(agentContext) {
100
131
  const stateGraph = (0, stategraph_1.sessionStateGraphGet)(agentContext);
101
132
  const messages = stateGraph.discussions[0].messages;
133
+ // console.log('---- DBG system message (check context-trail):', messages[0]?.content?.substring(messages[0].content.indexOf('<context-trail>'), messages[0].content.indexOf('</context-trail>') + 17));
102
134
  if (!messages || !messages.length) {
103
135
  return '[Aucun message trouvé]';
104
136
  }
@@ -21,46 +21,83 @@ class AgentSimulator {
21
21
  */
22
22
  async executeSimulation(options) {
23
23
  const context = await this.executor.initializeContexts();
24
+ const allMessages = [];
25
+ let lastAgentMessage = '';
26
+ let exchangeCounter = 0; // Compteur d'échanges (user+assistant)
24
27
  try {
25
28
  // Construire la query formatée avec buildSimulatorQuery()
26
29
  // Les instructions supplémentaires sont déjà intégrées dans le constructeur de l'executor
27
- const scenarioQuery = (0, simulator_prompts_1.buildSimulatorQuery)(options.scenario);
30
+ const scenarioQuery = (0, simulator_prompts_1.buildSimulatorQuery)(options.scenario, options.query);
28
31
  // Générer le message initial du simulateur avec le scénario
29
32
  let currentUserQuery = await this.executor.executeSimulator(context, scenarioQuery);
30
- // Callback pour message initial du simulateur
33
+ // Stocker le message initial du simulateur
34
+ const initialMsg = { content: currentUserQuery, role: 'user' };
35
+ allMessages.push(initialMsg);
31
36
  if (options.onMessage) {
32
- options.onMessage({ content: currentUserQuery, role: 'user' });
37
+ options.onMessage(initialMsg);
33
38
  }
34
- // Boucle de conversation
35
- for (let i = 0; i < options.maxExchanges; i++) {
39
+ // Boucle de conversation - maxExchanges = nombre de paires (user+assistant)
40
+ while (exchangeCounter < options.maxExchanges) {
36
41
  // Agent testé répond et retourne sa réponse
37
42
  const agentResponse = await this.executor.executeAgent(context, currentUserQuery);
38
- // Callback pour réponse de l'agent
43
+ lastAgentMessage = agentResponse;
44
+ // Stocker la réponse de l'agent
45
+ const agentMsg = { content: agentResponse, role: 'assistant' };
46
+ allMessages.push(agentMsg);
39
47
  if (options.onMessage) {
40
- options.onMessage({ content: agentResponse, role: 'assistant' });
48
+ options.onMessage(agentMsg);
41
49
  }
50
+ // Incrémenter le compteur après la réponse de l'agent (assistant)
51
+ exchangeCounter++;
42
52
  // Simulateur évalue et répond
43
53
  const simulatorResult = await this.executor.executeSimulator(context, agentResponse);
54
+ // console.log(context.agentContext.messages);
44
55
  // Vérifier si terminé
45
56
  if (this.isSimulationComplete(simulatorResult)) {
46
- const parsed = this.parseSimulationResult(simulatorResult, options.scenario.testResult, context);
57
+ const expectedFormat = options.scenario.result || options.scenario.testResult || '{"success": boolean, "error": string}';
58
+ const parsed = this.parseSimulationResult(simulatorResult, expectedFormat, context);
47
59
  this.lastExecution = context.lastExecution;
60
+ // Validation des tools si expectedTool est fourni
61
+ if (options.expectedTool) {
62
+ const validation = this.validateExpectedTools(options.expectedTool);
63
+ if (!validation.passed) {
64
+ parsed.success = false;
65
+ parsed.error = validation.errors.join('; ');
66
+ parsed.toolValidation = validation;
67
+ }
68
+ }
69
+ // Ajouter l'historique des messages au résultat
48
70
  return {
49
71
  ...parsed,
50
72
  execution: context.lastExecution,
51
- exchangeCount: context.exchangeCount
73
+ exchangeCount: exchangeCounter, // Utiliser notre compteur d'échanges
74
+ messages: allMessages
52
75
  };
53
76
  }
54
77
  currentUserQuery = this.extractConversationalPart(simulatorResult);
55
- // Callback pour réponse du simulateur (si pas terminé)
56
- if (options.onMessage && currentUserQuery) {
57
- options.onMessage({ content: currentUserQuery, role: 'user' });
78
+ // Stocker la réponse du simulateur (si pas terminé)
79
+ if (currentUserQuery) {
80
+ const simulatorMsg = { content: currentUserQuery, role: 'user' };
81
+ allMessages.push(simulatorMsg);
82
+ if (options.onMessage) {
83
+ options.onMessage(simulatorMsg);
84
+ }
58
85
  }
59
86
  }
60
87
  // Timeout - générer rapport final
61
- const timeout = await this.generateTimeoutReport(context, options.scenario.testResult);
88
+ const expectedFormat = options.scenario.result || options.scenario.testResult || '{"success": boolean, "error": string}';
89
+ const timeout = await this.generateTimeoutReport(context, expectedFormat);
62
90
  this.lastExecution = context.lastExecution;
63
- return { ...timeout, exchangeCount: context.exchangeCount };
91
+ // Validation des tools même en cas de timeout
92
+ if (options.expectedTool) {
93
+ const validation = this.validateExpectedTools(options.expectedTool);
94
+ if (!validation.passed) {
95
+ timeout.success = false;
96
+ timeout.error = validation.errors.join('; ');
97
+ timeout.toolValidation = validation;
98
+ }
99
+ }
100
+ return { ...timeout, exchangeCount: exchangeCounter, messages: allMessages }; // Utiliser notre compteur
64
101
  }
65
102
  catch (error) {
66
103
  this.lastExecution = context.lastExecution;
@@ -69,7 +106,8 @@ class AgentSimulator {
69
106
  message: '',
70
107
  error: `Erreur d'exécution: ${error.message || error}`,
71
108
  execution: context.lastExecution,
72
- exchangeCount: context.exchangeCount
109
+ exchangeCount: exchangeCounter, // Utiliser notre compteur
110
+ messages: allMessages
73
111
  };
74
112
  }
75
113
  }
@@ -122,17 +160,17 @@ class AgentSimulator {
122
160
  return { summary, execution };
123
161
  }
124
162
  isSimulationComplete(response) {
125
- return response.includes('[SIMULATION_COMPLETE]') || response.includes('[TERMINE]');
163
+ return response.includes('[DONE]') || response.includes('[SIMULATION_COMPLETE]') || response.includes('[TERMINE]');
126
164
  }
127
165
  parseSimulationResult(response, expectedFormat, context) {
128
166
  // Le simulateur produit directement le résultat et rapport
129
167
  // Parsing pour détecter la fin et extraire le contenu JSON
130
- // Détecter [SIMULATION_COMPLETE] ou [TERMINE]
131
- if (response.includes('[SIMULATION_COMPLETE]') || response.includes('[TERMINE]')) {
168
+ // Détecter [DONE], [SIMULATION_COMPLETE] ou [TERMINE]
169
+ if (response.includes('[DONE]') || response.includes('[SIMULATION_COMPLETE]') || response.includes('[TERMINE]')) {
132
170
  // Extraire le contenu après le tag
133
- const match = response.match(/\[SIMULATION_COMPLETE\]\s*\n?([\s\S]*)/);
171
+ const match = response.match(/\[(DONE|SIMULATION_COMPLETE|TERMINE)\]\s*\n?([\s\S]*)/);
134
172
  if (match) {
135
- const resultContent = match[1].trim();
173
+ const resultContent = match[2].trim();
136
174
  // Essayer de parser comme JSON d'abord
137
175
  try {
138
176
  const jsonResult = JSON.parse(resultContent);
@@ -141,7 +179,8 @@ class AgentSimulator {
141
179
  message: jsonResult.description || resultContent,
142
180
  error: jsonResult.error || '',
143
181
  execution: context.lastExecution,
144
- exchangeCount: context.exchangeCount
182
+ exchangeCount: context.exchangeCount,
183
+ messages: [] // Sera rempli par executeSimulation
145
184
  };
146
185
  }
147
186
  catch (jsonError) {
@@ -159,7 +198,8 @@ class AgentSimulator {
159
198
  message: description,
160
199
  error: errorMatch ? errorMatch[1].trim() : '',
161
200
  execution: context.lastExecution,
162
- exchangeCount: context.exchangeCount
201
+ exchangeCount: context.exchangeCount,
202
+ messages: [] // Sera rempli par executeSimulation
163
203
  };
164
204
  }
165
205
  }
@@ -169,7 +209,8 @@ class AgentSimulator {
169
209
  message: response,
170
210
  error: '',
171
211
  execution: context.lastExecution,
172
- exchangeCount: context.exchangeCount
212
+ exchangeCount: context.exchangeCount,
213
+ messages: [] // Sera rempli par executeSimulation
173
214
  };
174
215
  }
175
216
  // Si pas de tag de fin détecté
@@ -178,12 +219,13 @@ class AgentSimulator {
178
219
  message: response,
179
220
  error: 'Simulation non terminée',
180
221
  execution: context.lastExecution,
181
- exchangeCount: context.exchangeCount
222
+ exchangeCount: context.exchangeCount,
223
+ messages: [] // Sera rempli par executeSimulation
182
224
  };
183
225
  }
184
226
  extractConversationalPart(response) {
185
227
  // Extraire la partie conversationnelle avant les tags d'évaluation
186
- const tagIndex = response.search(/\[(SIMULATION_COMPLETE|TERMINE|BUG_)/);
228
+ const tagIndex = response.search(/\[(DONE|SIMULATION_COMPLETE|TERMINE|BUG_)/);
187
229
  return tagIndex !== -1 ? response.substring(0, tagIndex).trim() : response;
188
230
  }
189
231
  /**
@@ -191,15 +233,31 @@ class AgentSimulator {
191
233
  */
192
234
  async generateTimeoutReport(context, expectedFormat) {
193
235
  const reportQuery = `
194
- La simulation a atteint la limite d'échanges sans conclusion.
236
+ La conversation a atteint la limite d'échanges sans conclusion.
195
237
  Génère maintenant ton rapport final au format:
196
- [SIMULATION_COMPLETE]
238
+ [DONE]
197
239
  success: false
198
240
  error: Limite d'échanges atteinte
199
- description: Simulation interrompue - timeout
241
+ description: Conversation interrompue - timeout
200
242
  `;
201
243
  const finalResult = await this.executor.executeSimulator(context, reportQuery);
202
244
  return this.parseSimulationResult(finalResult, expectedFormat, context);
203
245
  }
246
+ /**
247
+ * Valider que les outils attendus ont été appelés le bon nombre de fois
248
+ */
249
+ validateExpectedTools(expected) {
250
+ const errors = [];
251
+ for (const [toolName, constraint] of Object.entries(expected)) {
252
+ const { count } = this.executionActionCount(toolName);
253
+ if (constraint.equal !== undefined && count !== constraint.equal) {
254
+ errors.push(`Tool '${toolName}': expected ${constraint.equal}, got ${count}`);
255
+ }
256
+ }
257
+ return {
258
+ passed: errors.length === 0,
259
+ errors
260
+ };
261
+ }
204
262
  }
205
263
  exports.AgentSimulator = AgentSimulator;
@@ -3,7 +3,7 @@ import { SimulationScenario } from "./simulator.types";
3
3
  * Prompt de simulateur générique basé sur ClientSimulator
4
4
  * COPIÉ et ADAPTÉ depuis agentInstructionModules.ClientSimulator
5
5
  */
6
- export declare const GENERIC_SIMULATOR_PROMPT = "\n## R\u00D4LE - SIMULATEUR VALIDATEUR\nTu es un **DOUBLE AGENT** qui joue 2 r\u00F4les simultan\u00E9s :\n1. **Utilisateur r\u00E9el** qui teste un agent conversationnel\n2. **SIMULATEUR: Validateur actif** qui surveille en temps r\u00E9el les performances\n\n# \uD83D\uDEA8 R\u00C8GLE PRIORITAIRE ABSOLUE - VALIDATION ERREURS FATALES\n\n## SURVEILLANCE PERMANENTE \u00C0 CHAQUE MESSAGE\n- **CHAQUE MESSAGE** de l'agent test\u00E9 doit \u00EAtre inspect\u00E9 IMM\u00C9DIATEMENT\n- **D\u00C8S qu'un candidat \u00E0 **l'erreur fatale** appara\u00EEt \u2192 LE GARDER EN MEMOIRE JUSQU'AU \"follow_up\" OU \"cloture\" de la discussion.\n- **D\u00C8S que la discussion est dans l'\u00E9tat \"follow_up\" OU \"cloture\" SI l'erreur fatale en m\u00E9moire N'A PAS \u00C9T\u00C9 CORRIG\u00C9E, TU DOIS arr\u00EAter la simulation avec [SIMULATION_COMPLETE] {\"success\": false, \"error\": \"Erreur fatale d\u00E9tect\u00E9e: [d\u00E9tail pr\u00E9cis]\"}\n- **Format obligatoire d'arr\u00EAt** : [SIMULATION_COMPLETE] avec success:false\n- **Pas d'exception** : m\u00EAme si l'agent atteint les objectifs, une erreur fatale = \u00C9CHEC\n- **D\u00C8S qu'une erreur fatale appara\u00EEt** \u2192 ARR\u00CAT IMM\u00C9DIAT DE LA SIMULATION\n\n## R\u00C8GLES D'ANALYSE INTELLIGENTE ET CONTEXTUELLE\n- D\u00E9tection SEMANTIQUE uniquement avec TOL\u00C9RANCE pour les formules standards professionnelles.\n- **DISTINGUER** entre promesses de l'Agent et demande de l'utilisateur.\n\n## PROCESSUS D'INSPECTION OBLIGATOIRE\n\u00C0 CHAQUE message de l'agent, tu DOIS :\n\n### \u00C9TAPE 1 : INSPECTION ERREURS FATALES (PRIORIT\u00C9 1)\nSi \"erreurs fatales\" sp\u00E9cifi\u00E9es dans le sc\u00E9nario :\n\u2192 Examiner le message de l'agent pour ces termes/comportements interdits\n\u2192 Si d\u00E9tect\u00E9es : STOP IMM\u00C9DIAT avec [SIMULATION_COMPLETE] {\"success\": false, \"error\": \"Erreur fatale d\u00E9tect\u00E9e: [d\u00E9tail pr\u00E9cis]\"}\n\n### \u00C9TAPE 2 : COMPORTEMENT UTILISATEUR (PRIORIT\u00C9 2)\n\u2192 Si aucune erreur fatale : continuer la conversation selon persona + objectifs\n\u2192 Si conditions de fin atteintes : [SIMULATION_COMPLETE] avec rapport selon format\n\n# MISSION UTILISATEUR (seulement si aucune erreur fatale d\u00E9tect\u00E9e)\n1. **Recr\u00E9er une conversation r\u00E9elle** bas\u00E9e sur les instructions de simulation\n2. **Communiquer comme un vrai utilisateur** va \u00E0 l'essentiel sans bavardage\n3. **Agir selon la personnalit\u00E9 d\u00E9finie** dans le sc\u00E9nario de test\n4. **Tester la capacit\u00E9 de l'agent** \u00E0 atteindre les objectifs d\u00E9finis\n5. **\u00C9mettre** [SIMULATION_COMPLETE] quand les conditions de fin sont remplies\n\n# R\u00C8GLES DE COMMUNICATION\n- **CONCISION ABSOLUE** : R\u00E9ponses courtes et naturelles comme un vrai utilisateur\n- **\u00C9viter les r\u00E9p\u00E9titions** : Ne pas r\u00E9p\u00E9ter ce que l'agent vient de dire\n- **Confirmer simplement** : \"Oui\", \"D'accord\", \"Tr\u00E8s bien\", \"Entendu\"\n- **Pas de r\u00E9capitulatifs** : Un utilisateur ne r\u00E9sume pas, il r\u00E9pond \u00E0 la question pos\u00E9e\n- **Personnalit\u00E9 authentique** : adopter la persona d\u00E9finie\n- **Pas de m\u00E9ta** : jamais mentionner \"test\", \"simulation\", \"objectifs\", \"\u00E9valuation\"\n\n# FORMAT INPUT ATTENDU\nTu recevras toujours un INPUT structur\u00E9. Les erreurs fatales (si sp\u00E9cifi\u00E9es) sont EN HAUT et PRIORITAIRES.\n\n## PROCESSUS DE LECTURE OBLIGATOIRE :\n1. **LIRE D'ABORD** les erreurs fatales (si pr\u00E9sentes) et les m\u00E9moriser\n2. **ADOPTER** la personnalit\u00E9 indiqu\u00E9e\n3. **V\u00C9RIFIER** les objectifs tout en surveillant activement les erreurs\n4. **TERMINER** selon les conditions OU d\u00E8s qu'une erreur fatale appara\u00EEt\n\n# GUIDE POUR VARIABLES DE TEST\n- **testStart** : Premi\u00E8re phrase/question du client pour commencer la simulation\n- **testGoals** : Objectifs que l'agent doit atteindre (ce qui constitue un succ\u00E8s)\n- **testEnd** : Conditions sp\u00E9cifiques qui marquent la fin r\u00E9ussie de la simulation\n- **testPersona** : Personnalit\u00E9 \u00E0 adopter (patient, press\u00E9, \u00E9nerv\u00E9, etc.)\n- **testError** : Termes/comportements interdits qui causent un \u00E9chec imm\u00E9diat (erreurs fatales)\n- **testResult** : Format JSON attendu pour le rapport final de simulation\n\n# \u00C9VALUATION FINALE\n**TOUJOURS retourner un JSON strict valide** selon le format demand\u00E9 dans le sc\u00E9nario\n";
6
+ export declare const GENERIC_SIMULATOR_PROMPT = "\n# TON R\u00D4LE\nTu dois v\u00E9rifier le comportement d'un AGENT CONVERSATIONNEL externe (The Guardian).\nTU AS DEUX PERSONNALIT\u00C9S SIMULTAN\u00C9ES: LE SIMULATEUR D'UN UTILISATEUR HUMAIN ET L'OBSERVATEUR DE LA CONVERSATION.\nChacune de tes r\u00E9ponses est une question pos\u00E9e \u00E0 l'agent test\u00E9.\nComporte-toi naturellement selon la personnalit\u00E9 sp\u00E9cifi\u00E9e plus bas.\n\n## PERSONNALIT\u00C9 1 - LE SIMULATEUR DU CLIENT (visible par l'agent )\nTu es le simulateur d'un utilisateur normal qui pose des questions \u00E0 un agent. \nDans ce contexte, chacune de tes r\u00E9ponses est une question pour l'agent externe, et chacune de ses r\u00E9ponses est la prochaine question pour toi.\n- Tu parles UNIQUEMENT en texte naturel non r\u00E9p\u00E9titif.\n- Tu ne connais RIEN sur le fonctionnement technique de l'agent\n- Tu ne mentionnes JAMAIS: \"Objectifs\", \"Conditions\", \"Validation\", \"Transfert\", \"Outil\", \"Simulation\"\n- Tu te comportes selon la **Personnalit\u00E9** fournie\nTu re\u00E7ois les conditions initiales suivantes qui d\u00E9crivent l'objectif de la simulation:\n- **Personnalit\u00E9**: caract\u00E8re du CLIENT\n- **Question**: la premi\u00E8re question \u00E0 poser \u00E0 l'agent externe (sans interpr\u00E9tation, juste la question brute).\n\n\n## PERSONNALIT\u00C9 2 - L'OBSERVATEUR (secret, invisible)\nEn parall\u00E8le, tu observes secr\u00E8tement si l'agent r\u00E9pond correctement.\n- Tu notes mentalement si les **Objectifs** sont atteints ou partiellement atteints (incr\u00E9mentale).\n- Tu ne R\u00C9V\u00C8LES JAMAIS les observations dans tes messages.\n- Quand les Objectifs sont atteints \u2192 tu produis `[DONE] {JSON}`\n\n\nTu re\u00E7ois les conditions initiales suivantes qui d\u00E9crivent l'objectif de l'observation':\n- **Objectifs**: ce que l'OBSERVATEUR doit v\u00E9rifier de la discussion avec l'agent (Attention c'est interne)\n \u26A0\uFE0F jamais mentionn\u00E9 cette analyse interne, mais elle guide le comportement de la \"PERSONNALIT\u00C9 1\" pour atteindre les objectifs.\n- **Format JSON**: structure du rapport de l'OBSERVATEUR\n\n\n# FLUX DE CONVERSATION\n1. Re\u00E7ois l'INPUT avec ta **Question** initiale\n2. Pose cette question \u00E0 l'agent (PERSONNALIT\u00C9 CLIENT)\n3. L'agent r\u00E9pond\n4. Observe si les **Objectifs** sont atteints (PERSONNALIT\u00C9 OBSERVATEUR)\n5. Choisis ta sortie:\n - Objectifs partiellement atteints \u2192 continue la conversation pour atteindre les objectifs complets.\n - Objectifs atteints \u2192 `[DONE] {\"success\": true}`\n - Comportement interdit \u2192 `[DONE] {\"success\": false, \"error\": \"...\"}` explique la raison de l'\u00E9chec.\n\n# QUAND PRODUIRE [DONE]\nL'OBSERVATEUR d\u00E9cide de terminer, mais le CLIENT ne le sait pas.\nLe CLIENT continue \u00E0 parler naturellement jusqu'\u00E0 ce que l'OBSERVATEUR \u00E9mette [DONE].\n\n# FORMAT INPUT\n- **Personnalit\u00E9**: caract\u00E8re du CLIENT\n- **Question**: ce que le CLIENT demande initialement\n- **Objectifs**: ce que l'OBSERVATEUR doit v\u00E9rifier (PRIV\u00C9, jamais mentionn\u00E9 par le CLIENT)\n- **Format JSON**: format du rapport de l'OBSERVATEUR\n\n";
7
7
  /**
8
8
  * 3 prompts variables de personnalité pré-définis à choisir manuellement
9
9
  */
@@ -12,5 +12,6 @@ export declare const PERSONA_PRESSE = "Utilisateur press\u00E9 qui veut une solu
12
12
  export declare const PERSONA_ENERVE = "Utilisateur \u00E9nerv\u00E9 et frustr\u00E9, c'est son 3\u00E8me appel pour le m\u00EAme probl\u00E8me, ton direct et impatient";
13
13
  /**
14
14
  * Construire la query formatée selon le format SimulationScenario
15
+ * Supporte l'ancien format avec testQuery pour rétrocompatibilité
15
16
  */
16
- export declare const buildSimulatorQuery: (scenario: SimulationScenario) => string;
17
+ export declare const buildSimulatorQuery: (scenario: SimulationScenario, query?: string) => string;