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
package/dist/src/llm/xai.js
CHANGED
|
@@ -54,26 +54,31 @@ exports.LLMxai = {
|
|
|
54
54
|
},
|
|
55
55
|
"MEDIUM-fast": {
|
|
56
56
|
temperature: 0.2,
|
|
57
|
-
model: "grok-4-1-fast-reasoning",
|
|
57
|
+
model: "grok-4-1-fast-non-reasoning",
|
|
58
58
|
stream: true
|
|
59
59
|
},
|
|
60
60
|
"MEDIUM": {
|
|
61
61
|
temperature: 0.2,
|
|
62
|
-
model: "grok-4-fast-reasoning",
|
|
62
|
+
model: "grok-4-1-fast-reasoning",
|
|
63
63
|
stream: true
|
|
64
64
|
},
|
|
65
65
|
"HIGH-fast": {
|
|
66
|
-
model: "grok-4-1-fast-reasoning",
|
|
66
|
+
model: "grok-4-1-fast-non-reasoning",
|
|
67
|
+
temperature: 0.2,
|
|
68
|
+
stream: true
|
|
69
|
+
},
|
|
70
|
+
"HIGH-codex": {
|
|
71
|
+
model: "grok-code-fast-1",
|
|
67
72
|
temperature: 0.2,
|
|
68
73
|
stream: true
|
|
69
74
|
},
|
|
70
75
|
"HIGH": {
|
|
71
|
-
model: "grok-4",
|
|
76
|
+
model: "grok-4-1-fast-reasoning",
|
|
72
77
|
temperature: 0.2,
|
|
73
78
|
stream: true
|
|
74
79
|
},
|
|
75
80
|
"HIGH-medium": {
|
|
76
|
-
model: "grok-4",
|
|
81
|
+
model: "grok-4-1-fast-non-reasoning",
|
|
77
82
|
temperature: 0.2,
|
|
78
83
|
stream: true
|
|
79
84
|
},
|
|
@@ -84,7 +89,7 @@ exports.LLMxai = {
|
|
|
84
89
|
},
|
|
85
90
|
"SEARCH": {
|
|
86
91
|
temperature: 0.2,
|
|
87
|
-
model: "grok-4-fast-reasoning",
|
|
92
|
+
model: "grok-4-1-fast-non-reasoning",
|
|
88
93
|
tools: [{ type: "web_search" }],
|
|
89
94
|
},
|
|
90
95
|
};
|
package/dist/src/prompts.d.ts
CHANGED
|
@@ -5,6 +5,20 @@ export declare const transferAgentPromptStructured = "\nCet outil permet de tran
|
|
|
5
5
|
export declare const transferAgentPromptHandoff = "# Contexte g\u00E9n\u00E9ral\nTu fais partie d'un syst\u00E8me multi-agents con\u00E7u pour faciliter la coordination et l'ex\u00E9cution entre plusieurs agents. Tu utilises deux abstractions principales : **Agents** et **Transferts**. \nUn agent poss\u00E8de des instructions et des outils, et peut, quand c'est appropri\u00E9, transmettre une conversation \u00E0 un autre agent avec une autre sp\u00E9cialisation. Les transferts se font en appelant un outil nomm\u00E9e `transferAgents`.\nLes transferts entre agents sont g\u00E9r\u00E9s automatiquement en arri\u00E8re-plan ; tu ne dois jamais mentionner ou attirer l'attention sur ces transferts dans ta conversation avec l'utilisateur.\n\n## PROTOCOLE CONTEXT TRAIL `<context-trail>`\nTU DOIS consulter le trail avant de prendre une d\u00E9cision pour \u00E9viter les r\u00E9p\u00E9titions et te coordonner avec les autres agents. Le trail est visible pour toi dans tes instructions syst\u00E8me pour:\n- D\u00E9tecter les boucles et ne pas les reproduire (action d\u00E9j\u00E0 faite \u2192 surtout ne pas r\u00E9p\u00E9ter)\n- Comprendre les \u00E9tapes et ce qui reste\n- Pr\u00E9vention du drift (maintenir l'alignement \u00E0 l'objectif)\n\n";
|
|
6
6
|
export declare const defaultOutputPrompt = "\n# OUTPUT INSTRUCTIONS\n- Only output CoT and Markdown.\n- Do not output the markdown code syntax, only the content.\n- Use the name of the document on top of the markdown.\n- You use bulleted lists for output, not numbered lists.\n- Do not output the main index as a section.\n- Do not output the images which are not relevant in section.\n- Ensure you follow ALL these instructions when creating your output.\n- EXAMPLE OF SECTION: `# {{page name}} - {{titre}}\n{{content}}`\n";
|
|
7
7
|
export declare const textToMarkdownPrompt = "# R\u00D4LE:\n- Tu es un expert en transformation de documents proc\u00E9duraux pour un RAG (Retrieval-Augmented Generation).\n- Ton r\u00F4le est de d\u00E9composer une proc\u00E9dure en plusieurs unit\u00E9s de connaissance atomiques, optimis\u00E9es pour la recherche s\u00E9mantique avec HNSW (cosine).\n- Tu agis comme un moteur de \"reader view\" capable de construire une version fluide et lisible du document original.\n\n# MISSION:\n- Tu dois analyser le document fourni (texte brut ou HTML) et le d\u00E9couper en plusieurs unit\u00E9s de connaissance distinctes.\n- Chaque unit\u00E9 doit commencer par \"Titre:\" et \u00EAtre s\u00E9par\u00E9e de la suivante par \"---\".\n- Tu dois suivre rigoureusement le format de sortie et les r\u00E8gles de structuration.\n- Tu utilises le DICTIONNAIRE pour comprendre le jargon de l'entreprise.\n\n# R\u00C8GLES DE STRUCTURATION D'UNE UNIT\u00C9\n\n1. **Titre (Obligatoire)**\n - Le champ \"Titre:\" Une phrase sp\u00E9cifique \u00E0 la section qui contient l'objectif, l'action, le p\u00E9rim\u00E8tre et le b\u00E9n\u00E9ficiaire.\n - Il sert de r\u00E9sum\u00E9 dense unique et contextualis\u00E9 pour l'embedding.\n\n2. **Section (Obligatoire)**\n - Le champ \"Section:\" contient le contenu d\u00E9taill\u00E9 et exhaustif de l'unit\u00E9, incluant le contexte, les \u00E9tapes et les actions.\n\n3. **Champs Optionnels (\u00E0 omettre si vides)**\n - **Exemple:** : Uniquement si un cas d'usage concret ou une situation illustrative est mentionn\u00E9.\n - **Template:** : Uniquement si un mod\u00E8le de lettre, d'e-mail ou de formulaire est d\u00E9crit.\n - **Exception:** : Uniquement si une variante \u00E0 la r\u00E8gle g\u00E9n\u00E9rale est sp\u00E9cifi\u00E9e.\n - **Si un champ est vide, tu ne dois PAS l'inclure dans la sortie.**\n\n# FORMAT DE SORTIE\n- La sortie ne doit contenir AUCUN titre Markdown (pas de \"##\") ni de frontmatter.\n- Chaque unit\u00E9 de connaissance est un bloc de texte.\n- Le s\u00E9parateur \"---\" est utilis\u00E9 exclusivement entre chaque unit\u00E9.\n\n## EXEMPLE DE SORTIE ATTENDUE\nTitre: {Objectif proc\u00E9dure} via {action} incluant {p\u00E9rim\u00E8tre} et {b\u00E9n\u00E9ficiaire}\nSection: Contenu d\u00E9taill\u00E9, contexte, \u00E9tapes, actions\nExemple: Cas d'usage illustratif (omis si vide)\nTemplate: Mod\u00E8le de document r\u00E9utilisable (omis si vide)\nException: Variante \u00E0 la r\u00E8gle g\u00E9n\u00E9rale (omis si vide)\n---\nTitre: Un autre objectif via une autre action\nSection: Le contenu de la deuxi\u00E8me unit\u00E9.\n---\nTitre: Un troisi\u00E8me objectif via une troisi\u00E8me action\nSection: Le contenu de la troisi\u00E8me unit\u00E9.\nTemplate: Un mod\u00E8le de lettre est d\u00E9crit ici.\n\n\n# DIRECTIVES DE NETTOYAGE\n- Analyser **chaque ligne du document** pour identifier sa structure logique (paragraphes, listes, tableaux).\n- Supprimer les caract\u00E8res invisibles ou parasites fr\u00E9quents issus d'une conversion PDF (ex : saut de page \"\\f\").\n- Masquer toute information sensible li\u00E9e \u00E0 une authentification avec des ast\u00E9risques (ex : `jo***3`).\n- \u26A0\uFE0F Les sections qui contiennent uniquement des liens relatifs \u00E0 des proc\u00E9dures sont supprim\u00E9es du r\u00E9sultat final.\n\n# DIRECTIVES PRIORITAIRES POUR CAS COMPLEXES\n- Ne jamais r\u00E9sumer les sections comportant des sc\u00E9narios conditionnels (\"Si... alors...\"). Tous les cas doivent \u00EAtre explicitement d\u00E9velopp\u00E9s.\n- Toute **logique de d\u00E9cision op\u00E9rationnelle** doit \u00EAtre repr\u00E9sent\u00E9e avec une structure claire : **liste num\u00E9rot\u00E9e, liste imbriqu\u00E9e ou tableau de d\u00E9cision**.\n- Lorsque le document mentionne une situation **urgente** (mots cl\u00E9s : \"URGENT\", \"imm\u00E9diat\"), ajouter une ic\u00F4ne \"\u26A0\uFE0F\" au d\u00E9but de l'\u00E9tape.\n\n# DICTIONNAIRE:\n- Logiciels Sp\u00E9cifiques: Quorum, MFiles, Base de connaissance, Teams, HomePad, Todoist, Mammutt, E-banking, INCH, Ecopartage, Immowise.\n- SGC: Service de Gestion de la Client\u00E8le\n- GED: service qui g\u00E8re le scan des documents, la mise sous plis, l'\u00E9conomat, le r\u00E9assort des salles de pauses, la saisie des donn\u00E9es pour orienter les documents dans M-Files\n- MED: Mise en demeure.\n- WC: Toilettes.\n- M-Files: logiciel de gestion de documents\n- PR ou PRSA: Pilet & Renaud SA\n- PPE: Service qui g\u00E8re les copropri\u00E9t\u00E9s.\n- GP: Garantie Bancaire\n- WC: Toilettes.\n- BAL: Boite \u00E0 Lettre\n- DD: Arrangement de paiement pour facture due mais qui n'est pas du loyer.\n- copro: copropri\u00E9taire (attention \u00E0 ne pas confondre avec gopros)\n- un bon (bons): ordre d'intervention pour travaux (ex, bon de travail, cr\u00E9ation de bons, bons, etc).\n- La Date \u00E0 jour Locataire: le dernier mois qui a \u00E9t\u00E9 pay\u00E9 par le locataire.\n\n# APPROCHE CoT (Chain of Thought):\n- Utilise un processus de r\u00E9flexion structur\u00E9 encadr\u00E9 par les balises <thinking></thinking> avant de g\u00E9n\u00E9rer le r\u00E9sultat final. \n- Dans cette section de raisonnement tu DOIS:\n 1. Analyse toutes les DIRECTIVES et instructions qui sont \u00E0 utiliser conjointement avec la question.\n 2. D\u00E9compose la solution en \u00E9tapes claires, avec des mots-cl\u00E9s non format\u00E9s et en utilisant des balises <step> \u00E0 l'int\u00E9rieur de la r\u00E9flexion <thinking>.\n 3. Ajuste continuellement ton raisonnement en fonction des r\u00E9sultats interm\u00E9diaires et des r\u00E9flexions.\n\n\n# OUTPUT INSTRUCTIONS\n- Only output CoT and Markdown.\n- Do not output the markdown code syntax, only the content.\n- Use the name of the document on top of the markdown.\n- You use bulleted lists for output, not numbered lists.\n- Do not output the main index as a section.\n- Do not output the images which are not relevant in section.\n- Ensure you follow ALL these instructions when creating your output.\n- EXAMPLE OF SECTION: `# {{page name}} - {{titre}}\n{{content}}`\n\n";
|
|
8
|
+
/**
|
|
9
|
+
* Per-page digest prompt for `callLLMForParsingPDF` (mupdf path).
|
|
10
|
+
*
|
|
11
|
+
* mupdf already provides GFM tables, bullet lists, and link footers.
|
|
12
|
+
* This prompt only normalises what mupdf leaves raw:
|
|
13
|
+
* - title hierarchy (MAJUSCULES, colon endings)
|
|
14
|
+
* - broken multi-line table cells
|
|
15
|
+
* - repeated page headers / footers
|
|
16
|
+
* - critical-element highlighting
|
|
17
|
+
*
|
|
18
|
+
* **No frontmatter** — the single YAML block is added by the caller (pdf2markdown).
|
|
19
|
+
* **finalReduce** (disabled) is reserved for a future "N-page light summary" feature.
|
|
20
|
+
*/
|
|
21
|
+
export declare const mupdfPagePrompt = "\nTu es *MarkdownPDF-Pro*.\n\nTu re\u00E7ois le contenu brut d'une page PDF extrait par mupdf : texte et tableaux GFM d\u00E9j\u00E0 partiellement structur\u00E9s.\n\n**Mission :** Nettoie et am\u00E9liore ce contenu en Markdown propre. Ne jamais produire de frontmatter YAML.\n\n**Ce que mupdf a d\u00E9j\u00E0 fourni (\u00E0 pr\u00E9server) :**\n- Tableaux `| col | col |` en GFM \u2014 ne pas les supprimer, mais possibilit\u00E9 d'am\u00E9liorer et corriger les cellules cass\u00E9es.\n- Listes `-` d\u00E9tect\u00E9es dans le PDF\n- Section `## Liens` en pied de page si pr\u00E9sente\n\n**Ce qu'il reste \u00E0 faire :**\n1. **Titres** : ligne en MAJUSCULES \u2192 `##` ; ligne finissant par `:` \u2192 `###` ; titre principal \u00E9vident \u2192 `#`.\n2. **Fusion de cellules cass\u00E9es** : si une cellule est coup\u00E9e sur plusieurs lignes (continuation sans s\u00E9parateur, hyph\u00E9nation en fin de ligne), fusionner dans la m\u00EAme cellule.\n3. **En-t\u00EAtes/pieds r\u00E9p\u00E9titifs** : supprimer les lignes qui ne sont que num\u00E9ro de page, logo ou nom d'entreprise sans apporter de contenu.\n4. **\u00C9l\u00E9ments critiques** : informations v\u00E9ritablement importantes \u2192 `\u26A0\uFE0F **gras**`.\n5. **Nettoyage** : un seul saut de ligne vide entre blocs ; pas de balises HTML ; conserver signes et abr\u00E9viations.\n6. **Coh\u00E9rence des tableaux** : normaliser le nombre de colonnes si des cellules manquent.\n7. **Groupes r\u00E9p\u00E9t\u00E9s dans un tableau** : si la m\u00EAme valeur de groupe appara\u00EEt dans la premi\u00E8re colonne sur plusieurs lignes cons\u00E9cutives (ex. `Code | ABC | \u2026`, `Code | DEF | \u2026`), il faut simplifier le groupe avec un titre.\n**Ne jamais :**\n- Inventer du contenu ou reformuler le fond\n- Ajouter un frontmatter YAML (`---`)\n- Ajouter des commentaires ou explications\n\nR\u00E9ponds uniquement avec le Markdown nettoy\u00E9 de la page.\n";
|
|
8
22
|
export declare const htmlToMarkdownPrompt = "\nVous \u00EAtes *MarkdownPDF-Pro*, un assistant expert charg\u00E9 de transformer un texte brut issu d\u2019un PDF en un fichier Markdown clair et minimaliste, sans mise en page complexe.\nTu travailles dans le contexte de l'entreprise Pilet & Renaud SA. Tu sais que les proc\u00E9dures proviennent des services suivants: SGC (Gestion de la Client\u00E8le), RH, PPE (copropri\u00E9t\u00E9), g\u00E9rance locataire, direction, comptabilit\u00E9, contentieux, IT.\n\n**But :**\nStructurer le contenu pour qu\u2019il soit imm\u00E9diatement lisible dans n\u2019importe quel \u00E9diteur Markdown, tout en pr\u00E9servant la hi\u00E9rarchie logique (titres, listes, tableaux simples).\n\n**Contraintes globales (IMP\u00C9RATIF) :**\n1. Aucune syntaxe HTML, pas de balises <div>, <span>, etc. \n2. Pas de styles CSS ni de code LaTeX. \n3. Utiliser exclusivement les \u00E9l\u00E9ments Markdown suivants : \n * `#` \u2026 `######` pour les titres \n * listes \u00E0 puces `-` ou num\u00E9rot\u00E9es `1.` \n * blocs de citation `>` si n\u00E9cessaire \n * tableaux au format pipe `| Col 1 | Col 2 |` \n * emphase `*italique*` et `**gras**` \n * Front-matter YAML `---\n ...\n---\n` pour les m\u00E9tadonn\u00E9es.\n4. Ne pas ajouter d\u2019analyse ou de commentaires personnels.\n5. Si le service n\u2019est pas d\u00E9duit du texte, laisser `service: unknown`.\n6. **Les tableaux doivent \u00EAtre d\u00E9tect\u00E9s et normalis\u00E9s selon les \u201CR\u00E8gles de TABLE Markdown\u201D ci-dessous (pas de copie brute ligne par ligne).**\n\nRemplir automatiquement le champ `title` sous la forme `{service} - {action} {object} {b\u00E9n\u00E9ficiaire}` en minuscules **uniquement si ces \u00E9l\u00E9ments sont clairement inf\u00E9r\u00E9s** ; sinon, utiliser le premier `# Titre` du document. Ne jamais \u00E9crire \u201Cunknown\u201D dans `title`.\n\n---\n\n### Heuristique de structuration\n1. **D\u00E9tection des titres** \n * Ligne en MAJUSCULES \u2192 `##` \n * Ligne qui finit par \u00AB : \u00BB \u2192 `###` \n * Saut de ligne double + mot initial capitalis\u00E9 \u2192 `##` si > 3 mots sinon `###`.\n2. **Paragraphes** : regrouper les lignes cons\u00E9cutives jusqu\u2019au prochain saut de ligne vide.\n3. **Listes** \n * Convertir les puces d\u2019origine (`\u2022`, `-`, `*`, chiffres suivis de `)` ou `.`). \n * Conserver l\u2019imbrication (quatre espaces par niveau).\n\n---\n\n### R\u00E8gles de TABLE Markdown (g\u00E9n\u00E9riques, robustes)\n1. **D\u00E9tection d\u2019un bloc tableau** : s\u00E9quence de \u22653 lignes pr\u00E9sentant un alignement r\u00E9gulier (espaces/tabs), des s\u00E9parateurs r\u00E9currents, OU une premi\u00E8re colonne contenant des *identifiants plausibles* (ex. codes, IDs, sigles). \n2. **Colonnes** : inf\u00E9rer le nombre de colonnes en analysant la majorit\u00E9 des lignes. Normaliser toutes les lignes \u00E0 ce nombre (remplir les cellules manquantes par vide). \n3. **En-t\u00EAte** : \n - Si une premi\u00E8re ligne contient des libell\u00E9s de colonnes \u2192 utiliser comme `header`. \n - Sinon, g\u00E9n\u00E9rer un en-t\u00EAte minimal et neutre (`Col 1`, `Col 2`, \u2026) ou, si identifi\u00E9, des noms g\u00E9n\u00E9riques (`Identifiant`, `Libell\u00E9`, `Commentaire`). \n4. **Fusion de lignes cass\u00E9es** : joindre aux cellules la/les lignes qui suivent quand elles sont des continuations (indentation, absence de s\u00E9parateur, hyph\u00E9nation en fin de ligne) pour \u00E9viter de cr\u00E9er de fausses lignes. \n5. **En-t\u00EAtes visuels (cat\u00E9gories)** : lignes isol\u00E9es sans s\u00E9parateurs ni motif tabulaire, servant d\u2019intertitre (ex. cat\u00E9gories, sections) \u2192 les rendre en `###` au-dessus du tableau ou entre deux tableaux, **pas** comme des lignes de donn\u00E9es. \n6. **Identifiants / codes** : d\u00E9tecter les *tokens* de type ID (lettres/chiffres/points/traits). Si pr\u00E9sents en premi\u00E8re colonne, **ne pas trier** ; **pr\u00E9server l\u2019ordre d\u2019origine du PDF**. \n7. **S\u00E9paration multi-tableaux** : d\u00E9marrer un nouveau tableau lorsque le sch\u00E9ma de colonnes change, lorsqu\u2019un intertitre visuel survient, ou apr\u00E8s un blanc significatif. \n8. **Nettoyage des cellules** : trim, consolidation des espaces multiples, \u00E9chapper `|` par `|`, conserver les signes et abr\u00E9viations. \n9. **R\u00E9f\u00E9rences crois\u00E9es non list\u00E9es** : si des identifiants sont mentionn\u00E9s dans une cellule (ex. \u201Cutiliser le 123456\u201D) mais n\u2019apparaissent pas comme ligne d\u00E9di\u00E9e, **ne pas les inventer** dans le tableau ; \u00E0 la place, ajouter apr\u00E8s le tableau une section `#### R\u00E9f\u00E9rences crois\u00E9es non list\u00E9es` avec une liste `- 123456 : contexte (extrait bref)` si utile. \n10. **Validation post-g\u00E9n\u00E9ration** : \n - Chaque tableau doit avoir \u22652 colonnes et \u22652 lignes de donn\u00E9es. \n - V\u00E9rifier la coh\u00E9rence (pas de d\u00E9calage de colonnes, pas de titre de cat\u00E9gorie dans les lignes). \n - Si la structure reste ambig\u00FCe, pr\u00E9f\u00E9rer une **liste structur\u00E9e** plut\u00F4t qu\u2019un tableau incorrect.\n\n---\n\n### Sp\u00E9cifique \u00E0 l'entreprise\n- Les informations v\u00E9ritablement critiques peuvent \u00EAtre signal\u00E9es avec `\u26A0\uFE0F` et `**gras**`, sans r\u00E9\u00E9crire le fond. \n- Mentionner par inf\u00E9rence le `service` **uniquement dans le front-matter** ; le corps doit rester fid\u00E8le \u00E0 la source. \n- Ne pas promouvoir des intertitres visuels en alertes `\u26A0\uFE0F`.\n\n---\n\n### \u00C9l\u00E9ments hors-texte\n- **Images** : `` (une ligne par image, \u00E0 l\u2019emplacement d\u2019origine). \n- **Notes de bas de page** : convertir en liens `[^n]` et regrouper \u00E0 la fin sous `## Notes`.\n\n---\n\n### Nettoyage final\n- Supprimer en-t\u00EAtes/pieds de page r\u00E9p\u00E9t\u00E9s (m\u00EAme s\u00E9quence sur \u2265 3 pages). \n- R\u00E9duire les blancs multiples \u00E0 un seul. \n- Conserver un seul saut de ligne vide entre blocs. \n- Supprimer les sections de revue automatique (ex. \u201Crapport de r\u00E9vision\u2026\u201D) quand d\u00E9tectables.\n\n---\n\n### Format d\u2019entr\u00E9e attendu\n**Proc\u00E9dure :**\n1. Lire attentivement le bloc `<<PDF_TEXT>>`. \n2. Appliquer les heuristiques ci-dessus, \u00E9tape par \u00E9tape (raisonnement interne, ne pas afficher). \n3. Produire un **front-matter** puis le **Markdown final brut**, sans d\u00E9limiteurs et sans commentaires.\n\n**Front-matter (YAML) \u00E0 produire :**\n---\ntitle: {service} - {action} {object} {b\u00E9n\u00E9ficiaire} # en minuscules si inf\u00E9r\u00E9s, sinon premier H1\nservice: {service} # \"unknown\" si non d\u00E9duit\nrole: rule\nowner: {owner}\n---\n\n\n";
|
|
9
23
|
export interface UsecaseExtractionOptions {
|
|
10
24
|
model?: string;
|
package/dist/src/prompts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.usecaseExtractionPrompt = exports.htmlToMarkdownPrompt = exports.textToMarkdownPrompt = exports.defaultOutputPrompt = exports.transferAgentPromptHandoff = exports.transferAgentPromptStructured = exports.transferAgentPrompt = exports.transferAgentPrompt__ = exports.transferAgentPrompt_ = void 0;
|
|
3
|
+
exports.usecaseExtractionPrompt = exports.htmlToMarkdownPrompt = exports.mupdfPagePrompt = exports.textToMarkdownPrompt = exports.defaultOutputPrompt = exports.transferAgentPromptHandoff = exports.transferAgentPromptStructured = exports.transferAgentPrompt = exports.transferAgentPrompt__ = exports.transferAgentPrompt_ = void 0;
|
|
4
4
|
exports.transferAgentPrompt_ = `Triggers a transfer of the user to a more specialized agent.
|
|
5
5
|
Calls escalate to a more specialized LLM agent or to a human agent, with additional context.
|
|
6
6
|
Only call this function if one of the available agents is appropriate. Don't transfer to your own agent type.
|
|
@@ -149,6 +149,46 @@ Template: Un modèle de lettre est décrit ici.
|
|
|
149
149
|
|
|
150
150
|
${exports.defaultOutputPrompt}
|
|
151
151
|
`;
|
|
152
|
+
/**
|
|
153
|
+
* Per-page digest prompt for `callLLMForParsingPDF` (mupdf path).
|
|
154
|
+
*
|
|
155
|
+
* mupdf already provides GFM tables, bullet lists, and link footers.
|
|
156
|
+
* This prompt only normalises what mupdf leaves raw:
|
|
157
|
+
* - title hierarchy (MAJUSCULES, colon endings)
|
|
158
|
+
* - broken multi-line table cells
|
|
159
|
+
* - repeated page headers / footers
|
|
160
|
+
* - critical-element highlighting
|
|
161
|
+
*
|
|
162
|
+
* **No frontmatter** — the single YAML block is added by the caller (pdf2markdown).
|
|
163
|
+
* **finalReduce** (disabled) is reserved for a future "N-page light summary" feature.
|
|
164
|
+
*/
|
|
165
|
+
exports.mupdfPagePrompt = `
|
|
166
|
+
Tu es *MarkdownPDF-Pro*.
|
|
167
|
+
|
|
168
|
+
Tu reçois le contenu brut d'une page PDF extrait par mupdf : texte et tableaux GFM déjà partiellement structurés.
|
|
169
|
+
|
|
170
|
+
**Mission :** Nettoie et améliore ce contenu en Markdown propre. Ne jamais produire de frontmatter YAML.
|
|
171
|
+
|
|
172
|
+
**Ce que mupdf a déjà fourni (à préserver) :**
|
|
173
|
+
- Tableaux \`| col | col |\` en GFM — ne pas les supprimer, mais possibilité d'améliorer et corriger les cellules cassées.
|
|
174
|
+
- Listes \`-\` détectées dans le PDF
|
|
175
|
+
- Section \`## Liens\` en pied de page si présente
|
|
176
|
+
|
|
177
|
+
**Ce qu'il reste à faire :**
|
|
178
|
+
1. **Titres** : ligne en MAJUSCULES → \`##\` ; ligne finissant par \`:\` → \`###\` ; titre principal évident → \`#\`.
|
|
179
|
+
2. **Fusion de cellules cassées** : si une cellule est coupée sur plusieurs lignes (continuation sans séparateur, hyphénation en fin de ligne), fusionner dans la même cellule.
|
|
180
|
+
3. **En-têtes/pieds répétitifs** : supprimer les lignes qui ne sont que numéro de page, logo ou nom d'entreprise sans apporter de contenu.
|
|
181
|
+
4. **Éléments critiques** : informations véritablement importantes → \`⚠️ **gras**\`.
|
|
182
|
+
5. **Nettoyage** : un seul saut de ligne vide entre blocs ; pas de balises HTML ; conserver signes et abréviations.
|
|
183
|
+
6. **Cohérence des tableaux** : normaliser le nombre de colonnes si des cellules manquent.
|
|
184
|
+
7. **Groupes répétés dans un tableau** : si la même valeur de groupe apparaît dans la première colonne sur plusieurs lignes consécutives (ex. \`Code | ABC | …\`, \`Code | DEF | …\`), il faut simplifier le groupe avec un titre.
|
|
185
|
+
**Ne jamais :**
|
|
186
|
+
- Inventer du contenu ou reformuler le fond
|
|
187
|
+
- Ajouter un frontmatter YAML (\`---\`)
|
|
188
|
+
- Ajouter des commentaires ou explications
|
|
189
|
+
|
|
190
|
+
Réponds uniquement avec le Markdown nettoyé de la page.
|
|
191
|
+
`;
|
|
152
192
|
exports.htmlToMarkdownPrompt = `
|
|
153
193
|
Vous êtes *MarkdownPDF-Pro*, un assistant expert chargé de transformer un texte brut issu d’un PDF en un fichier Markdown clair et minimaliste, sans mise en page complexe.
|
|
154
194
|
Tu travailles dans le contexte de l'entreprise Pilet & Renaud SA. Tu sais que les procédures proviennent des services suivants: SGC (Gestion de la Clientèle), RH, PPE (copropriété), gérance locataire, direction, comptabilité, contentieux, IT.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RAGManagerConfig, RAGRegistryEntry, RAGConfig, ParsedDocument, DocumentQueries } from './types';
|
|
1
|
+
import { RAGManagerConfig, RAGRegistryEntry, RAGConfig, ParsedDocument, RAGMetadata, DocumentQueries } from './types';
|
|
2
2
|
import { Embeddings } from './embeddings';
|
|
3
3
|
/**
|
|
4
4
|
* Gestionnaire multi-RAG stateless pour gérer plusieurs index RAG
|
|
@@ -75,6 +75,7 @@ export declare class RAGManager {
|
|
|
75
75
|
*/
|
|
76
76
|
notifyUpdate(name: string, opts?: {
|
|
77
77
|
action?: 'rename';
|
|
78
|
+
id?: number;
|
|
78
79
|
oldFile?: string;
|
|
79
80
|
newFile?: string;
|
|
80
81
|
}): void;
|
|
@@ -86,6 +87,15 @@ export declare class RAGManager {
|
|
|
86
87
|
* Archive un RAG existant
|
|
87
88
|
*/
|
|
88
89
|
private archive;
|
|
90
|
+
/**
|
|
91
|
+
* Charge la configuration depuis le fichier metadata
|
|
92
|
+
*/
|
|
93
|
+
private readMetadataFile;
|
|
94
|
+
/**
|
|
95
|
+
* Charge les métadonnées d'un RAG sans instancier un nouvel Embeddings.
|
|
96
|
+
* Si le RAG est déjà chargé, réutilise les métadonnées en mémoire.
|
|
97
|
+
*/
|
|
98
|
+
loadMetadata(name: string): RAGMetadata;
|
|
89
99
|
/**
|
|
90
100
|
* Charge la configuration depuis le fichier metadata
|
|
91
101
|
*/
|
|
@@ -107,6 +117,10 @@ export declare class RAGManager {
|
|
|
107
117
|
* @private
|
|
108
118
|
*/
|
|
109
119
|
private saveMapping;
|
|
120
|
+
/**
|
|
121
|
+
* Supprime les fichiers orphelins d'un dossier RAG à partir des documents indexés.
|
|
122
|
+
*/
|
|
123
|
+
private cleanupOrphanFiles;
|
|
110
124
|
/**
|
|
111
125
|
* Nettoie les anciennes archives d'un RAG
|
|
112
126
|
*/
|
|
@@ -311,6 +325,7 @@ export declare class RAGManager {
|
|
|
311
325
|
* Supprime un RAG du registre
|
|
312
326
|
*/
|
|
313
327
|
delete(name: string, archiveFlag?: boolean): Promise<void | Error>;
|
|
328
|
+
private resolveDocumentFilenameById;
|
|
314
329
|
/**
|
|
315
330
|
* Renomme un document dans un RAG existant
|
|
316
331
|
*
|
|
@@ -323,7 +338,7 @@ export declare class RAGManager {
|
|
|
323
338
|
* Et met à jour les références dans les fichiers JSON (mapping, metadata, queries)
|
|
324
339
|
*
|
|
325
340
|
* @param ragName Nom du RAG concerné
|
|
326
|
-
* @param
|
|
341
|
+
* @param oldFileOrId Ancien nom du fichier (ex: 'old-name.md') ou ID documentaire
|
|
327
342
|
* @param newFile Nouveau nom du fichier (ex: 'new-name.md')
|
|
328
343
|
*
|
|
329
344
|
* @example
|
|
@@ -331,7 +346,7 @@ export declare class RAGManager {
|
|
|
331
346
|
* ragManager.renameDocument('rule-validation-1', 'old-procedure.md', 'new-procedure.md');
|
|
332
347
|
* ```
|
|
333
348
|
*/
|
|
334
|
-
renameDocument(ragName: string,
|
|
349
|
+
renameDocument(ragName: string, oldFileOrId: string | number, newFile: string): void;
|
|
335
350
|
/**
|
|
336
351
|
* Met à jour les références d'un fichier dans les JSON du RAG
|
|
337
352
|
*
|
|
@@ -34,6 +34,9 @@ class RAGManager {
|
|
|
34
34
|
if (!config.baseDir || !(0, fs_1.existsSync)(config.baseDir)) {
|
|
35
35
|
throw new Error(`Le dossier du registre RAG n'existe pas: ${config.baseDir}`);
|
|
36
36
|
}
|
|
37
|
+
if (!config.defaultName || config.defaultName.trim() === '') {
|
|
38
|
+
throw new Error('RAGManagerConfig.defaultName est obligatoire et ne peut pas être vide');
|
|
39
|
+
}
|
|
37
40
|
this.config = {
|
|
38
41
|
tempDir: path_1.default.join(config.baseDir, 'temp'),
|
|
39
42
|
archiveDir: path_1.default.join(config.baseDir, 'archives'),
|
|
@@ -49,7 +52,10 @@ class RAGManager {
|
|
|
49
52
|
// store instance in memory
|
|
50
53
|
DEFAULT_RAG_INSTANCE[this.config.baseDir] = this;
|
|
51
54
|
const registry = this.getRegistry();
|
|
52
|
-
const defaultName = registry.defaultName
|
|
55
|
+
const defaultName = registry.defaultName;
|
|
56
|
+
if (!defaultName || defaultName.trim() === '') {
|
|
57
|
+
throw new Error('registry.json invalide: defaultName manquant');
|
|
58
|
+
}
|
|
53
59
|
DEFAULT_RAG_INSTANCE[defaultName] = this;
|
|
54
60
|
}
|
|
55
61
|
static get(config) {
|
|
@@ -101,7 +107,7 @@ class RAGManager {
|
|
|
101
107
|
registry = {
|
|
102
108
|
version: '1.0',
|
|
103
109
|
registries: {},
|
|
104
|
-
defaultName:
|
|
110
|
+
defaultName: this.config.defaultName
|
|
105
111
|
};
|
|
106
112
|
}
|
|
107
113
|
}
|
|
@@ -109,12 +115,12 @@ class RAGManager {
|
|
|
109
115
|
registry = {
|
|
110
116
|
version: '1.0',
|
|
111
117
|
registries: {},
|
|
112
|
-
defaultName:
|
|
118
|
+
defaultName: this.config.defaultName
|
|
113
119
|
};
|
|
114
120
|
}
|
|
115
|
-
//
|
|
121
|
+
// Fail-fast: defaultName doit toujours être défini explicitement
|
|
116
122
|
if (!registry.defaultName) {
|
|
117
|
-
registry.defaultName
|
|
123
|
+
throw new Error('registry.json invalide: defaultName manquant. Fournir defaultName dans la config RAG.');
|
|
118
124
|
}
|
|
119
125
|
// Scanner les dossiers pour découvrir les RAG existants
|
|
120
126
|
this.scanDirectoriesForRAGs(registry);
|
|
@@ -312,13 +318,39 @@ class RAGManager {
|
|
|
312
318
|
/**
|
|
313
319
|
* Charge la configuration depuis le fichier metadata
|
|
314
320
|
*/
|
|
315
|
-
|
|
316
|
-
const metadataFile = path_1.default.join(configPath,
|
|
321
|
+
readMetadataFile(configPath) {
|
|
322
|
+
const metadataFile = path_1.default.join(configPath, types_1.RAG_FILES.METADATA);
|
|
317
323
|
if (!(0, fs_1.existsSync)(metadataFile)) {
|
|
318
324
|
throw new Error(`Fichier metadata manquant: ${metadataFile}`);
|
|
319
325
|
}
|
|
320
326
|
try {
|
|
321
|
-
|
|
327
|
+
return JSON.parse((0, fs_1.readFileSync)(metadataFile, 'utf8'));
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
throw new Error(`Erreur lors du chargement des métadonnées RAG: ${error}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Charge les métadonnées d'un RAG sans instancier un nouvel Embeddings.
|
|
335
|
+
* Si le RAG est déjà chargé, réutilise les métadonnées en mémoire.
|
|
336
|
+
*/
|
|
337
|
+
loadMetadata(name) {
|
|
338
|
+
if (!this.exists(name)) {
|
|
339
|
+
throw new Error(`RAG '${name}' n'existe pas`);
|
|
340
|
+
}
|
|
341
|
+
const embeddingData = this.loadedEmbeddings.get(name);
|
|
342
|
+
if (embeddingData) {
|
|
343
|
+
return embeddingData.embedding.getMetadata();
|
|
344
|
+
}
|
|
345
|
+
const entry = this.getEntry(name);
|
|
346
|
+
return this.readMetadataFile(entry.configPath);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Charge la configuration depuis le fichier metadata
|
|
350
|
+
*/
|
|
351
|
+
loadConfig(configPath) {
|
|
352
|
+
try {
|
|
353
|
+
const metadata = this.readMetadataFile(configPath);
|
|
322
354
|
// Extraire la configuration depuis les métadonnées
|
|
323
355
|
const ragConfig = {
|
|
324
356
|
baseDir: configPath,
|
|
@@ -380,6 +412,41 @@ class RAGManager {
|
|
|
380
412
|
throw new Error(`Échec de la sauvegarde du mapping: ${error}`);
|
|
381
413
|
}
|
|
382
414
|
}
|
|
415
|
+
/**
|
|
416
|
+
* Supprime les fichiers orphelins d'un dossier RAG à partir des documents indexés.
|
|
417
|
+
*/
|
|
418
|
+
cleanupOrphanFiles(configPath, metadata) {
|
|
419
|
+
const allowedFiles = new Set([
|
|
420
|
+
types_1.RAG_FILES.VECTORS,
|
|
421
|
+
types_1.RAG_FILES.METADATA,
|
|
422
|
+
types_1.RAG_FILES.MAPPING,
|
|
423
|
+
types_1.RAG_FILES.QUERIES
|
|
424
|
+
]);
|
|
425
|
+
const uniqueFilenames = new Set();
|
|
426
|
+
for (const doc of Object.values(metadata.documents || {})) {
|
|
427
|
+
if (doc.filename) {
|
|
428
|
+
uniqueFilenames.add(doc.filename);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
for (const filename of uniqueFilenames) {
|
|
432
|
+
const baseName = filename.replace(/\.md$/, '');
|
|
433
|
+
allowedFiles.add(filename);
|
|
434
|
+
allowedFiles.add(`${filename}.sha`);
|
|
435
|
+
allowedFiles.add(`${baseName}.enhanced.md`);
|
|
436
|
+
allowedFiles.add(`${baseName}.query.json`);
|
|
437
|
+
}
|
|
438
|
+
for (const fileName of (0, fs_1.readdirSync)(configPath)) {
|
|
439
|
+
const fullPath = path_1.default.join(configPath, fileName);
|
|
440
|
+
if (!allowedFiles.has(fileName)) {
|
|
441
|
+
try {
|
|
442
|
+
(0, fs_1.rmSync)(fullPath, { recursive: true, force: true });
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
console.warn(`⚠️ Erreur suppression fichier orphelin ${fileName}:`, error);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
383
450
|
/**
|
|
384
451
|
* Nettoie les anciennes archives d'un RAG
|
|
385
452
|
*/
|
|
@@ -732,8 +799,15 @@ class RAGManager {
|
|
|
732
799
|
}
|
|
733
800
|
//
|
|
734
801
|
// Charger le metadata pour obtenir la liste des documents
|
|
802
|
+
// Ignorer les dossiers temporaires (temp/) sans metadata
|
|
735
803
|
const metadataFile = path_1.default.join(entry.configPath, types_1.RAG_FILES.METADATA);
|
|
736
804
|
if (!(0, fs_1.existsSync)(metadataFile)) {
|
|
805
|
+
//
|
|
806
|
+
// Si c'est un dossier temporaire (temp/rule-validation-*), retourner vide au lieu d'erreur
|
|
807
|
+
if (entry.configPath.includes('/temp/') || entry.status === 'building') {
|
|
808
|
+
console.warn(`⚠️ Dossier temporaire sans metadata ignoré: ${entry.configPath}`);
|
|
809
|
+
return { documents: {}, totalQueries: 0 };
|
|
810
|
+
}
|
|
737
811
|
throw new Error(`Fichier metadata manquant: ${metadataFile}`);
|
|
738
812
|
}
|
|
739
813
|
let metadata;
|
|
@@ -858,6 +932,7 @@ class RAGManager {
|
|
|
858
932
|
// Sauvegarder les métadonnées et le mapping
|
|
859
933
|
this.saveMetadata(buildPath, metadata);
|
|
860
934
|
this.saveMapping(buildPath, buildResult.mapping, buildResult);
|
|
935
|
+
this.cleanupOrphanFiles(buildPath, metadata);
|
|
861
936
|
// ✅ En mode legacy, on construit directement dans configPath (pas de déplacement)
|
|
862
937
|
if (!isLegacyMode && destDir) {
|
|
863
938
|
// Archiver l'ancienne version si elle existe
|
|
@@ -990,7 +1065,7 @@ class RAGManager {
|
|
|
990
1065
|
// Changer le défaut si nécessaire
|
|
991
1066
|
if (registry.defaultName === name) {
|
|
992
1067
|
const remainingRAGs = Object.keys(registry.registries);
|
|
993
|
-
registry.defaultName = remainingRAGs.length > 0 ? remainingRAGs[0] :
|
|
1068
|
+
registry.defaultName = remainingRAGs.length > 0 ? remainingRAGs[0] : this.config.defaultName;
|
|
994
1069
|
}
|
|
995
1070
|
this.saveRegistry(registry);
|
|
996
1071
|
console.log(`✅ RAG supprimé: ${name}`);
|
|
@@ -999,6 +1074,20 @@ class RAGManager {
|
|
|
999
1074
|
return error;
|
|
1000
1075
|
}
|
|
1001
1076
|
}
|
|
1077
|
+
resolveDocumentFilenameById(ragName, configPath, documentId) {
|
|
1078
|
+
try {
|
|
1079
|
+
const metadata = this.loadMetadata(ragName);
|
|
1080
|
+
for (const doc of Object.values(metadata.documents || {})) {
|
|
1081
|
+
if (typeof doc.metadata?.id === 'number' && doc.metadata.id === documentId) {
|
|
1082
|
+
return doc.filename;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
catch (error) {
|
|
1087
|
+
console.warn(`⚠️ Erreur lecture metadata pour résolution par ID:`, error);
|
|
1088
|
+
}
|
|
1089
|
+
return undefined;
|
|
1090
|
+
}
|
|
1002
1091
|
/**
|
|
1003
1092
|
* Renomme un document dans un RAG existant
|
|
1004
1093
|
*
|
|
@@ -1011,7 +1100,7 @@ class RAGManager {
|
|
|
1011
1100
|
* Et met à jour les références dans les fichiers JSON (mapping, metadata, queries)
|
|
1012
1101
|
*
|
|
1013
1102
|
* @param ragName Nom du RAG concerné
|
|
1014
|
-
* @param
|
|
1103
|
+
* @param oldFileOrId Ancien nom du fichier (ex: 'old-name.md') ou ID documentaire
|
|
1015
1104
|
* @param newFile Nouveau nom du fichier (ex: 'new-name.md')
|
|
1016
1105
|
*
|
|
1017
1106
|
* @example
|
|
@@ -1019,7 +1108,7 @@ class RAGManager {
|
|
|
1019
1108
|
* ragManager.renameDocument('rule-validation-1', 'old-procedure.md', 'new-procedure.md');
|
|
1020
1109
|
* ```
|
|
1021
1110
|
*/
|
|
1022
|
-
renameDocument(ragName,
|
|
1111
|
+
renameDocument(ragName, oldFileOrId, newFile) {
|
|
1023
1112
|
const entry = this.getEntry(ragName);
|
|
1024
1113
|
if (!entry) {
|
|
1025
1114
|
if (this.config.verbose) {
|
|
@@ -1028,6 +1117,15 @@ class RAGManager {
|
|
|
1028
1117
|
return;
|
|
1029
1118
|
}
|
|
1030
1119
|
const configPath = entry.configPath;
|
|
1120
|
+
const oldFile = typeof oldFileOrId === 'number'
|
|
1121
|
+
? this.resolveDocumentFilenameById(ragName, configPath, oldFileOrId)
|
|
1122
|
+
: oldFileOrId;
|
|
1123
|
+
if (!oldFile) {
|
|
1124
|
+
if (this.config.verbose) {
|
|
1125
|
+
console.log(`⚠️ Aucun document trouvé pour ${typeof oldFileOrId === 'number' ? `id=${oldFileOrId}` : oldFileOrId} dans RAG '${ragName}'`);
|
|
1126
|
+
}
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1031
1129
|
//
|
|
1032
1130
|
// Liste des fichiers à renommer (sans extension pour le basename)
|
|
1033
1131
|
const oldBase = oldFile.replace(/\.md$/, '');
|
|
@@ -1070,6 +1168,7 @@ class RAGManager {
|
|
|
1070
1168
|
// Notifier les embeddings chargés de se mettre à jour avec l'action rename
|
|
1071
1169
|
this.notifyUpdate(ragName, {
|
|
1072
1170
|
action: 'rename',
|
|
1171
|
+
id: typeof oldFileOrId === 'number' ? oldFileOrId : undefined,
|
|
1073
1172
|
oldFile,
|
|
1074
1173
|
newFile
|
|
1075
1174
|
});
|
|
@@ -1420,7 +1519,10 @@ class RAGManager {
|
|
|
1420
1519
|
*/
|
|
1421
1520
|
getDefault() {
|
|
1422
1521
|
const registry = this.getRegistry();
|
|
1423
|
-
|
|
1522
|
+
if (!registry.defaultName || registry.defaultName.trim() === '') {
|
|
1523
|
+
throw new Error('registry.json invalide: defaultName manquant');
|
|
1524
|
+
}
|
|
1525
|
+
return registry.defaultName;
|
|
1424
1526
|
}
|
|
1425
1527
|
/**
|
|
1426
1528
|
* Obtient les statistiques de tous les RAG
|
package/dist/src/rag/types.d.ts
CHANGED
|
@@ -278,13 +278,15 @@ export interface RAGRegistry {
|
|
|
278
278
|
version: string;
|
|
279
279
|
/** Liste des RAG disponibles */
|
|
280
280
|
registries: Record<string, RAGRegistryEntry>;
|
|
281
|
-
/** RAG par défaut (
|
|
281
|
+
/** RAG par défaut (obligatoire) */
|
|
282
282
|
defaultName?: string;
|
|
283
283
|
}
|
|
284
284
|
/** Configuration du gestionnaire RAG */
|
|
285
285
|
export interface RAGManagerConfig {
|
|
286
286
|
/** Répertoire de base du registre */
|
|
287
287
|
baseDir: string;
|
|
288
|
+
/** Nom du RAG par défaut (obligatoire) */
|
|
289
|
+
defaultName?: string;
|
|
288
290
|
/** Répertoire temporaire pour les constructions */
|
|
289
291
|
tempDir?: string;
|
|
290
292
|
/** Répertoire d'archives */
|
|
@@ -156,14 +156,14 @@ Temporary repository for E2E testing.`;
|
|
|
156
156
|
return (0, index_1.gitCheckConfiguration)(this.git);
|
|
157
157
|
}
|
|
158
158
|
async isPRClosed(branch) {
|
|
159
|
-
return (0, index_1.
|
|
159
|
+
return (0, index_1.gitIsPRClosedRobust)(this.git, branch, this.config);
|
|
160
160
|
}
|
|
161
161
|
async isPRClosedRobust(branch, config) {
|
|
162
162
|
return (0, index_1.gitIsPRClosedRobust)(this.git, branch, config || this.config);
|
|
163
163
|
}
|
|
164
164
|
async closePR(branch, author, message) {
|
|
165
165
|
console.log(`[DEBUG][E2EHelper.closePR] Closing PR: ${branch} by ${author.name}`);
|
|
166
|
-
return (0, index_1.
|
|
166
|
+
return (0, index_1.gitClosePRRobust)(this.git, branch, author, message || `Closed by ${author.name}`, this.config);
|
|
167
167
|
}
|
|
168
168
|
async closePRRobust(branch, closedBy, message, config) {
|
|
169
169
|
return (0, index_1.gitClosePRRobust)(this.git, branch, closedBy, message, config || this.config);
|
|
@@ -174,7 +174,47 @@ Temporary repository for E2E testing.`;
|
|
|
174
174
|
return (0, index_1.gitGetAllPR)(this.git, options);
|
|
175
175
|
}
|
|
176
176
|
async getNextPRNumber(validationPrefix) {
|
|
177
|
-
|
|
177
|
+
const initialPRCounter = 60;
|
|
178
|
+
const registryPath = (0, path_1.join)(this.config.repoPath, '.git', 'with-ids.json');
|
|
179
|
+
const now = new Date().toISOString();
|
|
180
|
+
const allBranches = await this.getAllBranches();
|
|
181
|
+
const numbers = allBranches
|
|
182
|
+
.filter((branch) => branch.startsWith(validationPrefix))
|
|
183
|
+
.map((branch) => parseInt(branch.substring(validationPrefix.length).split('-')[0], 10))
|
|
184
|
+
.filter((num) => !isNaN(num));
|
|
185
|
+
const maxBranchNumber = numbers.length > 0 ? Math.max(...numbers) : initialPRCounter;
|
|
186
|
+
let registry = {
|
|
187
|
+
last: 980,
|
|
188
|
+
lastPR: initialPRCounter,
|
|
189
|
+
used: [],
|
|
190
|
+
updated: now,
|
|
191
|
+
matters: {}
|
|
192
|
+
};
|
|
193
|
+
if ((0, fs_1.existsSync)(registryPath)) {
|
|
194
|
+
try {
|
|
195
|
+
registry = JSON.parse(await fs_1.promises.readFile(registryPath, 'utf8'));
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// Rebuild minimal registry fallback
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!Number.isInteger(registry.lastPR)) {
|
|
202
|
+
registry.lastPR = initialPRCounter;
|
|
203
|
+
}
|
|
204
|
+
if (!Number.isInteger(registry.last)) {
|
|
205
|
+
registry.last = 980;
|
|
206
|
+
}
|
|
207
|
+
if (!Array.isArray(registry.used)) {
|
|
208
|
+
registry.used = [];
|
|
209
|
+
}
|
|
210
|
+
if (!registry.matters || typeof registry.matters !== 'object') {
|
|
211
|
+
registry.matters = {};
|
|
212
|
+
}
|
|
213
|
+
const nextPR = Math.max(registry.lastPR, maxBranchNumber, initialPRCounter) + 1;
|
|
214
|
+
registry.lastPR = nextPR;
|
|
215
|
+
registry.updated = now;
|
|
216
|
+
await fs_1.promises.writeFile(registryPath, JSON.stringify(registry, null, 2), 'utf8');
|
|
217
|
+
return nextPR;
|
|
178
218
|
}
|
|
179
219
|
async newPR(files, description, author, options) {
|
|
180
220
|
//console.log(`[DEBUG][E2EHelper.newPR] Creating new PR by ${author.name} for files: ${files.join(', ')}`);
|
|
@@ -220,7 +260,11 @@ Temporary repository for E2E testing.`;
|
|
|
220
260
|
async editFile(filePath, content, branch) {
|
|
221
261
|
const user = { name: 'E2E Test', email: 'e2e@test.com' };
|
|
222
262
|
const targetBranch = branch || this.config.draftBranch;
|
|
223
|
-
|
|
263
|
+
const exists = await (0, index_1.gitFileExistsInBranch)(this.git, filePath, targetBranch);
|
|
264
|
+
if (!exists) {
|
|
265
|
+
throw new Error(`File "${filePath}" not found in branch "${targetBranch}"`);
|
|
266
|
+
}
|
|
267
|
+
return (0, index_1.gitCreateOrEditFile)(this.git, filePath, targetBranch, content, user, this.config);
|
|
224
268
|
}
|
|
225
269
|
async validateRepositoryState() {
|
|
226
270
|
const errors = [];
|
|
@@ -379,6 +423,9 @@ const defaultConfig = (tempDir) => {
|
|
|
379
423
|
instance: (0, simple_git_1.default)({ baseDir: tempDir, binary: 'git' }),
|
|
380
424
|
repoPath: tempDir,
|
|
381
425
|
uploadPath: (0, path_1.join)(tempDir, '.assets'), // Add uploadPath to default config
|
|
426
|
+
// FIXME(test-config): inject a dedicated fake remote when we need remote-aware E2E coverage.
|
|
427
|
+
// Empty string explicitly disables inheriting GIT_REMOTE_URL from the developer environment.
|
|
428
|
+
remoteUrl: '',
|
|
382
429
|
draftBranch: 'rule-editor',
|
|
383
430
|
mainBranch: 'main',
|
|
384
431
|
validationPrefix: 'rule-validation-',
|