agentic-api 2.0.491 → 2.0.592
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 +37 -34
- package/dist/src/agents/job.runner.d.ts +130 -0
- package/dist/src/agents/job.runner.js +339 -0
- package/dist/src/agents/reducer.core.d.ts +11 -1
- package/dist/src/agents/reducer.core.js +76 -86
- package/dist/src/agents/reducer.d.ts +1 -0
- package/dist/src/agents/reducer.factory.d.ts +46 -0
- package/dist/src/agents/reducer.factory.js +154 -0
- package/dist/src/agents/reducer.js +1 -0
- package/dist/src/agents/simulator.d.ts +26 -1
- package/dist/src/agents/simulator.dashboard.d.ts +140 -0
- package/dist/src/agents/simulator.dashboard.js +344 -0
- package/dist/src/agents/simulator.js +56 -0
- package/dist/src/agents/simulator.types.d.ts +38 -6
- package/dist/src/agents/simulator.utils.d.ts +22 -1
- package/dist/src/agents/simulator.utils.js +27 -0
- package/dist/src/execute/helpers.js +2 -2
- package/dist/src/execute/modelconfig.d.ts +21 -11
- package/dist/src/execute/modelconfig.js +29 -13
- package/dist/src/execute/responses.js +8 -7
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.js +21 -1
- package/dist/src/llm/config.d.ts +25 -0
- package/dist/src/llm/config.js +38 -0
- package/dist/src/llm/index.d.ts +48 -0
- package/dist/src/llm/index.js +115 -0
- package/dist/src/llm/openai.d.ts +6 -0
- package/dist/src/llm/openai.js +154 -0
- package/dist/src/llm/pricing.d.ts +26 -0
- package/dist/src/llm/pricing.js +129 -0
- package/dist/src/llm/xai.d.ts +17 -0
- package/dist/src/llm/xai.js +90 -0
- package/dist/src/pricing.llm.d.ts +3 -15
- package/dist/src/pricing.llm.js +10 -251
- package/dist/src/prompts.d.ts +0 -1
- package/dist/src/prompts.js +51 -118
- package/dist/src/rag/embeddings.d.ts +5 -1
- package/dist/src/rag/embeddings.js +15 -5
- package/dist/src/rag/parser.js +1 -1
- package/dist/src/rag/rag.manager.d.ts +44 -6
- package/dist/src/rag/rag.manager.js +138 -49
- package/dist/src/rag/types.d.ts +2 -0
- package/dist/src/rag/usecase.js +8 -11
- package/dist/src/rules/git/git.health.js +59 -4
- package/dist/src/rules/git/repo.d.ts +11 -4
- package/dist/src/rules/git/repo.js +64 -18
- package/dist/src/rules/git/repo.pr.d.ts +8 -0
- package/dist/src/rules/git/repo.pr.js +45 -1
- package/dist/src/rules/git/repo.tools.d.ts +5 -1
- package/dist/src/rules/git/repo.tools.js +54 -7
- package/dist/src/rules/types.d.ts +14 -0
- package/dist/src/rules/utils.matter.d.ts +0 -20
- package/dist/src/rules/utils.matter.js +42 -74
- package/dist/src/scrapper.js +2 -2
- package/dist/src/utils.d.ts +0 -8
- package/dist/src/utils.js +1 -28
- package/package.json +1 -1
|
@@ -10,6 +10,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const types_1 = require("./types");
|
|
11
11
|
const parser_1 = require("./parser");
|
|
12
12
|
const utils_1 = require("../utils");
|
|
13
|
+
const llm_1 = require("../llm");
|
|
14
|
+
const modelconfig_1 = require("../execute/modelconfig");
|
|
13
15
|
const usecase_1 = require("./usecase");
|
|
14
16
|
class Embeddings {
|
|
15
17
|
constructor(config) {
|
|
@@ -22,6 +24,7 @@ class Embeddings {
|
|
|
22
24
|
this.distance = config.distance || 'cosine';
|
|
23
25
|
this.inmemory = config.inmemory || false;
|
|
24
26
|
this.debug = false;
|
|
27
|
+
this.provider = config.provider || 'openai';
|
|
25
28
|
// Charger l'index existant si disponible et pas en mode inmemory
|
|
26
29
|
if (!this.inmemory && (0, fs_1.existsSync)(this.vectorsFile)) {
|
|
27
30
|
this.loadIndex();
|
|
@@ -127,14 +130,19 @@ class Embeddings {
|
|
|
127
130
|
};
|
|
128
131
|
}
|
|
129
132
|
/**
|
|
130
|
-
* Recherche sémantique avec
|
|
133
|
+
* Recherche sémantique avec le provider de l'embedding
|
|
134
|
+
* @param question La question à rechercher
|
|
135
|
+
* @param options Options de recherche
|
|
136
|
+
* @returns Les résultats de la recherche
|
|
131
137
|
*/
|
|
132
138
|
async semanticSearch(question, options = {}) {
|
|
133
139
|
const startTime = Date.now();
|
|
134
|
-
const
|
|
140
|
+
const provider = this.provider;
|
|
141
|
+
const openai = (0, llm_1.llmInstance)({ provider });
|
|
142
|
+
const embeddingConfig = (0, modelconfig_1.modelConfig)("EMBEDDING-small", { provider });
|
|
135
143
|
// Créer l'embedding de la question
|
|
136
144
|
const embedding = await openai.embeddings.create({
|
|
137
|
-
model:
|
|
145
|
+
model: embeddingConfig.model,
|
|
138
146
|
input: question,
|
|
139
147
|
dimensions: this.space,
|
|
140
148
|
encoding_format: 'float',
|
|
@@ -263,7 +271,9 @@ class Embeddings {
|
|
|
263
271
|
const m = options?.m || this.config.hnswConfig?.m || 32;
|
|
264
272
|
const isUpdate = options?.update || false;
|
|
265
273
|
const prepare = options?.prepare || ((input) => input);
|
|
266
|
-
const
|
|
274
|
+
const provider = this.provider;
|
|
275
|
+
const openai = (0, llm_1.llmInstance)({ provider });
|
|
276
|
+
const embeddingConfig = (0, modelconfig_1.modelConfig)("EMBEDDING-small", { provider });
|
|
267
277
|
const vectors = {};
|
|
268
278
|
const documentRefs = {};
|
|
269
279
|
const documentReferences = {};
|
|
@@ -304,7 +314,7 @@ class Embeddings {
|
|
|
304
314
|
}
|
|
305
315
|
// Créer l'embedding de la section
|
|
306
316
|
const embedding = await openai.embeddings.create({
|
|
307
|
-
model:
|
|
317
|
+
model: embeddingConfig.model,
|
|
308
318
|
input: prepare(section.content),
|
|
309
319
|
dimensions: this.space,
|
|
310
320
|
encoding_format: "float",
|
package/dist/src/rag/parser.js
CHANGED
|
@@ -34,7 +34,7 @@ function getSections(content, filename) {
|
|
|
34
34
|
content = contentWithoutMatter || content;
|
|
35
35
|
//
|
|
36
36
|
// le contenu est toujours sans le front-matter!
|
|
37
|
-
const rawSections = content.split('
|
|
37
|
+
const rawSections = content.split('\n---\n').map(section => section.trim());
|
|
38
38
|
if (!rawSections.length) {
|
|
39
39
|
return {
|
|
40
40
|
filename,
|
|
@@ -47,6 +47,9 @@ export declare class RAGManager {
|
|
|
47
47
|
/**
|
|
48
48
|
* Notifie les embeddings chargés de se mettre à jour
|
|
49
49
|
*
|
|
50
|
+
* Cette méthode est publique pour permettre aux applications de notifier
|
|
51
|
+
* les utilisateurs actifs du RAG (tools, search) qu'il a été mis à jour.
|
|
52
|
+
*
|
|
50
53
|
* @param name Nom du RAG à mettre à jour
|
|
51
54
|
* @param opts Options de mise à jour (action: 'rename' pour renommer un document)
|
|
52
55
|
*
|
|
@@ -59,18 +62,22 @@ export declare class RAGManager {
|
|
|
59
62
|
*
|
|
60
63
|
* @example
|
|
61
64
|
* ```typescript
|
|
62
|
-
* // Après un build
|
|
63
|
-
*
|
|
65
|
+
* // Après un build externe
|
|
66
|
+
* ragManager.notifyUpdate('procedures-stable');
|
|
64
67
|
*
|
|
65
68
|
* // Après un rename de document
|
|
66
|
-
*
|
|
69
|
+
* ragManager.notifyUpdate('procedures-stable', {
|
|
67
70
|
* action: 'rename',
|
|
68
71
|
* oldFile: 'old.md',
|
|
69
72
|
* newFile: 'new.md'
|
|
70
73
|
* });
|
|
71
74
|
* ```
|
|
72
75
|
*/
|
|
73
|
-
|
|
76
|
+
notifyUpdate(name: string, opts?: {
|
|
77
|
+
action?: 'rename';
|
|
78
|
+
oldFile?: string;
|
|
79
|
+
newFile?: string;
|
|
80
|
+
}): void;
|
|
74
81
|
/**
|
|
75
82
|
* Génère un nom d'archive avec timestamp YYYMMDD
|
|
76
83
|
*/
|
|
@@ -161,6 +168,15 @@ export declare class RAGManager {
|
|
|
161
168
|
* ```
|
|
162
169
|
*/
|
|
163
170
|
addDocument(name: string, filename: string, content: string): void;
|
|
171
|
+
/**
|
|
172
|
+
* Marque un document comme entièrement traité (enhanced + query.json générés)
|
|
173
|
+
* Le .sha est écrit APRÈS le traitement complet pour garantir la cohérence
|
|
174
|
+
*
|
|
175
|
+
* @param name Nom du RAG
|
|
176
|
+
* @param filename Nom du fichier (ex: 'procedure.md')
|
|
177
|
+
* @param content Contenu du document traité
|
|
178
|
+
*/
|
|
179
|
+
markDocumentProcessed(name: string, filename: string, content: string): void;
|
|
164
180
|
/**
|
|
165
181
|
* Prépare un RAG enfant en copiant les documents d'un RAG parent
|
|
166
182
|
*
|
|
@@ -242,6 +258,26 @@ export declare class RAGManager {
|
|
|
242
258
|
* ```
|
|
243
259
|
*/
|
|
244
260
|
loadUseCases(name: string, filename: string): DocumentQueries;
|
|
261
|
+
/**
|
|
262
|
+
* Charge tous les use cases de tous les documents d'un RAG
|
|
263
|
+
*
|
|
264
|
+
* Utilise le fichier rag-metadata.json pour obtenir la liste des documents valides
|
|
265
|
+
* puis charge chaque fichier .query.json correspondant
|
|
266
|
+
*
|
|
267
|
+
* @param name Nom du RAG
|
|
268
|
+
* @returns Objet contenant tous les use cases par document
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* const allQueries = ragManager.loadAllUseCases('my-rag');
|
|
273
|
+
* console.log(`${Object.keys(allQueries.documents).length} documents avec use cases`);
|
|
274
|
+
* console.log(`${allQueries.totalQueries} questions au total`);
|
|
275
|
+
* ```
|
|
276
|
+
*/
|
|
277
|
+
loadAllUseCases(name: string): {
|
|
278
|
+
documents: Record<string, DocumentQueries>;
|
|
279
|
+
totalQueries: number;
|
|
280
|
+
};
|
|
245
281
|
/**
|
|
246
282
|
* Construit un RAG de manière atomique
|
|
247
283
|
*
|
|
@@ -274,7 +310,7 @@ export declare class RAGManager {
|
|
|
274
310
|
/**
|
|
275
311
|
* Supprime un RAG du registre
|
|
276
312
|
*/
|
|
277
|
-
delete(name: string, archiveFlag?: boolean): Promise<void>;
|
|
313
|
+
delete(name: string, archiveFlag?: boolean): Promise<void | Error>;
|
|
278
314
|
/**
|
|
279
315
|
* Renomme un document dans un RAG existant
|
|
280
316
|
*
|
|
@@ -306,7 +342,8 @@ export declare class RAGManager {
|
|
|
306
342
|
*/
|
|
307
343
|
private updateJSONReferences;
|
|
308
344
|
/**
|
|
309
|
-
* Renomme un RAG existant
|
|
345
|
+
* Renomme un RAG existant (nom dans le registre uniquement)
|
|
346
|
+
* Le dossier physique n'est PAS modifié, seul le nom dans la config change.
|
|
310
347
|
*
|
|
311
348
|
* @param from Nom actuel du RAG
|
|
312
349
|
* @param to Nouveau nom du RAG
|
|
@@ -316,6 +353,7 @@ export declare class RAGManager {
|
|
|
316
353
|
* @example
|
|
317
354
|
* ```typescript
|
|
318
355
|
* await ragManager.rename('old-name', 'new-name', 'Description mise à jour');
|
|
356
|
+
* // Le dossier reste /path/to/old-name mais le RAG s'appelle 'new-name'
|
|
319
357
|
* ```
|
|
320
358
|
*/
|
|
321
359
|
rename(from: string, to: string, description?: string): Promise<void>;
|
|
@@ -53,12 +53,19 @@ class RAGManager {
|
|
|
53
53
|
DEFAULT_RAG_INSTANCE[defaultName] = this;
|
|
54
54
|
}
|
|
55
55
|
static get(config) {
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
// Normaliser le baseDir pour éviter les doublons dus aux trailing slashes
|
|
57
|
+
// ou aux variations de paths (relatif/absolu, symlinks, etc.)
|
|
58
|
+
const normalizedBaseDir = path_1.default.resolve(config.baseDir).replace(/\/+$/, '');
|
|
59
|
+
// Vérifier si une instance existe déjà pour ce baseDir normalisé
|
|
60
|
+
if (DEFAULT_RAG_INSTANCE[normalizedBaseDir]) {
|
|
61
|
+
return DEFAULT_RAG_INSTANCE[normalizedBaseDir];
|
|
62
|
+
}
|
|
63
|
+
// Créer une nouvelle instance avec le baseDir normalisé
|
|
64
|
+
const normalizedConfig = {
|
|
65
|
+
...config,
|
|
66
|
+
baseDir: normalizedBaseDir
|
|
67
|
+
};
|
|
68
|
+
return new RAGManager(normalizedConfig);
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* Nettoie le cache des instances (utile pour les tests)
|
|
@@ -206,6 +213,9 @@ class RAGManager {
|
|
|
206
213
|
/**
|
|
207
214
|
* Notifie les embeddings chargés de se mettre à jour
|
|
208
215
|
*
|
|
216
|
+
* Cette méthode est publique pour permettre aux applications de notifier
|
|
217
|
+
* les utilisateurs actifs du RAG (tools, search) qu'il a été mis à jour.
|
|
218
|
+
*
|
|
209
219
|
* @param name Nom du RAG à mettre à jour
|
|
210
220
|
* @param opts Options de mise à jour (action: 'rename' pour renommer un document)
|
|
211
221
|
*
|
|
@@ -218,11 +228,11 @@ class RAGManager {
|
|
|
218
228
|
*
|
|
219
229
|
* @example
|
|
220
230
|
* ```typescript
|
|
221
|
-
* // Après un build
|
|
222
|
-
*
|
|
231
|
+
* // Après un build externe
|
|
232
|
+
* ragManager.notifyUpdate('procedures-stable');
|
|
223
233
|
*
|
|
224
234
|
* // Après un rename de document
|
|
225
|
-
*
|
|
235
|
+
* ragManager.notifyUpdate('procedures-stable', {
|
|
226
236
|
* action: 'rename',
|
|
227
237
|
* oldFile: 'old.md',
|
|
228
238
|
* newFile: 'new.md'
|
|
@@ -495,18 +505,31 @@ class RAGManager {
|
|
|
495
505
|
if (!entry) {
|
|
496
506
|
throw new Error(`RAG '${name}' n'existe pas`);
|
|
497
507
|
}
|
|
498
|
-
// if (status.status !== 'building') {
|
|
499
|
-
// throw new Error(`RAG '${name}' n'est pas en construction (status: ${status.status})`);
|
|
500
|
-
// }
|
|
501
508
|
const buildPath = entry.configPath;
|
|
502
509
|
if (!(0, fs_1.existsSync)(buildPath)) {
|
|
503
510
|
throw new Error(`Le dossier de construction n'existe pas: ${buildPath}`);
|
|
504
511
|
}
|
|
505
512
|
const filePath = path_1.default.join(buildPath, filename);
|
|
506
|
-
|
|
507
|
-
//
|
|
513
|
+
// ✅ Sauvegarder le fichier source uniquement
|
|
514
|
+
// Le .sha est écrit par markDocumentProcessed() APRÈS génération de .enhanced.md et .query.json
|
|
508
515
|
(0, fs_1.writeFileSync)(filePath, content, 'utf8');
|
|
509
|
-
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Marque un document comme entièrement traité (enhanced + query.json générés)
|
|
519
|
+
* Le .sha est écrit APRÈS le traitement complet pour garantir la cohérence
|
|
520
|
+
*
|
|
521
|
+
* @param name Nom du RAG
|
|
522
|
+
* @param filename Nom du fichier (ex: 'procedure.md')
|
|
523
|
+
* @param content Contenu du document traité
|
|
524
|
+
*/
|
|
525
|
+
markDocumentProcessed(name, filename, content) {
|
|
526
|
+
const entry = this.getEntry(name);
|
|
527
|
+
if (!entry) {
|
|
528
|
+
throw new Error(`RAG '${name}' n'existe pas`);
|
|
529
|
+
}
|
|
530
|
+
const buildPath = entry.configPath;
|
|
531
|
+
const shaPath = path_1.default.join(buildPath, filename + '.sha');
|
|
532
|
+
// ✅ Sauvegarder le fingerprint pour marquer le document comme traité
|
|
510
533
|
const sha = (0, usecase_1.calculateFingerprint)(content);
|
|
511
534
|
(0, fs_1.writeFileSync)(shaPath, sha, 'utf8');
|
|
512
535
|
}
|
|
@@ -686,6 +709,72 @@ class RAGManager {
|
|
|
686
709
|
const queryFile = baseName + '.query.json';
|
|
687
710
|
return (0, usecase_1.loadUseCases)(queryFile, { baseDir: configPath });
|
|
688
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Charge tous les use cases de tous les documents d'un RAG
|
|
714
|
+
*
|
|
715
|
+
* Utilise le fichier rag-metadata.json pour obtenir la liste des documents valides
|
|
716
|
+
* puis charge chaque fichier .query.json correspondant
|
|
717
|
+
*
|
|
718
|
+
* @param name Nom du RAG
|
|
719
|
+
* @returns Objet contenant tous les use cases par document
|
|
720
|
+
*
|
|
721
|
+
* @example
|
|
722
|
+
* ```typescript
|
|
723
|
+
* const allQueries = ragManager.loadAllUseCases('my-rag');
|
|
724
|
+
* console.log(`${Object.keys(allQueries.documents).length} documents avec use cases`);
|
|
725
|
+
* console.log(`${allQueries.totalQueries} questions au total`);
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
loadAllUseCases(name) {
|
|
729
|
+
const entry = this.getEntry(name);
|
|
730
|
+
if (!entry) {
|
|
731
|
+
throw new Error(`RAG '${name}' n'existe pas`);
|
|
732
|
+
}
|
|
733
|
+
//
|
|
734
|
+
// Charger le metadata pour obtenir la liste des documents
|
|
735
|
+
const metadataFile = path_1.default.join(entry.configPath, types_1.RAG_FILES.METADATA);
|
|
736
|
+
if (!(0, fs_1.existsSync)(metadataFile)) {
|
|
737
|
+
throw new Error(`Fichier metadata manquant: ${metadataFile}`);
|
|
738
|
+
}
|
|
739
|
+
let metadata;
|
|
740
|
+
try {
|
|
741
|
+
metadata = JSON.parse((0, fs_1.readFileSync)(metadataFile, 'utf8'));
|
|
742
|
+
}
|
|
743
|
+
catch (error) {
|
|
744
|
+
throw new Error(`Erreur lors du chargement du metadata: ${error}`);
|
|
745
|
+
}
|
|
746
|
+
//
|
|
747
|
+
// Extraire les filenames uniques depuis metadata.documents
|
|
748
|
+
const uniqueFilenames = new Set();
|
|
749
|
+
for (const docRef of Object.values(metadata.documents)) {
|
|
750
|
+
if (docRef.filename) {
|
|
751
|
+
uniqueFilenames.add(docRef.filename);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
//
|
|
755
|
+
// Charger les use cases pour chaque document
|
|
756
|
+
const documents = {};
|
|
757
|
+
let totalQueries = 0;
|
|
758
|
+
const filenames = [];
|
|
759
|
+
for (const filename of uniqueFilenames) {
|
|
760
|
+
const baseName = filename.replace(/\.md$/, '');
|
|
761
|
+
const queryFile = path_1.default.join(entry.configPath, baseName + '.query.json');
|
|
762
|
+
if ((0, fs_1.existsSync)(queryFile)) {
|
|
763
|
+
try {
|
|
764
|
+
const queries = JSON.parse((0, fs_1.readFileSync)(queryFile, 'utf8'));
|
|
765
|
+
documents[filename] = queries;
|
|
766
|
+
totalQueries += queries.queries?.length || 0;
|
|
767
|
+
filenames.push(filename);
|
|
768
|
+
}
|
|
769
|
+
catch (error) {
|
|
770
|
+
//
|
|
771
|
+
// Log l'erreur mais continue avec les autres documents
|
|
772
|
+
console.warn(`⚠️ Erreur chargement use cases pour ${filename}:`, error.message);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return { documents, totalQueries };
|
|
777
|
+
}
|
|
689
778
|
/**
|
|
690
779
|
* Construit un RAG de manière atomique
|
|
691
780
|
*
|
|
@@ -881,28 +970,34 @@ class RAGManager {
|
|
|
881
970
|
*/
|
|
882
971
|
async delete(name, archiveFlag = true) {
|
|
883
972
|
if (!this.exists(name)) {
|
|
884
|
-
|
|
973
|
+
console.warn(`⚠️ RAG '${name}' n'existe pas, skip delete`);
|
|
974
|
+
return new Error(`RAG '${name}' n'existe pas`);
|
|
885
975
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
(0, fs_1.
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
976
|
+
try {
|
|
977
|
+
const entry = this.getEntry(name);
|
|
978
|
+
const registry = this.getRegistry();
|
|
979
|
+
// Archiver si demandé
|
|
980
|
+
if (archiveFlag) {
|
|
981
|
+
await this.archive(name);
|
|
982
|
+
}
|
|
983
|
+
else if ((0, fs_1.existsSync)(entry.configPath)) {
|
|
984
|
+
(0, fs_1.rmSync)(entry.configPath, { recursive: true, force: true });
|
|
985
|
+
}
|
|
986
|
+
// Supprimer du registre
|
|
987
|
+
delete registry.registries[name];
|
|
988
|
+
// Supprimer de la map des embeddings chargés
|
|
989
|
+
this.loadedEmbeddings.delete(name);
|
|
990
|
+
// Changer le défaut si nécessaire
|
|
991
|
+
if (registry.defaultName === name) {
|
|
992
|
+
const remainingRAGs = Object.keys(registry.registries);
|
|
993
|
+
registry.defaultName = remainingRAGs.length > 0 ? remainingRAGs[0] : 'RAGRegistry';
|
|
994
|
+
}
|
|
995
|
+
this.saveRegistry(registry);
|
|
996
|
+
console.log(`✅ RAG supprimé: ${name}`);
|
|
997
|
+
}
|
|
998
|
+
catch (error) {
|
|
999
|
+
return error;
|
|
903
1000
|
}
|
|
904
|
-
this.saveRegistry(registry);
|
|
905
|
-
console.log(`✅ RAG supprimé: ${name}`);
|
|
906
1001
|
}
|
|
907
1002
|
/**
|
|
908
1003
|
* Renomme un document dans un RAG existant
|
|
@@ -1041,7 +1136,8 @@ class RAGManager {
|
|
|
1041
1136
|
}
|
|
1042
1137
|
}
|
|
1043
1138
|
/**
|
|
1044
|
-
* Renomme un RAG existant
|
|
1139
|
+
* Renomme un RAG existant (nom dans le registre uniquement)
|
|
1140
|
+
* Le dossier physique n'est PAS modifié, seul le nom dans la config change.
|
|
1045
1141
|
*
|
|
1046
1142
|
* @param from Nom actuel du RAG
|
|
1047
1143
|
* @param to Nouveau nom du RAG
|
|
@@ -1051,6 +1147,7 @@ class RAGManager {
|
|
|
1051
1147
|
* @example
|
|
1052
1148
|
* ```typescript
|
|
1053
1149
|
* await ragManager.rename('old-name', 'new-name', 'Description mise à jour');
|
|
1150
|
+
* // Le dossier reste /path/to/old-name mais le RAG s'appelle 'new-name'
|
|
1054
1151
|
* ```
|
|
1055
1152
|
*/
|
|
1056
1153
|
async rename(from, to, description) {
|
|
@@ -1073,20 +1170,14 @@ class RAGManager {
|
|
|
1073
1170
|
throw new Error(`Le nom '${to}' est réservé et ne peut pas être utilisé`);
|
|
1074
1171
|
}
|
|
1075
1172
|
const sourceEntry = this.getEntry(from);
|
|
1076
|
-
const sourcePath = sourceEntry.configPath;
|
|
1077
|
-
const destPath = path_1.default.join(this.config.baseDir, to);
|
|
1078
1173
|
try {
|
|
1079
|
-
//
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
if (this.config.verbose)
|
|
1083
|
-
console.log(`📁 Dossier renommé: ${sourcePath} → ${destPath}`);
|
|
1084
|
-
}
|
|
1085
|
-
// Mettre à jour le registre
|
|
1174
|
+
//
|
|
1175
|
+
// Ne PAS renommer le dossier physique - juste le nom dans le registre
|
|
1176
|
+
// Le configPath reste inchangé (pointe vers le même dossier)
|
|
1086
1177
|
const registry = this.getRegistry();
|
|
1087
1178
|
registry.registries[to] = {
|
|
1088
1179
|
name: to,
|
|
1089
|
-
configPath:
|
|
1180
|
+
configPath: sourceEntry.configPath, // ✅ Garde le même chemin
|
|
1090
1181
|
status: sourceEntry.status,
|
|
1091
1182
|
description: description || sourceEntry.description
|
|
1092
1183
|
};
|
|
@@ -1100,12 +1191,10 @@ class RAGManager {
|
|
|
1100
1191
|
if (embeddingData) {
|
|
1101
1192
|
this.loadedEmbeddings.set(to, embeddingData);
|
|
1102
1193
|
this.loadedEmbeddings.delete(from);
|
|
1103
|
-
// Notifier l'embedding de se mettre à jour avec le nouveau chemin
|
|
1104
|
-
this.notifyUpdate(to);
|
|
1105
1194
|
}
|
|
1106
1195
|
// Mettre à jour le cache
|
|
1107
1196
|
this.saveRegistry(registry);
|
|
1108
|
-
console.log(`✅ RAG renommé: ${from} → ${to}`);
|
|
1197
|
+
console.log(`✅ RAG renommé: ${from} → ${to} (dossier inchangé: ${sourceEntry.configPath})`);
|
|
1109
1198
|
}
|
|
1110
1199
|
catch (error) {
|
|
1111
1200
|
console.error(`❌ Erreur lors du renommage de '${from}' en '${to}':`, error);
|
package/dist/src/rag/types.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export declare const RAG_FILES: {
|
|
|
5
5
|
readonly QUERIES: "rag-queries.json";
|
|
6
6
|
};
|
|
7
7
|
export interface RAGConfig {
|
|
8
|
+
/** Provider de l'embedding (default openai) */
|
|
9
|
+
provider?: string;
|
|
8
10
|
/** Répertoire de base pour les documents et index */
|
|
9
11
|
baseDir: string;
|
|
10
12
|
/** Nom du fichier de vecteurs (sans extension) */
|
package/dist/src/rag/usecase.js
CHANGED
|
@@ -132,25 +132,22 @@ async function extractAndSaveDocumentUseCases(document, baseDir, version, tag, o
|
|
|
132
132
|
const existingQueries = JSON.parse((0, fs_1.readFileSync)(queryFile, 'utf8'));
|
|
133
133
|
// Comparer le fingerprint
|
|
134
134
|
if (existingQueries.fingerprint === fingerprint) {
|
|
135
|
-
|
|
136
|
-
console.log(`⏭️ Use cases à jour (fingerprint identique): ${document.filename}`);
|
|
137
|
-
}
|
|
135
|
+
console.log(`⏭️ Skip queries: ${document.filename}`);
|
|
138
136
|
return existingQueries;
|
|
139
137
|
}
|
|
140
|
-
|
|
141
|
-
console.log(`🔄 Contenu modifié (fingerprint différent): ${document.filename}`);
|
|
142
|
-
}
|
|
138
|
+
console.log(`🔄 Source modifiée queries: ${document.filename}`);
|
|
143
139
|
}
|
|
144
140
|
catch (error) {
|
|
145
141
|
// Si erreur de lecture, on continue avec l'extraction
|
|
146
|
-
|
|
147
|
-
console.warn(`⚠️ Erreur lecture use cases existants: ${error}`);
|
|
148
|
-
}
|
|
142
|
+
console.warn(`⚠️ Erreur lecture use cases: ${error}`);
|
|
149
143
|
}
|
|
150
144
|
}
|
|
151
145
|
// Extraction nécessaire (fichier inexistant, fingerprint différent, ou force=true)
|
|
152
|
-
if (
|
|
153
|
-
console.log(`🔄
|
|
146
|
+
if (force) {
|
|
147
|
+
console.log(`🔄 Force queries: ${document.filename}`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
console.log(`✨ Nouveau queries: ${document.filename}`);
|
|
154
151
|
}
|
|
155
152
|
const { queries, cost } = await extractDocumentUseCases(document);
|
|
156
153
|
const docQueries = {
|
|
@@ -551,6 +551,44 @@ class GitHealthManager {
|
|
|
551
551
|
];
|
|
552
552
|
let fixed = 0;
|
|
553
553
|
const fixedFiles = new Set();
|
|
554
|
+
// ✅ ÉTAPE CRITIQUE: Charger le cache pour toutes les branches avant la réparation
|
|
555
|
+
// Cela permet à getFileID() de trouver l'ID existant du fichier
|
|
556
|
+
if (!dryRun && filesToFix.length > 0) {
|
|
557
|
+
console.log(` 🔍 Chargement du cache pour toutes les branches...`);
|
|
558
|
+
const allBranches = await (0, git_1.gitGetAllBranches)(this.git);
|
|
559
|
+
const uniqueFiles = new Set();
|
|
560
|
+
for (const fileRef of filesToFix) {
|
|
561
|
+
const [, ...fileParts] = fileRef.split(':');
|
|
562
|
+
const file = fileParts.join(':');
|
|
563
|
+
uniqueFiles.add(file);
|
|
564
|
+
}
|
|
565
|
+
// Mettre en cache la liste des fichiers par branche pour éviter les appels répétés
|
|
566
|
+
const branchFilesCache = new Map();
|
|
567
|
+
for (const branch of allBranches) {
|
|
568
|
+
try {
|
|
569
|
+
const filesInBranch = await (0, git_1.gitListFilesInBranch)(this.git, branch);
|
|
570
|
+
branchFilesCache.set(branch, filesInBranch);
|
|
571
|
+
}
|
|
572
|
+
catch (e) {
|
|
573
|
+
// Ignorer silencieusement les erreurs (branche peut être inaccessible)
|
|
574
|
+
branchFilesCache.set(branch, []);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
// Charger le cache pour chaque fichier dans les branches où il existe
|
|
578
|
+
for (const file of uniqueFiles) {
|
|
579
|
+
for (const branch of allBranches) {
|
|
580
|
+
try {
|
|
581
|
+
const filesInBranch = branchFilesCache.get(branch) || [];
|
|
582
|
+
if (filesInBranch.includes(file)) {
|
|
583
|
+
await (0, git_1.gitFileStrictMatter)(this.git, file, branch, this.config);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
catch (e) {
|
|
587
|
+
// Ignorer silencieusement les erreurs (fichier peut ne pas exister)
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
554
592
|
for (const fileRef of filesToFix) {
|
|
555
593
|
// Éviter de réparer deux fois le même fichier
|
|
556
594
|
if (fixedFiles.has(fileRef)) {
|
|
@@ -570,11 +608,19 @@ class GitHealthManager {
|
|
|
570
608
|
// Parser le matter complet
|
|
571
609
|
const parsed = (0, utils_matter_1.matterParse)(fileData.content);
|
|
572
610
|
const { matter: fullMatter, content } = parsed;
|
|
573
|
-
//
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
611
|
+
// ✅ CORRECTION: Utiliser gitEnsureMatterID() pour réutiliser l'ID existant du fichier
|
|
612
|
+
// Si le fichier existe déjà dans une autre branche, son ID sera réutilisé
|
|
613
|
+
// Sinon, un nouvel ID sera généré automatiquement
|
|
614
|
+
const matterWithID = (0, git_1.gitEnsureMatterID)(fullMatter, this.config, branchName, file);
|
|
615
|
+
if (matterWithID.id !== fullMatter.id) {
|
|
616
|
+
if (fullMatter.id && fullMatter.id > 999) {
|
|
617
|
+
console.log(` 🔧 ${file}: ID ${fullMatter.id} remplacé par ID existant ${matterWithID.id}`);
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
console.log(` 🔧 ${file}: Nouvel ID assigné: ${matterWithID.id}`);
|
|
621
|
+
}
|
|
577
622
|
}
|
|
623
|
+
fullMatter.id = matterWithID.id;
|
|
578
624
|
// Générer un titre si manquant (basé sur le nom du fichier ou le premier titre de section)
|
|
579
625
|
if (!fullMatter.title || fullMatter.title.trim() === '') {
|
|
580
626
|
// Essayer d'extraire le premier titre de section (# Title)
|
|
@@ -591,6 +637,15 @@ class GitHealthManager {
|
|
|
591
637
|
}
|
|
592
638
|
// Re-sérialiser et sauvegarder
|
|
593
639
|
const updatedContent = (0, utils_matter_1.matterSerialize)(content, fullMatter);
|
|
640
|
+
// ✅ CRITIQUE: Vérifier si le contenu a réellement changé avant de créer un commit
|
|
641
|
+
// Si le contenu n'a pas changé, ne pas créer de commit pour éviter de déplacer les notes Git
|
|
642
|
+
if (updatedContent === fileData.content) {
|
|
643
|
+
// Le contenu n'a pas changé, juste mettre à jour le cache sans créer de commit
|
|
644
|
+
console.log(` ℹ️ ${file}: Aucun changement nécessaire (ID ${fullMatter.id} déjà correct)`);
|
|
645
|
+
fixed++;
|
|
646
|
+
fixedFiles.add(fileRef);
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
594
649
|
// ✅ IMPORTANT: Désactiver withID car l'ID est déjà généré et enregistré
|
|
595
650
|
// Évite la double validation qui cause "ID déjà utilisé"
|
|
596
651
|
await (0, repo_1.gitCreateOrEditFile)(this.git, file, branchName, updatedContent, { name: 'GitHealthManager', email: 'health@system' }, { ...this.config, canForce: true, withID: false });
|
|
@@ -195,13 +195,20 @@ export declare function gitShowConfiguration(git: SimpleGit): Promise<any>;
|
|
|
195
195
|
*/
|
|
196
196
|
export declare function gitCheckConfiguration(git?: SimpleGit): Promise<any>;
|
|
197
197
|
/**
|
|
198
|
-
* Crée un fichier dans
|
|
199
|
-
*
|
|
198
|
+
* Crée ou modifie un fichier dans une branche Git et fait un commit automatique
|
|
199
|
+
*
|
|
200
|
+
* @param git Instance SimpleGit
|
|
200
201
|
* @param filePath Chemin du fichier
|
|
201
202
|
* @param PR Nom de la branche de Pull Request
|
|
202
203
|
* @param content Contenu du fichier
|
|
203
|
-
* @param user Utilisateur qui
|
|
204
|
-
* @param config Configuration Git
|
|
204
|
+
* @param user Utilisateur qui fait le commit
|
|
205
|
+
* @param config Configuration Git optionnelle
|
|
206
|
+
* @returns Historique du commit créé
|
|
207
|
+
*
|
|
208
|
+
* @fixme Ajouter un paramètre optionnel `commitMessage?: string` pour permettre de personnaliser
|
|
209
|
+
* le message de commit au lieu d'utiliser toujours `commit: ${filePath}` par défaut.
|
|
210
|
+
* Cela permettrait aux callers de spécifier des messages plus descriptifs.
|
|
211
|
+
*
|
|
205
212
|
* @throws GitOperationError si la création échoue
|
|
206
213
|
*/
|
|
207
214
|
export declare function gitCreateOrEditFile(git: SimpleGit, filePath: string, PR: string, content: string, user: RuleUser, config?: RulesGitConfig): Promise<GitCommitHistory>;
|