agentic-api 2.0.26 → 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/README.md +224 -60
- 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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.morsePrompt = exports.haikuPrompt = exports.welcomePrompt = exports.guessWordPrompt = exports.guessNumberPrompt = exports.systemReviewStructurePrompt = exports.systemReviewPrompt = exports.semanticPrompt = void 0;
|
|
4
|
+
const prompts_1 = require("../prompts");
|
|
4
5
|
exports.semanticPrompt = `
|
|
5
6
|
Tu es un expert en extraction sémantique, logique et représentation RDF.
|
|
6
7
|
|
|
@@ -101,71 +102,6 @@ Format de sortie :
|
|
|
101
102
|
|
|
102
103
|
Sois précis, concis, hiérarchique, et logique.
|
|
103
104
|
|
|
104
|
-
`;
|
|
105
|
-
exports.promptMarkdown = `# RÔLE:
|
|
106
|
-
- Tu es un expert en développement de test unitaires avec nodejs et jtest.
|
|
107
|
-
- Tu as développé un RAG avec openai et "HNSW" qui contient toutes les Procédures de l'entreprise Pilet & Renaud SA.
|
|
108
|
-
- Ta mission est de créer une série de tests exhaustifs pour valider que le RAG couvre à 100% le contenu des procédures de l'entreprise.
|
|
109
|
-
- Produire des questions à un coût important, tu dois être efficace, tu dois capturer un maximum de détails (sujet, relation, objet) avec un minimum de questions (maximum 4).
|
|
110
|
-
- Toutes les questions que tu vas créer concernent précisément le INPUT fournit ci-dessous.
|
|
111
|
-
- Pour orienter la formulation des questions, je te fournis quelques exemples de questions réelles.
|
|
112
|
-
- Chaque question doit satisfaire ces critères: clairement identifier le problème à résoudre ou l'action souhaitée dans un domaine précis, doit être spécifique et ne peut pas être ambiguë.
|
|
113
|
-
- En moyenne, chaque question doit être au maximum de 15 mots, mais tu peux en produire aussi des plus courtes (20%) pour élargir le champ des tests.
|
|
114
|
-
- La réponse contient la liste de mots très spécifiques à la procédure séparés par des virgules.
|
|
115
|
-
- Si la réponse concerne un schéma, une procédure ou l'utilisation d'un logiciel, tu dois décrire la procédure précisément.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
# EXEMPLES de formulation utilisées par les collaborateurs l'entreprise (attention à ne pas utiliser ces exemples si le sujet du INPUT´est différent).
|
|
119
|
-
- Écoulement bouché, que faire ?
|
|
120
|
-
- J’ai une fuite depuis le plafond de ma chambre, j’aimerais un sanitaire
|
|
121
|
-
- Mon frigo ne fonctionne pas, pouvez-vous mandater quelqu’un ?
|
|
122
|
-
- Mon store est resté bloqué, pouvez-vous faire quelque chose ?
|
|
123
|
-
- J’aimerais faire reproduire des clés, comment faire ? combien ça coûte ?
|
|
124
|
-
- Je suis fournisseur, ma facture n’est toujours pas payée par Pilet et Renaud.
|
|
125
|
-
- J’ai payé mon loyer, mais j’ai reçu un rappel, pourquoi ?
|
|
126
|
-
- Je paie toujours bien mon loyer, pouvez-vous supprimer les frais de rappel c’est la première fois que j’ai du retard.
|
|
127
|
-
- Est-ce que cet appartement est toujours disponible ? Comment déposer un dossier?
|
|
128
|
-
- Est-ce que mon dossier de candidature est retenu ? j’aimerais des infos.
|
|
129
|
-
- Inscription de korkmaz?
|
|
130
|
-
- J’ai reçu un appel manqué de la régie mais je ne sais pas qui a tenté de me joindre.
|
|
131
|
-
- Un fournisseur me dit que sa facture n’est toujours pas payée par Pilet et Renaud. Comment je vérifie ça?
|
|
132
|
-
- Comment créer un bon ?
|
|
133
|
-
- Quelles sont les tâches à faire après avoir conclu un contrat d’entretien ?
|
|
134
|
-
- Une entreprise souhaite travailler avec nous, que dois-je faire ?
|
|
135
|
-
|
|
136
|
-
# QUESTIONS A EVITER: Les exemples qui ne sont pas pertinents pour le RAG (les documents sont tous concernés par ces questions, c'est donc inutile de les inclure dans les tests).
|
|
137
|
-
- Ce document contient-il des liens externes ?
|
|
138
|
-
- Cette absence de liens affecte-t-elle la validité du document ?
|
|
139
|
-
- Qui doit valider les changements dans la procédure ?
|
|
140
|
-
- Comment valider une modification de procédure ?
|
|
141
|
-
|
|
142
|
-
# DICTIONNAIRE (jargon de l'entreprise):
|
|
143
|
-
- Logiciels Spécifiques: Quorum, MFiles, Base de connaissance, Teams, HomePad, Todoist, Mammutt, E-banking, INCH, Ecopartage, Immowise.
|
|
144
|
-
- SGC: Service de Gestion de la Clientèle
|
|
145
|
-
- GED: service qui gère le scan des documents, la mise sous plis, l’économat, le réassort des salles de pauses, la saisie des données pour orienter les documents dans M-Files
|
|
146
|
-
- MED: Mise en demeure.
|
|
147
|
-
- WC: Toilettes.
|
|
148
|
-
- M-Files: logiciel de gestion de documents
|
|
149
|
-
- PR ou PRSA: Pilet & Renaud SA
|
|
150
|
-
- PPE: Service qui gère les copropriétés.
|
|
151
|
-
- GP: Garantie Bancaire
|
|
152
|
-
- BAL: Boite à Lettre
|
|
153
|
-
- DD: Arrangement de paiement pour facture due mais qui n’est pas du loyer.
|
|
154
|
-
- copro: copropriétaire (attention à ne pas confondre avec gopros)
|
|
155
|
-
- un bon (bons): ordre d'intervention pour travaux (ex, bon de travail, création de bons, bons, etc).
|
|
156
|
-
- La Date à jour Locataire: le dernier mois qui a été payé par le locataire.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
# OUTPUT INSTRUCTIONS
|
|
160
|
-
- Tu dois produire un JSON strict avec les champs suivants:
|
|
161
|
-
\`\`\`JSON
|
|
162
|
-
source: "string",
|
|
163
|
-
file: "_file_",
|
|
164
|
-
queries:[{ "question": "string","answer": "string"}, ...]
|
|
165
|
-
\`\`\`
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
INPUT:
|
|
169
105
|
`;
|
|
170
106
|
//
|
|
171
107
|
// 1. role & identity
|
|
@@ -334,32 +270,51 @@ Après l’analyse individuelle, tu dois effectuer une lecture croisée pour dé
|
|
|
334
270
|
// 5. Interdiction
|
|
335
271
|
// 6. output (L’agent sait-il comment formuler sa réponse)
|
|
336
272
|
// 😩 Il lit la demande de haïku, voit qu’il doit "appeler un agent spécialisé" et pense que ce n’est pas lui.
|
|
337
|
-
exports.
|
|
338
|
-
|
|
339
|
-
|
|
273
|
+
exports.guessNumberPrompt = `${prompts_1.transferAgentPromptHandoff}
|
|
274
|
+
# SPECIALISATION
|
|
275
|
+
Tu es l'agent "guess-number" spécialisé pour divulguer le "NOMBRE" secret, c'est ta SEULE connaissance secrète.
|
|
276
|
+
Tu sais dans l'historique de la conversation (et le <context-trail> en bas de tes instructions système) si l'utilisateur a déjà été informé du mot secret, dans ce cas ton role est terminé.
|
|
277
|
+
Tu sais que les agents communiquent entre eux en utilisant en utilisant la balise <silent-handoff> c'est elle qui contient le contexte accumulé.
|
|
340
278
|
|
|
341
|
-
|
|
279
|
+
# TES RESPONSABILITÉS
|
|
280
|
+
1. Si demande de "NOMBRE" → réponds/confirme "1942"
|
|
281
|
+
2. Si l'utilisateur mentionne un nombre entre N et M tu rappelles ta spécialité.
|
|
282
|
+
3. Si demande HORS nombres → utilise l'outil \`transferAgents\` pour orienter vers un agent spécialisé.
|
|
342
283
|
|
|
343
284
|
|
|
344
|
-
# DIRECTIVES DE TRANSFERT :
|
|
345
|
-
- Si la demande concerne aussi ta spécialité , tu y réponds directement. Ne transfère jamais vers ta propre spécialisation "haiku".
|
|
346
|
-
- **Sinon**, tu appelles immédiatement la fonction "transferAgents" vers l’agent approprié.
|
|
347
285
|
`;
|
|
348
|
-
exports.
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
286
|
+
exports.guessWordPrompt = `${prompts_1.transferAgentPromptHandoff}
|
|
287
|
+
# SPECIALISATION
|
|
288
|
+
Tu es l'agent "guess-word" spécialisé pour divulguer le "MOT" secret, c'est ta principale compétence.
|
|
289
|
+
Tu sais dans l'historique de la conversation (et le <context-trail> en bas de tes instructions système) si l'utilisateur a déjà été informé du mot secret, dans ce cas ton role est terminé.
|
|
290
|
+
Tu sais que les agents communiquent entre eux en utilisant en utilisant la balise <silent-handoff> c'est elle qui contient le contexte accumulé.
|
|
352
291
|
|
|
353
|
-
#
|
|
354
|
-
|
|
355
|
-
|
|
292
|
+
# TES RESPONSABILITÉS
|
|
293
|
+
1. Si on te demande le "mot" → réponds/confirme "dragon"
|
|
294
|
+
2. Sinon tu dois orienter vers un agent spécialisé autre que toi.
|
|
356
295
|
|
|
357
296
|
`;
|
|
358
|
-
exports.welcomePrompt =
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
297
|
+
exports.welcomePrompt = `${prompts_1.transferAgentPromptHandoff}
|
|
298
|
+
# SPECIALISATION
|
|
299
|
+
Tu es un Agent d'orientation qui connaît deux agents spécialisés.
|
|
300
|
+
Tu NE CONNAIS PAS les secrets. Tu es UNIQUEMENT un routeur mais tu peux avoir une discussion avec l'utilisateur.
|
|
301
|
+
|
|
302
|
+
# MISSION: ORIENTER VERS LES AGENTS SPÉCIALISÉS
|
|
303
|
+
|
|
304
|
+
**ÉTAPE 1 - CONSULTER LE <context-trail> (en bas de tes instructions système) :**
|
|
305
|
+
- Cherche "orientation → guess-word" → si présent, guess-word déjà appelé
|
|
306
|
+
- Cherche "orientation → guess-number" → si présent, guess-number déjà appelé
|
|
307
|
+
|
|
308
|
+
**ÉTAPE 2 - DÉCIDER :**
|
|
309
|
+
- Question NOMBRE + "orientation → guess-number" PAS dans trail → appelle transferAgents vers "guess-number"
|
|
310
|
+
- Question MOT + "orientation → guess-word" PAS dans trail → appelle transferAgents vers "guess-word"
|
|
311
|
+
- Si agent déjà dans trail → NE PAS transférer, réponds "J'ai déjà orienté vers cet agent"
|
|
312
|
+
|
|
313
|
+
# RÈGLE ABSOLUE
|
|
314
|
+
- EN cas d'indécision, tu es l'agent avec qui l'utilisateur discute.
|
|
315
|
+
- Tu transfères MAX 1 fois par agent
|
|
316
|
+
- INTERDIT : Transférer si "orientation → <destination>" déjà dans trail
|
|
365
317
|
`;
|
|
318
|
+
// Legacy exports for backward compatibility (tests may use these)
|
|
319
|
+
exports.haikuPrompt = exports.guessNumberPrompt;
|
|
320
|
+
exports.morsePrompt = exports.guessWordPrompt;
|
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MapLLM - Simple hierarchical reducer with native loaders
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
4
|
+
import type { AgentConfig } from '../types';
|
|
5
|
+
import type { NativeLoader, MapLLMReduceResult } from './reducer.types';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for agent-based execution mode
|
|
8
|
+
*/
|
|
9
|
+
export interface AgentReducerConfig {
|
|
10
|
+
/** Agent configurations available for execution */
|
|
11
|
+
agents: AgentConfig[];
|
|
12
|
+
/** Default agent name to use if task doesn't specify one */
|
|
13
|
+
defaultAgent: string;
|
|
14
|
+
}
|
|
5
15
|
/**
|
|
6
16
|
* MapLLM - Orchestrateur principal pour le reduce hiérarchique
|
|
7
17
|
*/
|
|
8
18
|
export declare class MapLLM {
|
|
9
19
|
private loader;
|
|
20
|
+
private agentConfig?;
|
|
10
21
|
constructor(loader: NativeLoader);
|
|
11
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Vérifie si le loader fournit des agents (TaskListLoader)
|
|
24
|
+
*/
|
|
25
|
+
private hasAgents;
|
|
26
|
+
reduce(callback: (result: MapLLMReduceResult, currentValue: string | object) => MapLLMReduceResult, init: MapLLMReduceResult): Promise<MapLLMReduceResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Helper privé pour parsing Task depuis chunk content
|
|
29
|
+
*
|
|
30
|
+
* @param content - JSON string ou texte brut
|
|
31
|
+
* @returns Task object avec prompt
|
|
32
|
+
*/
|
|
33
|
+
private parseTask;
|
|
12
34
|
}
|
|
@@ -12,13 +12,34 @@ const utils_1 = require("../utils");
|
|
|
12
12
|
class MapLLM {
|
|
13
13
|
constructor(loader) {
|
|
14
14
|
this.loader = loader;
|
|
15
|
+
//
|
|
16
|
+
// ✅ Si pas d'agentConfig fourni, essayer d'extraire depuis le loader
|
|
17
|
+
if (this.hasAgents(loader)) {
|
|
18
|
+
const agentLoader = loader;
|
|
19
|
+
this.agentConfig = {
|
|
20
|
+
agents: agentLoader.agents,
|
|
21
|
+
defaultAgent: agentLoader.agents[0]?.name || 'default'
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Vérifie si le loader fournit des agents (TaskListLoader)
|
|
27
|
+
*/
|
|
28
|
+
hasAgents(loader) {
|
|
29
|
+
return loader && Array.isArray(loader.agents);
|
|
15
30
|
}
|
|
16
|
-
async reduce(
|
|
31
|
+
async reduce(callback, init) {
|
|
17
32
|
const startTime = Date.now();
|
|
33
|
+
//
|
|
34
|
+
// ✅ Extraire config depuis init (optionnel - si absent, continuer sans)
|
|
35
|
+
const config = init.config;
|
|
36
|
+
if (!config) {
|
|
37
|
+
throw new Error('config is required in MapLLMReduceResult.config');
|
|
38
|
+
}
|
|
18
39
|
// Merge init with defaults
|
|
19
40
|
let result = { ...init, ...{
|
|
20
41
|
continue: false,
|
|
21
|
-
model: init.model || (
|
|
42
|
+
model: init.model || ("LOW-fast"),
|
|
22
43
|
metadata: {
|
|
23
44
|
iterations: 0,
|
|
24
45
|
averageChunkSize: 0,
|
|
@@ -32,8 +53,9 @@ class MapLLM {
|
|
|
32
53
|
let position = 0;
|
|
33
54
|
let totalChunkSize = 0;
|
|
34
55
|
let totalReduce = 0;
|
|
56
|
+
const model = (0, execute_1.modelConfig)(result.model);
|
|
35
57
|
const openai = (0, utils_1.openaiInstance)();
|
|
36
|
-
const llm = Object.assign({},
|
|
58
|
+
const llm = Object.assign({}, model);
|
|
37
59
|
llm.stream = false;
|
|
38
60
|
delete llm.stream_options;
|
|
39
61
|
//
|
|
@@ -51,46 +73,91 @@ class MapLLM {
|
|
|
51
73
|
totalChunkSize += chunk.content.length;
|
|
52
74
|
// Update position immediately after loading (before any continue)
|
|
53
75
|
position = chunk.position;
|
|
54
|
-
// 2. Digest chunk
|
|
55
|
-
// Simple message array without memory manager - but preserve conversation
|
|
56
|
-
// Prepare messages based on acc type and content
|
|
76
|
+
// 2. Digest chunk - BRANCHE SELON MODE
|
|
57
77
|
const isFirstChunk = (typeof result.acc === 'string' && result.acc.length === 0) ||
|
|
58
78
|
(typeof result.acc === 'object' && Object.keys(result.acc).length === 0);
|
|
59
79
|
const accContent = typeof result.acc === 'string' ? result.acc : JSON.stringify(result.acc);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
let digestContent;
|
|
81
|
+
if (this.agentConfig) {
|
|
82
|
+
//
|
|
83
|
+
// ═══════════════════════════════════════
|
|
84
|
+
// MODE AGENT : executeAgent() avec tools
|
|
85
|
+
// ═══════════════════════════════════════
|
|
86
|
+
const task = this.parseTask(chunk.content);
|
|
87
|
+
const agentName = task.agentName || this.agentConfig.defaultAgent;
|
|
88
|
+
const agent = this.agentConfig.agents.find(a => a.name === agentName);
|
|
89
|
+
if (!agent) {
|
|
90
|
+
throw new Error(`Agent ${agentName} not found`);
|
|
91
|
+
}
|
|
92
|
+
//
|
|
93
|
+
// Build agent config with task-specific tools if provided
|
|
94
|
+
const taskAgent = task.tools ? {
|
|
95
|
+
...agent,
|
|
96
|
+
tools: [...(agent.tools || []), ...task.tools]
|
|
97
|
+
} : agent;
|
|
98
|
+
//
|
|
99
|
+
// force model for this task
|
|
100
|
+
if (task.model) {
|
|
101
|
+
taskAgent.model = task.model;
|
|
102
|
+
}
|
|
103
|
+
//
|
|
104
|
+
// Prepare query with context
|
|
105
|
+
const fullQuery = isFirstChunk
|
|
106
|
+
? `${config.digestPrompt}\n\n${task.prompt}`
|
|
107
|
+
: `${config.digestPrompt}\n\nPrevious context:\n${accContent}\n\nCurrent task:\n${task.prompt}`;
|
|
108
|
+
//
|
|
109
|
+
// Execute task with executeAgent
|
|
110
|
+
const execResult = await (0, execute_1.executeAgent)([taskAgent], {
|
|
111
|
+
query: fullQuery,
|
|
112
|
+
home: agentName,
|
|
113
|
+
stdout: init.stdout || execute_1.DummyWritable,
|
|
114
|
+
verbose: verbose,
|
|
115
|
+
debug: false
|
|
116
|
+
});
|
|
117
|
+
digestContent = execResult.content;
|
|
79
118
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
119
|
+
else {
|
|
120
|
+
//
|
|
121
|
+
// ══════════════════════════════════════
|
|
122
|
+
// MODE DOCUMENT : openai.chat direct
|
|
123
|
+
// ══════════════════════════════════════
|
|
124
|
+
const messages = isFirstChunk ? [
|
|
125
|
+
{ role: "system", content: config.digestPrompt },
|
|
126
|
+
{ role: "user", content: chunk.content }
|
|
127
|
+
] : [
|
|
128
|
+
{ role: "system", content: config.digestPrompt },
|
|
129
|
+
{ role: "assistant", content: accContent },
|
|
130
|
+
{ role: "user", content: chunk.content }
|
|
131
|
+
];
|
|
132
|
+
llm.messages = messages;
|
|
133
|
+
//
|
|
134
|
+
// Configure structured output if format is specified
|
|
135
|
+
if (result.format) {
|
|
136
|
+
llm.response_format = {
|
|
137
|
+
type: "json_schema",
|
|
138
|
+
json_schema: {
|
|
139
|
+
name: result.format.name,
|
|
140
|
+
schema: result.format.schema,
|
|
141
|
+
strict: result.format.strict ?? true
|
|
142
|
+
}
|
|
143
|
+
};
|
|
87
144
|
}
|
|
88
|
-
|
|
89
|
-
|
|
145
|
+
const chat = await openai.chat.completions.create(llm);
|
|
146
|
+
const digestMessage = chat.choices[0]?.message;
|
|
147
|
+
//
|
|
148
|
+
// Parse JSON if structured output is enabled
|
|
149
|
+
digestContent = digestMessage.content || '';
|
|
150
|
+
if (result.format && digestContent) {
|
|
151
|
+
try {
|
|
152
|
+
digestContent = JSON.parse(digestContent);
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
console.warn('Failed to parse structured output as JSON:', digestContent);
|
|
156
|
+
}
|
|
90
157
|
}
|
|
91
158
|
}
|
|
92
159
|
//
|
|
93
|
-
// the reduce callback operates the process of digesting and accumulating
|
|
160
|
+
// the reduce callback operates the process of digesting and accumulating
|
|
94
161
|
result = callback(result, digestContent);
|
|
95
162
|
if (result.maxIterations) {
|
|
96
163
|
throw new Error(`Maximum iterations (${result.metadata?.iterations}) reached without completion`);
|
|
@@ -203,5 +270,28 @@ class MapLLM {
|
|
|
203
270
|
}
|
|
204
271
|
return result;
|
|
205
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* Helper privé pour parsing Task depuis chunk content
|
|
275
|
+
*
|
|
276
|
+
* @param content - JSON string ou texte brut
|
|
277
|
+
* @returns Task object avec prompt
|
|
278
|
+
*/
|
|
279
|
+
parseTask(content) {
|
|
280
|
+
try {
|
|
281
|
+
const parsed = JSON.parse(content);
|
|
282
|
+
if (parsed.id && parsed.prompt) {
|
|
283
|
+
return parsed;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Not JSON or invalid Task format
|
|
288
|
+
}
|
|
289
|
+
//
|
|
290
|
+
// Fallback : traiter comme prompt direct
|
|
291
|
+
return {
|
|
292
|
+
id: 'direct',
|
|
293
|
+
prompt: content
|
|
294
|
+
};
|
|
295
|
+
}
|
|
206
296
|
}
|
|
207
297
|
exports.MapLLM = MapLLM;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Native Loaders for MapLLM
|
|
3
3
|
*/
|
|
4
|
-
import type { NativeLoader, ChunkStrategy } from './reducer.types';
|
|
4
|
+
import type { NativeLoader, ChunkStrategy, Task, Job } from './reducer.types';
|
|
5
|
+
import type { AgentConfig } from '../types';
|
|
5
6
|
/**
|
|
6
7
|
* FileNativeLoader - Loader pour fichiers avec chunking par lignes
|
|
7
8
|
*/
|
|
@@ -32,3 +33,56 @@ export declare class StringNativeLoader implements NativeLoader {
|
|
|
32
33
|
private chunkByLines;
|
|
33
34
|
private chunkByParagraphs;
|
|
34
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* TaskListLoader - Loader pour exécution séquentielle de tâches
|
|
38
|
+
* Compatible avec NativeLoader pour réutiliser la logique de MapLLM
|
|
39
|
+
* Job = TaskListLoader (pas de type séparé)
|
|
40
|
+
*/
|
|
41
|
+
export declare class TaskListLoader implements NativeLoader {
|
|
42
|
+
private _id;
|
|
43
|
+
private _tasks;
|
|
44
|
+
private _agents;
|
|
45
|
+
private _description;
|
|
46
|
+
/**
|
|
47
|
+
* Constructeur principal - crée un nouveau Job avec ID auto-généré
|
|
48
|
+
* @param tasks Liste des tâches
|
|
49
|
+
* @param agents Liste des agents matérialisés
|
|
50
|
+
* @param description Description du Job (optionnel)
|
|
51
|
+
*/
|
|
52
|
+
constructor(tasks: Task[], agents: AgentConfig[], description?: string);
|
|
53
|
+
/**
|
|
54
|
+
* ✅ Restaure depuis Job avec liste d'agents matérialisés
|
|
55
|
+
* @param job Job sérialisé (agents = string[])
|
|
56
|
+
* @param availableAgents Liste d'agents matérialisés pour reconstruction
|
|
57
|
+
*/
|
|
58
|
+
static fromJob(job: Job, availableAgents: AgentConfig[]): TaskListLoader;
|
|
59
|
+
/**
|
|
60
|
+
* ✅ Méthode static pour charger depuis OneDrive
|
|
61
|
+
* @param credential Token credential
|
|
62
|
+
* @param jobId ID du Job à charger
|
|
63
|
+
* @param availableAgents Liste d'agents matérialisés
|
|
64
|
+
*/
|
|
65
|
+
static loadJob(credential: any, jobId: string, availableAgents: AgentConfig[]): Promise<TaskListLoader | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Getters
|
|
68
|
+
*/
|
|
69
|
+
get id(): string;
|
|
70
|
+
get tasks(): Task[];
|
|
71
|
+
get agents(): AgentConfig[];
|
|
72
|
+
get description(): string;
|
|
73
|
+
get label(): string;
|
|
74
|
+
/**
|
|
75
|
+
* Ajoute une tâche (agent et model optionnels)
|
|
76
|
+
* @param task Tâche sans ID (auto-généré)
|
|
77
|
+
*/
|
|
78
|
+
addTask(task: Omit<Task, 'id'>): void;
|
|
79
|
+
/**
|
|
80
|
+
* ✅ Retourne Job sérialisable (AgentConfig → string[])
|
|
81
|
+
*/
|
|
82
|
+
toJob(): Job;
|
|
83
|
+
loadNativeChunk(position: number): Promise<{
|
|
84
|
+
content: string;
|
|
85
|
+
eof: boolean;
|
|
86
|
+
position: number;
|
|
87
|
+
}>;
|
|
88
|
+
}
|
|
@@ -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
|
+
}
|