🚀 Version finale avec Mode Liberté Intelligent et fonctionnalités avancées

##  Nouvelles fonctionnalités majeures
- Mode Liberté intelligent avec 15 itérations max et analyse itérative
- Bouton Visualiser pour prévisualisation Markdown complète
- Navigation table des matières corrigée et optimisée
- Formatage Markdown avancé (titres, listes, code, citations, liens)
- Configuration IA optimisée pour précision maximale

## 🔧 Améliorations techniques
- Correction parseMarkdown manquante dans les fonctions IA
- Optimisation des températures par fonction (0.1-0.4)
- Nettoyage configuration .env (35k tokens, paramètres intelligents)
- Suppression des paramètres inutilisés (rate limiting)
- Implémentation AI_TEMPERATURE dans le code

## 📖 Documentation
- README complet avec guide d'installation et utilisation
- Documentation Mode Liberté intelligent
- Architecture technique détaillée
- Guide de configuration avancée

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Augustin 2025-09-25 21:37:41 +02:00
parent 45d6344b18
commit 39a2276c66
9 changed files with 219 additions and 260 deletions

BIN
README.md

Binary file not shown.

View File

@ -6,6 +6,8 @@ class ConceptionAssistant {
this.undoStack = [];
this.redoStack = [];
this.tocTimer = null;
this.isPreviewMode = false;
this.originalContent = '';
this.init();
}
@ -66,6 +68,7 @@ class ConceptionAssistant {
// Boutons de contrôle des journaux
document.getElementById('save-journal')?.addEventListener('click', () => this.saveJournal());
document.getElementById('load-journal')?.addEventListener('click', () => this.showJournalSelector());
document.getElementById('preview-toggle')?.addEventListener('click', () => this.togglePreview());
// Table des matières
document.getElementById('refresh-toc')?.addEventListener('click', () => this.generateTOC());
@ -445,31 +448,47 @@ class ConceptionAssistant {
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith('#') && line.replace(/^#+\s*/, '') === title) {
// Créer un range temporaire pour scroller vers cette ligne
const range = document.createRange();
const selection = window.getSelection();
// Calculer la position approximative du caractère
const beforeLines = lines.slice(0, i).join('\n');
const charPosition = beforeLines.length;
try {
// Créer un range au début de la ligne trouvée
range.setStart(this.editor.childNodes[0] || this.editor, Math.min(charPosition, this.editor.textContent.length));
range.collapse(true);
// Approche plus simple : utiliser un élément temporaire avec une position spécifique
const tempElement = document.createElement('div');
tempElement.style.position = 'absolute';
tempElement.style.visibility = 'hidden';
tempElement.style.height = '1px';
// Créer un élément temporaire pour le scroll
const tempElement = document.createElement('span');
range.insertNode(tempElement);
// Calculer la position approximative en fonction de la ligne
const editorRect = this.editor.getBoundingClientRect();
const computedStyle = window.getComputedStyle(this.editor);
const lineHeight = parseInt(computedStyle.lineHeight) || 20;
tempElement.scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'nearest'
// Insérer l'élément temporaire dans l'éditeur
this.editor.appendChild(tempElement);
// Calculer la position de scroll basée sur le numéro de ligne
const targetPosition = i * lineHeight;
// Scroller vers la position calculée
this.editor.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
// Si l'éditeur n'a pas de scroll, utiliser le parent
if (this.editor.scrollHeight <= this.editor.clientHeight) {
const scrollContainer = this.editor.parentElement || document.documentElement;
const editorTop = this.editor.offsetTop;
scrollContainer.scrollTo({
top: editorTop + targetPosition - 100, // -100 pour un padding
behavior: 'smooth'
});
}
// Nettoyer l'élément temporaire
setTimeout(() => tempElement.remove(), 100);
setTimeout(() => {
if (tempElement.parentNode) {
tempElement.parentNode.removeChild(tempElement);
}
}, 100);
this.showNotification('Navigation vers la section', 'success');
return;
@ -618,23 +637,30 @@ class ConceptionAssistant {
// Mode liberté utilise toujours le document complet
result = await this.callAI('/api/ai/liberty-mode', { content: fullContent, iterations: count, focus: 'conception' });
// Appliquer automatiquement chaque itération au document
let updatedContent = fullContent;
result.results.forEach(iteration => {
updatedContent += '\n\n' + iteration.content;
});
// Utiliser le contenu final mis à jour par le backend
if (result.finalContent) {
this.editor.innerText = result.finalContent;
this.generateTOC();
this.saveState();
}
// Appliquer les changements directement
this.editor.innerText = updatedContent;
this.generateTOC();
this.saveState();
let libertyHTML = `<strong>🚀 Mode Liberté Intelligent (${result.iterations} itérations)</strong><br><br>`;
// Vérifier si l'IA s'est arrêtée prématurément
const lastIteration = result.results[result.results.length - 1];
if (lastIteration && lastIteration.stopped) {
libertyHTML += `<p>🛑 Analyse terminée après ${result.iterations} itérations - Aucune amélioration évidente supplémentaire détectée.</p>`;
} else {
libertyHTML += `<p>✅ Les ${result.iterations} itérations d'amélioration ont été automatiquement appliquées au document.</p>`;
}
let libertyHTML = `<strong>🚀 Mode Liberté appliqué (${result.iterations} itérations)</strong><br><br>`;
libertyHTML += `<p>✅ Les ${result.iterations} itérations ont été automatiquement ajoutées au document.</p>`;
result.results.forEach(iteration => {
const borderColor = iteration.stopped ? 'var(--warning-color)' : 'var(--success-color)';
const icon = iteration.stopped ? '🛑' : '🎯';
libertyHTML += `
<div style="background: var(--background-color); padding: 1rem; border-radius: 8px; margin: 0.5rem 0; border-left: 4px solid var(--success-color);">
<strong>Itération ${iteration.iteration} ajoutée :</strong><br><br>
<div style="background: var(--background-color); padding: 1rem; border-radius: 8px; margin: 0.5rem 0; border-left: 4px solid ${borderColor};">
<strong>${icon} Itération ${iteration.iteration} ${iteration.stopped ? '(Arrêt)' : '(Appliquée)'} :</strong><br><br>
${this.formatAIResponse(iteration.content)}
</div>
`;
@ -673,20 +699,21 @@ class ConceptionAssistant {
const sections = text.split('##');
let formattedHTML = '';
const self = this;
sections.forEach((section, index) => {
if (index === 0 && section.trim()) {
// Première section sans titre
formattedHTML += `<div style="margin-bottom: 1rem;">${this.parseMarkdown(section.trim())}</div>`;
formattedHTML += `<div style="margin-bottom: 1rem;">${self.parseMarkdown(section.trim())}</div>`;
} else if (section.trim()) {
const lines = section.split('\n');
const title = lines[0].trim();
const content = lines.slice(1).join('\n').trim();
// Sections normales - pas de markdown
// Sections normales - avec markdown
formattedHTML += `
<div style="margin: 1rem 0;">
<strong>${title}</strong><br><br>
${content}
<strong style="color: var(--primary-color); font-size: 1.1em;">${title}</strong><br><br>
<div style="margin-top: 0.5rem;">${self.parseMarkdown(content)}</div>
</div>
`;
}
@ -695,6 +722,47 @@ class ConceptionAssistant {
return formattedHTML || text;
}
parseMarkdown(text) {
if (!text) return '';
return text
// Titres H1-H6 (#, ##, ###, etc.)
.replace(/^(#{1,6})\s+(.+)$/gm, (match, hashes, title) => {
const level = hashes.length;
return `<h${level} style="color: var(--primary-color); margin: 1rem 0 0.5rem 0; font-weight: bold;">${title}</h${level}>`;
})
// Listes à puces (- ou *)
.replace(/^[\s]*[-\*]\s+(.+)$/gm, '<li style="margin: 0.25rem 0;">$1</li>')
// Listes numérotées
.replace(/^[\s]*\d+\.\s+(.+)$/gm, '<li style="margin: 0.25rem 0;">$1</li>')
// Code blocks avec ```
.replace(/```([\s\S]*?)```/g, '<pre style="background: var(--background-color); padding: 1rem; border-radius: 6px; border-left: 4px solid var(--primary-color); margin: 1rem 0; overflow-x: auto;"><code>$1</code></pre>')
// Citations avec >
.replace(/^>\s+(.+)$/gm, '<blockquote style="border-left: 4px solid var(--primary-color); padding-left: 1rem; margin: 1rem 0; font-style: italic; color: var(--text-light);">$1</blockquote>')
// Gras **texte**
.replace(/\*\*(.*?)\*\*/g, '<strong style="color: var(--primary-color);">$1</strong>')
// Italique *texte*
.replace(/\*(.*?)\*/g, '<em style="color: var(--text-light);">$1</em>')
// Code inline `code`
.replace(/`([^`]+)`/g, '<code style="background: var(--surface-color); padding: 0.2rem 0.4rem; border-radius: 3px; font-family: monospace; font-size: 0.9em;">$1</code>')
// Liens [texte](url)
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" style="color: var(--primary-color); text-decoration: underline;">$1</a>')
// Séparer les listes en blocs <ul> ou <ol>
.replace(/(<li[^>]*>.*<\/li>)/gs, (match) => {
if (match.includes('<li')) {
return `<ul style="margin: 0.5rem 0; padding-left: 1.5rem;">${match}</ul>`;
}
return match;
})
// Sauts de ligne doubles pour paragraphes
.replace(/\n\n+/g, '\n\n')
.replace(/\n\n/g, '</p><p style="margin: 0.75rem 0; line-height: 1.6;">')
// Sauts de ligne simples
.replace(/\n/g, '<br>')
// Encapsuler dans un paragraphe si pas déjà fait
.replace(/^(?!<[h1-6|ul|ol|pre|blockquote])/i, '<p style="margin: 0.75rem 0; line-height: 1.6;">')
.replace(/$/i, '</p>');
}
showAIFeedback(message) {
const feedback = document.getElementById('ai-assistant-feedback');
@ -894,4 +962,48 @@ function initializeTemplateForm() {
});
}
togglePreview() {
const previewBtn = document.getElementById('preview-toggle');
if (!this.isPreviewMode) {
// Passer en mode prévisualisation
this.originalContent = this.editor.innerHTML;
const markdownContent = this.editor.innerText;
// Convertir le Markdown en HTML joliment formaté
const previewHTML = this.parseMarkdown(markdownContent);
// Désactiver l'édition et appliquer le style preview
this.editor.contentEditable = false;
this.editor.innerHTML = `<div style="max-width: 800px; margin: 0 auto; padding: 2rem; line-height: 1.8; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">${previewHTML}</div>`;
this.editor.style.background = 'var(--background-color)';
this.editor.style.border = '1px solid var(--border-color)';
this.editor.style.borderRadius = '8px';
// Changer le bouton
previewBtn.innerHTML = '✏️ Éditer';
previewBtn.classList.remove('primary');
previewBtn.classList.add('secondary');
this.isPreviewMode = true;
this.showNotification('Mode prévisualisation activé', 'success');
} else {
// Revenir en mode édition
this.editor.contentEditable = true;
this.editor.innerHTML = this.originalContent;
this.editor.style.background = '';
this.editor.style.border = '';
this.editor.style.borderRadius = '';
// Changer le bouton
previewBtn.innerHTML = '👁️ Visualiser';
previewBtn.classList.remove('secondary');
previewBtn.classList.add('primary');
this.isPreviewMode = false;
this.showNotification('Mode édition activé', 'success');
}
}
}

View File

@ -8,10 +8,6 @@ MISTRAL_BASE_URL=https://api.mistral.ai/v1
# AI Features Configuration
AI_ENABLED=false
AI_MAX_TOKENS=4000
AI_TEMPERATURE=0.7
AI_TOP_P=0.95
# Rate Limiting for AI
AI_RATE_LIMIT_REQUESTS=10
AI_RATE_LIMIT_WINDOW=60000
AI_MAX_TOKENS=35000
AI_TEMPERATURE=0.3
AI_TOP_P=0.85

View File

@ -1 +0,0 @@
#Fait moi un texte sur le fairy

View File

@ -1,88 +0,0 @@
**Spécifications Techniques Projet Informatique**
## 1. Cadre général du projet
### 1.1 Contexte
[Résumé synthétique du projet, incluant son périmètre et sa finalité]
### 1.2 Objectifs
**Objectif principal** :
- [Description concise et orientée résultats]
**Fonctionnalités clés** :
- [Liste des éléments critiques, formulés sous forme de livrables ou de capacités]
### Description du projet
[Résumé en quelques lignes]
### Objectifs
- Objectif principal :
- Fonctionnalités clés :
## 2. Spécifications techniques
### Technologies utilisées
- **Frontend** :
- **Backend** :
- **Base de données** :
- **Outils** :
### Architecture
[Description simple de l'architecture]
## 3. Fonctionnalités
### Fonctionnalités principales
- [ ] Feature 1
- [ ] Feature 2
- [ ] Feature 3
### Fonctionnalités secondaires
- [ ] Feature A
- [ ] Feature B
## 4. Interface utilisateur
### Pages principales
- Page d'accueil :
- Page utilisateur :
- Page admin :
## 5. Base de données
### Modèles principaux
- **Utilisateur** : id, nom, email
- **Contenu** : id, titre, description
- **Session** : id, token, user_id
## 6. Planning de développement
### Sprint 1 (2 semaines)
- [ ] Setup du projet
- [ ] Authentification
- [ ] Interface de base
### Sprint 2 (2 semaines)
- [ ] CRUD principal
- [ ] Tests unitaires
- [ ] Déploiement
### Sprint 3 (2 semaines)
- [ ] Fonctionnalités avancées
- [ ] Optimisation
- [ ] Documentation
## 7. Tests et déploiement
### Tests
- [ ] Tests unitaires
- [ ] Tests d'intégration
- [ ] Tests utilisateur
### Déploiement
- **Environnement dev** :
- **Environnement prod** :
## 8. Notes techniques
[Espace pour notes de développement]

View File

@ -1,94 +0,0 @@
# Journal de Conception - Projet Informatique
## 1. Introduction
Une calculatrice
**Idée principale :**
une calculatrice que je peux accéder sur mon pc
## 2. Objectifs du projet
**Objectifs principaux :**
- [ ] Objectif 1
- [ ] Objectif 2
- [ ] Objectif 3
**Fonctionnalités clés recherchées :**
- Fonctionnalité essentielle 1
- Fonctionnalité essentielle 2
## 3. Présentation et spécifications
**Description détaillée :**
[Expliquer ce que fait le projet et ses enjeux]
**Cahier des charges :**
- **Besoin général** : [Problème à résoudre]
- **Besoins spécifiques** : [Liste des exigences]
## 4. Fonctionnalités attendues
- [ ] **Module utilisateur** : Inscription, connexion, profil
- [ ] **Module principal** : [Fonctionnalité cœur du projet]
- [ ] **Module administration** : Gestion des données
- [ ] **Module sécurité** : Authentification, autorisation
## 5. Conception globale
**Vue utilisateur :**
```
Interface Web → Authentification → Dashboard → Modules fonctionnels
```
**Architecture technique :**
```
[Client] ↔ [API REST] ↔ [Logique métier] ↔ [Base de données]
```
**Architecture logicielle :**
- **Frontend** : React/Vue.js + CSS Framework
- **Backend** : Node.js/Python + Framework web
- **Base de données** : PostgreSQL/MongoDB
- **API** : REST ou GraphQL
## 6. Problématiques et solutions
| Problématique | Solution technique |
|---------------|-------------------|
| Performance | Cache Redis + optimisation requêtes |
| Sécurité | HTTPS + JWT + validation inputs |
| Scalabilité | Architecture microservices |
## 7. Environnement et outils
**Outils de développement :**
- IDE : VS Code / IntelliJ
- Versioning : Git + GitHub/GitLab
- Gestion projet : Jira / Trello
**Stack technique :**
- Runtime : Node.js / Python
- Framework : Express / Django
- Tests : Jest / Pytest
## 8. Phases du projet
**Phase 1 - Conception (2 semaines) :**
- [ ] Finaliser l'architecture
- [ ] Mockups des interfaces
- [ ] Setup environnement dev
**Phase 2 - Développement (6 semaines) :**
- [ ] Backend et API
- [ ] Frontend et interfaces
- [ ] Intégration continue
**Phase 3 - Tests et déploiement (2 semaines) :**
- [ ] Tests automatisés
- [ ] Déploiement production
- [ ] Documentation utilisateur
## 9. Conclusion
**État d'avancement :**
[À compléter au fur et à mesure]
**Prochaines étapes :**
- [ ] Étape prioritaire 1
- [ ] Étape prioritaire 2
---
*Journal créé le : [DATE]*
*Dernière mise à jour : [DATE]*

View File

@ -1,5 +0,0 @@
{
"0": "936a1104-7afa-438f-b352-aa1f9294132d",
"1": "cb853f57-e578-42b4-8d39-bd71319d4d47",
"2": "d8ec4a9b-4c0f-4ea8-b374-1c85c13fd954"
}

View File

@ -28,7 +28,7 @@ function checkAIEnabled(req, res, next) {
}
// Fonction pour appeler l'API Mistral
async function callMistralAPI(messages, temperature = 0.7) {
async function callMistralAPI(messages, temperature = null) {
try {
const response = await fetch(`${MISTRAL_BASE_URL}/chat/completions`, {
method: 'POST',
@ -39,9 +39,9 @@ async function callMistralAPI(messages, temperature = 0.7) {
body: JSON.stringify({
model: MISTRAL_MODEL,
messages: messages,
temperature: temperature,
max_tokens: parseInt(process.env.AI_MAX_TOKENS) || 4000,
top_p: parseFloat(process.env.AI_TOP_P) || 0.95
temperature: temperature !== null ? temperature : parseFloat(process.env.AI_TEMPERATURE) || 0.3,
max_tokens: parseInt(process.env.AI_MAX_TOKENS) || 35000,
top_p: parseFloat(process.env.AI_TOP_P) || 0.85
})
});
@ -91,7 +91,7 @@ router.post('/rephrase', checkAIEnabled, async (req, res) => {
}
];
const result = await callMistralAPI(messages, 0.7);
const result = await callMistralAPI(messages, 0.2); // Reformulation précise
res.json({
success: true,
@ -141,7 +141,7 @@ router.post('/check-inconsistencies', checkAIEnabled, async (req, res) => {
}
];
const result = await callMistralAPI(messages, 0.3);
const result = await callMistralAPI(messages, 0.1); // Analyse précise et factuelle
res.json({
success: true,
@ -191,7 +191,7 @@ router.post('/check-duplications', checkAIEnabled, async (req, res) => {
}
];
const result = await callMistralAPI(messages, 0.3);
const result = await callMistralAPI(messages, 0.1); // Analyse précise et factuelle
res.json({
success: true,
@ -245,7 +245,7 @@ router.post('/give-advice', checkAIEnabled, async (req, res) => {
}
];
const result = await callMistralAPI(messages, 0.6);
const result = await callMistralAPI(messages, 0.4); // Conseils équilibrés
res.json({
success: true,
@ -275,54 +275,82 @@ router.post('/liberty-mode', checkAIEnabled, async (req, res) => {
});
}
const maxIterations = Math.min(parseInt(iterations), 5); // Limite à 5 itérations
const maxIterations = Math.min(parseInt(iterations), 15); // Limite à 15 itérations
const results = [];
let currentContent = content;
for (let i = 0; i < maxIterations; i++) {
const messages = [
{
role: 'system',
content: `Tu es un assistant créatif spécialisé en conception technique.
content: `Tu es un assistant créatif spécialisé en conception technique avec une approche itérative intelligente.
IMPORTANT: Montre ton raisonnement en suivant cette structure:
MISSION: Analyse le document et identifie LE PREMIER point que tu peux compléter, créer ou modifier avec plus de 90% de confiance basé sur les informations existantes dans le texte.
## 🧠 Raisonnement (Itération ${i + 1}/${maxIterations})
[Explique ton processus de création et ta logique]
RÈGLES STRICTES:
1. Ne traite qu'UN SEUL point par itération
2. Choisis le point le plus évident et logique à améliorer
3. Utilise uniquement les informations déjà présentes dans le document
4. Si rien ne peut être amélioré avec 90%+ de confiance, indique "STOP"
## 🚀 Contenu généré
[Ton contenu créatif complémentaire]
STRUCTURE OBLIGATOIRE:
Basé sur le contenu existant, génère de nouvelles idées et sections qui complètent naturellement le document.
## 🧠 Analyse (Itération ${i + 1}/${maxIterations})
[Identifie et explique le point le plus évident à améliorer]
Focus: ${focus}
## 🎯 Point identifié
[Le point spécifique que tu vas traiter]
Propose des extensions créatives mais pertinentes :
- Nouvelles sections logiques
- Détails techniques manquants
- Alternatives à considérer
- Implications et conséquences
- Améliorations possibles
## Amélioration
[Le contenu précis à ajouter/modifier, avec 90%+ de confiance]
Reste cohérent avec le style et le niveau technique du document existant.`
OU si rien ne peut être amélioré avec assez de confiance:
## 🛑 STOP
[Explication pourquoi aucune amélioration évidente n'est possible]
Focus: ${focus}`
},
{
role: 'user',
content: `Génère du contenu complémentaire pour ce document:\n\n${content}`
content: `Document à analyser (Itération ${i + 1}):\n\n${currentContent}`
}
];
const result = await callMistralAPI(messages, 0.8);
const result = await callMistralAPI(messages, 0.2); // Mode itératif intelligent et précis
// Vérifier si l'IA indique qu'il faut s'arrêter
if (result.toLowerCase().includes('🛑 stop') || result.toLowerCase().includes('## 🛑 stop')) {
results.push({
iteration: i + 1,
content: result,
stopped: true
});
break;
}
// Extraire l'amélioration de la réponse de l'IA
let improvement = '';
const improvementMatch = result.match(/## ✅ Amélioration\s*([\s\S]*?)(?=##|$)/i);
if (improvementMatch) {
improvement = improvementMatch[1].trim();
// Mettre à jour le contenu pour la prochaine itération
currentContent += '\n\n' + improvement;
}
results.push({
iteration: i + 1,
content: result
content: result,
improvement: improvement
});
}
res.json({
success: true,
data: {
iterations: maxIterations,
results: results
iterations: results.length,
results: results,
finalContent: currentContent
}
});

View File

@ -16,6 +16,7 @@ function getMain() {
<div id="journal-controls" style="padding: 1rem; border-bottom: 1px solid var(--border-color); display: flex; gap: 1rem; align-items: center; justify-content: center;">
<button id="save-journal" class="btn success">💾 Sauvegarder</button>
<button id="load-journal" class="btn">📂 Charger</button>
<button id="preview-toggle" class="btn primary">👁 Visualiser</button>
<span id="save-status" class="text-light"></span>
</div>
@ -62,6 +63,16 @@ function getMain() {
<option value="3" selected>3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
</select>
<button id="liberty-mode" class="btn" style="flex: 1;" title="Génération créative">
🚀 Mode Liberté