agentic-api 2.0.646 → 2.0.684

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.
@@ -40,20 +40,22 @@ 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");
54
53
  /**
55
54
  * Synchronise une branche PR avec son mergeBase pour corriger les références orphelines
56
55
  *
56
+ * @deprecated Utiliser le workflow applicatif (RulesWorkflow.syncPullRequest) et
57
+ * les opérations robustes orientées Git Notes. API conservée pour compatibilité.
58
+ *
57
59
  * FIXME: Cette fonction a un problème de gestion des métadonnées manquantes.
58
60
  *
59
61
  * PROBLÈME IDENTIFIÉ:
@@ -191,7 +193,7 @@ async function gitSyncPR(git, branch, user) {
191
193
  * @param branch Nom de la branche PR
192
194
  * @param validationToken Token utilisé pour marquer la fermeture (optionnel, utilise la config par défaut)
193
195
  * @returns true si le PR est fermé (dernier commit contient le token de validation)
194
- * DEPRECATED: use gitIsPRClosedRobust instead
196
+ * @deprecated Utiliser gitIsPRClosedRobust.
195
197
  */
196
198
  async function gitIsPRClosed(git, branch) {
197
199
  return gitIsPRClosedRobust(git, branch);
@@ -199,6 +201,8 @@ async function gitIsPRClosed(git, branch) {
199
201
  /**
200
202
  * Vérifie si une branche PR est fermée en utilisant Git Notes (avec fallback)
201
203
  * Version robuste qui remplace gitIsPRClosed
204
+ * @deprecated Préférer gitLoadPR() pour récupérer l'état PR complet.
205
+ *
202
206
  * @param git Instance Git
203
207
  * @param branch Nom de la branche PR
204
208
  * @param validationToken Token utilisé pour marquer la fermeture (optionnel, utilise la config par défaut)
@@ -287,6 +291,8 @@ async function gitGetAllPR(git, options = {}) {
287
291
  }
288
292
  /**
289
293
  * Finds closed PRs by scanning the history of the draft branch for merge commits with PR metadata.
294
+ * @deprecated Utiliser gitGetAllPR(git, { closed: true }) pour unifier le listing PR.
295
+ *
290
296
  * @param git SimpleGit instance
291
297
  * @param gitConfig The git configuration
292
298
  * @returns A list of PRInfo objects for closed PRs.
@@ -342,49 +348,6 @@ async function gitLoadPR(git, branch) {
342
348
  throw new errors_1.GitOperationError(`Failed to retrieve PR: ${error}`, 'pr_load');
343
349
  }
344
350
  }
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
351
  async function gitPRUpdateComments(git, branch, details, config) {
389
352
  const gitConf = (0, repo_tools_1.gitLoad)(config);
390
353
  const metadata = await gitGetPRMetadata(git, branch, config);
@@ -405,7 +368,8 @@ async function gitPRUpdateComments(git, branch, details, config) {
405
368
  return gitLoadPR(git, branch);
406
369
  }
407
370
  /**
408
- * DEPRECATED: use gitClosePRRobust instead
371
+ * @deprecated Utiliser gitClosePRRobust.
372
+ *
409
373
  * Ferme un PR en ajoutant un commit avec le token de validation
410
374
  * @param git Instance Git
411
375
  * @param branch Branche PR à fermer
@@ -483,6 +447,7 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
483
447
  // Note: "ours" dans ce contexte signifie "garder la version de la branche qu'on merge" (la PR)
484
448
  // car nous sommes sur rule-editor et on merge la PR
485
449
  let mergeResult;
450
+ let mergeCommitHash;
486
451
  try {
487
452
  mergeResult = await git
488
453
  .env({
@@ -498,6 +463,7 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
498
463
  '-m', `Merge branch '${branch}'`,
499
464
  branch
500
465
  ]);
466
+ mergeCommitHash = (await git.revparse(['HEAD'])).trim();
501
467
  }
502
468
  catch (mergeError) {
503
469
  if (gitConf.verbose) {
@@ -537,15 +503,22 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
537
503
  }
538
504
  }
539
505
  // Amend le commit de merge avec les bons contenus
540
- await git.commit('--amend', ['--no-edit'], {
506
+ const amendResult = await git.commit('--amend', ['--no-edit'], {
541
507
  '--author': `${closedBy.name} <${closedBy.email}>`
542
508
  });
509
+ mergeCommitHash = amendResult.commit || (await git.revparse(['HEAD'])).trim();
543
510
  mergeResult = { summary: { changes: prFiles.length } };
544
511
  }
545
512
  catch (fallbackError) {
546
513
  throw new errors_1.PRClosureError(`Failed to merge PR ${branch} with all strategies: ${mergeError}\nFallback error: ${fallbackError}`, branch, 'merge_failed');
547
514
  }
548
515
  }
516
+ // 6. Attacher aussi la note au commit de merge sur la branche cible.
517
+ // Cela garantit la traçabilité même si la branche PR est supprimée.
518
+ if (!mergeCommitHash) {
519
+ mergeCommitHash = (await git.revparse(['HEAD'])).trim();
520
+ }
521
+ await (0, repo_tools_1.gitWriteNote)(git, mergeCommitHash, finalMetadata, gitConf.gitNotes.namespace);
549
522
  const result = {
550
523
  metadata: finalMetadata,
551
524
  failed: false,
@@ -583,37 +556,6 @@ async function gitClosePRRobust(git, branch, closedBy, message, config) {
583
556
  (0, repo_tools_1.unlock)('checkout');
584
557
  }
585
558
  }
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
559
  /**
618
560
  * Crée une nouvelle branche de validation (pour un PR vers rule-editor)
619
561
  * à partir d'une branche source (typiquement rule-editor).
@@ -639,6 +581,20 @@ async function gitNewValidationRequest(git, files, description, author, options
639
581
  throw new errors_1.PRCreationError('Author is required', undefined, files);
640
582
  }
641
583
  try {
584
+ // Vérification atomique côté API: empêcher plusieurs PR ouvertes sur les mêmes fichiers.
585
+ const openPRs = await gitGetAllPR(git, {
586
+ closed: false,
587
+ validationPrefix: validationBranchPrefix
588
+ });
589
+ const conflictingPRs = openPRs.filter((pr) => pr.files.some((prFile) => files.includes(prFile)));
590
+ if (conflictingPRs.length > 0) {
591
+ const conflictingFiles = files.filter((file) => conflictingPRs.some((pr) => pr.files.includes(file)));
592
+ if (gitConfig.verbose) {
593
+ console.log('🌶️ DEBUG: gitNewValidationRequest -- conflicting PRs:', conflictingPRs.map((pr) => pr.branch));
594
+ }
595
+ const firstConflict = conflictingPRs[0].branch;
596
+ throw new errors_1.PRCreationError(`Le fichier est déjà dans la validation en cours #${firstConflict.replace(validationBranchPrefix, '')}`, firstConflict, conflictingFiles);
597
+ }
642
598
  // ✅ CLEANUP: Nettoyer tout état de merge corrompu avant de créer la branche
643
599
  // Cela évite l'erreur "you need to resolve your current index first"
644
600
  try {
@@ -654,7 +610,7 @@ async function gitNewValidationRequest(git, files, description, author, options
654
610
  console.warn('Cleanup before branch creation failed (non-critical):', cleanupError);
655
611
  }
656
612
  }
657
- const nextID = await gitGetNextPRNumber(git, validationBranchPrefix);
613
+ const nextID = await (0, repo_1.gitAllocateNextPRNumber)(git, validationBranchPrefix, gitConfig);
658
614
  const newBranchName = `${validationBranchPrefix}${nextID}`;
659
615
  await git.checkoutBranch(newBranchName, sourceBranch);
660
616
  const initialCommitMessage = `#${nextID} ${description}`;
@@ -710,7 +666,7 @@ async function gitNewValidationRequest(git, files, description, author, options
710
666
  }
711
667
  }
712
668
  /**
713
- * DEPRECATED
669
+ * @deprecated Utiliser gitNewValidationRequest().
714
670
  */
715
671
  async function gitNewPR(git, files, description, author, options = {}) {
716
672
  return gitNewValidationRequest(git, files, description, author, options);
@@ -122,7 +122,7 @@ 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) */
125
+ /** FIXME(oldfile): champ legacy transitoire pour notification UI rename */
126
126
  oldfile?: string;
127
127
  /** Auteur original de la règle (format git: "Name <email>") */
128
128
  author?: string;
@@ -38,7 +38,7 @@ export declare class AgentStateGraph implements IAgentStateGraph {
38
38
  set(agentName: string, content: string): void;
39
39
  /**
40
40
  * Ajoute une étape au CONTEXT TRAIL et met à jour le message system
41
- * Injecte automatiquement le trail dans le system message via updateSystemMessage()
41
+ * Injecte automatiquement le trail dans le system message via updateSystemContextTrail()
42
42
  *
43
43
  * Utilisée par:
44
44
  * - readCompletionsStream (responses.ts) : après chaque tool call exécuté
@@ -64,7 +64,7 @@ export declare class AgentStateGraph implements IAgentStateGraph {
64
64
  * Met à jour le message system avec le nouveau trail via regexp
65
65
  * @param agentName Nom de l'agent
66
66
  */
67
- private updateSystemMessage;
67
+ private updateSystemContextTrail;
68
68
  /**
69
69
  * Additionne l'usage des tokens pour un agent
70
70
  * @param agentName Nom de l'agent
@@ -86,12 +86,12 @@ class AgentStateGraph {
86
86
  discussion.messages[0].agent = systemMessage.agent;
87
87
  discussion.messages[0].timestamp = new Date();
88
88
  }
89
- this.updateSystemMessage(discussion);
89
+ this.updateSystemContextTrail(discussion);
90
90
  discussion.updatedAt = new Date();
91
91
  }
92
92
  /**
93
93
  * Ajoute une étape au CONTEXT TRAIL et met à jour le message system
94
- * Injecte automatiquement le trail dans le system message via updateSystemMessage()
94
+ * Injecte automatiquement le trail dans le system message via updateSystemContextTrail()
95
95
  *
96
96
  * Utilisée par:
97
97
  * - readCompletionsStream (responses.ts) : après chaque tool call exécuté
@@ -105,7 +105,7 @@ class AgentStateGraph {
105
105
  if (!discussion)
106
106
  return;
107
107
  discussion.trailSteps.push(step);
108
- this.updateSystemMessage(discussion);
108
+ this.updateSystemContextTrail(discussion);
109
109
  }
110
110
  /**
111
111
  * Retourne tous les steps du CONTEXT TRAIL pour une discussion
@@ -127,15 +127,14 @@ class AgentStateGraph {
127
127
  return '(No actions yet)';
128
128
  }
129
129
  return discussion.trailSteps.map(s => {
130
- const idPart = s.id ? ` [id: ${s.id}]` : '';
131
- return `- ${s.tool}: ${s.context} "${s.reason}"${idPart}`;
130
+ return `- ${s.tool}: ${s.reason}`;
132
131
  }).join('\n');
133
132
  }
134
133
  /**
135
134
  * Met à jour le message system avec le nouveau trail via regexp
136
135
  * @param agentName Nom de l'agent
137
136
  */
138
- updateSystemMessage(discussion) {
137
+ updateSystemContextTrail(discussion) {
139
138
  const systemMessage = discussion.messages.find((m) => m.role === 'system');
140
139
  if (!systemMessage)
141
140
  return;
@@ -41,14 +41,10 @@ export interface TokenUsage {
41
41
  * Utilisé pour maintenir une mémoire de travail des actions effectuées par les outils
42
42
  */
43
43
  export interface StepTrail {
44
- /** Nom de l'outil (ex: "transferAgents", "database") */
44
+ /** Nom de l'outil (ex: "lookupMfilesIntervenant", "lookupKnowledge") */
45
45
  tool: string;
46
- /** Contexte de l'action (ex: "orientation guess-word") */
47
- context: string;
48
- /** Justification/raison de l'action */
46
+ /** Raison de l'appel (context du résultat ou justification de l'appel) */
49
47
  reason: string;
50
- /** ID optionnel pour détection de boucles */
51
- id?: string;
52
48
  }
53
49
  /**
54
50
  * Discussion d'agent - thread de messages pour un agent spécifique
@@ -42,6 +42,7 @@ export type ToolContractOutput<T> = {
42
42
  can_retry: boolean;
43
43
  error_code?: string;
44
44
  transfer_message?: string;
45
+ pipeline?: string[];
45
46
  };
46
47
  };
47
48
  export interface AgentModelMapping {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-api",
3
- "version": "2.0.646",
3
+ "version": "2.0.684",
4
4
  "description": "API pour l'orchestration d'agents intelligents avec séquences et escalades automatiques",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",