1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8" /> 5 <title>Odysseus Chat</title> 6 <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M16 4L16 22L6 22Z' fill='%23e06c75'/%3E%3Cpath d='M16 8L16 22L24 22Z' fill='%23e06c75' opacity='0.6'/%3E%3Cpath d='M4 24Q10 20 16 24Q22 28 28 24' stroke='%23e06c75' stroke-width='2.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"> 7 <link rel="manifest" href="/static/manifest.json"> 8 <meta name="theme-color" content="#282c34"> 9 <meta name="apple-mobile-web-app-capable" content="yes"> 10 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> 11 <!-- Disable iOS / Android auto-linkifying of numbers (phone/date/address) 12 in email bodies â was wrapping random digits in <a href="tel:..."> with 13 browser-default styling that didn't match the Odysseus theme. --> 14 <meta name="format-detection" content="telephone=no, date=no, address=no, email=no"> 15 <link rel="apple-touch-icon" href="/static/icon-192.png"> 16
16<script nonce="0ef1c0e2ced0cc537d6ee0258e679162"> 17 window._odysseusLoadTime = Date.now(); 18 (function(){ 19 try { 20 var t = JSON.parse(localStorage.getItem('odysseus-theme')); 21 if (t && t.colors) { 22 var s = document.documentElement.style; 23 var c = t.colors; 24 s.setProperty('--bg', c.bg); 25 s.setProperty('--fg', c.fg); 26 s.setProperty('--panel', c.panel); 27 s.setProperty('--border', c.border); 28 if (c.red) s.setProperty('--red', c.red); 29 // Set --brand-color now (= custom brand or the theme red) so the 30 // loading-screen ASCII wave shows its final colour from the first 31 // paint. Otherwise it starts on --red and visibly switches once the 32 // app boots and applyColors() fills --brand-color. 33 var _bc = (c.advanced && c.advanced.brandColor) || c.red; 34 if (_bc) s.setProperty('--brand-color', _bc); 35 // Match the mobile browser toolbar / status bar to the saved theme bg 36 // from the very first paint. Otherwise the hardcoded dark meta sits 37 // there during load and the bar "switches" colour once the app boots. 38 var mtc = document.querySelector('meta[name="theme-color"]'); 39 if (mtc && c.bg) mtc.setAttribute('content', c.bg); 40 // Update favicon to match accent color 41 var ac = c.red || '#e06c75'; 42 var fav = document.querySelector("link[rel='icon']"); 43 if (fav) fav.href = 'data:image/svg+xml,' + encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><path d='M16 4L16 22L6 22Z' fill='" + ac + "'/><path d='M16 8L16 22L24 22Z' fill='" + ac + "' opacity='0.6'/><path d='M4 24Q10 20 16 24Q22 28 28 24' stroke='" + ac + "' stroke-width='2.5' fill='none' stroke-linecap='round'/></svg>"); 44 // Derive syntax highlighting colors from theme 45 function h2hsl(hex) { 46 hex = hex.replace('#',''); 47 var r=parseInt(hex.substring(0,2),16)/255, g=parseInt(hex.substring(2,4),16)/255, b=parseInt(hex.substring(4,6),16)/255; 48 var mx=Math.max(r,g,b), mn=Math.min(r,g,b), h, sv, l=(mx+mn)/2; 49 if(mx===mn){h=sv=0}else{var d=mx-mn;sv=l>0.5?d/(2-mx-mn):d/(mx+mn);if(mx===r)h=((g-b)/d+(g<b?6:0))/6;else if(mx===g)h=((b-r)/d+2)/6;else h=((r-g)/d+4)/6} 50 return[h*360,sv*100,l*100]; 51 } 52 function hsl2h(h,sv,l) { 53 h=((h%360)+360)%360;sv=Math.max(0,Math.min(100,sv))/100;l=Math.max(0,Math.min(100,l))/100; 54 var a=sv*Math.min(l,1-l);function f(n){var k=(n+h/30)%12;return l-a*Math.max(-1,Math.min(k-3,9-k,1))} 55 function th(v){return Math.round(v*255).toString(16).padStart(2,'0')} 56 return'#'+th(f(0))+th(f(8))+th(f(4)); 57 } 58 var fH=h2hsl(c.fg),bH=h2hsl(c.bg),rH=h2hsl(c.red||'#e06c75'); 59 var dk=bH[2]<50; 60 s.setProperty('--hl-bg', hsl2h(bH[0],bH[1],dk?Math.max(bH[2]-4,0):Math.min(bH[2]+4,100))); 61 s.setProperty('--hl-fg', c.fg); 62 s.setProperty('--hl-keyword', hsl2h((rH[0]+280)%360,Math.min(rH[1]+10,80),dk?70:45)); 63 s.setProperty('--hl-string', hsl2h(40,Math.min(fH[1]+20,70),dk?72:42)); 64 s.setProperty('--hl-comment', hsl2h(fH[0],Math.max(fH[1]-20,5),(fH[2]*0.5+bH[2]*0.5))); 65 s.setProperty('--hl-function', hsl2h(210,Math.min(fH[1]+20,75),dk?70:45)); 66 s.setProperty('--hl-number', hsl2h(20,Math.min(fH[1]+15,65),dk?68:48)); 67 s.setProperty('--hl-builtin', hsl2h(180,Math.min(fH[1]+15,60),dk?65:40)); 68 s.setProperty('--hl-variable', hsl2h((fH[0]+30)%360,Math.min(fH[1]+5,60),fH[2])); 69 s.setProperty('--hl-params', hsl2h(fH[0],Math.max(fH[1]-5,10),dk?Math.min(fH[2]+8,85):Math.max(fH[2]-8,25))); 70 // Apply advanced overrides if present 71 if (c.advanced) { 72 var a = c.advanced; 73 var advMap = {userBubbleBg:'--user-bubble-bg',aiBubbleBg:'--ai-bubble-bg',bubbleBorder:'--bubble-border',sidebarBg:'--sidebar-bg',sectionAccent:'--section-accent',brandColor:'--brand-color',inputBg:'--input-bg',inputBorder:'--input-border',sendBtnBg:'--send-btn-bg',sendBtnHover:'--send-btn-hover',codeBg:'--code-bg',codeFg:'--code-fg',toggleBg:'--toggle-bg',toggleActive:'--toggle-active',accentPrimary:'--accent-primary',accentError:'--accent-error'}; 74 for (var k in advMap) { if (a[k]) s.setProperty(advMap[k], a[k]); } 75 } 76 } 77 // Apply font early 78 if (t && t.font) { 79 var fm = {mono:"'Fira Code', monospace",sans:"system-ui, -apple-system, 'Segoe UI', sans-serif",serif:"Georgia, 'Times New Roman', serif"}; 80 if (fm[t.font]) { s.setProperty('--font-family', fm[t.font]); } 81 else { s.setProperty('--font-family', "'" + t.font.replace(/'/g,'') + "', sans-serif"); } 82 } 83 // Apply density class on html 84 if (t && t.density && t.density !== 'comfortable') { 85 document.documentElement.classList.add('density-' + t.density); 86 } 87 // Apply background pattern on body once available 88 if (t && t.bgPattern && t.bgPattern !== 'none') { 89 document.addEventListener('DOMContentLoaded', function() { 90 document.body.classList.add('bg-pattern-' + t.bgPattern); 91 }, {once:true}); 92 } 93 } catch(e){} 94 })(); 95 </script>
95 96 <!-- Per-route favicon. Bookmarking /calendar shows a calendar icon, 97 /notes a notes icon, etc. Each shape is rendered in the current 98 theme accent color. Falls back to the boat logo on the root path. --> 99
99<script nonce="0ef1c0e2ced0cc537d6ee0258e679162"> 100 (function(){ 101 try { 102 var path = (window.location.pathname || '').toLowerCase(); 103 var theme = (function(){ try { return JSON.parse(localStorage.getItem('odysseus-theme')); } catch(_) { return null; } })(); 104 var ac = (theme && (theme.red || theme.colors && theme.colors.red)) || '#e06c75'; 105 // Shapes are line-stroke SVGs (no emoji glyphs). Each entry returns 106 // the inner SVG markup rendered against currentColor=`ac`. 107 var SHAPES = { 108 '/calendar': 109 "<rect x='4' y='6' width='24' height='22' rx='2' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 110 "<line x1='4' y1='12' x2='28' y2='12' stroke='" + ac + "' stroke-width='2.5'/>" + 111 "<line x1='10' y1='3' x2='10' y2='9' stroke='" + ac + "' stroke-width='2.5' stroke-linecap='round'/>" + 112 "<line x1='22' y1='3' x2='22' y2='9' stroke='" + ac + "' stroke-width='2.5' stroke-linecap='round'/>", 113 '/notes': 114 "<rect x='6' y='4' width='20' height='24' rx='2' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 115 "<line x1='10' y1='10' x2='22' y2='10' stroke='" + ac + "' stroke-width='2'/>" + 116 "<line x1='10' y1='15' x2='22' y2='15' stroke='" + ac + "' stroke-width='2'/>" + 117 "<line x1='10' y1='20' x2='18' y2='20' stroke='" + ac + "' stroke-width='2'/>", 118 '/cookbook': 119 "<path d='M5 8 L5 26 A2 2 0 0 0 7 28 L25 28 A2 2 0 0 0 27 26 L27 8' fill='none' stroke='" + ac + "' stroke-width='2.5' stroke-linejoin='round'/>" + 120 "<path d='M9 4 L23 4 L23 8 L9 8 Z' fill='none' stroke='" + ac + "' stroke-width='2.5' stroke-linejoin='round'/>" + 121 "<line x1='11' y1='14' x2='21' y2='14' stroke='" + ac + "' stroke-width='2'/>" + 122 "<line x1='11' y1='19' x2='17' y2='19' stroke='" + ac + "' stroke-width='2'/>", 123 '/email': 124 "<rect x='4' y='7' width='24' height='18' rx='2' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 125 "<path d='M5 9 L16 17 L27 9' fill='none' stroke='" + ac + "' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'/>", 126 '/memory': 127 "<path d='M16 5 C10 5 6 9 6 14 C6 19 10 21 11 22 L11 26 L21 26 L21 22 C22 21 26 19 26 14 C26 9 22 5 16 5 Z' fill='none' stroke='" + ac + "' stroke-width='2.5' stroke-linejoin='round'/>" + 128 "<line x1='12' y1='28' x2='20' y2='28' stroke='" + ac + "' stroke-width='2'/>", 129 '/gallery': 130 "<rect x='4' y='4' width='24' height='24' rx='2' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 131 "<circle cx='12' cy='12' r='2.5' fill='" + ac + "'/>" + 132 "<path d='M4 22 L11 16 L18 21 L23 17 L28 22' fill='none' stroke='" + ac + "' stroke-width='2.5' stroke-linejoin='round'/>", 133 '/tasks': 134 "<rect x='4' y='4' width='24' height='24' rx='3' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 135 "<path d='M9 16 L14 21 L23 11' fill='none' stroke='" + ac + "' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'/>", 136 '/library': 137 "<rect x='5' y='5' width='5' height='22' rx='1' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 138 "<rect x='13' y='5' width='5' height='22' rx='1' fill='none' stroke='" + ac + "' stroke-width='2.5'/>" + 139 "<rect x='21' y='8' width='6' height='19' rx='1' fill='none' stroke='" + ac + "' stroke-width='2.5' transform='rotate(8 24 17)'/>", 140 }; 141 var inner = SHAPES[path]; 142 if (!inner) return; // Root path keeps the default boat icon. 143 var svg = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>" + inner + "</svg>"; 144 var href = 'data:image/svg+xml,' + encodeURIComponent(svg); 145 var fav = document.querySelector("link[rel='icon']"); 146 if (!fav) { fav = document.createElement('link'); fav.rel = 'icon'; fav.type = 'image/svg+xml'; document.head.appendChild(fav); } 147 fav.href = href; 148 var apple = document.querySelector("link[rel='apple-touch-icon']"); 149 if (!apple) { apple = document.createElement('link'); apple.rel = 'apple-touch-icon'; document.head.appendChild(apple); } 150 apple.href = href; 151 // Also customize the page title so the bookmark inherits a useful name. 152 var titles = { 153 '/calendar': 'Calendar â Odysseus', 154 '/notes': 'Notes â Odysseus', 155 '/cookbook': 'Cookbook â Odysseus', 156 '/email': 'Email â Odysseus', 157 '/memory': 'Memory â Odysseus', 158 '/gallery': 'Gallery â Odysseus', 159 '/tasks': 'Tasks â Odysseus', 160 '/library': 'Library â Odysseus', 161 }; 162 if (titles[path]) document.title = titles[path]; 163 // Per-route Android home-screen icon. We swap the <link rel="manifest"> 164 // to a per-page Blob URL with this route's SVG icon â that way "Add to 165 // Home Screen" picks up the route-specific glyph instead of the shared 166 // boat logo. Falls back silently on browsers without Blob URL support.
167 try { 168 if (inner && typeof Blob !== 'undefined') { 169 var pwa = { 170 name: (titles[path] || 'Odysseus'), 171 short_name: (titles[path] || 'Odysseus').split('â')[0].trim(), 172 start_url: path, 173 scope: '/', 174 display: 'standalone', 175 background_color: '#0e0e10', 176 theme_color: ac, 177 icons: [ 178 { src: href, sizes: '192x192', type: 'image/svg+xml', purpose: 'any maskable' }, 179 { src: href, sizes: '512x512', type: 'image/svg+xml', purpose: 'any maskable' }, 180 ], 181 }; 182 var blob = new Blob([JSON.stringify(pwa)], { type: 'application/manifest+json' }); 183 var url = URL.createObjectURL(blob); 184 var ml = document.querySelector("link[rel='manifest']"); 185 if (!ml) { ml = document.createElement('link'); ml.rel = 'manifest'; document.head.appendChild(ml); } 186 ml.href = url; 187 } 188 } catch(_) {} 189 } catch(e){} 190 })(); 191 </script>
191 192
192<script defer src="/static/lib/highlight.min.js"></script>
192 193 <!-- Inter font â self-hosted, no Google dependencies --> 194 <style> 195 @font-face { font-family: 'Inter'; font-weight: 400; font-style: normal; font-display: swap; src: url('/static/fonts/Inter-Regular.woff2') format('woff2'); } 196 @font-face { font-family: 'Inter'; font-weight: 500; font-style: normal; font-display: swap; src: url('/static/fonts/Inter-Medium.woff2') format('woff2'); } 197 @font-face { font-family: 'Inter'; font-weight: 600; font-style: normal; font-display: swap; src: url('/static/fonts/Inter-SemiBold.woff2') format('woff2'); } 198 </style> 199 <!-- KaTeX CSS is loaded with media="print" so it doesn't block render, 200 then flipped to "all" via JS after load. Mermaid init runs once the 201 library finishes loading. Both hooks are wired via addEventListener 202 below (inline onload= attrs are blocked by CSP script-src-attr). --> 203 <link id="katex-css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" media="print"> 204
204<script async src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js"></script>
204 205
205<script id="mermaid-script" async src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
205 206
206<script nonce="0ef1c0e2ced0cc537d6ee0258e679162"> 207 (function(){ 208 var k = document.getElementById('katex-css'); 209 if (k) k.addEventListener('load', function(){ k.media = 'all'; }, { once: true }); 210 var m = document.getElementById('mermaid-script'); 211 if (m) m.addEventListener('load', function(){ 212 if (window.odysseusInitMermaid) window.odysseusInitMermaid(); 213 }, { once: true }); 214 })(); 215 </script>
215 216 <link rel="stylesheet" href="/static/style.css"> 217 <link rel="modulepreload" href="/static/app.js"> 218 <link rel="modulepreload" href="/static/js/chat.js"> 219 <link rel="modulepreload" href="/static/js/ui.js"> 220 <link rel="modulepreload" href="/static/js/sessions.js"> 221 <link rel="modulepreload" href="/static/js/markdown.js"> 222 <meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content, viewport-fit=cover" /> 223</head> 224<body> 225 <!-- Loading overlay â minimal flash then immediate dismiss --> 226 <div id="app-loader" style="position:fixed;inset:0;z-index:99999;background:var(--bg,#282c34);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:8px;transition:opacity .15s;pointer-events:none"> 227 </div> 228
228<script nonce="0ef1c0e2ced0cc537d6ee0258e679162"> 229 (function(){ 230 // Dismiss loader almost immediately â no animation needed 231 var l=document.getElementById('app-loader'); 232 if(l){l.style.opacity='0';setTimeout(function(){l.remove()},150)} 233 })(); 234 </script>
234 235 <!-- Memory Management Modal --> 236 <div id="memory-modal" class="modal hidden"> 237 <div class="modal-content memory-modal-content" role="dialog" aria-label="Brain" style="background:var(--bg)"> 238 <div class="modal-header"> 239 <h4><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/></svg>Brain</h4> 240 <button class="close-btn" id="close-memory-modal" aria-label="Close memory modal">â</button> 241 </div> 242 <div class="modal-body memory-modal-body"> 243 <div class="memory-tabs"> 244 <button class="memory-tab active" data-memory-tab="browse"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px"><path d="M12 2a7 7 0 0 1 7 7c0 2.4-1.2 4.5-3 5.7V17a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2.3C6.2 13.5 5 11.4 5 9a7 7 0 0 1 7-7z"/><line x1="10" y1="22" x2="14" y2="22"/></svg>Memories <span id="memory-count" class="memory-count" style="font-size:0.8em;opacity:0.6;font-weight:normal;margin-left:4px">0</span></button> 245 <button class="memory-tab" data-memory-tab="skills"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>Skills <span id="skills-count" class="memory-count" style="font-size:0.8em;opacity:0.6;font-weight:normal;margin-left:4px">0</span></button> 246 <button class="memory-tab" data-memory-tab="add"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>Add</button> 247 <button class="memory-tab" data-memory-tab="settings"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>Settings</button> 248 </div> 249 <!-- ââ Browse tab ââ --> 250 <div class="memory-tab-panel" data-memory-panel="browse"> 251 <div class="admin-card" style="display:flex;flex-direction:column;overflow:hidden;flex:1;min-height:0;"> 252 <div style="display:flex;align-items:center;gap:8px;margin-bottom:2px;"> 253 <h2 style="display:flex;align-items:center;gap:6px;margin:0;padding:0;line-height:1;">Memories <span id="memory-count-h2" class="memory-count" style="font-size:0.6em;opacity:0.6;font-weight:normal"></span></h2> 254 <span style="flex:1"></span> 255 <label class="admin-switch" title="Include memories in chat context"><input type="checkbox" id="memory-enabled-header-toggle" checked /><span class="admin-slider"></span></label> 256 </div> 257 <p class="memory-desc doclib-desc" style="margin-top:6px;">Long-term facts the AI remembers across chats â recall, edit, or curate.</p> 258 <div class="memory-toolbar"> 259 <div class="memory-toolbar-row"> 260 <select id="memory-sort" class="memory-sort-select" aria-label="Sort memories"> 261 <option value="newest">Newest</option> 262 <option value="oldest">
262Oldest</option> 263 <option value="alpha">A-Z</option> 264 <option value="uses">Most used</option> 265 </select> 266 <button id="memory-select-btn" class="memory-toolbar-btn" title="Select multiple memories">Select</button> 267 <button id="memory-tidy-btn" class="memory-toolbar-btn" title="AI tidy: deduplicate and clean up memories"><svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-1px;margin-right:2px;"><path d="M12 0L14.59 8.41L23 12L14.59 15.59L12 24L9.41 15.59L1 12L9.41 8.41Z"/></svg> Tidy</button> 268 </div> 269 <input type="text" id="memory-search" placeholder="Search memoriesâ¦" class="memory-search-input" aria-label="Search memories" /> 270 <div id="memory-category-filters" class="memory-category-filters"> 271 <button class="memory-cat-chip active" data-cat="all">all</button> 272 </div> 273 </div> 274 <div id="memory-bulk-bar" class="memory-bulk-bar hidden"> 275 <label class="memory-bulk-check-all" style="position:relative;top:0px;"><input type="checkbox" id="memory-select-all" /> All</label> 276 <span id="memory-selected-count">0 Selected</span> 277 <button id="memory-bulk-delete" class="memory-toolbar-btn danger" disabled>
277<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:3px;"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>Delete</button> 278 <button id="memory-bulk-cancel" class="memory-toolbar-btn" title="Cancel (Esc)" style="margin-left:4px;padding:3px 6px;"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button> 279 </div> 280 <div id="memory-list" class="memory-list"></div> 281 <div id="memory-suggestions-body" class="memory-suggestions hidden"></div> 282 </div> 283 </div> 284 <!-- ââ Add tab ââ --> 285 <div class="memory-tab-panel hidden" data-memory-panel="add"> 286 <div class="admin-card"> 287 <div style="display:flex;align-items:center;gap:8px;margin-bottom:2px;"> 288 <h2 style="margin:0;padding:0;line-height:1;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><path d="M12 2a7 7 0 0 1 7 7c0 2.4-1.2 4.5-3 5.7V17a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2.3C6.2 13.5 5 11.4 5 9a7 7 0 0 1 7-7z"/><line x1="10" y1="22" x2="14" y2="22"/></svg>Add Memory</h2> 289 <span style="flex:1"></span> 290 <button id="memory-import-btn" class="theme-io-btn" title="Import memories from a file" style="height:26px;font-size:12px;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px;"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Import</button> 291 <button id="memory-export-btn" class="theme-io-btn" title="Export all memories as JSON" style="height:26px;font-size:12px;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px;"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Export</button> 292 <input type="file" id="memory-import-file" accept=".txt,.md,.pdf,.csv,.log,.json,.py,.js,.html" hidden /> 293 </div> 294 <p class="memory-desc doclib-desc" style="margin:4px 0 6px;"> 295 Import a <code>.txt</code>, <code>.md</code>, <code>.pdf</code>, <code>.csv</code>, <code>.log</code>, <code>.json</code>, <code>.py</code>, <code>.js</code>, or <code>.html</code> file — the AI reads it and suggests candidate memories you can approve. 296 </p> 297 <div class="memory-add-row" style="margin-top:8px;"> 298 <div class="skill-ph-wrap" style="flex:1;min-width:0;"> 299 <input type="text" id="new-memory-input" placeholder=" " class="memory-add-input skill-hint-input" aria-label="New memory text" /> 300 <span class="skill-rich-ph"><span class="k">Add a memory</span> — e.g. 'I prefer concise replies' <svg class="k" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-left:4px;" aria-hidden="true"><polyline points="9 10 4 15 9 20"/><path d="M20 4v7a4 4 0 0 1-4 4H4"/></svg></span> 301 </div> 302 <select id="new-memory-category" class="memory-edit-cat-select" aria-label="Memory category"></select> 303 </div> 304 </div> 305 <div class="admin-card"> 306 <div style="display:flex;align-items:baseline;gap:8px;margin-bottom:2px;"> 307 <h2 style="margin:0;padding:0;line-height:1;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>Add Skill</h2> 308 </div> 309 <p class="memory-desc doclib-desc" style="margin-top:6px;">Import a skill from GitHub or <a href="https://skills.sh" target="_blank" rel="noopener noreferrer">skills.sh</a> (folder with <code>SKILL.md</code> and optional templates).</p> 310 <div class="memory-add-row" style="margin-top:6px;margin-bottom:10px;"> 311 <div class="skill-ph-wrap" style="flex:1;min-width:0;"> 312 <input type="url" id="skill-import-url" placeholder=" " class="memory-add-input skill-hint-input" aria-label="Skill import URL" />
313 <span class="skill-rich-ph"><span class="k">Import URL</span> â e.g. GitHub tree link to a skill folder</span> 314 </div> 315 <button type="button" id="skill-import-url-btn" class="theme-io-btn" title="Import skill from URL" style="flex:none;height:28px;font-size:12px;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px;" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Import</button> 316 </div> 317 <p class="memory-desc doclib-desc" style="margin-top:0;">Or create a skill by hand â title, what it solves, and an approach.</p> 318 <div class="skill-ph-wrap" style="margin-top:4px;margin-bottom:6px;"> 319 <input type="text" id="new-skill-title" placeholder=" " class="memory-add-input skill-hint-input" aria-label="Skill title" /> 320 <span class="skill-rich-ph"><span class="k">Title</span> â short name, e.g. âbuild-vllm-wheelâ</span> 321 </div> 322 <div class="skill-ph-wrap" style="margin-bottom:6px;"> 323 <input type="text" id="new-skill-problem" placeholder=" " class="memory-add-input skill-hint-input" aria-label="When to use this skill" /> 324 <span class="skill-rich-ph"><span class="k">When to use</span> â what problem does this skill solve?</span> 325 </div> 326 <div class="skill-ph-wrap" style="margin-bottom:6px;"> 327 <textarea id="new-skill-solution" placeholder=" " class="memory-add-input skill-hint-input" rows="2" style="resize:vertical;" aria-label="How â the approach or steps"></textarea> 328 <span class="skill-rich-ph skill-rich-ph-top"><span class="k">How</span> â the approach, steps, commands, or rules to follow</span> 329 </div> 330 <div class="skill-ph-wrap" style="margin-bottom:8px;"> 331 <input type="text" id="new-skill-tags" placeholder=" " class="memory-add-input skill-hint-input" aria-label="Tags" /> 332 <span class="skill-rich-ph"><span class="k">Tags</span> â comma-separated, e.g. python, build, vllm</span> 333 </div> 334 <div style="display:flex;justify-content:flex-end;"> 335 <button id="add-skill-btn" class="confirm-btn confirm-btn-primary">Add Skill</button> 336 </div> 337 </div> 338 </div> 339 <!-- ââ Skills tab ââ --> 340 <div class="memory-tab-panel hidden" data-memory-panel="skills"> 341 <div class="admin-card" style="display:flex;flex-direction:column;overflow:hidden;flex:1;min-height:0;"> 342 <div style="display:flex;align-items:center;gap:8px;margin-bottom:2px;"> 343 <h2 style="margin:0;padding:0;line-height:1;">Skills <span id="skills-count-h2" class="memory-count" style="font-size:0.6em;opacity:0.6;font-weight:normal"></span></h2> 344 <span style="flex:1"></span> 345 <label class="admin-switch" title="Inject relevant skills into chat context"><input type="checkbox" id="skills-enabled-header-toggle" checked /><span class="admin-slider"></span></label> 346 </div> 347 <p class="memory-desc doclib-desc" style="margin-top:6px;">Reusable procedures the AI can call via /skill â sort by confidence to surface the proven ones.</p> 348 <div class="memory-toolbar"> 349 <div class="memory-toolbar-row"> 350 <select id="skills-sort" class="memory-sort-select"> 351 <optgroup label="Sort"> 352 <option value="sort:confidence">Confidence</option> 353 <option value="sort:uses">Most used</option> 354 <option value="sort:alpha">A-Z</option> 355 <option value="sort:recent">Recent</option> 356 </optgroup> 357 <optgroup label="Filter"> 358 <option value="filter:all">All skills</option> 359 <option value="filter:drafts">Drafts only</option> 360 <option value="filter:published">Published only</option> 361 <option value="filter:conf95">Confidence ⤠95%</option> 362 <option value="filter:conf90">Confidence ⤠90%</option> 363 <option value="filter:conf85">Confidence ⤠85%</option> 364 <option value="filter:conf80">Confidence ⤠80%</option> 365 <option value="filter:conf75">Confidence ⤠75%</option> 366 <option value="filter:conf70">Confidence ⤠70%</option> 367 </optgroup> 368 </select> 369 <button id="skills-select-btn" class="memory-toolbar-btn" title="Select multiple skills">Select</button> 370 <button id="skills-audit-btn" class="memory-toolbar-btn" title="Test every skill, auto-fix the weak ones, flag what still fails">
370<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-1px;margin-right:3px;"><path d="M12 0L14.59 8.41L23 12L14.59 15.59L12 24L9.41 15.59L1 12L9.41 8.41Z"/></svg>Audit all</button> 371 </div> 372 <input type="text" id="skills-search" placeholder="Search skillsâ¦" class="memory-search-input" aria-label="Search skills" /> 373 </div> 374 <div id="skills-audit-panel" class="skills-audit-panel hidden"></div> 375 <div id="skills-bulk-bar" class="memory-bulk-bar hidden"> 376 <label class="memory-bulk-check-all" style="position:relative;top:0px;"><input type="checkbox" id="skills-select-all" /> All</label> 377 <span id="skills-selected-count">0 Selected</span> 378 <button id="skills-bulk-publish" class="memory-toolbar-btn" disabled title="Publish selected drafts" style="margin-left:auto;"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:3px;"><polyline points="20 6 9 17 4 12"/></svg>Approve</button> 379 <button id="skills-bulk-audit" class="memory-toolbar-btn" disabled title="Audit selected draft skills">
379<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:3px;"><polygon points="5 3 19 12 5 21 5 3"/></svg>Audit</button> 380 <button id="skills-bulk-delete-nonpassing" class="memory-toolbar-btn danger" disabled title="Delete selected duplicates, generic/irrelevant skills, failed audits, and skills below threshold"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:3px;"><path d="M3 6h18"/><path d="M8 6V4h8v2"/><path d="M19 6l-1 14H6L5 6"/><path d="M10 11l4 4"/><path d="M14 11l-4 4"/></svg>Delete non passing</button> 381 <button id="skills-bulk-delete" class="memory-toolbar-btn danger" disabled><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:3px;"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>Delete</button> 382 <button id="skills-bulk-cancel" class="memory-toolbar-btn" title="Cancel (Esc)" style="padding:3px 6px;">
382<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button> 383 </div> 384 <div id="skills-list" class="memory-list"></div> 385 </div> 386 </div> 387 <!-- ââ Settings tab ââ --> 388 <div class="memory-tab-panel hidden" data-memory-panel="settings"> 389 <div class="admin-card"> 390 <div style="display:flex;align-items:center;justify-content:space-between;gap:12px"> 391 <h2 style="margin:0">Auto-extract memories</h2> 392 <label class="admin-switch" style="flex-shrink:0"><input type="checkbox" id="auto-memory-toggle" checked /><span class="admin-slider"></span></label> 393 </div> 394 <span class="admin-toggle-sub" style="display:block;margin-top:6px">Automatically extract memories from conversations.</span> 395 </div> 396 <div class="admin-card"> 397 <div style="display:flex;align-items:center;justify-content:space-between;gap:12px"> 398 <h2 style="margin:0">Auto-extract skills</h2> 399 <label class="admin-switch" style="flex-shrink:0"><input type="checkbox" id="auto-skills-toggle" /><span class="admin-slider"></span></label> 400 </div> 401 <span class="admin-toggle-sub" style="display:block;margin-top:6px;opacity:0.6">Automatically draft reusable skills from your workflows. Audit all can publish passing skills using the threshold below.</span> 402 <span class="admin-toggle-sub" style="display:block;margin-top:6px;opacity:0.6">The library can grow; cleanup retires weak/duplicate skills only after review.</span> 403 </div> 404 <div class="admin-card"> 405 <div style="display:flex;align-items:center;justify-content:space-between;gap:12px"> 406 <h2 style="margin:0">Inject Skills</h2> 407 </div> 408 <span class="admin-toggle-sub" style="display:block;margin-top:6px;opacity:0.6">Controls how many relevant published or approved skills are added to each agent request.</span> 409 <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:8px"> 410 <span class="admin-toggle-sub" style="margin:0">Max skills per request</span> 411 <input type="number" id="skill-max-input" min="0" max="12" step="1" value="3" aria-label="Max skills to inject" style="flex-shrink:0;width:72px;background:var(--input-bg,var(--panel));color:var(--fg);border:1px solid var(--border);border-radius:6px;padding:4px 6px;font-size:12px;text-align:right;font-variant-numeric:tabular-nums" /> 412 </div> 413 <span class="admin-toggle-sub" style="display:block;margin-top:6px;opacity:0.5">Set to 0 to disable skill injection.</span> 414 </div> 415 <div class="admin-card"> 416 <div style="display:flex;align-items:center;justify-content:space-between;gap:12px"> 417 <h2 style="margin:0">Auto-approve skills</h2> 418 <label class="admin-switch" style="flex-shrink:0"><input type="checkbox" id="auto-approve-skills-toggle" checked /><span class="admin-slider"></span></label> 419 </div> 420 <span class="admin-toggle-sub" style="display:block;margin-top:6px;opacity:0.6">Audit all publishes passing, necessary skills at or above this confidence. Off = keep audit results as drafts unless manually approved.</span> 421 <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:6px"> 422 <span class="admin-toggle-sub" style="margin:0">Minimum confidence</span> 423 <span style="display:flex;align-items:center;gap:8px;flex-shrink:0"> 424 <span id="skill-confidence-label" class="admin-toggle-sub" style="margin:0;min-width:42px;text-align:right;font-variant-numeric:tabular-nums">≥ 85%</span> 425 <input type="range" id="skill-confidence-slider" class="preset-range" min="50" max="100" step="5" value="85" style="width:120px;margin:0" /> 426 </span> 427 </div> 428 </div> 429 </div> 430 </div> 431 </div> 432 </div> 433 434 <!-- Theme Popup (floating panel) --> 435 <div id="theme-modal" class="modal hidden">
436 <div id="theme-popup" class="modal-content admin-modal-content" role="dialog" aria-label="Theme" style="background:var(--bg)"> 437 <div class="modal-header theme-popup-header" id="theme-popup-header"> 438 <h4><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><circle cx="12" cy="12" r="10"/><path d="M12 2a7 7 0 0 0 0 20 4 4 0 0 1 0-8 4 4 0 0 0 0-8"/><circle cx="8" cy="9" r="1.5" fill="currentColor"/><circle cx="15" cy="14" r="1.5" fill="currentColor"/><circle cx="9" cy="15" r="1.5" fill="currentColor"/></svg>Theme</h4> 439 <button type="button" class="theme-opacity-wrap theme-opacity-toggle hidden" id="theme-opacity-wrap" title="Fade this window to preview the page behind it" aria-pressed="false"> 440 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg> 441 <span class="theme-opacity-label">Peek</span> 442 </button> 443 <button class="close-btn" id="close-theme-popup" aria-label="Close theme">✖</button> 444 </div> 445 <!-- Theme tabs --> 446 <div class="admin-tabs" id="theme-tabs"> 447 <button class="admin-tab active" data-tab="theme-tab-browse"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px"><circle cx="12" cy="12" r="10"/><path d="M12 2a7 7 0 0 0 0 20 4 4 0 0 1 0-8 4 4 0 0 0 0-8"/><circle cx="8" cy="9" r="1.4" fill="currentColor"/><circle cx="15" cy="14" r="1.4" fill="currentColor"/><circle cx="9" cy="15" r="1.4" fill="currentColor"/></svg>Themes</button> 448 <button class="admin-tab" data-tab="theme-tab-customize"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px"><path d="M9.06 11.9l-3.5 3.5a2.85 2.85 0 1 0 4.03 4.03l8.49-8.49a4.5 4.5 0 1 0-6.36-6.36L3.18 12.62"/><path d="M14 7l3 3"/></svg>Customize</button> 449 </div> 450 451 <!-- Tab: Browse themes --> 452 <div id="theme-tab-browse" class="theme-tab-panel"> 453 <div class="admin-card"> 454 <h2>Default Themes</h2> 455 <div class="theme-grid" id="themeGrid"></div> 456 </div> 457 <div class="admin-card" id="themeUserCard" style="display:none"> 458 <h2>Your Themes</h2> 459 <div class="theme-grid" id="themeUserGrid"></div> 460 </div> 461 </div> 462 463 <!-- Tab: Customize --> 464 <div id="theme-tab-customize" class="theme-tab-panel" style="display:none"> 465 <div class="admin-card"> 466 <h2>Colors</h2> 467 <div class="theme-custom" id="themeCustom"> 468 <div class="color-row"><label>Background</label><input type="color" id="clr-bg"><button class="color-reset-btn" data-reset="bg" title="Reset this color" aria-label="Reset color">↺</button></div> 469 <div class="color-row"><label>Text</label><input type="color" id="clr-fg"><button class="color-reset-btn" data-reset="fg" title="Reset this color" aria-label="Reset color">↺</button></div> 470 <div class="color-row"><label>Panel</label><input type="color" id="clr-panel"><button class="color-reset-btn" data-reset="panel" title="Reset this color" aria-label="Reset color">↺</button></div> 471 <div class="color-row"><label>Sidebar</label><input type="color" id="adv-sidebarBg"><button class="color-reset-btn" data-reset-adv="sidebarBg" title="Reset this color" aria-label="Reset color">↺</button></div> 472 <div class="color-row"><label>Border</label><input type="color" id="clr-border"><button class="color-reset-btn" data-reset="border" title="Reset this color" aria-label="Reset color">↺</button></div> 473 <div class="color-row"><label>Accent</label><input type="color" id="clr-red"><button class="color-reset-btn" data-reset="red" title="Reset this color" aria-label="Reset color">↺</button></div> 474 </div> 475 </div> 476 <div class="theme-adv-toggle" id="theme-adv-toggle">
477 <span class="theme-adv-arrow">▶</span> More Colors 478 </div> 479 <div class="theme-adv-section hidden" id="themeAdvanced"> 480 <div class="theme-adv-group"> 481 <div class="theme-adv-group-label">Chat Bubbles</div> 482 <div class="theme-custom"> 483 <div class="color-row"><label>User Chat Bubble</label><input type="color" id="adv-userBubbleBg"><button class="color-reset-btn" data-reset-adv="userBubbleBg" title="Reset this color" aria-label="Reset color">↺</button></div> 484 <div class="color-row"><label>AI Chat Bubble</label><input type="color" id="adv-aiBubbleBg"><button class="color-reset-btn" data-reset-adv="aiBubbleBg" title="Reset this color" aria-label="Reset color">↺</button></div> 485 <div class="color-row"><label>Border Chat Bubble</label><input type="color" id="adv-bubbleBorder"><button class="color-reset-btn" data-reset-adv="bubbleBorder" title="Reset this color" aria-label="Reset color">↺</button></div> 486 </div> 487 </div> 488 <div class="theme-adv-group"> 489 <div class="theme-adv-group-label">Sidebar</div> 490 <div class="theme-custom"> 491 <div class="color-row"><label>Odysseus Logo</label><input type="color" id="adv-brandColor"><button class="color-reset-btn" data-reset-adv="brandColor" title="Reset this color" aria-label="Reset color">↺</button></div> 492 <div class="color-row"><label title="Hamburger menu"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" style="vertical-align:-2px;"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg></label><input type="color" id="adv-hamburgerColor"><button class="color-reset-btn" data-reset-adv="hamburgerColor" title="Reset this color" aria-label="Reset color">↺</button></div> 493 </div> 494 </div> 495 <div class="theme-adv-group"> 496 <div class="theme-adv-group-label">Chat Input / Prompt Area</div> 497 <div class="theme-custom"> 498 <div class="color-row"><label>Input Bg</label><input type="color" id="adv-inputBg"><button class="color-reset-btn" data-reset-adv="inputBg" title="Reset this color" aria-label="Reset color">↺</button></div> 499 <div class="color-row"><label>Input Border</label><input type="color" id="adv-inputBorder"><button class="color-reset-btn" data-reset-adv="inputBorder" title="Reset this color" aria-label="Reset color">↺</button></div> 500 <div class="color-row"><label>Send Btn</label><input type="color" id="adv-sendBtnBg"><button class="color-reset-btn" data-reset-adv="sendBtnBg" title="Reset this color" aria-label="Reset color">↺</button></div> 501 <div class="color-row"><label>Send Hover</label><input type="color" id="adv-sendBtnHover"><button class="color-reset-btn" data-reset-adv="sendBtnHover" title="Reset this color" aria-label="Reset color">↺</button></div> 502 </div> 503 </div> 504 <div class="theme-adv-group"> 505 <div class="theme-adv-group-label">Code Blocks</div> 506 <div class="theme-custom"> 507 <div class="color-row"><label>Code Bg</label><input type="color" id="adv-codeBg"><button class="color-reset-btn" data-reset-adv="codeBg" title="Reset this color" aria-label="Reset color">↺</button></div> 508 <div class="color-row"><label>Code Text</label><input type="color" id="adv-codeFg"><button class="color-reset-btn" data-reset-adv="codeFg" title="Reset this color" aria-label="Reset color">↺</button></div> 509 </div> 510 </div> 511 <div class="theme-adv-group"> 512 <div class="theme-adv-group-label">Controls</div> 513 <div class="theme-custom"> 514 <div class="color-row"><label>Toggle On</label><input type="color" id="adv-toggleActive"><button class="color-reset-btn" data-reset-adv="toggleActive" title="Reset this color" aria-label="Reset color">↺</button></div> 515 </div> 516 </div> 517 <div class="theme-adv-group"> 518 <div class="theme-adv-group-label">Custom Fonts</div> 519 <div class="theme-fd-label" style="opacity:0.4;">Drop <code>.woff2</code>, <code>.ttf</code>, or <code>.otf</code> files into <code>static/fonts/custom/</code> and reload â they'll appear in the Font dropdown above.</div> 520 </div> 521 <button class="theme-adv-clear-btn" id="theme-adv-clear">Clear Advanced Overrides</button> 522 </div> 523 <!-- Color Harmony Generator (its own card) --> 524 <div class="admin-card" id="theme-harmony-card"> 525 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><circle cx="13.5" cy="6.5" r="2.5"/><circle cx="19" cy="13" r="2.5"/><circle cx="6" cy="12" r="2.5"/><circle cx="10" cy="20" r="2.5"/></svg>Color Harmony</h2> 526 <div class="theme-harmony-row"> 527 <div class="theme-fd-group"> 528 <label class="theme-fd-label">Accent Color</label> 529 <div class="color-row" style="justify-content:flex-start;gap:8px;"> 530 <input type="color" id="harmony-accent" value="#e06c75">
531 <span id="harmony-accent-hex" style="font-size:11px;opacity:0.65;font-family:ui-monospace,monospace;letter-spacing:0.02em;">#e06c75</span> 532 </div> 533 </div> 534 <div class="theme-fd-group"> 535 <label class="theme-fd-label">Harmony</label> 536 <select id="harmony-type" class="theme-fd-select"> 537 <option value="complementary">Complementary</option> 538 <option value="analogous">Analogous</option> 539 <option value="triadic">Triadic</option> 540 <option value="monochromatic">Monochromatic</option> 541 </select> 542 </div> 543 </div> 544 <div class="theme-harmony-row" style="margin-top:6px;"> 545 <div class="theme-fd-group"> 546 <label class="theme-fd-label">Mode</label> 547 <select id="harmony-mode" class="theme-fd-select"> 548 <option value="dark">Dark</option> 549 <option value="light">Light</option> 550 </select> 551 </div> 552 <div class="theme-fd-group" style="justify-content:flex-end;"> 553 <button id="harmony-generate-btn" class="harmony-generate-btn">Generate</button> 554 </div> 555 </div> 556 <div id="harmony-preview" class="harmony-preview"></div> 557 </div> 558 <div class="admin-card"> 559 <h2>Font & Layout</h2> 560 <div class="theme-fd-row"> 561 <div class="theme-fd-group"> 562 <label class="theme-fd-label">Font</label> 563 <select id="theme-font-select" class="theme-fd-select" aria-label="Font"> 564 <option value="mono">Monospace</option> 565 <option value="sans">Sans-serif</option> 566 <option value="serif">Serif</option> 567 </select> 568 </div> 569 <div class="theme-fd-group"> 570 <label class="theme-fd-label">Density</label> 571 <select id="theme-density-select" class="theme-fd-select" aria-label="Density"> 572 <option value="compact">Compact</option> 573 <option value="comfortable">Comfortable</option> 574 <option value="spacious">Spacious</option> 575 </select> 576 </div> 577 <div class="theme-fd-group" id="theme-frosted-group"> 578 <label class="theme-fd-label" for="theme-frosted-toggle">Frosted</label> 579 <label class="admin-switch" style="margin-top:4px;"> 580 <input type="checkbox" id="theme-frosted-toggle"> 581 <span class="admin-slider"></span> 582 </label> 583 </div> 584 </div> 585 <div class="theme-fd-row"> 586 <div class="theme-fd-group" style="flex:1 1 0;"> 587 <label class="theme-fd-label">Background / Effect</label> 588 <select id="theme-bg-pattern-select" class="theme-fd-select"> 589 <option value="none">Solid</option> 590 <option value="dots">Dots</option> 591 <option value="synapse">Synapse</option> 592 <option value="rain">Rain</option> 593 <option value="constellations">Constellations</option> 594 <option value="perlin-flow">Perlin Flow</option> 595 <option value="petals">Petals</option> 596 <option value="sparkles">Sparkles</option> 597 <option value="embers">Embers</option> 598 </select> 599 </div> 600 <div class="theme-fd-group" style="flex:0 0 auto;align-items:center;"> 601 <label class="theme-fd-label"> </label> 602 <div class="color-row" style="margin:0;padding:0;"> 603 <input type="color" id="theme-bg-effect-color" value="#9cdef2" title="Effect color"> 604 <button class="color-reset-btn" data-reset-effect title="Reset to text color">↺</button> 605 </div> 606 </div> 607 </div> 608 <div class="theme-fd-row"> 609 <div class="theme-fd-group" id="theme-bg-intensity-group" style="flex:1 1 0;"> 610 <label class="theme-fd-label">Intensity</label> 611 <input type="range" id="theme-bg-intensity" class="theme-fd-range" min="0" max="100" step="5" value="100"> 612 </div> 613 <div class="theme-fd-group" id="theme-bg-size-group" style="flex:1 1 0;"> 614 <label class="theme-fd-label">Size</label> 615 <input type="range" id="theme-bg-size" class="theme-fd-range" min="30" max="250" step="10" value="100"> 616 </div> 617 </div> 618 </div> 619 <div class="admin-card" style="margin-top:8px;"> 620 <h2>Save / Share</h2> 621 <div class="theme-save-row" id="theme-save-row"> 622 <input type="text" id="theme-save-name" placeholder="Theme name..." maxlength="32"> 623 <button id="theme-save-go">Save</button> 624 </div> 625 <div class="theme-save-error" id="theme-save-error"></div> 626 <div class="theme-io-row" style="margin-top:6px;"> 627 <button id="theme-import-btn" class="theme-io-btn" title="Import a theme from JSON">⤒ Import</button> 628 <button id="theme-export-btn" class="theme-io-btn" title="Export current colors as JSON">⤓ Export</button> 629 </div> 630 <textarea id="theme-import-area" class="theme-import-area hidden" placeholder="Paste theme JSON here..." rows="3"></textarea> 631 <div class="theme-import-actions hidden" id="theme-import-actions"> 632 <button id="theme-import-go" class="theme-io-btn">Apply</button> 633 <button id="theme-import-cancel" class="theme-io-btn">Cancel</button> 634 </div> 635 </div> 636 <button id="theme-reset-btn">Reset to Default</button> 637 </div> 638 </div> 639 </div> 640 641 <div id="mobile-backdrop"></div> 642 <button id="mobile-menu-btn" aria-label="Toggle sidebar">☰</button> 643 644 <button class="hamburger-btn" id="hamburger-btn" title="Show sidebar"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg></button> 645 <!-- new session button removed â use + in send button instead --> 646 <div class="icon-rail" id="icon-rail"> 647 <div class="rail-resize-handle" id="rail-resize-handle"></div> 648 <!-- Static: core actions --> 649 <button class="icon-rail-btn" id="rail-search-btn" title="Search conversations (Ctrl+K)">
649<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="10" cy="10" r="7"/><path d="M21 21l-4.35-4.35"/></svg></button> 650 <button class="icon-rail-btn rail-new-chat" id="rail-new-session" title="New chat"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></button> 651 <button class="icon-rail-btn" id="rail-delete-session" title="Delete session">✕</button> 652 <div class="rail-separator"></div> 653 <!-- Dynamic contextual indicators (shown only while active) --> 654 <button class="icon-rail-btn rail-dynamic" id="rail-chats" title="Chat ready" style="display:none"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></button> 655 <button class="icon-rail-btn rail-dynamic" id="rail-documents" title="Documents" style="display:none"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="13" y2="17"/></svg></button> 656 <!-- Tool launchers â always visible, alphabetical --> 657 <button class="icon-rail-btn" id="rail-calendar" title="Calendar"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg></button> 658 <button class="icon-rail-btn" id="rail-compare" title="Compare"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg></button> 659 <button class="icon-rail-btn" id="rail-cookbook" title="Cookbook"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" style="opacity:0.7"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg></button> 660 <button class="icon-rail-btn" id="rail-research" title="Deep Research"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg></button> 661 <button class="icon-rail-btn" id="rail-email" title="Email"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></button> 662 <button class="icon-rail-btn" id="rail-gallery" title="Gallery"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg></button> 663 <button class="icon-rail-btn" id="rail-archive" title="Library"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/><path d="M9 7h6M9 11h4"/></svg></button> 664 <button class="icon-rail-btn" id="rail-memory" title="Brain">
664<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/></svg></button> 665 <button class="icon-rail-btn" id="rail-notes" title="Notes"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 3h10l4 4v14H5z"/><path d="M15 3v5h5"/><path d="M8 17.5 15.5 10l2.5 2.5L10.5 20H8z"/></svg></button> 666 <button class="icon-rail-btn" id="rail-tasks" title="Tasks"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/><path d="M9 16l2 2 4-4"/></svg></button> 667 <button class="icon-rail-btn" id="rail-theme" title="Theme"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a10 10 0 0 0 0 20 5 5 0 0 0 5-5 3 3 0 0 0-3-3h-2a3 3 0 0 1-3-3 5 5 0 0 1 5-5"/></svg></button> 668 <div style="flex:1"></div> 669 <!-- Static: bottom --> 670 <button class="icon-rail-btn" id="rail-settings" title="Settings"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></button> 671 </div> 672 673 <nav class="sidebar" id="sidebar" role="navigation" aria-label="Sidebar"> 674 <div class="sidebar-resize-handle" id="sidebar-resize-handle"></div> 675 <div class="sidebar-header"> 676 <button class="sidebar-hamburger" id="sidebar-toggle-btn" title="Toggle sidebar"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg></button> 677 <div class="sidebar-brand" id="sidebar-brand-btn" style="cursor:pointer;" title="New chat"> 678 <span class="sidebar-brand-title">Odysseus</span> 679 </div> 680 </div> 681 <div class="sidebar-inner"> 682 <div class="list-item" id="sidebar-new-chat-btn" title="New chat"> 683 <svg class="sidebar-action-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="position:relative;left:-2px;"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> 684 <span class="grow" style="position:relative;left:-3px;">New Chat</span> 685 </div> 686 <div class="list-item" id="sidebar-search-btn" title="Search conversations (Ctrl+K)"> 687 <svg class="sidebar-action-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="10" cy="10" r="7"/><path d="M21 21l-4.35-4.35"/></svg> 688 <span class="grow" style="position:relative;left:-1px;">Search</span> 689 </div> 690 <!-- Assistant sidebar entry removed â its log + settings live inside 691 the Tasks modal (Activity + Settings tabs). The backend 692 assistant session is still maintained for log_to_assistant() 693 writes from scheduled tasks. --> 694 695 <div class="section" id="sessions-section"> 696 <div class="section-header-flex">
697 <span class="section-title" id="chats-section-title"><svg class="section-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg><span id="chats-section-label" class="section-title-label">Chats</span><span id="chats-notif-dot" class="sidebar-notif-dot" style="display:none"></span></span> 698 <div style="position:relative; display:inline-block; display:flex; gap:4px; align-items:center;"> 699 <button type="button" class="section-header-btn chats-manage-btn" id="chats-library-btn" title="Manage Chats (Library)"> 700 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 701 <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/> 702 <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/> 703 <path d="M9 7h6M9 11h4"/> 704 </svg> 705 </button> 706 <button type="button" class="section-header-btn" id="session-sort-btn" title="Sort sessions"> 707 <svg class="sort-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 708 <line x1="4" y1="6" x2="20" y2="6"/> 709 <line x1="4" y1="12" x2="14" y2="12"/> 710 <line x1="4" y1="18" x2="9" y2="18"/> 711 </svg> 712 <svg class="sort-spinner" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" style="display:none; animation: spin 0.7s linear infinite;"> 713 <path d="M12 2a10 10 0 0 1 10 10" /> 714 </svg> 715 </button> 716 <div id="session-sort-dropdown" class="dropdown sort-dropdown" style="display:none;"> 717 <div class="dropdown-item sort-option sort-dropdown-item" data-sort="active">Last Active</div> 718 <div class="dropdown-item sort-option sort-dropdown-item" data-sort="newest">Newest First</div> 719 <div class="dropdown-item sort-option sort-dropdown-item" data-sort="group">By Folder</div> 720 <div class="dropdown-item sort-dropdown-item sort-dropdown-sep" id="auto-sort-sessions-row" style="display:flex;align-items:center;padding:0;"> 721 <span id="auto-sort-sessions-btn" style="flex:1;padding:5px 10px;cursor:pointer;display:inline-flex;align-items:center;gap:4px;"> 722 <span class="auto-sort-icon">
722<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-1px;margin-right:2px;"><path d="M12 0L14.59 8.41L23 12L14.59 15.59L12 24L9.41 15.59L1 12L9.41 8.41Z"/></svg> Tidy</span> 723 <span class="auto-sort-spinner" style="display:none;">Sorting...</span> 724 </span> 725 <button type="button" id="auto-sort-sessions-more" title="Tidy options" aria-label="Tidy options" style="background:none;border:none;border-left:1px solid var(--border);color:inherit;cursor:pointer;padding:5px 8px;font-size:9px;opacity:0.7;"><svg width="8" height="8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></button> 726 </div> 727 <div class="dropdown-item sort-dropdown-item" id="auto-sort-sessions-noai-btn" style="display:none;padding-left:24px;"> 728 Tidy <span class="auto-sort-noai-spinner" style="display:none;font-size:9px;opacity:0.6;margin-left:4px;">Cleaning...</span> 729 </div> 730 <div class="dropdown-item rearrange-toggle sort-dropdown-item sort-dropdown-sep" id="session-rearrange-toggle"> 731 ↑↓ Rearrange <span class="rearrange-check" style="float:right; opacity:0;">•</span> 732 </div> 733 <div class="dropdown-item sort-dropdown-item" id="session-select-from-dropdown"> 734 â Select 735 </div> 736 </div> 737 </div> 738 </div> 739 <div id="session-bulk-bar" class="session-bulk-bar hidden"> 740 <span id="session-select-all-dot" style="cursor:pointer;font-size:14px;opacity:0.4;user-select:none;">â</span><input type="checkbox" id="session-select-all" style="display:none;"><span style="font-size:10px;cursor:pointer;opacity:0.5;" id="session-select-all-label">All</span> 741 <div style="margin-left:auto;display:flex;gap:2px;align-items:center;"> 742 <button class="session-bulk-btn" id="session-bulk-archive" title="Archive selected"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="5" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg></button> 743 <button class="session-bulk-btn session-bulk-btn-danger" id="session-bulk-delete" title="Delete selected"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/></svg></button> 744 <button class="session-bulk-btn" id="session-bulk-cancel" title="Cancel"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button> 745 </div> 746 </div> 747 <div id="session-list" role="listbox"></div> 748 </div> 749 <!-- Hidden dropdown for session actions --> 750 <div id="session-actions-dropdown" class="dropdown hidden"> 751 <div class="dropdown-item" id="rename-session-option"> 752 <h4>Rename</h4> 753 <p>Change the session name</p> 754 </div> 755 <div class="dropdown-item" id="delete-session-option"> 756 <h4>Delete</h4> 757 <p>Remove this session permanently</p> 758 </div> 759 <div class="dropdown-item" id="memory-session-option"> 760 <h4>Memory</h4> 761 <p>Extract memories from this session</p> 762 </div> 763 </div> 764 765 <div class="section" id="email-section"> 766 <div class="section-header-flex"> 767 <span class="section-title" id="email-section-title" style="cursor:pointer;" title="Open email inbox"><svg class="section-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg><span>Email</span></span> 768 <button type="button" class="section-header-btn list-item-plus-btn" id="email-compose-btn" title="Compose email">
769 <svg class="list-item-plus-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> 770 <span class="list-item-plus-label">new</span> 771 </button> 772 <!-- Unread dot is a direct header child placed AFTER the compose 773 button (it used to live inside the title, before the button). 774 With the title's flex:1 eating the free space, this lands the 775 dot at the far-right corner with the + just to its left â 776 i.e. the dot and + swap places when the dot appears. --> 777 <span id="email-unread-dot" class="sidebar-notif-dot" style="display:none"></span> 778 </div> 779 </div> 780 781 <div class="section" id="models-section"> 782 <div class="section-header-flex"> 783 <span class="section-title"> Models</span> 784 <div style="position:relative; display:inline-block;"> 785 <button type="button" class="section-header-btn" id="model-sort-btn" title="Sort models"> 786 <svg class="sort-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 787 <line x1="4" y1="6" x2="20" y2="6"/> 788 <line x1="4" y1="12" x2="14" y2="12"/> 789 <line x1="4" y1="18" x2="9" y2="18"/> 790 </svg> 791 </button> 792 <div id="model-sort-dropdown" class="dropdown sort-dropdown" style="display:none;"> 793 <div class="dropdown-item sort-option sort-dropdown-item" data-sort="alpha">A-Z</div> 794 <div class="dropdown-item sort-option sort-dropdown-item" data-sort="last-used">Last used</div> 795 <div class="dropdown-item sort-option sort-dropdown-item" data-sort="most-used">Most used</div> 796 <div class="dropdown-item rearrange-toggle sort-dropdown-item sort-dropdown-sep" id="model-rearrange-toggle"> 797 ↑↓ Rearrange <span class="rearrange-check" style="float:right; opacity:0;">•</span> 798 </div> 799 </div> 800 </div> 801 </div> 802 <div id="models"> 803 <div class="models-row"> 804 <select id="model-select" aria-label="Select model" style="flex: 1; padding: 6px 8px; border-radius: 4px; border: 1px solid var(--border); background: var(--bg); color: var(--fg);"></select> 805 <button type="button" id="btn-model-chat" class="model-chat-btn" aria-label="Add model chat" style="transition: all 0.2s ease;"><span class="model-chat-btn-label">+ Chat</span></button> 806 </div> 807 </div> 808 </div> 809 810 <div class="section" id="tools-section"> 811 <div class="section-header-flex"> 812 <span class="section-title"><svg class="section-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>Tools</span> 813 </div> 814 <div class="list-item" id="tool-memory-btn"> 815 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 816 stroke-width="2" stroke-linecap="round" stroke-linejoin="round" 817 style="flex-shrink:0;opacity:0.5;"> 818 <path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/> 819 <path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/> 820 <path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/> 821 </svg> 822 <span class="grow">Brain</span> 823 </div> 824 <div class="list-item" id="tool-calendar-btn"> 825 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 826 stroke-width="2" stroke-linecap="round" stroke-linejoin="round" 827 style="flex-shrink:0;
827opacity:0.5;"> 828 <rect x="3" y="4" width="18" height="18" rx="2"/> 829 <line x1="16" y1="2" x2="16" y2="6"/> 830 <line x1="8" y1="2" x2="8" y2="6"/> 831 <line x1="3" y1="10" x2="21" y2="10"/> 832 </svg> 833 <span class="grow">Calendar</span> 834 </div> 835 <div class="list-item" id="tool-compare-btn"> 836 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0;opacity:0.5;"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg> 837 <span class="grow">Compare</span> 838 </div> 839 <div class="list-item" id="tool-cookbook-btn"> 840 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 841 stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" 842 style="flex-shrink:0;opacity:0.5;"> 843 <path d="M12 7v14"/> 844 <path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/> 845 </svg> 846 <span class="grow">Cookbook</span> 847 <span id="cookbook-bg-status" style="display:none;font-size:9px;opacity:0.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:12px;flex-shrink:1;min-width:0;position:relative;top:-1px;"></span> 848 <span class="cookbook-notif-dot" id="cookbook-notif-dot" style="display:none;margin-left:6px;margin-right:4px;position:relative;top:-1px;left:0px;"></span> 849 </div> 850 <div class="list-item" id="tool-research-btn"> 851 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink:0;opacity:0.5;"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg> 852 <span class="grow">Deep Research</span> 853 </div> 854 <div class="list-item" id="tool-gallery-btn"> 855 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 856 stroke-width="2" stroke-linecap="round" stroke-linejoin="round" 857 style="flex-shrink:0;opacity:0.5;"> 858 <rect x="3" y="3" width="18" height="18" rx="2"/> 859 <circle cx="8.5" cy="8.5" r="1.5"/> 860 <path d="M21 15l-5-5L5 21"/> 861 </svg> 862 <span class="grow">Gallery</span> 863 </div> 864 <div class="list-item" id="tool-library-btn"> 865 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0;opacity:0.5;"> 866 <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/><path d="M9 7h6M9 11h4"/> 867 </svg> 868 <span class="grow">Library</span> 869 <button type="button" class="list-item-plus-btn" id="library-new-doc-btn" title="New document"> 870 <svg class="list-item-plus-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="width:11px;height:11px;"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> 871 <span class="list-item-plus-label">new</span> 872 </button> 873 </div> 874 <div class="list-item" id="tool-notes-btn"> 875 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 876 stroke-width="2" stroke-linecap="round" stroke-linejoin="round" 877 style="flex-shrink:0;opacity:0.5;"> 878 <path d="M5 3h10l4 4v14H5z"/> 879 <path d="M15 3v5h5"/> 880 <path d="M8 17.5 15.5 10l2.5 2.5L10.5 20H8z"/> 881 </svg> 882 <span class="grow">Notes</span> 883 </div> 884 <div class="list-item" id="tool-tasks-btn"> 885 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 886 stroke-width="2" stroke-linecap="round" stroke-linejoin="round" 887 style="flex-shrink:0;
887opacity:0.5;"> 888 <rect x="3" y="4" width="18" height="18" rx="2"/> 889 <line x1="16" y1="2" x2="16" y2="6"/> 890 <line x1="8" y1="2" x2="8" y2="6"/> 891 <line x1="3" y1="10" x2="21" y2="10"/> 892 <path d="M9 16l2 2 4-4"/> 893 </svg> 894 <span class="grow">Tasks</span> 895 <span id="assistant-notif-dot" class="sidebar-notif-dot" style="display:none"></span> 896 </div> 897 898 <div class="list-item" id="tool-theme-btn"> 899 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" 900 stroke-width="2" stroke-linecap="round" stroke-linejoin="round" 901 style="flex-shrink:0;opacity:0.5;"> 902 <circle cx="12" cy="12" r="10"/> 903 <path d="M12 2a7 7 0 0 0 0 20 4 4 0 0 1 0-8 4 4 0 0 0 0-8"/> 904 <circle cx="8" cy="9" r="1.5" fill="currentColor"/> 905 <circle cx="15" cy="14" r="1.5" fill="currentColor"/> 906 <circle cx="9" cy="15" r="1.5" fill="currentColor"/> 907 </svg> 908 <span class="grow">Theme</span> 909 </div> 910 </div> 911 </div> 912 <div class="sidebar-user-bar" id="sidebar-user-bar"> 913 <!-- Logged in state --> 914 <div class="user-bar-left" id="user-bar-profile"> 915 <div class="user-bar-avatar" id="user-bar-avatar"></div> 916 <span class="user-bar-name" id="user-bar-name">User</span> 917 </div> 918 <div class="user-bar-actions" id="user-bar-actions"> 919 <button type="button" class="user-bar-btn" id="user-bar-settings" title="Settings"> 920 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg> 921 </button> 922 <button type="button" class="user-bar-btn user-bar-logout-btn" id="user-bar-logout" title="Log Out" style="display:none"> 923 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg> 924 </button> 925 </div> 926 <!-- Not logged in state --> 927 <button type="button" class="user-bar-signin-btn" id="user-bar-signin" style="display:none"> 928 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg> 929 Sign In 930 </button> 931 </div> 932 </nav> 933 934 <main class="chat-container welcome-active" id="chat-container" aria-label="Chat area" aria-busy="false"> 935 <!-- Persistent page heading for assistive tech. Visually hidden so it 936 never affects layout, but always present inside the main landmark 937 (the sidebar that shows the visible brand is hidden off-canvas on 938 mobile) so the page always exposes a single level-1 heading. --> 939 <h1 class="a11y-visually-hidden">Odysseus</h1> 940 <div class="chat-top-bar"> 941 <button type="button" class="incognito-indicator" id="incognito-indicator" title="Nobody mode active â click to deactivate" style="display:none;"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><line x1="8" y1="16" x2="16" y2="8"/>
941<line x1="8" y1="8" x2="16" y2="16"/></svg></button> 942 <div class="chat-meta-overlay"><span id="current-meta">Odysseus Chat</span><span id="current-meta-count" class="chat-meta-count" aria-hidden="true"></span><span id="session-cost-display" class="session-cost-display" style="display:none;"></span><span class="export-dropdown-wrap" id="export-dropdown-wrap"><button type="button" class="export-dl-btn" id="export-dl-btn" title="More"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></button><div class="export-dropdown-menu" id="export-dropdown-menu"><div class="export-dropdown-item" id="export-rename-btn"><span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></svg></span><span>Rename</span></div><div class="export-dropdown-item" id="export-copy-btn"><span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></span><span>Copy Chat</span></div><div class="export-dropdown-item" id="export-pdf-btn"><span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><path d="M9 15v-2h2a1.5 1.5 0 0 1 0 3H9z"/></svg></span><span>PDF</span></div><div class="export-dropdown-item" id="export-doc-btn"><span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg></span><span>Save to Documents</span></div></div></span></div> </div> 943 <div id="welcome-screen"> 944 <div class="welcome-name"><svg class="welcome-boat" viewBox="0 0 32 32"><path d="M16 4L16 22L6 22Z" fill="currentColor"/><path d="M16 8L16 22L24 22Z" fill="currentColor" opacity="0.6"/><path d="M4 24Q10 20 16 24Q22 28 28 24" stroke="currentColor" stroke-width="2.5" fill="none" stroke-linecap="round"/></svg>Odysseus</div> 945 <div class="welcome-sub" id="welcome-sub">Welcome, <span class="setup-trigger-link" style="color:var(--accent,var(--red));font-weight:600;cursor:pointer;text-decoration:underline;" title="Click to launch setup">type /setup</span> to get started.</div> 946 <div class="welcome-tip" id="welcome-tip"></div> 947 <button type="button" class="incognito-btn" id="incognito-btn" title="Enable Nobody mode â no memory, no history saved"> 948 <svg class="eye-open" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 949 <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/> 950 </svg> 951 <svg class="eye-blinded" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none"> 952 <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><line x1="8" y1="16" x2="16" y2="8"/><line x1="8" y1="8" x2="16" y2="16"/> 953 </svg> 954 <span class="incognito-label">Nobody</span> 955 </button> 956 <div id="welcome-setup" style="display:none"></div> 957 </div> 958
958<script nonce="0ef1c0e2ced0cc537d6ee0258e679162"> 959 (function(){ 960 var mobile = window.matchMedia('(max-width: 768px)').matches; 961 var desktop = [ 962 'Tip: Press Ctrl+K to search across all your conversations.', 963 'Tip: Press Ctrl+B to quickly toggle the sidebar.', 964 'Tip: Shift-click the sidebar toggle to swap it to the other side.', 965 'Tip: Drag and drop files onto the chat to attach them.', 966 'Tip: Right-click a session for rename, delete, and memory options.', 967 ]; 968 var phone = [ 969 'Tip: Long-press a session for rename, delete, and memory options.', 970 'Tip: Tap the eye icon for Nobody mode â no history saved.', 971 'Tip: Switch to Agent mode for web search and code execution.', 972 'Tip: Use Compare mode to test different models side by side.', 973 'Tip: Attach images or files using the + button next to the input.', 974 ]; 975 var tips = mobile ? phone : desktop; 976 var el = document.getElementById('welcome-tip'); 977 if (el) { 978 el.textContent = 'Type /setup, then choose Local models or API.'; 979 } 980 fetch('/api/version').then(function(r){return r.json()}).then(function(d){ 981 if (d.version) window._appVersion = d.version; 982 }).catch(function(){}); 983 })(); 984 </script>
984 985 <div id="chat-history" class="chat-history" role="log" aria-live="polite"></div> 986 987 <!-- Attachments strip --> 988 <div id="attach-strip" class="attach-strip"></div> 989 990 <!-- Hidden elements for form logic --> 991 <input type="checkbox" id="research-toggle" style="display:none;"> 992 <input type="checkbox" id="rag-toggle" style="display:none;"> 993 <input type="checkbox" id="incognito-toggle" style="display:none;"> 994 <input type="file" id="file-input" class="hidden" multiple /> 995 996 <!-- Unified chat input bar --> 997 <div class="chat-input-bar"> 998 <div class="chat-input-top"> 999 <div id="message-ghost" class="ghost-text-overlay" aria-hidden="true"></div> 1000 <textarea id="message" placeholder="Message Odysseus..." required autocomplete="off" aria-label="Message input" rows="1" autofocus></textarea> 1001 <!-- Model picker (inside chatbox, top-right) --> 1002 <div class="model-picker-wrap" id="model-picker-wrap"> 1003 <button type="button" class="model-picker-btn" id="model-picker-btn" title="Switch model"><span id="model-picker-label">Select model</span> <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 15 12 9 18 15"/></svg></button> 1004 <div class="model-picker-menu hidden" id="model-picker-menu"> 1005 <div class="model-picker-search-row"> 1006 <input type="text" id="model-picker-search" placeholder="Search models..." autocomplete="off" aria-label="Search models"> 1007 <button type="button" class="model-picker-action-btn primary" id="model-picker-add-models-btn" title="Add model endpoints" aria-label="Add model endpoints"> 1008 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg> 1009 </button> 1010 </div> 1011 <div class="model-picker-list" id="model-picker-list"></div> 1012 </div> 1013 </div> 1014 </div> 1015 <div id="pinned-tools-bar"></div> 1016 <div class="chat-input-bottom" style="visibility:hidden"> 1017 <div class="chat-input-left"> 1018 <!-- Overflow menu (+) â always first/left --> 1019 <div class="overflow-wrapper"> 1020 <button type="button" class="input-icon-btn overflow-plus-btn" id="overflow-plus-btn" title="More tools" aria-label="More tools" aria-haspopup="true"> 1021 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 1022 <polyline points="6 15 12 9 18 15"/> 1023 </svg> 1024 <span class="plus-active-dot"></span> 1025 </button> 1026 <div id="overflow-menu" class="overflow-menu hidden"> 1027 <button type="button" class="overflow-menu-item" id="overflow-attach-btn"> 1028 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg> 1029 <span>Attach files</span> 1030 </button> 1031 <button type="button" class="overflow-menu-item" id="overflow-doc-btn"> 1032 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 1033 <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/> 1034 </svg> 1035 <span>Documents</span> 1036 </button> 1037 <button type="button" class="overflow-menu-item" id="overflow-rag-btn"> 1038 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 1039 <ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/> 1040 </svg>
1041 <span>RAG</span> 1042 <span class="overflow-active-dot"></span> 1043 </button> 1044 <button type="button" class="overflow-menu-item" id="overflow-workspace-btn"> 1045 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1046 <path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/> 1047 </svg> 1048 <span>Workspace</span> 1049 <span class="overflow-active-dot"></span> 1050 </button> 1051 <!-- Inline "deep research mode" toggle removed (superseded by the 1052 Deep Research sidebar / trigger_research). The hidden 1053 #research-toggle checkbox is kept inert so existing JS refs 1054 don't break; without this entry point it can't be enabled. --> 1055 <!-- Group Chat moved to Characters modal Group tab --> 1056 <!-- TTS Mode hidden â read-aloud feature is off in this build. --> 1057 <button type="button" class="overflow-menu-item" id="overflow-tts-btn" hidden style="display:none"> 1058 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg> 1059 <span>TTS Mode</span> 1060 <span class="overflow-active-dot"></span> 1061 </button> 1062 <button type="button" class="overflow-menu-item" id="overflow-preset-btn"> 1063 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1064 <path d="m18 2 4 4"/><path d="m17 7 3-3"/><path d="M19 9 8.7 19.3c-1 1-2.5 1-3.4 0l-.6-.6c-1-1-1-2.5 0-3.4L15 5"/><path d="m9 11 4 4"/><path d="m5 19-3 3"/><path d="m14 4 6 6"/> 1065 </svg> 1066 <span>Prompt</span> 1067 </button> 1068 </div> 1069 </div> 1070 <!-- Web search (magnifying glass) --> 1071 <button type="button" class="input-icon-btn" title="Web search" id="web-toggle-btn" data-mode-tool="true" aria-label="Web search" aria-pressed="false"> 1072 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1073 <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/> 1074 </svg> 1075 </button> 1076 <!-- Shell commands (terminal) --> 1077 <button type="button" class="input-icon-btn" title="Shell Access" id="bash-toggle-btn" data-mode-tool="true" aria-label="Shell access" aria-pressed="false"> 1078 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1079 <polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/> 1080 </svg> 1081 </button> 1082 <!-- Workspace indicator (hidden until a folder is set) --> 1083 <button type="button" class="input-icon-btn tool-indicator" title="Workspace â click to clear" id="workspace-indicator-btn" aria-label="Clear workspace" style="display:none;"> 1084 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg> 1085 <span style="font-size:11px;margin-left:2px;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" id="workspace-indicator-name"></span> 1086 <svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg> 1087 </button> 1088 <!-- Plan mode (investigate read-only, propose a plan to approve) --> 1089 <button type="button" class="input-icon-btn" title="Plan mode â investigate read-only, then propose a plan to approve" id="plan-toggle-btn" data-mode-tool="true">
1090 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1091 <path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/> 1092 </svg> 1093 </button> 1094 <!-- RAG toolbar indicator (hidden until active) --> 1095 <button type="button" class="input-icon-btn tool-indicator" title="RAG active â click to deactivate" id="rag-indicator-btn" style="display:none;"> 1096 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 1097 <ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/> 1098 </svg> 1099 <span style="font-size:11px;margin-left:2px;">RAG</span> 1100 <svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg> 1101 </button> 1102 <!-- 6. Deep Research (hidden until active) --> 1103 <button type="button" class="input-icon-btn tool-indicator" title="Deep Research active â click to deactivate" id="research-toggle-btn" style="display:none;"> 1104 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg> 1105 <span style="font-size:11px;margin-left:2px;">Research</span> 1106 <svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg> 1107 </button> 1108 <!-- 7. Group Chat (hidden until active) --> 1109 <button type="button" class="input-icon-btn tool-indicator" title="Group Chat active â click to deactivate" id="group-toggle-btn" style="display:none;"> 1110 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg> 1111 <span style="font-size:11px;margin-left:2px;">Group</span> 1112 <svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg> 1113 </button> 1114 <input type="checkbox" id="group-toggle" style="display:none;"> 1115 <!-- Character indicator (hidden until active) --> 1116 <button type="button" class="input-icon-btn tool-indicator" title="Persona active â click to deactivate" id="character-indicator-btn" style="display:none;"> 1117 <svg id="char-indicator-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> 1118 <span id="character-indicator-name" style="font-size:11px;margin-left:2px;max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"></span> 1119 <svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg> 1120 </button> 1121 <!-- Compare toolbar indicator (hidden until active) --> 1122 <button type="button" class="input-icon-btn tool-indicator" title="Compare active â click to deactivate" id="compare-indicator-btn" style="display:none;">
1123 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg> 1124 <span style="font-size:11px;margin-left:2px;">Compare</span> 1125 <svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg> 1126 </button> 1127 </div> 1128 <div class="chat-input-right"> 1129 <!-- Agent / Chat mode toggle --> 1130 <div class="mode-toggle"> 1131 <button type="button" class="mode-toggle-btn active" id="mode-agent-btn" aria-pressed="true">Agent</button> 1132 <button type="button" class="mode-toggle-btn" id="mode-chat-btn" aria-pressed="false">Chat</button> 1133 </div> 1134 <button type="submit" form="chat-form" class="send-btn newchat-mode" data-mode="newchat" aria-label="New chat"> 1135 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg><span class="send-btn-label">+ New</span> 1136 </button> 1137 </div> 1138 </div> 1139 <!-- Hidden checkboxes for state --> 1140 <input type="checkbox" id="web-toggle" style="display:none;"> 1141 <input type="checkbox" id="bash-toggle" style="display:none;"> 1142 <input type="checkbox" id="plan-toggle" style="display:none;"> 1143 </div> 1144 <form id="chat-form" autocomplete="off" action="javascript:void(0);" style="display:none;"></form> 1145 1146 <!-- Character (custom preset) modal --> 1147 <div id="custom-preset-modal" class="modal hidden"> 1148 <div class="modal-content preset-modal-content" role="dialog" aria-label="Prompt" style="background:var(--bg)"> 1149 <div class="modal-header"> 1150 <h4><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><path d="m18 2 4 4"/><path d="m17 7 3-3"/><path d="M19 9 8.7 19.3c-1 1-2.5 1-3.4 0l-.6-.6c-1-1-1-2.5 0-3.4L15 5"/><path d="m9 11 4 4"/><path d="m5 19-3 3"/><path d="m14 4 6 6"/></svg>Prompt</h4> 1151 <button class="close-btn" id="close-custom-preset" aria-label="Close prompt">â</button> 1152 </div> 1153 <div class="modal-body preset-modal-body"> 1154 <div id="char-fields-wrap"> 1155 <div class="preset-tabs"> 1156 <button class="preset-tab active" data-chartab="inject"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 2 4 4"/><path d="m17 7 3-3"/><path d="M19 9 8.7 19.3c-1 1-2.5 1-3.4 0l-.6-.6c-1-1-1-2.5 0-3.4L15 5"/><path d="m9 11 4 4"/><path d="m5 19-3 3"/><path d="m14 4 6 6"/></svg><span>Inject</span></button> 1157 <button class="preset-tab" data-chartab="character"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Persona</span></button> 1158 <button class="preset-tab" data-chartab="group"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg><span>Group</span></button> 1159 </div> 1160 <!-- Inject tab (also holds model tuning: temperature + max tokens) --> 1161 <div class="preset-chartab" data-chartab-panel="inject"> 1162 <label for="inject-prefix">Prefix</label> 1163 <textarea id="inject-prefix" rows="2" placeholder="Added before your message" style="margin-bottom:8px"></textarea> 1164 <label for="inject-suffix">Suffix</label> 1165 <textarea id="inject-suffix" rows="2" placeholder="Added after your message" style="margin-bottom:12px"></textarea> 1166 <div class="preset-slider-row"> 1167 <label>Temperature <span class="preset-hint-icon" title="Controls randomness. Lower values g
1167ive focused, deterministic answers (good for code). Higher values give more creative, varied responses.">?</span></label> 1168 <span class="preset-slider-value" id="temp-value">1.0</span> 1169 </div> 1170 <input type="range" class="preset-range" id="custom-temperature" min="0" max="2" step="0.1" value="1.0"> 1171 <div class="preset-temp-hints"> 1172 <span>Precise / Code</span> 1173 <span>Balanced</span> 1174 <span>Creative</span> 1175 </div> 1176 <div class="preset-slider-row"> 1177 <label>Max Tokens <span class="preset-hint-icon" title="Maximum length of the AI response. 'No limit' lets the model decide when to stop.">?</span></label> 1178 <span class="preset-slider-value" id="tokens-value">No limit</span> 1179 </div> 1180 <input type="range" class="preset-range" id="custom-max-tokens" min="256" max="8448" step="256" value="8448"> 1181 </div> 1182 <!-- Prompt (character/persona) tab --> 1183 <div class="preset-chartab" data-chartab-panel="character" style="display:none"> 1184 <label>Persona</label> 1185 <div class="char-name-combo"> 1186 <select id="char-template-select" class="char-template-select"> 1187 <option value="">Select persona...</option> 1188 </select> 1189 <button type="button" id="char-new-btn" class="char-action-btn" title="Create a new persona">+ New</button> 1190 </div> 1191 <div id="char-name-row"> 1192 <label for="custom-character-name">Name</label> 1193 <div class="char-name-combo"> 1194 <input type="text" id="custom-character-name" maxlength="50" placeholder="Give your persona a name..." autocomplete="off" style="flex:1"> 1195 <button type="button" id="char-delete-template-btn" class="char-action-btn" title="Delete this persona and its memories" style="display:none;margin-top:-6px !important"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>Delete</button> 1196 <button type="button" id="reset-character-btn" class="char-action-btn" title="Reset to default" style="margin-top:-6px !important">↺ Reset</button> 1197 </div> 1198 </div> 1199 <label for="custom-system-prompt">System prompt</label> 1200 <div class="char-prompt-wrap"> 1201 <textarea id="custom-system-prompt" rows="4" placeholder="Write rough notes and click Expand, or leave empty"></textarea> 1202 <button type="button" id="char-expand-btn" class="char-expand-btn" title="AI expand â turn your notes into a full system prompt">
1203 <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-1px;margin-right:2px;"><path d="M12 0L14.59 8.41L23 12L14.59 15.59L12 24L9.41 15.59L1 12L9.41 8.41Z"/></svg> 1204 Expand 1205 </button> 1206 </div> 1207 </div> 1208 <!-- Group tab --> 1209 <div class="preset-chartab" data-chartab-panel="group" style="display:none"> 1210 <div style="display:flex;gap:4px;margin-bottom:8px;"> 1211 <button type="button" class="compare-parallel-toggle" id="group-mode-btn" style="flex:1;height:auto;width:auto;"> 1212 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="8" y1="6" x2="20" y2="6"/><line x1="8" y1="12" x2="20" y2="12"/><line x1="8" y1="18" x2="20" y2="18"/><circle cx="4" cy="6" r="1.5" fill="currentColor"/><circle cx="4" cy="12" r="1.5" fill="currentColor"/><circle cx="4" cy="18" r="1.5" fill="currentColor"/></svg> 1213 <span class="compare-toggle-label">Sequential</span> 1214 </button> 1215 </div> 1216 <div id="group-participants" style="display:flex;flex-direction:column;gap:4px;margin-bottom:0;max-height:220px;overflow-y:auto;"></div> 1217 <button type="button" id="group-add-btn" class="preset-save-btn" style="width:100%;background:none;border:1px dashed var(--border);color:var(--fg);opacity:0.6;font-size:11px;padding:4px;margin-top:0;">+ Add participant</button> 1218 </div> 1219 </div> 1220 </div> 1221 <div class="modal-footer"> 1222 <div style="flex:1"></div> 1223 <button type="button" id="cancel-custom-preset" style="margin-right:8px;display:none;">Cancel</button> 1224 <button type="button" id="save-custom-preset">Start</button> 1225 </div> 1226 </div> 1227 </div> 1228 1229 1230 </main> 1231 <button id="scroll-bottom-btn" class="scroll-nav-btn" title="Scroll to bottom">â¼</button> 1232
1232<script nonce="0ef1c0e2ced0cc537d6ee0258e679162"> 1233 (function(){ 1234 const container = document.getElementById('chat-history'); 1235 const chatBar = document.querySelector('.chat-input-bar'); 1236 const bottomBtn = document.getElementById('scroll-bottom-btn'); 1237 if (!container || !chatBar || !bottomBtn) return; 1238 1239 function reposition() { 1240 const barRect = chatBar.getBoundingClientRect(); 1241 bottomBtn.style.bottom = (window.innerHeight - barRect.top + 16) + 'px'; 1242 bottomBtn.style.right = (window.innerWidth - barRect.right + 8) + 'px'; 1243 } 1244 1245 function update() { 1246 reposition(); 1247 const scrollable = container.scrollHeight > container.clientHeight + 10; 1248 const atBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 300; 1249 if (scrollable && !atBottom) { 1250 bottomBtn.classList.remove('slide-out'); 1251 bottomBtn.classList.add('show'); 1252 } else if (bottomBtn.classList.contains('show')) { 1253 bottomBtn.classList.add('slide-out'); 1254 bottomBtn.classList.remove('show'); 1255 } 1256 } 1257 1258 let _scrollRaf = null; 1259 let _scrollTimeout = null; 1260 let _scrollingToBottom = false; 1261 1262 function cancelAutoScroll() { 1263 if (_scrollRaf) { cancelAnimationFrame(_scrollRaf); _scrollRaf = null; } 1264 if (_scrollTimeout) { clearTimeout(_scrollTimeout); _scrollTimeout = null; } 1265 _scrollingToBottom = false; 1266 } 1267 1268 container.addEventListener('scroll', update, {passive:true}); 1269 container.addEventListener('wheel', () => { if (_scrollingToBottom) cancelAutoScroll(); }, {passive:true}); 1270 container.addEventListener('touchstart', () => { if (_scrollingToBottom) cancelAutoScroll(); }, {passive:true}); 1271 1272 bottomBtn.addEventListener('click', () => { 1273 cancelAutoScroll(); 1274 const target = container.scrollHeight - container.clientHeight; 1275 _scrollingToBottom = true; 1276 function step() { 1277 if (!_scrollingToBottom) return; 1278 const diff = target - container.scrollTop; 1279 if (diff <= 8) { container.scrollTop = target; _scrollingToBottom = false; return; } 1280 container.scrollTop += diff * 0.2; 1281 _scrollRaf = requestAnimationFrame(step); 1282 } 1283 step(); 1284 _scrollTimeout = setTimeout(() => { if (_scrollingToBottom) { container.scrollTop = target; _scrollingToBottom = false; } }, 1500); 1285 }); 1286 new ResizeObserver(reposition).observe(chatBar); 1287 new MutationObserver(update).observe(container, {childList:true, subtree:true}); 1288 window.addEventListener('resize', reposition); 1289 update(); 1290 })(); 1291 </script>
1291 1292 1293 <!-- Rename Session Modal --> 1294 <div id="rename-session-modal" class="modal hidden"> 1295 <div class="modal-content" role="dialog" aria-label="Rename session" style="width: 400px;"> 1296 <div class="modal-header"> 1297 <h4>Rename Session</h4> 1298 <button class="close-btn" id="close-rename-session" aria-label="Close rename session modal">â</button> 1299 </div> 1300 <div class="modal-body"> 1301 <div style="margin-bottom: 12px;"> 1302 <label for="session-name-input" style="display: block; margin-bottom: 6px; font-weight: 500;">Session Name</label> 1303 <input 1304 type="text" 1305 id="session-name-input" 1306 placeholder="Enter session name" 1307 style="width: 100%; padding: 8px; border-radius: 4px;" 1308 /> 1309 </div> 1310 <div style="display: flex; justify-content: flex-end; gap: 8px;"> 1311 <button id="cancel-rename-session" style="padding: 6px 12px;">Cancel</button> 1312 <button id="save-session-name" style="padding: 6px 12px; background: var(--fg); color: var(--bg);">Save</button> 1313 </div> 1314 </div> 1315 </div> 1316 </div> 1317 1318 1319 <!-- Cookbook Modal --> 1320 <div id="cookbook-modal" class="modal hidden"> 1321 <div class="modal-content" role="dialog" aria-label="Cookbook" style="width: min(780px, 92vw); height: 94vh; max-height: 94vh; background: var(--bg);"> 1322 <div class="modal-header"> 1323 <h4 style="margin:0;margin-right:auto"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:6px"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>Cookbook</h4> 1324 <button class="close-btn" id="close-cookbook-modal" aria-label="Close cookbook">â</button> 1325 </div> 1326 <div class="modal-body cookbook-body"></div> 1327 </div> 1328 </div> 1329 1330 <!-- Settings Modal (all users) --> 1331 <div id="settings-modal" class="modal hidden"> 1332 <div class="modal-content settings-modal-content" role="dialog" aria-label="Settings"> 1333 <div class="modal-header"> 1334 <h4><span style="vertical-align:-1px;margin-right:6px;font-size:15px">⚙</span>Settings</h4> 1335 <button type="button" class="theme-opacity-wrap theme-opacity-toggle hidden" id="settings-opacity-wrap" title="Fade this window to preview the page behind it" aria-pressed="false">
1336 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg> 1337 <span class="theme-opacity-label">Peek</span> 1338 </button> 1339 <button class="close-btn" aria-label="Close settings">â</button> 1340 </div> 1341 <div class="admin-toggle-sub" style="padding:0 12px 8px;opacity:0.6;font-size:11px;">Toggle on/off visibility of tools and modules across the interface.</div> 1342 <div class="settings-layout"> 1343 <div class="settings-sidebar"> 1344 <!-- Section 1: AI plumbing (Add Models â AI Defaults â Search) --> 1345 <button class="settings-nav-item active" data-settings-tab="services"> 1346 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><circle cx="6" cy="6" r="1"/><circle cx="6" cy="18" r="1"/></svg> 1347 <span>Add Models</span> 1348 </button> 1349 <button class="settings-nav-item" data-settings-tab="ai"> 1350 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2a4 4 0 0 0-4 4v2H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2h-2V6a4 4 0 0 0-4-4z"/></svg> 1351 <span>AI Defaults</span> 1352 </button> 1353 <button class="settings-nav-item" data-settings-tab="search"> 1354 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> 1355 <span>Search</span> 1356 </button> 1357 <div class="settings-sidebar-divider"></div> 1358 <!-- Section 2: Comms (Integrations â Email â Reminders). 1359 Integrations leads here because it's where the underlying 1360 accounts the other two tabs depend on actually live. --> 1361 <button class="settings-nav-item" data-settings-tab="integrations"> 1362 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg> 1363 <span>Integrations</span> 1364 </button> 1365 <button class="settings-nav-item" data-settings-tab="email"> 1366 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg> 1367 <span>Email</span> 1368 </button> 1369 <button class="settings-nav-item" data-settings-tab="reminders"> 1370 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg> 1371 <span>Reminders</span> 1372 </button> 1373 <div class="settings-sidebar-divider"></div> 1374 <!-- Section 3: UX (Appearance â Shortcuts) --> 1375 <button class="settings-nav-item" data-settings-tab="appearance"> 1376 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 2a7 7 0 0 0 0 20 4 4 0 0 1 0-8 4 4 0 0 0 0-8"/></svg> 1377 <span>Appearance</span> 1378 </button> 1379 <button class="settings-nav-item" data-settings-tab="shortcuts"> 1380 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M6 8h.01M10 8h.01M14 8h.01M18 8h.01M8 12h.01M12 12h.01M16 12h.01M7 16h10"/></svg>
1381 <span>Shortcuts</span> 1382 </button> 1383 <div class="settings-sidebar-divider"></div> 1384 <!-- Section 4: Account (sits at the bottom of the user section) --> 1385 <button class="settings-nav-item" data-settings-tab="account"> 1386 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> 1387 <span>Account</span> 1388 </button> 1389 <div class="settings-sidebar-divider"></div> 1390 <!-- Section 5: Cloud Storage (HF Buckets) --> 1391 <button class="settings-nav-item" data-settings-tab="cloud-storage"> 1392 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/></svg> 1393 <span>Cloud Storage</span> 1394 </button> 1395 <!-- Section 6: Secrets & Environment --> 1396 <button class="settings-nav-item" data-settings-tab="secrets"> 1397 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg> 1398 <span>Secrets</span> 1399 </button> 1400 <!-- Section 7: GitHub --> 1401 <button class="settings-nav-item" data-settings-tab="github"> 1402 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg> 1403 <span>GitHub</span> 1404 </button> 1405 <div class="settings-sidebar-divider admin-only"></div> 1406 <div class="settings-sidebar-label admin-only">Admin</div> 1407 <button class="settings-nav-item admin-only" data-settings-tab="tools"> 1408 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg> 1409 <span>Agent Tools</span> 1410 </button> 1411 <button class="settings-nav-item admin-only" data-settings-tab="users"> 1412 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg> 1413 <span>Users</span> 1414 </button> 1415 <button class="settings-nav-item admin-only" data-settings-tab="system"> 1416 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg> 1417 <span>System</span> 1418 </button> 1419 </div> 1420 <div class="settings-panels"> 1421 1422 <!-- âââ AI TAB âââ --> 1423 1424 <div data-settings-panel="ai" class="hidden"> 1425 <div class="admin-card"> 1426 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>Default Chat Model</h2> 1427 <div class="admin-toggle-sub" style="margin-bottom:8px">The model used when creating a new chat session.</div> 1428 <div class="settings-col"> 1429 <div class="settings-row"> 1430 <label class="settings-label">Endpoint</label> 1431 <select id="set-defaultEpSelect" class="settings-select"></select> 1432 </div> 1433 <div class="settings-row"> 1434 <label class="settings-label">Model</label> 1435 <select id="set-defaultModelSelect" class="settings-select"></select> 1436 </div> 1437 <div id="set-defaultFallbacks" class="settings-fallbacks"></div> 1438 <button type="button" class="settings-fallback-add" id="set-defaultAddFallback" title="Add a model to try if the one above fails">+ Add fallback</button> 1439 <div id="set-defaultChatMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1440 </div> 1441 </div> 1442 <div class="admin-card"> 1443 <h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:1px;opacity:0.6;flex-shrink:0"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>Utility Model <span style="font-size:0.72em;opacity:0.55;font-weight:normal;">(Recommended: Local Endpoint)</span></h2> 1444 <div class="admin-toggle-sub" style="margin-bottom:8px">Runs background tasks (compaction, cleanup, auto-naming, retrieving memories from files) on a
1444small/local model instead of your chat model. Leave blank to use the chat model.</div> 1445 <div class="settings-col"> 1446 <div class="settings-row"> 1447 <label class="settings-label">Endpoint</label> 1448 <select id="set-utilityEpSelect" class="settings-select"><option value="">â</option></select> 1449 </div> 1450 <div class="settings-row"> 1451 <label class="settings-label">Model</label> 1452 <select id="set-utilityModelSelect" class="settings-select"><option value="">â</option></select> 1453 </div> 1454 <div id="set-utilityFallbacks" class="settings-fallbacks"></div> 1455 <button type="button" class="settings-fallback-add" id="set-utilityAddFallback" title="Add a model to try if the utility model fails">+ Add fallback</button> 1456 <div id="set-utilityChatMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1457 </div> 1458 </div> 1459 <div class="admin-card"> 1460 <h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:1px;opacity:0.6;flex-shrink:0"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>Vision<span style="flex:1"></span><label class="admin-switch" title="Analyze images with a vision-capable model"><input type="checkbox" id="set-visionEnabledToggle" checked><span class="admin-slider"></span></label></h2> 1461 <div class="admin-toggle-sub" style="margin-bottom:8px">Analyze images with a vision-capable model.</div> 1462 <div style="display:flex;flex-direction:column;gap:0.5rem;"> 1463 <div style="display:flex;align-items:center;gap:0.75rem;"> 1464 <label class="settings-label">Model</label> 1465 <select id="set-vlModelSelect" class="settings-select"><option value="">Auto-detect</option></select> 1466 </div> 1467 <div id="set-visionFallbacks" class="settings-fallbacks"></div> 1468 <button type="button" class="settings-fallback-add" id="set-visionAddFallback" title="Add a vision model to try if the one above fails">+ Add fallback</button> 1469 <div id="set-visionSettingsMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1470 </div> 1471 </div> 1472 <div class="admin-card"> 1473 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg>Research Model</h2> 1474 <div class="admin-toggle-sub" style="margin-bottom:8px">Model used for Deep Research. Falls back to the default chat model if not set.</div> 1475 <div class="settings-col"> 1476 <div class="settings-row"> 1477 <label class="settings-label">Endpoint</label> 1478 <select id="set-researchEndpoint" class="settings-select"> 1479 <option value="">Same as chat</option> 1480 </select> 1481 </div> 1482 <div class="settings-row"> 1483 <label class="settings-label">Model</label> 1484 <select id="set-researchModel" class="settings-select"> 1485 <option value="">Same as chat</option> 1486 </select> 1487 </div> 1488 <div class="settings-row"> 1489 <label class="settings-label">Search</label> 1490 <select id="set-researchSearch" class="settings-select"> 1491 <option value="">Same as web search</option> 1492 <option value="searxng">SearXNG</option> 1493 <option value="duckduckgo">DuckDuckGo</option> 1494 <option value="tavily">Tavily</option> 1495 <option value="brave">Brave</option> 1496 <option value="google">Google</option> 1497 <option value="serper">Serper</option> 1498 </select> 1499 </div> 1500 <div class="settings-row"> 1501 <label class="settings-label">Max Tokens</label> 1502 <input id="set-researchMaxTokens" type="text" inputmode="numeric" placeholder="8192 (default)" class="settings-select" style="width:120px;"> 1503 </div> 1504 <div class="settings-row"> 1505 <label class="settings-label">Extract Timeout</label> 1506 <input id="set-researchExtractTimeout" type="text" inputmode="numeric" placeholder="90 sec" class="settings-select" style="width:120px;"> 1507 </div> 1508 <div class="settings-row"> 1509 <label class="settings-label">Extract Parallel</label> 1510 <input id="set-researchExtractConcurrency" type="text" inputmode="numeric" placeholder="3" class="settings-select" style="width:120px;"> 1511 </div> 1512 <div class="settings-row"> 1513 <label class="settings-label">Max Time</label> 1514 <input id="set-researchRunTimeout" type="text" inputmode="numeric" placeholder="1800 sec (0 = no limit)" class="settings-select" style="width:120px;"> 1515 </div> 1516 <div id="set-researchMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1517 </div> 1518 </div> 1519 <div class="admin-card"> 1520 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>Agent</h2> 1521 <div class="admin-toggle-sub" style="margin-bottom:8px">Controls for the agent tool loop.</div> 1522 <div class="settings-col"> 1523 <div class="settings-row"> 1524 <label class="settings-label">Tool call limit</label> 1525 <input id="set-agentMaxTools" type="text" inputmode="numeric" placeholder="0 = unlimited" class="settings-select" style="width:120px;"> 1526 </div> 1527 <div class="settings-row"> 1528 <label class="settings-label">Max steps per message</label>
1529 <input id="set-agentMaxRounds" type="text" inputmode="numeric" placeholder="20" class="settings-select" style="width:120px;"> 1530 </div> 1531 <div id="set-agentMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1532 </div> 1533 </div> 1534 <!-- Image Generation removed â only inpaint remains in this build, 1535 and inpaint is configured via the gallery editor not this card. 1536 Keeping the DOM (hidden) so JS wiring against the inputs 1537 doesn't throw. --> 1538 <div class="admin-card" hidden style="display:none"> 1539 <h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:1px;opacity:0.6;flex-shrink:0"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg>Image Generation<span style="flex:1"></span><label class="admin-switch"><input type="checkbox" id="set-imgEnabledToggle" checked><span class="admin-slider"></span></label></h2> 1540 <div class="admin-toggle-sub" style="margin-bottom:8px">Configure which model to use for image generation.</div> 1541 <div style="display:flex;flex-direction:column;gap:0.5rem;"> 1542 <div style="display:flex;align-items:center;gap:0.75rem;"> 1543 <label class="settings-label">Model</label> 1544 <select id="set-imgModelSelect" class="settings-select"><option value="">Auto-detect</option></select> 1545 </div> 1546 <div style="display:flex;align-items:center;gap:0.75rem;"> 1547 <label class="settings-label">Quality</label> 1548 <select id="set-imgQualitySelect" class="settings-select"> 1549 <option value="low">Low (fastest, cheapest)</option> 1550 <option value="medium">Medium (default)</option> 1551 <option value="high">High (best quality)</option> 1552 </select> 1553 </div> 1554 <div id="set-imgSettingsMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1555 </div> 1556 </div> 1557 <!-- TTS panel hidden â user opted out of read-aloud entirely. Kept 1558 in DOM so the JS that wires set-ttsProviderSelect etc. doesn't 1559 throw on missing nodes; not visible to anyone. --> 1560 <div class="admin-card" hidden style="display:none"> 1561 <h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>Text to Speech<span style="flex:1"></span><label class="admin-switch"><input type="checkbox" id="set-ttsEnabledToggle" checked><span class="admin-slider"></span></label></h2> 1562 <div class="admin-toggle-sub" style="margin-bottom:8px">Configure TTS provider for assistant message read-aloud.</div> 1563 <div style="display:flex;flex-direction:column;gap:0.5rem;"> 1564 <div style="display:flex;align-items:center;gap:0.75rem;"> 1565 <label class="settings-label">Provider</label> 1566 <select id="set-ttsProviderSelect" class="settings-select"> 1567 <option value="disabled">Disabled</option> 1568 <option value="browser">Browser (built-in)</option> 1569 <option value="local">Local (Kokoro-82M)</option> 1570 </select> 1571 </div> 1572 <div id="set-ttsModelRow" style="display:flex;align-items:center;gap:0.75rem;"> 1573 <label class="settings-label">Model</label> 1574 <select id="set-ttsModelSelect" class="settings-select"> 1575 <option value="tts-1">tts-1 (fast)</option> 1576 <option value="tts-1-hd">tts-1-hd (quality)</option> 1577 <option value="gpt-4o-mini-tts">gpt-4o-mini-tts (steerable)</option> 1578 </select> 1579 <input id="set-ttsModelInput" type="text" placeholder="model name" style="flex:1;padding:5px;display:none;"> 1580 </div> 1581 <div id="set-ttsVoiceRow" style="display:flex;align-items:center;gap:0.75rem;"> 1582 <label class="settings-label">Voice</label> 1583 <select id="set-ttsVoiceSelect" class="settings-select"> 1584 <option value="alloy">Alloy</option> 1585 <option value="ash">Ash</option> 1586 <option value="coral">Coral</option> 1587 <option value="echo">Echo</option> 1588 <option value="fable">Fable</option> 1589 <option value="nova">Nova</option> 1590 <option value="onyx">Onyx</option> 1591 <option value="sage">Sage</option> 1592 <option value="shimmer">Shimmer</option> 1593 </select> 1594 <input id="set-ttsVoiceInput" type="text" placeholder="af_heart" style="flex:1;padding:5px;display:none;"> 1595 </div> 1596 <div id="set-ttsSpeedRow" style="display:flex;align-items:center;gap:0.75rem;"> 1597 <label class="settings-label">
1597Speed</label> 1598 <select id="set-ttsSpeedSelect" class="settings-select"> 1599 <option value="0.5">0.5x</option> 1600 <option value="0.75">0.75x</option> 1601 <option value="1" selected>1x (normal)</option> 1602 <option value="1.25">1.25x</option> 1603 <option value="1.5">1.5x</option> 1604 <option value="2">2x</option> 1605 </select> 1606 </div> 1607 <button type="button" id="set-ttsPreviewBtn" class="admin-btn-sm" style="margin-top:4px;padding:5px 16px;font-size:12px;">Preview</button> 1608 <div id="set-ttsSettingsMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1609 </div> 1610 </div> 1611 <div class="admin-card"> 1612 <h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg>Teacher Model <span style="font-size:0.72em;opacity:0.55;font-weight:normal;">(Experimental)</span><span style="flex:1"></span><label class="admin-switch"><input type="checkbox" id="set-teacherEnabledToggle"><span class="admin-slider"></span></label></h2> 1613 <div class="admin-toggle-sub" style="margin-bottom:8px">When a self-hosted student fails an agent-mode task, escalate to a SOTA teacher that writes a SKILL.md procedure so the student can do it next time. Off by default.</div> 1614 <div class="settings-col"> 1615 <div class="settings-row"> 1616 <label class="settings-label">Endpoint</label> 1617 <select id="set-teacherEpSelect" class="settings-select"><option value="">â</option></select> 1618 </div> 1619 <div class="settings-row"> 1620 <label class="settings-label">Model</label> 1621 <select id="set-teacherModelSelect" class="settings-select"><option value="">â</option></select> 1622 </div> 1623 <div id="set-teacherChatMsg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 45%, transparent);"></div> 1624 </div> 1625 </div> 1626 </div> 1627 1628 <!-- âââ SEARCH TAB âââ --> 1629 <div data-settings-panel="search" class="hidden"> 1630 <div class="admin-card"> 1631 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>Web Search</h2> 1632 <div class="admin-toggle-sub" style="margin-bottom:8px">Search API used for web search and deep research.</div> 1633 <div class="settings-col"> 1634 <div class="settings-row"> 1635 <label class="settings-label">Provider</label> 1636 <!-- Custom picker (with logos). Hidden native <select> mirrors 1637 its value so the existing JS that reads 1638 set-searchProvider keeps working unchanged. --> 1639 <div class="adm-provider-picker search-provider-picker" id="search-provider-picker" style="flex:1;position:relative;top:5px;"> 1640 <button type="button" class="adm-provider-btn" id="search-provider-btn"> 1641 <span class="adm-provider-current"><span class="adm-provider-logo"></span><span class="adm-provider-name">SearXNG</span></span> 1642 <svg class="adm-provider-caret" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg> 1643 </button> 1644 <div class="adm-provider-menu hidden" id="search-provider-menu"></div> 1645 </div> 1646 <select id="set-searchProvider" class="settings-select" style="display:none;"> 1647 <option value="searxng" data-search-logo="searxng">SearXNG (self-hosted)</option> 1648 <option value="duckduckgo" data-search-logo="duckduckgo">DuckDuckGo (free, no key)</option> 1649 <option value="brave" data-search-logo="brave">Brave Search</option> 1650 <option value="google_pse" data-search-logo="google_pse">Google PSE</option> 1651 <option value="tavily" data-search-logo="tavily">Tavily</option> 1652 <option value="serper" data-search-logo="serper">Serper.dev</option> 1653 <option value="disabled" data-search-logo="disabled">Disabled</option> 1654 </select> 1655 <button type="button" class="admin-btn-sm" id="set-searchTestBtn" title="Run a test query against the configured provider" style="margin-left:6px;flex-shrink:0;position:relative;top:2px;">Test</button> 1656 </div> 1657 <div class="settings-row"> 1658 <label class="settings-label">Results</label> 1659 <div style="display:flex;gap:8px;flex:1;"> 1660 <select id="set-searchResultCount" class="settings-select" style="flex:1;"> 1661 <option value="3">3</option> 1662 <option value="5" selected>5</option> 1663 <option value="10">10</option> 1664 <option value="20">20</option> 1665 <option value="custom">Custom</option> 1666 </select> 1667 <input id="set-searchResultCountCustom" type="number" class="settings-select" placeholder="Enter custom value" style="flex:1;display:none;min-width:120px;" min="1" max="100"> 1668 </div> 1669 </div> 1670 <div id="set-searchUrlRow" class="settings-row"> 1671 <label class="settings-label">URL</label> 1672 <input id="set-searchUrl" type="text" placeholder="http://localhost:8080" class="settings-select"> 1673 </div> 1674 <div id="set-searchKeyRow" class="settings-row" style="display:none;"> 1675 <label class="settings-label">API Key</label> 1676 <input id="set-searchApiKey" type="password" placeholder="API key" class="settings-select"> 1677 </div> 1678 <div id="set-searchCxRow" class="settings-row" style="display:none;"> 1679 <label class="settings-label">CX ID</label> 1680 <input id="set-searchCx" type="text" placeholder="Google PSE engine ID" class="settings-select"> 1681 </div> 1682 <div class="settings-row"> 1683 <label class="settings-label" title="Providers tried in order when the primary fails or hits a rate limit">Fallbacks</label> 1684 <div class="search-fallback-chain" id="set-searchFallbackChain"></div> 1685 </div> 1686 <div id="set-searchHint" class="admin-toggle-sub"></div> 1687 <div id="set-searchMsg" style="font-size:11px;"></div> 1688 </div> 1689 </div> 1690 </div> 1691 1692 <!-- âââ APPEARANCE TAB âââ --> 1693 <div data-settings-panel="appearance" class="settings-appearance-panel hidden"> 1694 <div class="admin-card" style="padding-bottom:6px;"> 1695 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/></svg>Sidebar</h2> 1696 <div class="vis-toggles"> 1697 <label class="vis-row">
1698 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M8 12l2.5 2.5L16 9"/></svg></span> 1699 <span class="vis-label">Odysseus <span class="vis-hint">Brand name</span></span> 1700 <input type="checkbox" checked data-ui-key="sidebar-brand"><span class="vis-switch"></span> 1701 </label> 1702 <label class="vis-row"> 1703 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="10" cy="10" r="7"/><path d="M21 21l-4.35-4.35"/></svg></span> 1704 <span class="vis-label">Search</span> 1705 <input type="checkbox" checked data-ui-key="sidebar-search"><span class="vis-switch"></span> 1706 </label> 1707 <label class="vis-row"> 1708 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></span> 1709 <span class="vis-label">New Chat</span> 1710 <input type="checkbox" checked data-ui-key="sidebar-new-chat"><span class="vis-switch"></span> 1711 </label> 1712 <label class="vis-row"> 1713 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span> 1714 <span class="vis-label">Chats <span class="vis-hint">Chat history list</span></span> 1715 <input type="checkbox" checked data-ui-key="sessions-section"><span class="vis-switch"></span> 1716 </label> 1717 <label class="vis-row"> 1718 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span> 1719 <span class="vis-label">Email</span> 1720 <input type="checkbox" checked data-ui-key="email-section"><span class="vis-switch"></span> 1721 </label> 1722 <label class="vis-row"> 1723 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg></span> 1724 <span class="vis-label">Models <span class="vis-hint">Model selector & quick-chat</span></span> 1725 <input type="checkbox" checked data-ui-key="models-section"><span class="vis-switch"></span> 1726 </label> 1727 <label class="vis-row"> 1728 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg></span> 1729 <span class="vis-label">Tools <span class="vis-hint">Whole section (header + all tools)</span></span> 1730 <input type="checkbox" checked data-ui-key="tools-section"><span class="vis-switch"></span> 1731 </label> 1732 <label class="vis-row"> 1733 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/></svg></span>
1734 <span class="vis-label">Brain</span> 1735 <input type="checkbox" checked data-ui-key="tool-memory"><span class="vis-switch"></span> 1736 </label> 1737 <label class="vis-row"> 1738 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg></span> 1739 <span class="vis-label">Calendar</span> 1740 <input type="checkbox" checked data-ui-key="tool-calendar"><span class="vis-switch"></span> 1741 </label> 1742 <label class="vis-row"> 1743 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg></span> 1744 <span class="vis-label">Compare</span> 1745 <input type="checkbox" checked data-ui-key="tool-compare"><span class="vis-switch"></span> 1746 </label> 1747 <label class="vis-row"> 1748 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/><path d="M9 7h6M9 11h4"/></svg></span> 1749 <span class="vis-label">Cookbook</span> 1750 <input type="checkbox" checked data-ui-key="tool-cookbook"><span class="vis-switch"></span> 1751 </label> 1752 <label class="vis-row"> 1753 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg></span> 1754 <span class="vis-label">Deep Research</span> 1755 <input type="checkbox" checked data-ui-key="tool-research"><span class="vis-switch"></span> 1756 </label> 1757 <label class="vis-row"> 1758 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg></span> 1759 <span class="vis-label">Gallery</span> 1760 <input type="checkbox" checked data-ui-key="tool-gallery"><span class="vis-switch"></span> 1761 </label> 1762 <label class="vis-row"> 1763 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="13" y2="17"/></svg></span> 1764 <span class="vis-label">Library</span> 1765 <input type="checkbox" checked data-ui-key="tool-library"><span class="vis-switch"></span> 1766 </label> 1767 <label class="vis-row"> 1768 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 7h6M9 11h6M9 15h4"/></svg></span> 1769 <span class="vis-label">Notes</span> 1770 <input type="checkbox" checked data-ui-key="tool-notes"><span class="vis-switch"></span> 1771 </label> 1772 <label class="vis-row"> 1773 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/><path d="M9 16l2 2 4-4"/></svg></span>
1774 <span class="vis-label">Tasks</span> 1775 <input type="checkbox" checked data-ui-key="tool-tasks"><span class="vis-switch"></span> 1776 </label> 1777 <label class="vis-row"> 1778 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a10 10 0 0 0 0 20 5 5 0 0 0 5-5 3 3 0 0 0-3-3h-2a3 3 0 0 1-3-3 5 5 0 0 1 5-5"/></svg></span> 1779 <span class="vis-label">Theme</span> 1780 <input type="checkbox" checked data-ui-key="tool-theme"><span class="vis-switch"></span> 1781 </label> 1782 <label class="vis-row"> 1783 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></span> 1784 <span class="vis-label">User <span class="vis-hint">Avatar & name</span></span> 1785 <input type="checkbox" checked data-ui-key="user-bar"><span class="vis-switch"></span> 1786 </label> 1787 <label class="vis-row"> 1788 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span> 1789 <span class="vis-label">Settings Button <span class="vis-hint">Cog next to user â re-open with <code>/settings</code></span></span> 1790 <input type="checkbox" checked data-ui-key="sidebar-settings-btn"><span class="vis-switch"></span> 1791 </label> 1792 </div> 1793 </div> 1794 <div class="admin-card" style="padding-bottom:6px;"> 1795 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>Chat Area</h2> 1796 <div class="vis-toggles"> 1797 <label class="vis-row"> 1798 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16"/><path d="M4 10h8"/></svg></span> 1799 <span class="vis-label">Session Header <span class="vis-hint">Model name & export above chat</span></span> 1800 <input type="checkbox" checked data-ui-key="chat-meta"><span class="vis-switch"></span> 1801 </label> 1802 <label class="vis-row"> 1803 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 3v2m0 14v2m-7-9H3m18 0h-2m-1.5-6.5L16 7m-8-1.5L6.5 7m11 11l-1.5-1.5M8 18l-1.5 1.5"/><circle cx="12" cy="12" r="4"/></svg></span> 1804 <span class="vis-label">Welcome Message <span class="vis-hint">Logo & tips on empty chat</span></span> 1805 <input type="checkbox" checked data-ui-key="welcome-text"><span class="vis-switch"></span> 1806 </label> 1807 <label class="vis-row">
1808 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span> 1809 <span class="vis-label">Incognito Mode <span class="vis-hint">No memory, no history saved</span></span> 1810 <input type="checkbox" checked data-ui-key="incognito-btn"><span class="vis-switch"></span> 1811 </label> 1812 <label class="vis-row"> 1813 <span class="vis-icon" style="font-size:13px;line-height:14px;">Aa</span> 1814 <span class="vis-label">Text-only Emojis <span class="vis-hint">Strip emojis from AI replies</span></span> 1815 <input type="checkbox" data-ui-key="text-emojis"><span class="vis-switch"></span> 1816 </label> 1817 <label class="vis-row"> 1818 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 2a7 7 0 0 0-7 7c0 3 2 5.5 4.5 7.5.7.6 1.2 1.3 1.5 2h2c.3-.7.8-1.4 1.5-2C17 14.5 19 12 19 9a7 7 0 0 0-7-7z"/><line x1="10" y1="22" x2="14" y2="22"/></svg></span> 1819 <span class="vis-label">Thinking Process <span class="vis-hint">Show <think> collapsible bars</span></span> 1820 <input type="checkbox" checked data-ui-key="show-thinking"><span class="vis-switch"></span> 1821 </label> 1822 <label class="vis-row"> 1823 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/><path d="M4 4l16 16"/></svg></span> 1824 <span class="vis-label">Sensitive Blur <span class="vis-hint">Blur emails, tokens, and secrets in AI output</span></span> 1825 <input type="checkbox" data-privacy-key="sensitive-blur"><span class="vis-switch"></span> 1826 </label> 1827 </div> 1828 </div> 1829 <div class="admin-card" style="padding-bottom:6px;"> 1830 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>Chat Bar</h2> 1831 <div class="vis-toggles"> 1832 <label class="vis-row"> 1833 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg></span> 1834 <span class="vis-label">Web Search</span> 1835 <input type="checkbox" checked data-ui-key="web-toggle-btn"><span class="vis-switch"></span> 1836 </label> 1837 <label class="vis-row"> 1838 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></span> 1839 <span class="vis-label">Document Editor</span> 1840 <input type="checkbox" checked data-ui-key="doc-toggle-btn"><span class="vis-switch"></span> 1841 </label> 1842 <label class="vis-row"> 1843 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg></span> 1844 <span class="vis-label">Shell</span> 1845 <input type="checkbox" checked data-ui-key="bash-toggle-btn"><span class="vis-switch"></span> 1846 </label> 1847 <label class="vis-row">
1848 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg></span> 1849 <span class="vis-label">More Tools <span class="vis-hint">Overflow menu</span></span> 1850 <input type="checkbox" checked data-ui-key="overflow-plus-btn"><span class="vis-switch"></span> 1851 </label> 1852 <label class="vis-row"> 1853 <span class="vis-icon vis-icon-text">A|C</span> 1854 <span class="vis-label">Agent / Chat <span class="vis-hint">Mode switcher</span></span> 1855 <input type="checkbox" checked data-ui-key="mode-toggle"><span class="vis-switch"></span> 1856 </label> 1857 <label class="vis-row"> 1858 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg></span> 1859 <span class="vis-label">Attach Files</span> 1860 <input type="checkbox" checked data-ui-key="attach-btn"><span class="vis-switch"></span> 1861 </label> 1862 <label class="vis-row"> 1863 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg></span> 1864 <span class="vis-label">Deep Research</span> 1865 <input type="checkbox" checked data-ui-key="research-btn"><span class="vis-switch"></span> 1866 </label> 1867 <label class="vis-row"> 1868 <span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></span> 1869 <span class="vis-label">Personas <span class="vis-hint">Persona picker & system prompt</span></span> 1870 <input type="checkbox" checked data-ui-key="preset-mini-btn"><span class="vis-switch"></span> 1871 </label> 1872 </div> 1873 </div> 1874 <div style="text-align:right;padding:0 4px;"> 1875 <button type="button" class="admin-btn-sm" id="set-uiVisResetBtn" style="opacity:0.5;">Reset All</button> 1876 </div> 1877 </div> 1878 1879 <!-- âââ THEME TAB âââ --> 1880 1881 <!-- âââ MEMORY TAB âââ --> 1882 <!-- âââ SHORTCUTS TAB âââ --> 1883 <div data-settings-panel="shortcuts" class="hidden"> 1884 <div class="admin-card" style="display:flex;align-items:center;justify-content:space-between;padding:10px 16px;"> 1885 <div> 1886 <h2 style="margin:0;font-size:13px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M6 8h.01M10 8h.01M14 8h.01M18 8h.01M8 12h.01M12 12h.01M16 12h.01M7 16h10"/></svg>Keyboard Shortcuts</h2> 1887 <p style="font-size:10px;opacity:0.4;margin:2px 0 0;">Click a shortcut to rebind. Press Escape to cancel.</p> 1888 </div> 1889 <button type="button" class="shortcut-action-btn is-reset" id="shortcuts-reset-btn" title="Reset Shortcuts" style="width:28px;height:28px;font-size:15px;">↩</button> 1890 </div> 1891 <div class="admin-card"> 1892 <div id="shortcuts-list"></div> 1893 </div> 1894 </div> 1895 1896 1897 <!-- âââ ACCOUNT TAB âââ --> 1898 <div data-settings-panel="account" class="hidden"> 1899 <div class="admin-card"> 1900 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>Account</h2> 1901 <div style="display:flex;align-items:center;gap:10px;margin:4px 0 12px;"> 1902 <div class="user-bar-avatar" id="settings-account-avatar" style="width:32px;height:32px;font-size:14px;"></div> 1903 <div style="flex:1;"> 1904 <div id="settings-account-username" style="font-size:13px;font-weight:600;"></div> 1905 <div id="settings-account-role" style="font-size:11px;opacity:0.5;"></div> 1906 </div> 1907 <button id="settings-logout-btn" style="background:color-mix(in srgb, var(--color-error) 10%, transparent);border:1px solid var(--color-error);border-radius:6px;padding:6px 12px;color:var(--color-error);font-family:inherit;font-size:12px;font-weight:500;cursor:pointer;transition:opacity 0.15s,background 0.15s;display:inline-flex;align-items:center;gap:6px;"> 1908 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg> 1909 Logout 1910 </button> 1911 </div> 1912 </div> 1913 <div class="admin-card"> 1914 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Change Password</h2> 1915 <div class="settings-col"> 1916 <input id="settings-pw-current" type="password" placeholder="Current password" autocomplete="current-password" style="padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 1917 <input id="settings-pw-new" type="password" placeholder="New password (min 8)" autocomplete="new-password" style="padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 1918 <input id="settings-pw-confirm" type="password" placeholder="Confirm new password" autocomplete="new-password" style="padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 1919 <div class="settings-row" style="margin-top:2px;justify-content:flex-end;">
1920 <span id="settings-pw-msg" style="font-size:11px;margin-right:auto;"></span> 1921 <button class="admin-btn-add" id="settings-pw-save">Update Password</button> 1922 </div> 1923 </div> 1924 </div> 1925 <div class="admin-card" id="settings-2fa-card"> 1926 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/><circle cx="12" cy="16" r="1"/></svg>Two-Factor Authentication</h2> 1927 <div id="settings-2fa-content"> 1928 <!-- Populated by JS --> 1929 </div> 1930 </div> 1931 </div> 1932 1933 <!-- âââ CLOUD STORAGE TAB âââ --> 1934 <div data-settings-panel="cloud-storage" class="hidden"> 1935 <div class="admin-card"> 1936 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/></svg>Hugging Face Cloud Storage</h2> 1937 <div class="admin-toggle-sub" style="margin-bottom:12px"> 1938 Use Hugging Face Storage Buckets for cloud file storage. Files uploaded to Odysseus are automatically synced to your bucket, enabling persistence across deployments and HF Spaces. 1939 </div> 1940 <div class="settings-col"> 1941 <div class="settings-row" style="align-items:center;margin-bottom:8px;"> 1942 <label style="font-size:12px;font-weight:500;min-width:90px;">HF Token</label> 1943 <input id="set-bucket-token" type="password" placeholder="hf_xxxxxxxxxxxxxxxxxxxx" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 1944 <button class="admin-btn-add" id="set-bucket-token-save" style="margin-left:8px;white-space:nowrap;">Save Token</button> 1945 </div> 1946 <div id="set-bucket-user-info" style="font-size:11px;opacity:0.7;margin-bottom:8px;display:none;"></div> 1947 </div> 1948 </div> 1949 1950 <div class="admin-card" id="set-bucket-config-card" style="opacity:0.5;pointer-events:none;"> 1951 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>Bucket Configuration</h2> 1952 <div class="settings-col"> 1953 <div class="settings-row" style="align-items:center;margin-bottom:8px;"> 1954 <label style="font-size:12px;font-weight:500;min-width:90px;">Active Bucket</label> 1955 <select id="set-bucket-select" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 1956 <option value="">No bucket selected</option> 1957 </select> 1958 <button class="admin-btn-add" id="set-bucket-select-btn" style="margin-left:8px;white-space:nowrap;">Select</button> 1959 </div> 1960 <div id="set-bucket-active-info" style="font-size:11px;opacity:0.7;margin-bottom:12px;display:none;"></div> 1961 1962 <div style="border-top:1px solid var(--border);padding-top:10px;margin-top:4px;"> 1963 <div style="font-size:12px;font-weight:500;margin-bottom:8px;">Create New Bucket</div> 1964 <div class="settings-row" style="align-items:center;margin-bottom:8px;"> 1965 <input id="set-bucket-new-name" type="text" placeholder="my-odysseus-data" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 1966 <label style="font-size:11px;display:flex;align-items:center;gap:4px;margin-left:8px;"> 1967 <input type="checkbox" id="set-bucket-new-private" checked> Private 1968 </label> 1969 <button class="admin-btn-add" id="set-bucket-create-btn" style="margin-left:8px;white-space:nowrap;">Create</button> 1970 </div> 1971 </div> 1972 </div> 1973 </div> 1974 1975 <div class="admin-card" id="set-bucket-status-card" style="display:none;"> 1976 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 3"/></svg>Storage Status</h2> 1977 <div id="set-bucket-status-content" style="font-size:12px;"></div> 1978 </div> 1979 1980 <div class="admin-card" id="set-bucket-files-card" style="display:none;"> 1981 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>Bucket Files</h2> 1982 <div class="settings-row" style="margin-bottom:8px;"> 1983 <button class="admin-btn-add" id="set-bucket-sync-btn" style="display:inline-flex;align-items:center;gap:4px;"> 1984 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg> 1985 Sync Uploads to Bucket 1986 </button> 1987 <button class="admin-btn-add" id="set-bucket-refresh-btn" style="margin-left:8px;">Refresh Files</button>
1988 <span id="set-bucket-files-msg" style="font-size:11px;margin-left:8px;"></span> 1989 </div> 1990 <div id="set-bucket-files-list" style="max-height:300px;overflow-y:auto;font-size:11px;font-family:var(--font-mono,'Menlo','Consolas',monospace);"></div> 1991 </div> 1992 1993 <div class="admin-card" id="set-bucket-danger-card" style="display:none;"> 1994 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6;color:var(--red)"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>Danger Zone</h2> 1995 <div class="settings-row" style="align-items:center;"> 1996 <div style="flex:1;"> 1997 <div style="font-size:12px;font-weight:500;">Disconnect Bucket</div> 1998 <div class="admin-toggle-sub" style="margin:2px 0 0;">Stop syncing files to the cloud. Local files are preserved.</div> 1999 </div> 2000 <button id="set-bucket-disconnect-btn" style="background:color-mix(in srgb, var(--color-error) 10%, transparent);border:1px solid var(--color-error);border-radius:6px;padding:6px 12px;color:var(--color-error);font-family:inherit;font-size:12px;font-weight:500;cursor:pointer;">Disconnect</button> 2001 </div> 2002 </div> 2003 </div> 2004 2005 <!-- âââ SECRETS TAB âââ --> 2006 <div data-settings-panel="secrets" class="hidden"> 2007 <div class="admin-card"> 2008 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>Secrets & Environment</h2> 2009 <div class="admin-toggle-sub" style="margin-bottom:8px"> 2010 Manage API keys, tokens, and configuration as environment variables. In HF Spaces, secrets are set via Space Settings and injected at runtime â <code>.env</code> files are not persistent. 2011 </div> 2012 <div id="secrets-space-banner"></div> 2013 <div class="settings-row" style="align-items:center;margin-bottom:8px;"> 2014 <button class="admin-btn-add" id="secrets-refresh-btn" style="font-size:11px;">Refresh</button> 2015 <span id="secrets-summary" style="font-size:11px;margin-left:8px;"></span> 2016 <span id="secrets-status-msg" style="font-size:11px;margin-left:8px;"></span> 2017 </div> 2018 <div id="secrets-list" style="max-height:400px;overflow-y:auto;font-size:11px;border:1px solid var(--border);border-radius:4px;"></div> 2019 </div> 2020 2021 <!-- Add custom secret --> 2022 <div class="admin-card"> 2023 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Add Secret / Variable</h2> 2024 <div class="admin-toggle-sub" style="margin-bottom:8px"> 2025 Add a new environment variable or secret. In HF Spaces, this sets it as a Space secret (triggers restart). Locally, it sets it in the current process only. 2026 </div> 2027 <div class="settings-row" style="align-items:center;margin-bottom:6px;"> 2028 <input id="secrets-custom-key" type="text" placeholder="API_KEY_NAME" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:monospace;font-size:12px;text-transform:uppercase;"> 2029 <input id="secrets-custom-value" type="password" placeholder="Value" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;margin-left:8px;"> 2030 <label style="font-size:11px;display:flex;align-items:center;gap:4px;margin-left:8px;white-space:nowrap;"> 2031 <input type="checkbox" id="secrets-custom-is-secret" checked> Secret 2032 </label> 2033 <button class="admin-btn-add" id="secrets-custom-add-btn" style="margin-left:8px;white-space:nowrap;">Add</button> 2034 </div>
2035 <span id="secrets-custom-msg" style="font-size:11px;"></span> 2036 </div> 2037 2038 <!-- Space secrets list (HF Spaces only) --> 2039 <div class="admin-card" id="secrets-space-actions" style="display:none;"> 2040 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>Space Secrets</h2> 2041 <div class="admin-toggle-sub" style="margin-bottom:8px"> 2042 Secrets currently set on this HF Space. Deleting a secret triggers a restart. 2043 </div> 2044 <div class="settings-row" style="align-items:center;margin-bottom:8px;"> 2045 <button class="admin-btn-add" id="secrets-space-refresh-btn" style="font-size:11px;">Refresh</button> 2046 <span id="secrets-space-msg" style="font-size:11px;margin-left:8px;"></span> 2047 </div> 2048 <div id="secrets-space-list" style="max-height:200px;overflow-y:auto;font-size:11px;border:1px solid var(--border);border-radius:4px;"></div> 2049 </div> 2050 2051 <!-- Secret editor modal --> 2052 <div id="secrets-editor-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:10000;display:none;align-items:center;justify-content:center;"> 2053 <div style="background:var(--bg-panel,var(--bg));border:1px solid var(--border);border-radius:8px;padding:20px;width:400px;max-width:90vw;box-shadow:0 8px 32px rgba(0,0,0,0.3);"> 2054 <h3 style="font-size:13px;margin:0 0 12px;">Set Secret Value</h3> 2055 <div style="margin-bottom:8px;"> 2056 <label style="font-size:10px;opacity:0.6;display:block;margin-bottom:4px;">Key</label> 2057 <input id="secrets-editor-key" type="text" readonly style="width:100%;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:monospace;font-size:12px;opacity:0.7;"> 2058 </div> 2059 <div style="margin-bottom:8px;"> 2060 <label style="font-size:10px;opacity:0.6;display:block;margin-bottom:4px;">Value</label> 2061 <div style="display:flex;gap:6px;"> 2062 <input id="secrets-editor-value" type="password" placeholder="Enter value..." style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 2063 <button id="secrets-editor-toggle" style="padding:6px 10px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-size:10px;cursor:pointer;">Show</button> 2064 </div> 2065 </div> 2066 <div style="margin-bottom:12px;"> 2067 <label style="font-size:11px;display:flex;align-items:center;gap:4px;"> 2068 <input type="checkbox" id="secrets-editor-is-secret" checked> Mark as secret (masked in HF Spaces UI) 2069 </label> 2070 </div> 2071 <div class="settings-row" style="justify-content:flex-end;gap:8px;"> 2072 <button id="secrets-editor-cancel" style="padding:6px 14px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;cursor:pointer;">Cancel</button> 2073 <button class="admin-btn-add" id="secrets-editor-save" style="padding:6px 14px;font-size:12px;">Save</button> 2074 </div> 2075 <span id="secrets-editor-msg" style="font-size:11px;display:block;margin-top:8px;"></span> 2076 </div> 2077 </div> 2078 </div> 2079 2080 <!-- âââ GITHUB TAB âââ --> 2081 <div data-settings-panel="github" class="hidden"> 2082 <div class="admin-card"> 2083 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>GitHub Integration</h2> 2084 <div class="admin-toggle-sub" style="margin-bottom:12px"> 2085 Connect your GitHub account to manage repositories directly from Odysseus. Create, publish, and delete repos â all from the UI. 2086 </div> 2087 2088 <!-- Auth section (shown when not connected) --> 2089 <div id="gh-auth-section" style="margin-bottom:8px;"> 2090 <div class="settings-col"> 2091 <div class="admin-toggle-sub" style="margin-bottom:8px;"> 2092 To get started, you need to create a <a href="https://github.com/settings/developers" target="_blank" rel="noopener" style="color:var(--brand-color,var(--red,#e06c75));">GitHub OAuth App</a> and set the <code>GITHUB_CLIENT_ID</code> and <code>GITHUB_CLIENT_SECRET</code> environment variables. The callback URL should be <code>{your-odysseus-url}/api/github/oauth/callback</code>. 2093 </div> 2094 <button class="admin-btn-add" id="gh-auth-connect" style="display:inline-flex;align-items:center;gap:6px;"> 2095 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></svg> 2096 Connect GitHub Account 2097 </button>
2098 <span id="gh-auth-msg" style="font-size:11px;margin-left:8px;"></span> 2099 </div> 2100 </div> 2101 2102 <!-- Connected section (shown when authenticated) --> 2103 <div id="gh-connected-section" style="display:none;"> 2104 <div id="gh-user-info" style="font-size:11px;margin-bottom:8px;"></div> 2105 <div class="settings-row" style="align-items:center;"> 2106 <span id="gh-rate-limit" style="font-size:10px;opacity:0.5;flex:1;"></span> 2107 <button id="gh-disconnect-btn" style="background:color-mix(in srgb, var(--color-error) 10%, transparent);border:1px solid var(--color-error);border-radius:6px;padding:4px 10px;color:var(--color-error);font-family:inherit;font-size:11px;font-weight:500;cursor:pointer;">Disconnect</button> 2108 <span id="gh-connected-msg" style="font-size:11px;margin-left:8px;"></span> 2109 </div> 2110 </div> 2111 </div> 2112 2113 <div class="admin-card" id="gh-config-card" style="opacity:0.5;pointer-events:none;"> 2114 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>Repositories</h2> 2115 <div class="settings-col"> 2116 <div class="settings-row" style="align-items:center;margin-bottom:8px;"> 2117 <button class="admin-btn-add" id="gh-refresh-repos-btn" style="font-size:11px;">Refresh</button> 2118 <span id="gh-repos-msg" style="font-size:11px;margin-left:8px;"></span> 2119 </div> 2120 <div id="gh-repos-list" style="max-height:250px;overflow-y:auto;font-size:11px;border:1px solid var(--border);border-radius:4px;"></div> 2121 </div> 2122 2123 <div style="border-top:1px solid var(--border);padding-top:10px;margin-top:10px;"> 2124 <div style="font-size:12px;font-weight:500;margin-bottom:8px;">Create New Repository</div> 2125 <div class="settings-row" style="align-items:center;margin-bottom:6px;"> 2126 <input id="gh-new-repo-name" type="text" placeholder="my-awesome-project" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 2127 <label style="font-size:11px;display:flex;align-items:center;gap:4px;margin-left:8px;"> 2128 <input type="checkbox" id="gh-new-repo-private" checked> Private 2129 </label> 2130 <button class="admin-btn-add" id="gh-create-repo-btn" style="margin-left:8px;white-space:nowrap;">Create</button> 2131 </div> 2132 <input id="gh-new-repo-desc" type="text" placeholder="Repository description (optional)" style="width:100%;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;margin-bottom:4px;"> 2133 <span id="gh-repo-msg" style="font-size:11px;"></span> 2134 </div> 2135 </div> 2136 2137 <div class="admin-card" id="gh-publish-card" style="opacity:0.5;pointer-events:none;"> 2138 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M12 12v9"/><path d="m8 17 4 4 4-4"/></svg>Publish Project</h2> 2139 <div class="admin-toggle-sub" style="margin-bottom:8px"> 2140 Push your Odysseus workspace configuration to a new GitHub repository for backup and sharing. 2141 </div> 2142 <div class="settings-row" style="align-items:center;"> 2143 <input id="gh-publish-repo-name" type="text" placeholder="my-odysseus-config" style="flex:1;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg);font-family:inherit;font-size:12px;"> 2144 <button class="admin-btn-add" id="gh-publish-btn" style="margin-left:8px;white-space:nowrap;">Publish</button>
2145 <span id="gh-publish-msg" style="font-size:11px;margin-left:8px;"></span> 2146 </div> 2147 </div> 2148 </div> 2149 2150 <!-- âââ EMAIL TAB âââ --> 2151 <div data-settings-panel="email" class="hidden"> 2152 <div class="admin-card"> 2153 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg>Email Accounts</h2> 2154 <div class="settings-row" style="align-items:center;"> 2155 <div class="admin-toggle-sub" style="margin:0;flex:1;">Add, edit, delete, and test accounts in Integrations.</div> 2156 <button class="admin-btn-add" id="set-email-open-integrations" style="display:inline-flex;align-items:center;gap:6px;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="opacity:0.7"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>Manage in Integrations</button> 2157 </div> 2158 </div> 2159 2160 <div class="admin-card"> 2161 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/><path d="M9 16l2 2 4-4"/></svg>Email Tasks</h2> 2162 <div class="settings-row" style="align-items:center;"> 2163 <div class="admin-toggle-sub" style="margin:0;flex:1;">Manage email background tasks in Tasks.</div> 2164 <button class="admin-btn-add" id="set-email-open-tasks" style="display:inline-flex;align-items:center;gap:6px;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="opacity:0.7"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/><path d="M9 16l2 2 4-4"/></svg>Open Tasks</button> 2165 </div> 2166 </div> 2167 2168 <div class="admin-card"> 2169 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>Writing Style</h2> 2170 <div class="admin-toggle-sub" style="margin-bottom:8px">AI-extracted from your sent emails. Used when AI drafts replies.</div> 2171 <div class="settings-col"> 2172 <textarea id="set-email-style" rows="4" class="settings-select" style="font-family:inherit;resize:vertical" placeholder="e.g. I write emails in this style. I don't use exclamation marks. I sign emails with: ..."></textarea> 2173 <div class="settings-row" style="margin-top:4px"> 2174 <span id="set-email-style-msg" style="font-size:11px;"></span> 2175 <button class="admin-btn-add" id="set-email-style-extract" style="margin-left:auto;">Extract from Sent (15 emails)</button> 2176 <button class="admin-btn-add" id="set-email-style-save">Save</button> 2177 </div> 2178 </div> 2179 </div> 2180 </div> 2181 2182 <!-- âââ REMINDERS TAB âââ --> 2183 <div data-settings-panel="reminders" class="hidden"> 2184 <div class="admin-card"> 2185 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>How you're reminded</h2> 2186 <div class="admin-toggle-sub" style="margin-bottom:8px">Controls how fired note reminders are delivered.</div> 2187 <div class="settings-col"> 2188 <div class="settings-row"> 2189 <label class="settings-label">Channel</label> 2190 <select id="set-reminder-channel" class="settings-select"> 2191 <option value="browser">Browser notification (default)</option> 2192 <option value="email" id="set-reminder-channel-email-opt">Email</option> 2193 <option value="ntfy" id="set-reminder-channel-ntfy-opt">ntfy</option> 2194 <option value="webhook" id="set-reminder-channel-webhook-opt">Webhook</option> 2195 </select> 2196 </div> 2197 <div id="set-reminder-email-from-row" class="settings-row" style="display:none"> 2198 <label class="settings-label">Send from</label> 2199 <select id="set-reminder-email-account" class="settings-select"></select> 2200 </div> 2201 <div id="set-reminder-email-to-row" class="settings-row" style="display:none"> 2202 <label class="settings-label">Send to</label> 2203 <input id="set-reminder-email-to" class="settings-select" type="email" placeholder="[email protected]" /> 2204 </div> 2205 <div id="set-reminder-ntfy-topic-row" class="settings-row" style="display:none"> 2206 <label class="settings-label">ntfy topic</label> 2207 <input id="set-reminder-ntfy-topic" class="settings-select" type="text" placeholder="reminders" /> 2208 </div> 2209 <div id="set-reminder-webhook-intg-row" class="settings-row" style="display:none"> 2210 <label class="settings-label">Integration</label> 2211 <select id="set-reminder-webhook-intg" class="settings-select"></select> 2212 </div> 2213 <div id="set-reminder-webhook-template-row" class="settings-row" style="display:none;align-items:flex-start"> 2214 <label class="settings-label" style="padding-top:6px">Payload</label> 2215 <textarea id="set-reminder-webhook-template" class="settings-select" rows="3" style="font-family:inherit;resize:vertical;flex:1" placeholder='{"content": "{{title}}: {{message}}"}'></textarea> 2216 </div> 2217 <div id="set-reminder-channel-hint" style="font-size:11px;opacity:0.6;"></div> 2218 <div style="font-size:11px;opacity:0.6;margin-top:4px;">Configure email account, ntfy server, etc. in <a href="#" id="set-reminders-open-integrations" style="color:var(--accent, var(--red));text-decoration:none;font-weight:600;">Integrations</a>.</div> 2219 </div> 2220 </div> 2221 <div class="admin-card"> 2222 <h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:1px;opacity:0.6;flex-shrink:0"><path d="M12 0L14.59 8.41L23 12L14.59 15.59L12 24L9.41 15.59L1 12L9.41 8.41Z"/></svg>AI Synthesis<span style="flex:1"></span><label class="admin-switch" title="Use the utility model to write reminder messages"><input type="checkbox" id="set-reminder-llm-toggle">
2222<span class="admin-slider"></span></label></h2> 2223 <div class="admin-toggle-sub" style="margin-bottom:8px">When on, the utility model writes a short, warm one-line reminder for browser, email, ntfy, AND webhook reminders instead of just the raw note content.</div> 2224 </div> 2225 <div class="admin-card"> 2226 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>Public App URL</h2> 2227 <div class="admin-toggle-sub" style="margin-bottom:8px">Used to build clickable links back to Odysseus inside outgoing reminder / urgent-email emails (e.g. <code>https://chat.yourdomain.com</code>). Leave blank to omit links.</div> 2228 <div class="settings-col"> 2229 <div class="settings-row"> 2230 <label class="settings-label">URL</label> 2231 <input id="set-app-public-url" class="settings-select" type="url" placeholder="https://chat.example.com" style="flex:1;" /> 2232 </div> 2233 <div id="set-app-public-url-msg" style="font-size:11px;color:color-mix(in srgb, var(--fg) 55%, transparent);"></div> 2234 </div> 2235 </div> 2236 <div class="admin-card"> 2237 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>Test</h2> 2238 <div class="admin-toggle-sub" style="margin-bottom:8px">Fire a test reminder using your current settings to verify everything works.</div> 2239 <div class="settings-row"> 2240 <span id="set-reminder-test-msg" style="font-size:11px;"></span> 2241 <button class="admin-btn-add" id="set-reminder-test-btn" style="margin-left:auto;">Send Test Reminder</button> 2242 </div> 2243 </div> 2244 </div> 2245 2246 <!-- âââ ADMIN: USERS TAB âââ --> 2247 <div data-settings-panel="users" class="hidden"> 2248 <div class="admin-card"> 2249 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="8.5" cy="7" r="4"/><line x1="20" y1="8" x2="20" y2="14"/><line x1="23" y1="11" x2="17" y2="11"/></svg>Registration</h2> 2250 <div class="admin-toggle-row"> 2251 <div> 2252 <div class="admin-toggle-label">Open signup</div> 2253 <div class="admin-toggle-sub">Allow anyone to create an account from the login page</div> 2254 </div> 2255 <label class="admin-switch"><input type="checkbox" id="adm-signupToggle"><span class="admin-slider"></span></label> 2256 </div> 2257 </div> 2258 <div class="admin-card"> 2259 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>Users</h2> 2260 <div id="adm-userList"><div class="admin-empty">Loading...</div></div> 2261 </div> 2262 <div class="admin-card"> 2263 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="8.5" cy="7" r="4"/><line x1="20" y1="8" x2="20" y2="14"/><line x1="23" y1="11" x2="17" y2="11"/></svg>Add User</h2> 2264 <div class="admin-add-form"> 2265 <input id="adm-newUsername" type="text" placeholder="Username (email)"> 2266 <input id="adm-newPassword" type="password" placeholder="Password (min 8)"> 2267 <div class="admin-switch-inline" title="Grant full admin access"><label class="admin-switch"><input type="checkbox" id="adm-newIsAdmin">
2267<span class="admin-slider"></span></label> Admin</div> 2268 </div> 2269 <div class="settings-row" style="margin-top:6px;"> 2270 <button class="admin-btn-add" id="adm-addBtn">Add User</button> 2271 <span id="adm-addMsg" style="font-size:11px"></span> 2272 </div> 2273 </div> 2274 </div> 2275 2276 <!-- âââ SERVICES TAB âââ --> 2277 <div data-settings-panel="services"> 2278 <div class="admin-card"> 2279 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><circle cx="6" cy="6" r="1"/><circle cx="6" cy="18" r="1"/></svg>Add Models <span style="opacity:0.45;font-weight:normal;font-size:0.82em">(Endpoints)</span></h2> 2280 <div class="admin-toggle-sub" style="margin-bottom:10px">Connect local models first, or add a cloud API.</div> 2281 2282 <!-- Local subsection --> 2283 <div class="adm-add-section collapsible collapsed" id="adm-add-local"> 2284 <div class="adm-ep-section-head adm-section-toggle" role="button" tabindex="0" aria-expanded="false">
2285 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:4px;"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/></svg> 2286 <span>Local</span> 2287 <svg class="adm-section-caret" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg> 2288 </div> 2289 <div class="admin-model-form"> 2290 <div class="admin-model-form-row"> 2291 <input id="adm-epLocalUrl" type="text" placeholder="Paste endpoint URL, e.g. http://localhost:11434/v1" style="flex:1"> 2292 <select id="adm-epLocalType" style="padding:5px;width:72px;flex-shrink:0;"> 2293 <option value="llm">LLM</option> 2294 <option value="image">Image</option> 2295 </select> 2296 </div> 2297 <div class="admin-model-form-row"> 2298 <input id="adm-epLocalApiKey" type="password" placeholder="API key (optional â for protected local endpoints)" autocomplete="off" style="flex:1"> 2299 </div> 2300 <div class="admin-model-form-row"> 2301 <span style="flex:1"></span> 2302 <button class="admin-btn-sm" id="adm-epLocalTestBtn" style="width:55px;text-align:center;">Test</button> 2303 <button class="admin-btn-add" id="adm-epLocalAddBtn" style="width:55px;text-align:center;">Add</button> 2304 </div> 2305 <div class="adm-quickstart-section collapsed" id="adm-add-local-quickstart"> 2306 <div class="adm-quickstart-toggle" role="button" tabindex="0" aria-expanded="false"> 2307 <span>Quickstart</span> 2308 <svg class="adm-section-caret" width="11" height="11" viewB
2308ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg> 2309 </div> 2310 <div class="adm-quickstart-body"> 2311 <button class="admin-btn-sm" id="adm-epDiscoverBtn" title="Scan your network for running model servers"> 2312 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" style="vertical-align:-1px;margin-right:4px;"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>Scan for Servers 2313 </button> 2314 <button class="admin-btn-sm" id="adm-epOllamaBtn" title="Fill the default Ollama endpoint">Ollama</button> 2315 </div> 2316 </div> 2317 <div id="adm-epLocalMsg" class="adm-ep-inline-msg"></div> 2318 </div> 2319 </div> 2320 2321 <!-- API subsection --> 2322 <div class="adm-add-section collapsible collapsed" id="adm-add-api" style="margin-top:14px"> 2323 <div class="adm-ep-section-head adm-section-toggle" role="button" tabindex="0" aria-expanded="false">
2324 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:4px;"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg> 2325 <span>API</span> 2326 <svg class="adm-section-caret" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg> 2327 </div> 2328 <div class="admin-model-form"> 2329 <!-- Custom picker (with logos). Hidden native <select> mirrors 2330 its value so the existing JS that reads adm-epProvider 2331 keeps working unchanged. --> 2332 <div class="adm-provider-picker adm-provider-combo" id="adm-provider-picker"> 2333 <input id="adm-epUrl" type="text" placeholder="Base URL or pick provider" autocomplete="off"> 2334 <button type="button" class="adm-provider-btn" id="adm-provider-btn" title="Pick provider"> 2335 <span class="adm-provider-current"><span class="adm-provider-logo"></span><span class="adm-provider-name">Provider</span></span> 2336 <svg class="adm-provider-caret" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg> 2337 </button> 2338 <div class="adm-provider-menu hidden" id="adm-provider-menu"></div> 2339 </div> 2340 <select id="adm-epProvider" style="display:none"> 2341 <option value="">Custom URL</option> 2342 <option value="https://api.anthropic.com" data-logo="anthropic">Anthropic</option> 2343 <option value="https://api.deepseek.com/v1" data-logo="deepseek" selected>DeepSeek</option> 2344 <option value="https://api.openai.com/v1" data-logo="openai">OpenAI</option> 2345 <option value="https://openrouter.ai/api/v1" data-logo="openrouter">OpenRouter</option> 2346 <option value="https://ollama.com/api" data-logo="ollama">Ollama Cloud</option> 2347 <option value="https://api.groq.com/openai/v1" data-logo="groq">Groq</option> 2348 <option value="https://api.mistral.ai/v1" data-logo="mistral">Mistral</option> 2349 <option value="https://api.together.xyz/v1" data-logo="together">Together AI</option> 2350 <option value="https://api.fireworks.ai/inference/v1" data-logo="fireworks">Fireworks AI</option> 2351 <option value="https://generativelanguage.googleapis.com/v1beta/openai" data-logo="gemini">Google Gemini</option> 2352 <option value="https://api.x.ai/v1" data-logo="grok">xAI Grok</option> 2353 <option value="https://api.z.ai/api/paas/v4" data-logo="zhipu">Z.AI (Zhipu)</option> 2354 <option value="https://api.z.ai/api/coding/paas/v4" data-logo="zhipu">Z.AI Coding Plan</option> 2355 </select> 2356 <div class="admin-model-form-row"> 2357 <input id="adm-epApiKey" type="password" placeholder="API key"> 2358 <select id="adm-epKind" style="padding:5px;width:82px;"> 2359 <option value="proxy">Proxy</option> 2360 <option value="api">API</option> 2361 </select> 2362 <select id="adm-epType" style="padding:5px;width:80px;"> 2363 <option value="llm">LLM</option> 2364 <option value="image">Image</option> 2365 </select> 2366 <button class="admin-btn-sm" id="adm-epApiTestBtn" style="width:55px;text-align:center;">Test</button> 2367 <button class="admin-btn-sm hidden" id="adm-epApiCancelTestBtn" style="width:62px;text-align:center;">Cancel</button> 2368 <button class="admin-btn-add" id="adm-epAddBtn" style="width:55px;text-align:center;">Add</button> 2369 </div> 2370 <div id="adm-epApiMsg" class="adm-ep-inline-msg"></div> 2371 </div> 2372 </div> 2373 </div> 2374 <div class="admin-card"> 2375 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>Added Models <span style="opacity:0.45;font-weight:normal;font-size:0.82em">(Endpoints)</span></h2> 2376 <div class="admin-toggle-sub" style="margin-bottom:10px">Manage the endpoints you've added.</div> 2377 <div class="adm-ep-section"> 2378 <div class="adm-ep-section-head">
2379 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:4px;"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/></svg> 2380 <span>Local</span> 2381 </div> 2382 <div id="adm-epList-local"><div class="admin-empty">Loading...</div></div> 2383 </div> 2384 <div class="adm-ep-section" style="margin-top:14px"> 2385 <div class="adm-ep-section-head"> 2386 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-1px;margin-right:4px;"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg> 2387 <span>API</span> 2388 </div> 2389 <div id="adm-epList-api"></div> 2390 </div> 2391 </div> 2392 </div> 2393 2394 <!-- âââ TOOLS TAB âââ --> 2395 <!-- âââ INTEGRATIONS TAB âââ --> 2396 <div data-settings-panel="integrations" class="hidden"> 2397 <div class="admin-card"> 2398 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>Integrations</h2> 2399 <div class="admin-toggle-sub" style="margin-bottom:8px">All external service connections in one place.</div> 2400 <div id="unified-integrations-list"></div> 2401 <div id="unified-intg-form" style="display:none"></div> 2402 <div style="text-align:center;padding:8px 0;"> 2403 <button type="button" class="admin-btn-sm" id="unified-intg-add-btn" style="display:inline-flex;align-items:center;gap:6px;">+ Add Integration<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="opacity:0.7;"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></button> 2404 </div> 2405 </div> 2406 </div> 2407 2408 <!-- âââ TOOLS TAB âââ --> 2409 <div data-settings-panel="tools" class="hidden"> 2410 <div class="admin-card" style="margin-bottom:12px;"> 2411 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>Built-in Tools</h2> 2412 <div class="admin-toggle-sub" style="margin-bottom:8px">Enable or disable tools available to the AI agent.</div> 2413 <div id="adm-builtin-tools-list" class="admin-user-list"></div> 2414 </div> 2415 </div> 2416 2417 <!-- âââ SYSTEM TAB âââ --> 2418 <div data-settings-panel="system" class="hidden"> 2419 2420 <div class="admin-card"> 2421 <h2><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:5px;opacity:0.6"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Data Backup</h2> 2422 <div class="admin-toggle-sub" style="margin-bottom:8px">Export or import your user data (memories, presets, settings, skills, preferences) as a JSON file.</div> 2423 <div style="display:flex;gap:8px;flex-wrap:wrap;"> 2424 <button class="admin-btn-add" id="adm-exportDataBtn">Export Data</button> 2425 <button class="admin-btn-add" id="adm-importDataBtn">Import Data</button> 2426 <input type="file" id="adm-importFile" accept=".json" style="display:none;"> 2427 </div> 2428 <div id="adm-backupMsg" style="margin-top:6px;"></div> 2429 </div> 2430 <div class="admin-card admin-danger-card"> 2431 <h2 style="color:#e55;">Danger Zone</h2> 2432 <div class="admin-toggle-sub" style="margin-bottom:8px">Irreversible. Each wipe targets one category â pick exactly what you want gone.</div> 2433 2434 <div style="display:flex;justify-content:space-between;align-items:center;"> 2435 <div> 2436 <div class="admin-toggle-label">Wipe all chats</div> 2437 <div class="admin-toggle-sub">Every session, message, and chat history. Documents/notes/etc. stay.</div> 2438 </div> 2439 <button class="admin-btn-delete" data-wipe-kind="chats" style="white-space:nowrap;">Wipe</button> 2440 </div> 2441 2442 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2443 <div> 2444 <div class="admin-toggle-label">Wipe all memory</div> 2445 <div class="admin-toggle-sub">Clears `memory.json`, the Memory table, and the vector store. Skills not affected.</div> 2446 </div> 2447 <button class="admin-btn-delete" data-wipe-kind="memory" style="white-space:nowrap;">Wipe</button> 2448 </div> 2449 2450 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2451 <div> 2452 <div class="admin-toggle-label">Wipe all skills</div> 2453 <div class="admin-toggle-sub">Drops `data/skills/` (all SKILL.md files). Memory not affected.</div> 2454 </div> 2455 <button class="admin-btn-delete" data-wipe-kind="skills" style="white-space:nowrap;">Wipe</button> 2456 </div> 2457 2458 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2459 <div> 2460 <div class="admin-toggle-label">Wipe all notes</div> 2461 <div class="admin-toggle-sub">Every note, todo, and checklist.</div> 2462 </div> 2463 <button class="admin-btn-delete" data-wipe-kind="notes" style="white-space:nowrap;">Wipe</button> 2464 </div> 2465 2466 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2467 <div> 2468 <div class="admin-toggle-label">Wipe all tasks</div> 2469 <div class="admin-toggle-sub">Every scheduled task and its run history (Tasks tool).</div> 2470 </div> 2471 <button class="admin-btn-delete" data-wipe-kind="tasks" style="white-space:nowrap;">Wipe</button> 2472 </div> 2473 2474 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2475 <div> 2476 <div class="admin-toggle-label">Wipe all documents</div> 2477 <div class="admin-toggle-sub">Every document and version. Drafts, exports, library â all gone.</div> 2478 </div> 2479 <button class="admin-btn-delete" data-wipe-kind="documents" style="white-space:nowrap;">Wipe</button> 2480 </div> 2481 2482 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2483 <div> 2484 <div class="admin-toggle-label">Wipe all gallery</div> 2485 <div class="admin-toggle-sub">Every image record and the upload directory on disk.</div> 2486 </div> 2487 <button class="admin-btn-delete" data-wipe-kind="gallery" style="white-space:nowrap;">Wipe</button> 2488 </div> 2489 2490 <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;"> 2491 <div> 2492 <div class="admin-toggle-label">Wipe all calendar</div> 2493 <div class="admin-toggle-sub">Every event and every calendar (incl. CalDAV-synced ones; resync to restore).</div> 2494 </div> 2495 <button class="admin-btn-delete" data-wipe-kind="calendar" style="white-space:nowrap;">Wipe</button> 2496 </div> 2497 2498 <div id="adm-wipeMsg" style="margin-top:8px;"></div> 2499 </div> 2500 </div> 2501 2502 </div> 2503 </div> 2504 </div> 2505 </div> 2506 2507 <!-- Search overlay (Ctrl+K command palette) --> 2508 <div class="search-overlay hidden" id="search-overlay"> 2509 <div class="search-popup"> 2510 <input type="text" id="search-input" placeholder="Search conversations..." autocomplete="off" /> 2511 <div class="search-results" id="search-results"></div> 2512 </div> 2513 </div> 2514 2515 <!-- Toast container (aria-live for screen readers) -->
2516 <div id="toast" class="toast" role="status" aria-live="polite"></div> 2517 2518 2519 2520<!-- Load modules in this order -->
2521<script type="module" src="/static/js/storage.js"></script>
vendor: 1 bytes, line 2521
2521
2522<script type="module" src="/static/js/ui.js"></script>
vendor: 1 bytes, line 2522
2522
2523<script type="module" src="/static/js/markdown.js"></script>
vendor: 1 bytes, line 2523
2523
2524<script type="module" src="/static/js/dragSort.js"></script>
vendor: 1 bytes, line 2524
2524
2525<script type="module" src="/static/js/sessions.js"></script>
vendor: 1 bytes, line 2525
2525
2526<script type="module" src="/static/js/memory.js"></script>
vendor: 1 bytes, line 2526
2526
2527<script type="module" src="/static/js/skills.js"></script>
vendor: 1 bytes, line 2527
2527
2528<script type="module" src="/static/js/tourHints.js"></script>
vendor: 1 bytes, line 2528
2528
2529<script type="module" src="/static/js/tourAutoplay.js"></script>
vendor: 1 bytes, line 2529
2529
2530<script type="module" src="/static/js/fileHandler.js"></script>
vendor: 1 bytes, line 2530
2530
2531<script type="module" src="/static/js/voiceRecorder.js"></script>
vendor: 1 bytes, line 2531
2531
2532<script type="module" src="/static/js/models.js"></script>
2532 <!-- This must come BEFORE app.js -->
2533<script type="module" src="/static/js/rag.js"></script>
vendor: 1 bytes, line 2533
2533
2534<script type="module" src="/static/js/presets.js"></script>
vendor: 1 bytes, line 2534
2534
2535<script type="module" src="/static/js/search.js"></script>
vendor: 1 bytes, line 2535
2535
2536<script type="module" src="/static/js/spinner.js"></script>
vendor: 1 bytes, line 2536
2536
2537<script type="module" src="/static/js/tts-ai.js"></script>
vendor: 1 bytes, line 2537
2537
2538<script type="module" src="/static/js/document.js"></script>
vendor: 1 bytes, line 2538
2538
2539<script type="module" src="/static/js/gallery.js"></script>
vendor: 1 bytes, line 2539
2539
2540<script type="module" src="/static/js/chatRenderer.js"></script>
vendor: 1 bytes, line 2540
2540
2541<script type="module" src="/static/js/codeRunner.js"></script>
vendor: 1 bytes, line 2541
2541
2542<script type="module" src="/static/js/chatStream.js"></script>
vendor: 1 bytes, line 2542
2542
2543<script type="module" src="/static/js/chat.js?v=20260604s"></script>
vendor: 1 bytes, line 2543
2543
2544<script type="module" src="/static/js/cookbook.js"></script>
vendor: 1 bytes, line 2544
2544
2545<script src="/static/js/cookbookSchedule.js"></script>
vendor: 1 bytes, line 2545
2545
2546<script type="module" src="/static/js/search-chat.js"></script>
vendor: 1 bytes, line 2546
2546
2547<script type="module" src="/static/js/compare/index.js"></script>
vendor: 1 bytes, line 2547
2547
2548<script type="module" src="/static/js/theme.js"></script>
vendor: 1 bytes, line 2548
2548
2549<script type="module" src="/static/js/censor.js"></script>
vendor: 1 bytes, line 2549
2549
2550<script type="module" src="/static/js/settings.js"></script>
vendor: 1 bytes, line 2550
2550
2551<script type="module" src="/static/js/hfBuckets.js"></script>
vendor: 1 bytes, line 2551
2551
2552<script type="module" src="/static/js/hfSecrets.js"></script>
vendor: 1 bytes, line 2552
2552
2553<script type="module" src="/static/js/githubRepos.js"></script>
vendor: 1 bytes, line 2553
2553
2554<script type="module" src="/static/js/admin.js"></script>
vendor: 1 bytes, line 2554
2554
2555<script type="module" src="/static/js/assistant.js"></script>
vendor: 1 bytes, line 2555
2555
2556<script type="module" src="/static/app.js"></script>
2556 <!-- app.js must be LAST -->
2557<script type="module" src="/static/js/init.js"></script>
vendor: 1 bytes, line 2557
2557
2558<script type="module" src="/static/js/a11y.js"></script>
vendor: 1 bytes, line 2558
2558
2559<script nonce="0ef1c0e2ced0cc537d6ee0258e679162">if('serviceWorker' in navigator){navigator.serviceWorker.register('/static/sw.js').catch(()=>{});}</script>
2559 2560</body> 2561</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.