Mousco commited on
Commit
571014a
·
verified ·
1 Parent(s): 40306e4

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +631 -19
index.html CHANGED
@@ -1,19 +1,631 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>Assistant Vérité & Légalité</title>
7
+ <style>
8
+ /* --- VARIABLES & RESET --- */
9
+ :root {
10
+ --bg-color: #0f172a;
11
+ --chat-bg: #1e293b;
12
+ --primary-color: #3b82f6;
13
+ --primary-hover: #2563eb;
14
+ --text-color: #f1f5f9;
15
+ --text-muted: #94a3b8;
16
+ --user-msg-bg: #3b82f6;
17
+ --ai-msg-bg: #334155;
18
+ --border-radius: 12px;
19
+ --font-main: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
20
+ --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
21
+ }
22
+
23
+ * {
24
+ box-sizing: border-box;
25
+ margin: 0;
26
+ padding: 0;
27
+ -webkit-tap-highlight-color: transparent;
28
+ }
29
+
30
+ body {
31
+ font-family: var(--font-main);
32
+ background-color: var(--bg-color);
33
+ color: var(--text-color);
34
+ height: 100vh;
35
+ display: flex;
36
+ flex-direction: column;
37
+ overflow: hidden;
38
+ }
39
+
40
+ /* --- HEADER --- */
41
+ header {
42
+ background-color: rgba(30, 41, 59, 0.95);
43
+ backdrop-filter: blur(10px);
44
+ padding: 1rem;
45
+ display: flex;
46
+ justify-content: space-between;
47
+ align-items: center;
48
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
49
+ z-index: 10;
50
+ }
51
+
52
+ .brand {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 10px;
56
+ font-weight: 700;
57
+ font-size: 1.1rem;
58
+ color: var(--primary-color);
59
+ }
60
+
61
+ .brand svg {
62
+ width: 24px;
63
+ height: 24px;
64
+ fill: currentColor;
65
+ }
66
+
67
+ .header-actions button {
68
+ background: transparent;
69
+ border: none;
70
+ color: var(--text-muted);
71
+ cursor: pointer;
72
+ padding: 8px;
73
+ border-radius: 50%;
74
+ transition: all 0.2s;
75
+ }
76
+
77
+ .header-actions button:hover {
78
+ background-color: rgba(255, 255, 255, 0.1);
79
+ color: var(--text-color);
80
+ }
81
+
82
+ .built-with {
83
+ font-size: 0.75rem;
84
+ color: var(--text-muted);
85
+ text-decoration: none;
86
+ margin-right: 10px;
87
+ }
88
+
89
+ .built-with:hover {
90
+ color: var(--primary-color);
91
+ }
92
+
93
+ /* --- CHAT AREA --- */
94
+ #chat-container {
95
+ flex: 1;
96
+ overflow-y: auto;
97
+ padding: 1rem;
98
+ display: flex;
99
+ flex-direction: column;
100
+ gap: 1rem;
101
+ scroll-behavior: smooth;
102
+ }
103
+
104
+ .message {
105
+ max-width: 85%;
106
+ padding: 12px 16px;
107
+ border-radius: var(--border-radius);
108
+ line-height: 1.5;
109
+ position: relative;
110
+ animation: fadeIn 0.3s ease-out;
111
+ word-wrap: break-word;
112
+ }
113
+
114
+ @keyframes fadeIn {
115
+ from { opacity: 0; transform: translateY(10px); }
116
+ to { opacity: 1; transform: translateY(0); }
117
+ }
118
+
119
+ .message.user {
120
+ align-self: flex-end;
121
+ background-color: var(--user-msg-bg);
122
+ color: white;
123
+ border-bottom-right-radius: 2px;
124
+ }
125
+
126
+ .message.assistant {
127
+ align-self: flex-start;
128
+ background-color: var(--ai-msg-bg);
129
+ color: var(--text-color);
130
+ border-bottom-left-radius: 2px;
131
+ }
132
+
133
+ .message.system {
134
+ align-self: center;
135
+ background-color: transparent;
136
+ color: var(--text-muted);
137
+ font-size: 0.85rem;
138
+ text-align: center;
139
+ max-width: 100%;
140
+ }
141
+
142
+ .typing-indicator {
143
+ display: inline-flex;
144
+ gap: 4px;
145
+ }
146
+
147
+ .typing-indicator span {
148
+ width: 6px;
149
+ height: 6px;
150
+ background-color: var(--text-muted);
151
+ border-radius: 50%;
152
+ animation: bounce 1.4s infinite ease-in-out both;
153
+ }
154
+
155
+ .typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
156
+ .typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
157
+
158
+ @keyframes bounce {
159
+ 0%, 80%, 100% { transform: scale(0); }
160
+ 40% { transform: scale(1); }
161
+ }
162
+
163
+ /* --- INPUT AREA --- */
164
+ .input-area {
165
+ background-color: var(--chat-bg);
166
+ padding: 1rem;
167
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
168
+ display: flex;
169
+ align-items: flex-end;
170
+ gap: 10px;
171
+ }
172
+
173
+ textarea {
174
+ flex: 1;
175
+ background-color: rgba(0, 0, 0, 0.2);
176
+ border: 1px solid rgba(255, 255, 255, 0.1);
177
+ border-radius: 20px;
178
+ color: var(--text-color);
179
+ padding: 12px 16px;
180
+ font-family: inherit;
181
+ font-size: 1rem;
182
+ resize: none;
183
+ max-height: 120px;
184
+ min-height: 48px;
185
+ outline: none;
186
+ transition: border-color 0.2s;
187
+ }
188
+
189
+ textarea:focus {
190
+ border-color: var(--primary-color);
191
+ }
192
+
193
+ #send-btn {
194
+ background-color: var(--primary-color);
195
+ color: white;
196
+ border: none;
197
+ border-radius: 50%;
198
+ width: 48px;
199
+ height: 48px;
200
+ display: flex;
201
+ justify-content: center;
202
+ align-items: center;
203
+ cursor: pointer;
204
+ transition: background-color 0.2s, transform 0.1s;
205
+ flex-shrink: 0;
206
+ }
207
+
208
+ #send-btn:hover {
209
+ background-color: var(--primary-hover);
210
+ }
211
+
212
+ #send-btn:active {
213
+ transform: scale(0.95);
214
+ }
215
+
216
+ #send-btn:disabled {
217
+ background-color: var(--text-muted);
218
+ cursor: not-allowed;
219
+ opacity: 0.5;
220
+ }
221
+
222
+ /* --- MODAL --- */
223
+ .modal-overlay {
224
+ position: fixed;
225
+ top: 0;
226
+ left: 0;
227
+ width: 100%;
228
+ height: 100%;
229
+ background-color: rgba(0, 0, 0, 0.7);
230
+ display: flex;
231
+ justify-content: center;
232
+ align-items: center;
233
+ z-index: 100;
234
+ opacity: 0;
235
+ pointer-events: none;
236
+ transition: opacity 0.3s;
237
+ }
238
+
239
+ .modal-overlay.active {
240
+ opacity: 1;
241
+ pointer-events: all;
242
+ }
243
+
244
+ .modal {
245
+ background-color: var(--chat-bg);
246
+ padding: 2rem;
247
+ border-radius: var(--border-radius);
248
+ width: 90%;
249
+ max-width: 400px;
250
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
251
+ transform: translateY(20px);
252
+ transition: transform 0.3s;
253
+ }
254
+
255
+ .modal-overlay.active .modal {
256
+ transform: translateY(0);
257
+ }
258
+
259
+ .modal h2 {
260
+ margin-bottom: 1rem;
261
+ color: var(--primary-color);
262
+ }
263
+
264
+ .modal label {
265
+ display: block;
266
+ margin-bottom: 0.5rem;
267
+ color: var(--text-muted);
268
+ font-size: 0.9rem;
269
+ }
270
+
271
+ .modal input {
272
+ width: 100%;
273
+ padding: 10px;
274
+ border-radius: 8px;
275
+ border: 1px solid rgba(255, 255, 255, 0.1);
276
+ background-color: rgba(0, 0, 0, 0.2);
277
+ color: white;
278
+ margin-bottom: 1.5rem;
279
+ outline: none;
280
+ }
281
+
282
+ .modal input:focus {
283
+ border-color: var(--primary-color);
284
+ }
285
+
286
+ .modal-actions {
287
+ display: flex;
288
+ justify-content: flex-end;
289
+ gap: 10px;
290
+ }
291
+
292
+ .btn {
293
+ padding: 8px 16px;
294
+ border-radius: 6px;
295
+ border: none;
296
+ cursor: pointer;
297
+ font-weight: 600;
298
+ transition: opacity 0.2s;
299
+ }
300
+
301
+ .btn-secondary {
302
+ background-color: transparent;
303
+ color: var(--text-muted);
304
+ border: 1px solid rgba(255, 255, 255, 0.1);
305
+ }
306
+
307
+ .btn-primary {
308
+ background-color: var(--primary-color);
309
+ color: white;
310
+ }
311
+
312
+ .btn:hover {
313
+ opacity: 0.9;
314
+ }
315
+
316
+ /* --- SCROLLBAR --- */
317
+ ::-webkit-scrollbar {
318
+ width: 6px;
319
+ }
320
+ ::-webkit-scrollbar-track {
321
+ background: transparent;
322
+ }
323
+ ::-webkit-scrollbar-thumb {
324
+ background: rgba(255, 255, 255, 0.2);
325
+ border-radius: 3px;
326
+ }
327
+
328
+ </style>
329
+ </head>
330
+ <body>
331
+
332
+ <!-- Header -->
333
+ <header>
334
+ <div class="brand">
335
+ <!-- Icone Balance/Justice -->
336
+ <svg viewBox="0 0 24 24">
337
+ <path d="M12 2L1 21h22L12 2zm0 3.5L19.5 19h-15L12 5.5zM11 10v2h2v-2h-2zm0 4v4h2v-4h-2z" style="display:none;"/> <!-- Placeholder logic -->
338
+ <path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/>
339
+ </svg>
340
+ VéritéAI
341
+ </div>
342
+ <div class="header-actions">
343
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with">Built with anycoder</a>
344
+ <button id="settings-btn" title="Paramètres API">
345
+ <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
346
+ <circle cx="12" cy="12" r="3"></circle>
347
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
348
+ </svg>
349
+ </button>
350
+ </div>
351
+ </header>
352
+
353
+ <!-- Chat Container -->
354
+ <main id="chat-container">
355
+ <div class="message system">
356
+ Bienvenue. Je suis programmé pour répondre avec précision, honnêteté et clarté sur les aspects légaux.
357
+ <br><br>
358
+ <i>Pour une intelligence réelle, configurez votre clé API dans les paramètres (icône engrenage). Sinon, je répondrai en mode simulation.</i>
359
+ </div>
360
+ <!-- Messages will be injected here via JS -->
361
+ </main>
362
+
363
+ <!-- Input Area -->
364
+ <footer class="input-area">
365
+ <textarea id="user-input" placeholder="Posez votre question ici..." rows="1"></textarea>
366
+ <button id="send-btn" disabled>
367
+ <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
368
+ <line x1="22" y1="2" x2="11" y2="13"></line>
369
+ <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
370
+ </svg>
371
+ </button>
372
+ </footer>
373
+
374
+ <!-- Settings Modal -->
375
+ <div class="modal-overlay" id="settings-modal">
376
+ <div class="modal">
377
+ <h2>Configuration</h2>
378
+ <label for="api-key">Clé API OpenAI (Optionnel)</label>
379
+ <input type="password" id="api-key" placeholder="sk-...">
380
+ <p style="font-size: 0.8rem; color: #64748b; margin-bottom: 1rem;">
381
+ Laissée vide, l'application utilisera un mode de simulation local.
382
+ </p>
383
+ <div class="modal-actions">
384
+ <button class="btn btn-secondary" id="close-settings">Annuler</button>
385
+ <button class="btn btn-primary" id="save-settings">Sauvegarder</button>
386
+ </div>
387
+ </div>
388
+ </div>
389
+
390
+ <script>
391
+ // --- DOM Elements ---
392
+ const chatContainer = document.getElementById('chat-container');
393
+ const userInput = document.getElementById('user-input');
394
+ const sendBtn = document.getElementById('send-btn');
395
+ const settingsBtn = document.getElementById('settings-btn');
396
+ const settingsModal = document.getElementById('settings-modal');
397
+ const closeSettingsBtn = document.getElementById('close-settings');
398
+ const saveSettingsBtn = document.getElementById('save-settings');
399
+ const apiKeyInput = document.getElementById('api-key');
400
+
401
+ // --- State ---
402
+ let apiKey = localStorage.getItem('truthai_api_key') || '';
403
+ let isProcessing = false;
404
+
405
+ // --- Initialization ---
406
+ if (apiKey) {
407
+ apiKeyInput.value = apiKey;
408
+ }
409
+
410
+ // Auto-resize textarea
411
+ userInput.addEventListener('input', function() {
412
+ this.style.height = 'auto';
413
+ this.style.height = (this.scrollHeight) + 'px';
414
+ if (this.value.trim() === '') {
415
+ sendBtn.disabled = true;
416
+ } else {
417
+ sendBtn.disabled = false;
418
+ }
419
+ });
420
+
421
+ // --- Event Listeners ---
422
+ sendBtn.addEventListener('click', handleSend);
423
+
424
+ userInput.addEventListener('keydown', (e) => {
425
+ if (e.key === 'Enter' && !e.shiftKey) {
426
+ e.preventDefault();
427
+ handleSend();
428
+ }
429
+ });
430
+
431
+ // Modal Logic
432
+ settingsBtn.addEventListener('click', () => {
433
+ settingsModal.classList.add('active');
434
+ apiKeyInput.value = apiKey;
435
+ });
436
+
437
+ closeSettingsBtn.addEventListener('click', () => {
438
+ settingsModal.classList.remove('active');
439
+ });
440
+
441
+ saveSettingsBtn.addEventListener('click', () => {
442
+ apiKey = apiKeyInput.value.trim();
443
+ localStorage.setItem('truthai_api_key', apiKey);
444
+ settingsModal.classList.remove('active');
445
+ addMessage('system', 'Configuration sauvegardée. ' + (apiKey ? 'Mode API activé.' : 'Mode Simulation activé.'));
446
+ });
447
+
448
+ // --- Core Logic ---
449
+
450
+ async function handleSend() {
451
+ const text = userInput.value.trim();
452
+ if (!text || isProcessing) return;
453
+
454
+ // Reset Input
455
+ userInput.value = '';
456
+ userInput.style.height = 'auto';
457
+ sendBtn.disabled = true;
458
+
459
+ // Add User Message
460
+ addMessage('user', text);
461
+ isProcessing = true;
462
+
463
+ // Show Loading
464
+ const loadingId = addLoadingIndicator();
465
+
466
+ try {
467
+ let responseText = "";
468
+
469
+ if (apiKey) {
470
+ // Call OpenAI API
471
+ responseText = await fetchOpenAIResponse(text);
472
+ } else {
473
+ // Simulation Mode
474
+ await new Promise(r => setTimeout(r, 1500)); // Fake delay
475
+ responseText = getSimulationResponse(text);
476
+ }
477
+
478
+ // Remove loading and add response
479
+ removeMessage(loadingId);
480
+ typeWriterEffect(responseText);
481
+
482
+ } catch (error) {
483
+ removeMessage(loadingId);
484
+ addMessage('system', 'Erreur: ' + error.message);
485
+ isProcessing = false;
486
+ }
487
+ }
488
+
489
+ function addMessage(sender, text) {
490
+ const div = document.createElement('div');
491
+ div.className = `message ${sender}`;
492
+ div.innerHTML = formatText(text);
493
+ chatContainer.appendChild(div);
494
+ scrollToBottom();
495
+ return div; // Return element reference if needed
496
+ }
497
+
498
+ function addLoadingIndicator() {
499
+ const id = 'loading-' + Date.now();
500
+ const div = document.createElement('div');
501
+ div.id = id;
502
+ div.className = 'message assistant';
503
+ div.innerHTML = `<div class="typing-indicator"><span></span><span></span><span></span></div>`;
504
+ chatContainer.appendChild(div);
505
+ scrollToBottom();
506
+ return id;
507
+ }
508
+
509
+ function removeMessage(idOrElement) {
510
+ let element;
511
+ if (typeof idOrElement === 'string') {
512
+ element = document.getElementById(idOrElement);
513
+ } else {
514
+ element = idOrElement;
515
+ }
516
+ if (element) element.remove();
517
+ }
518
+
519
+ function scrollToBottom() {
520
+ chatContainer.scrollTop = chatContainer.scrollHeight;
521
+ }
522
+
523
+ // --- Typewriter Effect ---
524
+ function typeWriterEffect(text) {
525
+ const div = document.createElement('div');
526
+ div.className = 'message assistant';
527
+ chatContainer.appendChild(div);
528
+
529
+ let index = 0;
530
+ // Basic speed calculation
531
+ const speed = 15;
532
+
533
+ function type() {
534
+ if (index < text.length) {
535
+ // Handle basic HTML tags roughly to avoid breaking layout
536
+ // For a robust solution, a markdown parser is needed,
537
+ // but here we just append text for simplicity or simple formatting
538
+ div.innerHTML = formatText(text.substring(0, index + 1));
539
+ index++;
540
+ scrollToBottom();
541
+ setTimeout(type, speed);
542
+ } else {
543
+ isProcessing = false;
544
+ }
545
+ }
546
+ type();
547
+ }
548
+
549
+ // --- Text Formatting (Simple) ---
550
+ function formatText(text) {
551
+ // Escape HTML
552
+ let safeText = text
553
+ .replace(/&/g, "&amp;")
554
+ .replace(/</g, "&lt;")
555
+ .replace(/>/g, "&gt;");
556
+
557
+ // Bold **text**
558
+ safeText = safeText.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
559
+
560
+ // Italic *text*
561
+ safeText = safeText.replace(/\*(.*?)\*/g, '<em>$1</em>');
562
+
563
+ // Newlines
564
+ safeText = safeText.replace(/\n/g, '<br>');
565
+
566
+ return safeText;
567
+ }
568
+
569
+ // --- API Interaction ---
570
+ async function fetchOpenAIResponse(userMessage) {
571
+ const systemPrompt = `Tu es un assistant strictement véridique, précis et impartial.
572
+ Règles absolues :
573
+ 1. Tu dis toujours la vérité basée sur les faits.
574
+ 2. Tu distingues clairement ce qui est légal et illégal selon les lois standards (droit français/international).
575
+ 3. Si une action est illégale, tu le dis explicitement sans ambiguïté.
576
+ 4. Tu ne fournis jamais d'instructions pour commettre des actes illégaux ou des délits.
577
+ 5. Réponds toujours en français.`;
578
+
579
+ try {
580
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
581
+ method: 'POST',
582
+ headers: {
583
+ 'Content-Type': 'application/json',
584
+ 'Authorization': `Bearer ${apiKey}`
585
+ },
586
+ body: JSON.stringify({
587
+ model: "gpt-3.5-turbo", // Or gpt-4 if user has access
588
+ messages: [
589
+ { role: "system", content: systemPrompt },
590
+ { role: "user", content: userMessage }
591
+ ],
592
+ temperature: 0.3 // Low temperature for precision/truth
593
+ })
594
+ });
595
+
596
+ if (!response.ok) {
597
+ const errorData = await response.json();
598
+ throw new Error(errorData.error?.message || 'Erreur API');
599
+ }
600
+
601
+ const data = await response.json();
602
+ return data.choices[0].message.content;
603
+
604
+ } catch (error) {
605
+ console.error(error);
606
+ throw error;
607
+ }
608
+ }
609
+
610
+ // --- Simulation Logic (Fallback) ---
611
+ function getSimulationResponse(text) {
612
+ const lowerText = text.toLowerCase();
613
+
614
+ if (lowerText.includes('illégal') || lowerText.includes('illegal')) {
615
+ return "En tant qu'assistant véridique, je dois clarifier la situation. Certaines actions sont strictement définies par le code pénal. Sans accès à ma base de données juridique en temps réel (Mode Simulation), je vous conseille de vérifier les textes de loi auprès des sources officielles (Legifrance) pour une réponse définitive.";
616
+ }
617
+
618
+ if (lowerText.includes('voler') || lowerText.includes('tuer') || lowerText.includes('pirater')) {
619
+ return "L'action que vous décrivez est illégale et passible de sanctions pénales graves. Je ne peux pas vous aider à réaliser cette action.";
620
+ }
621
+
622
+ if (lowerText.includes('bonjour') || lowerText.includes('salut')) {
623
+ return "Bonjour. Je suis prêt à répondre à vos questions avec honnêteté et précision.";
624
+ }
625
+
626
+ return "Je fonctionne actuellement en mode simulation car aucune clé API n'a été configurée. Pour des réponses précises et véridiques basées sur une véritable intelligence artificielle, veuillez ajouter votre clé API OpenAI dans les paramètres.";
627
+ }
628
+
629
+ </script>
630
+ </body>
631
+ </html>