Files
Alfredv2/alfred/app/static/js/alfred-hermes-new-session.js

112 lines
4.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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();
})();