omnius 1.0.600 → 1.0.601

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
@@ -678140,6 +678140,8 @@ ${AGENTS_END}`;
678140
678140
  var daemon_exports = {};
678141
678141
  __export(daemon_exports, {
678142
678142
  claimDaemonEndpoint: () => claimDaemonEndpoint,
678143
+ daemonPortFromServiceEnvironment: () => daemonPortFromServiceEnvironment,
678144
+ daemonServiceMatchesPort: () => daemonServiceMatchesPort,
678143
678145
  ensureDaemon: () => ensureDaemon,
678144
678146
  ensureDaemonVersion: () => ensureDaemonVersion,
678145
678147
  forceKillDaemon: () => forceKillDaemon,
@@ -678155,7 +678157,8 @@ __export(daemon_exports, {
678155
678157
  releaseDaemonEndpointForCurrentProcess: () => releaseDaemonEndpointForCurrentProcess,
678156
678158
  restartDaemon: () => restartDaemon,
678157
678159
  startDaemon: () => startDaemon,
678158
- stopDaemon: () => stopDaemon
678160
+ stopDaemon: () => stopDaemon,
678161
+ stopDaemonAtPort: () => stopDaemonAtPort
678159
678162
  });
678160
678163
  import { spawn as spawn28 } from "node:child_process";
678161
678164
  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";
@@ -678279,7 +678282,9 @@ async function isDaemonRunning(port) {
678279
678282
  const resp = await fetch(`http://127.0.0.1:${p2}/health`, {
678280
678283
  signal: AbortSignal.timeout(2e3)
678281
678284
  });
678282
- return resp.ok;
678285
+ if (!resp.ok) return false;
678286
+ const health = await resp.json();
678287
+ return health.status === "ok" && (typeof health.boot_version === "string" || typeof health.version === "string");
678283
678288
  } catch {
678284
678289
  return false;
678285
678290
  }
@@ -678345,12 +678350,49 @@ async function runUserSystemctl(args, timeout2 = 2e4) {
678345
678350
  return { available: false, ok: false };
678346
678351
  }
678347
678352
  }
678353
+ async function readUserSystemctl(args, timeout2 = 5e3) {
678354
+ try {
678355
+ const { spawnSync: spawnSync11 } = await import("node:child_process");
678356
+ const result = spawnSync11("systemctl", ["--user", ...args], {
678357
+ encoding: "utf8",
678358
+ stdio: ["ignore", "pipe", "ignore"],
678359
+ timeout: timeout2
678360
+ });
678361
+ return result.status === 0 ? result.stdout.trim() : null;
678362
+ } catch {
678363
+ return null;
678364
+ }
678365
+ }
678348
678366
  async function hasManagedDaemonService() {
678349
678367
  const enabled2 = await runUserSystemctl(["is-enabled", "omnius-daemon.service"], 5e3);
678350
678368
  if (enabled2.ok) return true;
678351
678369
  const active = await runUserSystemctl(["is-active", "omnius-daemon.service"], 5e3);
678352
678370
  return active.ok;
678353
678371
  }
678372
+ function daemonPortFromServiceEnvironment(value2) {
678373
+ const host = value2.match(/(?:^|\s)OMNIUS_HOST=(?:"([^"]+)"|'([^']+)'|([^\s]+))/)?.slice(1).find(Boolean);
678374
+ const direct = value2.match(/(?:^|\s)OMNIUS_PORT=(?:"(\d+)"|'(\d+)'|(\d+))/)?.slice(1).find(Boolean);
678375
+ const candidate = host?.match(/:(\d+)$/)?.[1] ?? direct;
678376
+ if (!candidate) return null;
678377
+ const port = Number(candidate);
678378
+ return Number.isInteger(port) && port >= 1 && port <= 65535 ? port : null;
678379
+ }
678380
+ function daemonServiceMatchesPort(requestedPort, effectiveEnvironment) {
678381
+ const effectivePort2 = daemonPortFromServiceEnvironment(effectiveEnvironment);
678382
+ return effectivePort2 === null ? requestedPort === DEFAULT_PORT2 : effectivePort2 === requestedPort;
678383
+ }
678384
+ async function managedDaemonServiceMatchesPort(port) {
678385
+ if (!await hasManagedDaemonService()) return false;
678386
+ const environment = await readUserSystemctl([
678387
+ "show",
678388
+ "omnius-daemon.service",
678389
+ "--property",
678390
+ "Environment",
678391
+ "--value"
678392
+ ]);
678393
+ if (environment === null) return false;
678394
+ return daemonServiceMatchesPort(port, environment);
678395
+ }
678354
678396
  function systemdQuote(value2) {
678355
678397
  return /[\s"\\]/.test(value2) ? `"${value2.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : value2;
678356
678398
  }
@@ -678448,6 +678490,43 @@ async function waitForDaemonStopped(port, attempts = DAEMON_GRACEFUL_STOP_ATTEMP
678448
678490
  }
678449
678491
  return false;
678450
678492
  }
678493
+ async function reclaimStaleDaemonEndpointClaim(port) {
678494
+ const lockFile = daemonLockFile(port);
678495
+ const record = readDaemonLock(lockFile);
678496
+ if (!record) return true;
678497
+ if (!await daemonPortIsFree(port)) return true;
678498
+ if (!processIsAlive(record.pid)) {
678499
+ const current2 = readDaemonLock(lockFile);
678500
+ if (current2?.pid === record.pid && current2.token === record.token) {
678501
+ try {
678502
+ unlinkSync22(lockFile);
678503
+ } catch {
678504
+ }
678505
+ }
678506
+ return true;
678507
+ }
678508
+ const lease = listProcessLeases({ includeInactive: false }).find(
678509
+ (item) => item.status === "active" && item.pid === record.pid && item.ownerKind === "daemon" && item.ownerId === `daemon:${port}`
678510
+ );
678511
+ if (!lease) return false;
678512
+ const stopped = await stopProcessLease(lease.leaseId, {
678513
+ reason: `stale daemon endpoint claim on port ${port}`,
678514
+ termGraceMs: 1e3
678515
+ });
678516
+ if (stopped.action !== "killed" && stopped.action !== "dead") return false;
678517
+ for (let attempt = 0; attempt < 20 && processIsAlive(record.pid); attempt++) {
678518
+ await delay3(100);
678519
+ }
678520
+ if (processIsAlive(record.pid)) return false;
678521
+ const current = readDaemonLock(lockFile);
678522
+ if (current?.pid === record.pid && current.token === record.token) {
678523
+ try {
678524
+ unlinkSync22(lockFile);
678525
+ } catch {
678526
+ }
678527
+ }
678528
+ return daemonPortIsFree(port);
678529
+ }
678451
678530
  async function reclaimOwnedDaemonListener(port = getDaemonPort(), dependencies = DEFAULT_RECLAIM_DEPENDENCIES) {
678452
678531
  const holders = await dependencies.holderPids(port);
678453
678532
  if (holders === null) {
@@ -678523,7 +678602,7 @@ async function reclaimOwnedDaemonListener(port = getDaemonPort(), dependencies =
678523
678602
  }
678524
678603
  async function restartDaemon(port, expectedVersion) {
678525
678604
  const p2 = port ?? getDaemonPort();
678526
- const managed = await hasManagedDaemonService();
678605
+ const managed = await managedDaemonServiceMatchesPort(p2);
678527
678606
  if (managed) {
678528
678607
  const restarted = await runUserSystemctl(["restart", "omnius-daemon.service"]);
678529
678608
  if (restarted.ok && (await waitForDaemonReady(p2, expectedVersion)).ok) return true;
@@ -678544,6 +678623,7 @@ async function restartDaemon(port, expectedVersion) {
678544
678623
  const reclaimed = await reclaimOwnedDaemonListener(p2);
678545
678624
  if (!reclaimed.ok) return false;
678546
678625
  }
678626
+ if (!await reclaimStaleDaemonEndpointClaim(p2)) return false;
678547
678627
  const pid = await startDaemon(p2);
678548
678628
  if (!pid) return false;
678549
678629
  return (await waitForDaemonReady(p2, expectedVersion)).ok;
@@ -678650,7 +678730,7 @@ async function startDaemon(port = getDaemonPort()) {
678650
678730
  projectRoot: process.cwd(),
678651
678731
  lifecycle: "daemon",
678652
678732
  persistent: true,
678653
- reason: `shared API daemon on port ${getDaemonPort()}`,
678733
+ reason: `shared API daemon on port ${daemonPort}`,
678654
678734
  command: [daemonCommand.command, ...daemonCommand.args].join(" "),
678655
678735
  cwd: process.cwd()
678656
678736
  });
@@ -678695,6 +678775,17 @@ function stopDaemon() {
678695
678775
  return false;
678696
678776
  }
678697
678777
  }
678778
+ async function stopDaemonAtPort(port = getDaemonPort()) {
678779
+ if (await managedDaemonServiceMatchesPort(port)) {
678780
+ const stopped = await runUserSystemctl(["stop", "omnius-daemon.service"]);
678781
+ if (stopped.ok && await waitForDaemonStopped(port)) return true;
678782
+ }
678783
+ const wasRunning = await isDaemonRunning(port);
678784
+ const reclaimed = await reclaimOwnedDaemonListener(port);
678785
+ if (!reclaimed.ok) return false;
678786
+ const claimCleared = await reclaimStaleDaemonEndpointClaim(port);
678787
+ return claimCleared && (wasRunning || reclaimed.action === "cleared");
678788
+ }
678698
678789
  async function forceKillDaemon(port) {
678699
678790
  const p2 = port ?? getDaemonPort();
678700
678791
  let killed = 0;
@@ -678804,6 +678895,9 @@ async function ensureDaemonVersion(expectedVersion = getLocalCliVersion(), port
678804
678895
  process.platform === "linux" && reclaimed.action === "blocked"
678805
678896
  );
678806
678897
  }
678898
+ if (!await reclaimStaleDaemonEndpointClaim(port)) {
678899
+ return finish(false, "failed", null, 0, process.platform === "linux");
678900
+ }
678807
678901
  getDaemonPid();
678808
678902
  const pid = await startDaemon(port);
678809
678903
  if (!pid) {
@@ -678888,9 +678982,11 @@ __export(tray_exports, {
678888
678982
  resolveTrayEndpoint: () => resolveTrayEndpoint,
678889
678983
  resolveTrayLaunchCommand: () => resolveTrayLaunchCommand,
678890
678984
  resolveTrayPaths: () => resolveTrayPaths,
678985
+ resolveTrayRegistrationCommand: () => resolveTrayRegistrationCommand,
678891
678986
  runTrayForeground: () => runTrayForeground,
678892
678987
  startTray: () => startTray,
678893
678988
  stopTray: () => stopTray,
678989
+ trayProcessCommandLooksOwned: () => trayProcessCommandLooksOwned,
678894
678990
  trayRequiresRestart: () => trayRequiresRestart,
678895
678991
  traySupport: () => traySupport,
678896
678992
  trayUpdatePresentation: () => trayUpdatePresentation,
@@ -678906,6 +679002,7 @@ import {
678906
679002
  mkdirSync as mkdirSync70,
678907
679003
  openSync as openSync5,
678908
679004
  readFileSync as readFileSync95,
679005
+ realpathSync,
678909
679006
  renameSync as renameSync18,
678910
679007
  unlinkSync as unlinkSync23,
678911
679008
  writeFileSync as writeFileSync61,
@@ -678921,7 +679018,8 @@ function trayUpdatePresentation(currentVersion, latestVersion, state = null) {
678921
679018
  title: `Updating to v${state.target_version} — ${state.phase.replaceAll("_", " ")}`,
678922
679019
  tooltip: `Operation ${state.operation_id}; progress is shared with the dashboard and CLI`,
678923
679020
  enabled: false,
678924
- targetVersion: state.target_version
679021
+ targetVersion: state.target_version,
679022
+ action: "update-omnius"
678925
679023
  };
678926
679024
  }
678927
679025
  if (state?.status === "failed" && state.target_version === latestVersion) {
@@ -678929,7 +679027,8 @@ function trayUpdatePresentation(currentVersion, latestVersion, state = null) {
678929
679027
  title: `Update to v${state.target_version} failed — retry`,
678930
679028
  tooltip: state.remediation || state.error || "Open the tray logs for update diagnostics",
678931
679029
  enabled: true,
678932
- targetVersion: state.target_version
679030
+ targetVersion: state.target_version,
679031
+ action: "update-omnius"
678933
679032
  };
678934
679033
  }
678935
679034
  if (currentVersion && latestVersion) {
@@ -678937,13 +679036,15 @@ function trayUpdatePresentation(currentVersion, latestVersion, state = null) {
678937
679036
  title: `Update Omnius to v${latestVersion}`,
678938
679037
  tooltip: `Install and verify the global package, executable, daemon, and tray (current v${currentVersion})`,
678939
679038
  enabled: true,
678940
- targetVersion: latestVersion
679039
+ targetVersion: latestVersion,
679040
+ action: "update-omnius"
678941
679041
  };
678942
679042
  }
678943
679043
  return {
678944
- title: currentVersion ? `Omnius v${currentVersion} is up to date` : "Check for Omnius updates",
678945
- tooltip: "Automatic update checks use the same cached registry result as the CLI and dashboard",
678946
- enabled: false
679044
+ title: currentVersion ? `Check for Omnius updates (v${currentVersion})` : "Check for Omnius updates",
679045
+ tooltip: "Check npm now; automatic checks continue in the background",
679046
+ enabled: Boolean(currentVersion),
679047
+ action: "check-update"
678947
679048
  };
678948
679049
  }
678949
679050
  function uidSuffix() {
@@ -678994,19 +679095,6 @@ function normalizeTrayEndpoint(value2) {
678994
679095
  return null;
678995
679096
  }
678996
679097
  }
678997
- function systemdDaemonEnvironment() {
678998
- if (process.platform !== "linux") return "";
678999
- try {
679000
- const result = spawnSync9(
679001
- "systemctl",
679002
- ["--user", "show", SERVICE_LABEL, "--property", "Environment", "--value"],
679003
- { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 2e3 }
679004
- );
679005
- return result.status === 0 ? result.stdout.trim() : "";
679006
- } catch {
679007
- return "";
679008
- }
679009
- }
679010
679098
  function endpointFromServiceEnvironment(value2) {
679011
679099
  const host = value2.match(/(?:^|\s)OMNIUS_HOST=(?:"([^"]+)"|'([^']+)'|([^\s]+))/)?.slice(1).find(Boolean);
679012
679100
  const port = value2.match(/(?:^|\s)OMNIUS_PORT=(?:"(\d+)"|'(\d+)'|(\d+))/)?.slice(1).find(Boolean);
@@ -679018,7 +679106,6 @@ function resolveTrayEndpoint(explicit) {
679018
679106
  process.env["OMNIUS_TRAY_ENDPOINT"],
679019
679107
  process.env["OMNIUS_HOST"],
679020
679108
  process.env["OMNIUS_PORT"],
679021
- endpointFromServiceEnvironment(systemdDaemonEnvironment()),
679022
679109
  DEFAULT_ENDPOINT
679023
679110
  ];
679024
679111
  for (const candidate of candidates) {
@@ -679158,6 +679245,30 @@ function readProcessState(path16) {
679158
679245
  return null;
679159
679246
  }
679160
679247
  }
679248
+ function processCommandLine(pid) {
679249
+ try {
679250
+ if (process.platform === "linux") {
679251
+ return readFileSync95(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ");
679252
+ }
679253
+ if (process.platform !== "win32") {
679254
+ return spawnSync9("ps", ["-p", String(pid), "-o", "command="], {
679255
+ encoding: "utf8",
679256
+ stdio: ["ignore", "pipe", "ignore"],
679257
+ timeout: 2e3
679258
+ }).stdout.trim();
679259
+ }
679260
+ return spawnSync9("wmic", ["process", "where", `ProcessId=${pid}`, "get", "CommandLine", "/value"], {
679261
+ encoding: "utf8",
679262
+ stdio: ["ignore", "pipe", "ignore"],
679263
+ timeout: 2e3
679264
+ }).stdout;
679265
+ } catch {
679266
+ return "";
679267
+ }
679268
+ }
679269
+ function trayProcessCommandLooksOwned(command) {
679270
+ return /(?:^|\s)tray\s+run(?:\s|$)/i.test(command) && (/(?:^|[\\/\s])omnius(?:[\\/\s]|$)/i.test(command) || /[\\/]dist[\\/]index\.js\b|launcher\.cjs\b/i.test(command));
679271
+ }
679161
679272
  function writeProcessState(paths, state) {
679162
679273
  mkdirSync70(paths.runtimeDir, { recursive: true, mode: 448 });
679163
679274
  const temporary = `${paths.stateFile}.${process.pid}.tmp`;
@@ -679232,6 +679343,34 @@ function resolveTrayLaunchCommand() {
679232
679343
  }
679233
679344
  return null;
679234
679345
  }
679346
+ function installedOmniusLaunchCommand() {
679347
+ try {
679348
+ const result = spawnSync9(process.platform === "win32" ? "where" : "which", ["omnius"], {
679349
+ encoding: "utf8",
679350
+ stdio: ["ignore", "pipe", "ignore"],
679351
+ timeout: 2e3
679352
+ });
679353
+ const first2 = result.stdout?.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
679354
+ return first2 && existsSync117(first2) ? commandForEntrypoint2(realpathSync(first2)) : null;
679355
+ } catch {
679356
+ return null;
679357
+ }
679358
+ }
679359
+ function resolveTrayRegistrationCommand() {
679360
+ return installedOmniusLaunchCommand() ?? resolveTrayLaunchCommand();
679361
+ }
679362
+ function registrationIconPath(launch) {
679363
+ const extension3 = process.platform === "win32" ? "ico" : "png";
679364
+ const entrypoints = [...launch.args, launch.command].filter((candidate) => existsSync117(candidate));
679365
+ for (const entrypoint of entrypoints) {
679366
+ const real = realpathSync(entrypoint);
679367
+ for (const packageRoot of [dirname43(real), join129(dirname43(real), "..")]) {
679368
+ const candidate = join129(packageRoot, "assets", "tray", `omnius-online.${extension3}`);
679369
+ if (existsSync117(candidate)) return candidate;
679370
+ }
679371
+ }
679372
+ return assetPath("online");
679373
+ }
679235
679374
  function desktopExecQuote(value2) {
679236
679375
  return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("$", "\\$").replaceAll("`", "\\`")}"`;
679237
679376
  }
@@ -679285,13 +679424,13 @@ start "" /b ${argv.map(windowsCmdQuote).join(" ")}\r
679285
679424
  throw new Error(`Autostart is not supported on ${platform8}`);
679286
679425
  }
679287
679426
  function writeTrayAutostart(endpoint) {
679288
- const launch = resolveTrayLaunchCommand();
679427
+ const launch = resolveTrayRegistrationCommand();
679289
679428
  if (!launch) throw new Error("Could not resolve the installed Omnius CLI entrypoint");
679290
679429
  const paths = resolveTrayPaths();
679291
679430
  mkdirSync70(dirname43(paths.autostartFile), { recursive: true });
679292
679431
  writeFileSync61(
679293
679432
  paths.autostartFile,
679294
- buildAutostartContent(process.platform, launch, endpoint, assetPath("online")),
679433
+ buildAutostartContent(process.platform, launch, endpoint, registrationIconPath(launch)),
679295
679434
  { encoding: "utf8", mode: process.platform === "win32" ? 448 : 384 }
679296
679435
  );
679297
679436
  return paths.autostartFile;
@@ -679313,44 +679452,12 @@ function uninstallTrayAutostart() {
679313
679452
  unlinkSync23(paths.autostartFile);
679314
679453
  return true;
679315
679454
  }
679316
- function runServiceControl(action) {
679317
- try {
679318
- if (process.platform === "linux") {
679319
- const result = spawnSync9("systemctl", ["--user", action, SERVICE_LABEL], {
679320
- stdio: "ignore",
679321
- timeout: 1e4
679322
- });
679323
- return result.status === 0;
679324
- }
679325
- if (process.platform === "darwin" && typeof process.getuid === "function") {
679326
- const domain = `gui/${process.getuid()}`;
679327
- const plist = join129(homedir40(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
679328
- if (action === "stop") {
679329
- return spawnSync9("launchctl", ["bootout", `${domain}/${LAUNCHD_LABEL}`], { stdio: "ignore", timeout: 1e4 }).status === 0;
679330
- }
679331
- if (action === "restart") {
679332
- return spawnSync9("launchctl", ["kickstart", "-k", `${domain}/${LAUNCHD_LABEL}`], { stdio: "ignore", timeout: 1e4 }).status === 0;
679333
- }
679334
- spawnSync9("launchctl", ["bootstrap", domain, plist], { stdio: "ignore", timeout: 1e4 });
679335
- return spawnSync9("launchctl", ["kickstart", `${domain}/${LAUNCHD_LABEL}`], { stdio: "ignore", timeout: 1e4 }).status === 0;
679336
- }
679337
- if (process.platform === "win32") {
679338
- const args = action === "stop" ? ["/End", "/TN", WINDOWS_TASK_NAME] : ["/Run", "/TN", WINDOWS_TASK_NAME];
679339
- return spawnSync9("schtasks", args, { stdio: "ignore", timeout: 1e4 }).status === 0;
679340
- }
679341
- } catch {
679342
- }
679343
- return false;
679344
- }
679345
679455
  async function controlDaemon(action, endpoint) {
679346
- if (runServiceControl(action)) return true;
679347
- if (action === "stop") return stopDaemon();
679348
- if (action === "restart") {
679349
- stopDaemon();
679350
- await new Promise((resolve87) => setTimeout(resolve87, 500));
679351
- }
679352
679456
  const port = Number(new URL(endpoint).port);
679353
- return await startDaemon(Number.isInteger(port) && port > 0 ? port : void 0) !== null;
679457
+ if (!Number.isInteger(port) || port <= 0) return false;
679458
+ if (action === "stop") return stopDaemonAtPort(port);
679459
+ if (action === "restart") return restartDaemon(port, getLocalCliVersion());
679460
+ return (await ensureDaemonVersion(getLocalCliVersion(), port)).ok;
679354
679461
  }
679355
679462
  function openExternal(target) {
679356
679463
  try {
@@ -679394,7 +679501,7 @@ function menuForHealth(health, endpoint, registered, update2) {
679394
679501
  title: update2.title,
679395
679502
  tooltip: update2.tooltip,
679396
679503
  enabled: update2.enabled,
679397
- action: "update-omnius"
679504
+ action: update2.action
679398
679505
  };
679399
679506
  return {
679400
679507
  healthItem,
@@ -679462,7 +679569,9 @@ async function startTray(explicitEndpoint) {
679462
679569
  if (!trayRequiresRestart(existing, endpoint, liveHealth)) {
679463
679570
  return { ...existing, health: liveHealth };
679464
679571
  }
679465
- await stopTray();
679572
+ if (!await stopTray()) {
679573
+ throw new Error(`Could not stop the existing Omnius indicator on ${existing.endpoint}`);
679574
+ }
679466
679575
  }
679467
679576
  const support = traySupport();
679468
679577
  if (!support.supported) throw new Error(support.reason || "Tray is not supported on this host");
@@ -679513,16 +679622,49 @@ async function stopTray() {
679513
679622
  }
679514
679623
  return false;
679515
679624
  }
679625
+ const state = readProcessState(paths.stateFile);
679626
+ if (state?.pid !== pid || !trayProcessCommandLooksOwned(processCommandLine(pid))) {
679627
+ return false;
679628
+ }
679516
679629
  try {
679517
679630
  process.kill(pid, "SIGTERM");
679518
679631
  } catch {
679519
679632
  return false;
679520
679633
  }
679521
679634
  for (let i2 = 0; i2 < 30; i2++) {
679522
- if (!isProcessAlive2(pid)) return true;
679635
+ if (!isProcessAlive2(pid)) {
679636
+ try {
679637
+ unlinkSync23(paths.pidFile);
679638
+ } catch {
679639
+ }
679640
+ try {
679641
+ unlinkSync23(paths.stateFile);
679642
+ } catch {
679643
+ }
679644
+ return true;
679645
+ }
679646
+ await new Promise((resolve87) => setTimeout(resolve87, 100));
679647
+ }
679648
+ if (!trayProcessCommandLooksOwned(processCommandLine(pid))) return false;
679649
+ try {
679650
+ process.kill(pid, "SIGKILL");
679651
+ } catch {
679652
+ }
679653
+ for (let i2 = 0; i2 < 20; i2++) {
679654
+ if (!isProcessAlive2(pid)) {
679655
+ try {
679656
+ unlinkSync23(paths.pidFile);
679657
+ } catch {
679658
+ }
679659
+ try {
679660
+ unlinkSync23(paths.stateFile);
679661
+ } catch {
679662
+ }
679663
+ return true;
679664
+ }
679523
679665
  await new Promise((resolve87) => setTimeout(resolve87, 100));
679524
679666
  }
679525
- return !isProcessAlive2(pid);
679667
+ return false;
679526
679668
  }
679527
679669
  async function runTrayForeground(explicitEndpoint) {
679528
679670
  const support = traySupport();
@@ -679619,6 +679761,7 @@ async function runTrayForeground(explicitEndpoint) {
679619
679761
  menuState.updateItem.title = updateView.title;
679620
679762
  menuState.updateItem.tooltip = updateView.tooltip;
679621
679763
  menuState.updateItem.enabled = updateView.enabled;
679764
+ menuState.updateItem.action = updateView.action;
679622
679765
  const autostartRegistered = existsSync117(paths.autostartFile);
679623
679766
  const autostartChanged = menuState.autostartItem.checked !== autostartRegistered;
679624
679767
  if (autostartChanged) menuState.autostartItem.checked = autostartRegistered;
@@ -679687,6 +679830,22 @@ async function runTrayForeground(explicitEndpoint) {
679687
679830
  await tray?.sendAction({ type: "update-item", item: menuState.updateItem });
679688
679831
  break;
679689
679832
  }
679833
+ case "check-update": {
679834
+ const currentVersion = health.version;
679835
+ if (!currentVersion) break;
679836
+ availableUpdate = await checkForUpdate(currentVersion, true);
679837
+ updateView = trayUpdatePresentation(
679838
+ currentVersion,
679839
+ availableUpdate?.latestVersion,
679840
+ readUpdateState()
679841
+ );
679842
+ menuState.updateItem.title = updateView.title;
679843
+ menuState.updateItem.tooltip = updateView.tooltip;
679844
+ menuState.updateItem.enabled = updateView.enabled;
679845
+ menuState.updateItem.action = updateView.action;
679846
+ await tray?.sendAction({ type: "update-item", item: menuState.updateItem });
679847
+ break;
679848
+ }
679690
679849
  case "quit":
679691
679850
  await shutdown();
679692
679851
  break;
@@ -679708,7 +679867,7 @@ async function runTrayForeground(explicitEndpoint) {
679708
679867
  releaseTrayPid(paths);
679709
679868
  }
679710
679869
  }
679711
- var DEFAULT_ENDPOINT, TRAY_HELPER_VERSION, POLL_INTERVAL_MS, START_WAIT_MS, SERVICE_LABEL, LAUNCHD_LABEL, WINDOWS_TASK_NAME, EXPECTED_HELPER_SHA256;
679870
+ var DEFAULT_ENDPOINT, TRAY_HELPER_VERSION, POLL_INTERVAL_MS, START_WAIT_MS, EXPECTED_HELPER_SHA256;
679712
679871
  var init_tray = __esm({
679713
679872
  "packages/cli/src/tray.ts"() {
679714
679873
  init_daemon();
@@ -679718,9 +679877,6 @@ var init_tray = __esm({
679718
679877
  TRAY_HELPER_VERSION = "2.1.4";
679719
679878
  POLL_INTERVAL_MS = 1e4;
679720
679879
  START_WAIT_MS = 5e3;
679721
- SERVICE_LABEL = "omnius-daemon.service";
679722
- LAUNCHD_LABEL = "ai.omnius.daemon";
679723
- WINDOWS_TASK_NAME = "OmniusDaemon";
679724
679880
  EXPECTED_HELPER_SHA256 = {
679725
679881
  aix: void 0,
679726
679882
  android: void 0,
@@ -679759,6 +679915,26 @@ function output(status, json = false) {
679759
679915
  `);
679760
679916
  else printStatus(status);
679761
679917
  }
679918
+ function endpointPort(endpoint) {
679919
+ const port = Number(new URL(endpoint).port);
679920
+ if (!Number.isInteger(port) || port <= 0) {
679921
+ throw new Error(`Invalid tray daemon endpoint: ${endpoint}`);
679922
+ }
679923
+ return port;
679924
+ }
679925
+ async function ensureTrayDaemonOnline(endpoint) {
679926
+ const port = endpointPort(endpoint);
679927
+ const daemon = await ensureDaemonVersion(getLocalCliVersion(), port);
679928
+ if (!daemon.ok) {
679929
+ throw new Error(`Could not reconcile the Omnius daemon on port ${port}`);
679930
+ }
679931
+ for (let attempt = 0; attempt < 10; attempt++) {
679932
+ const health = await pollTrayHealth(endpoint);
679933
+ if (health.kind === "online") return;
679934
+ await new Promise((resolve87) => setTimeout(resolve87, 200));
679935
+ }
679936
+ throw new Error(`Omnius daemon did not become online at ${endpoint}`);
679937
+ }
679762
679938
  async function trayCommand(options2) {
679763
679939
  const raw = options2.subCommand || "status";
679764
679940
  if (!SUBCOMMANDS.has(raw)) {
@@ -679767,10 +679943,12 @@ async function trayCommand(options2) {
679767
679943
  const subCommand = raw;
679768
679944
  const endpoint = resolveTrayEndpoint(options2.endpoint);
679769
679945
  if (subCommand === "run") {
679946
+ await ensureTrayDaemonOnline(endpoint);
679770
679947
  await runTrayForeground(endpoint);
679771
679948
  return;
679772
679949
  }
679773
679950
  if (subCommand === "install") {
679951
+ await ensureTrayDaemonOnline(endpoint);
679774
679952
  const registrationFile = installTrayAutostart(endpoint);
679775
679953
  const status = await startTray(endpoint);
679776
679954
  if (!options2.json) process.stdout.write(`Registered tray autostart: ${registrationFile}
@@ -679787,6 +679965,7 @@ async function trayCommand(options2) {
679787
679965
  return;
679788
679966
  }
679789
679967
  if (subCommand === "start") {
679968
+ await ensureTrayDaemonOnline(endpoint);
679790
679969
  output(await startTray(endpoint), options2.json);
679791
679970
  return;
679792
679971
  }
@@ -679798,7 +679977,11 @@ async function trayCommand(options2) {
679798
679977
  return;
679799
679978
  }
679800
679979
  if (subCommand === "restart") {
679801
- await stopTray();
679980
+ await ensureTrayDaemonOnline(endpoint);
679981
+ const status = await getTrayStatus(endpoint);
679982
+ if (status.running && !await stopTray()) {
679983
+ throw new Error(`Could not stop the existing Omnius indicator on ${status.endpoint}`);
679984
+ }
679802
679985
  output(await startTray(endpoint), options2.json);
679803
679986
  return;
679804
679987
  }
@@ -679808,6 +679991,7 @@ var SUBCOMMANDS;
679808
679991
  var init_tray2 = __esm({
679809
679992
  "packages/cli/src/commands/tray.ts"() {
679810
679993
  init_tray();
679994
+ init_daemon();
679811
679995
  SUBCOMMANDS = /* @__PURE__ */ new Set([
679812
679996
  "install",
679813
679997
  "uninstall",
@@ -724624,9 +724808,18 @@ async function runIndicatorCommand(rawAction, operations = DEFAULT_OPERATIONS) {
724624
724808
  daemon
724625
724809
  };
724626
724810
  }
724811
+ operations.register?.(endpoint);
724627
724812
  const started = await operations.start(endpoint);
724813
+ if (!started.running || !started.ready || started.endpoint !== endpoint || started.error) {
724814
+ return {
724815
+ level: "error",
724816
+ message: `Indicator did not bind to ${endpoint}. ` + formatIndicatorStatus(started, daemon),
724817
+ status: started,
724818
+ daemon
724819
+ };
724820
+ }
724628
724821
  const health = await waitForOnlineHealth(endpoint, operations);
724629
- const status = { ...started, endpoint, health };
724822
+ const status = { ...started, health };
724630
724823
  const level = status.error ? "error" : status.running && status.ready && health.kind === "online" ? "info" : "error";
724631
724824
  return {
724632
724825
  level,
@@ -724648,6 +724841,7 @@ var init_indicator_command = __esm({
724648
724841
  init_daemon();
724649
724842
  DEFAULT_OPERATIONS = {
724650
724843
  ensureDaemon: () => ensureDaemonVersion(),
724844
+ register: (endpoint) => installTrayAutostart(endpoint),
724651
724845
  start: (endpoint) => startTray(endpoint),
724652
724846
  status: () => getTrayStatus(),
724653
724847
  health: (endpoint) => pollTrayHealth(endpoint),
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.600",
3
+ "version": "1.0.601",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.600",
9
+ "version": "1.0.601",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -4084,9 +4084,9 @@
4084
4084
  }
4085
4085
  },
4086
4086
  "node_modules/hono": {
4087
- "version": "4.12.34",
4088
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.34.tgz",
4089
- "integrity": "sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==",
4087
+ "version": "4.13.0",
4088
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.0.tgz",
4089
+ "integrity": "sha512-jhunvfHWxd7J5EFfSgH4xsYJzSe/lfqbUCxiyyeaQasUsXeEHXtzVid+7EOGByc5JnFa23SSFL3Y2RV/z1T+eQ==",
4090
4090
  "license": "MIT",
4091
4091
  "engines": {
4092
4092
  "node": ">=16.9.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.600",
3
+ "version": "1.0.601",
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",