omnius 1.0.597 → 1.0.599

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
@@ -678083,6 +678083,7 @@ __export(daemon_exports, {
678083
678083
  getDaemonStatus: () => getDaemonStatus,
678084
678084
  getLocalCliVersion: () => getLocalCliVersion,
678085
678085
  isDaemonRunning: () => isDaemonRunning,
678086
+ reclaimOwnedDaemonListener: () => reclaimOwnedDaemonListener,
678086
678087
  recoverDaemonVersionBoundedly: () => recoverDaemonVersionBoundedly,
678087
678088
  releaseDaemonEndpointClaim: () => releaseDaemonEndpointClaim,
678088
678089
  releaseDaemonEndpointForCurrentProcess: () => releaseDaemonEndpointForCurrentProcess,
@@ -678094,6 +678095,7 @@ import { spawn as spawn28 } from "node:child_process";
678094
678095
  import { existsSync as existsSync116, readFileSync as readFileSync94, writeFileSync as writeFileSync60, mkdirSync as mkdirSync69, unlinkSync as unlinkSync22, openSync as openSync4, closeSync as closeSync4, writeSync as writeSync3, statSync as statSync46, renameSync as renameSync17 } from "node:fs";
678095
678096
  import { join as join128 } from "node:path";
678096
678097
  import { homedir as homedir39 } from "node:os";
678098
+ import { createServer as createNetServer } from "node:net";
678097
678099
  import { fileURLToPath as fileURLToPath18 } from "node:url";
678098
678100
  import { dirname as dirname42 } from "node:path";
678099
678101
  function getDaemonPort() {
@@ -678353,55 +678355,105 @@ ${fuser.stderr ?? ""}`;
678353
678355
  return null;
678354
678356
  }
678355
678357
  }
678356
- function processCommandLine(pid) {
678357
- try {
678358
- return readFileSync94(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ");
678359
- } catch {
678360
- return "";
678361
- }
678362
- }
678363
- function isOwnedOmniusDaemon(pid, daemonPid) {
678364
- if (pid === daemonPid) return true;
678365
- if (listProcessLeases({ includeInactive: false }).some((lease) => lease.pid === pid && lease.ownerKind === "daemon")) {
678366
- return true;
678367
- }
678368
- const command = processCommandLine(pid);
678369
- return /(?:^|[\\/\s])omnius(?:[\\/\s]|$)|omnius-daemon|[\\/]dist[\\/]index\.js\b|launcher\.cjs\b/i.test(command);
678370
- }
678371
- async function ownedDaemonPids(port) {
678372
- const daemonPid = getDaemonPid();
678373
- const candidates = /* @__PURE__ */ new Set();
678374
- if (daemonPid) candidates.add(daemonPid);
678375
- const holders = await portHolderPids(port);
678376
- for (const pid of holders ?? []) candidates.add(pid);
678377
- return [...candidates].filter((pid) => processIsAlive(pid) && isOwnedOmniusDaemon(pid, daemonPid));
678358
+ async function daemonPortIsFree(port) {
678359
+ return new Promise((resolve87) => {
678360
+ const probe = createNetServer();
678361
+ let settled = false;
678362
+ const finish = (free) => {
678363
+ if (settled) return;
678364
+ settled = true;
678365
+ resolve87(free);
678366
+ };
678367
+ probe.once("error", () => finish(false));
678368
+ probe.once("listening", () => {
678369
+ probe.close(() => finish(true));
678370
+ });
678371
+ probe.listen(port, "127.0.0.1");
678372
+ probe.unref();
678373
+ });
678378
678374
  }
678379
678375
  async function waitForDaemonStopped(port, attempts = DAEMON_GRACEFUL_STOP_ATTEMPTS) {
678380
678376
  for (let attempt = 0; attempt < attempts; attempt++) {
678381
678377
  const healthy = await isDaemonRunning(port);
678382
678378
  const holders = await portHolderPids(port);
678383
- if (!healthy && (holders === null || holders.length === 0)) return true;
678379
+ const portFree = holders === null ? await daemonPortIsFree(port) : holders.length === 0;
678380
+ if (!healthy && portFree) return true;
678384
678381
  await delay3(500);
678385
678382
  }
678386
678383
  return false;
678387
678384
  }
678388
- async function gracefullyStopOwnedDaemon(port) {
678389
- const pids = await ownedDaemonPids(port);
678390
- for (const pid of pids) {
678391
- try {
678392
- process.kill(pid, "SIGTERM");
678393
- } catch {
678385
+ async function reclaimOwnedDaemonListener(port = getDaemonPort(), dependencies = DEFAULT_RECLAIM_DEPENDENCIES) {
678386
+ const holders = await dependencies.holderPids(port);
678387
+ if (holders === null) {
678388
+ if (await dependencies.portIsFree(port)) {
678389
+ return { ok: true, action: "free", port, clearedPids: [], blockedPids: [] };
678394
678390
  }
678391
+ return {
678392
+ ok: false,
678393
+ action: "blocked",
678394
+ port,
678395
+ clearedPids: [],
678396
+ blockedPids: [],
678397
+ reason: "Could not identify the process holding the daemon port"
678398
+ };
678395
678399
  }
678396
- if (await waitForDaemonStopped(port)) return true;
678397
- const survivors = await ownedDaemonPids(port);
678398
- for (const pid of survivors) {
678399
- try {
678400
- process.kill(pid, "SIGKILL");
678401
- } catch {
678400
+ const uniqueHolders = [...new Set(holders.filter((pid) => pid > 0 && pid !== process.pid))];
678401
+ if (uniqueHolders.length === 0) {
678402
+ if (await dependencies.portIsFree(port)) {
678403
+ return { ok: true, action: "free", port, clearedPids: [], blockedPids: [] };
678404
+ }
678405
+ return {
678406
+ ok: false,
678407
+ action: "blocked",
678408
+ port,
678409
+ clearedPids: [],
678410
+ blockedPids: [],
678411
+ reason: "Daemon port is occupied but its holder could not be verified"
678412
+ };
678413
+ }
678414
+ const ownerId = `daemon:${port}`;
678415
+ const activeLeases = dependencies.leases().filter(
678416
+ (lease) => lease.status === "active" && lease.ownerKind === "daemon" && lease.ownerId === ownerId && uniqueHolders.includes(lease.pid)
678417
+ );
678418
+ const leasesByPid = new Map(activeLeases.map((lease) => [lease.pid, lease]));
678419
+ const blockedPids = uniqueHolders.filter((pid) => !leasesByPid.has(pid));
678420
+ if (blockedPids.length > 0) {
678421
+ return {
678422
+ ok: false,
678423
+ action: "blocked",
678424
+ port,
678425
+ clearedPids: [],
678426
+ blockedPids,
678427
+ reason: "Port holder is not an identity-verified Omnius daemon lease"
678428
+ };
678429
+ }
678430
+ const clearedPids = [];
678431
+ for (const pid of uniqueHolders) {
678432
+ const lease = leasesByPid.get(pid);
678433
+ const stopped = await dependencies.stopLease(lease.leaseId);
678434
+ if (stopped.action !== "killed" && stopped.action !== "dead") {
678435
+ return {
678436
+ ok: false,
678437
+ action: "failed",
678438
+ port,
678439
+ clearedPids,
678440
+ blockedPids: [pid],
678441
+ reason: stopped.reason || "Daemon lease identity could not be verified"
678442
+ };
678402
678443
  }
678444
+ clearedPids.push(pid);
678445
+ }
678446
+ if (!await dependencies.waitForFree(port)) {
678447
+ return {
678448
+ ok: false,
678449
+ action: "failed",
678450
+ port,
678451
+ clearedPids,
678452
+ blockedPids: [],
678453
+ reason: "Verified daemon stopped but the port did not become free"
678454
+ };
678403
678455
  }
678404
- return waitForDaemonStopped(port, 10);
678456
+ return { ok: true, action: "cleared", port, clearedPids, blockedPids: [] };
678405
678457
  }
678406
678458
  async function restartDaemon(port, expectedVersion) {
678407
678459
  const p2 = port ?? getDaemonPort();
@@ -678417,9 +678469,15 @@ async function restartDaemon(port, expectedVersion) {
678417
678469
  if (started.ok && (await waitForDaemonReady(p2, expectedVersion)).ok) return true;
678418
678470
  }
678419
678471
  await runUserSystemctl(["stop", "omnius-daemon.service"]);
678420
- if (!await waitForDaemonStopped(p2)) return false;
678472
+ if (!await waitForDaemonStopped(p2)) {
678473
+ const reclaimed = await reclaimOwnedDaemonListener(p2);
678474
+ if (!reclaimed.ok) return false;
678475
+ }
678476
+ }
678477
+ if (await isDaemonRunning(p2)) {
678478
+ const reclaimed = await reclaimOwnedDaemonListener(p2);
678479
+ if (!reclaimed.ok) return false;
678421
678480
  }
678422
- if (await isDaemonRunning(p2) && !await gracefullyStopOwnedDaemon(p2)) return false;
678423
678481
  const pid = await startDaemon(p2);
678424
678482
  if (!pid) return false;
678425
678483
  return (await waitForDaemonReady(p2, expectedVersion)).ok;
@@ -678496,7 +678554,7 @@ async function startDaemon(port = getDaemonPort()) {
678496
678554
  outFd = openSync4(join128(OMNIUS_DIR, "daemon.log"), "a");
678497
678555
  errFd = openSync4(join128(OMNIUS_DIR, "daemon.err.log"), "a");
678498
678556
  const leaseId = newProcessLeaseId("daemon");
678499
- const ownerId = `daemon:${getDaemonPort()}`;
678557
+ const ownerId = `daemon:${daemonPort}`;
678500
678558
  const child = spawn28(daemonCommand.command, daemonCommand.args, {
678501
678559
  detached: true,
678502
678560
  stdio: ["ignore", outFd, errFd],
@@ -678670,17 +678728,17 @@ async function ensureDaemonVersion(expectedVersion = getLocalCliVersion(), port
678670
678728
  }
678671
678729
  return finish(true, "unchanged", await getDaemonReportedVersion(port));
678672
678730
  }
678673
- const stalePid = getDaemonPid();
678674
- if (stalePid) {
678675
- try {
678676
- process.kill(stalePid, "SIGTERM");
678677
- } catch {
678678
- }
678679
- try {
678680
- unlinkSync22(PID_FILE);
678681
- } catch {
678682
- }
678731
+ const reclaimed = await reclaimOwnedDaemonListener(port);
678732
+ if (!reclaimed.ok) {
678733
+ return finish(
678734
+ false,
678735
+ "failed",
678736
+ null,
678737
+ 0,
678738
+ process.platform === "linux" && reclaimed.action === "blocked"
678739
+ );
678683
678740
  }
678741
+ getDaemonPid();
678684
678742
  const pid = await startDaemon(port);
678685
678743
  if (!pid) {
678686
678744
  for (let i2 = 0; i2 < 20; i2++) {
@@ -678728,7 +678786,7 @@ async function getDaemonStatus() {
678728
678786
  }
678729
678787
  return { running, pid, port, uptime: uptime2, pidFile: PID_FILE };
678730
678788
  }
678731
- var OMNIUS_DIR, PID_FILE, DEFAULT_PORT2, LOCK_INITIALIZATION_GRACE_MS, DAEMON_VERSION_RECOVERY_ATTEMPTS, DAEMON_GRACEFUL_STOP_ATTEMPTS;
678789
+ var OMNIUS_DIR, PID_FILE, DEFAULT_PORT2, LOCK_INITIALIZATION_GRACE_MS, DAEMON_VERSION_RECOVERY_ATTEMPTS, DAEMON_GRACEFUL_STOP_ATTEMPTS, DEFAULT_RECLAIM_DEPENDENCIES;
678732
678790
  var init_daemon = __esm({
678733
678791
  "packages/cli/src/daemon.ts"() {
678734
678792
  init_dist5();
@@ -678738,6 +678796,16 @@ var init_daemon = __esm({
678738
678796
  LOCK_INITIALIZATION_GRACE_MS = 5e3;
678739
678797
  DAEMON_VERSION_RECOVERY_ATTEMPTS = 2;
678740
678798
  DAEMON_GRACEFUL_STOP_ATTEMPTS = 20;
678799
+ DEFAULT_RECLAIM_DEPENDENCIES = {
678800
+ holderPids: (port) => portHolderPids(port),
678801
+ portIsFree: (port) => daemonPortIsFree(port),
678802
+ leases: () => listProcessLeases({ includeInactive: false }),
678803
+ stopLease: (leaseId) => stopProcessLease(leaseId, {
678804
+ reason: "stale daemon listener reclaim",
678805
+ termGraceMs: 1e3
678806
+ }),
678807
+ waitForFree: (port) => waitForDaemonStopped(port)
678808
+ };
678741
678809
  }
678742
678810
  });
678743
678811
 
@@ -678757,6 +678825,7 @@ __export(tray_exports, {
678757
678825
  runTrayForeground: () => runTrayForeground,
678758
678826
  startTray: () => startTray,
678759
678827
  stopTray: () => stopTray,
678828
+ trayRequiresRestart: () => trayRequiresRestart,
678760
678829
  traySupport: () => traySupport,
678761
678830
  trayUpdatePresentation: () => trayUpdatePresentation,
678762
678831
  uninstallTrayAutostart: () => uninstallTrayAutostart,
@@ -679149,7 +679218,7 @@ start "" /b ${argv.map(windowsCmdQuote).join(" ")}\r
679149
679218
  }
679150
679219
  throw new Error(`Autostart is not supported on ${platform8}`);
679151
679220
  }
679152
- function installTrayAutostart(endpoint) {
679221
+ function writeTrayAutostart(endpoint) {
679153
679222
  const launch = resolveTrayLaunchCommand();
679154
679223
  if (!launch) throw new Error("Could not resolve the installed Omnius CLI entrypoint");
679155
679224
  const paths = resolveTrayPaths();
@@ -679159,11 +679228,15 @@ function installTrayAutostart(endpoint) {
679159
679228
  buildAutostartContent(process.platform, launch, endpoint, assetPath("online")),
679160
679229
  { encoding: "utf8", mode: process.platform === "win32" ? 448 : 384 }
679161
679230
  );
679231
+ return paths.autostartFile;
679232
+ }
679233
+ function installTrayAutostart(endpoint) {
679234
+ const autostartFile = writeTrayAutostart(endpoint);
679162
679235
  if (process.platform === "darwin" && typeof process.getuid === "function") {
679163
679236
  spawnSync9("launchctl", ["bootout", `gui/${process.getuid()}/ai.omnius.tray`], { stdio: "ignore" });
679164
- spawnSync9("launchctl", ["bootstrap", `gui/${process.getuid()}`, paths.autostartFile], { stdio: "ignore" });
679237
+ spawnSync9("launchctl", ["bootstrap", `gui/${process.getuid()}`, autostartFile], { stdio: "ignore" });
679165
679238
  }
679166
- return paths.autostartFile;
679239
+ return autostartFile;
679167
679240
  }
679168
679241
  function uninstallTrayAutostart() {
679169
679242
  const paths = resolveTrayPaths();
@@ -679295,11 +679368,15 @@ async function getTrayStatus(explicitEndpoint) {
679295
679368
  }
679296
679369
  const state = readProcessState(paths.stateFile);
679297
679370
  const support = traySupport();
679371
+ const requestedEndpoint = resolveTrayEndpoint(explicitEndpoint);
679298
679372
  return {
679299
679373
  running,
679300
679374
  ready: running && Boolean(state?.ready),
679301
679375
  pid: running ? pid : null,
679302
- endpoint: state?.endpoint || resolveTrayEndpoint(explicitEndpoint),
679376
+ // A stopped indicator's cached state must not override an explicitly
679377
+ // requested endpoint. This previously kept resurrecting an obsolete
679378
+ // custom port (for example 11535) after the daemon had returned to 11435.
679379
+ endpoint: running || !explicitEndpoint ? state?.endpoint || requestedEndpoint : requestedEndpoint,
679303
679380
  registered: existsSync117(paths.autostartFile),
679304
679381
  registrationFile: paths.autostartFile,
679305
679382
  ...state?.health ? { health: state.health } : {},
@@ -679308,16 +679385,26 @@ async function getTrayStatus(explicitEndpoint) {
679308
679385
  ...state?.error ? { error: state.error } : {}
679309
679386
  };
679310
679387
  }
679388
+ function trayRequiresRestart(existing, endpoint, liveHealth) {
679389
+ return existing.endpoint !== endpoint || !existing.ready || Boolean(existing.error) || existing.health?.kind !== liveHealth.kind || existing.health?.version !== liveHealth.version;
679390
+ }
679311
679391
  async function startTray(explicitEndpoint) {
679312
- const existing = await getTrayStatus(explicitEndpoint);
679313
- if (existing.running) return existing;
679392
+ const endpoint = resolveTrayEndpoint(explicitEndpoint);
679393
+ const existing = await getTrayStatus(endpoint);
679394
+ if (existing.running) {
679395
+ const liveHealth = await pollTrayHealth(endpoint);
679396
+ if (!trayRequiresRestart(existing, endpoint, liveHealth)) {
679397
+ return { ...existing, health: liveHealth };
679398
+ }
679399
+ await stopTray();
679400
+ }
679314
679401
  const support = traySupport();
679315
679402
  if (!support.supported) throw new Error(support.reason || "Tray is not supported on this host");
679316
679403
  verifyTrayHelper();
679317
679404
  const launch = resolveTrayLaunchCommand();
679318
679405
  if (!launch) throw new Error("Could not resolve the installed Omnius CLI entrypoint");
679319
- const endpoint = resolveTrayEndpoint(explicitEndpoint);
679320
679406
  const paths = resolveTrayPaths();
679407
+ if (existing.registered) writeTrayAutostart(endpoint);
679321
679408
  mkdirSync70(paths.stateDir, { recursive: true, mode: 448 });
679322
679409
  mkdirSync70(paths.runtimeDir, { recursive: true, mode: 448 });
679323
679410
  try {
@@ -691887,9 +691974,9 @@ function buildCommandDef(name10, signatures) {
691887
691974
  const argsHint = inferArgsHint(signatures[0]?.signature ?? `/${name10}`);
691888
691975
  const surfaces = {
691889
691976
  tui: true,
691890
- rest: status === "implemented" && !["quit", "exit"].includes(name10) && !safety.destructive && !safety.secretBearing && !REST_BLOCKED.has(name10),
691891
- gateway: status === "implemented" && !safety.destructive && !safety.secretBearing,
691892
- agentTool: status === "implemented" && !safety.userOnly && !safety.destructive && !safety.secretBearing && !safety.profileGated
691977
+ rest: status === "implemented" && !["quit", "exit"].includes(name10) && !safety.destructive && !safety.secretBearing && !REST_BLOCKED.has(name10) && !LOCAL_TUI_ONLY.has(name10),
691978
+ gateway: status === "implemented" && !safety.destructive && !safety.secretBearing && !LOCAL_TUI_ONLY.has(name10),
691979
+ agentTool: status === "implemented" && !safety.userOnly && !safety.destructive && !safety.secretBearing && !safety.profileGated && !LOCAL_TUI_ONLY.has(name10)
691893
691980
  };
691894
691981
  return {
691895
691982
  name: name10,
@@ -691924,7 +692011,7 @@ function inferArgsHint(signature) {
691924
692011
  function normalizeCommandName(name10) {
691925
692012
  return name10.replace(/^\//, "").trim().toLowerCase();
691926
692013
  }
691927
- var COMMAND_SIGNATURES, PLANNED_SIGNATURES, CATEGORY_OVERRIDES, ALIASES, USER_ONLY, DESTRUCTIVE, NETWORKED, SECRET_BEARING, PROFILE_GATED, SELF_MODIFY_ALLOWED, REST_BLOCKED, TELEGRAM_PUBLIC_BOT_COMMANDS, CANONICAL_BY_ALIAS, DYNAMIC_COMMANDS, SLASH_COMMANDS;
692014
+ var COMMAND_SIGNATURES, PLANNED_SIGNATURES, CATEGORY_OVERRIDES, ALIASES, USER_ONLY, DESTRUCTIVE, NETWORKED, SECRET_BEARING, PROFILE_GATED, SELF_MODIFY_ALLOWED, REST_BLOCKED, LOCAL_TUI_ONLY, TELEGRAM_PUBLIC_BOT_COMMANDS, CANONICAL_BY_ALIAS, DYNAMIC_COMMANDS, SLASH_COMMANDS;
691928
692015
  var init_command_registry = __esm({
691929
692016
  "packages/cli/src/tui/command-registry.ts"() {
691930
692017
  COMMAND_SIGNATURES = [
@@ -691957,6 +692044,12 @@ var init_command_registry = __esm({
691957
692044
  ["/ollama cleanup --execute", "Terminate guarded stale Ollama pool runners"],
691958
692045
  ["/mcp", "Show MCP server/tool status and controls"],
691959
692046
  ["/mcp reload", "Reload MCP servers and tools"],
692047
+ ["/indicator", "Start the native system indicator and report readiness"],
692048
+ ["/indicator start", "Start the native system indicator and report readiness"],
692049
+ ["/indicator status", "Report native system indicator readiness and daemon health"],
692050
+ ["/tray", "Alias for /indicator"],
692051
+ ["/tray start", "Alias for /indicator start"],
692052
+ ["/tray status", "Alias for /indicator status"],
691960
692053
  ["/update", "Check for updates and auto-install"],
691961
692054
  ["/upgrade", "Alias for /update"],
691962
692055
  ["/update auto", "Enable auto-update after task completion (default)"],
@@ -692617,6 +692710,7 @@ var init_command_registry = __esm({
692617
692710
  scheduler: "runtime",
692618
692711
  reminder: "runtime",
692619
692712
  daemon: "runtime",
692713
+ indicator: "ui",
692620
692714
  apikey: "secret",
692621
692715
  key: "secret",
692622
692716
  secrets: "secret",
@@ -692667,6 +692761,7 @@ var init_command_registry = __esm({
692667
692761
  setup: ["wizard"],
692668
692762
  mcp: ["mcps"],
692669
692763
  update: ["upgrade"],
692764
+ indicator: ["tray"],
692670
692765
  listen: ["mic"],
692671
692766
  pointcloud: ["points", "pcl", "point"],
692672
692767
  neovim: ["nvim", "vim"],
@@ -692767,6 +692862,7 @@ var init_command_registry = __esm({
692767
692862
  "scheduler",
692768
692863
  "cron",
692769
692864
  "daemon",
692865
+ "indicator",
692770
692866
  "fortemi",
692771
692867
  "mouse",
692772
692868
  "approve",
@@ -692885,8 +692981,10 @@ var init_command_registry = __esm({
692885
692981
  "rollback",
692886
692982
  "background",
692887
692983
  "bg",
692888
- "paste"
692984
+ "paste",
692985
+ "indicator"
692889
692986
  ]);
692987
+ LOCAL_TUI_ONLY = /* @__PURE__ */ new Set(["indicator"]);
692890
692988
  TELEGRAM_PUBLIC_BOT_COMMANDS = [
692891
692989
  {
692892
692990
  command: "start",
@@ -724392,6 +724490,106 @@ var init_prune_menu = __esm({
724392
724490
  }
724393
724491
  });
724394
724492
 
724493
+ // packages/cli/src/tui/indicator-command.ts
724494
+ var indicator_command_exports = {};
724495
+ __export(indicator_command_exports, {
724496
+ runIndicatorCommand: () => runIndicatorCommand
724497
+ });
724498
+ async function waitForOnlineHealth(endpoint, operations, attempts = 5) {
724499
+ let health = await operations.health(endpoint);
724500
+ for (let attempt = 1; health.kind !== "online" && attempt < attempts; attempt++) {
724501
+ await operations.wait(200);
724502
+ health = await operations.health(endpoint);
724503
+ }
724504
+ return health;
724505
+ }
724506
+ function formatIndicatorStatus(status, daemon) {
724507
+ const state = status.running ? status.ready ? "ready" : "starting" : "stopped";
724508
+ const pid = status.pid ? ` (PID ${status.pid})` : "";
724509
+ const health = status.health?.label ?? "not checked";
724510
+ const autostart = status.registered ? "registered" : "not registered";
724511
+ const parts = [
724512
+ `Indicator: ${state}${pid}.`,
724513
+ `Health: ${health}.`,
724514
+ `Endpoint: ${status.endpoint}.`,
724515
+ `Autostart: ${autostart}.`
724516
+ ];
724517
+ if (daemon) {
724518
+ const version5 = daemon.observedVersion ?? daemon.expectedVersion;
724519
+ parts.push(
724520
+ `Daemon: ${daemon.action}${version5 ? ` (v${version5})` : ""} on port ${daemon.port}.`
724521
+ );
724522
+ }
724523
+ if (status.error) parts.push(`Error: ${status.error}`);
724524
+ return parts.join(" ");
724525
+ }
724526
+ async function runIndicatorCommand(rawAction, operations = DEFAULT_OPERATIONS) {
724527
+ const action = rawAction.trim().toLowerCase() || "start";
724528
+ if (action !== "start" && action !== "status") {
724529
+ return {
724530
+ level: "warning",
724531
+ message: "Usage: /indicator [start|status] (alias: /tray)"
724532
+ };
724533
+ }
724534
+ try {
724535
+ if (action === "status") {
724536
+ const cached2 = await operations.status();
724537
+ const health2 = await operations.health(cached2.endpoint);
724538
+ const status2 = { ...cached2, health: health2 };
724539
+ const level2 = status2.error ? "error" : status2.running && status2.ready && health2.kind === "online" ? "info" : "warning";
724540
+ return { level: level2, message: formatIndicatorStatus(status2), status: status2 };
724541
+ }
724542
+ const daemon = await operations.ensureDaemon();
724543
+ if (!daemon.ok) {
724544
+ const observed = daemon.observedVersion ? `; observed v${daemon.observedVersion}` : "";
724545
+ const migration = daemon.requiresPrivilegedMigration ? " Privileged service migration is required; run /daemon takeover." : "";
724546
+ return {
724547
+ level: "error",
724548
+ message: `Indicator not started: daemon reconciliation failed on port ${daemon.port}${observed}.${migration}`,
724549
+ daemon
724550
+ };
724551
+ }
724552
+ const endpoint = `http://127.0.0.1:${daemon.port}`;
724553
+ const daemonHealth = await waitForOnlineHealth(endpoint, operations);
724554
+ if (daemonHealth.kind !== "online") {
724555
+ return {
724556
+ level: "error",
724557
+ message: `Indicator not started: daemon did not become online at ${endpoint}. ` + daemonHealth.tooltip,
724558
+ daemon
724559
+ };
724560
+ }
724561
+ const started = await operations.start(endpoint);
724562
+ const health = await waitForOnlineHealth(endpoint, operations);
724563
+ const status = { ...started, endpoint, health };
724564
+ const level = status.error ? "error" : status.running && status.ready && health.kind === "online" ? "info" : "error";
724565
+ return {
724566
+ level,
724567
+ message: formatIndicatorStatus(status, daemon),
724568
+ status,
724569
+ daemon
724570
+ };
724571
+ } catch (error) {
724572
+ return {
724573
+ level: "error",
724574
+ message: `Indicator failed: ${error instanceof Error ? error.message : String(error)}`
724575
+ };
724576
+ }
724577
+ }
724578
+ var DEFAULT_OPERATIONS;
724579
+ var init_indicator_command = __esm({
724580
+ "packages/cli/src/tui/indicator-command.ts"() {
724581
+ init_tray();
724582
+ init_daemon();
724583
+ DEFAULT_OPERATIONS = {
724584
+ ensureDaemon: () => ensureDaemonVersion(),
724585
+ start: (endpoint) => startTray(endpoint),
724586
+ status: () => getTrayStatus(),
724587
+ health: (endpoint) => pollTrayHealth(endpoint),
724588
+ wait: (ms) => new Promise((resolve87) => setTimeout(resolve87, ms))
724589
+ };
724590
+ }
724591
+ });
724592
+
724395
724593
  // packages/cli/src/cron/types.ts
724396
724594
  var SILENT_MARKER, ONESHOT_GRACE_SECONDS, TICK_LOCK_FILE, CRON_DIR_NAME, JOBS_FILE_NAME, OUTPUT_DIR_NAME;
724397
724595
  var init_types5 = __esm({
@@ -735832,6 +736030,15 @@ ${result.output}`);
735832
736030
  await showCohereDashboard(ctx3);
735833
736031
  return "handled";
735834
736032
  }
736033
+ case "indicator":
736034
+ case "tray": {
736035
+ const { runIndicatorCommand: runIndicatorCommand2 } = await Promise.resolve().then(() => (init_indicator_command(), indicator_command_exports));
736036
+ const result = await runIndicatorCommand2(arg);
736037
+ if (result.level === "error") renderError(result.message);
736038
+ else if (result.level === "warning") renderWarning(result.message);
736039
+ else renderInfo(result.message);
736040
+ return "handled";
736041
+ }
735835
736042
  case "daemon": {
735836
736043
  const { getDaemonStatus: getDaemonStatus2, stopDaemon: stopDaemon2, ensureDaemon: ensureDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
735837
736044
  if (arg === "status" || !arg) {
@@ -792429,6 +792636,9 @@ function getWebUI() {
792429
792636
  <meta charset="UTF-8">
792430
792637
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
792431
792638
  <title>Omnius</title>
792639
+ <link rel="preconnect" href="https://fonts.googleapis.com">
792640
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
792641
+ <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
792432
792642
  <style>
792433
792643
  /* ─── Cold Tactical HUD design tokens ──────────────────────────────
792434
792644
  * Source of truth:
@@ -794212,6 +794422,316 @@ button {
794212
794422
  .hud-workbench { grid-template-columns: 1fr; }
794213
794423
  .hud-form-grid { grid-template-columns: 1fr; }
794214
794424
  }
794425
+
794426
+ /* ─── NOCLIP style kit ─────────────────────────────────────────────
794427
+ * Source: https://noclip.org/assets/ui-panels-CB6m2DCR.css
794428
+ * Keep this final: it intentionally collapses the older tactical HUD and
794429
+ * OpenWebUI experiments into noclip's restrained black/yellow system.
794430
+ */
794431
+ :root {
794432
+ color-scheme: dark;
794433
+ --nclp-bg-main: #000000;
794434
+ --nclp-bg-secondary: #111111;
794435
+ --nclp-bg-tertiary: #1a1a1a;
794436
+ --nclp-surface: #141414;
794437
+ --nclp-text: #fafafa;
794438
+ --nclp-muted: rgba(250, 250, 250, 0.70);
794439
+ --nclp-quiet: rgba(250, 250, 250, 0.48);
794440
+ --nclp-line: rgba(250, 250, 250, 0.12);
794441
+ --nclp-line-strong: rgba(250, 250, 250, 0.30);
794442
+ --nclp-yellow: #facc15;
794443
+ --nclp-amber: #f59e0b;
794444
+ --nclp-amber-soft: rgba(245, 158, 11, 0.14);
794445
+ --nclp-ok: #8ef6c8;
794446
+ --nclp-bad: #fca5a5;
794447
+ --nclp-font: Inter, 'IBM Plex Mono', 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
794448
+ --nclp-card: linear-gradient(145deg, rgba(20, 20, 20, 0.97), rgba(10, 10, 10, 0.97));
794449
+ --nclp-shadow: 0 16px 40px rgba(0, 0, 0, 0.16);
794450
+
794451
+ --hud-void: var(--nclp-bg-main);
794452
+ --hud-black: var(--nclp-bg-main);
794453
+ --hud-panel-solid: var(--nclp-surface);
794454
+ --hud-steel: var(--nclp-line);
794455
+ --hud-steel-2: var(--nclp-line-strong);
794456
+ --hud-dim: var(--nclp-quiet);
794457
+ --hud-muted: var(--nclp-muted);
794458
+ --hud-ink-soft: var(--nclp-muted);
794459
+ --hud-ink: var(--nclp-text);
794460
+ --hud-accent: var(--nclp-yellow);
794461
+ --hud-accent-strong: #fde047;
794462
+ --hud-cyan: var(--nclp-yellow);
794463
+ --hud-danger: var(--nclp-bad);
794464
+ --hud-success: var(--nclp-ok);
794465
+ --hud-panel-clip: none;
794466
+ --hud-button-clip: none;
794467
+ --hud-panel-shadow: var(--nclp-shadow);
794468
+ --hud-cyan-glow: none;
794469
+ --hud-amber-glow: none;
794470
+
794471
+ --color-bg: var(--nclp-bg-main);
794472
+ --color-bg-elevated: var(--nclp-surface);
794473
+ --color-bg-input: var(--nclp-bg-main);
794474
+ --color-bg-hover: var(--nclp-amber-soft);
794475
+ --color-fg: var(--nclp-text);
794476
+ --color-fg-muted: var(--nclp-muted);
794477
+ --color-fg-subtle: var(--nclp-muted);
794478
+ --color-fg-faint: var(--nclp-quiet);
794479
+ --color-border: var(--nclp-line);
794480
+ --color-border-strong: var(--nclp-line-strong);
794481
+ --color-accent: var(--nclp-yellow);
794482
+ --color-accent-hover: #fde047;
794483
+ --color-accent-fg: #111111;
794484
+ --color-success: var(--nclp-ok);
794485
+ --color-warning: var(--nclp-yellow);
794486
+ --color-error: var(--nclp-bad);
794487
+ --color-info: var(--nclp-yellow);
794488
+ --color-brand: var(--nclp-yellow);
794489
+ --color-brand-hover: #fde047;
794490
+ --font-display: var(--nclp-font);
794491
+ --font-ui: var(--nclp-font);
794492
+ --font-mono: var(--nclp-font);
794493
+ --radius-sm: 3px;
794494
+ --radius-md: 3px;
794495
+ --radius-lg: 3px;
794496
+ --radius-pill: 3px;
794497
+ }
794498
+
794499
+ /* NOCLIP is a dark-only style kit; keep the legacy theme toggle from leaking
794500
+ * its pale compatibility palette back into components using --color-* aliases. */
794501
+ html[data-theme="light"] {
794502
+ color-scheme: dark;
794503
+ --color-bg: var(--nclp-bg-main);
794504
+ --color-bg-elevated: var(--nclp-surface);
794505
+ --color-bg-input: var(--nclp-bg-main);
794506
+ --color-bg-hover: var(--nclp-amber-soft);
794507
+ --color-fg: var(--nclp-text);
794508
+ --color-fg-muted: var(--nclp-muted);
794509
+ --color-fg-subtle: var(--nclp-muted);
794510
+ --color-fg-faint: var(--nclp-quiet);
794511
+ --color-border: var(--nclp-line);
794512
+ --color-border-strong: var(--nclp-line-strong);
794513
+ }
794514
+
794515
+ html,
794516
+ body,
794517
+ #omnius-shell,
794518
+ #omnius-main {
794519
+ background: var(--nclp-bg-main) !important;
794520
+ color: var(--nclp-text) !important;
794521
+ font-family: var(--nclp-font) !important;
794522
+ }
794523
+
794524
+ body::before,
794525
+ body::after,
794526
+ #omnius-sidebar::before,
794527
+ .hud-btn__chrome,
794528
+ .hud-tab__chrome {
794529
+ content: none !important;
794530
+ display: none !important;
794531
+ }
794532
+
794533
+ #omnius-sidebar {
794534
+ background: var(--nclp-bg-main) !important;
794535
+ border-right: 1px solid var(--nclp-line) !important;
794536
+ box-shadow: none !important;
794537
+ }
794538
+
794539
+ #header,
794540
+ #sidebar-nav,
794541
+ #sidebar-footer,
794542
+ .session-topbar,
794543
+ #footer,
794544
+ #input-toolbar,
794545
+ #input-row,
794546
+ #processes-row,
794547
+ #tasks-row {
794548
+ background: var(--nclp-bg-secondary) !important;
794549
+ border-color: var(--nclp-line) !important;
794550
+ box-shadow: none !important;
794551
+ }
794552
+
794553
+ #chat-container,
794554
+ #agent-panel,
794555
+ #jobs-panel,
794556
+ #config-panel,
794557
+ #activity-panel,
794558
+ #projects-panel,
794559
+ #voice-panel,
794560
+ #generate-panel {
794561
+ background: var(--nclp-bg-main) !important;
794562
+ background-image: none !important;
794563
+ }
794564
+
794565
+ :is(.hud-panel, .hud-result-card, .tool-card, .omnius-modal-window,
794566
+ .settings-provider-module, .settings-provider-setup, .msg pre,
794567
+ #proc-popover, #slash-palette, #key-modal .modal) {
794568
+ position: relative;
794569
+ border: 1px solid var(--nclp-line) !important;
794570
+ border-radius: 3px !important;
794571
+ background: var(--nclp-card) !important;
794572
+ box-shadow: var(--nclp-shadow) !important;
794573
+ clip-path: none !important;
794574
+ backdrop-filter: none !important;
794575
+ }
794576
+
794577
+ :is(.hud-panel, .hud-result-card, .omnius-modal-window,
794578
+ .settings-provider-module, .settings-provider-setup)::before {
794579
+ content: "" !important;
794580
+ position: absolute !important;
794581
+ z-index: 2 !important;
794582
+ top: 0 !important;
794583
+ left: 0 !important;
794584
+ width: 38px !important;
794585
+ height: 2px !important;
794586
+ background: var(--nclp-yellow) !important;
794587
+ pointer-events: none !important;
794588
+ }
794589
+
794590
+ button,
794591
+ [role="button"],
794592
+ .hud-btn,
794593
+ .hud-tab,
794594
+ .sb-nav,
794595
+ .key-btn,
794596
+ .ibtn {
794597
+ border: 1px solid var(--nclp-line) !important;
794598
+ border-radius: 3px !important;
794599
+ background: var(--nclp-bg-secondary) !important;
794600
+ color: var(--nclp-text) !important;
794601
+ box-shadow: none !important;
794602
+ clip-path: none !important;
794603
+ font-family: var(--nclp-font) !important;
794604
+ font-size: 11px !important;
794605
+ font-weight: 800 !important;
794606
+ letter-spacing: 0.07em !important;
794607
+ text-transform: uppercase !important;
794608
+ }
794609
+
794610
+ :is(button, [role="button"], .hud-btn, .hud-tab, .sb-nav, .key-btn, .ibtn):hover:not(:disabled),
794611
+ :is(button, [role="button"], .hud-btn, .hud-tab, .sb-nav, .key-btn, .ibtn):focus-visible {
794612
+ border-color: var(--nclp-yellow) !important;
794613
+ color: var(--nclp-yellow) !important;
794614
+ background: var(--nclp-bg-secondary) !important;
794615
+ outline: none !important;
794616
+ }
794617
+
794618
+ :is(.hud-btn--primary, button[type="submit"], .is-primary) {
794619
+ border-color: var(--nclp-yellow) !important;
794620
+ background: var(--nclp-yellow) !important;
794621
+ color: #111111 !important;
794622
+ }
794623
+
794624
+ :is(.hud-btn--danger, .danger, .kill) {
794625
+ border-color: rgba(252, 165, 165, 0.52) !important;
794626
+ background: #3a1818 !important;
794627
+ color: #fef2f2 !important;
794628
+ }
794629
+
794630
+ button:disabled,
794631
+ [role="button"][aria-disabled="true"] {
794632
+ opacity: 0.45 !important;
794633
+ cursor: not-allowed !important;
794634
+ }
794635
+
794636
+ input,
794637
+ select,
794638
+ textarea,
794639
+ #input-area,
794640
+ #sidebar-search {
794641
+ border: 1px solid var(--nclp-line) !important;
794642
+ border-radius: 3px !important;
794643
+ background: var(--nclp-bg-main) !important;
794644
+ color: var(--nclp-text) !important;
794645
+ box-shadow: none !important;
794646
+ font-family: var(--nclp-font) !important;
794647
+ }
794648
+
794649
+ :is(input, select, textarea, #input-area, #sidebar-search):focus {
794650
+ border-color: var(--nclp-yellow) !important;
794651
+ box-shadow: 0 0 0 1px var(--nclp-yellow) !important;
794652
+ outline: none !important;
794653
+ }
794654
+
794655
+ .sb-nav.active,
794656
+ .sb-chat.active,
794657
+ .slash-row.selected,
794658
+ .slash-row:hover,
794659
+ .hud-tab.active,
794660
+ .hud-tab[aria-selected="true"] {
794661
+ border-color: var(--nclp-yellow) !important;
794662
+ background: var(--nclp-amber-soft) !important;
794663
+ color: var(--nclp-yellow) !important;
794664
+ box-shadow: none !important;
794665
+ }
794666
+
794667
+ #sidebar-brand,
794668
+ #header .accent,
794669
+ :is(.hud-panel__title, .hud-result-card strong, h1, h2, h3) {
794670
+ color: var(--nclp-text) !important;
794671
+ font-family: var(--nclp-font) !important;
794672
+ font-size: 11px !important;
794673
+ font-weight: 700 !important;
794674
+ letter-spacing: 0.13em !important;
794675
+ text-transform: uppercase !important;
794676
+ }
794677
+
794678
+ :is(label, .hud-rail-label, .topbar-label, .proc-label, .tasks-label,
794679
+ .slash-desc, .hud-field label) {
794680
+ color: var(--nclp-muted) !important;
794681
+ font-size: 10px !important;
794682
+ font-weight: 700 !important;
794683
+ letter-spacing: 0.08em !important;
794684
+ text-transform: uppercase !important;
794685
+ }
794686
+
794687
+ .msg.user > *,
794688
+ .msg.system > *,
794689
+ .msg.assistant::before,
794690
+ .task-item,
794691
+ .chip,
794692
+ .hud-chip {
794693
+ border: 1px solid var(--nclp-line) !important;
794694
+ border-radius: 3px !important;
794695
+ background: var(--nclp-bg-secondary) !important;
794696
+ box-shadow: none !important;
794697
+ clip-path: none !important;
794698
+ }
794699
+
794700
+ .msg.assistant::before {
794701
+ color: var(--nclp-yellow) !important;
794702
+ border-color: var(--nclp-yellow) !important;
794703
+ }
794704
+
794705
+ .hud-result-card strong,
794706
+ .metric,
794707
+ .metric-value,
794708
+ .card-value {
794709
+ color: var(--nclp-yellow) !important;
794710
+ font-variant-numeric: tabular-nums !important;
794711
+ }
794712
+
794713
+ .live,
794714
+ .success,
794715
+ .ok { color: var(--nclp-ok) !important; }
794716
+ .error,
794717
+ .bad { color: var(--nclp-bad) !important; }
794718
+
794719
+ html { scrollbar-color: var(--nclp-line-strong) var(--nclp-bg-main); }
794720
+ *::-webkit-scrollbar { width: 6px; height: 6px; }
794721
+ *::-webkit-scrollbar-track { background: var(--nclp-bg-main); }
794722
+ *::-webkit-scrollbar-thumb {
794723
+ background: var(--nclp-line-strong);
794724
+ border: 0;
794725
+ border-radius: 3px;
794726
+ }
794727
+ *::-webkit-scrollbar-thumb:hover { background: var(--nclp-yellow); }
794728
+
794729
+ @media (prefers-reduced-motion: reduce) {
794730
+ *, *::before, *::after {
794731
+ animation-duration: 0.01ms !important;
794732
+ transition-duration: 0.01ms !important;
794733
+ }
794734
+ }
794215
794735
  </style>
794216
794736
  </head>
794217
794737
  <body>
@@ -7302,6 +7302,38 @@
7302
7302
  }
7303
7303
  ]
7304
7304
  },
7305
+ {
7306
+ "id": "command.indicator",
7307
+ "kind": "command",
7308
+ "title": "/indicator",
7309
+ "summary": "Report native system indicator readiness and daemon health",
7310
+ "aliases": [
7311
+ "/indicator",
7312
+ "indicator"
7313
+ ],
7314
+ "keywords": [
7315
+ "command",
7316
+ "tui",
7317
+ "indicator"
7318
+ ],
7319
+ "interfaces": [
7320
+ {
7321
+ "type": "tui",
7322
+ "target": "/indicator"
7323
+ },
7324
+ {
7325
+ "type": "rest",
7326
+ "target": "/v1/commands/indicator"
7327
+ }
7328
+ ],
7329
+ "references": [
7330
+ {
7331
+ "type": "source",
7332
+ "target": "packages/cli/src/tui/command-registry.ts",
7333
+ "relation": "registry"
7334
+ }
7335
+ ]
7336
+ },
7305
7337
  {
7306
7338
  "id": "command.ingest",
7307
7339
  "kind": "command",
@@ -9799,6 +9831,38 @@
9799
9831
  }
9800
9832
  ]
9801
9833
  },
9834
+ {
9835
+ "id": "command.tray",
9836
+ "kind": "command",
9837
+ "title": "/tray",
9838
+ "summary": "Alias for /indicator status",
9839
+ "aliases": [
9840
+ "/tray",
9841
+ "tray"
9842
+ ],
9843
+ "keywords": [
9844
+ "command",
9845
+ "tui",
9846
+ "tray"
9847
+ ],
9848
+ "interfaces": [
9849
+ {
9850
+ "type": "tui",
9851
+ "target": "/tray"
9852
+ },
9853
+ {
9854
+ "type": "rest",
9855
+ "target": "/v1/commands/tray"
9856
+ }
9857
+ ],
9858
+ "references": [
9859
+ {
9860
+ "type": "source",
9861
+ "target": "packages/cli/src/tui/command-registry.ts",
9862
+ "relation": "registry"
9863
+ }
9864
+ ]
9865
+ },
9802
9866
  {
9803
9867
  "id": "command.tree",
9804
9868
  "kind": "command",
package/docs/DISCOVERY.md CHANGED
@@ -232,6 +232,7 @@ Daemon equivalents are `GET /v1/discovery?q=<intent>` and `GET /v1/discovery/{id
232
232
  | `command.hf` | /hf | Cancel any pending HF token prompt and fall back immediately |
233
233
  | `command.host` | /host | Set bind host:port (OMNIUS_HOST) and restart daemon |
234
234
  | `command.image` | /image | List image models by category, quality, size, and hardware fit |
235
+ | `command.indicator` | /indicator | Report native system indicator readiness and daemon health |
235
236
  | `command.ingest` | /ingest | Ingest an audio, PDF, or text file into memory |
236
237
  | `command.init` | Initialize agent discovery guidance | Create or update managed Omnius discovery blocks in project guidance while preserving user content. |
237
238
  | `command.insights` | /insights | Show historical session insights |
@@ -310,6 +311,7 @@ Daemon equivalents are `GET /v1/discovery?q=<intent>` and `GET /v1/discovery/{id
310
311
  | `command.tools` | /tools | List agent-created custom tools |
311
312
  | `command.toolsets` | /toolsets | Show or select tool exposure sets |
312
313
  | `command.transcribe` | /transcribe | Alias for /ingest &lt;file&gt; |
314
+ | `command.tray` | /tray | Alias for /indicator status |
313
315
  | `command.tree` | /tree | Show, hide, or inspect the action-tree presentation |
314
316
  | `command.undo` | /undo | Undo the last queued or saved exchange when available |
315
317
  | `command.update` | /update | Run full non-interactive update: package, deps, rebuild, Python, cloudflared |
@@ -14,6 +14,23 @@ omnius tray stop # stop only the indicator
14
14
  omnius tray uninstall # stop it and remove login startup
15
15
  ```
16
16
 
17
+ From an active Omnius TUI, use the local slash command instead:
18
+
19
+ ```text
20
+ /indicator # start and report readiness
21
+ /indicator status # inspect without starting
22
+ ```
23
+
24
+ `/tray` is retained as an alias. Login registration and the full
25
+ start/stop/restart lifecycle remain available through the top-level
26
+ `omnius tray` command.
27
+
28
+ `/indicator` first reconciles the current Omnius daemon on its configured
29
+ loopback port (11435 by default), waits for verified online health, repairs a
30
+ stale tray endpoint/autostart registration, and only then starts the native
31
+ indicator. Untracked processes occupying the port are reported as blockers and
32
+ are never terminated automatically.
33
+
17
34
  The indicator polls the daemon's loopback-only `GET /health` route. It does not
18
35
  load a model or contact the configured inference backend. If the daemon uses a
19
36
  non-default port, Omnius discovers `OMNIUS_HOST`/`OMNIUS_PORT` from the current
@@ -82,4 +99,3 @@ tail -f ~/.local/state/omnius/tray.err.log # Linux default
82
99
  with `--endpoint`; avoid `0.0.0.0` in client URLs.
83
100
  - **No graphical session:** run `omnius tray start` from the logged-in desktop
84
101
  session so `DISPLAY`/`WAYLAND_DISPLAY` and the session D-Bus address exist.
85
-
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.597",
3
+ "version": "1.0.599",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.597",
9
+ "version": "1.0.599",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.597",
3
+ "version": "1.0.599",
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/library.js",