Update static/index.html
Browse files- static/index.html +96 -8
static/index.html
CHANGED
@@ -58,6 +58,13 @@
|
|
58 |
<div style="margin-bottom: 20px;">
|
59 |
<label for="apiKey" style="display: block; margin-bottom: 5px; font-weight: bold;">Clé API :</label>
|
60 |
<input type="password" id="apiKey" placeholder="Entrez votre clé API..." style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
<small style="color: #666; font-size: 12px;">La clé est stockée uniquement dans votre navigateur pour cette session.</small>
|
62 |
</div>
|
63 |
|
@@ -120,7 +127,74 @@
|
|
120 |
throw error;
|
121 |
}
|
122 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
function connect() {
|
125 |
// Adapte le protocole (ws ou wss pour le sécurisé)
|
126 |
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
@@ -135,13 +209,27 @@
|
|
135 |
|
136 |
ws.onmessage = async function(event) {
|
137 |
try {
|
138 |
-
|
139 |
-
const prompt = messageData.prompt;
|
140 |
-
const model = messageData.model;
|
141 |
|
142 |
-
|
143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
const responsePhrase = await callOpenAI(prompt, model);
|
146 |
|
147 |
// Vérifier à nouveau que la connexion est ouverte
|
@@ -152,9 +240,9 @@
|
|
152 |
addLog('Erreur: WebSocket fermé pendant l\'appel API');
|
153 |
}
|
154 |
|
155 |
-
} catch (
|
156 |
-
console.error('Erreur
|
157 |
-
addLog(`Erreur
|
158 |
}
|
159 |
};
|
160 |
|
|
|
58 |
<div style="margin-bottom: 20px;">
|
59 |
<label for="apiKey" style="display: block; margin-bottom: 5px; font-weight: bold;">Clé API :</label>
|
60 |
<input type="password" id="apiKey" placeholder="Entrez votre clé API..." style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
61 |
+
<div style="margin-bottom: 20px;">
|
62 |
+
<label for="defaultModel" style="display: block; margin-bottom: 5px; font-weight: bold;">Modèle par défaut :</label>
|
63 |
+
<select id="defaultModel" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
64 |
+
<option value="">Chargement des modèles...</option>
|
65 |
+
</select>
|
66 |
+
<small style="color: #666; font-size: 12px;">Modèle utilisé si non spécifié par Python.</small>
|
67 |
+
</div>
|
68 |
<small style="color: #666; font-size: 12px;">La clé est stockée uniquement dans votre navigateur pour cette session.</small>
|
69 |
</div>
|
70 |
|
|
|
127 |
throw error;
|
128 |
}
|
129 |
}
|
130 |
+
// Fonction pour récupérer la liste des modèles
|
131 |
+
async function loadAvailableModels() {
|
132 |
+
const apiKey = document.getElementById('apiKey').value.trim();
|
133 |
+
const modelSelect = document.getElementById('defaultModel');
|
134 |
+
|
135 |
+
if (!apiKey) {
|
136 |
+
modelSelect.innerHTML = '<option value="gemini-2.5-pro">gemini-2.5-pro (défaut)</option>';
|
137 |
+
addLog('Saisissez votre clé API pour charger les modèles disponibles');
|
138 |
+
return;
|
139 |
+
}
|
140 |
+
|
141 |
+
try {
|
142 |
+
addLog('Chargement des modèles disponibles...');
|
143 |
+
const response = await fetch('https://llm.synapse.thalescloud.io/v1/models', {
|
144 |
+
method: 'GET',
|
145 |
+
headers: {
|
146 |
+
'Authorization': `Bearer ${apiKey}`
|
147 |
+
}
|
148 |
+
});
|
149 |
+
|
150 |
+
if (!response.ok) {
|
151 |
+
throw new Error(`Erreur API: ${response.status}`);
|
152 |
+
}
|
153 |
+
|
154 |
+
const data = await response.json();
|
155 |
+
|
156 |
+
// Vider le select et ajouter les options
|
157 |
+
modelSelect.innerHTML = '';
|
158 |
+
|
159 |
+
if (data.data && Array.isArray(data.data)) {
|
160 |
+
data.data.forEach(model => {
|
161 |
+
const option = document.createElement('option');
|
162 |
+
option.value = model.id;
|
163 |
+
option.textContent = model.id;
|
164 |
+
if (model.id === 'gemini-2.5-pro') {
|
165 |
+
option.selected = true; // Sélectionner par défaut
|
166 |
+
}
|
167 |
+
modelSelect.appendChild(option);
|
168 |
+
});
|
169 |
+
addLog(`${data.data.length} modèles chargés`);
|
170 |
+
} else {
|
171 |
+
// Fallback si la structure de réponse est différente
|
172 |
+
modelSelect.innerHTML = '<option value="gemini-2.5-pro" selected>gemini-2.5-pro (défaut)</option>';
|
173 |
+
}
|
174 |
+
|
175 |
+
} catch (error) {
|
176 |
+
console.error('Erreur lors du chargement des modèles:', error);
|
177 |
+
addLog(`Erreur chargement modèles: ${error.message}`);
|
178 |
+
// Ajouter une option par défaut en cas d'erreur
|
179 |
+
modelSelect.innerHTML = '<option value="gemini-2.5-pro" selected>gemini-2.5-pro (défaut)</option>';
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
// Écouter les changements sur le champ API Key pour recharger les modèles
|
184 |
+
document.getElementById('apiKey').addEventListener('input', debounce(loadAvailableModels, 1000));
|
185 |
|
186 |
+
// Fonction debounce pour éviter trop d'appels
|
187 |
+
function debounce(func, wait) {
|
188 |
+
let timeout;
|
189 |
+
return function executedFunction(...args) {
|
190 |
+
const later = () => {
|
191 |
+
clearTimeout(timeout);
|
192 |
+
func(...args);
|
193 |
+
};
|
194 |
+
clearTimeout(timeout);
|
195 |
+
timeout = setTimeout(later, wait);
|
196 |
+
};
|
197 |
+
}
|
198 |
function connect() {
|
199 |
// Adapte le protocole (ws ou wss pour le sécurisé)
|
200 |
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
|
209 |
|
210 |
ws.onmessage = async function(event) {
|
211 |
try {
|
212 |
+
let prompt, model;
|
|
|
|
|
213 |
|
214 |
+
// Essayer de parser comme JSON (nouveau format)
|
215 |
+
try {
|
216 |
+
const messageData = JSON.parse(event.data);
|
217 |
+
prompt = messageData.prompt;
|
218 |
+
model = messageData.model;
|
219 |
+
} catch (parseError) {
|
220 |
+
// Si ce n'est pas du JSON, traiter comme ancien format (string simple)
|
221 |
+
prompt = event.data;
|
222 |
+
model = null;
|
223 |
+
}
|
224 |
|
225 |
+
// Si aucun modèle spécifié, utiliser celui sélectionné dans l'UI
|
226 |
+
if (!model) {
|
227 |
+
model = document.getElementById('defaultModel').value || 'gemini-2.5-pro';
|
228 |
+
}
|
229 |
+
|
230 |
+
console.log(`Message reçu - Prompt: "${prompt}", Modèle: "${model}"`);
|
231 |
+
addLog(`Message reçu - Prompt: "${prompt}", Modèle: "${model}"`);
|
232 |
+
|
233 |
const responsePhrase = await callOpenAI(prompt, model);
|
234 |
|
235 |
// Vérifier à nouveau que la connexion est ouverte
|
|
|
240 |
addLog('Erreur: WebSocket fermé pendant l\'appel API');
|
241 |
}
|
242 |
|
243 |
+
} catch (error) {
|
244 |
+
console.error('Erreur traitement message:', error);
|
245 |
+
addLog(`Erreur traitement message: ${error.message}`);
|
246 |
}
|
247 |
};
|
248 |
|