tesseract-agent 0.9.1 → 0.9.2

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.
Files changed (2) hide show
  1. package/dist-bundle/cli.js +112 -9
  2. package/package.json +1 -1
@@ -58595,7 +58595,7 @@ var require_main = __commonJS({
58595
58595
  init_base_paths();
58596
58596
  import { existsSync as existsSync34, mkdtempSync as mkdtempSync2, readFileSync as readFileSync32, rmSync as rmSync9 } from "node:fs";
58597
58597
  import { createHash as createHash8 } from "node:crypto";
58598
- import { execFileSync as execFileSync4, spawn as spawn12 } from "node:child_process";
58598
+ import { execFileSync as execFileSync5, spawn as spawn12 } from "node:child_process";
58599
58599
  import { fileURLToPath as fileURLToPath4 } from "node:url";
58600
58600
  import { tmpdir as tmpdir4 } from "node:os";
58601
58601
  import { dirname as dirname25, join as join56, resolve as resolve11 } from "node:path";
@@ -79483,6 +79483,7 @@ async function startLocalServer(opts) {
79483
79483
  // ../../packages/host-core/dist/daemon-runtime.js
79484
79484
  init_base_paths();
79485
79485
  import { readFileSync as readFileSync30, writeFileSync as writeFileSync25, existsSync as existsSync28, mkdirSync as mkdirSync26, unlinkSync as unlinkSync3, chmodSync as chmodSync5 } from "node:fs";
79486
+ import { execFileSync as execFileSync4 } from "node:child_process";
79486
79487
  import { join as join50 } from "node:path";
79487
79488
  import { randomBytes as randomBytes8 } from "node:crypto";
79488
79489
  import { hostname as hostname4 } from "node:os";
@@ -80647,6 +80648,85 @@ async function runDaemon(opts = {}) {
80647
80648
  } catch {
80648
80649
  }
80649
80650
  }
80651
+ function otherDaemonPids() {
80652
+ const isDaemonCmd = (cmd) => {
80653
+ if (!/host-daemon[/\\](?:dist[/\\])?index\.js["']?\s*$/.test(cmd))
80654
+ return false;
80655
+ const exe0 = (cmd.trim().split(/\s+/)[0] ?? "").replace(/^["']/, "").split(/[/\\]/).pop() ?? "";
80656
+ return /^(Tesseract.*|Electron|electron|node)(\.exe)?$/i.test(exe0);
80657
+ };
80658
+ const pids = [];
80659
+ try {
80660
+ if (process.platform === "win32") {
80661
+ const raw = execFileSync4("powershell.exe", [
80662
+ "-NoProfile",
80663
+ "-NonInteractive",
80664
+ "-Command",
80665
+ `Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'host-daemon[\\\\/].*index\\.js' -and $_.Name -match '^(Tesseract.*|electron|node)\\.exe$' } | ForEach-Object { "$($_.ProcessId)\`t$($_.CommandLine)" }`
80666
+ ], { encoding: "utf8", timeout: 5e3, windowsHide: true });
80667
+ for (const line of raw.split(/\r?\n/)) {
80668
+ const i = line.indexOf(" ");
80669
+ if (i < 0)
80670
+ continue;
80671
+ const pid = Number(line.slice(0, i).trim());
80672
+ if (pid > 0 && isDaemonCmd(line.slice(i + 1)))
80673
+ pids.push(pid);
80674
+ }
80675
+ } else {
80676
+ const raw = execFileSync4("ps", ["-axww", "-o", "pid=,command="], { encoding: "utf8", timeout: 5e3 });
80677
+ for (const line of raw.split("\n")) {
80678
+ const m = line.match(/^\s*(\d+)\s+(.*)$/);
80679
+ if (m && isDaemonCmd(m[2]))
80680
+ pids.push(Number(m[1]));
80681
+ }
80682
+ }
80683
+ } catch {
80684
+ }
80685
+ return pids;
80686
+ }
80687
+ async function takeoverMachine() {
80688
+ const rivals = /* @__PURE__ */ new Set();
80689
+ try {
80690
+ const lp = Number(readFileSync30(pidfile(), "utf-8").trim());
80691
+ if (lp > 0)
80692
+ rivals.add(lp);
80693
+ } catch {
80694
+ }
80695
+ try {
80696
+ const sp = Number(JSON.parse(readFileSync30(statusFile(), "utf-8")).pid ?? 0);
80697
+ if (sp > 0)
80698
+ rivals.add(sp);
80699
+ } catch {
80700
+ }
80701
+ for (const p of otherDaemonPids())
80702
+ rivals.add(p);
80703
+ rivals.delete(process.pid);
80704
+ const live = [...rivals].filter(isAlive2);
80705
+ if (live.length) {
80706
+ for (const pid of live) {
80707
+ log5(`takeover: killing rival daemon pid=${pid} (latest-wins single-instance)`);
80708
+ try {
80709
+ process.kill(pid, "SIGTERM");
80710
+ } catch {
80711
+ }
80712
+ }
80713
+ for (let i = 0; i < 25 && live.some(isAlive2); i++)
80714
+ await new Promise((r) => setTimeout(r, 100));
80715
+ for (const pid of live)
80716
+ if (isAlive2(pid)) {
80717
+ log5(`takeover: SIGKILL rival pid=${pid} (ignored SIGTERM)`);
80718
+ try {
80719
+ process.kill(pid, "SIGKILL");
80720
+ } catch {
80721
+ }
80722
+ }
80723
+ }
80724
+ try {
80725
+ if (existsSync28(pidfile()))
80726
+ unlinkSync3(pidfile());
80727
+ } catch {
80728
+ }
80729
+ }
80650
80730
  function writeStatus(s) {
80651
80731
  try {
80652
80732
  writeFileSync25(statusFile(), JSON.stringify({ pid: process.pid, version: VERSION, execPath: process.execPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), gui: daemonGuiTrayActive(), ...localInfo ?? {}, ...s }));
@@ -80654,9 +80734,20 @@ async function runDaemon(opts = {}) {
80654
80734
  } catch {
80655
80735
  }
80656
80736
  }
80657
- if (process.env.CCB_RDESK_ROLE !== "client" && !acquireLock2()) {
80658
- log5("another daemon instance owns this machine \u2014 exiting");
80659
- process.exit(0);
80737
+ if (process.env.CCB_RDESK_ROLE !== "client") {
80738
+ await takeoverMachine();
80739
+ if (!acquireLock2()) {
80740
+ try {
80741
+ unlinkSync3(pidfile());
80742
+ } catch {
80743
+ }
80744
+ if (!acquireLock2()) {
80745
+ try {
80746
+ writeFileSync25(pidfile(), String(process.pid));
80747
+ } catch {
80748
+ }
80749
+ }
80750
+ }
80660
80751
  }
80661
80752
  let timer = null;
80662
80753
  let localServer = null;
@@ -80667,7 +80758,19 @@ async function runDaemon(opts = {}) {
80667
80758
  let activityTimer = null;
80668
80759
  const creds3 = readCredentials();
80669
80760
  const deviceId2 = creds3?.deviceId;
80670
- function shutdown(code) {
80761
+ const daemonStartedAt = Date.now();
80762
+ process.on("exit", (code) => {
80763
+ try {
80764
+ log5(`PROCESS EXIT code=${code} uptimeMs=${Date.now() - daemonStartedAt}`);
80765
+ } catch {
80766
+ }
80767
+ });
80768
+ function shutdown(code, reason = "unknown") {
80769
+ try {
80770
+ log5(`SHUTDOWN reason=${reason} code=${code} uptimeMs=${Date.now() - daemonStartedAt} ppid=${process.ppid} pid=${process.pid}`);
80771
+ log5(`SHUTDOWN caller: ${(new Error("shutdown").stack ?? "").split("\n").slice(2, 7).map((l) => l.trim()).join(" <- ")}`);
80772
+ } catch {
80773
+ }
80671
80774
  if (timer) {
80672
80775
  clearInterval(timer);
80673
80776
  timer = null;
@@ -80694,8 +80797,8 @@ async function runDaemon(opts = {}) {
80694
80797
  releaseLock();
80695
80798
  process.exit(code);
80696
80799
  }
80697
- process.on("SIGTERM", () => shutdown(0));
80698
- process.on("SIGINT", () => shutdown(0));
80800
+ process.on("SIGTERM", () => shutdown(0, "signal:SIGTERM"));
80801
+ process.on("SIGINT", () => shutdown(0, "signal:SIGINT"));
80699
80802
  if (process.env.CCB_RDESK_ROLE !== "client")
80700
80803
  process.env.CCB_HOST_DAEMON = "1";
80701
80804
  const localToken = randomBytes8(24).toString("hex");
@@ -80761,7 +80864,7 @@ async function runDaemon(opts = {}) {
80761
80864
  unlinkSync3(join50(daemonDir2(), "credentials.json"));
80762
80865
  } catch {
80763
80866
  }
80764
- shutdown(0);
80867
+ shutdown(0, "token-revoked-401");
80765
80868
  }
80766
80869
  return;
80767
80870
  }
@@ -81872,7 +81975,7 @@ async function captureClaudeSubscription(flags) {
81872
81975
  const file2 = join56(home, ".credentials.json");
81873
81976
  if (existsSync34(file2)) return readFileSync32(file2, "utf8");
81874
81977
  if (process.platform === "darwin") {
81875
- const value = execFileSync4("security", [
81978
+ const value = execFileSync5("security", [
81876
81979
  "find-generic-password",
81877
81980
  "-s",
81878
81981
  "Claude Code-credentials",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tesseract-agent",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "license": "UNLICENSED",
5
5
  "publishConfig": {
6
6
  "access": "public",