dsh: rename conversations, live model in header, swap to OmniRoute auto/* routes (opencode-go dropped - no creds/burn); direct deepseek routes dead

This commit is contained in:
2026-09-15 14:21:28 +10:00
parent 9d38d79abb
commit 882ffdb631
3 changed files with 58 additions and 15 deletions

View File

@@ -41,7 +41,7 @@
#sessions li.sel { background: var(--primary, #0075de); color: #fff; }
#sessions li .t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#sessions li .n { font-size: 11px; opacity: .7; }
#sessions li .del { background: none; border: none; cursor: pointer; color: inherit; opacity: .5; font-size: 13px; }
#sessions li .del, #sessions li .ren { background: none; border: none; cursor: pointer; color: inherit; opacity: .5; font-size: 13px; }
.chat-col { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.log { flex: 1; overflow: auto; }
.bubble { position: relative; white-space: pre-wrap; }
@@ -103,7 +103,7 @@
<button id="menuBtn" type="button" aria-label="Conversations" title="Conversations" style="display:none;align-items:center;justify-content:center;background:none;border:1px solid var(--hairline, #e6e6e6);border-radius:8px;padding:4px 9px;font-size:17px;cursor:pointer;line-height:1">☰</button>
<button id="themeBtn" type="button" title="Toggle dark mode" style="background:none;border:1px solid var(--hairline, #e6e6e6);border-radius:8px;padding:4px 8px;font-size:16px;cursor:pointer;color:var(--ink, #111)">🌙</button>
<div class="logo">DeepSeek Harness</div>
<div class="who" style="margin-left:auto">{{ DSH_SLOT }} · <span class="model">{{ DSH_MODEL }}</span></div>
<div class="who" style="margin-left:auto">{{ DSH_SLOT }} · <span class="model" id="whoModel">{{ DSH_MODEL }}</span></div>
</header>
<div class="app">
@@ -206,20 +206,39 @@
const n = document.createElement('span'); n.className = 'n'; n.textContent = s.count;
const d = document.createElement('button'); d.className = 'del'; d.textContent = '✕'; d.title = 'Delete';
d.addEventListener('click', (e) => { e.stopPropagation(); deleteSession(s.id); });
li.append(t, n, d);
const r = document.createElement('button'); r.className = 'ren'; r.textContent = '✎'; r.title = 'Rename';
r.addEventListener('click', (e) => { e.stopPropagation(); renameSession(s.id); });
li.append(t, n, r, d);
li.addEventListener('click', () => openSession(s.id));
listEl.appendChild(li);
});
}
function whoModel() {
const m = modelSel.value || '';
const label = [...modelSel.options].find(o => o.value === m);
const el = document.getElementById('whoModel');
if (el) el.textContent = label ? label.textContent : m;
}
async function renameSession(id) {
const s = await (await fetch('/api/sessions/' + id)).json();
const name = prompt('Rename conversation:', s.name || '');
if (name === null) return;
const fd = new URLSearchParams({ name });
const d = await (await fetch('/api/sessions/' + id + '/rename', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: fd })).json();
if (d.ok) loadSessions(); else alert('Rename failed: ' + (d.error || 'unknown'));
}
async function fetchModels() {
try {
const d = await (await fetch('/api/models')).json();
(d.current || []).forEach(m => {
const o = document.createElement('option'); o.value = m; o.textContent = (d.labels && d.labels[m]) || m;
if (m === d.default) o.selected = true;
if (m === (d.default || (d.current && d.current[0]))) o.selected = true;
modelSel.appendChild(o);
});
modelSel.addEventListener('change', () => { whoModel(); });
whoModel();
} catch (_) {}
}