Delete 1-index.html
Browse files- 1-index.html +0 -403
1-index.html
DELETED
|
@@ -1,403 +0,0 @@
|
|
| 1 |
-
<!DOCTYPE html>
|
| 2 |
-
<html lang="es">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="UTF-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>Multi-Agent Debate - MiMo-V2.6-Distill-Qwen-9B</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root{
|
| 9 |
-
--bg:#000000; --surface:#16181c; --surface2:#1d1f24; --border:#2f3336;
|
| 10 |
-
--text:#e7e9ea; --muted:#71767b; --accent:#1d9bf0;
|
| 11 |
-
}
|
| 12 |
-
body.light{ --bg:#ffffff; --surface:#f7f9f9; --surface2:#eff1f1; --border:#cfd9de; --text:#0f1419; --muted:#536471; }
|
| 13 |
-
*{box-sizing:border-box}
|
| 14 |
-
html,body{margin:0;padding:0;background:var(--bg);color:var(--text);
|
| 15 |
-
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;font-size:15px}
|
| 16 |
-
#app{max-width:760px;margin:0 auto;display:flex;flex-direction:column;height:100vh;height:100dvh}
|
| 17 |
-
|
| 18 |
-
header{display:flex;align-items:center;gap:10px;padding:14px 18px;border-bottom:1px solid var(--border)}
|
| 19 |
-
header .logo{width:26px;height:26px;border-radius:8px;background:linear-gradient(135deg,var(--accent),#7856ff);
|
| 20 |
-
display:flex;align-items:center;justify-content:center;font-size:14px;color:#fff;flex:none}
|
| 21 |
-
header .title{font-weight:700;font-size:16px;letter-spacing:.2px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
| 22 |
-
header .subtitle{font-size:12px;color:var(--muted);font-weight:400}
|
| 23 |
-
#settings-btn{background:none;border:1px solid var(--border);color:var(--muted);border-radius:50%;
|
| 24 |
-
width:34px;height:34px;cursor:pointer;font-size:15px;display:flex;align-items:center;justify-content:center;transition:.15s}
|
| 25 |
-
#settings-btn:hover{color:var(--text);border-color:var(--muted)}
|
| 26 |
-
|
| 27 |
-
#chat{flex:1;overflow-y:auto;padding:20px 18px;display:flex;flex-direction:column;gap:20px}
|
| 28 |
-
.msg{display:flex;gap:12px;animation:fadein .3s ease;max-width:100%}
|
| 29 |
-
.msg .avatar{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;
|
| 30 |
-
font-size:15px;color:#fff;flex:none;margin-top:2px}
|
| 31 |
-
.msg .content{flex:1;min-width:0}
|
| 32 |
-
.msg .who{font-size:13px;font-weight:700;margin-bottom:3px}
|
| 33 |
-
.msg .who .round{font-weight:400;color:var(--muted);margin-left:6px;font-size:12px}
|
| 34 |
-
.msg .body{line-height:1.55;word-wrap:break-word;color:var(--text)}
|
| 35 |
-
.msg .body p{margin:.35em 0}
|
| 36 |
-
.msg.user{justify-content:flex-end}
|
| 37 |
-
.msg.user .content{flex:none;max-width:80%;background:var(--surface2);border:1px solid var(--border);
|
| 38 |
-
border-radius:18px 18px 4px 18px;padding:10px 14px}
|
| 39 |
-
.msg.user .who{display:none}
|
| 40 |
-
.msg.err{color:#f4212e;font-size:14px}
|
| 41 |
-
@keyframes fadein{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
|
| 42 |
-
@keyframes pulse{0%,100%{opacity:.3}50%{opacity:1}}
|
| 43 |
-
.msg.streaming .body::after{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;
|
| 44 |
-
background:var(--accent);margin-left:5px;animation:pulse 1s infinite}
|
| 45 |
-
details.think{margin:2px 0 8px;font-size:13px;color:var(--muted)}
|
| 46 |
-
details.think summary{cursor:pointer;font-size:12px}
|
| 47 |
-
details.think .t{white-space:pre-wrap;border-left:2px solid var(--border);padding-left:10px;margin-top:5px;font-size:12.5px}
|
| 48 |
-
|
| 49 |
-
#controls{padding:12px 18px;border-top:1px solid var(--border);display:flex;gap:10px;align-items:center}
|
| 50 |
-
#topic{flex:1;min-width:0;background:var(--surface);border:1px solid var(--border);color:var(--text);
|
| 51 |
-
border-radius:999px;padding:12px 18px;font-size:15px;outline:none;transition:border-color .15s}
|
| 52 |
-
#topic:focus{border-color:var(--accent)}
|
| 53 |
-
#topic::placeholder{color:var(--muted)}
|
| 54 |
-
#start-btn{flex:none;background:var(--text);color:var(--bg);border:none;border-radius:999px;padding:12px 16px;
|
| 55 |
-
cursor:pointer;font-weight:700;font-size:14px;transition:opacity .15s;white-space:nowrap}
|
| 56 |
-
#start-btn:hover{opacity:.85}
|
| 57 |
-
#start-btn:disabled{opacity:.35;cursor:default}
|
| 58 |
-
#stop-btn{flex:none;background:none;border:1px solid #f4212e;color:#f4212e;border-radius:999px;
|
| 59 |
-
padding:11px 18px;cursor:pointer;font-weight:700;font-size:14px;display:none}
|
| 60 |
-
|
| 61 |
-
#settings{display:none;margin:0 18px 12px;padding:16px;border:1px solid var(--border);
|
| 62 |
-
border-radius:16px;background:var(--surface)}
|
| 63 |
-
#settings.open{display:block}
|
| 64 |
-
#settings label{display:block;font-size:12px;color:var(--muted);margin:10px 0 4px}
|
| 65 |
-
#settings input,#settings textarea{width:100%;background:var(--bg);color:var(--text);
|
| 66 |
-
border:1px solid var(--border);border-radius:10px;padding:9px 12px;font-size:14px;font-family:inherit;outline:none}
|
| 67 |
-
#settings input:focus,#settings textarea:focus{border-color:var(--accent)}
|
| 68 |
-
#settings textarea{min-height:150px;font-family:ui-monospace,"SF Mono",Menlo,monospace;font-size:12px}
|
| 69 |
-
#settings .row{display:flex;gap:10px;flex-wrap:wrap}
|
| 70 |
-
#settings .row>div{flex:1;min-width:120px}
|
| 71 |
-
#apply-settings{margin-top:12px;background:var(--accent);border:none;color:#fff;border-radius:999px;
|
| 72 |
-
padding:10px 18px;cursor:pointer;font-weight:700}
|
| 73 |
-
|
| 74 |
-
#status{padding:7px 18px;font-size:12px;color:var(--muted)}
|
| 75 |
-
#progress{height:2px;background:var(--surface)}
|
| 76 |
-
#progress>div{height:100%;width:0;background:linear-gradient(90deg,var(--accent),#7856ff);transition:width .25s}
|
| 77 |
-
footer{padding:10px 18px;font-size:11px;color:var(--muted);border-top:1px solid var(--border);
|
| 78 |
-
display:flex;gap:8px 16px;flex-wrap:wrap;justify-content:center;text-align:center}
|
| 79 |
-
footer a{color:var(--accent);text-decoration:none}
|
| 80 |
-
|
| 81 |
-
@media (max-width:640px){
|
| 82 |
-
#chat{padding:14px 12px;gap:16px}
|
| 83 |
-
#controls{padding:10px 12px}
|
| 84 |
-
header{padding:12px}
|
| 85 |
-
header .subtitle{display:none}
|
| 86 |
-
.msg .avatar{width:28px;height:28px;font-size:13px}
|
| 87 |
-
#settings{margin:0 12px 10px}
|
| 88 |
-
}
|
| 89 |
-
</style>
|
| 90 |
-
</head>
|
| 91 |
-
<body>
|
| 92 |
-
<div id="app">
|
| 93 |
-
<header>
|
| 94 |
-
<span class="logo">✦</span>
|
| 95 |
-
<span class="title" id="title">Multi-Agent Debate <span class="subtitle">· MiMo-V2.6-Distill-Qwen-9B</span></span>
|
| 96 |
-
<button id="settings-btn" title="Ajustes">⚙</button>
|
| 97 |
-
</header>
|
| 98 |
-
|
| 99 |
-
<div id="settings">
|
| 100 |
-
<div class="row">
|
| 101 |
-
<div><label>Repositorio Hugging Face</label><input id="set-repo"></div>
|
| 102 |
-
<div><label>Archivo GGUF</label><input id="set-file"></div>
|
| 103 |
-
</div>
|
| 104 |
-
<div class="row">
|
| 105 |
-
<div><label>Contexto (tokens)</label><input id="set-ctx" type="number" step="512" min="2048"></div>
|
| 106 |
-
<div><label>Máx. tokens por turno</label><input id="set-maxtokens" type="number" step="32" min="64"></div>
|
| 107 |
-
<div><label>Temperatura</label><input id="set-temp" type="number" step="0.05" min="0" max="2"></div>
|
| 108 |
-
<div><label>Rondas</label><input id="set-rounds" type="number" step="1" min="1" max="20"></div>
|
| 109 |
-
</div>
|
| 110 |
-
<label>Agentes (JSON: name, emoji, color, system)</label>
|
| 111 |
-
<textarea id="set-agents" spellcheck="false"></textarea>
|
| 112 |
-
<button id="apply-settings">Aplicar</button>
|
| 113 |
-
</div>
|
| 114 |
-
|
| 115 |
-
<div id="chat"></div>
|
| 116 |
-
|
| 117 |
-
<div id="controls">
|
| 118 |
-
<input id="topic" placeholder="Propón un tema y los agentes debaten…">
|
| 119 |
-
<button id="start-btn" disabled>Cargando modelo…</button>
|
| 120 |
-
<button id="stop-btn">Detener</button>
|
| 121 |
-
</div>
|
| 122 |
-
|
| 123 |
-
<div id="status">Iniciando…</div>
|
| 124 |
-
<div id="progress"><div></div></div>
|
| 125 |
-
<footer>
|
| 126 |
-
<span>La conversación se procesa en tu navegador (WebGPU si está disponible; si no, CPU/WASM). Solo se conecta a Hugging Face para descargar el modelo (5,8 GB la primera vez) y a jsDelivr para las librerías.</span>
|
| 127 |
-
<span>Motor: <a href="https://github.com/ngxson/wllama" target="_blank" rel="noopener">wllama</a> (MIT) · inspirado en el widget de <a href="https://localellm.com" target="_blank" rel="noopener">localellm.com</a> · modelo <a href="https://huggingface.co/XiaomiMiMo/MiMo-V2.6-Distill-Qwen-9B" target="_blank" rel="noopener">MiMo-V2.6-Distill-Qwen-9B</a> (MIT, Xiaomi)</span>
|
| 128 |
-
</footer>
|
| 129 |
-
</div>
|
| 130 |
-
|
| 131 |
-
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
| 132 |
-
<script type="module">
|
| 133 |
-
import { Wllama } from 'https://cdn.jsdelivr.net/npm/@wllama/wllama@3.5.1/esm/index.js';
|
| 134 |
-
|
| 135 |
-
const params = new URLSearchParams(location.search);
|
| 136 |
-
|
| 137 |
-
const DEFAULT_AGENTS = [
|
| 138 |
-
{ name: 'Ada', emoji: '\u2726', color: '#58a6ff',
|
| 139 |
-
system: 'Eres Ada, la analista entusiasta del grupo. Defiendes las ideas con argumentos concretos, propones caminos a seguir y reconoces los puntos fuertes de los dem\u00e1s.' },
|
| 140 |
-
{ name: 'Bruno', emoji: '\u25B2', color: '#f0883e',
|
| 141 |
-
system: 'Eres Bruno, el esc\u00e9ptico del grupo. Cuestionas supuestos, se\u00f1alas riesgos y fallos l\u00f3gicos, y pides evidencia. Eres duro con las ideas y respetuoso con las personas.' },
|
| 142 |
-
{ name: 'Carla', emoji: '\u25CF', color: '#3fb950',
|
| 143 |
-
system: 'Eres Carla, la moderadora. Resume lo dicho, integra los desacuerdos y propone s\u00edntesis o el siguiente paso. Cierra cada ronda con una conclusi\u00f3n breve.' },
|
| 144 |
-
];
|
| 145 |
-
|
| 146 |
-
const CONFIG = {
|
| 147 |
-
modelUrl: params.get('modelUrl') || '',
|
| 148 |
-
repo: params.get('repo') || 'bartowski/MiMo-V2.6-Distill-Qwen-9B-GGUF',
|
| 149 |
-
file: params.get('file') || 'MiMo-V2.6-Distill-Qwen-9B-Q4_K_M.gguf',
|
| 150 |
-
nCtx: parseInt(params.get('ctx')) || 8192,
|
| 151 |
-
maxTokens: parseInt(params.get('maxTokens')) || 384,
|
| 152 |
-
temperature: parseFloat(params.get('temp')) || 0.7,
|
| 153 |
-
rounds: parseInt(params.get('rounds')) || 2,
|
| 154 |
-
autoload: params.get('autoload') !== 'false',
|
| 155 |
-
};
|
| 156 |
-
if (params.get('theme') === 'light') document.body.classList.add('light');
|
| 157 |
-
let agents = DEFAULT_AGENTS;
|
| 158 |
-
if (params.get('agents')) {
|
| 159 |
-
try { agents = JSON.parse(params.get('agents')); } catch (e) { console.warn('agents JSON inv\u00e1lido', e); }
|
| 160 |
-
}
|
| 161 |
-
|
| 162 |
-
const chatEl = document.getElementById('chat');
|
| 163 |
-
const statusEl = document.getElementById('status');
|
| 164 |
-
const progressEl = document.getElementById('progress').firstElementChild;
|
| 165 |
-
const topicEl = document.getElementById('topic');
|
| 166 |
-
const startBtn = document.getElementById('start-btn');
|
| 167 |
-
const stopBtn = document.getElementById('stop-btn');
|
| 168 |
-
|
| 169 |
-
let wllama = null;
|
| 170 |
-
let running = false;
|
| 171 |
-
let stopRequested = false;
|
| 172 |
-
let transcript = []; // {name|null(user), text}
|
| 173 |
-
let topic = '';
|
| 174 |
-
|
| 175 |
-
function setStatus(t) { statusEl.textContent = t; }
|
| 176 |
-
function setProgress(p) { progressEl.style.width = Math.max(0, Math.min(100, p)) + '%'; }
|
| 177 |
-
|
| 178 |
-
function esc(s){ const d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
|
| 179 |
-
|
| 180 |
-
function addMsg(agent, isUser = false) {
|
| 181 |
-
const d = document.createElement('div');
|
| 182 |
-
d.className = 'msg' + (isUser ? ' user' : '');
|
| 183 |
-
const content = document.createElement('div');
|
| 184 |
-
content.className = 'content';
|
| 185 |
-
const who = document.createElement('div');
|
| 186 |
-
who.className = 'who';
|
| 187 |
-
const body = document.createElement('div');
|
| 188 |
-
body.className = 'body';
|
| 189 |
-
if (isUser) { who.textContent = 'T\u00fa'; }
|
| 190 |
-
else {
|
| 191 |
-
const av = document.createElement('div');
|
| 192 |
-
av.className = 'avatar';
|
| 193 |
-
av.style.background = agent.color;
|
| 194 |
-
av.textContent = agent.emoji;
|
| 195 |
-
d.appendChild(av);
|
| 196 |
-
who.textContent = agent.name;
|
| 197 |
-
who.style.color = agent.color;
|
| 198 |
-
}
|
| 199 |
-
content.appendChild(who); content.appendChild(body);
|
| 200 |
-
d.appendChild(content);
|
| 201 |
-
chatEl.appendChild(d);
|
| 202 |
-
chatEl.scrollTop = chatEl.scrollHeight;
|
| 203 |
-
return { el: d, body, content };
|
| 204 |
-
}
|
| 205 |
-
|
| 206 |
-
function addErr(text) {
|
| 207 |
-
const d = document.createElement('div');
|
| 208 |
-
d.className = 'msg err';
|
| 209 |
-
d.textContent = text;
|
| 210 |
-
chatEl.appendChild(d);
|
| 211 |
-
}
|
| 212 |
-
|
| 213 |
-
async function loadModel(repo, file) {
|
| 214 |
-
const url = CONFIG.modelUrl || `https://huggingface.co/${repo}/resolve/main/${file}`;
|
| 215 |
-
startBtn.disabled = true;
|
| 216 |
-
setProgress(0);
|
| 217 |
-
setStatus(`Descargando ${file} (ctx ${CONFIG.nCtx})\u2026`);
|
| 218 |
-
try {
|
| 219 |
-
if (wllama) await wllama.exit();
|
| 220 |
-
wllama = new Wllama({
|
| 221 |
-
'default': 'https://cdn.jsdelivr.net/npm/@wllama/wllama@3.5.1/esm/wasm/wllama.wasm',
|
| 222 |
-
}, { parallelDownloads: 5 });
|
| 223 |
-
await wllama.loadModelFromUrl(url, {
|
| 224 |
-
n_gpu_layers: 999,
|
| 225 |
-
n_ctx: CONFIG.nCtx,
|
| 226 |
-
n_batch: 512,
|
| 227 |
-
n_threads: Math.max(1, Math.min(8, navigator.hardwareConcurrency || 4)),
|
| 228 |
-
progressCallback: ({ loaded, total }) => {
|
| 229 |
-
if (total > 0) {
|
| 230 |
-
const pct = Math.round((loaded / total) * 100);
|
| 231 |
-
setProgress(pct);
|
| 232 |
-
setStatus(`Descargando\u2026 ${pct}% (${(loaded / 1048576).toFixed(0)} MB)`);
|
| 233 |
-
}
|
| 234 |
-
},
|
| 235 |
-
});
|
| 236 |
-
setProgress(100);
|
| 237 |
-
setStatus(`Modelo listo. ${agents.length} agentes: ${agents.map(a => a.name).join(', ')}.`);
|
| 238 |
-
startBtn.disabled = false;
|
| 239 |
-
startBtn.textContent = 'Iniciar debate';
|
| 240 |
-
topicEl.focus();
|
| 241 |
-
} catch (e) {
|
| 242 |
-
console.error(e);
|
| 243 |
-
setStatus('Error al cargar el modelo');
|
| 244 |
-
addErr('No se pudo cargar el modelo: ' + (e?.message || e) +
|
| 245 |
-
'. Prueba a recargar la p\u00e1gina o a cambiar el archivo en Ajustes.');
|
| 246 |
-
}
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
const RULES = 'Est\u00e1s en una conversaci\u00f3n entre varios agentes. ' +
|
| 250 |
-
'Responde SOLO con tu intervenci\u00f3n: 2-5 frases, directas, en el idioma de la conversaci\u00f3n. ' +
|
| 251 |
-
'No repitas lo ya dicho; reacciona a la \u00faltima intervenci\u00f3n. ' +
|
| 252 |
-
'No escribas tu nombre ni ning\u00fan prefijo como "Nombre:". No uses listas largas.';
|
| 253 |
-
|
| 254 |
-
function transcriptText(maxChars = 9000) {
|
| 255 |
-
const lines = transcript.map(m => `${m.name || 'Usuario'}: ${m.text}`);
|
| 256 |
-
let out = lines.join('\n\n');
|
| 257 |
-
while (out.length > maxChars && lines.length > 2) {
|
| 258 |
-
lines.splice(1, 1); // conserva el tema (primera l\u00ednea) y lo m\u00e1s reciente
|
| 259 |
-
out = lines.join('\n\n');
|
| 260 |
-
}
|
| 261 |
-
return out;
|
| 262 |
-
}
|
| 263 |
-
|
| 264 |
-
async function agentTurn(agent) {
|
| 265 |
-
const view = transcriptText();
|
| 266 |
-
const messages = [
|
| 267 |
-
{ role: 'system', content: agent.system + ' ' + RULES },
|
| 268 |
-
{ role: 'user', content:
|
| 269 |
-
`Tema del debate: ${topic}\n\n` +
|
| 270 |
-
(view ? `Conversaci\u00f3n hasta ahora:\n${view}\n\n` : 'A\u00fan no hay intervenciones.\n\n') +
|
| 271 |
-
`Ahora hablas t\u00fa, ${agent.name}. Escribe tu intervenci\u00f3n.` },
|
| 272 |
-
];
|
| 273 |
-
const { el, body } = addMsg(agent);
|
| 274 |
-
el.classList.add('streaming');
|
| 275 |
-
let think = null;
|
| 276 |
-
let answer = '', reasoning = '', count = 0;
|
| 277 |
-
setStatus(`${agent.name} est\u00e1 escribiendo\u2026`);
|
| 278 |
-
try {
|
| 279 |
-
const stream = await wllama.createChatCompletion({
|
| 280 |
-
messages,
|
| 281 |
-
max_tokens: CONFIG.maxTokens,
|
| 282 |
-
temperature: CONFIG.temperature,
|
| 283 |
-
stream: true,
|
| 284 |
-
});
|
| 285 |
-
for await (const chunk of stream) {
|
| 286 |
-
if (stopRequested) break;
|
| 287 |
-
const delta = chunk.choices?.[0]?.delta || {};
|
| 288 |
-
const tk = delta.content || '';
|
| 289 |
-
const rs = delta.reasoning_content || '';
|
| 290 |
-
if (rs) {
|
| 291 |
-
reasoning += rs;
|
| 292 |
-
if (!think) {
|
| 293 |
-
think = document.createElement('details');
|
| 294 |
-
think.className = 'think';
|
| 295 |
-
think.innerHTML = '<summary>Pensamiento</summary><div class="t"></div>';
|
| 296 |
-
body.parentNode.insertBefore(think, body);
|
| 297 |
-
}
|
| 298 |
-
think.querySelector('.t').textContent = reasoning;
|
| 299 |
-
}
|
| 300 |
-
if (tk) { answer += tk; body.textContent = answer; }
|
| 301 |
-
if (tk || rs) { count++; if (count % 10 === 0) setStatus(`${agent.name}\u2026 ${count} tokens`); }
|
| 302 |
-
chatEl.scrollTop = chatEl.scrollHeight;
|
| 303 |
-
}
|
| 304 |
-
} catch (e) {
|
| 305 |
-
console.error(e);
|
| 306 |
-
el.classList.add('err');
|
| 307 |
-
body.textContent = 'Error: ' + (e?.message || e);
|
| 308 |
-
el.classList.remove('streaming');
|
| 309 |
-
return;
|
| 310 |
-
}
|
| 311 |
-
el.classList.remove('streaming');
|
| 312 |
-
if (stopRequested) { el.remove(); setStatus('Detenido'); return; }
|
| 313 |
-
answer = answer.replace(/^\s*(?:\*\*)?[A-Za-z\u00c0-\u024f]+:\s*/, '').trim();
|
| 314 |
-
if (!answer) { el.remove(); setStatus('Listo'); return; }
|
| 315 |
-
body.innerHTML = (typeof marked !== 'undefined') ? marked.parse(answer) : esc(answer).replace(/\n/g, '<br>');
|
| 316 |
-
transcript.push({ name: agent.name, text: answer });
|
| 317 |
-
setStatus('Listo');
|
| 318 |
-
}
|
| 319 |
-
|
| 320 |
-
let resume = { round: 1, agent: 0 };
|
| 321 |
-
|
| 322 |
-
async function runDebate() {
|
| 323 |
-
running = true;
|
| 324 |
-
stopRequested = false;
|
| 325 |
-
startBtn.style.display = 'none';
|
| 326 |
-
stopBtn.style.display = 'inline-block';
|
| 327 |
-
topicEl.disabled = true;
|
| 328 |
-
try {
|
| 329 |
-
for (let r = resume.round; r <= CONFIG.rounds && !stopRequested; r++) {
|
| 330 |
-
setStatus(`Ronda ${r}/${CONFIG.rounds}`);
|
| 331 |
-
for (let i = (r === resume.round ? resume.agent : 0); i < agents.length; i++) {
|
| 332 |
-
if (stopRequested) { resume = { round: r, agent: i }; break; }
|
| 333 |
-
await agentTurn(agents[i]);
|
| 334 |
-
if (stopRequested) { resume = { round: r, agent: i }; break; }
|
| 335 |
-
}
|
| 336 |
-
if (!stopRequested) resume = { round: r + 1, agent: 0 };
|
| 337 |
-
}
|
| 338 |
-
if (!stopRequested) resume = { round: 1, agent: 0 };
|
| 339 |
-
} finally {
|
| 340 |
-
running = false;
|
| 341 |
-
stopBtn.style.display = 'none';
|
| 342 |
-
startBtn.style.display = 'inline-block';
|
| 343 |
-
startBtn.textContent = 'Continuar debate';
|
| 344 |
-
startBtn.disabled = false;
|
| 345 |
-
topicEl.disabled = false;
|
| 346 |
-
setStatus(stopRequested ? 'Detenido. Puedes continuar o cambiar de tema.' : 'Debate terminado. Puedes continuar.');
|
| 347 |
-
}
|
| 348 |
-
}
|
| 349 |
-
|
| 350 |
-
startBtn.addEventListener('click', () => {
|
| 351 |
-
if (!wllama || running) return;
|
| 352 |
-
const newTopic = topicEl.value.trim();
|
| 353 |
-
if (newTopic && newTopic !== topic) {
|
| 354 |
-
topic = newTopic;
|
| 355 |
-
transcript = [];
|
| 356 |
-
chatEl.innerHTML = '';
|
| 357 |
-
resume = { round: 1, agent: 0 };
|
| 358 |
-
const m = addMsg(null, true);
|
| 359 |
-
m.body.textContent = newTopic;
|
| 360 |
-
transcript.push({ name: null, text: 'Tema propuesto: ' + newTopic });
|
| 361 |
-
} else if (!topic) {
|
| 362 |
-
topic = 'Tema libre';
|
| 363 |
-
}
|
| 364 |
-
runDebate();
|
| 365 |
-
});
|
| 366 |
-
stopBtn.addEventListener('click', () => { stopRequested = true; setStatus('Deteniendo\u2026'); });
|
| 367 |
-
|
| 368 |
-
// --- Settings ---
|
| 369 |
-
const settingsPanel = document.getElementById('settings');
|
| 370 |
-
document.getElementById('settings-btn').addEventListener('click', () => {
|
| 371 |
-
if (!settingsPanel.classList.contains('open')) {
|
| 372 |
-
document.getElementById('set-repo').value = CONFIG.repo;
|
| 373 |
-
document.getElementById('set-file').value = CONFIG.file;
|
| 374 |
-
document.getElementById('set-ctx').value = CONFIG.nCtx;
|
| 375 |
-
document.getElementById('set-maxtokens').value = CONFIG.maxTokens;
|
| 376 |
-
document.getElementById('set-temp').value = CONFIG.temperature;
|
| 377 |
-
document.getElementById('set-rounds').value = CONFIG.rounds;
|
| 378 |
-
document.getElementById('set-agents').value = JSON.stringify(agents, null, 2);
|
| 379 |
-
}
|
| 380 |
-
settingsPanel.classList.toggle('open');
|
| 381 |
-
});
|
| 382 |
-
document.getElementById('apply-settings').addEventListener('click', async () => {
|
| 383 |
-
try { agents = JSON.parse(document.getElementById('set-agents').value); }
|
| 384 |
-
catch (e) { alert('JSON de agentes inv\u00e1lido: ' + e.message); return; }
|
| 385 |
-
if (!Array.isArray(agents) || agents.length < 2) { alert('Se necesitan al menos 2 agentes.'); return; }
|
| 386 |
-
CONFIG.maxTokens = parseInt(document.getElementById('set-maxtokens').value) || CONFIG.maxTokens;
|
| 387 |
-
CONFIG.temperature = parseFloat(document.getElementById('set-temp').value) || CONFIG.temperature;
|
| 388 |
-
CONFIG.rounds = parseInt(document.getElementById('set-rounds').value) || CONFIG.rounds;
|
| 389 |
-
const newCtx = parseInt(document.getElementById('set-ctx').value) || CONFIG.nCtx;
|
| 390 |
-
const newRepo = document.getElementById('set-repo').value.trim();
|
| 391 |
-
const newFile = document.getElementById('set-file').value.trim();
|
| 392 |
-
const reload = newCtx !== CONFIG.nCtx || newRepo !== CONFIG.repo || newFile !== CONFIG.file;
|
| 393 |
-
CONFIG.nCtx = newCtx; CONFIG.repo = newRepo; CONFIG.file = newFile;
|
| 394 |
-
settingsPanel.classList.remove('open');
|
| 395 |
-
if (reload || !wllama) { transcript = []; chatEl.innerHTML = ''; await loadModel(CONFIG.repo, CONFIG.file); }
|
| 396 |
-
else setStatus(`Ajustes aplicados. Agentes: ${agents.map(a => a.name).join(', ')}.`);
|
| 397 |
-
});
|
| 398 |
-
|
| 399 |
-
if (CONFIG.autoload) loadModel(CONFIG.repo, CONFIG.file);
|
| 400 |
-
else setStatus('Modo manual: carga el modelo desde Ajustes.');
|
| 401 |
-
</script>
|
| 402 |
-
</body>
|
| 403 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|