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.
- 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 +42 -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 +4 -0
- package/dist/src/agents/simulator.executor.d.ts +5 -1
- package/dist/src/agents/simulator.executor.js +41 -9
- package/dist/src/agents/simulator.js +86 -28
- package/dist/src/agents/simulator.prompts.d.ts +3 -2
- package/dist/src/agents/simulator.prompts.js +52 -78
- package/dist/src/agents/simulator.types.d.ts +20 -5
- package/dist/src/agents/simulator.utils.d.ts +7 -2
- package/dist/src/agents/simulator.utils.js +33 -11
- package/dist/src/agents/system.js +1 -2
- package/dist/src/execute.d.ts +17 -3
- package/dist/src/execute.js +156 -158
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
- package/dist/src/pricing.llm.js +234 -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 +125 -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 +1378 -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 +1 -0
- package/dist/src/rules/git/git.health.d.ts +57 -0
- package/dist/src/rules/git/git.health.js +281 -1
- package/dist/src/rules/git/index.d.ts +2 -2
- package/dist/src/rules/git/index.js +12 -1
- package/dist/src/rules/git/repo.d.ts +117 -0
- package/dist/src/rules/git/repo.js +536 -0
- 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 +16 -14
- package/dist/src/rules/utils.matter.d.ts +0 -4
- package/dist/src/rules/utils.matter.js +26 -7
- package/dist/src/scrapper.d.ts +15 -22
- package/dist/src/scrapper.js +57 -110
- package/dist/src/stategraph/index.d.ts +1 -1
- package/dist/src/stategraph/stategraph.d.ts +31 -2
- package/dist/src/stategraph/stategraph.js +93 -6
- package/dist/src/stategraph/stategraph.storage.js +4 -0
- package/dist/src/stategraph/types.d.ts +22 -0
- package/dist/src/types.d.ts +4 -2
- package/dist/src/types.js +1 -1
- 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 +60 -126
- package/package.json +7 -2
- 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/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
|
@@ -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
|
|
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?:
|
|
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:
|
|
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: [],
|
|
@@ -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
|
-
|
|
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
|
|
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 [
|
|
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: (
|
|
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:
|
|
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
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
context.lastExecution
|
|
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
|
-
//
|
|
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(
|
|
37
|
+
options.onMessage(initialMsg);
|
|
33
38
|
}
|
|
34
|
-
// Boucle de conversation
|
|
35
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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:
|
|
73
|
+
exchangeCount: exchangeCounter, // Utiliser notre compteur d'échanges
|
|
74
|
+
messages: allMessages
|
|
52
75
|
};
|
|
53
76
|
}
|
|
54
77
|
currentUserQuery = this.extractConversationalPart(simulatorResult);
|
|
55
|
-
//
|
|
56
|
-
if (
|
|
57
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
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[
|
|
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
|
|
236
|
+
La conversation a atteint la limite d'échanges sans conclusion.
|
|
195
237
|
Génère maintenant ton rapport final au format:
|
|
196
|
-
[
|
|
238
|
+
[DONE]
|
|
197
239
|
success: false
|
|
198
240
|
error: Limite d'échanges atteinte
|
|
199
|
-
description:
|
|
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
|
|
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;
|