From b90b0a6d149116ab9e0c38f2d465cdc068a18905 Mon Sep 17 00:00:00 2001 From: gramps Date: Mon, 13 Jul 2026 09:49:00 -0700 Subject: [PATCH] v0.17.17: timestamps on user messages, restore thumbs on AI (not web search), Shift+Enter triggers web search --- config.py | 2 +- templates/index.html | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/config.py b/config.py index abe364b..89e8086 100644 --- a/config.py +++ b/config.py @@ -9,7 +9,7 @@ import logging log = logging.getLogger("caic") -VERSION = "v0.17.16" +VERSION = "v0.17.17" OLLAMA_BASE = os.environ.get("OLLAMA_BASE", "http://localhost:11434") LLAMA_SERVER_BASE = os.environ.get("LLAMA_SERVER_BASE", "http://192.168.50.108:8081") SEARXNG_BASE = "http://localhost:8888" diff --git a/templates/index.html b/templates/index.html index 1e31e49..40d7a38 100644 --- a/templates/index.html +++ b/templates/index.html @@ -98,7 +98,7 @@ body { font-family: var(--font-body); background: var(--bg-primary); color: var( .badge.off { border-color:rgba(255,51,85,0.3); color:var(--danger); background:rgba(255,51,85,0.08); } .badge.admin { border-color:var(--border); color:var(--text-muted); } .badge.admin:hover { border-color:var(--accent-dim); color:var(--accent); } -.status-dot { width:6px; height:6px; border-radius:50%; background:var(--success); display:inline-block; flex-shrink:0; } +.role-label .msg-time { color:var(--text-muted); font-weight:400; font-size:10px; margin-left:6px; } .status-dot.offline { background:var(--danger); } .status-dot.warning { background:var(--warning); } @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.4} } @@ -409,7 +409,7 @@ body { font-family: var(--font-body); background: var(--bg-primary); color: var(
- +
@@ -1408,7 +1408,9 @@ function appendMessage(role, content, animate, isSearch = false, afterEl = null) const div = document.createElement('div'); div.className = 'message ' + role + (isSearch && role === 'assistant' ? ' search-result' : ''); if (!animate) div.style.animation = 'none'; - div.innerHTML = `
${role === 'user' ? 'YOU' : 'AI'}
${role}
${content ? renderMarkdown(content) : ''}
${role === 'assistant' ? '
' : ''}
`; + const now = new Date(); + const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + div.innerHTML = `
${role === 'user' ? 'YOU' : 'AI'}
${role}${role === 'user' ? ' ' + timeStr + '' : ''}
${content ? renderMarkdown(content) : ''}
${role === 'assistant' ? '
' : ''}
`; if (afterEl) { afterEl.parentNode.insertBefore(div, afterEl.nextSibling); } else { @@ -1499,6 +1501,26 @@ function addMessageToolbar(msgDiv) { URL.revokeObjectURL(a.href); }; toolbar.append(copyBtn, printBtn, saveBtn, sep()); + if (!msgDiv.classList.contains('search-result')) { + const rating = { value: 0 }; + const upBtn = document.createElement('button'); + upBtn.innerHTML = '👍'; + upBtn.title = 'Rate up'; + upBtn.onclick = () => { + rating.value = rating.value === 1 ? 0 : 1; + upBtn.classList.toggle('active', rating.value === 1); + dnBtn.classList.toggle('active', false); + }; + const dnBtn = document.createElement('button'); + dnBtn.innerHTML = '👎'; + dnBtn.title = 'Rate down'; + dnBtn.onclick = () => { + rating.value = rating.value === -1 ? 0 : -1; + dnBtn.classList.toggle('active', rating.value === -1); + upBtn.classList.toggle('active', false); + }; + toolbar.append(upBtn, dnBtn); + } function sep() { const s = document.createElement('span'); s.className = 'sep'; return s; } } @@ -1525,6 +1547,7 @@ let historyDraft = ''; userInput.addEventListener('input', function() { this.style.height = 'auto'; this.style.height = Math.min(this.scrollHeight, 200) + 'px'; }); userInput.addEventListener('keydown', e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); return; } + if (e.key === 'Enter' && e.shiftKey) { e.preventDefault(); sendSearch(); return; } if (e.key === 'ArrowUp') { e.preventDefault(); if (messageHistory.length === 0) return;