omnius 1.0.320 → 1.0.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -682806,8 +682806,8 @@ function getWebUI() {
682806
682806
  --color-border-strong:oklch(0.32 0 0); /* emphasized — gray-800 */
682807
682807
 
682808
682808
  /* Functional accents (openwebui pattern: blue for actions, sparing) */
682809
- --color-accent: #3b82f6; /* blue-500 — primary actions */
682810
- --color-accent-hover: #60a5fa; /* blue-400 */
682809
+ --color-accent: #14b8a6; /* teal-500 — primary actions */
682810
+ --color-accent-hover: #2dd4bf; /* teal-400 */
682811
682811
  --color-success: #22c55e; /* green-500 */
682812
682812
  --color-warning: #f59e0b; /* amber-500 */
682813
682813
  --color-error: #ef4444; /* red-500 */
@@ -682815,8 +682815,8 @@ function getWebUI() {
682815
682815
 
682816
682816
  /* Omnius brand — kept narrow scope for Omnius-only marks (active tab strip,
682817
682817
  * brand glyphs, status accents). NOT the dominant accent anymore. */
682818
- --color-brand: #b2920a;
682819
- --color-brand-hover: #d4ac0e;
682818
+ --color-brand: #14b8a6;
682819
+ --color-brand-hover: #2dd4bf;
682820
682820
 
682821
682821
  /* Typography */
682822
682822
  --font-ui: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
@@ -683071,7 +683071,7 @@ body {
683071
683071
  }
683072
683072
  #tasks-row .task-item.pending { color: var(--color-fg-faint); }
683073
683073
  #tasks-row .task-item.pending .mark { color: var(--color-fg-faint); }
683074
- #tasks-row .task-item.in_progress { color: var(--color-brand); border-color: var(--color-brand); box-shadow: 0 0 4px rgba(178,146,10,0.3); }
683074
+ #tasks-row .task-item.in_progress { color: var(--color-brand); border-color: var(--color-brand); box-shadow: 0 0 4px rgba(20,184,166,0.3); }
683075
683075
  #tasks-row .task-item.in_progress .mark { color: var(--color-brand); }
683076
683076
  #tasks-row .task-item.completed { color: #4a7a4a; }
683077
683077
  #tasks-row .task-item.completed .mark { color: #5fa55f; }
@@ -684047,7 +684047,8 @@ body { display:flex; flex-direction:column; height:100vh; margin:0; overflow:hid
684047
684047
  <button id="sidebar-toggle" onclick="toggleSidebar()" title="Toggle sidebar (Cmd/Ctrl+B)" style="background:transparent;border:none;color:var(--color-fg-muted);padding:4px;border-radius:var(--radius-sm);cursor:pointer;display:flex;align-items:center;justify-content:center;width:28px;height:28px">
684048
684048
  <svg width="18" height="18" 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 3v18"/></svg>
684049
684049
  </button>
684050
- <span id="sidebar-brand" style="font-weight:600;font-size:0.92rem;color:var(--color-fg);letter-spacing:-0.01em;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Omnius</span>
684050
+ <span id="sidebar-brand-dot" title="Connection status" style="width:9px;height:9px;border-radius:999px;background:#f59e0b;box-shadow:0 0 0 2px rgba(245,158,11,.16);flex:0 0 auto"></span>
684051
+ <span id="sidebar-brand" style="font-weight:600;font-size:0.92rem;color:var(--color-fg);letter-spacing:-0.01em;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">No project</span>
684051
684052
  </div>
684052
684053
 
684053
684054
  <!-- New chat button -->
@@ -684133,9 +684134,9 @@ body { display:flex; flex-direction:column; height:100vh; margin:0; overflow:hid
684133
684134
  <div id="omnius-main" style="flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden;background:var(--color-bg)">
684134
684135
 
684135
684136
  <div id="header">
684136
- <span class="accent">Omnius</span>
684137
+ <span class="accent" id="header-project-name">No project</span>
684137
684138
  <span class="status" id="status">connecting...</span>
684138
- <span id="update-btn" style="display:none;background:#3a2a10;border:1px solid var(--color-brand);color:var(--color-brand);padding:2px 8px;border-radius:3px;font-family:inherit;font-size:0.6rem;cursor:pointer" onclick="doUpdate()">update</span>
684139
+ <span id="update-btn" style="display:none;background:#0f3f3d;border:1px solid var(--color-brand);color:var(--color-brand);padding:2px 8px;border-radius:3px;font-family:inherit;font-size:0.6rem;cursor:pointer" onclick="doUpdate()">update</span>
684139
684140
  <select id="model-select"><option>loading...</option></select>
684140
684141
  <button class="key-btn" id="files-btn" onclick="toggleFilesForActiveTab()" title="Toggle workspace sidebar (chat or agent depending on active tab)">files</button>
684141
684142
  <button class="key-btn" id="sandbox-toggle" onclick="toggleSandbox()" title="Toggle Docker sandbox" style="opacity:0.5">sandbox: off</button>
@@ -684834,6 +684835,13 @@ $chatSessionId.subscribe(v => {
684834
684835
  const root = $currentProject.get()?.root;
684835
684836
  if (root) scopedSet(root, 'currentChatSessionId', v ?? '');
684836
684837
  schedulePrefsSave({ currentChatSessionId: v });
684838
+ try { if (typeof updateSessionSelect === 'function') updateSessionSelect(); } catch {}
684839
+ try {
684840
+ if (typeof _renderSidebarChats === 'function') {
684841
+ const search = document.getElementById('sidebar-search');
684842
+ _renderSidebarChats(search ? search.value : '');
684843
+ }
684844
+ } catch {}
684837
684845
  });
684838
684846
  $agentRunId.subscribe(v => {
684839
684847
  const root = $currentProject.get()?.root;
@@ -684855,6 +684863,8 @@ $activeTab.subscribe(v => {
684855
684863
  $currentProject.subscribe(async (proj) => {
684856
684864
  if (!proj || !proj.root) return;
684857
684865
  await migrateLegacyLocalStorage(proj.root);
684866
+ try { resetProjectWorkspace(proj.root); } catch {}
684867
+ try { renderProjectChrome(); } catch {}
684858
684868
  // Local hydrate
684859
684869
  const localModel = scopedGet(proj.root, 'selectedModel', '') || '';
684860
684870
  const localChat = scopedGet(proj.root, 'currentChatSessionId', '') || '';
@@ -684871,6 +684881,9 @@ $currentProject.subscribe(async (proj) => {
684871
684881
  if (initialGuiRoute.tab) $activeTab.set(initialGuiRoute.tab);
684872
684882
  else if (server?.activeTab) $activeTab.set(server.activeTab);
684873
684883
  else if (localTab) $activeTab.set(localTab);
684884
+ try { $chatSessions.set(loadScopedSessions()); } catch {}
684885
+ try { if (typeof updateSessionSelect === 'function') updateSessionSelect(); } catch {}
684886
+ try { renderProjectChrome(); } catch {}
684874
684887
  });
684875
684888
 
684876
684889
  // Backward-compat shims: legacy code reads "apiKey" and "chatSessionId"
@@ -684893,7 +684906,7 @@ Object.defineProperty(window, 'chatSessionId', {
684893
684906
  function loadScopedSessions() {
684894
684907
  const root = $currentProject.get()?.root;
684895
684908
  if (!root) {
684896
- try { return loadScopedSessions(); } catch { return {}; }
684909
+ try { return JSON.parse(localStorage.getItem('omnius-sessions') || '{}'); } catch { return {}; }
684897
684910
  }
684898
684911
  try { return JSON.parse(scopedGet(root, 'chatSessions', '{}')); } catch { return {}; }
684899
684912
  }
@@ -684908,7 +684921,7 @@ function saveScopedSessions(obj) {
684908
684921
  function loadScopedAgentRuns() {
684909
684922
  const root = $currentProject.get()?.root;
684910
684923
  if (!root) {
684911
- try { return loadScopedAgentRuns(); } catch { return {}; }
684924
+ try { return JSON.parse(localStorage.getItem('omnius-agent-runs') || '{}'); } catch { return {}; }
684912
684925
  }
684913
684926
  try { return JSON.parse(scopedGet(root, 'agentRuns', '{}')); } catch { return {}; }
684914
684927
  }
@@ -684937,6 +684950,56 @@ const modelSelect = document.getElementById('model-select');
684937
684950
  // because modelSelect already exists in the DOM at this point.
684938
684951
  modelSelect.addEventListener('change', () => persistSelectedModel());
684939
684952
  const statusEl = document.getElementById('status');
684953
+ let _connectionState = 'connecting';
684954
+ function _projectPathLeaf(path) {
684955
+ if (!path) return '';
684956
+ let trimmed = String(path);
684957
+ while (trimmed.length > 1 && trimmed.endsWith('/')) trimmed = trimmed.slice(0, -1);
684958
+ const parts = trimmed.split('/').filter(Boolean);
684959
+ return parts[parts.length - 1] || trimmed || path;
684960
+ }
684961
+ function _projectDisplayName(proj) {
684962
+ if (!proj) return 'No project';
684963
+ return proj.name || _projectPathLeaf(proj.root) || proj.root || 'Project';
684964
+ }
684965
+ function _endpointDisplayName(endpoint) {
684966
+ if (!endpoint) return '';
684967
+ try { return new URL(endpoint).host || endpoint; } catch { return String(endpoint); }
684968
+ }
684969
+ function renderProjectChrome() {
684970
+ const proj = $currentProject.get ? $currentProject.get() : null;
684971
+ const cfg = $config.get ? ($config.get() || {}) : {};
684972
+ const root = proj?.root || '';
684973
+ const name = _projectDisplayName(proj);
684974
+ const headerName = document.getElementById('header-project-name') || document.querySelector('#header .accent');
684975
+ if (headerName) {
684976
+ headerName.textContent = name;
684977
+ headerName.title = root || name;
684978
+ }
684979
+ const brand = document.getElementById('sidebar-brand');
684980
+ if (brand) {
684981
+ brand.textContent = name;
684982
+ brand.title = root || name;
684983
+ }
684984
+ if (statusEl) {
684985
+ const selected = ($selectedModel.get && $selectedModel.get()) || (modelSelect && modelSelect.value) || '';
684986
+ const endpointObj = cfg.endpoint || {};
684987
+ const endpoint = endpointObj.url || cfg.backendUrl || '';
684988
+ const endpointType = endpointObj.backendType || cfg.backendType || '';
684989
+ const endpointLabel = endpoint ? ((endpointType ? endpointType + ' ' : '') + _endpointDisplayName(endpoint)) : '';
684990
+ const bits = [String(_connectionState || 'connecting')];
684991
+ if (selected) bits.push(selected);
684992
+ if (endpointLabel) bits.push(endpointLabel);
684993
+ statusEl.textContent = bits.join(' · ');
684994
+ statusEl.title = [root, endpoint].filter(Boolean).join('\\n');
684995
+ statusEl.className = /connected|ready|online/i.test(_connectionState || '') ? 'status live' : 'status';
684996
+ }
684997
+ try { _syncSidebarStatus(); } catch {}
684998
+ }
684999
+ function setConnectionState(state) {
685000
+ _connectionState = state || 'connecting';
685001
+ renderProjectChrome();
685002
+ }
684940
685003
  let streaming = false;
684941
685004
  let messages = [];
684942
685005
  let chatAbortController = null; // for stop button
@@ -685045,8 +685108,7 @@ async function checkHealth() {
685045
685108
  try {
685046
685109
  const r = await fetch('/health', { cache: 'no-store' });
685047
685110
  const d = await r.json();
685048
- statusEl.textContent = 'connected (' + d.version + ')';
685049
- statusEl.className = 'status live';
685111
+ setConnectionState('connected');
685050
685112
  // Detect daemon version bump and refresh UI to new frontend bundle/state
685051
685113
  if (!seenVersion) {
685052
685114
  seenVersion = d.version || '';
@@ -685057,8 +685119,7 @@ async function checkHealth() {
685057
685119
  return;
685058
685120
  }
685059
685121
  } catch {
685060
- statusEl.textContent = 'disconnected';
685061
- statusEl.className = 'status';
685122
+ setConnectionState('disconnected');
685062
685123
  }
685063
685124
  }
685064
685125
 
@@ -685074,6 +685135,7 @@ async function loadModels() {
685074
685135
  fetch('/v1/models', { headers: headers() }).then(r => r.json()).catch(() => ({})),
685075
685136
  fetch('/v1/config', { headers: headers() }).then(r => r.json()).catch(() => ({})),
685076
685137
  ]);
685138
+ try { if (cfgResp && cfgResp.config) $config.set(cfgResp.config); renderProjectChrome(); } catch {}
685077
685139
  modelSelect.innerHTML = '';
685078
685140
  const list = Array.isArray(modelsResp.data) ? modelsResp.data : [];
685079
685141
  if (list.length === 0) {
@@ -685133,7 +685195,8 @@ async function loadModels() {
685133
685195
  const daemonModel = (cfgResp && cfgResp.config && cfgResp.config.model) || '';
685134
685196
  let cachedModel = '';
685135
685197
  try { cachedModel = localStorage.getItem('omnius.selectedModel') || ''; } catch {}
685136
- const candidates = [daemonModel, cachedModel].filter(Boolean);
685198
+ const projectModel = ($selectedModel.get && $selectedModel.get()) || '';
685199
+ const candidates = [projectModel, daemonModel, cachedModel].filter(Boolean);
685137
685200
  let recalled = null;
685138
685201
  for (const c of candidates) {
685139
685202
  const stripped = c.replace(/^local\\//, '');
@@ -685150,6 +685213,7 @@ async function loadModels() {
685150
685213
  // Persist the resolved value back to localStorage so a subsequent
685151
685214
  // refresh (before /v1/config has answered) can recall it instantly.
685152
685215
  try { localStorage.setItem('omnius.selectedModel', modelSelect.value); } catch {}
685216
+ try { if (modelSelect.value) $selectedModel.set(modelSelect.value); renderProjectChrome(); } catch {}
685153
685217
  } catch { modelSelect.innerHTML = '<option>error loading models</option>'; }
685154
685218
  }
685155
685219
 
@@ -687261,6 +687325,7 @@ async function loadConfig() {
687261
687325
  fetch('/v1/models', { headers: headers() }).then(r => r.json()),
687262
687326
  ]);
687263
687327
  const c = cfg.config || {};
687328
+ try { $config.set({ ...c, endpoint: ep }); renderProjectChrome(); } catch {}
687264
687329
  document.getElementById('config-content').innerHTML =
687265
687330
  '<table style="width:100%">' +
687266
687331
  Object.entries(c).map(([k,v]) =>
@@ -687809,6 +687874,7 @@ function saveSessions() {
687809
687874
  };
687810
687875
  }
687811
687876
  saveScopedSessions(saved);
687877
+ try { $chatSessions.set(saved); } catch {}
687812
687878
  updateSessionSelect();
687813
687879
  }
687814
687880
 
@@ -687860,6 +687926,7 @@ function deleteChatSession() {
687860
687926
  const saved = loadScopedSessions();
687861
687927
  delete saved[chatSessionId];
687862
687928
  saveScopedSessions(saved);
687929
+ try { $chatSessions.set(saved); } catch {}
687863
687930
  switchSession('');
687864
687931
  updateSessionSelect();
687865
687932
  }
@@ -688013,6 +688080,8 @@ function switchSession(id) {
688013
688080
  messages = [];
688014
688081
  document.getElementById('conversation').innerHTML = '';
688015
688082
  syncRouteForTab('chat', true);
688083
+ updateSessionSelect();
688084
+ try { _renderSidebarChats(_lastSidebarFilter || ''); } catch {}
688016
688085
  return;
688017
688086
  }
688018
688087
  const saved = loadScopedSessions();
@@ -688065,6 +688134,17 @@ function switchSession(id) {
688065
688134
  }
688066
688135
  }
688067
688136
  syncRouteForTab('chat', true);
688137
+ updateSessionSelect();
688138
+ try { _renderSidebarChats(_lastSidebarFilter || ''); } catch {}
688139
+ try { refreshTodos(id); } catch {}
688140
+ } else {
688141
+ chatSessionId = null;
688142
+ messages = [];
688143
+ const conv = document.getElementById('conversation');
688144
+ if (conv) conv.innerHTML = '';
688145
+ addMessage('system', 'No saved messages for this session.');
688146
+ updateSessionSelect();
688147
+ try { _renderSidebarChats(_lastSidebarFilter || ''); } catch {}
688068
688148
  }
688069
688149
  }
688070
688150
 
@@ -688126,6 +688206,34 @@ const agentTreeExpanded = new Set();
688126
688206
  const agentTreeCache = new Map();
688127
688207
  let agentTreeRoot = null;
688128
688208
 
688209
+ function resetProjectWorkspace(root) {
688210
+ const nextRoot = root || null;
688211
+ chatWorkingDir = nextRoot;
688212
+ agentWorkingDir = nextRoot;
688213
+ contextFiles = [];
688214
+ agentContextFiles = [];
688215
+ try { treeExpanded.clear(); treeCache.clear(); } catch {}
688216
+ try { agentTreeExpanded.clear(); agentTreeCache.clear(); } catch {}
688217
+ treeRoot = nextRoot;
688218
+ agentTreeRoot = nextRoot;
688219
+ const chatLabel = document.getElementById('workspace-dir-label');
688220
+ if (chatLabel) chatLabel.textContent = 'CWD: ' + (nextRoot || '(daemon default)');
688221
+ const agentLabel = document.getElementById('agent-workspace-dir-label');
688222
+ if (agentLabel) agentLabel.textContent = 'CWD: ' + (nextRoot || '(daemon default)');
688223
+ const wdInput = document.getElementById('agent-working-dir');
688224
+ if (wdInput) wdInput.value = nextRoot || '';
688225
+ try { renderContextChips(); } catch {}
688226
+ try { renderAgentContextChips(); } catch {}
688227
+ try {
688228
+ const chatSb = document.getElementById('workspace-sidebar');
688229
+ if (chatSb && chatSb.style.display === 'block') loadWorkspaceRoot();
688230
+ } catch {}
688231
+ try {
688232
+ const agentSb = document.getElementById('agent-workspace-sidebar');
688233
+ if (agentSb && agentSb.style.display === 'block') loadAgentWorkspaceRoot();
688234
+ } catch {}
688235
+ }
688236
+
688129
688237
  function toggleAgentWorkspace() {
688130
688238
  const sb = document.getElementById('agent-workspace-sidebar');
688131
688239
  if (!sb) return;
@@ -688137,9 +688245,12 @@ async function loadAgentWorkspaceRoot() {
688137
688245
  const cwdEl = document.getElementById('agent-workspace-cwd');
688138
688246
  if (!cwdEl) return;
688139
688247
  try {
688140
- const r = await fetch('/v1/files', { headers: headers() });
688248
+ const projectRoot = $currentProject.get()?.root || '';
688249
+ const requestedRoot = agentWorkingDir || projectRoot;
688250
+ const url = requestedRoot ? '/v1/files?path=' + encodeURIComponent(requestedRoot) : '/v1/files';
688251
+ const r = await fetch(url, { headers: headers() });
688141
688252
  const d = await r.json();
688142
- const rootPath = d.path || '.';
688253
+ const rootPath = d.path || requestedRoot || '.';
688143
688254
  cwdEl.innerHTML = '';
688144
688255
  const wsSpan = document.createElement('span');
688145
688256
  wsSpan.style.cssText = 'color:var(--color-fg-muted)';
@@ -688274,11 +688385,13 @@ window.toggleFilesForActiveTab = toggleFilesForActiveTab;
688274
688385
 
688275
688386
  async function loadWorkspaceRoot() {
688276
688387
  const cwdEl = document.getElementById('workspace-cwd');
688277
- // Default: daemon's cwd (from /v1/files with no path)
688278
688388
  try {
688279
- const r = await fetch('/v1/files', { headers: headers() });
688389
+ const projectRoot = $currentProject.get()?.root || '';
688390
+ const requestedRoot = chatWorkingDir || projectRoot;
688391
+ const url = requestedRoot ? '/v1/files?path=' + encodeURIComponent(requestedRoot) : '/v1/files';
688392
+ const r = await fetch(url, { headers: headers() });
688280
688393
  const d = await r.json();
688281
- const rootPath = d.path || '.';
688394
+ const rootPath = d.path || requestedRoot || '.';
688282
688395
  cwdEl.innerHTML = '';
688283
688396
  const wsSpan = document.createElement('span');
688284
688397
  wsSpan.style.cssText = 'color:var(--color-fg-muted)';
@@ -689174,6 +689287,19 @@ async function restoreChatSession() {
689174
689287
  }
689175
689288
  }
689176
689289
  }
689290
+ try {
689291
+ const saved = loadScopedSessions();
689292
+ saved[data.id] = {
689293
+ id: data.id,
689294
+ messages: messages,
689295
+ model: data.model || modelSelect.value,
689296
+ updatedAt: data.updated_at || data.updatedAt || new Date().toISOString(),
689297
+ preview: messages.slice(-1)[0]?.content?.slice(0, 50) || 'empty',
689298
+ };
689299
+ saveScopedSessions(saved);
689300
+ $chatSessions.set(saved);
689301
+ updateSessionSelect();
689302
+ } catch {}
689177
689303
  try { refreshTodos(data.id); } catch {}
689178
689304
  if (data.in_flight && data.in_flight.status === 'running') {
689179
689305
  attachInFlightPoller(data.id, data.in_flight);
@@ -689826,6 +689952,9 @@ $currentProject.subscribe((proj) => {
689826
689952
  // The hydrate subscriber inside the store layer has already updated
689827
689953
  // $selectedModel / $chatSessionId / $agentRunId from server prefs.
689828
689954
  // These reactions just refresh data the model + sessions panels need.
689955
+ try { resetProjectWorkspace(proj?.root || null); } catch {}
689956
+ try { $chatSessions.set(loadScopedSessions()); } catch {}
689957
+ try { renderProjectChrome(); } catch {}
689829
689958
  try { if (typeof loadModels === 'function') loadModels(); } catch {}
689830
689959
  try { if (typeof loadConfig === 'function') loadConfig(); } catch {}
689831
689960
  try { if (typeof updateSessionSelect === 'function') updateSessionSelect(); } catch {}
@@ -689837,13 +689966,13 @@ $currentProject.subscribe((proj) => {
689837
689966
  // $selectedModel changes update the visible <select> if it's not
689838
689967
  // already in sync (handles cross-tab updates + server-side overrides).
689839
689968
  $selectedModel.subscribe((m) => {
689840
- if (!m || !modelSelect) return;
689841
- if (modelSelect.value !== m) {
689969
+ if (m && modelSelect && modelSelect.value !== m) {
689842
689970
  // Only set if option exists; otherwise loadModels will reconcile
689843
689971
  if (Array.from(modelSelect.options).some(o => o.value === m)) {
689844
689972
  modelSelect.value = m;
689845
689973
  }
689846
689974
  }
689975
+ try { renderProjectChrome(); } catch {}
689847
689976
  });
689848
689977
 
689849
689978
  // $activeTab changes flip the tab UI (one-way: subscriber → DOM).
@@ -690036,16 +690165,19 @@ function _syncSidebarStatus() {
690036
690165
  const src = document.getElementById('status');
690037
690166
  const dst = document.getElementById('sidebar-status-text');
690038
690167
  const dot = document.getElementById('sidebar-status-dot');
690168
+ const brandDot = document.getElementById('sidebar-brand-dot');
690039
690169
  if (!src || !dst) return;
690040
690170
  const text = (src.textContent || '').trim();
690041
- dst.textContent = text || 'idle';
690042
- if (dot) {
690043
- let color = 'var(--color-fg-faint)';
690044
- if (/connect/i.test(text)) color = 'var(--color-warning)';
690045
- else if (/online|ready|ok/i.test(text)) color = 'var(--color-success)';
690046
- else if (/error|fail|down/i.test(text)) color = 'var(--color-error)';
690047
- else if (text) color = 'var(--color-success)';
690048
- dot.style.background = color;
690171
+ const state = String(_connectionState || text || '').toLowerCase();
690172
+ dst.textContent = text || state || 'idle';
690173
+ let color = '#6b7280';
690174
+ if (/disconnect|error|fail|down|offline/.test(state)) color = '#ef4444';
690175
+ else if (/connected|online|ready|ok|live/.test(state)) color = '#22c55e';
690176
+ else if (/connect|loading|pending/.test(state)) color = '#f59e0b';
690177
+ for (const el of [dot, brandDot]) {
690178
+ if (!el) continue;
690179
+ el.style.background = color;
690180
+ el.style.boxShadow = '0 0 0 2px ' + color + '22';
690049
690181
  }
690050
690182
  // Mirror the legacy update-btn visibility into the sidebar.
690051
690183
  const upd = document.getElementById('update-btn');
@@ -690161,10 +690293,10 @@ function deleteChatById(chatId) {
690161
690293
  // Also drop from pinned + folder map.
690162
690294
  setChatPinned(getChatPinned().filter(x => x !== chatId));
690163
690295
  const map = getChatFolderMap(); delete map[chatId]; setChatFolderMap(map);
690164
- try { if (typeof saveSessions === 'function') saveSessions(); } catch {}
690296
+ try { saveScopedSessions(all); } catch {}
690165
690297
  // If we just deleted the active chat, route the user to a fresh new chat.
690166
690298
  try {
690167
- const active = (typeof $currentSession !== 'undefined' && $currentSession.get) ? $currentSession.get() : null;
690299
+ const active = chatSessionId || (($chatSessionId.get && $chatSessionId.get()) || null);
690168
690300
  if (active === chatId && typeof newChatSession === 'function') newChatSession();
690169
690301
  } catch {}
690170
690302
  }
@@ -690307,7 +690439,7 @@ function _renderSidebarChats(filter) {
690307
690439
  const sessions = (typeof $chatSessions !== 'undefined' && $chatSessions.get) ? $chatSessions.get() : {};
690308
690440
  const allIds = Object.keys(sessions || {});
690309
690441
  const q = (filter || '').trim().toLowerCase();
690310
- const activeId = (typeof $currentSession !== 'undefined' && $currentSession.get) ? $currentSession.get() : null;
690442
+ const activeId = chatSessionId || (($chatSessionId.get && $chatSessionId.get()) || null);
690311
690443
 
690312
690444
  const folders = getChatFolders();
690313
690445
  const pinned = getChatPinned();
@@ -690420,8 +690552,8 @@ function filterSidebarChats(q) {
690420
690552
  _renderSidebarChats(search ? search.value : '');
690421
690553
  });
690422
690554
  }
690423
- if (typeof $currentSession !== 'undefined' && $currentSession.subscribe) {
690424
- $currentSession.subscribe(() => {
690555
+ if ($chatSessionId && $chatSessionId.subscribe) {
690556
+ $chatSessionId.subscribe(() => {
690425
690557
  const search = document.getElementById('sidebar-search');
690426
690558
  _renderSidebarChats(search ? search.value : '');
690427
690559
  });
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.320",
3
+ "version": "1.0.321",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.320",
9
+ "version": "1.0.321",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.320",
3
+ "version": "1.0.321",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",