agentic-api 2.0.31 → 2.0.314

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/src/agents/agents.example.js +21 -22
  2. package/dist/src/agents/authentication.js +1 -2
  3. package/dist/src/agents/prompts.d.ts +5 -4
  4. package/dist/src/agents/prompts.js +42 -87
  5. package/dist/src/agents/reducer.core.d.ts +24 -2
  6. package/dist/src/agents/reducer.core.js +125 -35
  7. package/dist/src/agents/reducer.loaders.d.ts +55 -1
  8. package/dist/src/agents/reducer.loaders.js +114 -1
  9. package/dist/src/agents/reducer.types.d.ts +45 -2
  10. package/dist/src/agents/semantic.js +1 -2
  11. package/dist/src/agents/simulator.d.ts +4 -0
  12. package/dist/src/agents/simulator.executor.d.ts +5 -1
  13. package/dist/src/agents/simulator.executor.js +41 -9
  14. package/dist/src/agents/simulator.js +86 -28
  15. package/dist/src/agents/simulator.prompts.d.ts +3 -2
  16. package/dist/src/agents/simulator.prompts.js +52 -78
  17. package/dist/src/agents/simulator.types.d.ts +20 -5
  18. package/dist/src/agents/simulator.utils.d.ts +7 -2
  19. package/dist/src/agents/simulator.utils.js +33 -11
  20. package/dist/src/agents/system.js +1 -2
  21. package/dist/src/execute.d.ts +17 -3
  22. package/dist/src/execute.js +156 -158
  23. package/dist/src/index.d.ts +1 -1
  24. package/dist/src/index.js +1 -1
  25. package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
  26. package/dist/src/pricing.llm.js +234 -0
  27. package/dist/src/prompts.d.ts +13 -4
  28. package/dist/src/prompts.js +221 -114
  29. package/dist/src/rag/embeddings.d.ts +36 -18
  30. package/dist/src/rag/embeddings.js +125 -128
  31. package/dist/src/rag/index.d.ts +5 -5
  32. package/dist/src/rag/index.js +14 -17
  33. package/dist/src/rag/parser.d.ts +2 -1
  34. package/dist/src/rag/parser.js +11 -14
  35. package/dist/src/rag/rag.examples.d.ts +27 -0
  36. package/dist/src/rag/rag.examples.js +151 -0
  37. package/dist/src/rag/rag.manager.d.ts +383 -0
  38. package/dist/src/rag/rag.manager.js +1378 -0
  39. package/dist/src/rag/types.d.ts +128 -12
  40. package/dist/src/rag/types.js +100 -1
  41. package/dist/src/rag/usecase.d.ts +37 -0
  42. package/dist/src/rag/usecase.js +96 -7
  43. package/dist/src/rules/git/git.e2e.helper.js +1 -0
  44. package/dist/src/rules/git/git.health.d.ts +57 -0
  45. package/dist/src/rules/git/git.health.js +281 -1
  46. package/dist/src/rules/git/index.d.ts +2 -2
  47. package/dist/src/rules/git/index.js +12 -1
  48. package/dist/src/rules/git/repo.d.ts +117 -0
  49. package/dist/src/rules/git/repo.js +536 -0
  50. package/dist/src/rules/git/repo.tools.d.ts +22 -1
  51. package/dist/src/rules/git/repo.tools.js +50 -1
  52. package/dist/src/rules/types.d.ts +16 -14
  53. package/dist/src/rules/utils.matter.d.ts +0 -4
  54. package/dist/src/rules/utils.matter.js +26 -7
  55. package/dist/src/scrapper.d.ts +15 -22
  56. package/dist/src/scrapper.js +57 -110
  57. package/dist/src/stategraph/index.d.ts +1 -1
  58. package/dist/src/stategraph/stategraph.d.ts +31 -2
  59. package/dist/src/stategraph/stategraph.js +93 -6
  60. package/dist/src/stategraph/stategraph.storage.js +4 -0
  61. package/dist/src/stategraph/types.d.ts +22 -0
  62. package/dist/src/types.d.ts +4 -2
  63. package/dist/src/types.js +1 -1
  64. package/dist/src/usecase.d.ts +11 -2
  65. package/dist/src/usecase.js +27 -35
  66. package/dist/src/utils.d.ts +32 -18
  67. package/dist/src/utils.js +60 -126
  68. package/package.json +7 -2
  69. package/dist/src/agents/digestor.test.d.ts +0 -1
  70. package/dist/src/agents/digestor.test.js +0 -45
  71. package/dist/src/agents/reducer.example.d.ts +0 -28
  72. package/dist/src/agents/reducer.example.js +0 -118
  73. package/dist/src/agents/reducer.process.d.ts +0 -16
  74. package/dist/src/agents/reducer.process.js +0 -143
  75. package/dist/src/agents/reducer.tools.d.ts +0 -29
  76. package/dist/src/agents/reducer.tools.js +0 -157
  77. package/dist/src/agents/simpleExample.d.ts +0 -3
  78. package/dist/src/agents/simpleExample.js +0 -38
  79. package/dist/src/agents/system-review.d.ts +0 -5
  80. package/dist/src/agents/system-review.js +0 -181
  81. package/dist/src/agents/systemReview.d.ts +0 -4
  82. package/dist/src/agents/systemReview.js +0 -22
  83. package/dist/src/princing.openai.js +0 -54
  84. package/dist/src/rag/tools.d.ts +0 -76
  85. package/dist/src/rag/tools.js +0 -196
  86. package/dist/src/rules/user.mapper.d.ts +0 -61
  87. package/dist/src/rules/user.mapper.js +0 -160
  88. package/dist/src/rules/utils/slug.d.ts +0 -22
  89. package/dist/src/rules/utils/slug.js +0 -35
@@ -44,16 +44,6 @@ export interface RAGMetadata {
44
44
  config: RAGConfig;
45
45
  /** Mapping ID → référence document/section */
46
46
  documents: Record<string, DocumentReference>;
47
- /**
48
- * Dernier identifiant documentaire attribué.
49
- * Utilisé pour générer un ID documentaire stable (matter.id) indépendant du nom de fichier.
50
- */
51
- docLastID?: number;
52
- /** Checkpoint avec le hash du dernier commit de la branche */
53
- checkpoint: {
54
- branch: string;
55
- hash: string;
56
- };
57
47
  /** Statistiques de l'index */
58
48
  stats: {
59
49
  totalDocuments: number;
@@ -98,13 +88,25 @@ export interface DocumentSection {
98
88
  export interface ParsedDocument {
99
89
  /** Nom du fichier source dans GIT*/
100
90
  filename: string;
101
- /** Métadonnées du front-matter */
102
- matter: Record<string, any>;
91
+ /** Métadonnées du front-matter (id et title obligatoires) */
92
+ matter: RAGMatter;
103
93
  /** Contenu sans le front-matter */
104
94
  content: string;
105
95
  /** Sections du document */
106
96
  sections: DocumentSection[];
107
97
  }
98
+ /**
99
+ * Métadonnées du front-matter d'un document RAG
100
+ * IMPORTANT: id et title sont obligatoires
101
+ */
102
+ export interface RAGMatter {
103
+ /** Identifiant documentaire stable (entier positif, max 2^32-1 pour hnswlib) */
104
+ id: number;
105
+ /** Titre descriptif du document */
106
+ title: string;
107
+ /** Propriétés optionnelles supplémentaires */
108
+ [key: string]: string | Date | number | boolean;
109
+ }
108
110
  export interface RAGRef {
109
111
  /** ID du document */
110
112
  id: number;
@@ -158,6 +160,32 @@ export interface DocumentQueries {
158
160
  queries: UserQuery[];
159
161
  /** Coût de l'extraction */
160
162
  cost: number;
163
+ /** fingerprint content hash (SHA-256 du contenu source) - Optionnel pour rétrocompatibilité */
164
+ fingerprint?: string;
165
+ }
166
+ /**
167
+ * Résultat de la construction d'un index vectoriel
168
+ *
169
+ * Retourné par Embeddings.indexFromDocuments() pour que RAGManager
170
+ * puisse créer les métadonnées complètes du RAG.
171
+ *
172
+ * Cette interface sépare clairement les responsabilités :
173
+ * - Embeddings : Construction de l'index vectoriel
174
+ * - RAGManager : Gestion des métadonnées et du cycle de vie
175
+ */
176
+ export interface IndexBuildResult {
177
+ /** Nombre total de vecteurs indexés */
178
+ totalVectors: number;
179
+ /** Dimensions des vecteurs */
180
+ vectorDimensions: number;
181
+ /** Références des documents avec leurs métadonnées */
182
+ documents: Record<string, DocumentReference>;
183
+ /** Mapping ID -> ref des sections */
184
+ mapping: Record<string, string>;
185
+ /** Tag de version généré */
186
+ tag: string;
187
+ /** Version du format */
188
+ version: string;
161
189
  }
162
190
  /** Interface pour le fichier de mapping des IDs */
163
191
  export interface RAGMapping {
@@ -176,3 +204,91 @@ export interface RAGMapping {
176
204
  * Génère un tag de version au format vYYYYMMDD
177
205
  */
178
206
  export declare function generateVersionTag(): string;
207
+ /**
208
+ * Contraintes pour les IDs hnswlib-node
209
+ * Les labels dans hnswlib sont des entiers non-signés 32 bits
210
+ */
211
+ export declare const HNSW_ID_CONSTRAINTS: {
212
+ readonly MIN: 0;
213
+ readonly MAX: 4294967295;
214
+ readonly RESERVED_START: 0;
215
+ readonly RESERVED_END: 999;
216
+ };
217
+ /**
218
+ * Vérifie si un ID est valide pour hnswlib-node
219
+ *
220
+ * Les contraintes sont :
221
+ * - Doit être un entier
222
+ * - Doit être >= 0
223
+ * - Doit être <= 2^32-1 (4294967295)
224
+ * - Doit être > 999 (pour éviter les IDs réservés)
225
+ *
226
+ * @param id L'ID à vérifier
227
+ * @returns true si l'ID est valide, false sinon
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * isValidHNSWID(1000) // true
232
+ * isValidHNSWID(999) // false (réservé)
233
+ * isValidHNSWID(-1) // false (négatif)
234
+ * isValidHNSWID(1.5) // false (pas un entier)
235
+ * ```
236
+ */
237
+ export declare function isValidHNSWID(id: number): boolean;
238
+ /**
239
+ * Vérifie si les métadonnées RAGMatter sont valides
240
+ *
241
+ * Les contraintes sont :
242
+ * - id et title doivent être définis
243
+ * - id doit être un entier valide pour hnswlib (> 999, < 2^32)
244
+ * - title doit être une chaîne non vide
245
+ *
246
+ * @param matter Les métadonnées à vérifier
247
+ * @returns true si les métadonnées sont valides, false sinon
248
+ * @throws Error avec un message descriptif si les métadonnées sont invalides
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * isValidRAGMatter({ id: 1000, title: 'Mon document' }) // true
253
+ * isValidRAGMatter({ id: 999, title: 'Test' }) // throws (ID réservé)
254
+ * isValidRAGMatter({ id: 1000, title: '' }) // throws (titre vide)
255
+ * ```
256
+ */
257
+ export declare function isValidRAGMatter(matter: any): matter is RAGMatter;
258
+ /** Interface pour une entrée du registre RAG */
259
+ export interface RAGRegistryEntry {
260
+ /** Identifiant unique (slug) */
261
+ name: string;
262
+ /** Chemin vers le dossier du RAGConfig (tempPath si building, destDir si active) */
263
+ configPath: string;
264
+ /** Chemin de destination finale (utilisé pour remplacer configPath après build) */
265
+ destDir?: string;
266
+ /** Statut du RAG */
267
+ status: 'active' | 'building' | 'archived' | 'error' | 'paused';
268
+ /** Description optionnelle du RAG */
269
+ description?: string;
270
+ /** Hash du dernier commit Git (checkpoint pour builds incrémentaux) */
271
+ checkpoint?: string;
272
+ }
273
+ /** Interface pour le registre des RAG */
274
+ export interface RAGRegistry {
275
+ /** Version du registre */
276
+ version: string;
277
+ /** Liste des RAG disponibles */
278
+ registries: Record<string, RAGRegistryEntry>;
279
+ /** RAG par défaut (par défaut: 'RAGRegistry') */
280
+ defaultName?: string;
281
+ }
282
+ /** Configuration du gestionnaire RAG */
283
+ export interface RAGManagerConfig {
284
+ /** Répertoire de base du registre */
285
+ baseDir: string;
286
+ /** Répertoire temporaire pour les constructions */
287
+ tempDir?: string;
288
+ /** Répertoire d'archives */
289
+ archiveDir?: string;
290
+ /** Nombre maximum d'archives par RAG */
291
+ maxArchives?: number;
292
+ /** Mode verbose */
293
+ verbose?: boolean;
294
+ }
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RAG_FILES = void 0;
3
+ exports.HNSW_ID_CONSTRAINTS = exports.RAG_FILES = void 0;
4
4
  exports.generateVersionTag = generateVersionTag;
5
+ exports.isValidHNSWID = isValidHNSWID;
6
+ exports.isValidRAGMatter = isValidRAGMatter;
5
7
  // Constantes pour les noms de fichiers RAG
6
8
  exports.RAG_FILES = {
7
9
  VECTORS: 'rag-hnsw.dat',
@@ -19,3 +21,100 @@ function generateVersionTag() {
19
21
  const day = String(today.getDate()).padStart(2, '0');
20
22
  return `v${year}${month}${day}`;
21
23
  }
24
+ /**
25
+ * Contraintes pour les IDs hnswlib-node
26
+ * Les labels dans hnswlib sont des entiers non-signés 32 bits
27
+ */
28
+ exports.HNSW_ID_CONSTRAINTS = {
29
+ MIN: 0,
30
+ MAX: 4294967295, // 2^32 - 1
31
+ RESERVED_START: 0,
32
+ RESERVED_END: 999 // IDs réservés pour usage interne
33
+ };
34
+ /**
35
+ * Vérifie si un ID est valide pour hnswlib-node
36
+ *
37
+ * Les contraintes sont :
38
+ * - Doit être un entier
39
+ * - Doit être >= 0
40
+ * - Doit être <= 2^32-1 (4294967295)
41
+ * - Doit être > 999 (pour éviter les IDs réservés)
42
+ *
43
+ * @param id L'ID à vérifier
44
+ * @returns true si l'ID est valide, false sinon
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * isValidHNSWID(1000) // true
49
+ * isValidHNSWID(999) // false (réservé)
50
+ * isValidHNSWID(-1) // false (négatif)
51
+ * isValidHNSWID(1.5) // false (pas un entier)
52
+ * ```
53
+ */
54
+ function isValidHNSWID(id) {
55
+ return (Number.isInteger(id) &&
56
+ id >= exports.HNSW_ID_CONSTRAINTS.MIN &&
57
+ id <= exports.HNSW_ID_CONSTRAINTS.MAX &&
58
+ id > exports.HNSW_ID_CONSTRAINTS.RESERVED_END);
59
+ }
60
+ /**
61
+ * Vérifie si les métadonnées RAGMatter sont valides
62
+ *
63
+ * Les contraintes sont :
64
+ * - id et title doivent être définis
65
+ * - id doit être un entier valide pour hnswlib (> 999, < 2^32)
66
+ * - title doit être une chaîne non vide
67
+ *
68
+ * @param matter Les métadonnées à vérifier
69
+ * @returns true si les métadonnées sont valides, false sinon
70
+ * @throws Error avec un message descriptif si les métadonnées sont invalides
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * isValidRAGMatter({ id: 1000, title: 'Mon document' }) // true
75
+ * isValidRAGMatter({ id: 999, title: 'Test' }) // throws (ID réservé)
76
+ * isValidRAGMatter({ id: 1000, title: '' }) // throws (titre vide)
77
+ * ```
78
+ */
79
+ function isValidRAGMatter(matter) {
80
+ // Vérifier que matter existe
81
+ if (!matter || typeof matter !== 'object' || Array.isArray(matter)) {
82
+ throw new Error('RAGMatter: matter est requis et doit être un objet');
83
+ }
84
+ // Vérifier que id existe et est un nombre
85
+ if (matter.id === undefined || matter.id === null) {
86
+ // Message plus explicite si le matter est complètement vide
87
+ const matterKeys = Object.keys(matter);
88
+ if (matterKeys.length === 0) {
89
+ throw new Error('RAGMatter: le front-matter est vide. Le contenu fourni ne contient probablement pas de front-matter YAML. Utilisez matterSerialize() pour ajouter le front-matter avant d\'appeler getSections().');
90
+ }
91
+ throw new Error(`RAGMatter: le champ "id" est obligatoire (matter reçu: ${JSON.stringify(matter)})`);
92
+ }
93
+ if (typeof matter.id !== 'number') {
94
+ throw new Error(`RAGMatter: le champ "id" doit être un nombre (reçu: ${typeof matter.id})`);
95
+ }
96
+ // Vérifier que l'ID est valide pour hnswlib
97
+ if (!isValidHNSWID(matter.id)) {
98
+ if (!Number.isInteger(matter.id)) {
99
+ throw new Error(`RAGMatter: l'ID ${matter.id} doit être un entier`);
100
+ }
101
+ if (matter.id <= exports.HNSW_ID_CONSTRAINTS.RESERVED_END) {
102
+ throw new Error(`RAGMatter: l'ID ${matter.id} est réservé (doit être > ${exports.HNSW_ID_CONSTRAINTS.RESERVED_END})`);
103
+ }
104
+ if (matter.id > exports.HNSW_ID_CONSTRAINTS.MAX) {
105
+ throw new Error(`RAGMatter: l'ID ${matter.id} dépasse la limite maximale (${exports.HNSW_ID_CONSTRAINTS.MAX})`);
106
+ }
107
+ throw new Error(`RAGMatter: l'ID ${matter.id} n'est pas valide`);
108
+ }
109
+ // Vérifier que title existe et est une chaîne non vide
110
+ if (matter.title === undefined || matter.title === null) {
111
+ throw new Error('RAGMatter: le champ "title" est obligatoire');
112
+ }
113
+ if (typeof matter.title !== 'string') {
114
+ throw new Error(`RAGMatter: le champ "title" doit être une chaîne (reçu: ${typeof matter.title})`);
115
+ }
116
+ if (matter.title.trim().length === 0) {
117
+ throw new Error('RAGMatter: le champ "title" ne peut pas être vide');
118
+ }
119
+ return true;
120
+ }
@@ -1,4 +1,12 @@
1
1
  import { DocumentQueries, UserQuery, RAGConfig, ParsedDocument } from './types';
2
+ /**
3
+ * Calcule le fingerprint SHA-256 d'un contenu
4
+ * Utilisé pour détecter si un document a changé et nécessite une re-extraction
5
+ *
6
+ * @param content Contenu du document
7
+ * @returns Hash SHA-256 en hexadécimal
8
+ */
9
+ export declare function calculateFingerprint(content: string): string;
2
10
  /**
3
11
  * Extrait tous les use cases d'un document parsé
4
12
  */
@@ -14,3 +22,32 @@ export declare function saveUseCases(queries: DocumentQueries, config: RAGConfig
14
22
  * Charge les use cases depuis un fichier JSON
15
23
  */
16
24
  export declare function loadUseCases(file: string, config: RAGConfig): DocumentQueries;
25
+ /**
26
+ * Extrait et sauvegarde les use cases d'un document
27
+ * Fonction standalone indépendante de la classe Embeddings
28
+ *
29
+ * Optimisation: Utilise un fingerprint (SHA-256) pour détecter si le document a changé.
30
+ * Si le fingerprint est identique, retourne les use cases existants sans re-extraction.
31
+ *
32
+ * @param document Document parsé
33
+ * @param baseDir Dossier où sauvegarder le fichier .query.json
34
+ * @param version Version du RAG (optionnel)
35
+ * @param tag Tag de version (optionnel)
36
+ * @param options Options d'extraction
37
+ * @param options.force Forcer la re-extraction même si le fingerprint est identique
38
+ * @param options.verbose Afficher les logs détaillés
39
+ * @returns Les queries extraites avec leur coût
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // Extraction avec cache (skip si fingerprint identique)
44
+ * const queries = await extractAndSaveDocumentUseCases(doc, './rag');
45
+ *
46
+ * // Forcer la re-extraction
47
+ * const queries = await extractAndSaveDocumentUseCases(doc, './rag', '1.0', 'v1', { force: true });
48
+ * ```
49
+ */
50
+ export declare function extractAndSaveDocumentUseCases(document: ParsedDocument, baseDir: string, version?: string, tag?: string, options?: {
51
+ force?: boolean;
52
+ verbose?: boolean;
53
+ }): Promise<DocumentQueries>;
@@ -3,12 +3,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.calculateFingerprint = calculateFingerprint;
6
7
  exports.extractDocumentUseCases = extractDocumentUseCases;
7
8
  exports.saveUseCases = saveUseCases;
8
9
  exports.loadUseCases = loadUseCases;
10
+ exports.extractAndSaveDocumentUseCases = extractAndSaveDocumentUseCases;
9
11
  const fs_1 = require("fs");
10
12
  const path_1 = __importDefault(require("path"));
13
+ const crypto_1 = require("crypto");
14
+ const types_1 = require("./types");
11
15
  const usecase_1 = require("../usecase");
16
+ /**
17
+ * Calcule le fingerprint SHA-256 d'un contenu
18
+ * Utilisé pour détecter si un document a changé et nécessite une re-extraction
19
+ *
20
+ * @param content Contenu du document
21
+ * @returns Hash SHA-256 en hexadécimal
22
+ */
23
+ function calculateFingerprint(content) {
24
+ return (0, crypto_1.createHash)('sha256').update(content, 'utf8').digest('hex');
25
+ }
12
26
  /**
13
27
  * Extrait tous les use cases d'un document parsé
14
28
  */
@@ -26,22 +40,22 @@ async function extractDocumentUseCases(parsedDocument) {
26
40
  continue;
27
41
  }
28
42
  try {
29
- const { json, cost } = await (0, usecase_1.callGPTToExtractUserQueries)(section.content, filename);
30
- const result = JSON.parse(json);
43
+ const { json, cost } = await (0, usecase_1.llmExtractUserQueries)(section.content, filename);
44
+ const result = json ? JSON.parse(json) : { queries: [] };
31
45
  if (result.queries && Array.isArray(result.queries)) {
32
46
  // Enrichir chaque query avec les informations de section
33
47
  const enrichedQueries = result.queries.map((query) => ({
34
48
  ...query,
35
49
  filename: path_1.default.basename(filename, path_1.default.extname(filename)),
36
- sectionIndex: index,
37
- ref: `${path_1.default.basename(filename, path_1.default.extname(filename))}#section-${index}`
50
+ sectionIndex: section.index,
51
+ ref: `${path_1.default.basename(filename, path_1.default.extname(filename))}#section-${section.index}`
38
52
  }));
39
53
  allQueries.push(...enrichedQueries);
40
54
  }
41
55
  totalCost += cost;
42
56
  }
43
57
  catch (error) {
44
- console.error(`Erreur lors de l'extraction des use cases pour ${filename}, section ${index}:`, error);
58
+ console.error(`Erreur lors de l'extraction des use cases pour ${filename}, section ${index}:`, error.message);
45
59
  }
46
60
  }
47
61
  return { queries: allQueries, cost: totalCost };
@@ -52,8 +66,12 @@ async function extractDocumentUseCases(parsedDocument) {
52
66
  function saveUseCases(queries, config) {
53
67
  try {
54
68
  const file = path_1.default.join(config.baseDir, queries.file);
69
+ // Créer le répertoire s'il n'existe pas
70
+ const dir = path_1.default.dirname(file);
71
+ if (!(0, fs_1.existsSync)(dir)) {
72
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
73
+ }
55
74
  (0, fs_1.writeFileSync)(file, JSON.stringify(queries, null, 2), 'utf8');
56
- console.log(`🔔 Use cases sauvegardés: ${file}`);
57
75
  }
58
76
  catch (error) {
59
77
  console.error('Erreur lors de la sauvegarde des use cases:', error);
@@ -73,7 +91,78 @@ function loadUseCases(file, config) {
73
91
  return JSON.parse((0, fs_1.readFileSync)(queriesFile, 'utf8'));
74
92
  }
75
93
  catch (error) {
76
- console.error('🔔 Erreur lors du chargement des use cases:', error);
94
+ console.error('🔔 Erreur lors du chargement des use cases:', error.message);
77
95
  throw new Error(`Erreur lors du chargement des use cases: ${queriesFile} ${error.message}`);
78
96
  }
79
97
  }
98
+ /**
99
+ * Extrait et sauvegarde les use cases d'un document
100
+ * Fonction standalone indépendante de la classe Embeddings
101
+ *
102
+ * Optimisation: Utilise un fingerprint (SHA-256) pour détecter si le document a changé.
103
+ * Si le fingerprint est identique, retourne les use cases existants sans re-extraction.
104
+ *
105
+ * @param document Document parsé
106
+ * @param baseDir Dossier où sauvegarder le fichier .query.json
107
+ * @param version Version du RAG (optionnel)
108
+ * @param tag Tag de version (optionnel)
109
+ * @param options Options d'extraction
110
+ * @param options.force Forcer la re-extraction même si le fingerprint est identique
111
+ * @param options.verbose Afficher les logs détaillés
112
+ * @returns Les queries extraites avec leur coût
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * // Extraction avec cache (skip si fingerprint identique)
117
+ * const queries = await extractAndSaveDocumentUseCases(doc, './rag');
118
+ *
119
+ * // Forcer la re-extraction
120
+ * const queries = await extractAndSaveDocumentUseCases(doc, './rag', '1.0', 'v1', { force: true });
121
+ * ```
122
+ */
123
+ async function extractAndSaveDocumentUseCases(document, baseDir, version, tag, options = {}) {
124
+ const { force = false, verbose = false } = options;
125
+ const filename = path_1.default.basename(document.filename, path_1.default.extname(document.filename));
126
+ const queryFile = path_1.default.join(baseDir, filename + '.query.json');
127
+ // Calculer le fingerprint du contenu source
128
+ const fingerprint = calculateFingerprint(document.content || '');
129
+ // Vérifier si le fichier existe déjà et si le fingerprint est identique
130
+ if (!force && (0, fs_1.existsSync)(queryFile)) {
131
+ try {
132
+ const existingQueries = JSON.parse((0, fs_1.readFileSync)(queryFile, 'utf8'));
133
+ // Comparer le fingerprint
134
+ if (existingQueries.fingerprint === fingerprint) {
135
+ if (verbose) {
136
+ console.log(`⏭️ Use cases à jour (fingerprint identique): ${document.filename}`);
137
+ }
138
+ return existingQueries;
139
+ }
140
+ else if (verbose) {
141
+ console.log(`🔄 Contenu modifié (fingerprint différent): ${document.filename}`);
142
+ }
143
+ }
144
+ catch (error) {
145
+ // Si erreur de lecture, on continue avec l'extraction
146
+ if (verbose) {
147
+ console.warn(`⚠️ Erreur lecture use cases existants: ${error}`);
148
+ }
149
+ }
150
+ }
151
+ // Extraction nécessaire (fichier inexistant, fingerprint différent, ou force=true)
152
+ if (verbose && force) {
153
+ console.log(`🔄 Re-extraction forcée: ${document.filename}`);
154
+ }
155
+ const { queries, cost } = await extractDocumentUseCases(document);
156
+ const docQueries = {
157
+ type: 'use-cases',
158
+ version: version || '1.0',
159
+ tag: tag || (0, types_1.generateVersionTag)(),
160
+ source: document.filename,
161
+ file: filename + '.query.json',
162
+ cost,
163
+ queries,
164
+ fingerprint // ✅ Ajouter le fingerprint
165
+ };
166
+ saveUseCases(docQueries, { baseDir });
167
+ return docQueries;
168
+ }
@@ -404,6 +404,7 @@ class GitE2EFactory {
404
404
  gitConfig,
405
405
  autoCleanup: options?.autoCleanup ?? true
406
406
  };
407
+ testConfig.gitConfig.verbose = options?.customConfig?.verbose ?? false;
407
408
  const helper = new GitE2EHelper(testConfig);
408
409
  // Set test environment
409
410
  process.env.NODE_ENV = 'test';
@@ -1,4 +1,16 @@
1
1
  import { RulesGitConfig, GitHealthStatus } from '../types';
2
+ /**
3
+ * Rapport d'analyse des IDs
4
+ */
5
+ export interface SafeIDsReport {
6
+ scanned: number;
7
+ valid: number;
8
+ missingID: string[];
9
+ missingTitle: string[];
10
+ invalidID: string[];
11
+ duplicateID: string[];
12
+ errors: string[];
13
+ }
2
14
  /**
3
15
  * Git Repository Health Manager
4
16
  *
@@ -63,4 +75,49 @@ export declare class GitHealthManager {
63
75
  * - Erreurs de traitement par branche → continue avec les autres
64
76
  */
65
77
  migrateNotes(): Promise<void>;
78
+ /**
79
+ * Analyse les IDs des documents Markdown dans une branche
80
+ *
81
+ * @param branch Branche à analyser (par défaut: toutes les branches)
82
+ * @returns Rapport d'analyse avec les fichiers problématiques
83
+ */
84
+ analyseSafeIDs(branch?: string): Promise<SafeIDsReport>;
85
+ /**
86
+ * Répare les IDs problématiques identifiés dans un rapport d'analyse
87
+ *
88
+ * @param report Rapport d'analyse généré par analyseSafeIDs
89
+ * @param options Options de réparation
90
+ * @param options.dryRun Mode simulation (affiche les réparations sans modifier)
91
+ * @returns Rapport mis à jour avec les fichiers réparés
92
+ */
93
+ repairSafeIDs(report: SafeIDsReport, options?: {
94
+ dryRun?: boolean;
95
+ }): Promise<SafeIDsReport>;
96
+ /**
97
+ * Vérifie et répare les IDs manquants dans tous les documents Markdown du repository
98
+ *
99
+ * Cette méthode orchestre l'analyse et la réparation :
100
+ * 1. Analyse les documents avec analyseSafeIDs()
101
+ * 2. Si autoFix est activé, répare avec repairSafeIDs()
102
+ *
103
+ * @param options Options de scan et réparation
104
+ * @param options.branch Branche spécifique à scanner (par défaut: toutes les branches)
105
+ * @param options.autoFix Active la réparation automatique (par défaut: false)
106
+ * @param options.dryRun Mode simulation (affiche les problèmes sans modifier)
107
+ * @returns Résumé des documents scannés et réparés
108
+ */
109
+ ensureSafeIDS(options?: {
110
+ branch?: string;
111
+ autoFix?: boolean;
112
+ dryRun?: boolean;
113
+ }): Promise<{
114
+ scanned: number;
115
+ valid: number;
116
+ missingID: number;
117
+ missingTitle: number;
118
+ invalidID: number;
119
+ duplicateID: number;
120
+ fixed: number;
121
+ errors: string[];
122
+ }>;
66
123
  }