omnius 1.0.323 → 1.0.324

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
@@ -595348,6 +595348,23 @@ __export(task_complete_box_exports, {
595348
595348
  renderSessionHistoryBox: () => renderSessionHistoryBox,
595349
595349
  renderTaskCompleteBox: () => renderTaskCompleteBox
595350
595350
  });
595351
+ function refreshBoxPalette() {
595352
+ if (themeMode() === "system") {
595353
+ GREEN = DEFAULT_FG;
595354
+ FG_BORDER = DEFAULT_FG;
595355
+ FG_TITLE = DEFAULT_BOLD_FG;
595356
+ FG_METRIC = DEFAULT_FG;
595357
+ FG_LABEL = DEFAULT_FG;
595358
+ return;
595359
+ }
595360
+ const accent = tuiAccent();
595361
+ const borderColor = accent >= 0 ? accent : TASK_COMPLETE_GREEN_256;
595362
+ GREEN = `\x1B[38;5;${borderColor}m`;
595363
+ FG_BORDER = `\x1B[38;5;${borderColor}m`;
595364
+ FG_TITLE = `\x1B[1;38;5;${borderColor}m`;
595365
+ FG_METRIC = "\x1B[38;5;222m";
595366
+ FG_LABEL = "\x1B[38;5;147m";
595367
+ }
595351
595368
  function deriveTitle(task) {
595352
595369
  if (!task || !task.trim()) return "Task Complete";
595353
595370
  const source = task.replace(/^[\s\S]*?\n---\s*\n\s*NEW TASK:\s*/i, "").replace(/^NEW TASK:\s*/i, "").replace(/<task-handoff>[\s\S]*?<\/task-handoff>/gi, " ").replace(/<session-recap>[\s\S]*?<\/session-recap>/gi, " ").replace(/^\[task_(?:boundary|summary)\][\s\S]*?(?=\n\n|$)/gim, " ");
@@ -595540,6 +595557,7 @@ function buildLabeledFooterLines(label, items, width) {
595540
595557
  return lines;
595541
595558
  }
595542
595559
  function buildBoxLines(data, width) {
595560
+ refreshBoxPalette();
595543
595561
  const w = Math.max(40, width);
595544
595562
  const title = deriveTitle(data.task);
595545
595563
  const metrics2 = buildMetricsChip(data);
@@ -595579,6 +595597,7 @@ function buildBoxLines(data, width) {
595579
595597
  return lines;
595580
595598
  }
595581
595599
  function buildSessionHistoryBoxLines(data, width) {
595600
+ refreshBoxPalette();
595582
595601
  const w = Math.max(40, width);
595583
595602
  const title = deriveTitle(data.title || "Session History");
595584
595603
  const metrics2 = buildSessionHistoryMetricsChip(data);
@@ -595710,11 +595729,12 @@ function detectProvenanceAnchors(toolOutputs) {
595710
595729
  }
595711
595730
  return [...out].slice(0, 16);
595712
595731
  }
595713
- var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, TASK_COMPLETE_GREEN_256, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
595732
+ var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, TASK_COMPLETE_GREEN_256, DEFAULT_FG, DEFAULT_BOLD_FG, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
595714
595733
  var init_task_complete_box = __esm({
595715
595734
  "packages/cli/src/tui/task-complete-box.ts"() {
595716
595735
  "use strict";
595717
595736
  init_text_selection();
595737
+ init_theme();
595718
595738
  BOX_TL = "╭";
595719
595739
  BOX_TR = "╮";
595720
595740
  BOX_BL = "╰";
@@ -595725,6 +595745,8 @@ var init_task_complete_box = __esm({
595725
595745
  BOX_TJ_R = "┤";
595726
595746
  RESET = "\x1B[0m";
595727
595747
  TASK_COMPLETE_GREEN_256 = 154;
595748
+ DEFAULT_FG = "\x1B[39m";
595749
+ DEFAULT_BOLD_FG = "\x1B[1;39m";
595728
595750
  GREEN = `\x1B[38;5;${TASK_COMPLETE_GREEN_256}m`;
595729
595751
  FG_BORDER = `\x1B[38;5;${TASK_COMPLETE_GREEN_256}m`;
595730
595752
  FG_TITLE = `\x1B[1;38;5;${TASK_COMPLETE_GREEN_256}m`;
@@ -605735,6 +605757,31 @@ function getLastTaskSummary(repoRoot) {
605735
605757
  const clean5 = text2.replace(/^\[.*?\]\s*/, "").replace(/\s+/g, " ").trim();
605736
605758
  return clean5.length > 40 ? clean5.slice(0, 37) + "..." : clean5;
605737
605759
  }
605760
+ function cleanSessionHistoryDisplayLine(line) {
605761
+ return String(line || "").replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "").replace(/^[>❯▹∙•*+\-\s]+/, "").replace(/^\[.*?\]\s*/, "").replace(/^(?:User|Assistant|You|Open Agent|Omnius)\s*:\s*/i, "").replace(/\s+/g, " ").trim();
605762
+ }
605763
+ function isNoisySessionHistoryLine(line) {
605764
+ const clean5 = cleanSessionHistoryDisplayLine(line || "");
605765
+ if (!clean5) return true;
605766
+ return /^(?:Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \/endpoint|Knowledge graph:|Zettelkasten:|Episodes captured:|Current OMNIUS_HOST:|Loaded TUI session|General session$|Chat tui:sess|i\s+)/i.test(clean5);
605767
+ }
605768
+ function firstMeaningfulSessionHistoryLine(lines) {
605769
+ for (const line of lines) {
605770
+ const clean5 = cleanSessionHistoryDisplayLine(line);
605771
+ if (!isNoisySessionHistoryLine(clean5)) return clean5;
605772
+ }
605773
+ return "";
605774
+ }
605775
+ function sanitizeSessionHistoryEntry(repoRoot, entry) {
605776
+ if (!isNoisySessionHistoryLine(entry.name) && !isNoisySessionHistoryLine(entry.description)) return entry;
605777
+ const lines = loadSessionHistory(repoRoot, entry.id) || [];
605778
+ const fallback = firstMeaningfulSessionHistoryLine(lines);
605779
+ return {
605780
+ ...entry,
605781
+ name: isNoisySessionHistoryLine(entry.name) ? fallback ? fallback.length > 40 ? fallback.slice(0, 37) + "..." : fallback : entry.name : entry.name,
605782
+ description: isNoisySessionHistoryLine(entry.description) ? fallback || entry.description : entry.description
605783
+ };
605784
+ }
605738
605785
  function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
605739
605786
  const sessDir = join125(repoRoot, OMNIUS_DIR, SESSIONS_DIR);
605740
605787
  mkdirSync66(sessDir, { recursive: true });
@@ -605782,7 +605829,7 @@ function listSessions(repoRoot) {
605782
605829
  try {
605783
605830
  if (!existsSync110(indexPath)) return [];
605784
605831
  const index = JSON.parse(readFileSync89(indexPath, "utf-8"));
605785
- return index.sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
605832
+ return index.map((entry) => sanitizeSessionHistoryEntry(repoRoot, entry)).sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
605786
605833
  } catch {
605787
605834
  return [];
605788
605835
  }
@@ -605813,12 +605860,9 @@ function deleteSession(repoRoot, sessionId) {
605813
605860
  }
605814
605861
  }
605815
605862
  function generateSessionName(lines) {
605816
- for (const line of lines.slice(0, 30)) {
605817
- const clean5 = line.trim();
605818
- if (clean5.length > 10 && !clean5.startsWith("i ") && !clean5.startsWith(" ")) {
605819
- const phrase = clean5.replace(/^[>❯▹]\s*/, "").slice(0, 40);
605820
- return phrase.length > 37 ? phrase.slice(0, 37) + "..." : phrase;
605821
- }
605863
+ const phrase = firstMeaningfulSessionHistoryLine(lines.slice(0, 80));
605864
+ if (phrase.length > 10) {
605865
+ return phrase.length > 40 ? phrase.slice(0, 37) + "..." : phrase;
605822
605866
  }
605823
605867
  return `Session ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
605824
605868
  }
@@ -605836,7 +605880,9 @@ function generateSessionDescription(lines) {
605836
605880
  }
605837
605881
  if (topics.length >= 3) break;
605838
605882
  }
605839
- return topics.length > 0 ? topics.join(", ") : "General session";
605883
+ if (topics.length > 0) return topics.join(", ");
605884
+ const fallback = firstMeaningfulSessionHistoryLine(lines.slice(0, 120));
605885
+ return fallback || "General session";
605840
605886
  }
605841
605887
  function detectManifests(repoRoot) {
605842
605888
  const manifests = [];
@@ -607403,6 +607449,25 @@ __export(status_bar_exports, {
607403
607449
  unlockFooterRedraws: () => unlockFooterRedraws
607404
607450
  });
607405
607451
  import { readFileSync as readFileSync91 } from "node:fs";
607452
+ function headerButtonGlyphFg() {
607453
+ const a2 = tuiAccent();
607454
+ return a2 < 0 ? "\x1B[39m" : `\x1B[38;5;${a2}m`;
607455
+ }
607456
+ function headerButtonBg() {
607457
+ const a2 = tuiAccent();
607458
+ return a2 < 0 ? "\x1B[7m" : `\x1B[48;5;${a2}m`;
607459
+ }
607460
+ function headerButtonFg() {
607461
+ const a2 = tuiAccent();
607462
+ return a2 < 0 ? "" : `\x1B[38;5;${contrastTextColor(a2)}m`;
607463
+ }
607464
+ function headerAccentBoldFg() {
607465
+ const a2 = tuiAccent();
607466
+ return a2 < 0 ? "\x1B[1;39m" : `\x1B[1;38;5;${a2}m`;
607467
+ }
607468
+ function headerTelegramFg() {
607469
+ return themeMode() === "system" ? "\x1B[39m" : "\x1B[38;5;45m";
607470
+ }
607406
607471
  function stripSubAgentPrefix(label) {
607407
607472
  const stripped = label.replace(/^\s*sub[-\s]?agents?\b[\s:_–—-]*/i, "").trim();
607408
607473
  return stripped.length > 0 ? stripped : label.trim();
@@ -607460,6 +607525,11 @@ function refreshThemeVars() {
607460
607525
  BOX_FG = tuiBoxFg();
607461
607526
  TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
607462
607527
  TEXT_DIM = tuiTextDim();
607528
+ HEADER_BUTTON_GLYPH_FG = headerButtonGlyphFg();
607529
+ HEADER_BUTTON_BG = headerButtonBg();
607530
+ HEADER_BUTTON_FG = headerButtonFg();
607531
+ HEADER_ACCENT_BOLD_FG = headerAccentBoldFg();
607532
+ HEADER_TELEGRAM_FG = headerTelegramFg();
607463
607533
  }
607464
607534
  function sanitizeSponsorHeaderText(value2, max = SPONSOR_HEADER_LABEL_MAX) {
607465
607535
  const cleaned = stripAnsi(String(value2 ?? "")).replace(/[\x00-\x1F\x7F]/g, " ").replace(/\s+/g, " ").trim();
@@ -607494,7 +607564,7 @@ function setTerminalTitle(task, version4) {
607494
607564
  process.stdout.write(data);
607495
607565
  }
607496
607566
  }
607497
- var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, HEADER_ACCENT_GREEN, HEADER_ACCENT_BOLD_FG, HEADER_BUTTON_BG, HEADER_BUTTON_FG, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
607567
+ var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, HEADER_BUTTON_GLYPH_FG, HEADER_BUTTON_BG, HEADER_BUTTON_FG, HEADER_ACCENT_BOLD_FG, HEADER_TELEGRAM_FG, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
607498
607568
  var init_status_bar = __esm({
607499
607569
  "packages/cli/src/tui/status-bar.ts"() {
607500
607570
  "use strict";
@@ -607674,10 +607744,11 @@ var init_status_bar = __esm({
607674
607744
  TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
607675
607745
  TEXT_DIM = tuiTextDim();
607676
607746
  NO_SUB_AGENTS_HEADER_LABEL = " no agents ";
607677
- HEADER_ACCENT_GREEN = 154;
607678
- HEADER_ACCENT_BOLD_FG = `\x1B[1;38;5;${HEADER_ACCENT_GREEN}m`;
607679
- HEADER_BUTTON_BG = `\x1B[48;5;${HEADER_ACCENT_GREEN}m`;
607680
- HEADER_BUTTON_FG = "\x1B[38;5;0m";
607747
+ HEADER_BUTTON_GLYPH_FG = headerButtonGlyphFg();
607748
+ HEADER_BUTTON_BG = headerButtonBg();
607749
+ HEADER_BUTTON_FG = headerButtonFg();
607750
+ HEADER_ACCENT_BOLD_FG = headerAccentBoldFg();
607751
+ HEADER_TELEGRAM_FG = headerTelegramFg();
607681
607752
  BOX_TL3 = "╭";
607682
607753
  BOX_TR3 = "╮";
607683
607754
  BOX_BL3 = "╰";
@@ -608148,7 +608219,7 @@ var init_status_bar = __esm({
608148
608219
  return fg2;
608149
608220
  };
608150
608221
  const decorateMenuButton = (cmd, label) => {
608151
- return `\x1B[38;5;${HEADER_ACCENT_GREEN}m🭁\x1B[0m${HEADER_BUTTON_FG}${HEADER_BUTTON_BG}${label}\x1B[0m${PANEL_BG_SEQ}\x1B[38;5;${HEADER_ACCENT_GREEN}m🭝\x1B[0m${PANEL_BG_SEQ}`;
608222
+ return `${HEADER_BUTTON_GLYPH_FG}🭁\x1B[0m${HEADER_BUTTON_BG}${HEADER_BUTTON_FG}${label}\x1B[0m${PANEL_BG_SEQ}${HEADER_BUTTON_GLYPH_FG}🭝\x1B[0m${PANEL_BG_SEQ}`;
608152
608223
  };
608153
608224
  const decorateAgentButton = (content, color, active) => {
608154
608225
  const bg = `\x1B[48;5;${color}m`;
@@ -608282,7 +608353,7 @@ var init_status_bar = __esm({
608282
608353
  sysItems.push({
608283
608354
  render: () => renderBtn(
608284
608355
  "telegram",
608285
- `\x1B[38;5;45m${telegramDot}${telegramLabel}\x1B[0m`
608356
+ `${HEADER_TELEGRAM_FG}${telegramDot}${telegramLabel}\x1B[0m`
608286
608357
  ) + " ",
608287
608358
  w: telegramLabel.length + 2
608288
608359
  });
@@ -610719,8 +610790,8 @@ ${CONTENT_BG_SEQ}`);
610719
610790
  const label = `✈ tg${suffix}`;
610720
610791
  const compact3 = `✈${suffix}`;
610721
610792
  sections.push({
610722
- expanded: `\x1B[38;5;45m${label}\x1B[0m`,
610723
- compact: `\x1B[38;5;45m${compact3}\x1B[0m`,
610793
+ expanded: `${HEADER_TELEGRAM_FG}${label}\x1B[0m`,
610794
+ compact: `${HEADER_TELEGRAM_FG}${compact3}\x1B[0m`,
610724
610795
  expandedW: 2 + 3 + suffix.length,
610725
610796
  compactW: 2 + suffix.length,
610726
610797
  empty: false,
@@ -645238,22 +645309,51 @@ function normalizeRoot(root) {
645238
645309
  }
645239
645310
  }
645240
645311
  function stripAnsi5(text2) {
645241
- return String(text2 || "").replace(/\[[0-9;]*[a-zA-Z]/g, "");
645312
+ return String(text2 || "").replace(/\u001b\[[0-9;]*[a-zA-Z]/g, "");
645313
+ }
645314
+ function cleanSessionDisplayLine(line) {
645315
+ return stripAnsi5(line).replace(/^[>❯▹∙•*+\-\s]+/, "").replace(/^(?:User|Assistant|You|Open Agent|Omnius)\s*:\s*/i, "").replace(/\s+/g, " ").trim();
645316
+ }
645317
+ function isNoisySessionDisplayLine(line) {
645318
+ const clean5 = cleanSessionDisplayLine(line || "");
645319
+ if (!clean5) return true;
645320
+ return /^(?:Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \/endpoint|Knowledge graph:|Zettelkasten:|Episodes captured:|Current OMNIUS_HOST:|Loaded TUI session|General session$|Chat tui:sess|\[Imported TUI session transcript\]|Title:|Description:|Project root:|i\s+)/i.test(clean5);
645321
+ }
645322
+ function bestSessionDisplayLine(text2) {
645323
+ const lines = stripAnsi5(text2).split(/\r?\n/);
645324
+ for (const line of lines) {
645325
+ const clean5 = cleanSessionDisplayLine(line);
645326
+ if (!isNoisySessionDisplayLine(clean5)) return clean5;
645327
+ }
645328
+ const fallback = stripAnsi5(text2).replace(/\s+/g, " ").trim();
645329
+ return isNoisySessionDisplayLine(fallback) ? "" : fallback;
645242
645330
  }
645243
645331
  function makeTitle(text2) {
645244
- const clean5 = stripAnsi5(text2).replace(/\s+/g, " ").trim();
645332
+ const clean5 = bestSessionDisplayLine(text2);
645245
645333
  if (!clean5) return "Chat session";
645246
- return clean5.length > 72 ? `${clean5.slice(0, 69)}...` : clean5;
645334
+ return clean5.length > 72 ? clean5.slice(0, 69) + "..." : clean5;
645247
645335
  }
645248
645336
  function makePreview(text2) {
645249
- const clean5 = stripAnsi5(text2).replace(/\s+/g, " ").trim();
645250
- return clean5.length > 160 ? `${clean5.slice(0, 157)}...` : clean5;
645337
+ const clean5 = bestSessionDisplayLine(text2);
645338
+ return clean5.length > 160 ? clean5.slice(0, 157) + "..." : clean5;
645251
645339
  }
645252
645340
  function normalizeLoadedSession(parsed) {
645253
645341
  if (!parsed.source) parsed.source = "web";
645254
645342
  if (parsed.projectRoot) parsed.projectRoot = normalizeRoot(parsed.projectRoot);
645343
+ if (parsed.title && isNoisySessionDisplayLine(parsed.title)) parsed.title = void 0;
645344
+ if (parsed.preview && isNoisySessionDisplayLine(parsed.preview)) parsed.preview = "";
645345
+ const importedContext = (parsed.messages || []).find(
645346
+ (m2) => m2.role === "system" && m2.content.startsWith("[Imported TUI session transcript]")
645347
+ )?.content;
645348
+ if ((parsed.source === "tui" || parsed.id?.startsWith("tui:")) && importedContext) {
645349
+ const importedPreview = makePreview(importedContext);
645350
+ if (!parsed.preview && importedPreview) parsed.preview = importedPreview;
645351
+ if (!parsed.title && importedPreview) parsed.title = makeTitle(importedPreview);
645352
+ }
645255
645353
  if (!parsed.preview) {
645256
- const last2 = [...parsed.messages || []].reverse().find((m2) => m2.role === "user" || m2.role === "assistant");
645354
+ const last2 = [...parsed.messages || []].reverse().find(
645355
+ (m2) => (m2.role === "user" || m2.role === "assistant") && !isNoisySessionDisplayLine(m2.content)
645356
+ );
645257
645357
  parsed.preview = last2 ? makePreview(last2.content) : "";
645258
645358
  }
645259
645359
  if (!parsed.title && parsed.preview) parsed.title = makeTitle(parsed.preview);
@@ -645426,9 +645526,10 @@ function getSession2(sessionId, model, cwd4) {
645426
645526
  function importTranscriptSession(opts) {
645427
645527
  const projectRoot = normalizeRoot(opts.projectRoot) ?? process.cwd();
645428
645528
  const id = opts.id;
645429
- const title = opts.title || makeTitle(opts.description || id);
645430
- const preview = makePreview(opts.description || opts.transcriptLines.slice(-8).join(" "));
645431
645529
  const transcript = opts.transcriptLines.map(stripAnsi5).join("\n").trim();
645530
+ const metadataSource = [opts.title, opts.description, transcript].filter(Boolean).join("\n");
645531
+ const title = makeTitle(metadataSource || id);
645532
+ const preview = makePreview([opts.description, transcript].filter(Boolean).join("\n") || title);
645432
645533
  const cappedTranscript = transcript.length > 32e3 ? `[earlier transcript truncated: ${transcript.length - 32e3} chars]
645433
645534
  ` + transcript.slice(-32e3) : transcript;
645434
645535
  const importedContext = [
@@ -685535,6 +685636,44 @@ async function loadServerPrefs() {
685535
685636
  } catch { return null; }
685536
685637
  }
685537
685638
 
685639
+ function isNoisyChatSessionText(text) {
685640
+ const clean = String(text || '').replace(/\\s+/g, ' ').trim();
685641
+ if (!clean) return true;
685642
+ const t = clean.replace(/^[>❯▹∙•\\-\\s]+/, '');
685643
+ return /^(Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \\/endpoint|General session$|Loaded TUI session|Chat tui:sess)/i.test(t);
685644
+ }
685645
+
685646
+ function isGenericChatTitle(id, title) {
685647
+ const t = String(title || '').trim();
685648
+ if (!t) return true;
685649
+ if (isNoisyChatSessionText(t)) return true;
685650
+ if (t === 'Chat ' + String(id || '').slice(0, 8)) return true;
685651
+ return /^Chat tui:sess/i.test(t);
685652
+ }
685653
+
685654
+ function sessionDisplayTitle(id, session) {
685655
+ const s = session || {};
685656
+ for (const candidate of [s.title, s.name, s.preview]) {
685657
+ if (!isGenericChatTitle(id, candidate)) return String(candidate).trim();
685658
+ }
685659
+ if (Array.isArray(s.messages)) {
685660
+ for (let i = s.messages.length - 1; i >= 0; i--) {
685661
+ const msg = s.messages[i];
685662
+ const content = msg && typeof msg.content === 'string' ? msg.content : '';
685663
+ if (!isGenericChatTitle(id, content)) return content.replace(/\\s+/g, ' ').trim().slice(0, 72);
685664
+ }
685665
+ }
685666
+ return String(id || '').startsWith('tui:') ? 'TUI session ' + String(id).slice(4, 16) : 'Chat ' + String(id || '').slice(0, 8);
685667
+ }
685668
+
685669
+ function sessionDisplayPreview(session) {
685670
+ const s = session || {};
685671
+ for (const candidate of [s.preview, s.title, s.name]) {
685672
+ if (!isNoisyChatSessionText(candidate)) return String(candidate).trim();
685673
+ }
685674
+ return '';
685675
+ }
685676
+
685538
685677
  async function loadServerChatSessions() {
685539
685678
  const root = $currentProject.get()?.root || '';
685540
685679
  if (!root) return;
@@ -685547,16 +685686,24 @@ async function loadServerChatSessions() {
685547
685686
  for (const sess of (data.sessions || [])) {
685548
685687
  if (!sess || !sess.id) continue;
685549
685688
  const existing = merged[sess.id] || {};
685689
+ const serverTitle = sess.title || sess.preview || '';
685690
+ const existingTitle = existing.title || existing.name || '';
685691
+ const title = !isGenericChatTitle(sess.id, existingTitle)
685692
+ ? existingTitle
685693
+ : (!isGenericChatTitle(sess.id, serverTitle) ? serverTitle : sessionDisplayTitle(sess.id, sess));
685694
+ const preview = !isNoisyChatSessionText(existing.preview)
685695
+ ? existing.preview
685696
+ : (!isNoisyChatSessionText(sess.preview) ? sess.preview : sessionDisplayPreview(sess));
685550
685697
  merged[sess.id] = {
685551
685698
  ...existing,
685552
685699
  id: sess.id,
685553
- title: existing.title || sess.title || sess.preview || ('Chat ' + String(sess.id).slice(0, 8)),
685554
- name: existing.name || sess.title || sess.preview || ('Chat ' + String(sess.id).slice(0, 8)),
685555
- preview: existing.preview || sess.preview || sess.title || '',
685700
+ title,
685701
+ name: !isGenericChatTitle(sess.id, existing.name) ? existing.name : title,
685702
+ preview,
685556
685703
  model: existing.model || sess.model || '',
685557
685704
  source: sess.source || existing.source || 'web',
685558
685705
  projectRoot: sess.projectRoot || root,
685559
- updatedAt: existing.updatedAt || sess.lastActivity || sess.updatedAt || '',
685706
+ updatedAt: sess.lastActivity || sess.updatedAt || existing.updatedAt || '',
685560
685707
  messages: existing.messages || [],
685561
685708
  };
685562
685709
  }
@@ -686085,6 +686232,7 @@ function addMessage(role, content) {
686085
686232
  }
686086
686233
  if (role === 'assistant' || (role === 'user' && looksLikeMarkdown(content))) {
686087
686234
  host.innerHTML = renderMarkdown(content);
686235
+ appendArtifactsForText(host, content);
686088
686236
  } else {
686089
686237
  host.textContent = content;
686090
686238
  }
@@ -686380,6 +686528,7 @@ function renderToolCallEvent(parent, chunkLike) {
686380
686528
  argsDiv.appendChild(row);
686381
686529
  }
686382
686530
  }
686531
+ appendArtifactControls(argsDiv, extractArtifactsFromValue(a));
686383
686532
  details.appendChild(argsDiv);
686384
686533
  }
686385
686534
  parent.appendChild(details);
@@ -686396,6 +686545,7 @@ function renderToolResultEvent(parent, chunkLike) {
686396
686545
  : 'background:var(--color-bg-elevated);color:var(--color-fg-muted);';
686397
686546
  resultEl.style.cssText = errStyle + 'padding:4px 8px 4px 18px;margin:0 0 2px 0;font-size:0.65rem';
686398
686547
  appendExpandableContent(resultEl, chunkLike.output || '', { truncateAt: 150, baseStyle: 'color:inherit;' });
686548
+ appendArtifactControls(resultEl, extractArtifactsFromValue(chunkLike));
686399
686549
  parent.appendChild(resultEl);
686400
686550
  return resultEl;
686401
686551
  }
@@ -686751,6 +686901,7 @@ async function sendMessage() {
686751
686901
  fullContent += summaryText;
686752
686902
  }
686753
686903
  contentDiv.innerHTML = renderMarkdown(fullContent);
686904
+ appendArtifactsForText(contentDiv, fullContent);
686754
686905
  hideStreamingIndicator(msgDiv);
686755
686906
  maybeAutoScroll();
686756
686907
  }
@@ -686862,6 +687013,7 @@ async function sendMessage() {
686862
687013
  argsDiv.appendChild(row);
686863
687014
  }
686864
687015
  }
687016
+ appendArtifactControls(argsDiv, extractArtifactsFromValue(a));
686865
687017
  details.appendChild(argsDiv);
686866
687018
  }
686867
687019
  toolsContainer.appendChild(details);
@@ -686874,10 +687026,8 @@ async function sendMessage() {
686874
687026
  // 150 chars. The button sits underneath the result block.
686875
687027
  if (chunk.type === 'tool_result') {
686876
687028
  if (isInternalChatTool(chunk.tool || '')) continue;
686877
- const resultEl = document.createElement('div');
686878
- resultEl.style.cssText = 'background:var(--color-bg-elevated);padding:4px 8px 4px 18px;margin:0 0 2px 0;color:var(--color-fg-muted);font-size:0.65rem';
686879
- appendExpandableContent(resultEl, chunk.output || '', { truncateAt: 150, baseStyle: 'color:var(--color-fg-muted);' });
686880
- toolsContainer.appendChild(resultEl);
687029
+ renderToolResultEvent(toolsContainer, chunk);
687030
+ maybeAutoScroll();
686881
687031
  continue;
686882
687032
  }
686883
687033
 
@@ -686893,6 +687043,7 @@ async function sendMessage() {
686893
687043
  hideStreamingIndicator(msgDiv);
686894
687044
  fullContent += delta;
686895
687045
  contentDiv.innerHTML = renderMarkdown(fullContent);
687046
+ appendArtifactsForText(contentDiv, fullContent);
686896
687047
  try { _highlightCodeBlocks(contentDiv); } catch {}
686897
687048
  maybeAutoScroll();
686898
687049
  }
@@ -686916,6 +687067,7 @@ async function sendMessage() {
686916
687067
 
686917
687068
  // Final render: content + collapsible tools + metadata
686918
687069
  contentDiv.innerHTML = renderMarkdown(fullContent);
687070
+ appendArtifactsForText(contentDiv, fullContent);
686919
687071
  // OWUI-3: streaming complete — drop the pulsing dot.
686920
687072
  hideStreamingIndicator(msgDiv);
686921
687073
  try { _highlightCodeBlocks(contentDiv); } catch {}
@@ -688828,12 +688980,20 @@ async function loadJobs() {
688828
688980
  function saveSessions() {
688829
688981
  const saved = loadScopedSessions();
688830
688982
  if (chatSessionId) {
688983
+ const existing = saved[chatSessionId] || (($chatSessions.get && $chatSessions.get()) || {})[chatSessionId] || {};
688984
+ const preview = messages.slice(-1)[0]?.content?.slice(0, 50) || sessionDisplayPreview(existing) || 'empty';
688985
+ const title = !isGenericChatTitle(chatSessionId, existing.title || existing.name)
688986
+ ? (existing.title || existing.name)
688987
+ : sessionDisplayTitle(chatSessionId, { ...existing, preview, messages });
688831
688988
  saved[chatSessionId] = {
688989
+ ...existing,
688832
688990
  id: chatSessionId,
688991
+ title,
688992
+ name: !isGenericChatTitle(chatSessionId, existing.name) ? existing.name : title,
688833
688993
  messages: messages,
688834
688994
  model: modelSelect.value,
688835
688995
  updatedAt: new Date().toISOString(),
688836
- preview: messages.slice(-1)[0]?.content?.slice(0, 50) || 'empty',
688996
+ preview,
688837
688997
  };
688838
688998
  }
688839
688999
  saveScopedSessions(saved);
@@ -688859,7 +689019,7 @@ function updateSessionSelect() {
688859
689019
  for (const [id, s] of entries) {
688860
689020
  const opt = document.createElement('option');
688861
689021
  opt.value = id;
688862
- opt.textContent = (s.preview || 'session').slice(0, 40);
689022
+ opt.textContent = sessionDisplayTitle(id, s).slice(0, 40);
688863
689023
  if (id === chatSessionId) opt.selected = true;
688864
689024
  sel.appendChild(opt);
688865
689025
  }
@@ -689668,6 +689828,255 @@ function rawFileUrl(path) {
689668
689828
  return '/v1/files/raw?path=' + encodeURIComponent(path);
689669
689829
  }
689670
689830
 
689831
+ function cleanArtifactPathCandidate(value) {
689832
+ let s = String(value || '').trim();
689833
+ s = s.replace(/^["'(<]+/, '').replace(/[)"'>,.;:]+$/, '');
689834
+ return s;
689835
+ }
689836
+
689837
+ function isPreviewableArtifactInfo(info) {
689838
+ return info && (info.kind === 'audio' || info.kind === 'video' || info.kind === 'image' || info.kind === 'pdf' || isTextPreviewable(info));
689839
+ }
689840
+
689841
+ function mediaUrlForStoredPath(path) {
689842
+ const normalized = String(path || '').split(String.fromCharCode(92)).join('/');
689843
+ const marker = '/.omnius/media/';
689844
+ const idx = normalized.indexOf(marker);
689845
+ if (idx < 0) return null;
689846
+ const rest = normalized.slice(idx + marker.length);
689847
+ const parts = rest.split('/').filter(Boolean);
689848
+ if (parts.length < 2) return null;
689849
+ const group = parts[0];
689850
+ const name = parts[parts.length - 1];
689851
+ const kind = group === 'images' ? 'image'
689852
+ : group === 'videos' ? 'video'
689853
+ : group === 'audio' ? 'audio'
689854
+ : group === 'music' ? 'music'
689855
+ : null;
689856
+ if (!kind || !name) return null;
689857
+ return '/v1/media/file?kind=' + encodeURIComponent(kind) + '&name=' + encodeURIComponent(name);
689858
+ }
689859
+
689860
+ function artifactFromPath(path, hint) {
689861
+ const clean = cleanArtifactPathCandidate(path);
689862
+ if (!clean) return null;
689863
+ const info = fileInfoFor(null, clean);
689864
+ if (info.kind === 'binary' || info.kind === 'archive') return null;
689865
+ const mediaUrl = mediaUrlForStoredPath(clean);
689866
+ return {
689867
+ path: clean,
689868
+ url: mediaUrl || rawFileUrl(clean),
689869
+ name: baseNameForPath(clean),
689870
+ kind: hint || info.kind,
689871
+ mime: info.mime,
689872
+ info,
689873
+ };
689874
+ }
689875
+
689876
+ function artifactFromUrl(url, hint) {
689877
+ const clean = cleanArtifactPathCandidate(url);
689878
+ if (!clean) return null;
689879
+ if (!/^\\/v1\\/media\\/file\\?/.test(clean) && !/^\\/v1\\/files\\/raw\\?/.test(clean) && !/^https?:\\/\\//i.test(clean)) return null;
689880
+ let name = clean;
689881
+ let kind = hint || '';
689882
+ let path = '';
689883
+ try {
689884
+ const u = new URL(clean, window.location.origin);
689885
+ path = u.searchParams.get('path') || '';
689886
+ name = u.searchParams.get('name') || (path ? baseNameForPath(path) : '') || baseNameForPath(u.pathname) || clean;
689887
+ kind = kind || u.searchParams.get('kind') || '';
689888
+ if (kind === 'music') kind = 'audio';
689889
+ } catch {}
689890
+ const info = fileInfoFor({ name, kind }, path || name);
689891
+ return { path, url: clean, name, kind: kind || info.kind, mime: info.mime, info };
689892
+ }
689893
+
689894
+ function uniqueArtifacts(items) {
689895
+ const seen = new Set();
689896
+ const out = [];
689897
+ for (const item of items || []) {
689898
+ if (!item) continue;
689899
+ const key = (item.url || '') + '|' + (item.path || '');
689900
+ if (!key.trim() || seen.has(key)) continue;
689901
+ seen.add(key);
689902
+ out.push(item);
689903
+ }
689904
+ return out;
689905
+ }
689906
+
689907
+ function extractArtifactsFromText(text) {
689908
+ const raw = String(text || '');
689909
+ if (!raw.trim()) return [];
689910
+ const out = [];
689911
+
689912
+ const urlRe = /\\/v1\\/(?:media\\/file|files\\/raw)\\?[^\\s"'<>]+/g;
689913
+ for (const match of raw.matchAll(urlRe)) {
689914
+ out.push(artifactFromUrl(match[0]));
689915
+ }
689916
+
689917
+ const pathRe = /(?:~|\\/|[A-Za-z]:[\\\\/])[^\\s"'<>]+/g;
689918
+ for (const match of raw.matchAll(pathRe)) {
689919
+ const candidate = cleanArtifactPathCandidate(match[0]);
689920
+ if (/^\\/v1\\/(?:media\\/file|files\\/raw)\\?/i.test(candidate)) continue;
689921
+ const info = fileInfoFor(null, candidate);
689922
+ if (isPreviewableArtifactInfo(info)) out.push(artifactFromPath(candidate));
689923
+ }
689924
+
689925
+ const trimmed = raw.trim();
689926
+ if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
689927
+ try {
689928
+ out.push(...extractArtifactsFromValue(JSON.parse(trimmed)));
689929
+ } catch {}
689930
+ }
689931
+
689932
+ return uniqueArtifacts(out);
689933
+ }
689934
+
689935
+ function extractArtifactsFromValue(value) {
689936
+ const out = [];
689937
+ const walk = (v, key) => {
689938
+ if (v == null) return;
689939
+ if (typeof v === 'string') {
689940
+ const lowerKey = String(key || '').toLowerCase();
689941
+ if (/^(path|file|filename|output|url|href|src|artifact|download)$/.test(lowerKey)) {
689942
+ out.push(artifactFromUrl(v) || artifactFromPath(v));
689943
+ }
689944
+ out.push(...extractArtifactsFromText(v));
689945
+ return;
689946
+ }
689947
+ if (Array.isArray(v)) {
689948
+ for (const item of v.slice(0, 20)) walk(item, key);
689949
+ return;
689950
+ }
689951
+ if (typeof v === 'object') {
689952
+ const obj = v;
689953
+ const kind = typeof obj.kind === 'string' ? obj.kind : '';
689954
+ const direct = obj.url || obj.href || obj.src || obj.path || obj.output || obj.file || obj.filename;
689955
+ if (typeof direct === 'string') out.push(artifactFromUrl(direct, kind) || artifactFromPath(direct, kind));
689956
+ for (const [k, child] of Object.entries(obj).slice(0, 30)) walk(child, k);
689957
+ }
689958
+ };
689959
+ walk(value, '');
689960
+ return uniqueArtifacts(out);
689961
+ }
689962
+
689963
+ async function downloadArtifact(artifact) {
689964
+ const url = artifact.url || (artifact.path ? rawFileUrl(artifact.path) : '');
689965
+ if (!url) return;
689966
+ try {
689967
+ const r = await fetch(url, { headers: headers() });
689968
+ if (!r.ok) throw new Error('HTTP ' + r.status);
689969
+ const blob = await r.blob();
689970
+ const href = URL.createObjectURL(blob);
689971
+ const a = document.createElement('a');
689972
+ a.href = href;
689973
+ a.download = artifact.name || baseNameForPath(artifact.path || url) || 'artifact';
689974
+ document.body.appendChild(a);
689975
+ a.click();
689976
+ a.remove();
689977
+ setTimeout(() => URL.revokeObjectURL(href), 5000);
689978
+ } catch (e) {
689979
+ const s = document.getElementById('status');
689980
+ if (s) {
689981
+ const old = s.textContent;
689982
+ s.textContent = 'download failed: ' + (e && e.message ? e.message : String(e));
689983
+ setTimeout(() => { s.textContent = old; }, 2500);
689984
+ }
689985
+ }
689986
+ }
689987
+
689988
+ function previewArtifact(artifact) {
689989
+ if (artifact.path) {
689990
+ previewFile(artifact.path);
689991
+ return;
689992
+ }
689993
+ const info = artifact.info || fileInfoFor({ name: artifact.name, kind: artifact.kind }, artifact.name || artifact.url);
689994
+ const shell = createFilePreviewShell(artifact.name || artifact.url, info);
689995
+ const src = artifact.url;
689996
+ const openLink = shell.card.querySelector('a');
689997
+ if (openLink) openLink.href = src;
689998
+ if (info.kind === 'audio') {
689999
+ const audio = document.createElement('audio');
690000
+ audio.controls = true;
690001
+ audio.preload = 'metadata';
690002
+ audio.src = src;
690003
+ audio.style.cssText = 'width:min(680px,82vw);display:block';
690004
+ shell.body.appendChild(audio);
690005
+ } else if (info.kind === 'video') {
690006
+ const video = document.createElement('video');
690007
+ video.controls = true;
690008
+ video.preload = 'metadata';
690009
+ video.src = src;
690010
+ video.style.cssText = 'max-width:86vw;max-height:76vh;background:#000;display:block';
690011
+ shell.body.appendChild(video);
690012
+ } else if (info.kind === 'image') {
690013
+ const img = document.createElement('img');
690014
+ img.src = src;
690015
+ img.alt = artifact.name || 'artifact';
690016
+ img.style.cssText = 'max-width:86vw;max-height:76vh;object-fit:contain;display:block';
690017
+ shell.body.appendChild(img);
690018
+ } else {
690019
+ const link = document.createElement('a');
690020
+ link.href = src;
690021
+ link.target = '_blank';
690022
+ link.rel = 'noopener noreferrer';
690023
+ link.textContent = 'open artifact';
690024
+ link.style.cssText = 'color:var(--color-brand);border:1px solid var(--color-border);border-radius:3px;padding:6px 10px;text-decoration:none';
690025
+ shell.body.appendChild(link);
690026
+ }
690027
+ document.body.appendChild(shell.modal);
690028
+ }
690029
+
690030
+ function appendArtifactControls(parent, artifacts) {
690031
+ const items = uniqueArtifacts(artifacts);
690032
+ if (!parent || items.length === 0) return null;
690033
+ const wrap = document.createElement('div');
690034
+ wrap.className = 'artifact-controls';
690035
+ wrap.style.cssText = 'display:flex;flex-direction:column;gap:6px;margin:6px 0 2px 0';
690036
+ for (const artifact of items) {
690037
+ const info = artifact.info || fileInfoFor({ name: artifact.name, kind: artifact.kind }, artifact.path || artifact.name || artifact.url);
690038
+ const row = document.createElement('div');
690039
+ row.style.cssText = 'display:flex;align-items:center;gap:8px;min-width:0;background:var(--color-bg);border:1px solid var(--color-border);border-left:2px solid var(--color-brand);border-radius:4px;padding:6px 8px;color:var(--color-fg);font-size:0.68rem';
690040
+ const label = document.createElement('span');
690041
+ label.textContent = (info.icon || '◇') + ' ' + (artifact.name || baseNameForPath(artifact.path || artifact.url || 'artifact'));
690042
+ label.title = artifact.path || artifact.url || '';
690043
+ label.style.cssText = 'min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1';
690044
+ row.appendChild(label);
690045
+
690046
+ if (info.kind === 'audio') {
690047
+ const audio = document.createElement('audio');
690048
+ audio.controls = true;
690049
+ audio.preload = 'metadata';
690050
+ audio.src = artifact.url || rawFileUrl(artifact.path);
690051
+ audio.style.cssText = 'width:min(320px,40vw);height:28px;flex:0 1 320px';
690052
+ row.appendChild(audio);
690053
+ } else if (isPreviewableArtifactInfo(info)) {
690054
+ const view = document.createElement('button');
690055
+ view.type = 'button';
690056
+ view.textContent = 'view';
690057
+ view.title = 'View ' + info.label;
690058
+ view.style.cssText = 'background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-brand);border-radius:3px;padding:3px 8px;cursor:pointer;font:inherit;font-size:0.64rem;flex-shrink:0';
690059
+ view.onclick = (e) => { e.stopPropagation(); previewArtifact(artifact); };
690060
+ row.appendChild(view);
690061
+ }
690062
+
690063
+ const download = document.createElement('button');
690064
+ download.type = 'button';
690065
+ download.textContent = 'download';
690066
+ download.title = 'Download ' + (artifact.name || 'artifact');
690067
+ download.style.cssText = 'background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-brand);border-radius:3px;padding:3px 8px;cursor:pointer;font:inherit;font-size:0.64rem;flex-shrink:0';
690068
+ download.onclick = (e) => { e.stopPropagation(); downloadArtifact(artifact); };
690069
+ row.appendChild(download);
690070
+ wrap.appendChild(row);
690071
+ }
690072
+ parent.appendChild(wrap);
690073
+ return wrap;
690074
+ }
690075
+
690076
+ function appendArtifactsForText(parent, text) {
690077
+ return appendArtifactControls(parent, extractArtifactsFromText(text));
690078
+ }
690079
+
689671
690080
  function appendFileKindBadge(row, info) {
689672
690081
  if (!info || info.kind === 'text') return;
689673
690082
  const badge = document.createElement('span');
@@ -690446,7 +690855,9 @@ async function restoreChatSession() {
690446
690855
  messages: messages,
690447
690856
  model: data.model || modelSelect.value,
690448
690857
  updatedAt: data.updated_at || data.updatedAt || new Date().toISOString(),
690449
- preview: messages.slice(-1)[0]?.content?.slice(0, 50) || 'empty',
690858
+ title: data.title || (($chatSessions.get && $chatSessions.get()) || {})[data.id]?.title || sessionDisplayTitle(data.id, { messages }),
690859
+ name: data.title || (($chatSessions.get && $chatSessions.get()) || {})[data.id]?.name || sessionDisplayTitle(data.id, { messages }),
690860
+ preview: data.preview || messages.slice(-1)[0]?.content?.slice(0, 50) || 'empty',
690450
690861
  };
690451
690862
  saveScopedSessions(saved);
690452
690863
  $chatSessions.set({ ...(($chatSessions.get && $chatSessions.get()) || {}), ...saved });
@@ -691633,7 +692044,7 @@ function _renderSidebarChats(filter) {
691633
692044
 
691634
692045
  const renderRow = (id) => {
691635
692046
  const s = sessions[id] || {};
691636
- const title = (s.title || s.name || ('Chat ' + String(id).slice(0, 8))).toString();
692047
+ const title = sessionDisplayTitle(id, s).toString();
691637
692048
  const cls = 'sb-chat' + (id === activeId ? ' active' : '');
691638
692049
  const safeId = String(id).replace(/'/g, "\\\\'");
691639
692050
  const safeTitle = title.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
@@ -701804,6 +702215,10 @@ ${historyLines}
701804
702215
  jsonResponse(res, 200, {
701805
702216
  id: session.id,
701806
702217
  model: session.model,
702218
+ title: session.title ?? null,
702219
+ preview: session.preview ?? null,
702220
+ source: session.source ?? "web",
702221
+ projectRoot: session.projectRoot ?? null,
701807
702222
  messages: publicMessages,
701808
702223
  message_count: publicMessages.length,
701809
702224
  tokens_in: session.tokensIn,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.323",
3
+ "version": "1.0.324",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.323",
9
+ "version": "1.0.324",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -5239,9 +5239,9 @@
5239
5239
  "license": "Apache-2.0 OR MIT"
5240
5240
  },
5241
5241
  "node_modules/nanoid": {
5242
- "version": "5.1.14",
5243
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.14.tgz",
5244
- "integrity": "sha512-5c8l8kVzqpnDPaicbEop/fV0Q1w16FmbWtVhMqugTozAwYdlIQojWH5a/M7UfziFmGdQRrUdV+EPzc9Xng3VAQ==",
5242
+ "version": "5.1.15",
5243
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.15.tgz",
5244
+ "integrity": "sha512-kBg3RpGtIe+RpTbyXwoI6pk5yD7KUiI3sygUqgeBMRst42KmhB4RZC7eiO9Wa1HIpaCCtpE2DJ6OI4Wi5ebwFw==",
5245
5245
  "funding": [
5246
5246
  {
5247
5247
  "type": "github",
@@ -6484,9 +6484,9 @@
6484
6484
  "license": "MIT"
6485
6485
  },
6486
6486
  "node_modules/semver": {
6487
- "version": "7.8.4",
6488
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
6489
- "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
6487
+ "version": "7.8.5",
6488
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
6489
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
6490
6490
  "license": "ISC",
6491
6491
  "bin": {
6492
6492
  "semver": "bin/semver.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.323",
3
+ "version": "1.0.324",
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",