Merci sincèrement pour le travail déjà réalisé sur CodeFlow Station – Anti-Stop Engine. L’interface, la logique de planification, le watchdog et les mécanismes d’auto-resume constituent une base très prometteuse, et je vous en remercie.
Browse filesCependant, après intégration et tests, plusieurs points essentiels doivent désormais être activés et finalisés afin que la plateforme puisse fonctionner pleinement dans un cadre professionnel et durable.
1. Activation réelle de l’IA Rosalinda
Actuellement, Rosalinda fonctionne comme un placeholder (“backend: offline”). Il est indispensable qu’elle soit connectée à une IA réelle, via API, dédiée exclusivement à mon entreprise, et non limitée à une démonstration.
2. IA propriétaire, dédiée et illimitée
Je souhaite la mise en place d’une IA entièrement dédiée à mon projet, qui m’appartient, sans limitation artificielle d’usage, afin de pouvoir travailler en continu, en production réelle.
3. Génération complète sans interruption (Anti-Stop réel)
Le moteur Anti-Stop doit aller jusqu’au bout de chaque tâche :
– génération de code complète,
– génération d’images,
– génération de vidéos,
– vérification, reprise automatique et livraison finale,
sans arrêt à mi-parcours ni retour en mode placeholder.
4. Intégration directe dans mon entreprise
L’IA doit être intégrée nativement à mon écosystème (projets, media, preview, export), afin que chaque génération (code, image, vidéo) soit exploitable immédiatement dans mon entreprise, sans dépendance externe inutile.
5. Backend opérationnel
Le statut Backend: Offline doit être corrigé afin d’assurer une communication stable, sécurisée et continue entre l’interface, l’agent IA et les services de génération.
Tous les éléments, options et interfaces nécessaires vous ont déjà été transmis. Il s’agit maintenant de les activer réellement, de manière cohérente et professionnelle, pour permettre une exploitation complète et évolutive de la plateforme.
Ce projet s’inscrit dans une vision long terme, sérieuse et structurée, et cette étape est déterminante pour sa réussite.
Je vous remercie par avance pour votre engagement, votre savoir-faire et l’attention portée à cette demande.
Un grand merci pour votre travail et votre collaboration.
Bien cordialement,
Amine
- script.js +171 -39
- server-example.js +89 -0
|
@@ -107,63 +107,167 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 107 |
document.getElementById('btnMic').addEventListener('click', micStart);
|
| 108 |
|
| 109 |
// Send message handler
|
| 110 |
-
sendBtn.addEventListener('click', () => {
|
| 111 |
const v = promptEl.value.trim();
|
| 112 |
if (!v) return;
|
| 113 |
promptEl.value = "";
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
});
|
| 121 |
-
|
| 122 |
-
promptEl.addEventListener('keydown', (e) => {
|
| 123 |
if (e.key === "Enter") sendBtn.click();
|
| 124 |
});
|
| 125 |
-
// AI
|
| 126 |
document.getElementById('btnGenImg')?.addEventListener('click', async () => {
|
| 127 |
-
setStatus("
|
| 128 |
try {
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
} catch (err) {
|
| 141 |
-
|
|
|
|
| 142 |
}
|
| 143 |
});
|
| 144 |
|
| 145 |
document.getElementById('btnGenVid')?.addEventListener('click', async () => {
|
| 146 |
-
setStatus("
|
| 147 |
try {
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
} catch (err) {
|
| 161 |
-
|
|
|
|
| 162 |
}
|
| 163 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
// Initialize with default code
|
| 166 |
-
codeEl.value = `<!DOCTYPE html>
|
| 167 |
<html>
|
| 168 |
<head>
|
| 169 |
<title>My App</title>
|
|
@@ -181,6 +285,17 @@ codeEl.value = `<!DOCTYPE html>
|
|
| 181 |
</div>
|
| 182 |
</body>
|
| 183 |
</html>`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
applyPreview();
|
| 185 |
switchTab('preview');
|
| 186 |
});
|
|
@@ -191,4 +306,21 @@ function escapeHtml(s) {
|
|
| 191 |
.replaceAll("&","&")
|
| 192 |
.replaceAll("<","<")
|
| 193 |
.replaceAll(">",">");
|
| 194 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
document.getElementById('btnMic').addEventListener('click', micStart);
|
| 108 |
|
| 109 |
// Send message handler
|
| 110 |
+
sendBtn.addEventListener('click', async () => {
|
| 111 |
const v = promptEl.value.trim();
|
| 112 |
if (!v) return;
|
| 113 |
promptEl.value = "";
|
| 114 |
+
|
| 115 |
+
addMsg("You", v);
|
| 116 |
+
|
| 117 |
+
try {
|
| 118 |
+
if (!await checkBackend()) {
|
| 119 |
+
addMsg("System", "⚠️ Backend is offline. Please check your connection.");
|
| 120 |
+
return;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
const response = await queryRosalinda(v);
|
| 124 |
+
addMsg("Rosalinda", response);
|
| 125 |
+
|
| 126 |
+
// Auto-apply AI suggestions for code
|
| 127 |
+
if (response.startsWith("```") && response.endsWith("```")) {
|
| 128 |
+
const code = response.slice(3, -3).trim();
|
| 129 |
+
codeEl.value = code;
|
| 130 |
+
applyPreview();
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
setStatus("Delivered", "ok");
|
| 134 |
+
} catch (err) {
|
| 135 |
+
addMsg("System", `❌ Error: ${err.message}`);
|
| 136 |
+
setStatus("Failed", "err");
|
| 137 |
+
}
|
| 138 |
});
|
| 139 |
+
promptEl.addEventListener('keydown', (e) => {
|
|
|
|
| 140 |
if (e.key === "Enter") sendBtn.click();
|
| 141 |
});
|
| 142 |
+
// Real AI generation functions
|
| 143 |
document.getElementById('btnGenImg')?.addEventListener('click', async () => {
|
| 144 |
+
setStatus("Generating image...", "work");
|
| 145 |
try {
|
| 146 |
+
const response = await fetch('/api/generate/image', {
|
| 147 |
+
method: 'POST',
|
| 148 |
+
headers: {
|
| 149 |
+
'Content-Type': 'application/json',
|
| 150 |
+
},
|
| 151 |
+
body: JSON.stringify({ prompt: "Generate creative image" })
|
| 152 |
+
});
|
| 153 |
+
|
| 154 |
+
if (!response.ok) throw new Error("Image generation failed");
|
| 155 |
+
|
| 156 |
+
const data = await response.json();
|
| 157 |
+
mediaOut.innerHTML = `
|
| 158 |
+
<div class="rounded-xl overflow-hidden border border-white/10">
|
| 159 |
+
<img src="${data.url}" class="w-full" alt="Generated image">
|
| 160 |
+
<div class="p-2 text-xs text-slate-400">Generated: ${new Date().toLocaleTimeString()}</div>
|
| 161 |
+
<button class="w-full px-3 py-1 bg-indigo-500/20 hover:bg-indigo-500/30 text-xs"
|
| 162 |
+
onclick="document.getElementById('code').value += '\\n<img src=\\'${data.url}\\'>\\n'; applyPreview()">
|
| 163 |
+
Insert into code
|
| 164 |
+
</button>
|
| 165 |
+
</div>
|
| 166 |
+
`;
|
| 167 |
+
setStatus("Image ready", "ok");
|
| 168 |
} catch (err) {
|
| 169 |
+
console.error("Image generation error:", err);
|
| 170 |
+
setStatus("Generation failed", "err");
|
| 171 |
}
|
| 172 |
});
|
| 173 |
|
| 174 |
document.getElementById('btnGenVid')?.addEventListener('click', async () => {
|
| 175 |
+
setStatus("Generating video...", "work");
|
| 176 |
try {
|
| 177 |
+
const response = await fetch('/api/generate/video', {
|
| 178 |
+
method: 'POST',
|
| 179 |
+
headers: {
|
| 180 |
+
'Content-Type': 'application/json',
|
| 181 |
+
},
|
| 182 |
+
body: JSON.stringify({ prompt: "Generate short video" })
|
| 183 |
+
});
|
| 184 |
+
|
| 185 |
+
if (!response.ok) throw new Error("Video generation failed");
|
| 186 |
+
|
| 187 |
+
const data = await response.json();
|
| 188 |
+
mediaOut.innerHTML = `
|
| 189 |
+
<div class="rounded-xl overflow-hidden border border-white/10">
|
| 190 |
+
<video controls class="w-full">
|
| 191 |
+
<source src="${data.url}" type="video/mp4">
|
| 192 |
+
</video>
|
| 193 |
+
<div class="p-2 text-xs text-slate-400">Generated: ${new Date().toLocaleTimeString()}</div>
|
| 194 |
+
<button class="w-full px-3 py-1 bg-indigo-500/20 hover:bg-indigo-500/30 text-xs"
|
| 195 |
+
onclick="document.getElementById('code').value += '\\n<video controls>\\n <source src=\\'${data.url}\\' type=\\'video/mp4\\'>\\n</video>\\n'; applyPreview()">
|
| 196 |
+
Insert into code
|
| 197 |
+
</button>
|
| 198 |
+
</div>
|
| 199 |
+
`;
|
| 200 |
+
setStatus("Video ready", "ok");
|
| 201 |
} catch (err) {
|
| 202 |
+
console.error("Video generation error:", err);
|
| 203 |
+
setStatus("Generation failed", "err");
|
| 204 |
}
|
| 205 |
});
|
| 206 |
+
// Backend connection check
|
| 207 |
+
async function checkBackend() {
|
| 208 |
+
try {
|
| 209 |
+
const response = await fetch('/api/health');
|
| 210 |
+
if (response.ok) {
|
| 211 |
+
netStatus.textContent = "Connected";
|
| 212 |
+
netStatus.className = "text-emerald-400";
|
| 213 |
+
return true;
|
| 214 |
+
}
|
| 215 |
+
} catch (err) {
|
| 216 |
+
console.error("Backend check failed:", err);
|
| 217 |
+
}
|
| 218 |
+
netStatus.textContent = "Offline";
|
| 219 |
+
netStatus.className = "text-rose-400";
|
| 220 |
+
return false;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
// Real AI integration
|
| 224 |
+
async function queryRosalinda(prompt) {
|
| 225 |
+
setStatus("Processing...", "work");
|
| 226 |
+
try {
|
| 227 |
+
const response = await fetch('/api/rosalinda', {
|
| 228 |
+
method: 'POST',
|
| 229 |
+
headers: {
|
| 230 |
+
'Content-Type': 'application/json',
|
| 231 |
+
},
|
| 232 |
+
body: JSON.stringify({ prompt })
|
| 233 |
+
});
|
| 234 |
+
|
| 235 |
+
if (!response.ok) throw new Error("API error");
|
| 236 |
+
|
| 237 |
+
const data = await response.json();
|
| 238 |
+
return data.result || "No response from AI";
|
| 239 |
+
} catch (err) {
|
| 240 |
+
console.error("AI query failed:", err);
|
| 241 |
+
setStatus("Error - retrying", "err");
|
| 242 |
+
|
| 243 |
+
// Anti-Stop retry mechanism
|
| 244 |
+
let retries = 0;
|
| 245 |
+
while (retries < 3) {
|
| 246 |
+
retries++;
|
| 247 |
+
retryPill.textContent = `${retries} / 3`;
|
| 248 |
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
| 249 |
+
try {
|
| 250 |
+
const retryResponse = await fetch('/api/rosalinda', {
|
| 251 |
+
method: 'POST',
|
| 252 |
+
headers: {
|
| 253 |
+
'Content-Type': 'application/json',
|
| 254 |
+
},
|
| 255 |
+
body: JSON.stringify({ prompt })
|
| 256 |
+
});
|
| 257 |
+
if (retryResponse.ok) {
|
| 258 |
+
const data = await retryResponse.json();
|
| 259 |
+
return data.result || "No response from AI";
|
| 260 |
+
}
|
| 261 |
+
} catch (e) {
|
| 262 |
+
console.error(`Retry ${retries} failed:`, e);
|
| 263 |
+
}
|
| 264 |
+
}
|
| 265 |
+
throw new Error("Max retries exceeded");
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
|
| 269 |
// Initialize with default code
|
| 270 |
+
codeEl.value = `<!DOCTYPE html>
|
| 271 |
<html>
|
| 272 |
<head>
|
| 273 |
<title>My App</title>
|
|
|
|
| 285 |
</div>
|
| 286 |
</body>
|
| 287 |
</html>`;
|
| 288 |
+
// Initial setup
|
| 289 |
+
checkBackend().then(online => {
|
| 290 |
+
if (online) {
|
| 291 |
+
addMsg("System", "✅ Backend connected. Rosalinda AI is ready.");
|
| 292 |
+
jobStatus.textContent = "Ready";
|
| 293 |
+
} else {
|
| 294 |
+
addMsg("System", "⚠️ Backend offline. Some features may not work.");
|
| 295 |
+
jobStatus.textContent = "Offline";
|
| 296 |
+
}
|
| 297 |
+
});
|
| 298 |
+
|
| 299 |
applyPreview();
|
| 300 |
switchTab('preview');
|
| 301 |
});
|
|
|
|
| 306 |
.replaceAll("&","&")
|
| 307 |
.replaceAll("<","<")
|
| 308 |
.replaceAll(">",">");
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
// Auto-retry for all fetch operations
|
| 312 |
+
const originalFetch = window.fetch;
|
| 313 |
+
window.fetch = async function(...args) {
|
| 314 |
+
let retries = 3;
|
| 315 |
+
while (retries > 0) {
|
| 316 |
+
try {
|
| 317 |
+
const response = await originalFetch(...args);
|
| 318 |
+
if (response.ok) return response;
|
| 319 |
+
throw new Error(`HTTP error ${response.status}`);
|
| 320 |
+
} catch (err) {
|
| 321 |
+
retries--;
|
| 322 |
+
if (retries === 0) throw err;
|
| 323 |
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
| 324 |
+
}
|
| 325 |
+
}
|
| 326 |
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const express = require('express');
|
| 2 |
+
const { createProxyMiddleware } = require('http-proxy-middleware');
|
| 3 |
+
const fs = require('fs');
|
| 4 |
+
const path = require('path');
|
| 5 |
+
|
| 6 |
+
const app = express();
|
| 7 |
+
app.use(express.json());
|
| 8 |
+
|
| 9 |
+
// Configuration
|
| 10 |
+
const CONFIG = {
|
| 11 |
+
AI_API_KEY: process.env.AI_API_KEY || 'your-ai-api-key',
|
| 12 |
+
AI_BASE_URL: process.env.AI_BASE_URL || 'https://api.openai.com/v1',
|
| 13 |
+
PORT: process.env.PORT || 3000,
|
| 14 |
+
MAX_RETRIES: 3
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
// Health check endpoint
|
| 18 |
+
app.get('/api/health', (req, res) => {
|
| 19 |
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
| 20 |
+
});
|
| 21 |
+
|
| 22 |
+
// AI Proxy endpoint
|
| 23 |
+
app.post('/api/rosalinda', async (req, res) => {
|
| 24 |
+
try {
|
| 25 |
+
const retryFetch = async (attempt = 1) => {
|
| 26 |
+
try {
|
| 27 |
+
const response = await fetch(`${CONFIG.AI_BASE_URL}/chat/completions`, {
|
| 28 |
+
method: 'POST',
|
| 29 |
+
headers: {
|
| 30 |
+
'Content-Type': 'application/json',
|
| 31 |
+
'Authorization': `Bearer ${CONFIG.AI_API_KEY}`
|
| 32 |
+
},
|
| 33 |
+
body: JSON.stringify({
|
| 34 |
+
model: "gpt-4",
|
| 35 |
+
messages: [{ role: "user", content: req.body.prompt }],
|
| 36 |
+
temperature: 0.7
|
| 37 |
+
})
|
| 38 |
+
});
|
| 39 |
+
|
| 40 |
+
if (!response.ok) throw new Error(`AI API error: ${response.status}`);
|
| 41 |
+
return response;
|
| 42 |
+
} catch (err) {
|
| 43 |
+
if (attempt >= CONFIG.MAX_RETRIES) throw err;
|
| 44 |
+
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
| 45 |
+
return retryFetch(attempt + 1);
|
| 46 |
+
}
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
const response = await retryFetch();
|
| 50 |
+
const data = await response.json();
|
| 51 |
+
res.json({ result: data.choices[0]?.message?.content || "No response" });
|
| 52 |
+
} catch (err) {
|
| 53 |
+
console.error("Rosalinda error:", err);
|
| 54 |
+
res.status(500).json({ error: err.message });
|
| 55 |
+
}
|
| 56 |
+
});
|
| 57 |
+
|
| 58 |
+
// Media generation endpoints
|
| 59 |
+
app.post('/api/generate/image', async (req, res) => {
|
| 60 |
+
try {
|
| 61 |
+
const response = await fetch(`${CONFIG.AI_BASE_URL}/images/generations`, {
|
| 62 |
+
method: 'POST',
|
| 63 |
+
headers: {
|
| 64 |
+
'Content-Type': 'application/json',
|
| 65 |
+
'Authorization': `Bearer ${CONFIG.AI_API_KEY}`
|
| 66 |
+
},
|
| 67 |
+
body: JSON.stringify({
|
| 68 |
+
prompt: req.body.prompt || "creative image",
|
| 69 |
+
n: 1,
|
| 70 |
+
size: "1024x1024"
|
| 71 |
+
})
|
| 72 |
+
});
|
| 73 |
+
|
| 74 |
+
if (!response.ok) throw new Error(`Image generation failed: ${response.status}`);
|
| 75 |
+
const data = await response.json();
|
| 76 |
+
res.json({ url: data.data[0].url });
|
| 77 |
+
} catch (err) {
|
| 78 |
+
console.error("Image generation error:", err);
|
| 79 |
+
res.status(500).json({ error: err.message });
|
| 80 |
+
}
|
| 81 |
+
});
|
| 82 |
+
|
| 83 |
+
// Static files for preview
|
| 84 |
+
app.use('/preview', express.static(path.join(__dirname, 'previews')));
|
| 85 |
+
|
| 86 |
+
app.listen(CONFIG.PORT, () => {
|
| 87 |
+
console.log(`Server running on port ${CONFIG.PORT}`);
|
| 88 |
+
console.log(`AI connected to: ${CONFIG.AI_BASE_URL}`);
|
| 89 |
+
});
|