112 lines
4.9 KiB
JavaScript
112 lines
4.9 KiB
JavaScript
/* ALFRED_HERMES_NEW_SESSION_V1 — reset sûr de la seule session conversationnelle Hermes. */
|
||
(() => {
|
||
'use strict';
|
||
function setup() {
|
||
const grid = document.querySelector('#avMoreDialog .av-more-grid');
|
||
if (!grid || document.getElementById('avHermesNewSession')) return false;
|
||
|
||
const button = document.createElement('button');
|
||
button.type = 'button';
|
||
button.id = 'avHermesNewSession';
|
||
button.className = 'av-hermes-new-session';
|
||
button.innerHTML = '<svg viewBox="0 0 24 24" class="a-icon" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 3v6h6"/><path d="M12 7v5l4 2"/></svg><span>Nouvelle session Hermes</span>';
|
||
grid.appendChild(button);
|
||
|
||
const dialog = document.createElement('dialog');
|
||
dialog.id = 'avHermesSessionDialog';
|
||
dialog.className = 'av-hermes-session-dialog';
|
||
dialog.setAttribute('aria-labelledby', 'avHermesSessionTitle');
|
||
dialog.innerHTML = `
|
||
<form method="dialog" class="av-hermes-session-content">
|
||
<h2 id="avHermesSessionTitle">Nouvelle session Hermes</h2>
|
||
<p>Repartir sans le contexte de l’ancienne conversation. La prochaine demande utilisera une nouvelle session avec les outils Hermes disponibles. La session actuelle sera sauvegardée.</p>
|
||
<p class="av-hermes-session-note">Les outils, les Skills et les réglages de Dona restent inchangés. Aucune tâche Hermes n'est annulée.</p>
|
||
<p id="avHermesSessionMessage" class="av-hermes-session-message" role="status" aria-live="polite"></p>
|
||
<div class="av-hermes-session-actions">
|
||
<button type="button" id="avHermesSessionCancel" class="av-hermes-session-secondary">Annuler</button>
|
||
<button type="button" id="avHermesSessionConfirm" class="av-hermes-session-primary">Créer une nouvelle session</button>
|
||
</div>
|
||
</form>`;
|
||
document.body.appendChild(dialog);
|
||
|
||
const msg = dialog.querySelector('#avHermesSessionMessage');
|
||
const confirm = dialog.querySelector('#avHermesSessionConfirm');
|
||
const cancel = dialog.querySelector('#avHermesSessionCancel');
|
||
let csrf = '';
|
||
let busy = false;
|
||
|
||
function setMessage(text, error = false) {
|
||
msg.textContent = text;
|
||
msg.classList.toggle('is-error', error);
|
||
}
|
||
|
||
button.addEventListener('click', async () => {
|
||
document.getElementById('avMoreDialog')?.close();
|
||
setMessage('');
|
||
confirm.hidden = false;
|
||
cancel.textContent = 'Annuler';
|
||
dialog.showModal();
|
||
confirm.disabled = true;
|
||
try {
|
||
const response = await fetch('/api/control/auth', {credentials:'same-origin',cache:'no-store'});
|
||
if (!response.ok) throw new Error('Vérification administrateur impossible.');
|
||
const auth = await response.json();
|
||
if (!auth.authenticated || !auth.csrf) {
|
||
setMessage('Connecte-toi d’abord en administrateur dans Configuration (/config), puis reviens ici.', true);
|
||
confirm.hidden = true;
|
||
cancel.textContent = 'Fermer';
|
||
const link = document.createElement('a');
|
||
link.href = '/config';
|
||
link.textContent = 'Ouvrir Configuration';
|
||
link.className = 'av-hermes-session-login';
|
||
const old = dialog.querySelector('.av-hermes-session-login');
|
||
old?.remove();
|
||
msg.after(link);
|
||
} else {
|
||
dialog.querySelector('.av-hermes-session-login')?.remove();
|
||
csrf = auth.csrf;
|
||
confirm.disabled = false;
|
||
}
|
||
} catch (e) {
|
||
setMessage(e.message, true);
|
||
}
|
||
});
|
||
|
||
cancel.addEventListener('click', () => { if (!busy) dialog.close(); });
|
||
confirm.addEventListener('click', async () => {
|
||
if (busy || !csrf) return;
|
||
busy = true;
|
||
confirm.disabled = true;
|
||
cancel.disabled = true;
|
||
setMessage('Création de la nouvelle session…');
|
||
try {
|
||
const response = await fetch('/api/control/hermes/new-session', {
|
||
method:'POST', credentials:'same-origin', cache:'no-store',
|
||
headers: {'X-Alfred-CSRF':csrf,'Content-Type':'application/json'},
|
||
body:'{}'
|
||
});
|
||
const data = await response.json();
|
||
if (!response.ok || !data.ok) throw new Error(data.error || 'Erreur HTTP '+response.status);
|
||
setMessage(data.message || 'Nouvelle session prête.');
|
||
confirm.hidden = true;
|
||
cancel.textContent = 'Fermer';
|
||
} catch (e) {
|
||
setMessage(e.message, true);
|
||
} finally {
|
||
busy = false;
|
||
cancel.disabled = false;
|
||
confirm.disabled = false;
|
||
}
|
||
});
|
||
return true;
|
||
}
|
||
|
||
function init() {
|
||
if (setup()) return;
|
||
const observer = new MutationObserver(() => { if (setup()) observer.disconnect(); });
|
||
observer.observe(document.body,{childList:true,subtree:true});
|
||
}
|
||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, {once:true});
|
||
else init();
|
||
})();
|