agentic-api 2.0.646 → 2.0.885
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/prompts.d.ts +2 -3
- package/dist/src/agents/prompts.js +21 -118
- package/dist/src/agents/reducer.loaders.d.ts +103 -1
- package/dist/src/agents/reducer.loaders.js +164 -2
- package/dist/src/agents/reducer.types.d.ts +34 -3
- package/dist/src/agents/simulator.d.ts +32 -2
- package/dist/src/agents/simulator.executor.d.ts +15 -5
- package/dist/src/agents/simulator.executor.js +134 -67
- package/dist/src/agents/simulator.js +251 -8
- package/dist/src/agents/simulator.prompts.d.ts +55 -10
- package/dist/src/agents/simulator.prompts.js +305 -61
- package/dist/src/agents/simulator.types.d.ts +62 -1
- package/dist/src/agents/simulator.types.js +5 -0
- package/dist/src/agents/subagent.d.ts +128 -0
- package/dist/src/agents/subagent.js +231 -0
- package/dist/src/agents/worker.executor.d.ts +48 -0
- package/dist/src/agents/worker.executor.js +152 -0
- package/dist/src/execute/helpers.d.ts +3 -0
- package/dist/src/execute/helpers.js +222 -16
- package/dist/src/execute/responses.js +81 -55
- package/dist/src/execute/shared.d.ts +5 -0
- package/dist/src/execute/shared.js +27 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +3 -1
- package/dist/src/llm/openai.js +8 -1
- package/dist/src/llm/pricing.js +2 -0
- package/dist/src/llm/xai.js +11 -6
- package/dist/src/prompts.d.ts +14 -0
- package/dist/src/prompts.js +41 -1
- package/dist/src/rag/rag.manager.d.ts +18 -3
- package/dist/src/rag/rag.manager.js +114 -12
- package/dist/src/rag/types.d.ts +3 -1
- package/dist/src/rules/git/git.e2e.helper.js +51 -4
- package/dist/src/rules/git/git.health.js +89 -56
- package/dist/src/rules/git/index.d.ts +2 -2
- package/dist/src/rules/git/index.js +22 -5
- package/dist/src/rules/git/repo.d.ts +64 -6
- package/dist/src/rules/git/repo.js +572 -141
- package/dist/src/rules/git/repo.pr.d.ts +11 -18
- package/dist/src/rules/git/repo.pr.js +82 -94
- package/dist/src/rules/git/repo.tools.d.ts +5 -0
- package/dist/src/rules/git/repo.tools.js +6 -1
- package/dist/src/rules/types.d.ts +0 -2
- package/dist/src/rules/utils.matter.js +1 -5
- package/dist/src/scrapper.d.ts +138 -25
- package/dist/src/scrapper.js +538 -160
- package/dist/src/stategraph/stategraph.d.ts +6 -2
- package/dist/src/stategraph/stategraph.js +21 -6
- package/dist/src/stategraph/types.d.ts +14 -6
- package/dist/src/types.d.ts +22 -0
- package/dist/src/utils.d.ts +24 -0
- package/dist/src/utils.js +84 -86
- package/package.json +3 -2
- package/dist/src/agents/semantic.d.ts +0 -4
- package/dist/src/agents/semantic.js +0 -19
- package/dist/src/execute/legacy.d.ts +0 -46
- package/dist/src/execute/legacy.js +0 -460
- package/dist/src/pricing.llm.d.ts +0 -5
- package/dist/src/pricing.llm.js +0 -14
|
@@ -3,6 +3,9 @@ import { RulesGitConfig, PRMetadata, PRInfo, RuleUser, PRMergeResult, RulePullRe
|
|
|
3
3
|
/**
|
|
4
4
|
* Synchronise une branche PR avec son mergeBase pour corriger les références orphelines
|
|
5
5
|
*
|
|
6
|
+
* @deprecated Utiliser le workflow applicatif (RulesWorkflow.syncPullRequest) et
|
|
7
|
+
* les opérations robustes orientées Git Notes. API conservée pour compatibilité.
|
|
8
|
+
*
|
|
6
9
|
* FIXME: Cette fonction a un problème de gestion des métadonnées manquantes.
|
|
7
10
|
*
|
|
8
11
|
* PROBLÈME IDENTIFIÉ:
|
|
@@ -38,12 +41,14 @@ export declare function gitSyncPR(git: SimpleGit, branch: string, user: RuleUser
|
|
|
38
41
|
* @param branch Nom de la branche PR
|
|
39
42
|
* @param validationToken Token utilisé pour marquer la fermeture (optionnel, utilise la config par défaut)
|
|
40
43
|
* @returns true si le PR est fermé (dernier commit contient le token de validation)
|
|
41
|
-
*
|
|
44
|
+
* @deprecated Utiliser gitIsPRClosedRobust.
|
|
42
45
|
*/
|
|
43
46
|
export declare function gitIsPRClosed(git: SimpleGit, branch: string): Promise<boolean>;
|
|
44
47
|
/**
|
|
45
48
|
* Vérifie si une branche PR est fermée en utilisant Git Notes (avec fallback)
|
|
46
49
|
* Version robuste qui remplace gitIsPRClosed
|
|
50
|
+
* @deprecated Préférer gitLoadPR() pour récupérer l'état PR complet.
|
|
51
|
+
*
|
|
47
52
|
* @param git Instance Git
|
|
48
53
|
* @param branch Nom de la branche PR
|
|
49
54
|
* @param validationToken Token utilisé pour marquer la fermeture (optionnel, utilise la config par défaut)
|
|
@@ -73,23 +78,18 @@ export declare function gitGetAllPR(git: SimpleGit, options?: {
|
|
|
73
78
|
}): Promise<PRInfo[]>;
|
|
74
79
|
/**
|
|
75
80
|
* Finds closed PRs by scanning the history of the draft branch for merge commits with PR metadata.
|
|
81
|
+
* @deprecated Utiliser gitGetAllPR(git, { closed: true }) pour unifier le listing PR.
|
|
82
|
+
*
|
|
76
83
|
* @param git SimpleGit instance
|
|
77
84
|
* @param gitConfig The git configuration
|
|
78
85
|
* @returns A list of PRInfo objects for closed PRs.
|
|
79
86
|
*/
|
|
80
87
|
export declare function gitGetClosedPRs(git: SimpleGit, gitConfig: RulesGitConfig): Promise<PRInfo[]>;
|
|
81
88
|
export declare function gitLoadPR(git: SimpleGit, branch: string): Promise<PRInfo>;
|
|
82
|
-
/**
|
|
83
|
-
* Remplace explicitement un nom de fichier dans les métadonnées d'une PR.
|
|
84
|
-
* Utilisé pour refléter immédiatement les renames sans dépendre de git diff.
|
|
85
|
-
*/
|
|
86
|
-
export declare function gitPRReplaceFile(git: SimpleGit, branch: string, options?: {
|
|
87
|
-
remove?: string;
|
|
88
|
-
add?: string;
|
|
89
|
-
}, config?: RulesGitConfig): Promise<void>;
|
|
90
89
|
export declare function gitPRUpdateComments(git: SimpleGit, branch: string, details: RulePullRequestDetails, config?: RulesGitConfig): Promise<PRInfo>;
|
|
91
90
|
/**
|
|
92
|
-
*
|
|
91
|
+
* @deprecated Utiliser gitClosePRRobust.
|
|
92
|
+
*
|
|
93
93
|
* Ferme un PR en ajoutant un commit avec le token de validation
|
|
94
94
|
* @param git Instance Git
|
|
95
95
|
* @param branch Branche PR à fermer
|
|
@@ -111,13 +111,6 @@ export declare function gitClosePR(git: SimpleGit, branch: string, author: RuleU
|
|
|
111
111
|
* @returns Hash du commit de fermeture ou référence de la note
|
|
112
112
|
*/
|
|
113
113
|
export declare function gitClosePRRobust(git: SimpleGit, branch: string, closedBy: RuleUser, message?: string, config?: RulesGitConfig): Promise<PRMergeResult>;
|
|
114
|
-
/**
|
|
115
|
-
* Trouve le prochain numéro de PR disponible (protégé contre la concurrence)
|
|
116
|
-
* @param git Instance Git
|
|
117
|
-
* @param validationPrefix Préfixe des branches de validation
|
|
118
|
-
* @returns Prochain numéro de PR
|
|
119
|
-
*/
|
|
120
|
-
export declare function gitGetNextPRNumber(git: SimpleGit, validationPrefix: string): Promise<number>;
|
|
121
114
|
/**
|
|
122
115
|
* Crée une nouvelle branche de validation (pour un PR vers rule-editor)
|
|
123
116
|
* à partir d'une branche source (typiquement rule-editor).
|
|
@@ -136,7 +129,7 @@ export declare function gitNewValidationRequest(git: SimpleGit, files: string[],
|
|
|
136
129
|
validationBranchPrefix?: string;
|
|
137
130
|
}): Promise<PRInfo>;
|
|
138
131
|
/**
|
|
139
|
-
*
|
|
132
|
+
* @deprecated Utiliser gitNewValidationRequest().
|
|
140
133
|
*/
|
|
141
134
|
export declare function gitNewPR(git: SimpleGit, files: string[], description: string, author: RuleUser, options?: {
|
|
142
135
|
content?: string[];
|
|
@@ -40,20 +40,23 @@ exports.gitGetPRMetadata = gitGetPRMetadata;
|
|
|
40
40
|
exports.gitGetAllPR = gitGetAllPR;
|
|
41
41
|
exports.gitGetClosedPRs = gitGetClosedPRs;
|
|
42
42
|
exports.gitLoadPR = gitLoadPR;
|
|
43
|
-
exports.gitPRReplaceFile = gitPRReplaceFile;
|
|
44
43
|
exports.gitPRUpdateComments = gitPRUpdateComments;
|
|
45
44
|
exports.gitClosePR = gitClosePR;
|
|
46
45
|
exports.gitClosePRRobust = gitClosePRRobust;
|
|
47
|
-
exports.gitGetNextPRNumber = gitGetNextPRNumber;
|
|
48
46
|
exports.gitNewValidationRequest = gitNewValidationRequest;
|
|
49
47
|
exports.gitNewPR = gitNewPR;
|
|
50
48
|
const errors_1 = require("../errors");
|
|
51
49
|
const path_1 = require("path");
|
|
52
50
|
const fs = __importStar(require("fs/promises"));
|
|
53
51
|
const repo_tools_1 = require("./repo.tools");
|
|
52
|
+
const repo_1 = require("./repo");
|
|
53
|
+
const utils_matter_1 = require("../utils.matter");
|
|
54
54
|
/**
|
|
55
55
|
* Synchronise une branche PR avec son mergeBase pour corriger les références orphelines
|
|
56
56
|
*
|
|
57
|
+
* @deprecated Utiliser le workflow applicatif (RulesWorkflow.syncPullRequest) et
|
|
58
|
+
* les opérations robustes orientées Git Notes. API conservée pour compatibilité.
|
|
59
|
+
*
|
|
57
60
|
* FIXME: Cette fonction a un problème de gestion des métadonnées manquantes.
|
|
58
61
|
*
|
|
59
62
|
* PROBLÈME IDENTIFIÉ:
|
|
@@ -152,9 +155,12 @@ async function gitSyncPR(git, branch, user) {
|
|
|
152
155
|
throw new errors_1.GitOperationError(`Failed to sync PR ${branch} with merge base ${mergeBase}: ${mergeError}`, 'pr_sync', { branch, mergeBase, mergeError, fallbackError });
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
|
-
// Préserver les fichiers originaux de la PR (ne pas recalculer après merge)
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
+
// Préserver les fichiers originaux de la PR (ne pas recalculer après merge).
|
|
159
|
+
// NOTE IMPORTANTE:
|
|
160
|
+
// - gitSyncPR fait un merge technique pour maintenir la branche de validation à jour.
|
|
161
|
+
// - Ce merge NE DOIT PAS redéfinir le scope métier de la PR.
|
|
162
|
+
// - metadata.files reste la source de vérité (pilotée par add/edit/rename/delete).
|
|
163
|
+
// - Un diff Git post-merge peut être ambigu (base mouvante, merge commit, refs).
|
|
158
164
|
const updatedMetadata = {
|
|
159
165
|
...pr.metadata,
|
|
160
166
|
files: pr.metadata.files, // Préserver les fichiers originaux
|
|
@@ -191,7 +197,7 @@ async function gitSyncPR(git, branch, user) {
|
|
|
191
197
|
* @param branch Nom de la branche PR
|
|
192
198
|
* @param validationToken Token utilisé pour marquer la fermeture (optionnel, utilise la config par défaut)
|
|
193
199
|
* @returns true si le PR est fermé (dernier commit contient le token de validation)
|
|
194
|
-
*
|
|
200
|
+
* @deprecated Utiliser gitIsPRClosedRobust.
|
|
195
201
|
*/
|
|
196
202
|
async function gitIsPRClosed(git, branch) {
|
|
197
203
|
return gitIsPRClosedRobust(git, branch);
|
|
@@ -199,6 +205,8 @@ async function gitIsPRClosed(git, branch) {
|
|
|
199
205
|
/**
|
|
200
206
|
* Vérifie si une branche PR est fermée en utilisant Git Notes (avec fallback)
|
|
201
207
|
* Version robuste qui remplace gitIsPRClosed
|
|
208
|
+
* @deprecated Préférer gitLoadPR() pour récupérer l'état PR complet.
|
|
209
|
+
*
|
|
202
210
|
* @param git Instance Git
|
|
203
211
|
* @param branch Nom de la branche PR
|
|
204
212
|
* @param validationToken Token utilisé pour marquer la fermeture (optionnel, utilise la config par défaut)
|
|
@@ -232,13 +240,33 @@ async function gitIsPRClosedRobust(git, branch, config) {
|
|
|
232
240
|
async function gitGetPRMetadata(git, branch, config) {
|
|
233
241
|
const gitConf = (0, repo_tools_1.gitLoad)(config);
|
|
234
242
|
try {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
243
|
+
const expectedPRId = Number.parseInt(branch.replace(gitConf.validationPrefix, ''), 10);
|
|
244
|
+
// D'abord essayer de chercher rapidement sur HEAD / historique récent.
|
|
245
|
+
const metadata = await (0, repo_tools_1.gitReadNote)(git, branch, gitConf.gitNotes.namespace, 20);
|
|
246
|
+
if (metadata) {
|
|
247
|
+
// Si ce n'est pas une branche de validation standard, on retourne tel quel.
|
|
248
|
+
if (Number.isNaN(expectedPRId)) {
|
|
249
|
+
return metadata;
|
|
250
|
+
}
|
|
251
|
+
// Branche de validation: rejeter une note dont l'ID ne correspond pas.
|
|
252
|
+
if (metadata.id === expectedPRId) {
|
|
253
|
+
return metadata;
|
|
254
|
+
}
|
|
255
|
+
if (gitConf.verbose) {
|
|
256
|
+
console.warn(`⚠️ gitGetPRMetadata(${branch}): note récente id=${metadata.id}, attendu=${expectedPRId}. Recherche approfondie...`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Fallback robuste: scanner plus large et ne retenir que la note du bon PR.
|
|
260
|
+
if (!Number.isNaN(expectedPRId)) {
|
|
261
|
+
const log = await git.log(['-n', '200', branch]);
|
|
262
|
+
for (const commit of log.all) {
|
|
263
|
+
const note = await (0, repo_tools_1.gitReadNote)(git, commit.hash, gitConf.gitNotes.namespace, 1);
|
|
264
|
+
if (note && note.id === expectedPRId) {
|
|
265
|
+
return note;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
242
270
|
}
|
|
243
271
|
catch (error) {
|
|
244
272
|
// This typically happens if the branch doesn't exist, which is a valid case.
|
|
@@ -287,6 +315,8 @@ async function gitGetAllPR(git, options = {}) {
|
|
|
287
315
|
}
|
|
288
316
|
/**
|
|
289
317
|
* Finds closed PRs by scanning the history of the draft branch for merge commits with PR metadata.
|
|
318
|
+
* @deprecated Utiliser gitGetAllPR(git, { closed: true }) pour unifier le listing PR.
|
|
319
|
+
*
|
|
290
320
|
* @param git SimpleGit instance
|
|
291
321
|
* @param gitConfig The git configuration
|
|
292
322
|
* @returns A list of PRInfo objects for closed PRs.
|
|
@@ -317,12 +347,13 @@ async function gitGetClosedPRs(git, gitConfig) {
|
|
|
317
347
|
}
|
|
318
348
|
async function gitLoadPR(git, branch) {
|
|
319
349
|
try {
|
|
350
|
+
const gitConf = (0, repo_tools_1.gitLoad)();
|
|
320
351
|
// Load metadata from
|
|
321
352
|
const metadata = await gitGetPRMetadata(git, branch);
|
|
322
353
|
if (!metadata) {
|
|
323
354
|
throw new errors_1.GitOperationError(`PR not found for branch ${branch}`, 'pr_load', { branch });
|
|
324
355
|
}
|
|
325
|
-
const files = metadata.files || (await (0, repo_tools_1.gitGetDiffFiles)(git, branch, metadata?.mergeBase, '.md'));
|
|
356
|
+
const files = metadata.files || (await (0, repo_tools_1.gitGetDiffFiles)(git, branch, metadata?.mergeBase || gitConf.draftBranch, '.md'));
|
|
326
357
|
// Récupérer les infos du dernier commit de la branche
|
|
327
358
|
const log = await git.log({ from: branch, to: branch, maxCount: 1 });
|
|
328
359
|
const lastCommit = log.latest;
|
|
@@ -342,49 +373,6 @@ async function gitLoadPR(git, branch) {
|
|
|
342
373
|
throw new errors_1.GitOperationError(`Failed to retrieve PR: ${error}`, 'pr_load');
|
|
343
374
|
}
|
|
344
375
|
}
|
|
345
|
-
/**
|
|
346
|
-
* Remplace explicitement un nom de fichier dans les métadonnées d'une PR.
|
|
347
|
-
* Utilisé pour refléter immédiatement les renames sans dépendre de git diff.
|
|
348
|
-
*/
|
|
349
|
-
async function gitPRReplaceFile(git, branch, options = {}, config) {
|
|
350
|
-
const { remove, add } = options;
|
|
351
|
-
if (!remove && !add) {
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
const gitConf = (0, repo_tools_1.gitLoad)(config);
|
|
355
|
-
const metadata = await gitGetPRMetadata(git, branch, config);
|
|
356
|
-
if (!metadata) {
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
const currentFiles = Array.isArray(metadata.files) ? metadata.files : [];
|
|
360
|
-
const seen = new Set();
|
|
361
|
-
const nextFiles = [];
|
|
362
|
-
for (const file of currentFiles) {
|
|
363
|
-
if (!file) {
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
if (remove && file === remove) {
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
if (seen.has(file)) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
seen.add(file);
|
|
373
|
-
nextFiles.push(file);
|
|
374
|
-
}
|
|
375
|
-
if (add && !seen.has(add)) {
|
|
376
|
-
nextFiles.push(add);
|
|
377
|
-
seen.add(add);
|
|
378
|
-
}
|
|
379
|
-
const changed = currentFiles.length !== nextFiles.length ||
|
|
380
|
-
currentFiles.some((file, idx) => file !== nextFiles[idx]);
|
|
381
|
-
if (!changed) {
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
metadata.files = nextFiles;
|
|
385
|
-
const headCommitHash = (await git.revparse([branch])).trim();
|
|
386
|
-
await (0, repo_tools_1.gitWriteNote)(git, headCommitHash, metadata, gitConf.gitNotes.namespace);
|
|
387
|
-
}
|
|
388
376
|
async function gitPRUpdateComments(git, branch, details, config) {
|
|
389
377
|
const gitConf = (0, repo_tools_1.gitLoad)(config);
|
|
390
378
|
const metadata = await gitGetPRMetadata(git, branch, config);
|
|
@@ -405,7 +393,8 @@ async function gitPRUpdateComments(git, branch, details, config) {
|
|
|
405
393
|
return gitLoadPR(git, branch);
|
|
406
394
|
}
|
|
407
395
|
/**
|
|
408
|
-
*
|
|
396
|
+
* @deprecated Utiliser gitClosePRRobust.
|
|
397
|
+
*
|
|
409
398
|
* Ferme un PR en ajoutant un commit avec le token de validation
|
|
410
399
|
* @param git Instance Git
|
|
411
400
|
* @param branch Branche PR à fermer
|
|
@@ -483,6 +472,7 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
|
|
|
483
472
|
// Note: "ours" dans ce contexte signifie "garder la version de la branche qu'on merge" (la PR)
|
|
484
473
|
// car nous sommes sur rule-editor et on merge la PR
|
|
485
474
|
let mergeResult;
|
|
475
|
+
let mergeCommitHash;
|
|
486
476
|
try {
|
|
487
477
|
mergeResult = await git
|
|
488
478
|
.env({
|
|
@@ -498,6 +488,7 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
|
|
|
498
488
|
'-m', `Merge branch '${branch}'`,
|
|
499
489
|
branch
|
|
500
490
|
]);
|
|
491
|
+
mergeCommitHash = (await git.revparse(['HEAD'])).trim();
|
|
501
492
|
}
|
|
502
493
|
catch (mergeError) {
|
|
503
494
|
if (gitConf.verbose) {
|
|
@@ -537,15 +528,22 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
|
|
|
537
528
|
}
|
|
538
529
|
}
|
|
539
530
|
// Amend le commit de merge avec les bons contenus
|
|
540
|
-
await git.commit('--amend', ['--no-edit'], {
|
|
531
|
+
const amendResult = await git.commit('--amend', ['--no-edit'], {
|
|
541
532
|
'--author': `${closedBy.name} <${closedBy.email}>`
|
|
542
533
|
});
|
|
534
|
+
mergeCommitHash = amendResult.commit || (await git.revparse(['HEAD'])).trim();
|
|
543
535
|
mergeResult = { summary: { changes: prFiles.length } };
|
|
544
536
|
}
|
|
545
537
|
catch (fallbackError) {
|
|
546
538
|
throw new errors_1.PRClosureError(`Failed to merge PR ${branch} with all strategies: ${mergeError}\nFallback error: ${fallbackError}`, branch, 'merge_failed');
|
|
547
539
|
}
|
|
548
540
|
}
|
|
541
|
+
// 6. Attacher aussi la note au commit de merge sur la branche cible.
|
|
542
|
+
// Cela garantit la traçabilité même si la branche PR est supprimée.
|
|
543
|
+
if (!mergeCommitHash) {
|
|
544
|
+
mergeCommitHash = (await git.revparse(['HEAD'])).trim();
|
|
545
|
+
}
|
|
546
|
+
await (0, repo_tools_1.gitWriteNote)(git, mergeCommitHash, finalMetadata, gitConf.gitNotes.namespace);
|
|
549
547
|
const result = {
|
|
550
548
|
metadata: finalMetadata,
|
|
551
549
|
failed: false,
|
|
@@ -583,37 +581,6 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
|
|
|
583
581
|
(0, repo_tools_1.unlock)('checkout');
|
|
584
582
|
}
|
|
585
583
|
}
|
|
586
|
-
/**
|
|
587
|
-
* Trouve le prochain numéro de PR disponible (protégé contre la concurrence)
|
|
588
|
-
* @param git Instance Git
|
|
589
|
-
* @param validationPrefix Préfixe des branches de validation
|
|
590
|
-
* @returns Prochain numéro de PR
|
|
591
|
-
*/
|
|
592
|
-
async function gitGetNextPRNumber(git, validationPrefix) {
|
|
593
|
-
await (0, repo_tools_1.lock)('pr-number');
|
|
594
|
-
try {
|
|
595
|
-
const allBranches = await (0, repo_tools_1.gitGetAllBranches)(git);
|
|
596
|
-
const prBranches = allBranches.filter((branch) => branch.startsWith(validationPrefix));
|
|
597
|
-
if (prBranches.length === 0) {
|
|
598
|
-
return 1;
|
|
599
|
-
}
|
|
600
|
-
const numbers = prBranches
|
|
601
|
-
.map((branch) => {
|
|
602
|
-
const numberPart = branch.substring(validationPrefix.length);
|
|
603
|
-
// Gérer les cas où le nom de branche contient plus que le numéro après le préfixe
|
|
604
|
-
const actualNumber = parseInt(numberPart.split('-')[0], 10);
|
|
605
|
-
return actualNumber;
|
|
606
|
-
})
|
|
607
|
-
.filter((num) => !isNaN(num));
|
|
608
|
-
return numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
|
|
609
|
-
}
|
|
610
|
-
catch (error) {
|
|
611
|
-
throw new errors_1.GitOperationError(`Failed to get next PR number: ${error}`, 'pr_number', { validationPrefix, originalError: error });
|
|
612
|
-
}
|
|
613
|
-
finally {
|
|
614
|
-
(0, repo_tools_1.unlock)('pr-number');
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
584
|
/**
|
|
618
585
|
* Crée une nouvelle branche de validation (pour un PR vers rule-editor)
|
|
619
586
|
* à partir d'une branche source (typiquement rule-editor).
|
|
@@ -639,6 +606,20 @@ async function gitNewValidationRequest(git, files, description, author, options
|
|
|
639
606
|
throw new errors_1.PRCreationError('Author is required', undefined, files);
|
|
640
607
|
}
|
|
641
608
|
try {
|
|
609
|
+
// Vérification atomique côté API: empêcher plusieurs PR ouvertes sur les mêmes fichiers.
|
|
610
|
+
const openPRs = await gitGetAllPR(git, {
|
|
611
|
+
closed: false,
|
|
612
|
+
validationPrefix: validationBranchPrefix
|
|
613
|
+
});
|
|
614
|
+
const conflictingPRs = openPRs.filter((pr) => pr.files.some((prFile) => files.includes(prFile)));
|
|
615
|
+
if (conflictingPRs.length > 0) {
|
|
616
|
+
const conflictingFiles = files.filter((file) => conflictingPRs.some((pr) => pr.files.includes(file)));
|
|
617
|
+
if (gitConfig.verbose) {
|
|
618
|
+
console.log('🌶️ DEBUG: gitNewValidationRequest -- conflicting PRs:', conflictingPRs.map((pr) => pr.branch));
|
|
619
|
+
}
|
|
620
|
+
const firstConflict = conflictingPRs[0].branch;
|
|
621
|
+
throw new errors_1.PRCreationError(`Le fichier est déjà dans la validation en cours #${firstConflict.replace(validationBranchPrefix, '')}`, firstConflict, conflictingFiles);
|
|
622
|
+
}
|
|
642
623
|
// ✅ CLEANUP: Nettoyer tout état de merge corrompu avant de créer la branche
|
|
643
624
|
// Cela évite l'erreur "you need to resolve your current index first"
|
|
644
625
|
try {
|
|
@@ -654,7 +635,7 @@ async function gitNewValidationRequest(git, files, description, author, options
|
|
|
654
635
|
console.warn('Cleanup before branch creation failed (non-critical):', cleanupError);
|
|
655
636
|
}
|
|
656
637
|
}
|
|
657
|
-
const nextID = await
|
|
638
|
+
const nextID = await (0, repo_1.gitAllocateNextPRNumber)(git, validationBranchPrefix, gitConfig);
|
|
658
639
|
const newBranchName = `${validationBranchPrefix}${nextID}`;
|
|
659
640
|
await git.checkoutBranch(newBranchName, sourceBranch);
|
|
660
641
|
const initialCommitMessage = `#${nextID} ${description}`;
|
|
@@ -663,9 +644,16 @@ async function gitNewValidationRequest(git, files, description, author, options
|
|
|
663
644
|
if (!content[idx]) {
|
|
664
645
|
continue;
|
|
665
646
|
}
|
|
666
|
-
|
|
647
|
+
let fileContent = content[idx];
|
|
648
|
+
// Assurer l'ID documentaire lors de la création d'une PR avec contenus fournis.
|
|
649
|
+
if (gitConfig.withID !== false) {
|
|
650
|
+
const parsed = (0, utils_matter_1.matterParse)(fileContent);
|
|
651
|
+
parsed.matter = (0, repo_1.gitEnsureMatterID)(parsed.matter, gitConfig, newBranchName, files[idx]);
|
|
652
|
+
fileContent = (0, utils_matter_1.matterSerialize)(parsed.content, parsed.matter);
|
|
653
|
+
}
|
|
654
|
+
// console.log('writeFile',files[idx],fileContent);
|
|
667
655
|
// This writeFile is in-memory and stages the file.
|
|
668
|
-
await _writeFileAndCommit(git, files[idx],
|
|
656
|
+
await _writeFileAndCommit(git, files[idx], fileContent, author, gitConfig, initialCommitMessage);
|
|
669
657
|
}
|
|
670
658
|
const metadata = {
|
|
671
659
|
id: nextID,
|
|
@@ -710,7 +698,7 @@ async function gitNewValidationRequest(git, files, description, author, options
|
|
|
710
698
|
}
|
|
711
699
|
}
|
|
712
700
|
/**
|
|
713
|
-
*
|
|
701
|
+
* @deprecated Utiliser gitNewValidationRequest().
|
|
714
702
|
*/
|
|
715
703
|
async function gitNewPR(git, files, description, author, options = {}) {
|
|
716
704
|
return gitNewValidationRequest(git, files, description, author, options);
|
|
@@ -123,6 +123,11 @@ export declare function gitGetAllBranches(git: SimpleGit, options?: {
|
|
|
123
123
|
* @param baseBranch Branche de base (par défaut: main)
|
|
124
124
|
* @param filter Filtre optionnel (ex: '.md')
|
|
125
125
|
* @returns Liste des fichiers modifiés
|
|
126
|
+
*
|
|
127
|
+
* NOTE IMPORTANTE:
|
|
128
|
+
* - Ce résultat est une vue TECHNIQUE du diff Git (commits/références), pas une vérité métier PR.
|
|
129
|
+
* - Ne pas utiliser seul pour reconstruire metadata.files d'une PR.
|
|
130
|
+
* - La source de vérité métier reste metadata.files maintenu par add/edit/rename/delete.
|
|
126
131
|
*/
|
|
127
132
|
export declare function gitGetDiffFiles(git: SimpleGit, targetBranch: string, baseBranch?: string, filter?: string): Promise<string[]>;
|
|
128
133
|
/**
|
|
@@ -129,7 +129,7 @@ function gitLoad(defaultConfig) {
|
|
|
129
129
|
}
|
|
130
130
|
// console.log(`🌶️ gitLoad: First Loading git config`,defaultConfig);
|
|
131
131
|
const verbose = defaultConfig?.verbose || process.env.GIT_VERBOSE === 'true';
|
|
132
|
-
const remoteUrl = defaultConfig?.remoteUrl
|
|
132
|
+
const remoteUrl = defaultConfig?.remoteUrl ?? process.env.GIT_REMOTE_URL;
|
|
133
133
|
const repoPath = defaultConfig?.repoPath || process.env.GIT_REPO_PATH;
|
|
134
134
|
const uploadPath = defaultConfig?.uploadPath || process.env.GIT_UPLOAD_PATH;
|
|
135
135
|
const draftBranch = defaultConfig?.draftBranch || process.env.DEFAULT_BRANCH_DRAFT;
|
|
@@ -625,6 +625,11 @@ async function gitGetAllBranches(git, options = {}) {
|
|
|
625
625
|
* @param baseBranch Branche de base (par défaut: main)
|
|
626
626
|
* @param filter Filtre optionnel (ex: '.md')
|
|
627
627
|
* @returns Liste des fichiers modifiés
|
|
628
|
+
*
|
|
629
|
+
* NOTE IMPORTANTE:
|
|
630
|
+
* - Ce résultat est une vue TECHNIQUE du diff Git (commits/références), pas une vérité métier PR.
|
|
631
|
+
* - Ne pas utiliser seul pour reconstruire metadata.files d'une PR.
|
|
632
|
+
* - La source de vérité métier reste metadata.files maintenu par add/edit/rename/delete.
|
|
628
633
|
*/
|
|
629
634
|
async function gitGetDiffFiles(git, targetBranch, baseBranch, filter) {
|
|
630
635
|
const gitConfig = gitLoad();
|
|
@@ -122,8 +122,6 @@ export interface FrontMatter {
|
|
|
122
122
|
id?: number;
|
|
123
123
|
/** Titre descriptif de la règle */
|
|
124
124
|
title: string;
|
|
125
|
-
/** Ancien nom de fichier (pour renommage) */
|
|
126
|
-
oldfile?: string;
|
|
127
125
|
/** Auteur original de la règle (format git: "Name <email>") */
|
|
128
126
|
author?: string;
|
|
129
127
|
/** Email du validateur assigné à cette règle */
|
|
@@ -121,13 +121,9 @@ function matterParse(markdown) {
|
|
|
121
121
|
* ✅ NOUVELLE FONCTION pour reconstruire le contenu complet
|
|
122
122
|
*/
|
|
123
123
|
function matterSerializeFromRule(rule) {
|
|
124
|
-
|
|
125
|
-
const matter = { ...rule.matter };
|
|
126
|
-
delete matter.oldfile;
|
|
127
|
-
return matterSerialize(rule.content, matter);
|
|
124
|
+
return matterSerialize(rule.content, rule.matter);
|
|
128
125
|
}
|
|
129
126
|
function matterSerialize(content, matter) {
|
|
130
|
-
// Créer un objet propre pour le front-matter (exclure oldfile)
|
|
131
127
|
const cleanMatter = { ...matter };
|
|
132
128
|
const result = Object.keys(cleanMatter).reduce((acc, key) => {
|
|
133
129
|
const value = cleanMatter[key];
|
package/dist/src/scrapper.d.ts
CHANGED
|
@@ -1,48 +1,161 @@
|
|
|
1
1
|
import { FrontMatter } from "./rules/types";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/** Raw image data extracted from a PDF page. */
|
|
3
|
+
export interface PageImage {
|
|
4
|
+
/** Raw pixel buffer: RGBA, RGB, grayscale bytes, or JPEG-encoded bytes. */
|
|
5
|
+
data: Buffer;
|
|
6
|
+
/** Pixel format / encoding of the buffer content. */
|
|
7
|
+
type: 'jpeg' | 'rgb' | 'rgba' | 'grayscale';
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
/** Dimensions of a single GFM table detected on a page. */
|
|
12
|
+
export interface PageTable {
|
|
13
|
+
/** Number of data rows (header and separator lines excluded). */
|
|
14
|
+
rows: number;
|
|
15
|
+
/** Number of columns inferred from the header line. */
|
|
16
|
+
cols: number;
|
|
17
|
+
}
|
|
18
|
+
/** Structured representation of a single PDF page. */
|
|
19
|
+
export interface Page {
|
|
20
|
+
pageNumber: number;
|
|
21
|
+
/** Cleaned body text, with reconstructed GFM tables. Running headers/footers removed. */
|
|
22
|
+
text: string;
|
|
23
|
+
/**
|
|
24
|
+
* Running page header detected across ≥ 3 consecutive pages (e.g. chapter title,
|
|
25
|
+
* magazine section name). Undefined for the poppler engine or single-page PDFs.
|
|
26
|
+
*/
|
|
27
|
+
header?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Running page footer detected across ≥ 3 consecutive pages (e.g. folio number,
|
|
30
|
+
* document title). Undefined for the poppler engine or single-page PDFs.
|
|
31
|
+
*/
|
|
32
|
+
footer?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Dimensions of each GFM table found in `text`.
|
|
35
|
+
* Used by `callLLMForParsingPDF` to select an appropriate model:
|
|
36
|
+
* pages with wide (cols > 3) or long (rows > 10) tables are upgraded
|
|
37
|
+
* from `LOW-fast` to `MEDIUM-fast` automatically.
|
|
38
|
+
*/
|
|
39
|
+
tables: PageTable[];
|
|
40
|
+
/** Images extracted from the page. Always empty for the poppler engine. */
|
|
41
|
+
images: PageImage[];
|
|
42
|
+
}
|
|
43
|
+
/** Extraction backend selection. */
|
|
44
|
+
export type PdftotextEngine = 'poppler' | 'mupdf';
|
|
6
45
|
/**
|
|
7
|
-
*
|
|
46
|
+
* Converts extracted PDF content to clean Markdown via LLM.
|
|
8
47
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
48
|
+
* Two paths depending on the `pdfData` type:
|
|
49
|
+
*
|
|
50
|
+
* **`Page[]` (mupdf path)** — `MapLLM.reduce`, one page per chunk.
|
|
51
|
+
* Each page is processed by `mupdfPagePrompt` (heading normalisation, broken-cell
|
|
52
|
+
* fusion, repeated-header removal). No frontmatter is added here; the caller
|
|
53
|
+
* (`pdf2markdown`) prepends the single YAML block.
|
|
54
|
+
*
|
|
55
|
+
* NOTE: `finalReduce` is intentionally disabled — it is reserved for a future
|
|
56
|
+
* "N-page light summary" feature where a second LLM pass synthesises the whole
|
|
57
|
+
* document into a shorter version.
|
|
58
|
+
*
|
|
59
|
+
* A raw `string` (e.g. from `html2markdown`) is automatically wrapped into a
|
|
60
|
+
* single `Page` so both callers share the exact same code path.
|
|
61
|
+
*
|
|
62
|
+
* @param inputfile - Original file path (used for logging only).
|
|
63
|
+
* @param pdfData - Either a `Page[]` array (mupdf) or a raw string.
|
|
64
|
+
* @param links - External links appended as `## Liens` footer (string path).
|
|
65
|
+
* @param model - LLM model alias (default: `'MEDIUM-fast'`).
|
|
14
66
|
*/
|
|
15
|
-
export declare function callLLMForParsingPDF(inputfile: string, pdfData:
|
|
67
|
+
export declare function callLLMForParsingPDF(inputfile: string, pdfData: Page[] | string, links?: {
|
|
68
|
+
text: string;
|
|
69
|
+
href: string;
|
|
70
|
+
}[], model?: string): Promise<{
|
|
16
71
|
markdown: string;
|
|
17
72
|
cost: number;
|
|
18
73
|
}>;
|
|
19
74
|
/**
|
|
20
|
-
* Parses an HTML file and converts it to markdown using
|
|
75
|
+
* Parses an HTML file and converts it to markdown using LLM.
|
|
21
76
|
*
|
|
22
77
|
* @param {string} output - The directory path where the output markdown file will be saved.
|
|
23
78
|
* @param {string} file - The path to the HTML file to be parsed.
|
|
24
79
|
* @param {string} service - The service name used as part of the output filename output.
|
|
25
80
|
* @param {string} model - The model to use for parsing (default: "MEDIUM-fast")
|
|
26
|
-
* @returns {Promise<{markdown: string, cost: number}>} - The generated markdown content and the cost of the
|
|
81
|
+
* @returns {Promise<{markdown: string, cost: number}>} - The generated markdown content and the cost of the API call.
|
|
27
82
|
*/
|
|
28
83
|
export declare function html2markdown(output: string, file: string, service: string, model?: string): Promise<{
|
|
29
84
|
markdown: string;
|
|
30
85
|
cost: number;
|
|
31
86
|
}>;
|
|
32
87
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
88
|
+
* Extracts plain text from a PDF using the system `pdftotext` binary (poppler-utils).
|
|
89
|
+
*
|
|
90
|
+
* - Pages are delimited by form-feed (\f) characters in the binary's output.
|
|
91
|
+
* - Excessive blank lines are normalised (3+ → 2).
|
|
92
|
+
* - Images are NOT extracted (always []).
|
|
93
|
+
*
|
|
94
|
+
* NOTE: Better alternative is `pdftotext_pdfjs` which uses Mozilla's PDF engine
|
|
95
|
+
* to extract text + images + links in a single Node.js-native pass, with better
|
|
96
|
+
* table reconstruction for complex layouts. See `pdftotext_pdfjs` for details.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} pdfPath - Absolute path to the PDF file.
|
|
99
|
+
* @param {string} outputDir - Directory used for temporary files.
|
|
100
|
+
* @returns {Promise<Page[]>} One `Page` per PDF page, text-only.
|
|
101
|
+
*/
|
|
102
|
+
export declare function pdftotext_poppler(pdfPath: string, outputDir: string): Promise<Page[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Extracts text, reconstructed tables, links, and optionally page-raster images
|
|
105
|
+
* from a PDF using the **mupdf** npm package (WASM build of the MuPDF C library).
|
|
106
|
+
*
|
|
107
|
+
* Key advantages over the poppler engine:
|
|
108
|
+
* - `table-hunt` detects tables geometrically even in **untagged** PDFs.
|
|
109
|
+
* - `segment` splits the page into logical reading-order blocks.
|
|
110
|
+
* - Significantly faster than pdfjs for large documents.
|
|
111
|
+
* - No shell binary dependency (pure WASM, runs anywhere Node.js does).
|
|
112
|
+
*
|
|
113
|
+
* Images (opt-in via `withImages: true`): each page is rasterised at 1.5× scale
|
|
114
|
+
* (≈ 113 DPI). The `imageFormat` option controls encoding:
|
|
115
|
+
*
|
|
116
|
+
* | format | size/page (base64) | notes |
|
|
117
|
+
* |-------------|-------------------|--------------------------------|
|
|
118
|
+
* | `'rgb'` | ≈ 4.4 MB | raw RGB, lossless, large |
|
|
119
|
+
* | `'gray'` | ≈ 1.5 MB | raw grayscale, 3× smaller |
|
|
120
|
+
* | `'jpeg'` | ≈ 100–200 KB | JPEG quality 75, 31× smaller |
|
|
121
|
+
*
|
|
122
|
+
* Disabled by default because image data quickly exhausts stdout buffers for
|
|
123
|
+
* large documents. Use `jpeg` for production with vision models.
|
|
124
|
+
*
|
|
125
|
+
* NOTE: `mupdf` is ESM-only. Extraction is delegated to a standalone
|
|
126
|
+
* `mupdf-extract.mjs` worker spawned via `execAsync`, which avoids any
|
|
127
|
+
* ESM/CJS interoperability issues in the main process and under ts-jest.
|
|
128
|
+
*
|
|
129
|
+
* @param {string} pdfPath - Absolute path to the PDF file.
|
|
130
|
+
* @param {object} [options]
|
|
131
|
+
* @param {boolean} [options.withImages=false] - Rasterise each page.
|
|
132
|
+
* @param {'rgb'|'gray'|'jpeg'} [options.imageFormat='rgb'] - Pixel encoding.
|
|
133
|
+
* @returns {Promise<Page[]>} One `Page` per PDF page with text, GFM tables, and optional images.
|
|
43
134
|
*/
|
|
44
|
-
export declare function
|
|
135
|
+
export declare function pdftotext_mupdf(pdfPath: string, options?: {
|
|
136
|
+
withImages?: boolean;
|
|
137
|
+
imageFormat?: 'rgb' | 'gray' | 'jpeg';
|
|
138
|
+
}): Promise<Page[]>;
|
|
139
|
+
/**
|
|
140
|
+
* Converts a PDF to a structured Markdown file.
|
|
141
|
+
*
|
|
142
|
+
* Pipeline:
|
|
143
|
+
* 1. `pdftotext_mupdf` (or poppler) → `Page[]`
|
|
144
|
+
* 2. `callLLMForParsingPDF` — MapLLM.reduce, one page per chunk
|
|
145
|
+
* 3. Prepend a **single** YAML frontmatter block and write to `outputDir`.
|
|
146
|
+
*
|
|
147
|
+
* Model choice: `LOW-fast` is sufficient — mupdf output is already clean GFM;
|
|
148
|
+
* the LLM only normalises headings and removes repeated headers/footers.
|
|
149
|
+
* Use `MEDIUM-fast` for complex layouts that need heavier restructuring.
|
|
150
|
+
*
|
|
151
|
+
* @param outputDir - Directory for the output `.md` file.
|
|
152
|
+
* @param pdf - Absolute path to the PDF file.
|
|
153
|
+
* @param matter - Document metadata; defaults derived from filename.
|
|
154
|
+
* @param model - LLM model alias (default: `'LOW-fast'`).
|
|
155
|
+
* @param engine - Extraction backend (default: `'mupdf'`).
|
|
156
|
+
* @returns `{ markdown, outputPath }` — frontmatter-prefixed markdown and output path.
|
|
157
|
+
*/
|
|
158
|
+
export declare function pdf2markdown(outputDir: string, pdf: string, matter: FrontMatter | null, model?: string, engine?: PdftotextEngine): Promise<{
|
|
45
159
|
markdown: string;
|
|
46
|
-
cost: number;
|
|
47
160
|
outputPath: string;
|
|
48
161
|
}>;
|