omnius 1.0.3 → 1.0.5

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
@@ -7852,7 +7852,6 @@ var init_nexus = __esm({
7852
7852
  * Usage: node nexus-daemon.mjs <nexus-dir> <agent-name> [agent-type]
7853
7853
  */
7854
7854
 
7855
- import { NexusClient } from 'open-agents-nexus';
7856
7855
  import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync, appendFileSync, watch as fsWatch } from 'node:fs';
7857
7856
  import { join } from 'node:path';
7858
7857
  import { homedir, hostname } from 'node:os';
@@ -7930,6 +7929,40 @@ const globalKeyDir = join(homedir(), '.omnius');
7930
7929
  const globalKeyPath = join(globalKeyDir, 'identity.key');
7931
7930
  const projectKeyPath = join(nexusDir, 'identity.key');
7932
7931
  const keyPath = existsSync(globalKeyPath) ? globalKeyPath : projectKeyPath;
7932
+
7933
+ function formatStartupError(err) {
7934
+ if (!err) return 'Unknown startup error';
7935
+ var msg = err && err.stack ? String(err.stack) : String(err && err.message ? err.message : err);
7936
+ return msg.replace(/\\x1B\\[[0-?]*[ -/]*[@-~]/g, '').slice(0, 4000);
7937
+ }
7938
+
7939
+ async function loadNexusClientClass() {
7940
+ try {
7941
+ var mod = await import('open-agents-nexus');
7942
+ if (!mod || !mod.NexusClient) throw new Error('open-agents-nexus did not export NexusClient');
7943
+ return mod.NexusClient;
7944
+ } catch (err) {
7945
+ var msg = 'Failed to load open-agents-nexus: ' + formatStartupError(err);
7946
+ try { appendFileSync(join(nexusDir, 'daemon.err'), 'Nexus daemon dependency load failed: ' + msg + '\\n'); } catch {}
7947
+ try {
7948
+ writeFileSync(statusFile, JSON.stringify({
7949
+ pid: process.pid,
7950
+ connected: false,
7951
+ peerId: null,
7952
+ agentName: agentName,
7953
+ agentType: agentType,
7954
+ rooms: [],
7955
+ capabilities: [],
7956
+ blockedPeers: [],
7957
+ connectedAt: null,
7958
+ error: msg,
7959
+ }, null, 2));
7960
+ } catch {}
7961
+ process.exit(1);
7962
+ }
7963
+ }
7964
+
7965
+ const NexusClient = await loadNexusClientClass();
7933
7966
  var nexusOpts = {
7934
7967
  keyStorePath: keyPath,
7935
7968
  agentName,
@@ -13188,6 +13221,21 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13188
13221
  res((stdout || "").trim());
13189
13222
  });
13190
13223
  });
13224
+ const isNativeDataChannelError = (text) => /node-datachannel|node_datachannel\.node|datachannel\/dist/i.test(text);
13225
+ const tryRepairNodeDataChannel = async () => {
13226
+ const cmds = existsSync17(join21(this.repoRoot, "pnpm-lock.yaml")) ? ["pnpm rebuild node-datachannel 2>&1", "npm rebuild node-datachannel 2>&1"] : ["npm rebuild node-datachannel 2>&1", "pnpm rebuild node-datachannel 2>&1"];
13227
+ const failures = [];
13228
+ for (const cmd of cmds) {
13229
+ try {
13230
+ await execAsync3(cmd, { cwd: this.repoRoot, timeout: 18e4 });
13231
+ return `Repaired node-datachannel native addon with: ${cmd.replace(" 2>&1", "")}`;
13232
+ } catch (err) {
13233
+ failures.push(`${cmd.replace(" 2>&1", "")}: ${err?.message ?? String(err)}`.slice(0, 500));
13234
+ }
13235
+ }
13236
+ return `node-datachannel native addon repair failed:
13237
+ ${failures.join("\n")}`;
13238
+ };
13191
13239
  try {
13192
13240
  const nexusPkg = join21(nodeModulesDir, "open-agents-nexus", "package.json");
13193
13241
  if (existsSync17(nexusPkg)) {
@@ -13294,7 +13342,17 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13294
13342
  errTail = (await readFile9(daemonErrPath, "utf8")).slice(-300);
13295
13343
  } catch {
13296
13344
  }
13297
- return `Nexus daemon failed to connect: ${status.error}${errTail ? "\n" + errTail : ""}`;
13345
+ const statusError = String(status.error ?? "");
13346
+ if (!args.__native_repair_attempted && isNativeDataChannelError(`${statusError}
13347
+ ${errTail}`)) {
13348
+ const repair = await tryRepairNodeDataChannel();
13349
+ if (/^Repaired /.test(repair)) {
13350
+ return this.doConnect({ ...args, __native_repair_attempted: true });
13351
+ }
13352
+ return `Nexus daemon failed to connect: ${statusError}
13353
+ ${repair}${errTail ? "\n" + errTail : ""}`;
13354
+ }
13355
+ return `Nexus daemon failed to connect: ${statusError}${errTail ? "\n" + errTail : ""}`;
13298
13356
  }
13299
13357
  if (status.connected && status.peerId) {
13300
13358
  return [
@@ -13320,6 +13378,17 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13320
13378
  try {
13321
13379
  earlyOutput = (await readFile9(daemonLogPath, "utf8")).slice(-500);
13322
13380
  } catch {
13381
+ }
13382
+ const earlyCombined = `${earlyError}
13383
+ ${earlyOutput}`;
13384
+ if (!args.__native_repair_attempted && isNativeDataChannelError(earlyCombined)) {
13385
+ const repair = await tryRepairNodeDataChannel();
13386
+ if (/^Repaired /.test(repair)) {
13387
+ return this.doConnect({ ...args, __native_repair_attempted: true });
13388
+ }
13389
+ return `Daemon failed to start.
13390
+ ${repair}
13391
+ ${earlyError ? "\n" + earlyError : ""}${earlyOutput ? "\n" + earlyOutput : ""}`;
13323
13392
  }
13324
13393
  if (pid) {
13325
13394
  return `Daemon spawned (pid: ${pid}) but still connecting. Check status in a moment.${earlyError ? "\nStderr: " + earlyError.slice(0, 200) : ""}`;
@@ -526480,6 +526549,14 @@ var init_app_state = __esm({
526480
526549
  });
526481
526550
 
526482
526551
  // packages/orchestrator/dist/streaming-executor.js
526552
+ function stableValueKey(value2) {
526553
+ if (value2 === null || typeof value2 !== "object")
526554
+ return JSON.stringify(value2);
526555
+ if (Array.isArray(value2))
526556
+ return `[${value2.map(stableValueKey).join(",")}]`;
526557
+ const record = value2;
526558
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableValueKey(record[key])}`).join(",")}}`;
526559
+ }
526483
526560
  var StreamingToolExecutor;
526484
526561
  var init_streaming_executor = __esm({
526485
526562
  "packages/orchestrator/dist/streaming-executor.js"() {
@@ -526631,6 +526708,62 @@ var init_streaming_executor = __esm({
526631
526708
  return true;
526632
526709
  return false;
526633
526710
  }
526711
+ entryFingerprint(entry) {
526712
+ return `${entry.name}:${stableValueKey(entry.args)}`;
526713
+ }
526714
+ findPriorEquivalent(entry) {
526715
+ const entryIdx = this.insertionOrder.indexOf(entry.id);
526716
+ if (entryIdx <= 0 || !entry.finalized)
526717
+ return null;
526718
+ const fp = this.entryFingerprint(entry);
526719
+ for (let i2 = 0; i2 < entryIdx; i2++) {
526720
+ const prior = this.tools.get(this.insertionOrder[i2]);
526721
+ if (!prior || !prior.finalized)
526722
+ continue;
526723
+ if (this.entryFingerprint(prior) === fp)
526724
+ return prior;
526725
+ }
526726
+ return null;
526727
+ }
526728
+ cloneDuplicateResult(prior) {
526729
+ if (!prior.result)
526730
+ return null;
526731
+ const prefix = `[DUPLICATE STREAM TOOL CALL — reused result from ${prior.id}]
526732
+ `;
526733
+ return {
526734
+ success: prior.result.success,
526735
+ output: prior.result.output ? `${prefix}${prior.result.output}` : prior.result.output,
526736
+ error: prior.result.error
526737
+ };
526738
+ }
526739
+ mirrorPriorEquivalent(entry) {
526740
+ const prior = this.findPriorEquivalent(entry);
526741
+ if (!prior)
526742
+ return false;
526743
+ if ((prior.state === "completed" || prior.state === "failed" || prior.state === "yielded") && prior.result) {
526744
+ entry.state = prior.result.success ? "completed" : "failed";
526745
+ entry.result = this.cloneDuplicateResult(prior) ?? prior.result;
526746
+ entry.startedAt = prior.startedAt;
526747
+ entry.completedAt = prior.completedAt ?? Date.now();
526748
+ return true;
526749
+ }
526750
+ if (prior.state === "executing" && prior.promise) {
526751
+ entry.state = "executing";
526752
+ entry.startedAt = prior.startedAt ?? Date.now();
526753
+ entry.promise = prior.promise.then(() => {
526754
+ entry.result = this.cloneDuplicateResult(prior) ?? {
526755
+ success: false,
526756
+ output: "",
526757
+ error: "Duplicate streaming tool call could not reuse prior result"
526758
+ };
526759
+ entry.state = entry.result.success ? "completed" : "failed";
526760
+ entry.completedAt = Date.now();
526761
+ this.processQueue();
526762
+ });
526763
+ return true;
526764
+ }
526765
+ return false;
526766
+ }
526634
526767
  /**
526635
526768
  * Process the queue in insertion order.
526636
526769
  * Starts tools that can execute, stops at first exclusive tool that must wait.
@@ -526640,6 +526773,8 @@ var init_streaming_executor = __esm({
526640
526773
  const entry = this.tools.get(id);
526641
526774
  if (!entry || entry.state !== "queued")
526642
526775
  continue;
526776
+ if (this.mirrorPriorEquivalent(entry))
526777
+ continue;
526643
526778
  if (this.canExecute(entry)) {
526644
526779
  this.startExecution(entry);
526645
526780
  } else if (!entry.concurrencySafe) {
@@ -535397,6 +535532,7 @@ ${sr.result.output}`;
535397
535532
  this.emit({
535398
535533
  type: "assistant_text",
535399
535534
  content: summary,
535535
+ source: "task_complete_summary",
535400
535536
  turn,
535401
535537
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
535402
535538
  });
@@ -535437,6 +535573,7 @@ ${sr.result.output}`;
535437
535573
  this.emit({
535438
535574
  type: "assistant_text",
535439
535575
  content: summary,
535576
+ source: "task_complete_summary",
535440
535577
  turn,
535441
535578
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
535442
535579
  });
@@ -535512,6 +535649,7 @@ ${sr.result.output}`;
535512
535649
  this.emit({
535513
535650
  type: "assistant_text",
535514
535651
  content: summary,
535652
+ source: "task_complete_summary",
535515
535653
  turn,
535516
535654
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
535517
535655
  });
@@ -536237,6 +536375,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
536237
536375
  this.emit({
536238
536376
  type: "assistant_text",
536239
536377
  content: summary,
536378
+ source: "task_complete_summary",
536240
536379
  turn,
536241
536380
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
536242
536381
  });
@@ -540083,6 +540222,7 @@ ${description}`
540083
540222
  this.emit({
540084
540223
  type: "assistant_text",
540085
540224
  content: cleanContent,
540225
+ source: "model_visible_text",
540086
540226
  turn,
540087
540227
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
540088
540228
  });
@@ -549721,27 +549861,27 @@ var init_theme = __esm({
549721
549861
  },
549722
549862
  branding: {
549723
549863
  mode: "branding",
549724
- bg: 0,
549725
- // black
549726
- accent: 178,
549727
- // #ffae00 yellow
549728
- textPrimary: 178,
549729
- // #ffae00 yellow
549864
+ bg: -1,
549865
+ // terminal default background
549866
+ accent: 37,
549867
+ // teal
549868
+ textPrimary: 37,
549869
+ // teal
549730
549870
  textDim: 240,
549731
549871
  // grey
549732
- boxColor: 178
549733
- // #ffae00 yellow
549872
+ boxColor: 37
549873
+ // teal
549734
549874
  },
549735
549875
  custom: {
549736
549876
  mode: "custom",
549737
- bg: 0,
549738
- accent: 178,
549877
+ bg: -1,
549878
+ accent: 37,
549739
549879
  textPrimary: 252,
549740
549880
  textDim: 245,
549741
549881
  boxColor: 252
549742
549882
  }
549743
549883
  };
549744
- _config2 = { ...PRESETS.branding };
549884
+ _config2 = { ...PRESETS.system };
549745
549885
  }
549746
549886
  });
549747
549887
 
@@ -551291,10 +551431,10 @@ var init_render = __esm({
551291
551431
  warn: (t2) => fg256(214, t2),
551292
551432
  /** Success text — green for confirmations */
551293
551433
  ok: (t2) => fg256(78, t2),
551294
- /** Accent — yellow (178) matching header/banner */
551295
- accent: (t2) => fg256(178, t2),
551296
- /** Muted accent — dim yellow for secondary accent */
551297
- accentDim: (t2) => fg256(136, t2)
551434
+ /** Accent — teal matching header/banner */
551435
+ accent: (t2) => fg256(37, t2),
551436
+ /** Muted accent — dim teal for secondary accent */
551437
+ accentDim: (t2) => fg256(30, t2)
551298
551438
  };
551299
551439
  pastel = {
551300
551440
  pink: (t2) => fg256(218, t2),
@@ -551402,11 +551542,11 @@ var init_render = __esm({
551402
551542
  // User interaction
551403
551543
  ask_user: "Ask user"
551404
551544
  };
551405
- accent = (t2) => fg256(178, t2);
551406
- accentBright = (t2) => fg256(220, t2);
551407
- accentDim = (t2) => fg256(136, t2);
551408
- accentWarm = (t2) => fg256(214, t2);
551409
- accentSoft = (t2) => fg256(180, t2);
551545
+ accent = (t2) => fg256(37, t2);
551546
+ accentBright = (t2) => fg256(44, t2);
551547
+ accentDim = (t2) => fg256(30, t2);
551548
+ accentWarm = (t2) => fg256(43, t2);
551549
+ accentSoft = (t2) => fg256(80, t2);
551410
551550
  TOOL_COLORS = {
551411
551551
  file_read: accentSoft,
551412
551552
  file_write: accentWarm,
@@ -557646,8 +557786,8 @@ var init_braille_spinner = __esm({
557646
557786
  return (x * x * 31 + x * 17 + 59) % 97 / 97;
557647
557787
  };
557648
557788
  MOOD_RAMPS = {
557649
- neutral: [237, 94, 130, 136, 172, 172, 178, 178, 214],
557650
- // default amber→yellow
557789
+ neutral: [237, 24, 30, 36, 37, 43, 44, 50, 51],
557790
+ // default teal/cyan
557651
557791
  success: [237, 22, 28, 34, 40, 46, 47, 48, 49],
557652
557792
  // green pulse
557653
557793
  error: [237, 52, 88, 124, 160, 196, 197, 203, 209],
@@ -557658,8 +557798,8 @@ var init_braille_spinner = __esm({
557658
557798
  // purple contemplation
557659
557799
  };
557660
557800
  THEME_DEFAULT = {
557661
- ramp: [237, 94, 130, 136, 172, 172, 178, 178, 214],
557662
- // grey amber → yellow (matches header)
557801
+ ramp: [237, 24, 30, 36, 37, 43, 44, 50, 51],
557802
+ // grey -> teal/cyan
557663
557803
  speed: 2
557664
557804
  };
557665
557805
  THEME_FILE = {
@@ -557679,7 +557819,7 @@ var init_braille_spinner = __esm({
557679
557819
  speed: 4
557680
557820
  };
557681
557821
  THEME_MEMORY = {
557682
- ramp: [237, 136, 172, 178, 179, 214, 215, 220, 222],
557822
+ ramp: [237, 23, 29, 35, 36, 37, 43, 44, 50],
557683
557823
  speed: 1
557684
557824
  };
557685
557825
  THEME_SKILL = {
@@ -557691,7 +557831,7 @@ var init_braille_spinner = __esm({
557691
557831
  speed: 2
557692
557832
  };
557693
557833
  THEME_DREAM = {
557694
- ramp: [237, 94, 130, 136, 172, 178, 179, 214, 220],
557834
+ ramp: [237, 24, 30, 36, 37, 43, 44, 50, 51],
557695
557835
  speed: 1
557696
557836
  };
557697
557837
  DEFAULT_METRICS = {
@@ -558303,7 +558443,7 @@ var init_text_selection = __esm({
558303
558443
  "packages/cli/src/tui/text-selection.ts"() {
558304
558444
  "use strict";
558305
558445
  init_layout2();
558306
- SEL_BG = 178;
558446
+ SEL_BG = 37;
558307
558447
  SEL_FG = 30;
558308
558448
  SEL_START = `\x1B[${SEL_FG}m\x1B[48;5;${SEL_BG}m`;
558309
558449
  SEL_END = `\x1B[0m`;
@@ -559594,8 +559734,8 @@ var init_status_bar = __esm({
559594
559734
  const decorateMenuButton = (cmd, label) => {
559595
559735
  const isBranding = themeMode() === "branding";
559596
559736
  if (isBranding) {
559597
- const BRAND_BG = 178;
559598
- const BRAND_FG = 65;
559737
+ const BRAND_BG = 37;
559738
+ const BRAND_FG = 0;
559599
559739
  return linkify(
559600
559740
  cmd,
559601
559741
  `\x1B[38;5;${BRAND_FG}m\x1B[48;5;${BRAND_BG}m ${label} \x1B[0m${PANEL_BG_SEQ}`
@@ -561516,7 +561656,7 @@ ${CONTENT_BG_SEQ}`);
561516
561656
  if (this._contentScrollOffset > 0) {
561517
561657
  const label = " ↓ scroll to bottom ";
561518
561658
  const startCol = 3;
561519
- buf += `\x1B[${spacerRow};${startCol}H\x1B[48;5;236m\x1B[38;5;229m${label}\x1B[0m${CONTENT_BG_SEQ}`;
561659
+ buf += `\x1B[${spacerRow};${startCol}H\x1B[38;5;37m${label}\x1B[0m${CONTENT_BG_SEQ}`;
561520
561660
  this._scrollBtnRegion = {
561521
561661
  row: spacerRow,
561522
561662
  start: startCol,
@@ -564239,6 +564379,23 @@ import { promisify as promisify5 } from "node:util";
564239
564379
  import { existsSync as existsSync85, writeFileSync as writeFileSync46, readFileSync as readFileSync71, appendFileSync as appendFileSync4, mkdirSync as mkdirSync49 } from "node:fs";
564240
564380
  import { join as join102 } from "node:path";
564241
564381
  import { homedir as homedir30, platform as platform4 } from "node:os";
564382
+ function wrapText(value2, width) {
564383
+ const words = value2.split(/\s+/).filter(Boolean);
564384
+ const lines = [];
564385
+ let line = "";
564386
+ for (const word2 of words) {
564387
+ if (!line) {
564388
+ line = word2;
564389
+ } else if (Array.from(line).length + 1 + Array.from(word2).length <= width) {
564390
+ line += " " + word2;
564391
+ } else {
564392
+ lines.push(line);
564393
+ line = word2;
564394
+ }
564395
+ }
564396
+ if (line) lines.push(line);
564397
+ return lines.length > 0 ? lines : [""];
564398
+ }
564242
564399
  async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
564243
564400
  if (_toolSupportCache.has(modelName)) return _toolSupportCache.get(modelName);
564244
564401
  try {
@@ -564459,7 +564616,7 @@ function ensureCurl() {
564459
564616
  if (hasCmd("curl")) return true;
564460
564617
  const plat = platform4();
564461
564618
  if (plat === "win32") {
564462
- process.stdout.write(` ${c3.yellow("⚠")} curl not found on Windows — install it manually.
564619
+ process.stdout.write(` ${c3.cyan("⚠")} curl not found on Windows — install it manually.
564463
564620
  `);
564464
564621
  return false;
564465
564622
  }
@@ -564483,7 +564640,7 @@ function ensureCurl() {
564483
564640
  return true;
564484
564641
  }
564485
564642
  } catch {
564486
- process.stdout.write(` ${c3.yellow("⚠")} ${s2.label} install failed, trying next...
564643
+ process.stdout.write(` ${c3.cyan("⚠")} ${s2.label} install failed, trying next...
564487
564644
  `);
564488
564645
  }
564489
564646
  }
@@ -564520,7 +564677,7 @@ function ensureZstd() {
564520
564677
  else if (hasCmd("apk")) installCmd = "apk add --no-cache zstd";
564521
564678
  if (!installCmd) {
564522
564679
  process.stdout.write(`
564523
- ${c3.yellow("⚠")} Could not detect package manager to install zstd.
564680
+ ${c3.cyan("⚠")} Could not detect package manager to install zstd.
564524
564681
  `);
564525
564682
  return false;
564526
564683
  }
@@ -564689,7 +564846,7 @@ function runElevatedCommand(command, opts = {}) {
564689
564846
  function runOllamaInstallScript() {
564690
564847
  const zstdReady = ensureZstd();
564691
564848
  if (!zstdReady) {
564692
- process.stdout.write(` ${c3.yellow("⚠")} Proceeding without zstd — install may fail if the script requires it.
564849
+ process.stdout.write(` ${c3.cyan("⚠")} Proceeding without zstd — install may fail if the script requires it.
564693
564850
  `);
564694
564851
  }
564695
564852
  const elevated = buildElevatedInstall();
@@ -564700,9 +564857,9 @@ function runOllamaInstallScript() {
564700
564857
  process.stdout.write(` ${c3.cyan("●")} Elevation: SUDO_ASKPASS (GUI password modal)
564701
564858
  `);
564702
564859
  } else {
564703
- process.stdout.write(` ${c3.yellow("⚠")} No GUI password helper available — install may stall waiting for sudo.
564860
+ process.stdout.write(` ${c3.cyan("⚠")} No GUI password helper available — install may stall waiting for sudo.
564704
564861
  `);
564705
- process.stdout.write(` ${c3.yellow("⚠")} Install one of: pkexec / zenity / kdialog / yad / ssh-askpass
564862
+ process.stdout.write(` ${c3.cyan("⚠")} Install one of: pkexec / zenity / kdialog / yad / ssh-askpass
564706
564863
  `);
564707
564864
  }
564708
564865
  const runOnce = () => {
@@ -564722,7 +564879,7 @@ function runOllamaInstallScript() {
564722
564879
  const combined = stderr + "\n" + message2;
564723
564880
  if (combined.includes("requires zstd") || combined.includes("install zstd")) {
564724
564881
  process.stdout.write(`
564725
- ${c3.yellow("⚠")} Ollama install script requires zstd. Attempting to install it...
564882
+ ${c3.cyan("⚠")} Ollama install script requires zstd. Attempting to install it...
564726
564883
  `);
564727
564884
  if (ensureZstd()) {
564728
564885
  runOnce();
@@ -564747,7 +564904,7 @@ async function autoInstallOllama(rl) {
564747
564904
  } else if (plat === "win32") {
564748
564905
  return installOllamaWindows();
564749
564906
  }
564750
- process.stdout.write(` ${c3.yellow("⚠")} Unsupported platform: ${plat}
564907
+ process.stdout.write(` ${c3.cyan("⚠")} Unsupported platform: ${plat}
564751
564908
  `);
564752
564909
  process.stdout.write(` ${c3.dim("Visit https://ollama.com to install manually.")}
564753
564910
 
@@ -564768,7 +564925,7 @@ function installOllamaLinux() {
564768
564925
  return true;
564769
564926
  }
564770
564927
  process.stdout.write(`
564771
- ${c3.yellow("⚠")} Install script ran but ollama not found on PATH.
564928
+ ${c3.cyan("⚠")} Install script ran but ollama not found on PATH.
564772
564929
  `);
564773
564930
  return false;
564774
564931
  } catch (err) {
@@ -564802,7 +564959,7 @@ async function installOllamaMac(_rl) {
564802
564959
  `);
564803
564960
  } else {
564804
564961
  process.stdout.write(`
564805
- ${c3.yellow("⚠")} Homebrew install completed but brew not found on PATH.
564962
+ ${c3.cyan("⚠")} Homebrew install completed but brew not found on PATH.
564806
564963
  `);
564807
564964
  process.stdout.write(` ${c3.dim('Try: eval "$(/opt/homebrew/bin/brew shellenv)"')}
564808
564965
 
@@ -564832,7 +564989,7 @@ async function installOllamaMac(_rl) {
564832
564989
  return true;
564833
564990
  }
564834
564991
  process.stdout.write(`
564835
- ${c3.yellow("⚠")} brew install completed but ollama not found on PATH.
564992
+ ${c3.cyan("⚠")} brew install completed but ollama not found on PATH.
564836
564993
  `);
564837
564994
  return false;
564838
564995
  } catch (err) {
@@ -564859,7 +565016,7 @@ function installOllamaWindows() {
564859
565016
  return true;
564860
565017
  }
564861
565018
  process.stdout.write(`
564862
- ${c3.yellow("⚠")} Install script ran but ollama not found on PATH.
565019
+ ${c3.cyan("⚠")} Install script ran but ollama not found on PATH.
564863
565020
  `);
564864
565021
  return false;
564865
565022
  } catch (err) {
@@ -564874,7 +565031,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
564874
565031
  if (!ollamaInstalled) {
564875
565032
  if (rl) {
564876
565033
  process.stdout.write(`
564877
- ${c3.yellow("⚠")} Ollama is not installed on this system.
565034
+ ${c3.cyan("⚠")} Ollama is not installed on this system.
564878
565035
  `);
564879
565036
  const answer = await ask(rl, ` ${c3.bold("Install Ollama now?")} (Y/n) `);
564880
565037
  if (answer.toLowerCase() === "n") {
@@ -564901,7 +565058,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
564901
565058
  const child = spawn24("ollama", ["serve"], { stdio: "ignore", detached: true });
564902
565059
  child.unref();
564903
565060
  } catch {
564904
- process.stdout.write(` ${c3.yellow("⚠")} Could not start ollama serve.
565061
+ process.stdout.write(` ${c3.cyan("⚠")} Could not start ollama serve.
564905
565062
 
564906
565063
  `);
564907
565064
  return false;
@@ -564921,7 +565078,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
564921
565078
  } catch {
564922
565079
  }
564923
565080
  }
564924
- process.stdout.write(` ${c3.yellow("⚠")} Ollama started but not responding. Try ${c3.bold("ollama serve")} manually.
565081
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama started but not responding. Try ${c3.bold("ollama serve")} manually.
564925
565082
 
564926
565083
  `);
564927
565084
  return false;
@@ -564996,7 +565153,7 @@ function pullModelWithAutoUpdate(tag) {
564996
565153
  const combined = errMsg + "\n" + stderr;
564997
565154
  if (combined.includes("412") || combined.includes("newer version") || combined.includes("requires a newer version")) {
564998
565155
  process.stdout.write(`
564999
- ${c3.yellow("⚠")} Ollama needs to be updated for this model.
565156
+ ${c3.cyan("⚠")} Ollama needs to be updated for this model.
565000
565157
  `);
565001
565158
  if (!ensureCurl()) {
565002
565159
  throw new Error("curl is required to update Ollama but could not be installed.");
@@ -565124,7 +565281,7 @@ function ensurePython3() {
565124
565281
  }
565125
565282
  }
565126
565283
  }
565127
- process.stdout.write(` ${c3.yellow("⚠")} Could not install Python3 automatically. Install manually.
565284
+ process.stdout.write(` ${c3.cyan("⚠")} Could not install Python3 automatically. Install manually.
565128
565285
 
565129
565286
  `);
565130
565287
  }
@@ -565163,7 +565320,7 @@ function ensurePythonVenv() {
565163
565320
  }
565164
565321
  }
565165
565322
  }
565166
- process.stdout.write(` ${c3.yellow("⚠")} Could not install python3-venv. Install manually: sudo apt install python3-venv
565323
+ process.stdout.write(` ${c3.cyan("⚠")} Could not install python3-venv. Install manually: sudo apt install python3-venv
565167
565324
 
565168
565325
  `);
565169
565326
  }
@@ -565249,12 +565406,12 @@ async function promptForCustomEndpoint(config, rl) {
565249
565406
  }
565250
565407
  }
565251
565408
  if (!testOk) {
565252
- process.stdout.write(` ${c3.yellow("⚠")} Endpoint returned HTTP ${resp.status}
565409
+ process.stdout.write(` ${c3.cyan("⚠")} Endpoint returned HTTP ${resp.status}
565253
565410
  `);
565254
565411
  }
565255
565412
  }
565256
565413
  } catch (err) {
565257
- process.stdout.write(` ${c3.yellow("⚠")} Could not reach endpoint: ${err instanceof Error ? err.message : String(err)}
565414
+ process.stdout.write(` ${c3.cyan("⚠")} Could not reach endpoint: ${err instanceof Error ? err.message : String(err)}
565258
565415
  `);
565259
565416
  }
565260
565417
  if (!testOk) {
@@ -565292,7 +565449,7 @@ async function promptForCustomEndpoint(config, rl) {
565292
565449
  }
565293
565450
  async function doSetup(config, rl) {
565294
565451
  process.stdout.write(`
565295
- ${c3.bold(c3.cyan("omnius"))}
565452
+ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
565296
565453
  `);
565297
565454
  process.stdout.write(` ${c3.dim("─".repeat(60))}
565298
565455
  `);
@@ -565329,36 +565486,43 @@ async function doSetup(config, rl) {
565329
565486
  const bw = 30;
565330
565487
  const sw = 24;
565331
565488
  const boxW = 52;
565332
- const boxLine = (content, visLen) => {
565489
+ const boxLine = (content) => {
565490
+ const visLen = visibleLen(content);
565333
565491
  const pad = Math.max(0, boxW - visLen);
565334
565492
  return ` ${c3.dim("│")}${content}${" ".repeat(pad)}${c3.dim("│")}
565335
565493
  `;
565336
565494
  };
565495
+ const boxWrappedDimLine = (content, indent = " ") => {
565496
+ const lines = wrapText(content, Math.max(1, boxW - visibleLen(indent)));
565497
+ for (const line of lines) {
565498
+ process.stdout.write(boxLine(`${indent}${c3.dim(line)}`));
565499
+ }
565500
+ };
565337
565501
  const hLine = (ch) => ` ${c3.dim(ch + "─".repeat(boxW) + (ch === "┌" ? "┐" : ch === "├" ? "┤" : "┘"))}
565338
565502
  `;
565339
565503
  process.stdout.write("\n");
565340
565504
  process.stdout.write(hLine("┌"));
565341
- process.stdout.write(boxLine(` ${c3.bold("Inference Capability")}`, 22));
565505
+ process.stdout.write(boxLine(` ${c3.bold("Inference Capability")}`));
565342
565506
  process.stdout.write(hLine("├"));
565343
- process.stdout.write(boxLine(` ${c3.bold("Overall")}`, 9));
565507
+ process.stdout.write(boxLine(` ${c3.bold("Overall")}`));
565344
565508
  const overallBar = renderScoreBar(score.overall, bw);
565345
565509
  const overallLabel = `${String(score.overall).padStart(3)}/100`;
565346
- process.stdout.write(boxLine(` ${overallBar} ${c3.bold(overallLabel)}`, 2 + bw + 1 + overallLabel.length));
565347
- process.stdout.write(boxLine(` ${c3.dim(score.summary)}`, 2 + score.summary.length));
565510
+ process.stdout.write(boxLine(` ${overallBar} ${c3.bold(overallLabel)}`));
565511
+ boxWrappedDimLine(score.summary);
565348
565512
  process.stdout.write(hLine("├"));
565349
565513
  const memLabel = `${specs.totalRamGB.toFixed(0)} GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)} GB VRAM` : "");
565350
- process.stdout.write(boxLine(` ${c3.bold("Memory")} ${c3.dim(memLabel)}`, 11 + memLabel.length));
565351
- process.stdout.write(boxLine(` ${renderScoreBar(score.memory, sw)} ${String(score.memory).padStart(3)}`, 2 + sw + 1 + 3));
565352
- process.stdout.write(boxLine("", 0));
565514
+ process.stdout.write(boxLine(` ${c3.bold("Memory")} ${c3.dim(memLabel)}`));
565515
+ process.stdout.write(boxLine(` ${renderScoreBar(score.memory, sw)} ${String(score.memory).padStart(3)}`));
565516
+ process.stdout.write(boxLine(""));
565353
565517
  const gpuLabel = specs.gpuVramGB > 0 ? specs.gpuName || "NVIDIA GPU" : "CPU only";
565354
- process.stdout.write(boxLine(` ${c3.bold("Compute")} ${c3.dim(gpuLabel)}`, 11 + gpuLabel.length));
565355
- process.stdout.write(boxLine(` ${renderScoreBar(score.compute, sw)} ${String(score.compute).padStart(3)}`, 2 + sw + 1 + 3));
565356
- process.stdout.write(boxLine("", 0));
565518
+ process.stdout.write(boxLine(` ${c3.bold("Compute")} ${c3.dim(gpuLabel)}`));
565519
+ process.stdout.write(boxLine(` ${renderScoreBar(score.compute, sw)} ${String(score.compute).padStart(3)}`));
565520
+ process.stdout.write(boxLine(""));
565357
565521
  const speedLabel = specs.gpuVramGB > 0 ? "GPU accelerated" : "CPU inference";
565358
- process.stdout.write(boxLine(` ${c3.bold("Speed")} ${c3.dim(speedLabel)}`, 11 + speedLabel.length));
565359
- process.stdout.write(boxLine(` ${renderScoreBar(score.speed, sw)} ${String(score.speed).padStart(3)}`, 2 + sw + 1 + 3));
565522
+ process.stdout.write(boxLine(` ${c3.bold("Speed")} ${c3.dim(speedLabel)}`));
565523
+ process.stdout.write(boxLine(` ${renderScoreBar(score.speed, sw)} ${String(score.speed).padStart(3)}`));
565360
565524
  process.stdout.write(hLine("├"));
565361
- process.stdout.write(boxLine(` ${c3.bold("Model Compatibility")}`, 21));
565525
+ process.stdout.write(boxLine(` ${c3.bold("Model Compatibility")}`));
565362
565526
  for (const compat of score.modelCompat) {
565363
565527
  const icon = compat.fits ? c3.green("✔") : c3.red("✖");
565364
565528
  const tag = compat.fits ? compat.tag : c3.dim(compat.tag);
@@ -565372,7 +565536,7 @@ async function doSetup(config, rl) {
565372
565536
  process.stdout.write("\n");
565373
565537
  let hasPython = hasCmd("python3") || hasCmd("python");
565374
565538
  if (!hasPython) {
565375
- process.stdout.write(` ${c3.yellow("⚠")} Python3 not found (needed for vision, OCR, browser automation).
565539
+ process.stdout.write(` ${c3.cyan("⚠")} Python3 not found (needed for vision, OCR, browser automation).
565376
565540
  `);
565377
565541
  const installPy = await ask(rl, ` ${c3.bold("Install Python3?")} (Y/n) `);
565378
565542
  if (installPy.toLowerCase() !== "n") {
@@ -565383,7 +565547,7 @@ async function doSetup(config, rl) {
565383
565547
  if (hasPython) {
565384
565548
  const hasVenv = checkPythonVenv();
565385
565549
  if (!hasVenv) {
565386
- process.stdout.write(` ${c3.yellow("⚠")} Python3 venv module not found (needed for Moondream, OCR, browser automation).
565550
+ process.stdout.write(` ${c3.cyan("⚠")} Python3 venv module not found (needed for Moondream, OCR, browser automation).
565387
565551
  `);
565388
565552
  const installVenv = await ask(rl, ` ${c3.bold("Install python3-venv?")} (Y/n) `);
565389
565553
  if (installVenv.toLowerCase() !== "n") {
@@ -565396,7 +565560,7 @@ async function doSetup(config, rl) {
565396
565560
  try {
565397
565561
  models = await fetchOllamaModels(config.backendUrl);
565398
565562
  } catch {
565399
- process.stdout.write(` ${c3.yellow("⚠")} Cannot reach Ollama at ${c3.bold(config.backendUrl)}
565563
+ process.stdout.write(` ${c3.cyan("⚠")} Cannot reach Ollama at ${c3.bold(config.backendUrl)}
565400
565564
 
565401
565565
  `);
565402
565566
  const useCustom = await ask(rl, ` ${c3.bold("Use a custom inference endpoint instead?")} (Y/n) `);
@@ -565422,12 +565586,12 @@ async function doSetup(config, rl) {
565422
565586
 
565423
565587
  `);
565424
565588
  } catch {
565425
- process.stdout.write(` ${c3.yellow("⚠")} Ollama started but not responding yet. It may need a moment.
565589
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama started but not responding yet. It may need a moment.
565426
565590
 
565427
565591
  `);
565428
565592
  }
565429
565593
  } catch {
565430
- process.stdout.write(` ${c3.yellow("⚠")} Could not start Ollama. Try running ${c3.bold("ollama serve")} manually.
565594
+ process.stdout.write(` ${c3.cyan("⚠")} Could not start Ollama. Try running ${c3.bold("ollama serve")} manually.
565431
565595
 
565432
565596
  `);
565433
565597
  }
@@ -565450,12 +565614,12 @@ async function doSetup(config, rl) {
565450
565614
 
565451
565615
  `);
565452
565616
  } catch {
565453
- process.stdout.write(` ${c3.yellow("⚠")} Ollama installed but not responding yet. Try ${c3.bold("ollama serve")} manually.
565617
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama installed but not responding yet. Try ${c3.bold("ollama serve")} manually.
565454
565618
 
565455
565619
  `);
565456
565620
  }
565457
565621
  } catch {
565458
- process.stdout.write(` ${c3.yellow("⚠")} Ollama installed. Start it with: ${c3.bold("ollama serve")}
565622
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama installed. Start it with: ${c3.bold("ollama serve")}
565459
565623
 
565460
565624
  `);
565461
565625
  }
@@ -565482,7 +565646,7 @@ async function doSetup(config, rl) {
565482
565646
  `);
565483
565647
  return currentModel.name;
565484
565648
  }
565485
- process.stdout.write(` ${c3.yellow("⚠")} Default model ${c3.bold(config.model)} is not available.
565649
+ process.stdout.write(` ${c3.cyan("⚠")} Default model ${c3.bold(config.model)} is not available.
565486
565650
 
565487
565651
  `);
565488
565652
  if (models.length > 0) {
@@ -565514,7 +565678,7 @@ async function doSetup(config, rl) {
565514
565678
  return selected.name;
565515
565679
  }
565516
565680
  } else {
565517
- process.stdout.write(` ${c3.yellow("⚠")} No models found on this system.
565681
+ process.stdout.write(` ${c3.cyan("⚠")} No models found on this system.
565518
565682
 
565519
565683
  `);
565520
565684
  }
@@ -566584,7 +566748,7 @@ export PATH="${binDir}:$PATH" # Added by omnius for nvim
566584
566748
  } catch {
566585
566749
  }
566586
566750
  }
566587
- var execAsync2, QWEN_VARIANTS, _toolSupportCache, _cloudflaredInstallPromise;
566751
+ var execAsync2, OMNIUS_FIRST_RUN_BANNER, ANSI_RE, visibleLen, QWEN_VARIANTS, _toolSupportCache, _cloudflaredInstallPromise;
566588
566752
  var init_setup = __esm({
566589
566753
  "packages/cli/src/tui/setup.ts"() {
566590
566754
  "use strict";
@@ -566594,6 +566758,17 @@ var init_setup = __esm({
566594
566758
  init_dist();
566595
566759
  init_tui_select();
566596
566760
  execAsync2 = promisify5(exec4);
566761
+ OMNIUS_FIRST_RUN_BANNER = [
566762
+ " ░▒▓██████▓▒░░▒▓██████████████▓▒░░▒▓███████▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓███████▓▒░ ",
566763
+ "░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ",
566764
+ "░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ",
566765
+ "░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░ ",
566766
+ "░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ",
566767
+ "░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ",
566768
+ " ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░ "
566769
+ ].join("\n");
566770
+ ANSI_RE = /\x1B\[[0-?]*[ -/]*[@-~]/g;
566771
+ visibleLen = (value2) => Array.from(value2.replace(ANSI_RE, "")).length;
566597
566772
  QWEN_VARIANTS = [
566598
566773
  { tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
566599
566774
  { tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
@@ -581466,7 +581641,7 @@ async function showColorMenu(ctx3) {
581466
581641
  {
581467
581642
  key: "branding",
581468
581643
  label: `Omnius Branding${currentConfig.mode === "branding" ? " (active)" : ""}`,
581469
- detail: "#ffae00 accent on black"
581644
+ detail: "Teal accent on terminal background"
581470
581645
  },
581471
581646
  {
581472
581647
  key: "custom",
@@ -587626,30 +587801,30 @@ function getNodeMnemonic() {
587626
587801
  function createDefaultBanner(version4 = "0.120.0") {
587627
587802
  const width = termCols();
587628
587803
  const rows = headerHeight();
587629
- const yellow = tuiAccent() < 0 ? -1 : tuiAccent();
587804
+ const accent2 = tuiAccent() < 0 ? -1 : tuiAccent();
587630
587805
  const bgBlack = tuiBg() < 0 ? -1 : tuiBg();
587631
587806
  const grid = [];
587632
587807
  const innerW = width - 2;
587633
587808
  const topRow = [];
587634
- topRow.push({ char: "╭", fg: yellow, bg: bgBlack, bold: false });
587809
+ topRow.push({ char: "╭", fg: accent2, bg: bgBlack, bold: false });
587635
587810
  for (let c9 = 0; c9 < innerW; c9++) {
587636
- topRow.push({ char: "─", fg: yellow, bg: bgBlack, bold: false });
587811
+ topRow.push({ char: "─", fg: accent2, bg: bgBlack, bold: false });
587637
587812
  }
587638
- topRow.push({ char: "╮", fg: yellow, bg: bgBlack, bold: false });
587813
+ topRow.push({ char: "╮", fg: accent2, bg: bgBlack, bold: false });
587639
587814
  grid.push(topRow);
587640
587815
  const midRow = [];
587641
- midRow.push({ char: "│", fg: yellow, bg: bgBlack, bold: false });
587816
+ midRow.push({ char: "│", fg: accent2, bg: bgBlack, bold: false });
587642
587817
  for (let c9 = 0; c9 < innerW; c9++) {
587643
587818
  midRow.push({ char: " ", fg: 0, bg: bgBlack, bold: false });
587644
587819
  }
587645
- midRow.push({ char: "│", fg: yellow, bg: bgBlack, bold: false });
587820
+ midRow.push({ char: "│", fg: accent2, bg: bgBlack, bold: false });
587646
587821
  grid.push(midRow);
587647
587822
  const botRow = [];
587648
- botRow.push({ char: "╰", fg: yellow, bg: bgBlack, bold: false });
587823
+ botRow.push({ char: "╰", fg: accent2, bg: bgBlack, bold: false });
587649
587824
  for (let c9 = 0; c9 < innerW; c9++) {
587650
- botRow.push({ char: "─", fg: yellow, bg: bgBlack, bold: false });
587825
+ botRow.push({ char: "─", fg: accent2, bg: bgBlack, bold: false });
587651
587826
  }
587652
- botRow.push({ char: "╯", fg: yellow, bg: bgBlack, bold: false });
587827
+ botRow.push({ char: "╯", fg: accent2, bg: bgBlack, bold: false });
587653
587828
  grid.push(botRow);
587654
587829
  return {
587655
587830
  id: "default-header",
@@ -588330,7 +588505,7 @@ var init_carousel_descriptors = __esm({
588330
588505
  },
588331
588506
  {
588332
588507
  name: "memory",
588333
- colors: [136, 172, 178, 179, 214, 215, 220, 222],
588508
+ colors: [23, 29, 35, 36, 37, 43, 44, 50],
588334
588509
  tools: ["memory_read", "memory_write"]
588335
588510
  },
588336
588511
  {
@@ -593226,7 +593401,7 @@ import { mkdirSync as mkdirSync60, existsSync as existsSync105, unlinkSync as un
593226
593401
  import { join as join120, resolve as resolve39, basename as basename22 } from "node:path";
593227
593402
  import { writeFile as writeFileAsync } from "node:fs/promises";
593228
593403
  import { createHash as createHash19, randomInt } from "node:crypto";
593229
- function parseTelegramInteractionDecision(text, forcedRoute) {
593404
+ function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
593230
593405
  const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
593231
593406
  const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
593232
593407
  if (!jsonText) return null;
@@ -593236,7 +593411,7 @@ function parseTelegramInteractionDecision(text, forcedRoute) {
593236
593411
  const route = forcedRoute ?? parsedRoute;
593237
593412
  if (!route) return null;
593238
593413
  const shouldReplyRaw = parsed["should_reply"] ?? parsed["shouldReply"];
593239
- const shouldReply = typeof shouldReplyRaw === "boolean" ? shouldReplyRaw : true;
593414
+ const shouldReply = typeof shouldReplyRaw === "boolean" ? shouldReplyRaw : options2.defaultShouldReply ?? true;
593240
593415
  const confidenceRaw = Number(parsed["confidence"]);
593241
593416
  const confidence = Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : 0;
593242
593417
  const reason = String(parsed["reason"] ?? "live inference decision").slice(0, 240);
@@ -593299,6 +593474,41 @@ function sanitizeTelegramProgressText(text, maxLength) {
593299
593474
  const compact = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
593300
593475
  return compact.length > maxLength ? compact.slice(0, Math.max(0, maxLength - 3)) + "..." : compact;
593301
593476
  }
593477
+ function compactTelegramVisibleText(text) {
593478
+ return stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
593479
+ }
593480
+ function isTelegramPotentialNoReplyPrefix(text) {
593481
+ const lower = compactTelegramVisibleText(text).toLowerCase();
593482
+ return Boolean(lower) && "no_reply".startsWith(lower);
593483
+ }
593484
+ function isTelegramNoReplySentinel(text) {
593485
+ const lower = compactTelegramVisibleText(text).toLowerCase();
593486
+ return lower === "no_reply" || lower.startsWith("no_reply");
593487
+ }
593488
+ function isTelegramInternalStatusText(text) {
593489
+ const compact = compactTelegramVisibleText(text);
593490
+ if (!compact) return false;
593491
+ const lower = compact.toLowerCase();
593492
+ if (isTelegramNoReplySentinel(compact)) return true;
593493
+ if (lower === "complete" || lower === "completed") return true;
593494
+ if (/^memory stage:/i.test(compact)) return true;
593495
+ if (/^\[ppr[-_\s]?skip\]/i.test(compact)) return true;
593496
+ if (/^(casual|ambient|group)\b.{0,180}\b(skipping|skipped|not directed|no action needed|no reply)\b/i.test(compact)) return true;
593497
+ if (/^no further action needed\b/i.test(compact)) return true;
593498
+ if (/^no action needed\b.{0,120}\b(task|complete|completed|done)\b/i.test(compact)) return true;
593499
+ if (/^(there'?s|there is) no active task\b/i.test(compact)) return true;
593500
+ if (/^everything'?s (done|complete|completed|wrapped up)\b/i.test(compact)) return true;
593501
+ if (/\balready (been )?(provided|answered|handled|delivered) above\b/i.test(compact)) return true;
593502
+ if (/\b(no remaining work|nothing left to do|task is complete|task has been completed)\b/i.test(compact)) return true;
593503
+ return false;
593504
+ }
593505
+ function cleanTelegramVisibleReply(text, options2 = {}) {
593506
+ const clean3 = stripTelegramHiddenThinking(text).trim();
593507
+ if (!clean3) return "";
593508
+ if (options2.suppressPotentialNoReplyPrefix && isTelegramPotentialNoReplyPrefix(clean3)) return "";
593509
+ if (isTelegramInternalStatusText(clean3)) return "";
593510
+ return clean3;
593511
+ }
593302
593512
  function truncateTelegramContext(text, maxLength) {
593303
593513
  const trimmed = text.trim();
593304
593514
  if (trimmed.length <= maxLength) return trimmed;
@@ -593419,13 +593629,14 @@ function selectTelegramFinalResponse(args) {
593419
593629
  args.streamText,
593420
593630
  args.accumulated,
593421
593631
  args.assistantText
593422
- ].map((candidate) => stripTelegramHiddenThinking(candidate || "").trim()).filter(Boolean);
593632
+ ].map((candidate) => cleanTelegramVisibleReply(candidate || "")).filter(Boolean);
593423
593633
  if (visibleCandidates.length > 0) {
593424
593634
  return visibleCandidates.reduce(
593425
593635
  (best, current) => current.length > best.length ? current : best
593426
593636
  );
593427
593637
  }
593428
- return stripTelegramHiddenThinking(args.summary || "").trim();
593638
+ void args.summary;
593639
+ return "";
593429
593640
  }
593430
593641
  function formatTelegramProgressEvent(event) {
593431
593642
  if (event.type === "tool_call" && event.toolName === "task_complete") return null;
@@ -593435,23 +593646,25 @@ function formatTelegramProgressEvent(event) {
593435
593646
  }
593436
593647
  if (event.type === "tool_result") {
593437
593648
  const preview = sanitizeTelegramProgressText(event.content || "", 80);
593649
+ if (isTelegramInternalStatusText(preview)) return null;
593438
593650
  const toolName = escapeTelegramHTML(event.toolName || "tool");
593439
593651
  if (preview) return `${toolName}: ${escapeTelegramHTML(preview)}`;
593440
593652
  return event.success ? `${toolName} completed` : `${toolName} failed`;
593441
593653
  }
593442
593654
  if (event.type === "status") {
593443
593655
  const content = sanitizeTelegramProgressText(event.content || "", 120);
593656
+ if (isTelegramInternalStatusText(content)) return null;
593444
593657
  return content ? escapeTelegramHTML(content) : null;
593445
593658
  }
593446
593659
  return null;
593447
593660
  }
593448
593661
  function renderTelegramLiveProgressHTML(progressLines, accumulated) {
593449
- const draft = stripTelegramHiddenThinking(accumulated).trim();
593662
+ const draft = cleanTelegramVisibleReply(accumulated, { suppressPotentialNoReplyPrefix: true });
593450
593663
  if (draft) {
593451
593664
  const clipped = draft.length > 2e3 ? `${draft.slice(0, 1997).trimEnd()}...` : draft;
593452
593665
  return convertMarkdownToTelegramHTML(clipped);
593453
593666
  }
593454
- return progressLines.slice(-6).map((line) => line.trim()).filter(Boolean).join("\n");
593667
+ return progressLines.slice(-6).map((line) => line.trim()).filter((line) => !isTelegramInternalStatusText(line)).filter(Boolean).join("\n");
593455
593668
  }
593456
593669
  function telegramSyntheticHelpSignatures() {
593457
593670
  return [
@@ -593935,14 +594148,17 @@ RULES FOR GROUP CONTEXT:
593935
594148
  6. You may share general knowledge and helpful guidance
593936
594149
  `.trim();
593937
594150
  GROUP_REPLY_DISCRETION_PROMPT = `
593938
- REPLY DISCRETION: You are in a group chat. Only respond if:
593939
- 1. Someone @mentioned the bot directly
593940
- 2. The message is a reply to one of your previous messages
593941
- 3. The message clearly asks a question or requests help
593942
- 4. You have genuinely useful information to contribute
593943
-
593944
- If the message is casual group chatter not directed at you, use task_complete
593945
- with summary "no_reply" to silently skip without responding.
594151
+ REPLY DISCRETION: You are in a group chat. The live router has already filtered
594152
+ most ambient chatter. Continue to be selective:
594153
+ 1. Respond when someone directly addresses the bot, replies to the bot, or keeps
594154
+ an active bot-involved task moving.
594155
+ 2. Stay silent for conversation between other people, third-person commentary
594156
+ about the bot, status chatter, or questions clearly meant for someone else.
594157
+ 3. Do not reply just because you know an answer or could add color.
594158
+
594159
+ If you determine no visible reply should be sent, call task_complete with summary
594160
+ "no_reply". Never write "no_reply", "skipping", "no action needed", or a status
594161
+ explanation as assistant text.
593946
594162
  `.trim();
593947
594163
  TELEGRAM_CHAT_MODE_PROMPT = `
593948
594164
  You are Omnius replying in Telegram quick-chat mode.
@@ -593956,6 +594172,7 @@ Rules:
593956
594172
  6. Use the Telegram conversation context stream as the source of truth for who said what, recent group dynamics, and retained earlier context.
593957
594173
  7. Do not claim older chat is unavailable when the context stream contains it. If asked what you see, summarize the supplied transcript, speakers, and relationship/tone signals.
593958
594174
  8. Mirror the current sender's tone and directness while staying safe and clear.
594175
+ 9. Never send router decisions, skip explanations, memory-stage notes, task-complete summaries, or "no_reply" as chat text.
593959
594176
  `.trim();
593960
594177
  ADMIN_CHAT_PROFILE_PROMPT = `
593961
594178
  You are replying to the authenticated Telegram admin in a private DM.
@@ -593972,6 +594189,7 @@ Capabilities:
593972
594189
  Telegram response contract:
593973
594190
  - Write the actual Telegram reply as normal assistant text before completion.
593974
594191
  - task_complete is only an internal completion signal; do not put status reports, wrap-up notes, or meta-commentary there.
594192
+ - "no_reply" is an internal silent-skip sentinel only; never emit it or explain it in assistant text.
593975
594193
  - Do not summarize the fact that you answered; the visible assistant text must be the answer itself.
593976
594194
  - If you delegated long-running work, include the sub-agent id/status and what the admin should expect next.
593977
594195
  `.trim();
@@ -594076,6 +594294,8 @@ Telegram response contract:
594076
594294
  groupSkipLogAt = /* @__PURE__ */ new Map();
594077
594295
  /** Telegram interaction routing profile */
594078
594296
  interactionMode = "auto";
594297
+ /** Actual model context window discovered by the main TUI. */
594298
+ contextWindowSize = 0;
594079
594299
  /** Event handler for forwarding sub-agent events to parent TUI */
594080
594300
  onSubAgentEvent = null;
594081
594301
  /** Tool policy config — user overrides from config */
@@ -594126,6 +594346,9 @@ Telegram response contract:
594126
594346
  getInteractionMode() {
594127
594347
  return this.interactionMode;
594128
594348
  }
594349
+ setContextWindowSize(size) {
594350
+ this.contextWindowSize = Number.isFinite(size) && size > 0 ? Math.trunc(size) : 0;
594351
+ }
594129
594352
  /** Update tool policy config at runtime (e.g., from /disable command) */
594130
594353
  setToolPolicyConfig(config) {
594131
594354
  this.toolPolicyConfig = config;
@@ -594627,6 +594850,7 @@ ${lines.join("\n")}`);
594627
594850
  return sections.join("\n\n");
594628
594851
  }
594629
594852
  maybeLogTelegramGroupSkip(msg, reason) {
594853
+ if (process.env["OMNIUS_TELEGRAM_DEBUG_SKIPS"] !== "1") return;
594630
594854
  const sessionKey = this.sessionKeyForMessage(msg);
594631
594855
  const now = Date.now();
594632
594856
  const last2 = this.groupSkipLogAt.get(sessionKey) ?? 0;
@@ -594637,17 +594861,17 @@ ${lines.join("\n")}`);
594637
594861
  async inferTelegramInteractionDecision(msg, toolContext) {
594638
594862
  const config = this.agentConfig;
594639
594863
  const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
594864
+ const isGroup = msg.chatType !== "private";
594640
594865
  if (!config) {
594641
594866
  return {
594642
594867
  route: forcedRoute ?? "action",
594643
- shouldReply: true,
594868
+ shouldReply: !isGroup,
594644
594869
  confidence: 0,
594645
- reason: "router inference unavailable; escalating to action path instead of using text heuristics",
594870
+ reason: isGroup ? "router inference unavailable; public group fails closed without keyword heuristics" : "router inference unavailable; private chat defaults to reply",
594646
594871
  source: "inference-unavailable"
594647
594872
  };
594648
594873
  }
594649
594874
  const sessionKey = this.sessionKeyForMessage(msg);
594650
- const isGroup = msg.chatType !== "private";
594651
594875
  const backend = new OllamaAgenticBackend(
594652
594876
  config.backendUrl,
594653
594877
  config.model,
@@ -594665,7 +594889,9 @@ ${lines.join("\n")}`);
594665
594889
  `- chat: a short conversational answer can be produced without tools.`,
594666
594890
  `- action: tools, workspace context, media processing, web lookup, delegation, or a multi-step agent loop may be needed.`,
594667
594891
  ``,
594668
- `Reply discretion: infer from the live thread, speaker relationships, direct mentions, replies, tone, and current message. Do not use static keyword rules. In private chats, should_reply is normally true. In groups, should_reply can be false only when silence is the most contextually appropriate behavior.`,
594892
+ `Reply discretion: infer from the live thread, speaker relationships, direct mentions, replies, tone, and current message. Do not use static keyword rules.`,
594893
+ `Private chats: should_reply is normally true.`,
594894
+ `Group/public chats: default should_reply to false unless the current message clearly addresses the bot, replies to the bot, continues an active bot-involved exchange, assigns the bot work, or asks for the bot's view. Ambient chatter, third-person discussion about the bot, commands meant for a human, or questions among other people are false. Do not set true just because the bot could help.`,
594669
594895
  forcedLine,
594670
594896
  ``,
594671
594897
  `Tool context: ${toolContext}`,
@@ -594692,19 +594918,21 @@ ${msg.text}`
594692
594918
  tools: [],
594693
594919
  temperature: 0,
594694
594920
  maxTokens: 220,
594695
- timeoutMs: Math.min(config.timeoutMs ?? 3e4, 15e3),
594921
+ timeoutMs: Math.min(Math.max(config.timeoutMs ?? 3e4, 5e3), 15e3),
594696
594922
  think: false
594697
594923
  });
594698
594924
  const text = result.choices[0]?.message?.content ?? "";
594699
- const parsed = parseTelegramInteractionDecision(text, forcedRoute);
594925
+ const parsed = parseTelegramInteractionDecision(text, forcedRoute, {
594926
+ defaultShouldReply: !isGroup
594927
+ });
594700
594928
  if (parsed) return parsed;
594701
594929
  } catch {
594702
594930
  }
594703
594931
  return {
594704
594932
  route: forcedRoute ?? "action",
594705
- shouldReply: true,
594933
+ shouldReply: !isGroup,
594706
594934
  confidence: 0,
594707
- reason: "router inference failed; escalating to action path instead of using text heuristics",
594935
+ reason: isGroup ? "router inference failed; public group fails closed without keyword heuristics" : "router inference failed; private chat defaults to reply",
594708
594936
  source: "inference-unavailable"
594709
594937
  };
594710
594938
  }
@@ -594718,6 +594946,19 @@ ${msg.text}`
594718
594946
  return `Workspace context unavailable: ${reason}`;
594719
594947
  }
594720
594948
  }
594949
+ telegramFallbackCompactionThreshold(modelTier) {
594950
+ if (modelTier === "small") return 12e3;
594951
+ if (modelTier === "medium") return 24e3;
594952
+ return 4e4;
594953
+ }
594954
+ telegramWorkspaceBudget(profile) {
594955
+ if (this.contextWindowSize > 0) {
594956
+ const ratio = profile === "chat" ? 0.08 : 0.12;
594957
+ const floor = profile === "chat" ? 16e3 : 24e3;
594958
+ return Math.max(floor, Math.floor(this.contextWindowSize * ratio));
594959
+ }
594960
+ return profile === "chat" ? 16e3 : 24e3;
594961
+ }
594721
594962
  buildPrimaryTuiSessionContext(telegramSessionId) {
594722
594963
  const primarySessionId = process.env["OMNIUS_SESSION_ID"] || process.env["OMNIUS_TUI_SESSION_ID"] || "";
594723
594964
  if (!primarySessionId || primarySessionId === telegramSessionId) return "";
@@ -594775,7 +595016,7 @@ ${ADMIN_CHAT_PROFILE_PROMPT}`);
594775
595016
  if (primarySessionContext) sections.push(`## Primary TUI Session State
594776
595017
 
594777
595018
  ${primarySessionContext}`);
594778
- const workspaceContext = this.buildTelegramWorkspaceContext(modelTier, profile === "chat" ? 16e3 : 24e3);
595019
+ const workspaceContext = this.buildTelegramWorkspaceContext(modelTier, this.telegramWorkspaceBudget(profile));
594779
595020
  if (workspaceContext) sections.push(`## Workspace Context
594780
595021
 
594781
595022
  ${workspaceContext}`);
@@ -595096,6 +595337,20 @@ Join: ${newUrl}`);
595096
595337
  }
595097
595338
  const existing = this.subAgents.get(sessionKey);
595098
595339
  if (existing && !existing.aborted) {
595340
+ const isGroup = msg.chatType !== "private";
595341
+ if (isGroup) {
595342
+ this.recordTelegramUserMessage(msg, "ambient");
595343
+ const decision2 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
595344
+ this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? "steering" : "ambient");
595345
+ this.subAgentViewCallbacks?.onWrite(
595346
+ existing.viewId,
595347
+ `live steering: ${decision2.shouldReply ? decision2.route : "no_reply"} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}): ${decision2.reason}`
595348
+ );
595349
+ if (!decision2.shouldReply) {
595350
+ this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision2.reason}`);
595351
+ return;
595352
+ }
595353
+ }
595099
595354
  let steeringText = msg.text;
595100
595355
  if (msg.media) {
595101
595356
  const mediaContext = await this.processMedia(msg);
@@ -595106,7 +595361,11 @@ Join: ${newUrl}`);
595106
595361
  ${mediaContext}`;
595107
595362
  }
595108
595363
  }
595109
- this.recordTelegramUserMessage(msg, "steering", steeringText);
595364
+ if (isGroup) {
595365
+ this.markLastTelegramUserMessageMode(msg, "steering");
595366
+ } else {
595367
+ this.recordTelegramUserMessage(msg, "steering", steeringText);
595368
+ }
595110
595369
  if (existing.runner) {
595111
595370
  existing.runner.injectUserMessage(steeringText);
595112
595371
  this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "mid-conversation steering injected"));
@@ -595172,7 +595431,8 @@ ${mediaContext}`;
595172
595431
  clearInterval(subAgent.typingInterval);
595173
595432
  subAgent.typingInterval = null;
595174
595433
  }
595175
- if (result === "no_reply" || result === "") {
595434
+ const finalText = cleanTelegramVisibleReply(result || "");
595435
+ if (!finalText) {
595176
595436
  if (msg.chatType !== "private") {
595177
595437
  this.maybeLogTelegramGroupSkip(msg, "discretion: skipped reply");
595178
595438
  } else {
@@ -595186,20 +595446,10 @@ ${mediaContext}`;
595186
595446
  }
595187
595447
  return;
595188
595448
  }
595189
- const finalText = stripTelegramHiddenThinking(result || "").trim();
595190
595449
  if (subAgent.liveMessagePromise) {
595191
595450
  await subAgent.liveMessagePromise.catch(() => {
595192
595451
  });
595193
595452
  }
595194
- if (!finalText) {
595195
- if (subAgent.liveMessageId && !msg.guestQueryId) {
595196
- await this.deleteLiveMessage(msg.chatId, subAgent.liveMessageId).catch(() => {
595197
- });
595198
- }
595199
- this.subAgentViewCallbacks?.onWrite(subAgent.viewId, "completed: no model reply");
595200
- this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "completed");
595201
- return;
595202
- }
595203
595453
  this.recordTelegramAssistantMessage(msg, finalText, "action");
595204
595454
  const finalHtml = convertMarkdownToTelegramHTML(finalText);
595205
595455
  await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
@@ -595280,7 +595530,7 @@ ${mediaContext}`;
595280
595530
  clearInterval(subAgent.typingInterval);
595281
595531
  subAgent.typingInterval = null;
595282
595532
  }
595283
- const finalText = stripTelegramHiddenThinking(result || "").trim();
595533
+ const finalText = cleanTelegramVisibleReply(result || "");
595284
595534
  if (subAgent.liveMessagePromise) {
595285
595535
  await subAgent.liveMessagePromise.catch(() => {
595286
595536
  });
@@ -595370,10 +595620,12 @@ ${mediaContext}`;
595370
595620
  }
595371
595621
  if (liveMessageId && !msg.guestQueryId && now - lastEditMs > 900) {
595372
595622
  lastEditMs = now;
595623
+ const html = renderTelegramLiveProgressHTML(progressLines, accumulated);
595624
+ if (!html.trim()) return;
595373
595625
  await this.editLiveMessage(
595374
595626
  msg.chatId,
595375
595627
  liveMessageId,
595376
- renderTelegramLiveProgressHTML(progressLines, accumulated)
595628
+ html
595377
595629
  ).catch(() => {
595378
595630
  });
595379
595631
  } else if (!liveMessageId && !liveMessagePromise && !msg.guestQueryId) {
@@ -595399,7 +595651,7 @@ ${mediaContext}`;
595399
595651
  clearInterval(typingInterval);
595400
595652
  typingInterval = null;
595401
595653
  }
595402
- const cleaned = stripTelegramHiddenThinking(finalText || accumulated).trim();
595654
+ const cleaned = cleanTelegramVisibleReply(finalText || accumulated);
595403
595655
  const pendingLiveMessage = liveMessagePromise;
595404
595656
  if (pendingLiveMessage) {
595405
595657
  await pendingLiveMessage.catch(() => {
@@ -595452,7 +595704,7 @@ ${mediaContext}`;
595452
595704
  isGroup ? 44 : 24
595453
595705
  );
595454
595706
  const safety = isAdminDM ? "Admin private DM. The user is trusted, but quick-chat mode still has no tool access." : isAdminGroup ? ADMIN_GROUP_PROMPT : TELEGRAM_SAFETY_PROMPT;
595455
- const groupHint = isGroup ? `Telegram group: ${msg.chatTitle || "unknown"}. Keep the reply short and relevant.` : "Telegram private chat.";
595707
+ const groupHint = isGroup ? `Telegram group: ${msg.chatTitle || "unknown"}. The live router selected this turn as reply-worthy; keep the reply short and relevant. Never output a skip decision, no_reply marker, memory-stage note, or completion status.` : "Telegram private chat.";
595456
595708
  const runtime = buildTelegramRuntimeContext(/* @__PURE__ */ new Date());
595457
595709
  const messages2 = [
595458
595710
  {
@@ -595523,6 +595775,7 @@ ${mediaContext}` : ""}`
595523
595775
  const isGroup = msg.chatType !== "private";
595524
595776
  const creativeWorkspace = subAgent.creativeWorkspaceRoot ? formatTelegramCreativeWorkspacePrompt(subAgent.creativeWorkspaceRoot) : "";
595525
595777
  const sessionContext = this.buildTelegramSessionContext(msg, ctx3, profile, modelTier);
595778
+ const contextWindowSize = this.contextWindowSize;
595526
595779
  const backend = new OllamaAgenticBackend(
595527
595780
  config.backendUrl,
595528
595781
  config.model,
@@ -595534,7 +595787,8 @@ ${mediaContext}` : ""}`
595534
595787
  temperature: 0.3,
595535
595788
  requestTimeoutMs: config.timeoutMs,
595536
595789
  taskTimeoutMs: isAdminDM ? config.timeoutMs * 3 : config.timeoutMs,
595537
- compactionThreshold: modelTier === "small" ? 8e3 : 16e3,
595790
+ compactionThreshold: this.telegramFallbackCompactionThreshold(modelTier),
595791
+ contextWindowSize,
595538
595792
  modelTier,
595539
595793
  streamEnabled: true,
595540
595794
  dynamicContext: sessionContext.context,
@@ -595567,7 +595821,7 @@ ${mediaContext}` : ""}`
595567
595821
  }
595568
595822
  } else if (event.type === "status" && event.content) {
595569
595823
  this.subAgentViewCallbacks?.onWrite(subAgent.viewId, `status: ${event.content}`);
595570
- } else if (event.type === "assistant_text" && event.content) {
595824
+ } else if (event.type === "assistant_text" && event.content && event.source !== "task_complete_summary") {
595571
595825
  subAgent.assistantText = event.content;
595572
595826
  } else if (event.type === "stream_end" && event.content) {
595573
595827
  subAgent.streamText = event.content;
@@ -595642,7 +595896,7 @@ ${toolHint}
595642
595896
  Telegram message from @${msg.username}${chatLabel}:
595643
595897
  ${msg.text}
595644
595898
 
595645
- Respond concisely and safely.`;
595899
+ Respond concisely and safely. Send the actual chat reply, not router/status/completion commentary.`;
595646
595900
  }
595647
595901
  if (mediaContext) {
595648
595902
  userPrompt += `
@@ -595671,11 +595925,11 @@ ${creativeWorkspace}` : ""}`;
595671
595925
  buildSubAgentTools(context2, repoRoot, chatId, todoSessionId) {
595672
595926
  const taskComplete = {
595673
595927
  name: "task_complete",
595674
- description: "Internal completion signal for Telegram runs. Put the actual user-facing reply in assistant text before calling this. Use summary 'no_reply' only to silently skip responding.",
595928
+ description: "Internal completion signal for Telegram runs. Put the actual user-facing reply in assistant text before calling this. Use summary 'no_reply' only to silently skip responding; never write that sentinel as assistant text.",
595675
595929
  parameters: {
595676
595930
  type: "object",
595677
595931
  properties: {
595678
- summary: { type: "string", description: "Internal completion note, or 'no_reply' to skip when no assistant reply should be sent" }
595932
+ summary: { type: "string", description: "Internal completion note, or 'no_reply' to skip when no assistant reply should be sent. This is never shown directly to Telegram." }
595679
595933
  },
595680
595934
  required: ["summary"]
595681
595935
  },
@@ -595778,6 +596032,13 @@ ${creativeWorkspace}` : ""}`;
595778
596032
  fullSubAgentTool
595779
596033
  ];
595780
596034
  const allTools = context2 === "telegram-admin-dm" ? adminTools : sharedReadMemoryWebTools;
596035
+ if (this.contextWindowSize > 0) {
596036
+ for (const tool of allTools) {
596037
+ if ("setContextWindowSize" in tool && typeof tool.setContextWindowSize === "function") {
596038
+ tool.setContextWindowSize(this.contextWindowSize);
596039
+ }
596040
+ }
596041
+ }
595781
596042
  let adaptedTools = allTools.map((tool) => adaptTool5(tool, todoSessionId));
595782
596043
  adaptedTools = applyToolPolicy(adaptedTools, context2, this.toolPolicyConfig);
595783
596044
  if (context2 !== "telegram-admin-dm") {
@@ -624050,6 +624311,7 @@ ${result.summary}`
624050
624311
  resolvedContextWindowSize = ctxSize;
624051
624312
  statusBar.setContextWindowSize(ctxSize);
624052
624313
  setActiveTaskContextWindowSize(ctxSize);
624314
+ telegramBridge?.setContextWindowSize(ctxSize);
624053
624315
  }
624054
624316
  }).catch(() => {
624055
624317
  });
@@ -624977,8 +625239,12 @@ This is an independent background session started from /background.`
624977
625239
  await new Promise((r3) => setTimeout(r3, 5e3));
624978
625240
  return _tryNexusConnect(attempt + 1);
624979
625241
  }
625242
+ const nexusLogPath = join136(repoRoot, ".omnius", "nexus", "daemon.err");
625243
+ const visibleOut = out.length > 1200 ? `${out.slice(0, 1200)}...` : out;
624980
625244
  writeContent(
624981
- () => renderWarning(`Nexus auto-connect failed: ${out.slice(0, 100)}`)
625245
+ () => renderWarning(`Nexus auto-connect failed:
625246
+ ${visibleOut}
625247
+ Log: ${nexusLogPath}`)
624982
625248
  );
624983
625249
  } else if (out.includes("still connecting") || out.includes("spawned")) {
624984
625250
  for (let i2 = 0; i2 < 30; i2++) {
@@ -625974,6 +626240,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
625974
626240
  currentConfig,
625975
626241
  repoRoot
625976
626242
  );
626243
+ if (resolvedContextWindowSize > 0) {
626244
+ telegramBridge.setContextWindowSize(resolvedContextWindowSize);
626245
+ }
625977
626246
  telegramBridge.setInteractionMode(savedSettings.telegramMode ?? "auto");
625978
626247
  if (adminId) {
625979
626248
  telegramBridge.setAdmin(adminId);
@@ -626015,7 +626284,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
626015
626284
  }
626016
626285
  });
626017
626286
  telegramBridge.setOnSubAgentEvent((chatId, username, event) => {
626018
- if (event.type === "tool_call" && event.toolName) {
626287
+ if (event.type === "tool_call" && event.toolName && event.toolName !== "task_complete") {
626019
626288
  const argsPreview = event.toolArgs ? JSON.stringify(event.toolArgs).slice(0, 60) : "";
626020
626289
  writeContent(
626021
626290
  () => renderTelegramSubAgentToolCall(
@@ -626024,7 +626293,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
626024
626293
  argsPreview
626025
626294
  )
626026
626295
  );
626027
- } else if (event.type === "status" && event.content) {
626296
+ } else if (event.type === "status" && event.content && process.env["OMNIUS_TELEGRAM_DEBUG_STATUS"] === "1") {
626028
626297
  writeContent(
626029
626298
  () => renderTelegramSubAgentEvent(username, event.content)
626030
626299
  );
@@ -626728,7 +626997,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
626728
626997
  },
626729
626998
  onAgentSpeech(text) {
626730
626999
  writeContent(
626731
- () => renderInfo(`\x1B[38;5;178m[agent]\x1B[0m ${text.slice(0, 120)}`)
627000
+ () => renderInfo(`\x1B[38;5;37m[agent]\x1B[0m ${text.slice(0, 120)}`)
626732
627001
  );
626733
627002
  },
626734
627003
  // Keep state changes silent
@@ -627042,6 +627311,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
627042
627311
  setContextWindowSize: (size) => {
627043
627312
  resolvedContextWindowSize = size;
627044
627313
  statusBar.setContextWindowSize(size);
627314
+ telegramBridge?.setContextWindowSize(size);
627045
627315
  },
627046
627316
  setCapabilities: (caps) => {
627047
627317
  resolvedCaps = caps;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.3",
9
+ "version": "1.0.5",
10
10
  "hasInstallScript": true,
11
11
  "license": "CC-BY-NC-4.0",
12
12
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
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",