@zixt/host 0.0.118 → 0.0.120

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/index.js +937 -461
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,27 +8,27 @@ var __export = (target, all) => {
8
8
  };
9
9
 
10
10
  // src/supervisor.ts
11
- import { spawn as spawn5 } from "node:child_process";
11
+ import { spawn as spawn6 } from "node:child_process";
12
12
  import { fstatSync } from "node:fs";
13
13
  import {
14
14
  access as access2,
15
15
  lstat as lstat5,
16
- mkdir as mkdir5,
16
+ mkdir as mkdir6,
17
17
  open as open4,
18
18
  readFile as readFile7,
19
19
  readlink,
20
20
  readdir as readdir4,
21
21
  rename as rename3,
22
- rm as rm5,
22
+ rm as rm6,
23
23
  symlink
24
24
  } from "node:fs/promises";
25
- import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute9, join as join8, relative as relative4, resolve as resolve5, sep as sep4 } from "node:path";
26
- import { homedir as homedir3 } from "node:os";
25
+ import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute10, join as join10, relative as relative4, resolve as resolve5, sep as sep4 } from "node:path";
26
+ import { homedir as homedir4 } from "node:os";
27
27
 
28
28
  // package.json
29
29
  var package_default = {
30
30
  name: "@zixt/host",
31
- version: "0.0.118",
31
+ version: "0.0.120",
32
32
  type: "module",
33
33
  exports: {
34
34
  ".": "./src/client.ts",
@@ -22148,10 +22148,10 @@ async function publishTaskFile(input) {
22148
22148
  if (!roots.some((root) => isWithin(file2, root))) {
22149
22149
  return { ok: false, error: "the file is outside this task workspace" };
22150
22150
  }
22151
- const stat3 = await lstat(file2);
22152
- if (!stat3.isFile()) return { ok: false, error: "only regular files can be published" };
22153
- if (stat3.size < 1) return { ok: false, error: "empty files cannot be published" };
22154
- if (stat3.size > TASK_ARTIFACT_MAX_BYTES) {
22151
+ const stat4 = await lstat(file2);
22152
+ if (!stat4.isFile()) return { ok: false, error: "only regular files can be published" };
22153
+ if (stat4.size < 1) return { ok: false, error: "empty files cannot be published" };
22154
+ if (stat4.size > TASK_ARTIFACT_MAX_BYTES) {
22155
22155
  return {
22156
22156
  ok: false,
22157
22157
  error: `the file is larger than Zixt's ${TASK_ARTIFACT_MAX_BYTES / 1024 / 1024} MB limit`
@@ -22364,13 +22364,299 @@ function isCommandNotFound(text) {
22364
22364
  return /\bENOENT\b|is not recognized|command not found|no such file/i.test(text);
22365
22365
  }
22366
22366
 
22367
+ // src/runners/runner-install.ts
22368
+ import { spawn as spawn2 } from "node:child_process";
22369
+ import { mkdir, rm, writeFile } from "node:fs/promises";
22370
+ import { homedir, tmpdir } from "node:os";
22371
+ import { isAbsolute as isAbsolute3, join as join3 } from "node:path";
22372
+
22373
+ // src/runners/installer-env.ts
22374
+ import { dirname, join as join2 } from "node:path";
22375
+ function npmCommand(platform = process.platform) {
22376
+ return platform === "win32" ? "npm.cmd" : "npm";
22377
+ }
22378
+ async function resolveInstallerCommand(options = {}) {
22379
+ const platform = options.platform ?? process.platform;
22380
+ const command = npmCommand(platform);
22381
+ if (platform !== "win32") return command;
22382
+ const execPath = options.execPath ?? process.execPath;
22383
+ const resolution = {
22384
+ platform,
22385
+ ...options.searchPath !== void 0 ? { searchPath: options.searchPath } : {}
22386
+ };
22387
+ return (
22388
+ // npm ships beside the `node` running this process, and that copy is the
22389
+ // one matching it. A per-user Scheduled Task may carry no npm on PATH.
22390
+ await resolveTrustedCliCommand(join2(dirname(execPath), command), resolution) ?? await resolveTrustedCliCommand(command, resolution) ?? // Nothing resolved: keep the previous behaviour, so a Machine without npm
22391
+ // fails one install rather than changing how failure is handled.
22392
+ command
22393
+ );
22394
+ }
22395
+ function windowsInstallerCommandLine(command, args) {
22396
+ return [command, ...args].map(quoteForCmd).join(" ");
22397
+ }
22398
+ function sanitizedInstallerEnv(inherited) {
22399
+ const allowed = /* @__PURE__ */ new Set([
22400
+ "PATH",
22401
+ "HOME",
22402
+ "USERPROFILE",
22403
+ "SYSTEMROOT",
22404
+ "WINDIR",
22405
+ "TEMP",
22406
+ "TMP",
22407
+ "TMPDIR",
22408
+ "LOCALAPPDATA",
22409
+ "APPDATA",
22410
+ "XDG_CONFIG_HOME",
22411
+ "XDG_CACHE_HOME",
22412
+ "HTTP_PROXY",
22413
+ "HTTPS_PROXY",
22414
+ "NO_PROXY",
22415
+ "ALL_PROXY",
22416
+ "NODE_EXTRA_CA_CERTS",
22417
+ "SSL_CERT_FILE",
22418
+ "SSL_CERT_DIR",
22419
+ "NPM_CONFIG_REGISTRY",
22420
+ "NPM_CONFIG_CACHE",
22421
+ "NPM_CONFIG_USERCONFIG",
22422
+ "NPM_CONFIG_STRICT_SSL"
22423
+ ]);
22424
+ return Object.fromEntries(
22425
+ Object.entries(inherited).filter(
22426
+ ([name, value]) => value !== void 0 && allowed.has(name.toUpperCase())
22427
+ )
22428
+ );
22429
+ }
22430
+
22431
+ // src/runners/runner-install.ts
22432
+ var CLAUDE_INSTALLER_URL_POSIX = "https://claude.ai/install.sh";
22433
+ var CLAUDE_INSTALLER_URL_WINDOWS = "https://claude.ai/install.ps1";
22434
+ var CODEX_PACKAGE = "@openai/codex";
22435
+ var INSTALL_TIMEOUT_MS = 10 * 6e4;
22436
+ var FAILURE_COOLDOWN_MS = 10 * 6e4;
22437
+ function defaultRunnerToolsRoot() {
22438
+ return join3(homedir(), ".zixt", "tools");
22439
+ }
22440
+ function runnerCommandCandidates(type, options = {}) {
22441
+ const platform = options.platform ?? process.platform;
22442
+ const home = options.home ?? homedir();
22443
+ const toolsRoot = options.toolsRoot ?? defaultRunnerToolsRoot();
22444
+ if (type === "claude-code") return [join3(home, ".local", "bin", "claude")];
22445
+ return platform === "win32" ? [join3(toolsRoot, "codex")] : [join3(toolsRoot, "bin", "codex")];
22446
+ }
22447
+ async function commandRuns(path) {
22448
+ return new Promise((resolve18) => {
22449
+ let child;
22450
+ try {
22451
+ child = spawnCli(path, ["--version"], {
22452
+ stdio: "ignore",
22453
+ windowsHide: true
22454
+ });
22455
+ } catch {
22456
+ resolve18(false);
22457
+ return;
22458
+ }
22459
+ const timer = setTimeout(() => {
22460
+ child.kill();
22461
+ resolve18(false);
22462
+ }, 1e4);
22463
+ timer.unref?.();
22464
+ child.once("error", () => {
22465
+ clearTimeout(timer);
22466
+ resolve18(false);
22467
+ });
22468
+ child.once("exit", (code) => {
22469
+ clearTimeout(timer);
22470
+ resolve18(code === 0);
22471
+ });
22472
+ });
22473
+ }
22474
+ async function resolveRunnerCommand(command, type, options = {}) {
22475
+ const candidates = [];
22476
+ if (!options.managedOnly) {
22477
+ const fromPath = await resolveTrustedCliCommand(command, options.resolution ?? {});
22478
+ if (fromPath) candidates.push(fromPath);
22479
+ }
22480
+ if (!command.includes("/") && !command.includes("\\")) {
22481
+ for (const candidate of runnerCommandCandidates(type, options)) {
22482
+ const resolved = await resolveTrustedCliCommand(candidate, options.resolution ?? {});
22483
+ if (resolved && !candidates.includes(resolved)) candidates.push(resolved);
22484
+ }
22485
+ }
22486
+ if (!options.probe) return candidates[0] ?? null;
22487
+ for (const candidate of candidates) {
22488
+ if (await commandRuns(candidate)) return candidate;
22489
+ }
22490
+ return null;
22491
+ }
22492
+ function windowsPowershell(env) {
22493
+ const root = env.SYSTEMROOT ?? env.WINDIR;
22494
+ if (!root || !isAbsolute3(root)) return null;
22495
+ return join3(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
22496
+ }
22497
+ async function runInstaller(plan, env) {
22498
+ await new Promise((resolveRun, rejectRun) => {
22499
+ const child = plan.shellLine !== void 0 ? spawn2(plan.shellLine, {
22500
+ ...plan.cwd ? { cwd: plan.cwd } : {},
22501
+ env,
22502
+ // stdin stays closed: see the module comment. Output flows to the
22503
+ // ordinary worker console so progress reaches the cloud and the
22504
+ // local console file.
22505
+ stdio: ["ignore", "inherit", "inherit"],
22506
+ windowsHide: true,
22507
+ shell: true
22508
+ }) : spawn2(plan.command, plan.args, {
22509
+ ...plan.cwd ? { cwd: plan.cwd } : {},
22510
+ env,
22511
+ stdio: ["ignore", "inherit", "inherit"],
22512
+ windowsHide: true
22513
+ });
22514
+ let settled = false;
22515
+ const finish = (error52) => {
22516
+ if (settled) return;
22517
+ settled = true;
22518
+ clearTimeout(timer);
22519
+ if (error52) rejectRun(error52);
22520
+ else resolveRun();
22521
+ };
22522
+ const timer = setTimeout(() => {
22523
+ child.kill();
22524
+ finish(new Error("the runner installer did not finish within 10 minutes"));
22525
+ }, INSTALL_TIMEOUT_MS);
22526
+ timer.unref?.();
22527
+ child.once("error", (error52) => finish(error52));
22528
+ child.once("exit", (code, signal) => {
22529
+ if (code === 0) finish();
22530
+ else {
22531
+ finish(
22532
+ new Error(
22533
+ signal ? `the runner installer stopped with ${signal}` : `the runner installer exited with code ${code ?? "unknown"}`
22534
+ )
22535
+ );
22536
+ }
22537
+ });
22538
+ });
22539
+ }
22540
+ async function downloadInstallerScript(url3, destination) {
22541
+ const response = await fetch(url3, { signal: AbortSignal.timeout(6e4) });
22542
+ if (!response.ok) {
22543
+ throw new Error(`the installer download answered HTTP ${response.status}`);
22544
+ }
22545
+ const body = await response.text();
22546
+ if (!body || body.length > 5 * 1024 * 1024) {
22547
+ throw new Error("the installer download looked wrong and was not run");
22548
+ }
22549
+ await writeFile(destination, body, { encoding: "utf8", mode: 448 });
22550
+ }
22551
+ function createRunnerAutoInstaller(options) {
22552
+ const platform = options.platform ?? process.platform;
22553
+ const home = options.home ?? homedir();
22554
+ const toolsRoot = options.toolsRoot ?? defaultRunnerToolsRoot();
22555
+ const now = options.now ?? Date.now;
22556
+ const inFlight = /* @__PURE__ */ new Map();
22557
+ const failedAt = /* @__PURE__ */ new Map();
22558
+ const installClaude = async () => {
22559
+ const script = join3(
22560
+ tmpdir(),
22561
+ `zixt-claude-install-${process.pid}-${crypto.randomUUID()}.${platform === "win32" ? "ps1" : "sh"}`
22562
+ );
22563
+ try {
22564
+ if (platform === "win32") {
22565
+ await downloadInstallerScript(CLAUDE_INSTALLER_URL_WINDOWS, script);
22566
+ const powershell = windowsPowershell(process.env);
22567
+ if (!powershell) throw new Error("Windows PowerShell could not be found");
22568
+ await runInstaller(
22569
+ {
22570
+ command: powershell,
22571
+ args: ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script]
22572
+ },
22573
+ sanitizedInstallerEnv(process.env)
22574
+ );
22575
+ } else {
22576
+ await downloadInstallerScript(CLAUDE_INSTALLER_URL_POSIX, script);
22577
+ await runInstaller({ command: "bash", args: [script] }, sanitizedInstallerEnv(process.env));
22578
+ }
22579
+ } finally {
22580
+ await rm(script, { force: true }).catch(() => void 0);
22581
+ }
22582
+ };
22583
+ const installCodex = async () => {
22584
+ await mkdir(toolsRoot, { recursive: true, mode: 448 });
22585
+ const npm = await resolveInstallerCommand({ platform });
22586
+ const args = [
22587
+ "install",
22588
+ "-g",
22589
+ "--prefix",
22590
+ toolsRoot,
22591
+ "--no-audit",
22592
+ "--no-fund",
22593
+ "--ignore-scripts",
22594
+ CODEX_PACKAGE
22595
+ ];
22596
+ if (platform === "win32") {
22597
+ await runInstaller(
22598
+ { shellLine: windowsInstallerCommandLine(npm, args), cwd: toolsRoot },
22599
+ sanitizedInstallerEnv(process.env)
22600
+ );
22601
+ } else {
22602
+ await runInstaller(
22603
+ { command: npm, args, cwd: toolsRoot },
22604
+ sanitizedInstallerEnv(process.env)
22605
+ );
22606
+ }
22607
+ };
22608
+ const install = options.install ?? ((type) => type === "claude-code" ? installClaude() : installCodex());
22609
+ return {
22610
+ ensureInstalled(type) {
22611
+ if (inFlight.has(type)) return;
22612
+ const lastFailure = failedAt.get(type);
22613
+ if (lastFailure !== void 0 && now() - lastFailure < FAILURE_COOLDOWN_MS) return;
22614
+ options.onEvent({ runner: type, state: "started" });
22615
+ const attempt = (async () => {
22616
+ try {
22617
+ await install(type);
22618
+ const resolved = await resolveRunnerCommand(
22619
+ type === "claude-code" ? "claude" : "codex",
22620
+ type,
22621
+ {
22622
+ home,
22623
+ toolsRoot,
22624
+ probe: true,
22625
+ managedOnly: true,
22626
+ ...options.resolution ? { resolution: options.resolution } : {}
22627
+ }
22628
+ );
22629
+ if (!resolved) {
22630
+ throw new Error("the installer finished but the runner is still not on this Machine");
22631
+ }
22632
+ failedAt.delete(type);
22633
+ options.onEvent({ runner: type, state: "completed" });
22634
+ } catch (error52) {
22635
+ failedAt.set(type, now());
22636
+ options.onEvent({
22637
+ runner: type,
22638
+ state: "failed",
22639
+ error: error52 instanceof Error ? error52.message : "unknown runner install error"
22640
+ });
22641
+ } finally {
22642
+ inFlight.delete(type);
22643
+ }
22644
+ })();
22645
+ inFlight.set(type, attempt);
22646
+ },
22647
+ async settled() {
22648
+ while (inFlight.size > 0) await Promise.allSettled([...inFlight.values()]);
22649
+ }
22650
+ };
22651
+ }
22652
+
22367
22653
  // src/runners/title.ts
22368
22654
  var TITLE_TIMEOUT_MS = 45e3;
22369
22655
  var INSTRUCTIONS_BUDGET = 4e3;
22370
22656
  var CLAUDE_TITLE_MODEL = "haiku";
22371
22657
  async function generateTaskTitle(instructions, runner) {
22372
22658
  if (runner && runner.type !== "claude-code") return null;
22373
- const command = await resolveTrustedCliCommand("claude");
22659
+ const command = await resolveRunnerCommand("claude", "claude-code");
22374
22660
  if (!command) return null;
22375
22661
  const prompt = [
22376
22662
  "Name this task for a task list. Reply with ONLY the name: at most eight",
@@ -22443,7 +22729,7 @@ function isPlausibleTaskTitle(title) {
22443
22729
  // src/worker-watchdog.ts
22444
22730
  import { randomUUID } from "node:crypto";
22445
22731
  import { writeFileSync as writeFileSync2 } from "node:fs";
22446
- import { isAbsolute as isAbsolute4 } from "node:path";
22732
+ import { isAbsolute as isAbsolute5 } from "node:path";
22447
22733
 
22448
22734
  // src/worker-ownership.ts
22449
22735
  import {
@@ -22456,8 +22742,8 @@ import {
22456
22742
  rmSync,
22457
22743
  writeFileSync
22458
22744
  } from "node:fs";
22459
- import { chmod, lstat as lstat2, mkdir, open, readFile as readFile2, readdir, rm, rmdir } from "node:fs/promises";
22460
- import { basename as basename2, dirname, isAbsolute as isAbsolute3, join as join2, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
22745
+ import { chmod, lstat as lstat2, mkdir as mkdir2, open, readFile as readFile2, readdir, rm as rm2, rmdir } from "node:fs/promises";
22746
+ import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute4, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
22461
22747
  var LAUNCHER_OWNERSHIP_DIR_ENV = "ZIXT_HOST_LAUNCHER_OWNERSHIP_DIR";
22462
22748
  var WORKER_OWNERSHIP_FILE_ENV = "ZIXT_HOST_WORKER_OWNERSHIP_FILE";
22463
22749
  var SUPERVISOR_OWNERSHIP_FILE_ENV = "ZIXT_HOST_SUPERVISOR_OWNERSHIP_FILE";
@@ -22467,8 +22753,8 @@ var MAX_OWNERSHIP_RECORD_BYTES = 4 * 1024;
22467
22753
  var MAX_OWNERSHIP_RECORDS = 32;
22468
22754
  var MAX_OWNERSHIP_GENERATIONS = 32;
22469
22755
  function workerOwnershipFile(directory, nonce) {
22470
- if (!isAbsolute3(directory) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce)) return null;
22471
- return join2(directory, `${nonce}.json`);
22756
+ if (!isAbsolute4(directory) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce)) return null;
22757
+ return join4(directory, `${nonce}.json`);
22472
22758
  }
22473
22759
  function workerOwnershipArguments(nonce) {
22474
22760
  return [WORKER_OWNERSHIP_ARGUMENT, nonce];
@@ -22477,7 +22763,7 @@ function consumeWorkerOwnershipArguments(argv, env) {
22477
22763
  const file2 = env[WORKER_OWNERSHIP_FILE_ENV];
22478
22764
  const nonce = env.ZIXT_HOST_WORKER_WATCHDOG_NONCE;
22479
22765
  if (typeof file2 !== "string") return { argv: [...argv], requested: false, valid: true };
22480
- if (typeof nonce !== "string" || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || !isAbsolute3(file2) || basename2(file2) !== `${nonce}.json`) {
22766
+ if (typeof nonce !== "string" || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || !isAbsolute4(file2) || basename2(file2) !== `${nonce}.json`) {
22481
22767
  return { argv: [...argv], requested: true, valid: false };
22482
22768
  }
22483
22769
  const result = [];
@@ -22504,11 +22790,11 @@ function syncDirectorySync(path) {
22504
22790
  }
22505
22791
  }
22506
22792
  function recordWorkerOwnership(path, nonce, pid = process.pid) {
22507
- if (!isAbsolute3(path) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || basename2(path) !== `${nonce}.json` || !Number.isSafeInteger(pid) || pid <= 1) {
22793
+ if (!isAbsolute4(path) || !SAFE_WORKER_OWNERSHIP_NONCE.test(nonce) || basename2(path) !== `${nonce}.json` || !Number.isSafeInteger(pid) || pid <= 1) {
22508
22794
  return false;
22509
22795
  }
22510
- const directory = dirname(path);
22511
- const temporary = join2(directory, `.pending-${crypto.randomUUID()}`);
22796
+ const directory = dirname2(path);
22797
+ const temporary = join4(directory, `.pending-${crypto.randomUUID()}`);
22512
22798
  const existingMatches = () => {
22513
22799
  try {
22514
22800
  const metadata = lstatSync(path);
@@ -22562,16 +22848,16 @@ async function syncDirectory(path) {
22562
22848
  }
22563
22849
  }
22564
22850
  async function ensurePrivateOwnershipRoot(root) {
22565
- if (!isAbsolute3(root)) throw new Error("launcher ownership root is invalid");
22566
- const firstCreated = await mkdir(root, { recursive: true, mode: 448 });
22851
+ if (!isAbsolute4(root)) throw new Error("launcher ownership root is invalid");
22852
+ const firstCreated = await mkdir2(root, { recursive: true, mode: 448 });
22567
22853
  if (firstCreated && process.platform !== "win32") {
22568
22854
  const first = resolve3(firstCreated);
22569
22855
  const target = resolve3(root);
22570
- await syncDirectory(dirname(first));
22856
+ await syncDirectory(dirname2(first));
22571
22857
  let current = first;
22572
22858
  for (const part of relative2(first, target).split(sep2).filter(Boolean)) {
22573
22859
  await syncDirectory(current);
22574
- current = join2(current, part);
22860
+ current = join4(current, part);
22575
22861
  }
22576
22862
  }
22577
22863
  const metadata = await lstat2(root);
@@ -22584,14 +22870,14 @@ async function createLauncherOwnershipGeneration(root) {
22584
22870
  await ensurePrivateOwnershipRoot(root);
22585
22871
  for (let attempt = 0; attempt < 8; attempt++) {
22586
22872
  const nonce = crypto.randomUUID();
22587
- const directory = join2(root, nonce);
22873
+ const directory = join4(root, nonce);
22588
22874
  try {
22589
- await mkdir(directory, { mode: 448 });
22875
+ await mkdir2(directory, { mode: 448 });
22590
22876
  await syncDirectory(root);
22591
22877
  return {
22592
22878
  nonce,
22593
22879
  directory,
22594
- supervisorOwnershipFile: join2(directory, `${nonce}.json`)
22880
+ supervisorOwnershipFile: join4(directory, `${nonce}.json`)
22595
22881
  };
22596
22882
  } catch (error52) {
22597
22883
  if (error52.code !== "EEXIST") throw error52;
@@ -22610,7 +22896,7 @@ async function readLauncherOwnershipGenerations(root) {
22610
22896
  if (!entry.isDirectory() || entry.isSymbolicLink() || !SAFE_WORKER_OWNERSHIP_NONCE.test(entry.name)) {
22611
22897
  throw new Error("launcher ownership root is malformed");
22612
22898
  }
22613
- const directory = join2(root, entry.name);
22899
+ const directory = join4(root, entry.name);
22614
22900
  const metadata = await lstat2(directory);
22615
22901
  if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
22616
22902
  throw new Error("launcher ownership generation is not a trusted directory");
@@ -22619,7 +22905,7 @@ async function readLauncherOwnershipGenerations(root) {
22619
22905
  generations.push({
22620
22906
  nonce: entry.name,
22621
22907
  directory,
22622
- supervisorOwnershipFile: join2(directory, `${entry.name}.json`)
22908
+ supervisorOwnershipFile: join4(directory, `${entry.name}.json`)
22623
22909
  });
22624
22910
  }
22625
22911
  return generations.sort((left, right) => left.nonce.localeCompare(right.nonce));
@@ -22633,7 +22919,7 @@ function parseRecord(value, path, expectedNonce) {
22633
22919
  return { schema: 1, nonce: expectedNonce, pid: record2.pid, path };
22634
22920
  }
22635
22921
  async function readWorkerOwnershipRecords(directory) {
22636
- if (!isAbsolute3(directory)) throw new Error("worker ownership directory is invalid");
22922
+ if (!isAbsolute4(directory)) throw new Error("worker ownership directory is invalid");
22637
22923
  const entries = await readdir(directory, { withFileTypes: true }).catch(
22638
22924
  (error52) => {
22639
22925
  if (error52.code === "ENOENT") return [];
@@ -22645,9 +22931,9 @@ async function readWorkerOwnershipRecords(directory) {
22645
22931
  }
22646
22932
  const records = [];
22647
22933
  for (const entry of entries) {
22648
- const path = join2(directory, entry.name);
22934
+ const path = join4(directory, entry.name);
22649
22935
  if (entry.name.startsWith(".pending-")) {
22650
- await rm(path, { force: true });
22936
+ await rm2(path, { force: true });
22651
22937
  continue;
22652
22938
  }
22653
22939
  const match = /^([A-Za-z0-9_-]{16,200})\.json$/.exec(entry.name);
@@ -22667,15 +22953,15 @@ async function readWorkerOwnershipRecords(directory) {
22667
22953
  return records;
22668
22954
  }
22669
22955
  async function forgetWorkerOwnership(path) {
22670
- if (!isAbsolute3(path)) throw new Error("worker ownership path is invalid");
22671
- const directory = dirname(path);
22672
- await rm(path, { force: true });
22956
+ if (!isAbsolute4(path)) throw new Error("worker ownership path is invalid");
22957
+ const directory = dirname2(path);
22958
+ await rm2(path, { force: true });
22673
22959
  await syncDirectory(directory);
22674
22960
  }
22675
22961
  async function removeWorkerOwnershipDirectory(directory) {
22676
22962
  try {
22677
22963
  await rmdir(directory);
22678
- await syncDirectory(dirname(directory));
22964
+ await syncDirectory(dirname2(directory));
22679
22965
  } catch (error52) {
22680
22966
  if (error52.code !== "ENOENT") throw error52;
22681
22967
  }
@@ -22765,7 +23051,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
22765
23051
  }
22766
23052
  const heartbeatFile = env[WORKER_WATCHDOG_FILE_ENV];
22767
23053
  const ipc = typeof process.send === "function" && process.connected;
22768
- const file2 = !ipc && typeof heartbeatFile === "string" && isAbsolute4(heartbeatFile) ? heartbeatFile : null;
23054
+ const file2 = !ipc && typeof heartbeatFile === "string" && isAbsolute5(heartbeatFile) ? heartbeatFile : null;
22769
23055
  if (!ipc && !file2) {
22770
23056
  heartbeatActive = false;
22771
23057
  heartbeatUsesIpc = false;
@@ -22928,7 +23214,7 @@ function workerWatchdogIsActive() {
22928
23214
  // src/workspaces.ts
22929
23215
  import { access, stat as stat2 } from "node:fs/promises";
22930
23216
  import { constants } from "node:fs";
22931
- import { join as join3 } from "node:path";
23217
+ import { join as join5 } from "node:path";
22932
23218
  var PROBE_TIMEOUT_MS = 2e3;
22933
23219
  async function withinBudget(work) {
22934
23220
  let timer;
@@ -22967,7 +23253,7 @@ async function probeWorkspace(workspace) {
22967
23253
  await withinBudget(access(workspace, constants.R_OK | constants.X_OK));
22968
23254
  let error52 = null;
22969
23255
  try {
22970
- await withinBudget(stat2(join3(workspace, ".git")));
23256
+ await withinBudget(stat2(join5(workspace, ".git")));
22971
23257
  } catch {
22972
23258
  error52 = "Usable, but not a git repository";
22973
23259
  }
@@ -25264,9 +25550,9 @@ function watchForUpdates(options) {
25264
25550
  }
25265
25551
 
25266
25552
  // src/runners/process-tree.ts
25267
- import { spawn as spawn2 } from "node:child_process";
25553
+ import { spawn as spawn3 } from "node:child_process";
25268
25554
  import { readFile as readFile3 } from "node:fs/promises";
25269
- import { isAbsolute as isAbsolute5, join as join4 } from "node:path";
25555
+ import { isAbsolute as isAbsolute6, join as join6 } from "node:path";
25270
25556
  var windowsProcessTreeModule = process.platform === "win32" ? import("@vscode/windows-process-tree").catch(() => null) : null;
25271
25557
  var PROCESS_TERM_GRACE_MS = 500;
25272
25558
  var PROCESS_EXIT_POLL_MS = 20;
@@ -25351,7 +25637,7 @@ async function observePosixGuardianNonce(pid, nonce) {
25351
25637
  }
25352
25638
  }
25353
25639
  return new Promise((resolve18, reject3) => {
25354
- const observer = spawn2("/bin/ps", ["-ww", "-o", "command=", "-p", String(pid)], {
25640
+ const observer = spawn3("/bin/ps", ["-ww", "-o", "command=", "-p", String(pid)], {
25355
25641
  stdio: ["ignore", "pipe", "ignore"]
25356
25642
  });
25357
25643
  let output = "";
@@ -25442,7 +25728,7 @@ function posixProcessRecordsFromPs(output) {
25442
25728
  }
25443
25729
  async function snapshotPosixProcesses() {
25444
25730
  return new Promise((resolve18, reject3) => {
25445
- const observer = spawn2("/bin/ps", ["-axo", "uid=,pid=,ppid=,pgid=,stat="], {
25731
+ const observer = spawn3("/bin/ps", ["-axo", "uid=,pid=,ppid=,pgid=,stat="], {
25446
25732
  stdio: ["ignore", "pipe", "ignore"]
25447
25733
  });
25448
25734
  let output = "";
@@ -25722,13 +26008,13 @@ async function observePosixGroupIdentity(records, pgid, identity) {
25722
26008
  }
25723
26009
  function defaultTaskkillCommand() {
25724
26010
  const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
25725
- if (!windowsRoot || !isAbsolute5(windowsRoot)) {
26011
+ if (!windowsRoot || !isAbsolute6(windowsRoot)) {
25726
26012
  throw new ProcessTreeTerminationError(
25727
26013
  "termination_failed",
25728
26014
  "Windows runner tree termination authority is unavailable"
25729
26015
  );
25730
26016
  }
25731
- return join4(windowsRoot, "System32", "taskkill.exe");
26017
+ return join6(windowsRoot, "System32", "taskkill.exe");
25732
26018
  }
25733
26019
  function validWindowsPid(value) {
25734
26020
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= 4294967295;
@@ -25864,7 +26150,7 @@ async function waitForProcessesExit(pids, timeoutMs) {
25864
26150
  async function runTaskkill(pid, command, timeoutMs = TASKKILL_TIMEOUT_MS, independentlyTrackedPids = []) {
25865
26151
  const trustedCommand = command ?? defaultTaskkillCommand();
25866
26152
  const result = await new Promise((resolve18, reject3) => {
25867
- const killer = spawn2(trustedCommand, ["/PID", String(pid), "/T", "/F"], {
26153
+ const killer = spawn3(trustedCommand, ["/PID", String(pid), "/T", "/F"], {
25868
26154
  stdio: ["ignore", "pipe", "pipe"],
25869
26155
  windowsHide: true
25870
26156
  });
@@ -26110,14 +26396,14 @@ async function terminateProcessTree(child, childExited, options = {}) {
26110
26396
  }
26111
26397
 
26112
26398
  // src/release-state.ts
26113
- import { lstat as lstat3, mkdir as mkdir2, open as open2, readFile as readFile4, rename, rm as rm2 } from "node:fs/promises";
26114
- import { dirname as dirname2, join as join5 } from "node:path";
26399
+ import { lstat as lstat3, mkdir as mkdir3, open as open2, readFile as readFile4, rename, rm as rm3 } from "node:fs/promises";
26400
+ import { dirname as dirname3, join as join7 } from "node:path";
26115
26401
  var STATE_FILE = "release-state.json";
26116
26402
  var STATE_SCHEMA = 1;
26117
26403
  var MAX_STATE_BYTES = 4 * 1024;
26118
26404
  var VERSION = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
26119
26405
  function releaseStatePath(root) {
26120
- return join5(root, STATE_FILE);
26406
+ return join7(root, STATE_FILE);
26121
26407
  }
26122
26408
  function parseState(value) {
26123
26409
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -26168,8 +26454,8 @@ function createReleaseStateStore(root) {
26168
26454
  },
26169
26455
  async save(state) {
26170
26456
  const normalized = parseState(state);
26171
- await mkdir2(root, { recursive: true, mode: 448 });
26172
- const temporary = join5(root, `.${STATE_FILE}.${process.pid}.${crypto.randomUUID()}.tmp`);
26457
+ await mkdir3(root, { recursive: true, mode: 448 });
26458
+ const temporary = join7(root, `.${STATE_FILE}.${process.pid}.${crypto.randomUUID()}.tmp`);
26173
26459
  const handle = await open2(temporary, "wx", 384);
26174
26460
  try {
26175
26461
  await handle.writeFile(`${JSON.stringify(normalized)}
@@ -26180,7 +26466,7 @@ function createReleaseStateStore(root) {
26180
26466
  await syncDirectory2(root);
26181
26467
  } catch (error52) {
26182
26468
  await handle.close().catch(() => void 0);
26183
- await rm2(temporary, { force: true }).catch(() => void 0);
26469
+ await rm3(temporary, { force: true }).catch(() => void 0);
26184
26470
  throw error52;
26185
26471
  }
26186
26472
  },
@@ -26193,17 +26479,17 @@ function createReleaseStateStore(root) {
26193
26479
  }
26194
26480
  );
26195
26481
  if (!present) return;
26196
- await rm2(path);
26197
- await syncDirectory2(dirname2(path));
26482
+ await rm3(path);
26483
+ await syncDirectory2(dirname3(path));
26198
26484
  }
26199
26485
  };
26200
26486
  }
26201
26487
 
26202
26488
  // src/worker-diagnostics.ts
26203
26489
  import { randomUUID as randomUUID2 } from "node:crypto";
26204
- import { mkdir as mkdir3, readdir as readdir2, readFile as readFile5, rm as rm3, writeFile } from "node:fs/promises";
26205
- import { homedir } from "node:os";
26206
- import { isAbsolute as isAbsolute6, join as join6 } from "node:path";
26490
+ import { mkdir as mkdir4, readdir as readdir2, readFile as readFile5, rm as rm4, writeFile as writeFile2 } from "node:fs/promises";
26491
+ import { homedir as homedir2 } from "node:os";
26492
+ import { isAbsolute as isAbsolute7, join as join8 } from "node:path";
26207
26493
  var WORKER_DIAGNOSTICS_DIR_ENV = "ZIXT_HOST_DIAGNOSTICS_DIR";
26208
26494
  var RETAINED_RECORDS = 20;
26209
26495
  var STDERR_TAIL_LINES = 40;
@@ -26211,11 +26497,11 @@ var STDERR_LINE_LIMIT = 800;
26211
26497
  var RECORD_TTL_MS = 7 * 24 * 60 * 6e4;
26212
26498
  var RECORD_FILE = /^[0-9a-f-]{36}\.json$/;
26213
26499
  function defaultWorkerDiagnosticsRoot() {
26214
- return join6(homedir(), ".zixt", "host-diagnostics");
26500
+ return join8(homedir2(), ".zixt", "host-diagnostics");
26215
26501
  }
26216
26502
  function configuredWorkerDiagnosticsRoot(env = process.env) {
26217
26503
  const configured = env[WORKER_DIAGNOSTICS_DIR_ENV];
26218
- return typeof configured === "string" && isAbsolute6(configured) ? configured : null;
26504
+ return typeof configured === "string" && isAbsolute7(configured) ? configured : null;
26219
26505
  }
26220
26506
  function boundedStderr(lines) {
26221
26507
  return lines.slice(-STDERR_TAIL_LINES).map(
@@ -26224,13 +26510,13 @@ function boundedStderr(lines) {
26224
26510
  }
26225
26511
  async function recordWorkerExit(root, record2) {
26226
26512
  try {
26227
- await mkdir3(root, { recursive: true, mode: 448 });
26513
+ await mkdir4(root, { recursive: true, mode: 448 });
26228
26514
  const stored = {
26229
26515
  ...record2,
26230
26516
  schema: 1,
26231
26517
  stderr: boundedStderr(record2.stderr)
26232
26518
  };
26233
- await writeFile(join6(root, `${randomUUID2()}.json`), JSON.stringify(stored), {
26519
+ await writeFile2(join8(root, `${randomUUID2()}.json`), JSON.stringify(stored), {
26234
26520
  encoding: "utf8",
26235
26521
  mode: 384
26236
26522
  });
@@ -26266,7 +26552,7 @@ async function readWorkerExits(root) {
26266
26552
  const stored = [];
26267
26553
  for (const name of names) {
26268
26554
  if (!RECORD_FILE.test(name)) continue;
26269
- const file2 = join6(root, name);
26555
+ const file2 = join8(root, name);
26270
26556
  try {
26271
26557
  const record2 = parseRecord2(await readFile5(file2, "utf8"));
26272
26558
  if (record2) stored.push({ file: file2, record: record2 });
@@ -26276,7 +26562,7 @@ async function readWorkerExits(root) {
26276
26562
  return stored.sort((a, b) => Date.parse(a.record.at) - Date.parse(b.record.at));
26277
26563
  }
26278
26564
  async function forgetWorkerExits(files) {
26279
- await Promise.all(files.map((file2) => rm3(file2, { force: true }).catch(() => {
26565
+ await Promise.all(files.map((file2) => rm4(file2, { force: true }).catch(() => {
26280
26566
  })));
26281
26567
  }
26282
26568
  async function pruneWorkerExits(root, nowMs) {
@@ -26308,26 +26594,26 @@ function describeWorkerExit(record2) {
26308
26594
  }
26309
26595
 
26310
26596
  // src/runners/run-artifacts.ts
26311
- import { spawn as spawn4 } from "node:child_process";
26597
+ import { spawn as spawn5 } from "node:child_process";
26312
26598
  import {
26313
26599
  chmod as chmod2,
26314
26600
  lstat as lstat4,
26315
- mkdir as mkdir4,
26601
+ mkdir as mkdir5,
26316
26602
  open as open3,
26317
26603
  readdir as readdir3,
26318
26604
  readFile as readFile6,
26319
26605
  realpath as realpath3,
26320
26606
  rename as rename2,
26321
- rm as rm4,
26322
- writeFile as writeFile2
26607
+ rm as rm5,
26608
+ writeFile as writeFile3
26323
26609
  } from "node:fs/promises";
26324
- import { homedir as homedir2 } from "node:os";
26325
- import { dirname as dirname3, isAbsolute as isAbsolute8, join as join7, relative as relative3, resolve as resolve4, sep as sep3, win32 as win322 } from "node:path";
26610
+ import { homedir as homedir3 } from "node:os";
26611
+ import { dirname as dirname4, isAbsolute as isAbsolute9, join as join9, relative as relative3, resolve as resolve4, sep as sep3, win32 as win322 } from "node:path";
26326
26612
 
26327
26613
  // src/windows-job.ts
26328
- import { spawn as spawn3 } from "node:child_process";
26614
+ import { spawn as spawn4 } from "node:child_process";
26329
26615
  import { randomUUID as randomUUID3 } from "node:crypto";
26330
- import { isAbsolute as isAbsolute7, win32 } from "node:path";
26616
+ import { isAbsolute as isAbsolute8, win32 } from "node:path";
26331
26617
  var WINDOWS_CONTAINMENT_GATE_ENV = "ZIXT_WINDOWS_CONTAINMENT_GATE";
26332
26618
  var WINDOWS_CONTAINMENT_GATE_PREFIX = "__ZIXT_WINDOWS_CONTAINMENT_READY__";
26333
26619
  var WINDOWS_POST_CONTAINMENT_CWD_ENV = "ZIXT_WINDOWS_POST_CONTAINMENT_CWD";
@@ -26640,7 +26926,7 @@ async function createWindowsJobContainment(pid, options) {
26640
26926
  const env = options.env ?? process.env;
26641
26927
  const nonce = randomUUID3();
26642
26928
  const encodedSource = encodedPowershellSource(WINDOWS_JOB_HELPER_SOURCE);
26643
- const helper = options.spawnHelper ? options.spawnHelper(nonce, encodedSource) : spawn3(
26929
+ const helper = options.spawnHelper ? options.spawnHelper(nonce, encodedSource) : spawn4(
26644
26930
  options.powershellCommand ?? defaultPowershellCommand(env),
26645
26931
  [
26646
26932
  "-NoLogo",
@@ -26823,7 +27109,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
26823
27109
  const postContainmentCwd = env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
26824
27110
  delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
26825
27111
  if (postContainmentCwd !== void 0) {
26826
- if (!isAbsolute7(postContainmentCwd)) return finish(false);
27112
+ if (!isAbsolute8(postContainmentCwd)) return finish(false);
26827
27113
  try {
26828
27114
  process.chdir(postContainmentCwd);
26829
27115
  } catch {
@@ -27061,7 +27347,7 @@ foreach ($path in $paths) {
27061
27347
  }
27062
27348
  `;
27063
27349
  function defaultRunArtifactRoot() {
27064
- return join7(homedir2(), ".zixt", "run-artifacts");
27350
+ return join9(homedir3(), ".zixt", "run-artifacts");
27065
27351
  }
27066
27352
  function requireSafeSegment(value, field) {
27067
27353
  if (!SAFE_SEGMENT.test(value)) {
@@ -27073,7 +27359,7 @@ function isMissing(error52) {
27073
27359
  }
27074
27360
  function assertBelow(parent, child) {
27075
27361
  const path = relative3(parent, child);
27076
- const escapes = path === "" || path === ".." || path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute8(path);
27362
+ const escapes = path === "" || path === ".." || path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute9(path);
27077
27363
  if (escapes) throw new Error("run artifact path escapes its private root");
27078
27364
  }
27079
27365
  async function requireRealDirectory(path, label) {
@@ -27108,7 +27394,7 @@ async function prepareRoot(root) {
27108
27394
  const absolute = resolve4(root);
27109
27395
  let realProfile;
27110
27396
  if (process.platform === "win32") {
27111
- const profile = resolve4(homedir2());
27397
+ const profile = resolve4(homedir3());
27112
27398
  assertWindowsProfileBoundary(profile, absolute);
27113
27399
  await rejectWindowsSymlinkAncestors(profile, absolute);
27114
27400
  realProfile = await realpath3(profile);
@@ -27117,7 +27403,7 @@ async function prepareRoot(root) {
27117
27403
  await lstat4(absolute);
27118
27404
  } catch (error52) {
27119
27405
  if (!isMissing(error52)) throw error52;
27120
- await mkdir4(absolute, { recursive: true, mode: DIRECTORY_MODE });
27406
+ await mkdir5(absolute, { recursive: true, mode: DIRECTORY_MODE });
27121
27407
  }
27122
27408
  const real = await requireRealDirectory(absolute, "run artifact root");
27123
27409
  if (realProfile) assertWindowsProfileBoundary(realProfile, real);
@@ -27125,14 +27411,14 @@ async function prepareRoot(root) {
27125
27411
  return real;
27126
27412
  }
27127
27413
  async function prepareAgentRoot(root, agentId) {
27128
- const path = join7(root, agentId);
27414
+ const path = join9(root, agentId);
27129
27415
  assertBelow(root, path);
27130
27416
  try {
27131
27417
  await lstat4(path);
27132
27418
  } catch (error52) {
27133
27419
  if (!isMissing(error52)) throw error52;
27134
27420
  try {
27135
- await mkdir4(path, { mode: DIRECTORY_MODE });
27421
+ await mkdir5(path, { mode: DIRECTORY_MODE });
27136
27422
  } catch (mkdirError) {
27137
27423
  if (mkdirError.code !== "EEXIST") throw mkdirError;
27138
27424
  }
@@ -27148,10 +27434,10 @@ async function lockDownWindowsDirectories(paths) {
27148
27434
  if (!windowsRoot || !win322.isAbsolute(windowsRoot)) {
27149
27435
  throw new Error("private Windows run-artifact ACL authority is unavailable");
27150
27436
  }
27151
- const powershell = join7(windowsRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
27437
+ const powershell = join9(windowsRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
27152
27438
  const encoded = Buffer.from(WINDOWS_PRIVATE_DACL_SCRIPT, "utf16le").toString("base64");
27153
27439
  await new Promise((resolvePromise, reject3) => {
27154
- const helper = spawn4(
27440
+ const helper = spawn5(
27155
27441
  powershell,
27156
27442
  ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", encoded],
27157
27443
  {
@@ -27190,16 +27476,16 @@ async function lockDownWindowsDirectories(paths) {
27190
27476
  });
27191
27477
  }
27192
27478
  async function createPrivateDirectory(parent, name) {
27193
- const path = join7(parent, name);
27479
+ const path = join9(parent, name);
27194
27480
  assertBelow(parent, path);
27195
- await mkdir4(path, { mode: DIRECTORY_MODE });
27481
+ await mkdir5(path, { mode: DIRECTORY_MODE });
27196
27482
  await chmod2(path, DIRECTORY_MODE);
27197
27483
  const real = await realpath3(path);
27198
27484
  assertBelow(parent, real);
27199
27485
  return real;
27200
27486
  }
27201
27487
  async function writePrivateFile(path, content) {
27202
- await writeFile2(path, content, { flag: "wx", mode: FILE_MODE });
27488
+ await writeFile3(path, content, { flag: "wx", mode: FILE_MODE });
27203
27489
  await chmod2(path, FILE_MODE);
27204
27490
  }
27205
27491
  function quotePosix(value) {
@@ -27219,24 +27505,24 @@ async function createRunArtifacts(input) {
27219
27505
  requireSafeSegment(input.agentId, "agentId");
27220
27506
  requireSafeSegment(input.runToken, "runToken");
27221
27507
  const root = await prepareRoot(input.root);
27222
- const removeTree = input.removeTree ?? ((path) => rm4(path, { recursive: true, force: true }));
27508
+ const removeTree = input.removeTree ?? ((path) => rm5(path, { recursive: true, force: true }));
27223
27509
  const cleanupRetryDelayMs = input.cleanupRetryDelayMs ?? CLEANUP_RETRY_DELAY_MS;
27224
27510
  const agentRoot = await prepareAgentRoot(root, input.agentId);
27225
27511
  await lockDownWindowsDirectories([root, agentRoot]);
27226
- const runRoot = join7(agentRoot, input.runToken);
27512
+ const runRoot = join9(agentRoot, input.runToken);
27227
27513
  assertBelow(agentRoot, runRoot);
27228
27514
  try {
27229
- await mkdir4(runRoot, { mode: DIRECTORY_MODE });
27515
+ await mkdir5(runRoot, { mode: DIRECTORY_MODE });
27230
27516
  await chmod2(runRoot, DIRECTORY_MODE);
27231
27517
  const realRunRoot = await realpath3(runRoot);
27232
27518
  assertBelow(agentRoot, realRunRoot);
27233
27519
  const emptyGithubConfigDirectory = await createPrivateDirectory(realRunRoot, "gh-config");
27234
27520
  const emptyGitHooksDirectory = await createPrivateDirectory(realRunRoot, "git-hooks");
27235
27521
  const gitBridgesDirectory = await createPrivateDirectory(realRunRoot, "git-bridges");
27236
- const denySshScript = join7(realRunRoot, "deny-ssh.cjs");
27237
- const runnerWrapperScript = join7(realRunRoot, "runner-wrapper.cjs");
27238
- const systemPromptPath = join7(realRunRoot, "system-prompt.txt");
27239
- const mcpConfigPath = join7(realRunRoot, "mcp.json");
27522
+ const denySshScript = join9(realRunRoot, "deny-ssh.cjs");
27523
+ const runnerWrapperScript = join9(realRunRoot, "runner-wrapper.cjs");
27524
+ const systemPromptPath = join9(realRunRoot, "system-prompt.txt");
27525
+ const mcpConfigPath = join9(realRunRoot, "mcp.json");
27240
27526
  await writePrivateFile(denySshScript, "process.exitCode = 127;");
27241
27527
  await writePrivateFile(runnerWrapperScript, RUNNER_GUARDIAN);
27242
27528
  return {
@@ -27258,9 +27544,9 @@ async function createRunArtifacts(input) {
27258
27544
  },
27259
27545
  async writePrivateDataFile(name, content) {
27260
27546
  requireSafeSegment(name, "private file name");
27261
- const path = join7(realRunRoot, name);
27547
+ const path = join9(realRunRoot, name);
27262
27548
  assertBelow(realRunRoot, path);
27263
- await writeFile2(path, content, { flag: "wx", mode: FILE_MODE });
27549
+ await writeFile3(path, content, { flag: "wx", mode: FILE_MODE });
27264
27550
  await chmod2(path, FILE_MODE);
27265
27551
  return path;
27266
27552
  },
@@ -27289,7 +27575,7 @@ async function sweepOrphanedRunArtifacts(root) {
27289
27575
  const absolute = resolve4(root);
27290
27576
  let realProfile;
27291
27577
  if (process.platform === "win32") {
27292
- const profile = resolve4(homedir2());
27578
+ const profile = resolve4(homedir3());
27293
27579
  assertWindowsProfileBoundary(profile, absolute);
27294
27580
  await rejectWindowsSymlinkAncestors(profile, absolute);
27295
27581
  realProfile = await realpath3(profile);
@@ -27308,20 +27594,20 @@ async function sweepOrphanedRunArtifacts(root) {
27308
27594
  let removed = 0;
27309
27595
  for (const agent of agents) {
27310
27596
  if (!SAFE_SEGMENT.test(agent.name) || !agent.isDirectory() || agent.isSymbolicLink()) continue;
27311
- const agentPath = join7(realRoot, agent.name);
27597
+ const agentPath = join9(realRoot, agent.name);
27312
27598
  const runs = await readdir3(agentPath, { withFileTypes: true });
27313
27599
  for (const run3 of runs) {
27314
27600
  if (!SAFE_SEGMENT.test(run3.name) || !run3.isDirectory() || run3.isSymbolicLink()) continue;
27315
- const runPath = join7(agentPath, run3.name);
27601
+ const runPath = join9(agentPath, run3.name);
27316
27602
  assertBelow(agentPath, runPath);
27317
- await rm4(runPath, { recursive: true, force: true });
27603
+ await rm5(runPath, { recursive: true, force: true });
27318
27604
  removed++;
27319
27605
  }
27320
27606
  }
27321
27607
  return removed;
27322
27608
  }
27323
27609
  function defaultRunRegistryRoot() {
27324
- return join7(homedir2(), ".zixt", "run-registry");
27610
+ return join9(homedir3(), ".zixt", "run-registry");
27325
27611
  }
27326
27612
  async function terminateRecordedRunProcesses(registryRoot = defaultRunRegistryRoot(), terminate = terminateRecordedProcessTree) {
27327
27613
  const entries = await readRecordedRunAssignmentEntriesStrict(registryRoot);
@@ -27347,23 +27633,23 @@ async function syncRunRegistryDirectory(path) {
27347
27633
  }
27348
27634
  }
27349
27635
  async function ensureDurableRunRegistryRoot(registryRoot, syncDirectory8) {
27350
- const firstCreated = await mkdir4(registryRoot, { recursive: true, mode: DIRECTORY_MODE });
27636
+ const firstCreated = await mkdir5(registryRoot, { recursive: true, mode: DIRECTORY_MODE });
27351
27637
  if (firstCreated && process.platform !== "win32") {
27352
27638
  const first = resolve4(firstCreated);
27353
27639
  const target = resolve4(registryRoot);
27354
- await syncDirectory8(dirname3(first));
27640
+ await syncDirectory8(dirname4(first));
27355
27641
  let current = first;
27356
27642
  for (const part of relative3(first, target).split(sep3).filter(Boolean)) {
27357
27643
  await syncDirectory8(current);
27358
- current = join7(current, part);
27644
+ current = join9(current, part);
27359
27645
  }
27360
27646
  }
27361
27647
  await chmod2(registryRoot, DIRECTORY_MODE);
27362
27648
  }
27363
27649
  async function recordRunAssignment(runToken, record2, registryRoot = defaultRunRegistryRoot(), options = {}) {
27364
27650
  if (!SAFE_SEGMENT.test(runToken)) return false;
27365
- const destination = join7(registryRoot, `${runToken}.json`);
27366
- const temporary = join7(registryRoot, `.${runToken}.${process.pid}.${Date.now()}.tmp`);
27651
+ const destination = join9(registryRoot, `${runToken}.json`);
27652
+ const temporary = join9(registryRoot, `.${runToken}.${process.pid}.${Date.now()}.tmp`);
27367
27653
  let handle;
27368
27654
  try {
27369
27655
  const syncDirectory8 = options.syncDirectory ?? syncRunRegistryDirectory;
@@ -27383,7 +27669,7 @@ async function recordRunAssignment(runToken, record2, registryRoot = defaultRunR
27383
27669
  } finally {
27384
27670
  await handle?.close().catch(() => {
27385
27671
  });
27386
- await rm4(temporary, { force: true }).catch(() => {
27672
+ await rm5(temporary, { force: true }).catch(() => {
27387
27673
  });
27388
27674
  }
27389
27675
  }
@@ -27395,7 +27681,7 @@ async function forgetRunAssignment(runToken, registryRoot = defaultRunRegistryRo
27395
27681
  if (retainingAssignments) return;
27396
27682
  if (!SAFE_SEGMENT.test(runToken)) return;
27397
27683
  try {
27398
- await rm4(join7(registryRoot, `${runToken}.json`), { force: true });
27684
+ await rm5(join9(registryRoot, `${runToken}.json`), { force: true });
27399
27685
  } catch {
27400
27686
  }
27401
27687
  }
@@ -27440,7 +27726,7 @@ async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistr
27440
27726
  if (!SAFE_SEGMENT.test(runToken)) continue;
27441
27727
  let text;
27442
27728
  try {
27443
- text = await readFile6(join7(registryRoot, entry.name), "utf8");
27729
+ text = await readFile6(join9(registryRoot, entry.name), "utf8");
27444
27730
  } catch {
27445
27731
  continue;
27446
27732
  }
@@ -27476,7 +27762,7 @@ async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunR
27476
27762
  }
27477
27763
  let text;
27478
27764
  try {
27479
- text = await readFile6(join7(registryRoot, entry.name), "utf8");
27765
+ text = await readFile6(join9(registryRoot, entry.name), "utf8");
27480
27766
  } catch {
27481
27767
  throw new Error("committed run registry witness could not be read");
27482
27768
  }
@@ -27493,13 +27779,13 @@ async function forgetAcknowledgedRunAssignments(assignments, registryRoot = defa
27493
27779
  );
27494
27780
  const entries = await readRecordedRunAssignmentEntries(registryRoot);
27495
27781
  await Promise.all(
27496
- entries.filter(({ record: record2 }) => acknowledged.has(`${record2.taskId}:${record2.epoch}`)).map(({ runToken }) => rm4(join7(registryRoot, `${runToken}.json`), { force: true }))
27782
+ entries.filter(({ record: record2 }) => acknowledged.has(`${record2.taskId}:${record2.epoch}`)).map(({ runToken }) => rm5(join9(registryRoot, `${runToken}.json`), { force: true }))
27497
27783
  );
27498
27784
  }
27499
27785
  async function forgetSupersededRunAssignments(taskId, epoch, registryRoot = defaultRunRegistryRoot()) {
27500
27786
  const entries = await readRecordedRunAssignmentEntries(registryRoot);
27501
27787
  await Promise.all(
27502
- entries.filter(({ record: record2 }) => record2.taskId === taskId && record2.epoch < epoch).map(({ runToken }) => rm4(join7(registryRoot, `${runToken}.json`), { force: true }))
27788
+ entries.filter(({ record: record2 }) => record2.taskId === taskId && record2.epoch < epoch).map(({ runToken }) => rm5(join9(registryRoot, `${runToken}.json`), { force: true }))
27503
27789
  );
27504
27790
  }
27505
27791
 
@@ -27525,7 +27811,7 @@ function streakBackoffMs(streak) {
27525
27811
  var RELEASE_PROBATION_MS = 5 * 6e4;
27526
27812
  var FAST_UPDATE_EXIT_MS = 1e4;
27527
27813
  var STOP_GRACE_MS = 3e4;
27528
- var INSTALL_TIMEOUT_MS = 5 * 6e4;
27814
+ var INSTALL_TIMEOUT_MS2 = 5 * 6e4;
27529
27815
  var WORKER_WATCHDOG_CHECK_MS = 1e3;
27530
27816
  var WORKER_WATCHDOG_TIMEOUT_MS = 15e3;
27531
27817
  var WORKER_WATCHDOG_STARTUP_MS = 6e4;
@@ -27567,39 +27853,16 @@ function captureWorkerStderr(child) {
27567
27853
  return () => (partial2 ? [...lines, partial2] : [...lines]).slice(-WORKER_STDERR_TAIL_LINES);
27568
27854
  }
27569
27855
  function versionsRoot() {
27570
- return process.env.ZIXT_HOST_VERSIONS_DIR ?? join8(homedir3(), ".zixt", "host-versions");
27571
- }
27572
- function npmCommand(platform = process.platform) {
27573
- return platform === "win32" ? "npm.cmd" : "npm";
27574
- }
27575
- async function resolveInstallerCommand(options = {}) {
27576
- const platform = options.platform ?? process.platform;
27577
- const command = npmCommand(platform);
27578
- if (platform !== "win32") return command;
27579
- const execPath = options.execPath ?? process.execPath;
27580
- const resolution = {
27581
- platform,
27582
- ...options.searchPath !== void 0 ? { searchPath: options.searchPath } : {}
27583
- };
27584
- return (
27585
- // npm ships beside the `node` running this process, and that copy is the
27586
- // one matching it. A per-user Scheduled Task may carry no npm on PATH.
27587
- await resolveTrustedCliCommand(join8(dirname4(execPath), command), resolution) ?? await resolveTrustedCliCommand(command, resolution) ?? // Nothing resolved: keep the previous behaviour, so a Machine without npm
27588
- // fails one install rather than changing how failure is handled.
27589
- command
27590
- );
27591
- }
27592
- function windowsInstallerCommandLine(command, args) {
27593
- return [command, ...args].map(quoteForCmd).join(" ");
27856
+ return process.env.ZIXT_HOST_VERSIONS_DIR ?? join10(homedir4(), ".zixt", "host-versions");
27594
27857
  }
27595
27858
  function installedReleaseEntry(version2, root = versionsRoot()) {
27596
- return join8(root, version2, "node_modules", PACKAGE_NAME, "dist", "index.js");
27859
+ return join10(root, version2, "node_modules", PACKAGE_NAME, "dist", "index.js");
27597
27860
  }
27598
27861
  function releaseEntryAtPrefix(prefix) {
27599
- return join8(prefix, "node_modules", PACKAGE_NAME, "dist", "index.js");
27862
+ return join10(prefix, "node_modules", PACKAGE_NAME, "dist", "index.js");
27600
27863
  }
27601
27864
  function releaseManifestAtPrefix(prefix) {
27602
- return join8(prefix, "node_modules", PACKAGE_NAME, "package.json");
27865
+ return join10(prefix, "node_modules", PACKAGE_NAME, "package.json");
27603
27866
  }
27604
27867
  async function validReleaseAtPrefix(prefix, version2) {
27605
27868
  try {
@@ -27624,9 +27887,9 @@ async function syncDirectory3(path) {
27624
27887
  }
27625
27888
  }
27626
27889
  function installedReleaseVersion(entry, root = versionsRoot()) {
27627
- if (!isAbsolute9(entry)) return null;
27890
+ if (!isAbsolute10(entry)) return null;
27628
27891
  const relativeEntry = relative4(resolve5(root), resolve5(entry));
27629
- if (!relativeEntry || relativeEntry.startsWith(`..${sep4}`) || isAbsolute9(relativeEntry)) {
27892
+ if (!relativeEntry || relativeEntry.startsWith(`..${sep4}`) || isAbsolute10(relativeEntry)) {
27630
27893
  return null;
27631
27894
  }
27632
27895
  const version2 = relativeEntry.split(sep4)[0];
@@ -27634,10 +27897,10 @@ function installedReleaseVersion(entry, root = versionsRoot()) {
27634
27897
  return resolve5(entry) === resolve5(installedReleaseEntry(version2, root)) ? version2 : null;
27635
27898
  }
27636
27899
  function currentReleaseEntry(root = versionsRoot(), platform = process.platform) {
27637
- return join8(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
27900
+ return join10(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
27638
27901
  }
27639
27902
  function windowsReleasePointer(root = versionsRoot()) {
27640
- return join8(root, WINDOWS_RELEASE_POINTER);
27903
+ return join10(root, WINDOWS_RELEASE_POINTER);
27641
27904
  }
27642
27905
  var WINDOWS_STABLE_LAUNCHER = `${WINDOWS_LAUNCHER_MARKER}
27643
27906
  'use strict';
@@ -27672,9 +27935,9 @@ child.once('error', () => process.exit(1));
27672
27935
  child.once('exit', (code) => process.exit(code == null ? 1 : code));
27673
27936
  `;
27674
27937
  async function replaceDurableFile(path, contents, sync = syncDirectory3) {
27675
- const parent = dirname4(path);
27676
- await mkdir5(parent, { recursive: true, mode: 448 });
27677
- const temporary = join8(parent, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
27938
+ const parent = dirname5(path);
27939
+ await mkdir6(parent, { recursive: true, mode: 448 });
27940
+ const temporary = join10(parent, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
27678
27941
  const handle = await open4(temporary, "wx", 384);
27679
27942
  try {
27680
27943
  await handle.writeFile(contents, "utf8");
@@ -27684,7 +27947,7 @@ async function replaceDurableFile(path, contents, sync = syncDirectory3) {
27684
27947
  await sync(parent);
27685
27948
  } catch (error52) {
27686
27949
  await handle.close().catch(() => void 0);
27687
- await rm5(temporary, { force: true }).catch(() => void 0);
27950
+ await rm6(temporary, { force: true }).catch(() => void 0);
27688
27951
  throw error52;
27689
27952
  }
27690
27953
  }
@@ -27694,7 +27957,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
27694
27957
  }
27695
27958
  await access2(entry);
27696
27959
  if (platform === "win32") {
27697
- await mkdir5(root, { recursive: true, mode: 448 });
27960
+ await mkdir6(root, { recursive: true, mode: 448 });
27698
27961
  const launcher = currentReleaseEntry(root, platform);
27699
27962
  const existingLauncher = await lstat5(launcher).catch((error52) => {
27700
27963
  if (error52.code === "ENOENT") return null;
@@ -27743,7 +28006,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
27743
28006
  return launcher;
27744
28007
  }
27745
28008
  if (platform !== "linux" && platform !== "darwin") return entry;
27746
- await mkdir5(root, { recursive: true, mode: 448 });
28009
+ await mkdir6(root, { recursive: true, mode: 448 });
27747
28010
  const current = currentReleaseEntry(root, platform);
27748
28011
  const existing = await lstat5(current).catch((error52) => {
27749
28012
  if (error52.code === "ENOENT") return null;
@@ -27752,13 +28015,13 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
27752
28015
  if (existing && !existing.isSymbolicLink()) {
27753
28016
  throw new Error("the Zixt Host current-release entry is not a symbolic link");
27754
28017
  }
27755
- const temporary = join8(root, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
28018
+ const temporary = join10(root, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
27756
28019
  try {
27757
28020
  await symlink(entry, temporary, "file");
27758
28021
  await rename3(temporary, current);
27759
28022
  await sync(root);
27760
28023
  } catch (error52) {
27761
- await rm5(temporary, { force: true }).catch(() => void 0);
28024
+ await rm6(temporary, { force: true }).catch(() => void 0);
27762
28025
  throw error52;
27763
28026
  }
27764
28027
  return current;
@@ -27779,43 +28042,11 @@ async function activatedReleaseVersion(root = versionsRoot(), platform = process
27779
28042
  try {
27780
28043
  const current = currentReleaseEntry(root, platform);
27781
28044
  const target = await readlink(current);
27782
- return installedReleaseVersion(resolve5(dirname4(current), target), root);
28045
+ return installedReleaseVersion(resolve5(dirname5(current), target), root);
27783
28046
  } catch {
27784
28047
  return null;
27785
28048
  }
27786
28049
  }
27787
- function sanitizedInstallerEnv(inherited) {
27788
- const allowed = /* @__PURE__ */ new Set([
27789
- "PATH",
27790
- "HOME",
27791
- "USERPROFILE",
27792
- "SYSTEMROOT",
27793
- "WINDIR",
27794
- "TEMP",
27795
- "TMP",
27796
- "TMPDIR",
27797
- "LOCALAPPDATA",
27798
- "APPDATA",
27799
- "XDG_CONFIG_HOME",
27800
- "XDG_CACHE_HOME",
27801
- "HTTP_PROXY",
27802
- "HTTPS_PROXY",
27803
- "NO_PROXY",
27804
- "ALL_PROXY",
27805
- "NODE_EXTRA_CA_CERTS",
27806
- "SSL_CERT_FILE",
27807
- "SSL_CERT_DIR",
27808
- "NPM_CONFIG_REGISTRY",
27809
- "NPM_CONFIG_CACHE",
27810
- "NPM_CONFIG_USERCONFIG",
27811
- "NPM_CONFIG_STRICT_SSL"
27812
- ]);
27813
- return Object.fromEntries(
27814
- Object.entries(inherited).filter(
27815
- ([name, value]) => value !== void 0 && allowed.has(name.toUpperCase())
27816
- )
27817
- );
27818
- }
27819
28050
  var WINDOWS_INSTALLER_GUARDIAN = String.raw`
27820
28051
  const { spawn } = require('node:child_process');
27821
28052
  const nonce = process.argv[1];
@@ -27860,7 +28091,13 @@ process.stdin.on('data', (chunk) => {
27860
28091
  const target = spawn(config.commandLine, {
27861
28092
  cwd: config.cwd,
27862
28093
  env: process.env,
27863
- stdio: 'inherit',
28094
+ // Never share this guardian's stdin with npm. The guardian keeps an
28095
+ // active read pending on that pipe (the config protocol above), and a
28096
+ // Windows child whose inherited stdin pipe has a concurrent reader wedges
28097
+ // inside Node startup until the reader dies - npm sat at zero CPU for the
28098
+ // whole install timeout on a real Machine (live, 2026-08-18). An
28099
+ // unattended install may never depend on stdin anyway.
28100
+ stdio: ['ignore', 'inherit', 'inherit'],
27864
28101
  windowsHide: true,
27865
28102
  // cmd.exe has to resolve npm.cmd, so the shell stays - but the whole line
27866
28103
  // arrives pre-quoted as one string. Node's (command, args, shell) shape is
@@ -27893,15 +28130,15 @@ async function installRelease(version2, options = {}) {
27893
28130
  }
27894
28131
  const platform = options.platform ?? process.platform;
27895
28132
  const root = options.root ?? versionsRoot();
27896
- const prefix = join8(root, version2);
28133
+ const prefix = join10(root, version2);
27897
28134
  const entry = installedReleaseEntry(version2, root);
27898
28135
  if (await validReleaseAtPrefix(prefix, version2)) return entry;
27899
28136
  if (options.signal?.aborted)
27900
28137
  return fail("cancelled", "this Host was stopping before npm started");
27901
28138
  const installerCommand = options.installerCommand ?? await resolveInstallerCommand({ platform });
27902
- await mkdir5(root, { recursive: true, mode: 448 });
27903
- const staging = join8(root, `.install-${version2}-${process.pid}-${crypto.randomUUID()}`);
27904
- const quarantine = join8(root, `.invalid-${version2}-${process.pid}-${crypto.randomUUID()}`);
28139
+ await mkdir6(root, { recursive: true, mode: 448 });
28140
+ const staging = join10(root, `.install-${version2}-${process.pid}-${crypto.randomUUID()}`);
28141
+ const quarantine = join10(root, `.invalid-${version2}-${process.pid}-${crypto.randomUUID()}`);
27905
28142
  const usesWindowsInstallerGuardian = platform === "win32" && options.spawnInstaller === void 0;
27906
28143
  const installerGateNonce = usesWindowsInstallerGuardian ? crypto.randomUUID() : null;
27907
28144
  const installerArguments = (installPrefix, installVersion) => [
@@ -27916,15 +28153,18 @@ async function installRelease(version2, options = {}) {
27916
28153
  const spawnInstaller = options.spawnInstaller ?? ((installPrefix, installVersion) => {
27917
28154
  const installerArgs = installerArguments(installPrefix, installVersion);
27918
28155
  if (usesWindowsInstallerGuardian) {
27919
- return spawn5(process.execPath, ["-e", WINDOWS_INSTALLER_GUARDIAN, installerGateNonce], {
28156
+ return spawn6(process.execPath, ["-e", WINDOWS_INSTALLER_GUARDIAN, installerGateNonce], {
27920
28157
  cwd: root,
27921
28158
  stdio: ["pipe", "inherit", "inherit", "ipc"],
27922
28159
  env: sanitizedInstallerEnv(process.env),
27923
28160
  windowsHide: true
27924
28161
  });
27925
28162
  }
27926
- return spawn5(installerCommand, installerArgs, {
27927
- stdio: "inherit",
28163
+ return spawn6(installerCommand, installerArgs, {
28164
+ // stdin stays closed for the same reason as the Windows guardian
28165
+ // above: this worker actively reads its own stdin (the supervisor's
28166
+ // stop pipe), and an unattended npm must not share or depend on it.
28167
+ stdio: ["ignore", "inherit", "inherit"],
27928
28168
  env: sanitizedInstallerEnv(process.env),
27929
28169
  detached: true
27930
28170
  });
@@ -27933,7 +28173,7 @@ async function installRelease(version2, options = {}) {
27933
28173
  try {
27934
28174
  child = spawnInstaller(staging, version2);
27935
28175
  } catch (error52) {
27936
- await rm5(staging, { recursive: true, force: true }).catch(() => void 0);
28176
+ await rm6(staging, { recursive: true, force: true }).catch(() => void 0);
27937
28177
  return fail(
27938
28178
  "installer_unavailable",
27939
28179
  `${installerCommand} could not be started (${error52 instanceof Error ? error52.message : "unknown error"})`
@@ -27959,7 +28199,7 @@ async function installRelease(version2, options = {}) {
27959
28199
  installerContainmentSetupError = error52;
27960
28200
  return null;
27961
28201
  }) : Promise.resolve(null);
27962
- const timeoutMs = options.timeoutMs ?? INSTALL_TIMEOUT_MS;
28202
+ const timeoutMs = options.timeoutMs ?? INSTALL_TIMEOUT_MS2;
27963
28203
  const outcome = { code: null, signal: null, timedOut: false, spawnError: null };
27964
28204
  const installed = await new Promise((resolve18, reject3) => {
27965
28205
  let finished = false;
@@ -28130,8 +28370,8 @@ async function installRelease(version2, options = {}) {
28130
28370
  `${prefix} is not a runnable ${PACKAGE_NAME}@${version2} after installing`
28131
28371
  );
28132
28372
  } finally {
28133
- await rm5(staging, { recursive: true, force: true }).catch(() => void 0);
28134
- await rm5(quarantine, { recursive: true, force: true }).catch(() => void 0);
28373
+ await rm6(staging, { recursive: true, force: true }).catch(() => void 0);
28374
+ await rm6(quarantine, { recursive: true, force: true }).catch(() => void 0);
28135
28375
  }
28136
28376
  }
28137
28377
  async function pruneInstalledVersions(keep, root = versionsRoot()) {
@@ -28146,10 +28386,10 @@ async function pruneInstalledVersions(keep, root = versionsRoot()) {
28146
28386
  const removed = [];
28147
28387
  for (const name of entries) {
28148
28388
  if (protectedDirs.has(name) || !VERSION_DIR.test(name)) continue;
28149
- const dir = join8(root, name);
28389
+ const dir = join10(root, name);
28150
28390
  if (running && running.startsWith(`${dir}${sep4}`)) continue;
28151
28391
  try {
28152
- await rm5(dir, { recursive: true, force: true });
28392
+ await rm6(dir, { recursive: true, force: true });
28153
28393
  removed.push(name);
28154
28394
  } catch {
28155
28395
  }
@@ -28160,7 +28400,7 @@ function durableState(phase, candidateVersion, fallbackVersion) {
28160
28400
  return { schema: 1, phase, candidateVersion, fallbackVersion };
28161
28401
  }
28162
28402
  async function validInstalledRelease(version2, root = versionsRoot()) {
28163
- return validReleaseAtPrefix(join8(root, version2), version2);
28403
+ return validReleaseAtPrefix(join10(root, version2), version2);
28164
28404
  }
28165
28405
  async function recoverDurableReleaseState(store, runningVersion, activeBootVersion, activate, log2) {
28166
28406
  const state = await store.load();
@@ -28278,7 +28518,7 @@ function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityO
28278
28518
  delete env.ZIXT_HOST_REJECT_VERSION;
28279
28519
  if (command.rejectedVersion) env.ZIXT_HOST_REJECT_VERSION = command.rejectedVersion;
28280
28520
  const entry = compatibilityProxy ? process.argv[1] ?? "" : command.entry ?? process.argv[1] ?? "";
28281
- const child = spawn5(process.execPath, [entry, ...argv, ...ownership?.argv ?? []], {
28521
+ const child = spawn6(process.execPath, [entry, ...argv, ...ownership?.argv ?? []], {
28282
28522
  // stdin is a pipe this process owns: closing it is how the worker is
28283
28523
  // asked to stop, which works identically on Windows, where there is no
28284
28524
  // real SIGINT to send. stdout stays the person's terminal; stderr is teed
@@ -28286,7 +28526,7 @@ function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityO
28286
28526
  stdio: watchdog ? ["pipe", "inherit", "pipe", "ipc"] : ["pipe", "inherit", "pipe"],
28287
28527
  env,
28288
28528
  ...containmentGateNonce ? {
28289
- cwd: ownership?.ownershipFile ? dirname4(ownership.ownershipFile) : dirname4(entry)
28529
+ cwd: ownership?.ownershipFile ? dirname5(ownership.ownershipFile) : dirname5(entry)
28290
28530
  } : {},
28291
28531
  // The launch nonce is not a user-facing CLI argument. Keeping it as
28292
28532
  // argv[0] gives the stable launcher an exact cross-platform process
@@ -28315,7 +28555,7 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
28315
28555
  const ownership = consumeWorkerOwnershipArguments(argv, env);
28316
28556
  const nonce = env[WORKER_WATCHDOG_NONCE_ENV];
28317
28557
  const ownershipFile = env[WORKER_OWNERSHIP_FILE_ENV];
28318
- if (typeof target !== "string" || !isAbsolute9(target) || typeof nonce !== "string" || typeof ownershipFile !== "string" || !ownership.requested || !ownership.valid) {
28558
+ if (typeof target !== "string" || !isAbsolute10(target) || typeof nonce !== "string" || typeof ownershipFile !== "string" || !ownership.requested || !ownership.valid) {
28319
28559
  return 1;
28320
28560
  }
28321
28561
  if (!recordWorkerOwnership(ownershipFile, nonce)) return 1;
@@ -28330,7 +28570,9 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
28330
28570
  delete workerEnv[WORKER_OWNERSHIP_FILE_ENV];
28331
28571
  delete workerEnv[LAUNCHER_OWNERSHIP_DIR_ENV];
28332
28572
  delete workerEnv[SUPERVISOR_OWNERSHIP_FILE_ENV];
28333
- const child = spawn5(process.execPath, [target, ...ownership.argv], {
28573
+ delete workerEnv[WINDOWS_CONTAINMENT_GATE_ENV];
28574
+ delete workerEnv[WINDOWS_POST_CONTAINMENT_CWD_ENV];
28575
+ const child = spawn6(process.execPath, [target, ...ownership.argv], {
28334
28576
  stdio: ["pipe", "inherit", "inherit"],
28335
28577
  env: workerEnv,
28336
28578
  // The proxy is already a detached group/session leader on POSIX. The old
@@ -28386,7 +28628,7 @@ async function launchHostSupervisor(options = {}) {
28386
28628
  const generationNonce = ownershipDirectory ? basename3(ownershipDirectory) : null;
28387
28629
  if (ownershipDirectory && generationNonce) {
28388
28630
  env[LAUNCHER_OWNERSHIP_DIR_ENV] = ownershipDirectory;
28389
- env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join8(ownershipDirectory, `${generationNonce}.json`);
28631
+ env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join10(ownershipDirectory, `${generationNonce}.json`);
28390
28632
  } else {
28391
28633
  delete env[LAUNCHER_OWNERSHIP_DIR_ENV];
28392
28634
  }
@@ -28394,10 +28636,10 @@ async function launchHostSupervisor(options = {}) {
28394
28636
  if (!containmentGateNonce) delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
28395
28637
  if (version2) env[SUPERVISOR_VERSION_ENV] = version2;
28396
28638
  else delete env[SUPERVISOR_VERSION_ENV];
28397
- const child2 = spawn5(process.execPath, [supervisorEntry, ...argv], {
28639
+ const child2 = spawn6(process.execPath, [supervisorEntry, ...argv], {
28398
28640
  stdio: ["pipe", "inherit", "inherit"],
28399
28641
  env,
28400
- ...containmentGateNonce ? { cwd: ownershipDirectory ?? dirname4(supervisorEntry) } : {},
28642
+ ...containmentGateNonce ? { cwd: ownershipDirectory ?? dirname5(supervisorEntry) } : {},
28401
28643
  detached: platform !== "win32",
28402
28644
  // The new launcher can discover the durable PID record and still has
28403
28645
  // to bind it to this exact process before signalling a recycled PID.
@@ -28409,8 +28651,8 @@ async function launchHostSupervisor(options = {}) {
28409
28651
  });
28410
28652
  const customDelay = options.delay;
28411
28653
  const ownsWorkerBoundary = options.spawnSupervisor === void 0 || options.ownershipRoot !== void 0;
28412
- const ownershipRoot = options.ownershipRoot ?? join8(versionsRoot(), "launcher-ownership");
28413
- const runRegistryRoot2 = options.runRegistryRoot ?? (options.ownershipRoot ? join8(dirname4(options.ownershipRoot), "run-registry") : defaultRunRegistryRoot());
28654
+ const ownershipRoot = options.ownershipRoot ?? join10(versionsRoot(), "launcher-ownership");
28655
+ const runRegistryRoot2 = options.runRegistryRoot ?? (options.ownershipRoot ? join10(dirname5(options.ownershipRoot), "run-registry") : defaultRunRegistryRoot());
28414
28656
  const terminateRecordedOwnership = options.terminateRecordedOwnership ?? terminateRecordedProcessTree;
28415
28657
  const createSupervisorContainment = options.createSupervisorContainment ?? (platform === "win32" && options.spawnSupervisor === void 0 ? async (target, identityNonce, signal) => {
28416
28658
  if (!target.pid) throw new Error("supervisor process id is unavailable");
@@ -28519,8 +28761,8 @@ async function launchHostSupervisor(options = {}) {
28519
28761
  let stdinIsPipe = options.parentStdinIsPipe ?? false;
28520
28762
  if (options.parentStdinIsPipe === void 0) {
28521
28763
  try {
28522
- const stat3 = fstatSync(0);
28523
- stdinIsPipe = !stat3.isCharacterDevice() && !stat3.isFile() && !process.stdin.isTTY;
28764
+ const stat4 = fstatSync(0);
28765
+ stdinIsPipe = !stat4.isCharacterDevice() && !stat4.isFile() && !process.stdin.isTTY;
28524
28766
  } catch {
28525
28767
  }
28526
28768
  }
@@ -28677,10 +28919,10 @@ async function superviseHost(options = {}) {
28677
28919
  const log2 = options.log ?? ((message) => console.error(message));
28678
28920
  const signalWorker = options.signalWorker ?? signalWorkerGroup;
28679
28921
  const inheritedOwnershipDirectory = process.env[LAUNCHER_OWNERSHIP_DIR_ENV];
28680
- const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute9(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
28922
+ const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute10(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
28681
28923
  if (productionLifecycle && isSupervisorRole() && launcherOwnershipDirectory) {
28682
28924
  const generationNonce = basename3(launcherOwnershipDirectory);
28683
- const expectedOwnershipFile = join8(launcherOwnershipDirectory, `${generationNonce}.json`);
28925
+ const expectedOwnershipFile = join10(launcherOwnershipDirectory, `${generationNonce}.json`);
28684
28926
  const configuredOwnershipFile = process.env[SUPERVISOR_OWNERSHIP_FILE_ENV];
28685
28927
  if (process.argv0 !== generationNonce || configuredOwnershipFile !== expectedOwnershipFile || !recordWorkerOwnership(expectedOwnershipFile, generationNonce)) {
28686
28928
  log2("Zixt Host: supervisor ownership could not be committed; refusing to start a worker");
@@ -29329,9 +29571,9 @@ function beginWorkerShutdown(options) {
29329
29571
  // src/parent-pipe.ts
29330
29572
  import { fstatSync as fstatSync2 } from "node:fs";
29331
29573
  var END_OF_TEXT = 3;
29332
- function stdinIsParentPipe(stat3 = (fd) => fstatSync2(fd), isTTY = process.stdin.isTTY === true) {
29574
+ function stdinIsParentPipe(stat4 = (fd) => fstatSync2(fd), isTTY = process.stdin.isTTY === true) {
29333
29575
  try {
29334
- const stdin = stat3(0);
29576
+ const stdin = stat4(0);
29335
29577
  return !stdin.isCharacterDevice() && !stdin.isFile() && !isTTY;
29336
29578
  } catch {
29337
29579
  return false;
@@ -29359,14 +29601,14 @@ function watchParentPipe(pipe2, onStop) {
29359
29601
  }
29360
29602
 
29361
29603
  // src/index.ts
29362
- import { homedir as homedir14, hostname as hostname3 } from "node:os";
29604
+ import { homedir as homedir16, hostname as hostname3 } from "node:os";
29363
29605
 
29364
29606
  // src/hardware.ts
29365
29607
  import { existsSync } from "node:fs";
29366
29608
  import { statfs } from "node:fs/promises";
29367
- import { cpus, freemem, homedir as homedir4, totalmem } from "node:os";
29368
- import { dirname as dirname5, resolve as resolve6 } from "node:path";
29369
- async function machineHardware(workRoot = homedir4()) {
29609
+ import { cpus, freemem, homedir as homedir5, totalmem } from "node:os";
29610
+ import { dirname as dirname6, resolve as resolve6 } from "node:path";
29611
+ async function machineHardware(workRoot = homedir5()) {
29370
29612
  return {
29371
29613
  // A container or cgroup can hide processors from this count; it is what
29372
29614
  // this process can see, which is what its Tasks will actually get.
@@ -29394,7 +29636,7 @@ function nearestExistingPath(start) {
29394
29636
  let candidate = resolve6(start);
29395
29637
  for (let depth = 0; depth < 16; depth++) {
29396
29638
  if (existsSync(candidate)) return candidate;
29397
- const parent = dirname5(candidate);
29639
+ const parent = dirname6(candidate);
29398
29640
  if (parent === candidate) return null;
29399
29641
  candidate = parent;
29400
29642
  }
@@ -29588,17 +29830,17 @@ function createDemoBrowserAdapterFactory() {
29588
29830
  }
29589
29831
 
29590
29832
  // src/browser/manager.ts
29591
- import { lstat as lstat6, mkdir as mkdir6, open as open5, opendir, readFile as readFile8, rename as rename4, rm as rm6 } from "node:fs/promises";
29592
- import { homedir as homedir5 } from "node:os";
29593
- import { dirname as dirname6, join as join9, resolve as resolve7 } from "node:path";
29833
+ import { lstat as lstat6, mkdir as mkdir7, open as open5, opendir, readFile as readFile8, rename as rename4, rm as rm7 } from "node:fs/promises";
29834
+ import { homedir as homedir6 } from "node:os";
29835
+ import { dirname as dirname7, join as join11, resolve as resolve7 } from "node:path";
29594
29836
  var SAFE_SEGMENT2 = /^[A-Za-z0-9_-]{1,200}$/;
29595
29837
  var FRAME_MIN_INTERVAL_MS = 100;
29596
29838
  var IDLE_TIMEOUT_MS = 15 * 6e4;
29597
29839
  var BrowserManager = class {
29598
29840
  constructor(opts) {
29599
29841
  this.opts = opts;
29600
- this.profileRoot = opts.profileRoot ?? join9(homedir5(), ".zixt", "browser-profiles");
29601
- this.profileStateRoot = join9(this.profileRoot, ".profile-state");
29842
+ this.profileRoot = opts.profileRoot ?? join11(homedir6(), ".zixt", "browser-profiles");
29843
+ this.profileStateRoot = join11(this.profileRoot, ".profile-state");
29602
29844
  this.viewport = opts.viewport ?? BROWSER_DEFAULT_VIEWPORT;
29603
29845
  this.idleTimeoutMs = opts.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
29604
29846
  this.frameMinIntervalMs = opts.frameMinIntervalMs ?? FRAME_MIN_INTERVAL_MS;
@@ -29695,15 +29937,15 @@ var BrowserManager = class {
29695
29937
  exactChild(root, child) {
29696
29938
  const canonicalRoot = resolve7(root);
29697
29939
  const target = resolve7(canonicalRoot, child);
29698
- if (dirname6(target) !== canonicalRoot) {
29940
+ if (dirname7(target) !== canonicalRoot) {
29699
29941
  throw new Error("browser profile path escaped its owned root");
29700
29942
  }
29701
29943
  return target;
29702
29944
  }
29703
29945
  async ensureOwnedDirectory(path) {
29704
- await mkdir6(path, { recursive: true, mode: 448 });
29705
- const stat3 = await lstat6(path);
29706
- if (!stat3.isDirectory() || stat3.isSymbolicLink()) {
29946
+ await mkdir7(path, { recursive: true, mode: 448 });
29947
+ const stat4 = await lstat6(path);
29948
+ if (!stat4.isDirectory() || stat4.isSymbolicLink()) {
29707
29949
  throw new Error("browser profile root must be an owned directory, not a symbolic link");
29708
29950
  }
29709
29951
  }
@@ -29767,7 +30009,7 @@ var BrowserManager = class {
29767
30009
  await this.syncDirectory(this.profileStateRoot);
29768
30010
  await this.syncDirectory(this.profileRoot);
29769
30011
  } catch (error52) {
29770
- await rm6(temporary, { force: true }).catch(() => {
30012
+ await rm7(temporary, { force: true }).catch(() => {
29771
30013
  });
29772
30014
  throw error52;
29773
30015
  }
@@ -29847,7 +30089,7 @@ var BrowserManager = class {
29847
30089
  } catch (error52) {
29848
30090
  if (error52.code !== "ENOENT") throw error52;
29849
30091
  }
29850
- await mkdir6(profileDir, { recursive: true, mode: 448 });
30092
+ await mkdir7(profileDir, { recursive: true, mode: 448 });
29851
30093
  const adapter = await this.opts.factory.open({
29852
30094
  taskId,
29853
30095
  agentId,
@@ -29935,7 +30177,7 @@ var BrowserManager = class {
29935
30177
  });
29936
30178
  const sessionTaskIds = [...this.sessions.values()].filter((session) => session.agentId === agentId).map((session) => session.taskId);
29937
30179
  for (const taskId of sessionTaskIds) await this.closeLocked(taskId, "stopped");
29938
- await rm6(this.profilePath(agentId), { recursive: true, force: true, maxRetries: 3 });
30180
+ await rm7(this.profilePath(agentId), { recursive: true, force: true, maxRetries: 3 });
29939
30181
  await this.syncDirectory(this.profileRoot);
29940
30182
  });
29941
30183
  }
@@ -30106,13 +30348,13 @@ var BrowserManager = class {
30106
30348
  };
30107
30349
 
30108
30350
  // src/browser/playwright-adapter.ts
30109
- import { spawn as spawn6 } from "node:child_process";
30351
+ import { spawn as spawn7 } from "node:child_process";
30110
30352
  import { access as access3 } from "node:fs/promises";
30111
30353
  import { createRequire } from "node:module";
30112
- import { dirname as dirname7, join as join10 } from "node:path";
30354
+ import { dirname as dirname8, join as join12 } from "node:path";
30113
30355
  var nodeRequire = createRequire(import.meta.url);
30114
30356
  var playwrightCoreManifestPath = nodeRequire.resolve("playwright-core/package.json");
30115
- var playwrightCoreRoot = dirname7(playwrightCoreManifestPath);
30357
+ var playwrightCoreRoot = dirname8(playwrightCoreManifestPath);
30116
30358
  var playwrightCoreVersion = nodeRequire(playwrightCoreManifestPath).version;
30117
30359
  if (typeof playwrightCoreVersion !== "string" || !/^\d+\.\d+\.\d+$/.test(playwrightCoreVersion)) {
30118
30360
  throw new Error("playwright-core package version is invalid");
@@ -30129,12 +30371,15 @@ async function loadPlaywright() {
30129
30371
  return import("playwright-core");
30130
30372
  }
30131
30373
  async function installChromium() {
30132
- const cliPath = join10(playwrightCoreRoot, "cli.js");
30374
+ const cliPath = join12(playwrightCoreRoot, "cli.js");
30133
30375
  await new Promise((resolve18, reject3) => {
30134
- const child = spawn6(process.execPath, [cliPath, "install", "chromium"], {
30376
+ const child = spawn7(process.execPath, [cliPath, "install", "chromium"], {
30135
30377
  env: process.env,
30136
30378
  stdio: ["ignore", "inherit", "inherit"],
30137
- windowsHide: false
30379
+ // A service-managed Host has no console; letting Windows allocate one
30380
+ // here would flash a visible window on the signed-in desktop for the
30381
+ // whole download. Progress still flows through the inherited pipes.
30382
+ windowsHide: true
30138
30383
  });
30139
30384
  let settled = false;
30140
30385
  const finish = (error52) => {
@@ -30760,11 +31005,11 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
30760
31005
  }
30761
31006
 
30762
31007
  // src/runners/cli-runner.ts
30763
- import { spawn as spawn9 } from "node:child_process";
31008
+ import { spawn as spawn10 } from "node:child_process";
30764
31009
  import { randomUUID as randomUUID11 } from "node:crypto";
30765
- import { lstat as lstat11, mkdir as mkdir11, realpath as realpath8 } from "node:fs/promises";
30766
- import { homedir as homedir6 } from "node:os";
30767
- import { dirname as dirname9, isAbsolute as isAbsolute15, join as join16, resolve as resolve10 } from "node:path";
31010
+ import { lstat as lstat11, mkdir as mkdir12, realpath as realpath8 } from "node:fs/promises";
31011
+ import { homedir as homedir7 } from "node:os";
31012
+ import { dirname as dirname10, isAbsolute as isAbsolute16, join as join18, resolve as resolve10 } from "node:path";
30768
31013
 
30769
31014
  // src/tool-packs/browser/authentication-wall.ts
30770
31015
  var AUTH_PATH_SEGMENT = /(?:^|\/)(?:log[-_]?in|sign[-_]?in|sso|saml|auth|authorize|authenticate|oauth2?|session\/new|checkpoint)(?:\/|$)/i;
@@ -33582,16 +33827,16 @@ function createGithubPushOrchestrator(input) {
33582
33827
  }
33583
33828
 
33584
33829
  // src/tool-packs/github/git-bridge.ts
33585
- import { spawn as spawn7 } from "node:child_process";
33830
+ import { spawn as spawn8 } from "node:child_process";
33586
33831
  import { randomUUID as randomUUID8 } from "node:crypto";
33587
- import { chmod as chmod4, lstat as lstat8, mkdir as mkdir7, realpath as realpath5, rm as rm7 } from "node:fs/promises";
33588
- import { dirname as dirname8, isAbsolute as isAbsolute11, join as join12, relative as relative6 } from "node:path";
33832
+ import { chmod as chmod4, lstat as lstat8, mkdir as mkdir8, realpath as realpath5, rm as rm8 } from "node:fs/promises";
33833
+ import { dirname as dirname9, isAbsolute as isAbsolute12, join as join14, relative as relative6 } from "node:path";
33589
33834
 
33590
33835
  // src/tool-packs/github/git-credential-broker.ts
33591
33836
  import { createServer } from "node:http";
33592
33837
  import { randomBytes, randomUUID as randomUUID7, timingSafeEqual } from "node:crypto";
33593
- import { chmod as chmod3, lstat as lstat7, realpath as realpath4, writeFile as writeFile3 } from "node:fs/promises";
33594
- import { isAbsolute as isAbsolute10, join as join11, relative as relative5 } from "node:path";
33838
+ import { chmod as chmod3, lstat as lstat7, realpath as realpath4, writeFile as writeFile4 } from "node:fs/promises";
33839
+ import { isAbsolute as isAbsolute11, join as join13, relative as relative5 } from "node:path";
33595
33840
  var MAX_REQUEST_BYTES = 16 * 1024;
33596
33841
  var FILE_MODE2 = 384;
33597
33842
  var HELPER_SOURCE = String.raw`'use strict';
@@ -33705,7 +33950,7 @@ async function readBoundedBody2(request) {
33705
33950
  }
33706
33951
  function assertChildPath(parent, child) {
33707
33952
  const path = relative5(parent, child);
33708
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute10(path)) {
33953
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute11(path)) {
33709
33954
  throw new Error("Git credential helper path escaped its private run directory");
33710
33955
  }
33711
33956
  }
@@ -33720,9 +33965,9 @@ async function createGithubGitCredentialBroker(input) {
33720
33965
  throw new Error("Git credential broker requires a private real run directory");
33721
33966
  }
33722
33967
  const runRoot = await realpath4(input.runArtifactsRoot);
33723
- const helperPath = join11(runRoot, `git-credential-${randomUUID7()}.cjs`);
33968
+ const helperPath = join13(runRoot, `git-credential-${randomUUID7()}.cjs`);
33724
33969
  assertChildPath(runRoot, helperPath);
33725
- await writeFile3(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
33970
+ await writeFile4(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
33726
33971
  await chmod3(helperPath, FILE_MODE2);
33727
33972
  const capability2 = randomBytes(32).toString("base64url");
33728
33973
  const expectedPath = `${input.repositoryFullName}.git`;
@@ -33820,7 +34065,7 @@ ${stderr}`;
33820
34065
  }
33821
34066
  function assertBelow2(parent, child, label) {
33822
34067
  const path = relative6(parent, child);
33823
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute11(path)) {
34068
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
33824
34069
  throw new GithubGitProcessError("invalid_input");
33825
34070
  }
33826
34071
  void label;
@@ -33835,8 +34080,8 @@ async function requireRealDirectory2(path, label) {
33835
34080
  }
33836
34081
  async function validateTokenlessPaths(command) {
33837
34082
  if (command.kind === "clone-from-bridge") {
33838
- if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
33839
- const parent = await requireRealDirectory2(dirname8(command.destination), "clone parent");
34083
+ if (!isAbsolute12(command.destination)) throw new GithubGitProcessError("invalid_input");
34084
+ const parent = await requireRealDirectory2(dirname9(command.destination), "clone parent");
33840
34085
  assertBelow2(parent, command.destination, "clone destination");
33841
34086
  const destination = await lstat8(command.destination).catch((error52) => {
33842
34087
  if (error52.code === "ENOENT") return null;
@@ -33846,7 +34091,7 @@ async function validateTokenlessPaths(command) {
33846
34091
  return;
33847
34092
  }
33848
34093
  if ("repositoryPath" in command) {
33849
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34094
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
33850
34095
  const repositoryPath5 = await requireRealDirectory2(command.repositoryPath, "repository path");
33851
34096
  if (repositoryPath5 !== command.repositoryPath) throw new GithubGitProcessError("invalid_input");
33852
34097
  }
@@ -33926,13 +34171,13 @@ async function runGit(input, args, env) {
33926
34171
  if (input.authoritySignal.aborted || input.cancelledNow()) {
33927
34172
  throw new GithubGitProcessError("cancelled");
33928
34173
  }
33929
- if (!isAbsolute11(input.executablePath)) throw new GithubGitProcessError("invalid_input");
34174
+ if (!isAbsolute12(input.executablePath)) throw new GithubGitProcessError("invalid_input");
33930
34175
  const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
33931
34176
  if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > DEFAULT_TIMEOUT_MS2) {
33932
34177
  throw new GithubGitProcessError("invalid_input");
33933
34178
  }
33934
34179
  return new Promise((resolvePromise, rejectPromise) => {
33935
- const child = spawn7(input.executablePath, [...input.commandPrefixArgs ?? [], ...args], {
34180
+ const child = spawn8(input.executablePath, [...input.commandPrefixArgs ?? [], ...args], {
33936
34181
  cwd: input.trustedCwd,
33937
34182
  env,
33938
34183
  shell: false,
@@ -34032,7 +34277,7 @@ function tokenlessArgs(command) {
34032
34277
  switch (command.kind) {
34033
34278
  case "clone-from-bridge":
34034
34279
  assertRef(command.branch);
34035
- if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
34280
+ if (!isAbsolute12(command.destination)) throw new GithubGitProcessError("invalid_input");
34036
34281
  return [
34037
34282
  "clone",
34038
34283
  "--no-recurse-submodules",
@@ -34044,7 +34289,7 @@ function tokenlessArgs(command) {
34044
34289
  ];
34045
34290
  case "fetch-from-bridge":
34046
34291
  assertFetchRefspecs(command.refspecs);
34047
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34292
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34048
34293
  return [
34049
34294
  "-C",
34050
34295
  command.repositoryPath,
@@ -34056,7 +34301,7 @@ function tokenlessArgs(command) {
34056
34301
  ...command.refspecs
34057
34302
  ];
34058
34303
  case "copy-commit-to-bridge":
34059
- if (!isAbsolute11(command.repositoryPath) || !SHA.test(command.sha)) {
34304
+ if (!isAbsolute12(command.repositoryPath) || !SHA.test(command.sha)) {
34060
34305
  throw new GithubGitProcessError("invalid_input");
34061
34306
  }
34062
34307
  return [
@@ -34068,11 +34313,11 @@ function tokenlessArgs(command) {
34068
34313
  `${command.sha}:refs/zixt/push-source`
34069
34314
  ];
34070
34315
  case "rev-parse":
34071
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34316
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34072
34317
  assertRef(command.ref);
34073
34318
  return ["-C", command.repositoryPath, "rev-parse", "--verify", `${command.ref}^{commit}`];
34074
34319
  case "remote-configure":
34075
- if (!isAbsolute11(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
34320
+ if (!isAbsolute12(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
34076
34321
  throw new GithubGitProcessError("invalid_input");
34077
34322
  }
34078
34323
  return [
@@ -34084,7 +34329,7 @@ function tokenlessArgs(command) {
34084
34329
  `https://github.com/${command.repositoryFullName}.git`
34085
34330
  ];
34086
34331
  case "status":
34087
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34332
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34088
34333
  return [
34089
34334
  "-C",
34090
34335
  command.repositoryPath,
@@ -34114,7 +34359,7 @@ function createGithubGitBridge(input) {
34114
34359
  })();
34115
34360
  const requireBridge = async (value) => {
34116
34361
  const current = await roots();
34117
- if (!isAbsolute11(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
34362
+ if (!isAbsolute12(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
34118
34363
  const real = await requireRealDirectory2(value, "git bridge");
34119
34364
  assertBelow2(current.bridges, real, "git bridge");
34120
34365
  if (real !== value) throw new GithubGitProcessError("invalid_input");
@@ -34124,9 +34369,9 @@ function createGithubGitBridge(input) {
34124
34369
  async createPrivateBridge() {
34125
34370
  if (closed) throw new GithubGitProcessError("cancelled");
34126
34371
  const current = await roots();
34127
- const path = join12(current.bridges, `${randomUUID8()}.git`);
34372
+ const path = join14(current.bridges, `${randomUUID8()}.git`);
34128
34373
  assertBelow2(current.bridges, path, "git bridge");
34129
- await mkdir7(path, { mode: DIRECTORY_MODE2 });
34374
+ await mkdir8(path, { mode: DIRECTORY_MODE2 });
34130
34375
  await chmod4(path, DIRECTORY_MODE2);
34131
34376
  try {
34132
34377
  await runGit(
@@ -34142,16 +34387,16 @@ function createGithubGitBridge(input) {
34142
34387
  );
34143
34388
  const real = await requireRealDirectory2(path, "git bridge");
34144
34389
  assertBelow2(current.bridges, real, "git bridge");
34145
- const hooks = join12(real, "hooks");
34146
- await rm7(hooks, { recursive: true, force: true });
34147
- await mkdir7(hooks, { mode: DIRECTORY_MODE2 });
34390
+ const hooks = join14(real, "hooks");
34391
+ await rm8(hooks, { recursive: true, force: true });
34392
+ await mkdir8(hooks, { mode: DIRECTORY_MODE2 });
34148
34393
  await chmod4(hooks, DIRECTORY_MODE2);
34149
- const config2 = join12(real, "config");
34394
+ const config2 = join14(real, "config");
34150
34395
  await chmod4(config2, 384);
34151
34396
  active.add(real);
34152
34397
  return real;
34153
34398
  } catch (error52) {
34154
- await rm7(path, { recursive: true, force: true }).catch(() => {
34399
+ await rm8(path, { recursive: true, force: true }).catch(() => {
34155
34400
  });
34156
34401
  throw error52;
34157
34402
  }
@@ -34245,7 +34490,7 @@ function createGithubGitBridge(input) {
34245
34490
  },
34246
34491
  async destroyPrivateBridge(path) {
34247
34492
  const bridge = await requireBridge(path);
34248
- await rm7(bridge, { recursive: true, force: true });
34493
+ await rm8(bridge, { recursive: true, force: true });
34249
34494
  active.delete(bridge);
34250
34495
  credentialed2.delete(bridge);
34251
34496
  },
@@ -34253,7 +34498,7 @@ function createGithubGitBridge(input) {
34253
34498
  if (closed) return;
34254
34499
  closed = true;
34255
34500
  const paths = [...active];
34256
- await Promise.all(paths.map((path) => rm7(path, { recursive: true, force: true })));
34501
+ await Promise.all(paths.map((path) => rm8(path, { recursive: true, force: true })));
34257
34502
  active.clear();
34258
34503
  credentialed2.clear();
34259
34504
  }
@@ -34594,8 +34839,8 @@ function createRepositoryTools(runtime) {
34594
34839
 
34595
34840
  // src/tool-packs/github/workspace.ts
34596
34841
  import { randomUUID as randomUUID9 } from "node:crypto";
34597
- import { chmod as chmod5, lstat as lstat9, mkdir as mkdir8, readFile as readFile9, realpath as realpath6, rename as rename5, rm as rm8, writeFile as writeFile4 } from "node:fs/promises";
34598
- import { isAbsolute as isAbsolute12, join as join13, relative as relative7, resolve as resolve8 } from "node:path";
34842
+ import { chmod as chmod5, lstat as lstat9, mkdir as mkdir9, readFile as readFile9, realpath as realpath6, rename as rename5, rm as rm9, writeFile as writeFile5 } from "node:fs/promises";
34843
+ import { isAbsolute as isAbsolute13, join as join15, relative as relative7, resolve as resolve8 } from "node:path";
34599
34844
  var SAFE_LOCAL_ID = /^[A-Za-z0-9_-]{1,200}$/;
34600
34845
  var FULL_NAME2 = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
34601
34846
  var DIRECTORY_MODE3 = 448;
@@ -34613,7 +34858,7 @@ function hasControlCharacter2(value) {
34613
34858
  }
34614
34859
  function assertBelow3(parent, child, label) {
34615
34860
  const path = relative7(parent, child);
34616
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
34861
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute13(path)) {
34617
34862
  throw new Error(`${label} escaped the task workspace`);
34618
34863
  }
34619
34864
  }
@@ -34632,10 +34877,10 @@ async function requireRealDirectory3(path, label) {
34632
34877
  return real;
34633
34878
  }
34634
34879
  async function createOrRequirePrivateDirectory(parent, name, label) {
34635
- const path = join13(parent, name);
34880
+ const path = join15(parent, name);
34636
34881
  assertBelow3(parent, path, label);
34637
34882
  try {
34638
- await mkdir8(path, { mode: DIRECTORY_MODE3 });
34883
+ await mkdir9(path, { mode: DIRECTORY_MODE3 });
34639
34884
  } catch (error52) {
34640
34885
  if (error52.code !== "EEXIST") throw error52;
34641
34886
  }
@@ -34715,8 +34960,8 @@ async function createGithubWorkspaceService(input) {
34715
34960
  if (expectedFullName !== void 0 && repository.fullName !== expectedFullName) {
34716
34961
  throw new Error("GitHub repository name does not match this task grant");
34717
34962
  }
34718
- const destination = join13(repositoriesRoot, parsed.data);
34719
- const metadataPath = join13(metadataRoot, `${parsed.data}.json`);
34963
+ const destination = join15(repositoriesRoot, parsed.data);
34964
+ const metadataPath = join15(metadataRoot, `${parsed.data}.json`);
34720
34965
  if (!await pathExists(destination) || !await pathExists(metadataPath)) {
34721
34966
  throw new Error("GitHub repository workspace has not been prepared");
34722
34967
  }
@@ -34733,14 +34978,14 @@ async function createGithubWorkspaceService(input) {
34733
34978
  return real;
34734
34979
  };
34735
34980
  const cloneRepository = async (clone2) => {
34736
- const destination = join13(repositoriesRoot, clone2.repositoryId);
34737
- const metadataPath = join13(metadataRoot, `${clone2.repositoryId}.json`);
34981
+ const destination = join15(repositoriesRoot, clone2.repositoryId);
34982
+ const metadataPath = join15(metadataRoot, `${clone2.repositoryId}.json`);
34738
34983
  assertBelow3(repositoriesRoot, destination, "repository path");
34739
34984
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
34740
34985
  if (await pathExists(destination) || await pathExists(metadataPath)) {
34741
34986
  throw new Error("GitHub repository workspace already exists or is inconsistent");
34742
34987
  }
34743
- const temporary = join13(repositoriesRoot, `.clone-${randomUUID9()}`);
34988
+ const temporary = join15(repositoriesRoot, `.clone-${randomUUID9()}`);
34744
34989
  assertBelow3(repositoriesRoot, temporary, "temporary clone");
34745
34990
  try {
34746
34991
  await input.git.clone({
@@ -34765,9 +35010,9 @@ async function createGithubWorkspaceService(input) {
34765
35010
  path: destination,
34766
35011
  ...clone2.createIntentId === void 0 ? {} : { createIntentId: clone2.createIntentId }
34767
35012
  };
34768
- const metadataTemporary = join13(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
35013
+ const metadataTemporary = join15(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
34769
35014
  assertBelow3(metadataRoot, metadataTemporary, "temporary repository metadata");
34770
- await writeFile4(metadataTemporary, `${JSON.stringify(metadata)}
35015
+ await writeFile5(metadataTemporary, `${JSON.stringify(metadata)}
34771
35016
  `, {
34772
35017
  flag: "wx",
34773
35018
  mode: FILE_MODE3
@@ -34778,11 +35023,11 @@ async function createGithubWorkspaceService(input) {
34778
35023
  try {
34779
35024
  await rename5(metadataTemporary, metadataPath);
34780
35025
  } catch (error52) {
34781
- await rm8(destination, { recursive: true, force: true });
35026
+ await rm9(destination, { recursive: true, force: true });
34782
35027
  throw error52;
34783
35028
  }
34784
35029
  } finally {
34785
- await rm8(metadataTemporary, { force: true }).catch(() => {
35030
+ await rm9(metadataTemporary, { force: true }).catch(() => {
34786
35031
  });
34787
35032
  }
34788
35033
  const path = await requireRealDirectory3(destination, "GitHub repository");
@@ -34794,14 +35039,14 @@ async function createGithubWorkspaceService(input) {
34794
35039
  headSha
34795
35040
  };
34796
35041
  } finally {
34797
- await rm8(temporary, { recursive: true, force: true }).catch(() => {
35042
+ await rm9(temporary, { recursive: true, force: true }).catch(() => {
34798
35043
  });
34799
35044
  }
34800
35045
  };
34801
35046
  const prepareRepository = async (authority) => {
34802
35047
  const { repository } = authority;
34803
- const destination = join13(repositoriesRoot, repository.repositoryId);
34804
- const metadataPath = join13(metadataRoot, `${repository.repositoryId}.json`);
35048
+ const destination = join15(repositoriesRoot, repository.repositoryId);
35049
+ const metadataPath = join15(metadataRoot, `${repository.repositoryId}.json`);
34805
35050
  assertBelow3(repositoriesRoot, destination, "repository path");
34806
35051
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
34807
35052
  return withWorkspaceLock(destination, async () => {
@@ -34966,7 +35211,7 @@ async function createGithubWorkspaceService(input) {
34966
35211
  throw new Error("GitHub created repository is outside this installation");
34967
35212
  }
34968
35213
  parseGitRef(cloneInput.repository.defaultBranch, "default branch");
34969
- return withWorkspaceLock(join13(repositoriesRoot, repositoryId2), async () => {
35214
+ return withWorkspaceLock(join15(repositoriesRoot, repositoryId2), async () => {
34970
35215
  const prepared = await cloneRepository({
34971
35216
  repositoryId: repositoryId2,
34972
35217
  fullName: cloneInput.repository.fullName,
@@ -37090,8 +37335,8 @@ function createCommsToolPacks(grants, context) {
37090
37335
  }
37091
37336
 
37092
37337
  // src/runners/attachments.ts
37093
- import { mkdir as mkdir9, writeFile as writeFile5 } from "node:fs/promises";
37094
- import { join as join14 } from "node:path";
37338
+ import { mkdir as mkdir10, writeFile as writeFile6 } from "node:fs/promises";
37339
+ import { join as join16 } from "node:path";
37095
37340
  var WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
37096
37341
  function sanitizeAttachmentFileName(name) {
37097
37342
  const base = name.split(/[/\\]/).pop() ?? "";
@@ -37120,10 +37365,10 @@ async function materializeAttachments(task, taskRoot) {
37120
37365
  `attached file "${attachment.name}" arrived incomplete (${bytes.byteLength} of ${attachment.size} bytes)`
37121
37366
  );
37122
37367
  }
37123
- const directory = join14(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
37124
- await mkdir9(directory, { recursive: true });
37125
- const path = join14(directory, sanitizeAttachmentFileName(attachment.name));
37126
- await writeFile5(path, bytes);
37368
+ const directory = join16(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
37369
+ await mkdir10(directory, { recursive: true });
37370
+ const path = join16(directory, sanitizeAttachmentFileName(attachment.name));
37371
+ await writeFile6(path, bytes);
37127
37372
  materialized.push({
37128
37373
  path,
37129
37374
  name: attachment.name,
@@ -38140,7 +38385,7 @@ function createAskUserServer() {
38140
38385
  }
38141
38386
 
38142
38387
  // src/runners/runner-env.ts
38143
- import { delimiter as delimiter2, isAbsolute as isAbsolute13 } from "node:path";
38388
+ import { delimiter as delimiter2, isAbsolute as isAbsolute14 } from "node:path";
38144
38389
  var PROVIDER_AUTHORITY_PREFIXES = ["GH_", "GITHUB_", "GIT_", "SSH_"];
38145
38390
  var HOST_AUTHORITY_PREFIXES = [
38146
38391
  "ZIXT_",
@@ -38199,7 +38444,7 @@ function inheritedValue(env, name) {
38199
38444
  }
38200
38445
  function sanitizeInheritedSearchPath(path) {
38201
38446
  if (!path) return "";
38202
- return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute13(entry)).join(delimiter2);
38447
+ return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute14(entry)).join(delimiter2);
38203
38448
  }
38204
38449
  function buildRunnerEnv(input) {
38205
38450
  const env = {};
@@ -38280,9 +38525,9 @@ function buildRunnerEnv(input) {
38280
38525
  // src/runners/github-shell-auth.ts
38281
38526
  import { execFile } from "node:child_process";
38282
38527
  import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
38283
- import { chmod as chmod6, lstat as lstat10, mkdir as mkdir10, realpath as realpath7, writeFile as writeFile6 } from "node:fs/promises";
38528
+ import { chmod as chmod6, lstat as lstat10, mkdir as mkdir11, realpath as realpath7, writeFile as writeFile7 } from "node:fs/promises";
38284
38529
  import { createServer as createServer3 } from "node:http";
38285
- import { isAbsolute as isAbsolute14, join as join15, relative as relative8 } from "node:path";
38530
+ import { isAbsolute as isAbsolute15, join as join17, relative as relative8 } from "node:path";
38286
38531
  var MAX_REQUEST_BYTES2 = 16 * 1024;
38287
38532
  var DIRECTORY_MODE4 = 448;
38288
38533
  var PRIVATE_FILE_MODE = 384;
@@ -38488,7 +38733,7 @@ function parseGhInvocation(body) {
38488
38733
  }
38489
38734
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
38490
38735
  const { args, cwd } = value;
38491
- if (!Array.isArray(args) || args.length > 256 || args.some((argument) => typeof argument !== "string" || argument.length > 4096) || typeof cwd !== "string" || cwd.length === 0 || cwd.length > 4096 || !isAbsolute14(cwd)) {
38736
+ if (!Array.isArray(args) || args.length > 256 || args.some((argument) => typeof argument !== "string" || argument.length > 4096) || typeof cwd !== "string" || cwd.length === 0 || cwd.length > 4096 || !isAbsolute15(cwd)) {
38492
38737
  return null;
38493
38738
  }
38494
38739
  return { args, cwd };
@@ -38647,7 +38892,7 @@ function activationCredential(grant, now = Date.now()) {
38647
38892
  }
38648
38893
  function assertChildPath2(parent, child) {
38649
38894
  const path = relative8(parent, child);
38650
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute14(path)) {
38895
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute15(path)) {
38651
38896
  throw new Error("GitHub shell helper path escaped its private run directory");
38652
38897
  }
38653
38898
  }
@@ -38658,7 +38903,7 @@ function quoteForPosixShell(value) {
38658
38903
  return quoteForGitShell2(value);
38659
38904
  }
38660
38905
  async function writePrivate(path, content, executable = false) {
38661
- await writeFile6(path, content, {
38906
+ await writeFile7(path, content, {
38662
38907
  flag: "wx",
38663
38908
  mode: executable ? EXECUTABLE_FILE_MODE : PRIVATE_FILE_MODE
38664
38909
  });
@@ -38670,7 +38915,7 @@ async function prepareHelpers(input) {
38670
38915
  throw new Error("GitHub shell authentication requires a private real run directory");
38671
38916
  }
38672
38917
  const runRoot = await realpath7(input.runRoot);
38673
- const helperPath = join15(runRoot, "github-shell-git-credential.cjs");
38918
+ const helperPath = join17(runRoot, "github-shell-git-credential.cjs");
38674
38919
  assertChildPath2(runRoot, helperPath);
38675
38920
  await writePrivate(helperPath, GIT_HELPER_SOURCE);
38676
38921
  if (!input.ghExecutablePath) {
@@ -38681,14 +38926,14 @@ async function prepareHelpers(input) {
38681
38926
  wrapperSourcePath: null
38682
38927
  };
38683
38928
  }
38684
- const shellToolsDirectory = join15(runRoot, "shell-tools");
38929
+ const shellToolsDirectory = join17(runRoot, "shell-tools");
38685
38930
  assertChildPath2(runRoot, shellToolsDirectory);
38686
- await mkdir10(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
38931
+ await mkdir11(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
38687
38932
  await chmod6(shellToolsDirectory, DIRECTORY_MODE4);
38688
- const wrapperSourcePath = join15(runRoot, "github-shell-gh-wrapper.cjs");
38933
+ const wrapperSourcePath = join17(runRoot, "github-shell-gh-wrapper.cjs");
38689
38934
  assertChildPath2(runRoot, wrapperSourcePath);
38690
38935
  await writePrivate(wrapperSourcePath, GH_WRAPPER_SOURCE);
38691
- const wrapperPath = join15(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
38936
+ const wrapperPath = join17(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
38692
38937
  assertChildPath2(runRoot, wrapperPath);
38693
38938
  const launcher = process.platform === "win32" ? `@"${process.execPath.replaceAll('"', '""')}" "${wrapperSourcePath.replaceAll('"', '""')}" %*\r
38694
38939
  ` : `#!/bin/sh
@@ -38911,7 +39156,7 @@ password=${credential.accessToken}
38911
39156
  }
38912
39157
 
38913
39158
  // src/runners/working-context.ts
38914
- import { spawn as spawn8 } from "node:child_process";
39159
+ import { spawn as spawn9 } from "node:child_process";
38915
39160
  import { resolve as resolve9 } from "node:path";
38916
39161
  var COMMAND_TIMEOUT_MS = 5e3;
38917
39162
  var OUTPUT_LIMIT_BYTES = 128 * 1024;
@@ -39042,7 +39287,7 @@ async function stopWorkingContextCommand(child, childExited, options = {}) {
39042
39287
  function run(command, args, cwd, env, signal) {
39043
39288
  if (signal?.aborted) return Promise.resolve(null);
39044
39289
  return new Promise((resolvePromise) => {
39045
- const child = spawn8(command, [...args], {
39290
+ const child = spawn9(command, [...args], {
39046
39291
  cwd,
39047
39292
  env: { ...env, GIT_OPTIONAL_LOCKS: "0" },
39048
39293
  detached: process.platform !== "win32",
@@ -39482,7 +39727,7 @@ async function settlesWithin(promise2, timeoutMs) {
39482
39727
  }
39483
39728
  }
39484
39729
  function defaultRunnerWorkspaceRoot() {
39485
- return join16(homedir6(), ".zixt", "workspaces");
39730
+ return join18(homedir7(), ".zixt", "workspaces");
39486
39731
  }
39487
39732
  function defaultRunnerArtifactRoot() {
39488
39733
  return defaultRunArtifactRoot();
@@ -39531,7 +39776,7 @@ function createCliRunner(adapter, opts = {}) {
39531
39776
  const prefixArgs = opts.commandPrefixArgs ?? [];
39532
39777
  const maxWallTimeMs = opts.maxWallTimeMs;
39533
39778
  const workspaceRoot = opts.workspaceRoot ?? defaultRunnerWorkspaceRoot();
39534
- const artifactRoot = opts.artifactRoot ?? (opts.workspaceRoot === void 0 ? defaultRunnerArtifactRoot() : join16(dirname9(workspaceRoot), "run-artifacts"));
39779
+ const artifactRoot = opts.artifactRoot ?? (opts.workspaceRoot === void 0 ? defaultRunnerArtifactRoot() : join18(dirname10(workspaceRoot), "run-artifacts"));
39535
39780
  const runRegistryRoot2 = opts.runRegistryRoot ?? defaultRunRegistryRoot();
39536
39781
  const createArtifacts = opts.createArtifacts ?? createRunArtifacts;
39537
39782
  const toolPackRegistry2 = opts.toolPackRegistry ?? createDefaultToolPackRegistry();
@@ -39549,7 +39794,7 @@ function createCliRunner(adapter, opts = {}) {
39549
39794
  };
39550
39795
  const askUserServer = createAskUserServer();
39551
39796
  const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
39552
- const windowsComspecCandidate = process.platform === "win32" && windowsRoot ? join16(windowsRoot, "System32", "cmd.exe") : void 0;
39797
+ const windowsComspecCandidate = process.platform === "win32" && windowsRoot ? join18(windowsRoot, "System32", "cmd.exe") : void 0;
39553
39798
  let safetyFailure;
39554
39799
  return async (task) => {
39555
39800
  if (safetyFailure) {
@@ -39589,8 +39834,8 @@ function createCliRunner(adapter, opts = {}) {
39589
39834
  usage: { inputTokens: 0, outputTokens: 0 }
39590
39835
  };
39591
39836
  }
39592
- const taskRoot = join16(workspaceRoot, task.agentId);
39593
- await mkdir11(taskRoot, { recursive: true });
39837
+ const taskRoot = join18(workspaceRoot, task.agentId);
39838
+ await mkdir12(taskRoot, { recursive: true });
39594
39839
  if (task.cancelledNow()) return cancelledBeforeRun();
39595
39840
  const configuredWorkspace = task.spec.workspace;
39596
39841
  let cwd = taskRoot;
@@ -39656,7 +39901,10 @@ function createCliRunner(adapter, opts = {}) {
39656
39901
  let terminalOutcomeProducedUnderAuthority = false;
39657
39902
  let preparedTerminalOutcome;
39658
39903
  try {
39659
- const resolvedCommand = await resolveTrustedCliCommand(command, trustedCommandOptions);
39904
+ const resolvedCommand = await resolveRunnerCommand(command, adapter.type, {
39905
+ resolution: trustedCommandOptions,
39906
+ probe: true
39907
+ });
39660
39908
  const resolvedWindowsComspec = windowsComspecCandidate ? await resolveTrustedCliCommand(windowsComspecCandidate, trustedCommandOptions) : null;
39661
39909
  const git = await measuredGit();
39662
39910
  const githubGrant = providerGrants.find(
@@ -39926,8 +40174,8 @@ ${attachmentSection}` : prompt;
39926
40174
  let changed = false;
39927
40175
  for (const path of paths) {
39928
40176
  if (!path || path.length > 4096) continue;
39929
- const absolutePath = isAbsolute15(path) ? path : resolve10(cwd, path);
39930
- const directory = dirname9(absolutePath);
40177
+ const absolutePath = isAbsolute16(path) ? path : resolve10(cwd, path);
40178
+ const directory = dirname10(absolutePath);
39931
40179
  observedWorkingDirectories.delete(directory);
39932
40180
  observedWorkingDirectories.add(directory);
39933
40181
  while (observedWorkingDirectories.size > 19) {
@@ -40366,7 +40614,7 @@ function runCliProcess(options) {
40366
40614
  return new Promise((resolve18) => {
40367
40615
  const platform = options.platform ?? process.platform;
40368
40616
  const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID11() : void 0;
40369
- const child = options.guardian ? spawn9(
40617
+ const child = options.guardian ? spawn10(
40370
40618
  options.guardian.nodeCommand,
40371
40619
  [
40372
40620
  options.guardian.scriptPath,
@@ -40377,7 +40625,7 @@ function runCliProcess(options) {
40377
40625
  // The idle pre-assignment guardian must never load from or depend
40378
40626
  // on an untrusted Task checkout. Only the post-gate target enters
40379
40627
  // the requested working directory from its private release frame.
40380
- cwd: dirname9(options.guardian.scriptPath),
40628
+ cwd: dirname10(options.guardian.scriptPath),
40381
40629
  env: runnerGuardianEnv(process.env, containmentGateNonce),
40382
40630
  stdio: ["pipe", "pipe", "pipe"],
40383
40631
  windowsHide: true,
@@ -40658,13 +40906,13 @@ import { randomUUID as randomUUID12 } from "node:crypto";
40658
40906
 
40659
40907
  // src/runners/runtime-observation.ts
40660
40908
  import { open as open6, readdir as readdir5, realpath as realpath9 } from "node:fs/promises";
40661
- import { homedir as homedir7 } from "node:os";
40662
- import { join as join17 } from "node:path";
40909
+ import { homedir as homedir8 } from "node:os";
40910
+ import { join as join19 } from "node:path";
40663
40911
  var READ_WINDOW_BYTES = 1024 * 1024;
40664
40912
  var CATALOG_TIMEOUT_MS = 15e3;
40665
40913
  var CATALOG_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
40666
40914
  function homeFrom(env) {
40667
- return env["HOME"] || env["USERPROFILE"] || homedir7();
40915
+ return env["HOME"] || env["USERPROFILE"] || homedir8();
40668
40916
  }
40669
40917
  async function readHead(path) {
40670
40918
  let handle;
@@ -40719,9 +40967,9 @@ function displayValue(value, maxLength) {
40719
40967
  return trimmed;
40720
40968
  }
40721
40969
  function claudeTranscriptPath(input) {
40722
- const configDir = input.env["CLAUDE_CONFIG_DIR"] || join17(homeFrom(input.env), ".claude");
40970
+ const configDir = input.env["CLAUDE_CONFIG_DIR"] || join19(homeFrom(input.env), ".claude");
40723
40971
  const slug = input.resolvedCwd.replace(/[^a-zA-Z0-9]/g, "-");
40724
- return join17(configDir, "projects", slug, `${input.sessionId}.jsonl`);
40972
+ return join19(configDir, "projects", slug, `${input.sessionId}.jsonl`);
40725
40973
  }
40726
40974
  async function readClaudeSessionEffort(input) {
40727
40975
  const resolvedCwd = await realpath9(input.cwd).catch(() => input.cwd);
@@ -40737,18 +40985,18 @@ async function readClaudeSessionEffort(input) {
40737
40985
  }
40738
40986
  async function newestDirectories(root, limit) {
40739
40987
  const entries = await readdir5(root, { withFileTypes: true }).catch(() => []);
40740
- return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join17(root, name));
40988
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join19(root, name));
40741
40989
  }
40742
40990
  async function findCodexRolloutPath(input) {
40743
- const codexHome = input.env["CODEX_HOME"] || join17(homeFrom(input.env), ".codex");
40744
- const sessions = join17(codexHome, "sessions");
40991
+ const codexHome = input.env["CODEX_HOME"] || join19(homeFrom(input.env), ".codex");
40992
+ const sessions = join19(codexHome, "sessions");
40745
40993
  const suffix = `-${input.threadId}.jsonl`;
40746
40994
  for (const year of await newestDirectories(sessions, 2)) {
40747
40995
  for (const month of await newestDirectories(year, 2)) {
40748
40996
  for (const day of await newestDirectories(month, 3)) {
40749
40997
  const files = await readdir5(day).catch(() => []);
40750
40998
  const match = files.find((name) => name.endsWith(suffix));
40751
- if (match) return join17(day, match);
40999
+ if (match) return join19(day, match);
40752
41000
  }
40753
41001
  }
40754
41002
  }
@@ -41142,18 +41390,18 @@ function improveErrorMessage(error52) {
41142
41390
  }
41143
41391
 
41144
41392
  // src/runners/codex.ts
41145
- import { mkdir as mkdir12, readFile as readFile10, writeFile as writeFile7 } from "node:fs/promises";
41393
+ import { mkdir as mkdir13, readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
41146
41394
  import { randomUUID as randomUUID13 } from "node:crypto";
41147
- import { homedir as homedir8 } from "node:os";
41148
- import { join as join18 } from "node:path";
41395
+ import { homedir as homedir9 } from "node:os";
41396
+ import { join as join20 } from "node:path";
41149
41397
  var CODEX_NOT_FOUND_MESSAGE = "The `codex` CLI was not found on this Machine. Install it (npm install -g @openai/codex) and sign in with `codex login`, or switch the agent to API-key auth.";
41150
41398
  function defaultCodexThreadIndexRoot() {
41151
- return join18(homedir8(), ".zixt", "codex-threads");
41399
+ return join20(homedir9(), ".zixt", "codex-threads");
41152
41400
  }
41153
41401
  var SAFE_SEGMENT3 = /^[A-Za-z0-9_-]{1,200}$/;
41154
41402
  function threadIndexPath(root, agentId, sessionKey) {
41155
41403
  if (!SAFE_SEGMENT3.test(agentId) || !SAFE_SEGMENT3.test(sessionKey)) return null;
41156
- return join18(root, agentId, `${sessionKey}.json`);
41404
+ return join20(root, agentId, `${sessionKey}.json`);
41157
41405
  }
41158
41406
  async function readThreadId(path) {
41159
41407
  try {
@@ -41257,7 +41505,7 @@ ${value}` : value;
41257
41505
  const recordedThreadId = indexPath ? await readThreadId(indexPath) : null;
41258
41506
  const rememberThread = (threadId) => {
41259
41507
  if (!indexPath) return;
41260
- void mkdir12(join18(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile7(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
41508
+ void mkdir13(join20(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile8(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
41261
41509
  });
41262
41510
  };
41263
41511
  const observeRuntime = (threadId) => {
@@ -41720,9 +41968,9 @@ function improveCodexErrorMessage(error52) {
41720
41968
  }
41721
41969
 
41722
41970
  // src/runners/git-preflight.ts
41723
- import { spawn as spawn10 } from "node:child_process";
41971
+ import { spawn as spawn11 } from "node:child_process";
41724
41972
  import { realpath as realpath10 } from "node:fs/promises";
41725
- import { isAbsolute as isAbsolute16, resolve as resolve11 } from "node:path";
41973
+ import { isAbsolute as isAbsolute17, resolve as resolve11 } from "node:path";
41726
41974
  var OUTPUT_LIMIT = 8192;
41727
41975
  var DEFAULT_TIMEOUT_MS4 = 1e4;
41728
41976
  var VERSION_PATTERN = /^git version [^\r\n]{1,108}$/;
@@ -41738,7 +41986,7 @@ function unavailable(error52, checkedAt, executablePath = null) {
41738
41986
  async function preflightGit(options = {}) {
41739
41987
  const checkedAt = (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
41740
41988
  const configured = options.command;
41741
- if (configured !== void 0 && !isAbsolute16(configured)) {
41989
+ if (configured !== void 0 && !isAbsolute17(configured)) {
41742
41990
  return unavailable("configured git command must be an absolute file", checkedAt);
41743
41991
  }
41744
41992
  const trustedCwd = await realpath10(resolve11(options.trustedCwd ?? process.cwd())).catch(() => null);
@@ -41769,7 +42017,7 @@ async function preflightGit(options = {}) {
41769
42017
  }
41770
42018
  async function runVersionProbe(input) {
41771
42019
  return new Promise((resolvePromise) => {
41772
- const child = spawn10(input.executablePath, input.args, {
42020
+ const child = spawn11(input.executablePath, input.args, {
41773
42021
  cwd: input.cwd,
41774
42022
  env: {
41775
42023
  ...process.env.SystemRoot ? { SystemRoot: process.env.SystemRoot } : {},
@@ -41838,7 +42086,7 @@ async function preflightClaudeCode(options = {}) {
41838
42086
  const command = options.command ?? "claude";
41839
42087
  const prefixArgs = options.commandPrefixArgs ?? [];
41840
42088
  const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
41841
- const trustedCommand = await resolveTrustedCliCommand(command);
42089
+ const trustedCommand = await resolveRunnerCommand(command, "claude-code", { probe: true });
41842
42090
  if (!trustedCommand) {
41843
42091
  return {
41844
42092
  type: "claude-code",
@@ -41889,7 +42137,7 @@ async function preflightCodex(options = {}) {
41889
42137
  const command = options.command ?? "codex";
41890
42138
  const prefixArgs = options.commandPrefixArgs ?? [];
41891
42139
  const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
41892
- const trustedCommand = await resolveTrustedCliCommand(command);
42140
+ const trustedCommand = await resolveRunnerCommand(command, "codex", { probe: true });
41893
42141
  if (!trustedCommand) {
41894
42142
  return {
41895
42143
  type: "codex",
@@ -41991,11 +42239,11 @@ function run2(command, args) {
41991
42239
  }
41992
42240
 
41993
42241
  // src/linux-service.ts
41994
- import { spawn as spawn11 } from "node:child_process";
42242
+ import { spawn as spawn12 } from "node:child_process";
41995
42243
  import { constants as constants2 } from "node:fs";
41996
- import { access as access4, chmod as chmod7, mkdir as mkdir13, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
41997
- import { homedir as homedir9, userInfo } from "node:os";
41998
- import { basename as basename4, dirname as dirname10, join as join19, relative as relative9, resolve as resolve12, sep as sep5 } from "node:path";
42244
+ import { access as access4, chmod as chmod7, mkdir as mkdir14, open as open7, rename as rename6, rm as rm10 } from "node:fs/promises";
42245
+ import { homedir as homedir10, userInfo } from "node:os";
42246
+ import { basename as basename4, dirname as dirname11, join as join21, relative as relative9, resolve as resolve12, sep as sep5 } from "node:path";
41999
42247
  var SERVICE_NAME = "zixt-host.service";
42000
42248
  var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
42001
42249
  var SERVICE_STABILITY_DELAY_MS = 2e3;
@@ -42024,7 +42272,7 @@ function boundedAppend(current, chunk) {
42024
42272
  async function defaultRunCommand(command, args) {
42025
42273
  const commandEnvironment3 = systemServiceCommandEnvironment();
42026
42274
  return new Promise((resolve18) => {
42027
- const child = spawn11(command, [...args], {
42275
+ const child = spawn12(command, [...args], {
42028
42276
  stdio: ["ignore", "pipe", "pipe"],
42029
42277
  env: commandEnvironment3,
42030
42278
  windowsHide: true
@@ -42096,22 +42344,22 @@ async function defaultSyncDirectory(path) {
42096
42344
  }
42097
42345
  }
42098
42346
  async function ensureDirectory(path, mode, syncDirectory8) {
42099
- const firstCreated = await mkdir13(path, { recursive: true, mode });
42347
+ const firstCreated = await mkdir14(path, { recursive: true, mode });
42100
42348
  if (!firstCreated) return;
42101
42349
  const first = resolve12(firstCreated);
42102
42350
  const target = resolve12(path);
42103
- await syncDirectory8(dirname10(first));
42351
+ await syncDirectory8(dirname11(first));
42104
42352
  let current = first;
42105
42353
  const descendants = relative9(first, target);
42106
42354
  for (const part of descendants ? descendants.split(sep5) : []) {
42107
42355
  await syncDirectory8(current);
42108
- current = join19(current, part);
42356
+ current = join21(current, part);
42109
42357
  }
42110
42358
  }
42111
42359
  async function replacePrivateFile(path, contents, mode, syncDirectory8) {
42112
- const parent = dirname10(path);
42360
+ const parent = dirname11(path);
42113
42361
  await ensureDirectory(parent, 448, syncDirectory8);
42114
- const temporary = join19(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42362
+ const temporary = join21(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42115
42363
  const handle = await open7(temporary, "wx", mode);
42116
42364
  try {
42117
42365
  await handle.writeFile(contents, "utf8");
@@ -42122,7 +42370,7 @@ async function replacePrivateFile(path, contents, mode, syncDirectory8) {
42122
42370
  await syncDirectory8(parent);
42123
42371
  } catch (error52) {
42124
42372
  await handle.close().catch(() => void 0);
42125
- await rm9(temporary, { force: true }).catch(() => void 0);
42373
+ await rm10(temporary, { force: true }).catch(() => void 0);
42126
42374
  throw error52;
42127
42375
  }
42128
42376
  }
@@ -42155,7 +42403,7 @@ async function installLinuxService(options) {
42155
42403
  throw new Error("Linux automatic startup is available only on Linux.");
42156
42404
  }
42157
42405
  const env = options.env ?? process.env;
42158
- const home = options.home ?? homedir9();
42406
+ const home = options.home ?? homedir10();
42159
42407
  const username = oneLine(options.username ?? userInfo().username, "user name");
42160
42408
  const token2 = oneLine(options.token, "pairing code");
42161
42409
  const path = oneLine(
@@ -42163,12 +42411,12 @@ async function installLinuxService(options) {
42163
42411
  "command search path"
42164
42412
  );
42165
42413
  const cloudUrl = options.cloudUrl ? oneLine(options.cloudUrl, "Zixt Cloud address") : void 0;
42166
- const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join19(home, ".config");
42167
- const configRoot = options.serviceConfigRoot ?? join19(xdgConfigHome, "zixt");
42168
- const unitRoot = options.userUnitRoot ?? join19(xdgConfigHome, "systemd", "user");
42169
- const environmentPath = join19(configRoot, "host.env");
42170
- const unitPath = join19(unitRoot, SERVICE_NAME);
42171
- const installVersion = options.installVersion ?? installRelease;
42414
+ const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join21(home, ".config");
42415
+ const configRoot = options.serviceConfigRoot ?? join21(xdgConfigHome, "zixt");
42416
+ const unitRoot = options.userUnitRoot ?? join21(xdgConfigHome, "systemd", "user");
42417
+ const environmentPath = join21(configRoot, "host.env");
42418
+ const unitPath = join21(unitRoot, SERVICE_NAME);
42419
+ const installVersion = options.installVersion ?? ((version2, onFailure) => installRelease(version2, onFailure ? { onFailure } : {}));
42172
42420
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : activateInstalledRelease);
42173
42421
  const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
42174
42422
  const run3 = options.runCommand ?? defaultRunCommand;
@@ -42183,9 +42431,15 @@ async function installLinuxService(options) {
42183
42431
  "This Linux computer does not have the systemd tools Zixt needs to start itself."
42184
42432
  );
42185
42433
  }
42186
- const releaseEntry = await installVersion(options.hostVersion);
42434
+ const attempt = { failure: null };
42435
+ const releaseEntry = await installVersion(options.hostVersion, (failure2) => {
42436
+ attempt.failure = failure2;
42437
+ });
42187
42438
  if (!releaseEntry) {
42188
- throw new Error(`Zixt Host ${options.hostVersion} could not be installed for automatic start.`);
42439
+ const failed = attempt.failure;
42440
+ throw new Error(
42441
+ `Zixt Host ${options.hostVersion} could not be installed for automatic start${failed ? ` (${failed.reason}: ${failed.detail})` : ""}.`
42442
+ );
42189
42443
  }
42190
42444
  const currentEntry = await activateVersion(releaseEntry);
42191
42445
  const linger = async () => {
@@ -42207,8 +42461,12 @@ async function installLinuxService(options) {
42207
42461
  ...cloudUrl ? [`ZIXT_CLOUD_URL=${systemdEnvironmentValue(cloudUrl)}`] : [],
42208
42462
  `PATH=${systemdEnvironmentValue(path)}`,
42209
42463
  ...env.ZIXT_HOST_UPDATE ? [`ZIXT_HOST_UPDATE=${systemdEnvironmentValue(env.ZIXT_HOST_UPDATE)}`] : [],
42464
+ ...env.ZIXT_RUNNER_AUTOINSTALL ? [`ZIXT_RUNNER_AUTOINSTALL=${systemdEnvironmentValue(env.ZIXT_RUNNER_AUTOINSTALL)}`] : [],
42210
42465
  ...env.ZIXT_HOST_UPDATE_URL ? [`ZIXT_HOST_UPDATE_URL=${systemdEnvironmentValue(env.ZIXT_HOST_UPDATE_URL)}`] : [],
42211
42466
  ...env.ZIXT_HOST_VERSIONS_DIR ? [`ZIXT_HOST_VERSIONS_DIR=${systemdEnvironmentValue(env.ZIXT_HOST_VERSIONS_DIR)}`] : [],
42467
+ // A Machine on a private registry mirror checks ZIXT_HOST_UPDATE_URL for
42468
+ // releases; its unattended npm installs must follow the same mirror.
42469
+ ...env.NPM_CONFIG_REGISTRY ? [`NPM_CONFIG_REGISTRY=${systemdEnvironmentValue(env.NPM_CONFIG_REGISTRY)}`] : [],
42212
42470
  ""
42213
42471
  ].join("\n");
42214
42472
  await replacePrivateFile(environmentPath, serviceEnvironment, 384, syncDirectory8);
@@ -42284,11 +42542,11 @@ async function installLinuxService(options) {
42284
42542
  }
42285
42543
 
42286
42544
  // src/macos-service.ts
42287
- import { spawn as spawn12 } from "node:child_process";
42545
+ import { spawn as spawn13 } from "node:child_process";
42288
42546
  import { constants as constants3 } from "node:fs";
42289
- import { access as access5, chmod as chmod8, mkdir as mkdir14, open as open8, rename as rename7, rm as rm10 } from "node:fs/promises";
42290
- import { homedir as homedir10, userInfo as userInfo2 } from "node:os";
42291
- import { basename as basename5, dirname as dirname11, join as join20, relative as relative10, resolve as resolve13, sep as sep6 } from "node:path";
42547
+ import { access as access5, chmod as chmod8, mkdir as mkdir15, open as open8, rename as rename7, rm as rm11 } from "node:fs/promises";
42548
+ import { homedir as homedir11, userInfo as userInfo2 } from "node:os";
42549
+ import { basename as basename5, dirname as dirname12, join as join22, relative as relative10, resolve as resolve13, sep as sep6 } from "node:path";
42292
42550
  var LAUNCH_AGENT_LABEL = "ai.zixt.host";
42293
42551
  var SERVICE_STABILITY_DELAY_MS2 = 2e3;
42294
42552
  var COMMAND_TIMEOUT_MS2 = 7e4;
@@ -42312,21 +42570,21 @@ async function syncDirectory4(path) {
42312
42570
  }
42313
42571
  }
42314
42572
  async function ensureDirectory2(path, sync) {
42315
- const firstCreated = await mkdir14(path, { recursive: true, mode: 448 });
42573
+ const firstCreated = await mkdir15(path, { recursive: true, mode: 448 });
42316
42574
  if (!firstCreated) return;
42317
42575
  const first = resolve13(firstCreated);
42318
42576
  const target = resolve13(path);
42319
- await sync(dirname11(first));
42577
+ await sync(dirname12(first));
42320
42578
  let current = first;
42321
42579
  for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
42322
42580
  await sync(current);
42323
- current = join20(current, part);
42581
+ current = join22(current, part);
42324
42582
  }
42325
42583
  }
42326
42584
  async function replacePrivateFile2(path, contents, mode, sync) {
42327
- const parent = dirname11(path);
42585
+ const parent = dirname12(path);
42328
42586
  await ensureDirectory2(parent, sync);
42329
- const temporary = join20(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42587
+ const temporary = join22(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42330
42588
  const handle = await open8(temporary, "wx", mode);
42331
42589
  try {
42332
42590
  await handle.writeFile(contents, "utf8");
@@ -42337,7 +42595,7 @@ async function replacePrivateFile2(path, contents, mode, sync) {
42337
42595
  await sync(parent);
42338
42596
  } catch (error52) {
42339
42597
  await handle.close().catch(() => void 0);
42340
- await rm10(temporary, { force: true }).catch(() => void 0);
42598
+ await rm11(temporary, { force: true }).catch(() => void 0);
42341
42599
  throw error52;
42342
42600
  }
42343
42601
  }
@@ -42351,7 +42609,7 @@ function commandEnvironment(env) {
42351
42609
  }
42352
42610
  async function defaultRunCommand2(command, args, env) {
42353
42611
  return new Promise((resolveResult) => {
42354
- const child = spawn12(command, [...args], {
42612
+ const child = spawn13(command, [...args], {
42355
42613
  stdio: ["ignore", "pipe", "pipe"],
42356
42614
  env: commandEnvironment(env)
42357
42615
  });
@@ -42414,7 +42672,7 @@ async function installMacosService(options) {
42414
42672
  throw new Error("macOS automatic startup is available only on macOS.");
42415
42673
  }
42416
42674
  const env = options.env ?? process.env;
42417
- const home = options.home ?? homedir10();
42675
+ const home = options.home ?? homedir11();
42418
42676
  const uid = options.uid ?? userInfo2().uid;
42419
42677
  if (!Number.isSafeInteger(uid) || uid < 0) throw new Error("macOS user id is invalid.");
42420
42678
  const token2 = oneLine2(options.token, "pairing code");
@@ -42423,15 +42681,15 @@ async function installMacosService(options) {
42423
42681
  options.path ?? env.PATH ?? "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin",
42424
42682
  "command search path"
42425
42683
  );
42426
- const configRoot = options.configRoot ?? join20(home, "Library", "Application Support", "Zixt");
42427
- const launchAgentsRoot = options.launchAgentsRoot ?? join20(home, "Library", "LaunchAgents");
42428
- const logRoot = options.logRoot ?? join20(home, "Library", "Logs", "Zixt");
42429
- const configPath = join20(configRoot, "host.env");
42430
- const launcherPath = join20(configRoot, "host-launcher.sh");
42431
- const plistPath = join20(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
42432
- const stdoutPath = join20(logRoot, "host.log");
42433
- const stderrPath = join20(logRoot, "host-error.log");
42434
- const installVersion = options.installVersion ?? installRelease;
42684
+ const configRoot = options.configRoot ?? join22(home, "Library", "Application Support", "Zixt");
42685
+ const launchAgentsRoot = options.launchAgentsRoot ?? join22(home, "Library", "LaunchAgents");
42686
+ const logRoot = options.logRoot ?? join22(home, "Library", "Logs", "Zixt");
42687
+ const configPath = join22(configRoot, "host.env");
42688
+ const launcherPath = join22(configRoot, "host-launcher.sh");
42689
+ const plistPath = join22(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
42690
+ const stdoutPath = join22(logRoot, "host.log");
42691
+ const stderrPath = join22(logRoot, "host-error.log");
42692
+ const installVersion = options.installVersion ?? ((version2, onFailure) => installRelease(version2, onFailure ? { onFailure } : {}));
42435
42693
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
42436
42694
  const resolveCommand = options.resolveCommand ?? (async () => defaultResolveCommand2());
42437
42695
  const run3 = options.runCommand ?? ((command, args) => defaultRunCommand2(command, args, env));
@@ -42439,9 +42697,15 @@ async function installMacosService(options) {
42439
42697
  const delay4 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
42440
42698
  const launchctl = await resolveCommand("launchctl");
42441
42699
  if (!launchctl) throw new Error("macOS launchctl could not be found.");
42442
- const releaseEntry = await installVersion(options.hostVersion);
42700
+ const attempt = { failure: null };
42701
+ const releaseEntry = await installVersion(options.hostVersion, (failure2) => {
42702
+ attempt.failure = failure2;
42703
+ });
42443
42704
  if (!releaseEntry) {
42444
- throw new Error(`Zixt Host ${options.hostVersion} could not be installed for automatic start.`);
42705
+ const failed = attempt.failure;
42706
+ throw new Error(
42707
+ `Zixt Host ${options.hostVersion} could not be installed for automatic start${failed ? ` (${failed.reason}: ${failed.detail})` : ""}.`
42708
+ );
42445
42709
  }
42446
42710
  const currentEntry = await activateVersion(releaseEntry);
42447
42711
  await ensureDirectory2(configRoot, sync);
@@ -42454,8 +42718,12 @@ async function installMacosService(options) {
42454
42718
  `PATH=${shellValue(path)}`,
42455
42719
  "ZIXT_HOST_SERVICE_MANAGER=launchd",
42456
42720
  ...env.ZIXT_HOST_UPDATE ? [`ZIXT_HOST_UPDATE=${shellValue(env.ZIXT_HOST_UPDATE)}`] : [],
42721
+ ...env.ZIXT_RUNNER_AUTOINSTALL ? [`ZIXT_RUNNER_AUTOINSTALL=${shellValue(env.ZIXT_RUNNER_AUTOINSTALL)}`] : [],
42457
42722
  ...env.ZIXT_HOST_UPDATE_URL ? [`ZIXT_HOST_UPDATE_URL=${shellValue(env.ZIXT_HOST_UPDATE_URL)}`] : [],
42458
42723
  ...env.ZIXT_HOST_VERSIONS_DIR ? [`ZIXT_HOST_VERSIONS_DIR=${shellValue(env.ZIXT_HOST_VERSIONS_DIR)}`] : [],
42724
+ // A Machine on a private registry mirror checks ZIXT_HOST_UPDATE_URL for
42725
+ // releases; its unattended npm installs must follow the same mirror.
42726
+ ...env.NPM_CONFIG_REGISTRY ? [`NPM_CONFIG_REGISTRY=${shellValue(env.NPM_CONFIG_REGISTRY)}`] : [],
42459
42727
  ""
42460
42728
  ].join("\n");
42461
42729
  await replacePrivateFile2(configPath, serviceEnvironment, 384, sync);
@@ -42515,11 +42783,11 @@ async function installMacosService(options) {
42515
42783
  }
42516
42784
 
42517
42785
  // src/windows-service.ts
42518
- import { spawn as spawn13 } from "node:child_process";
42786
+ import { spawn as spawn14 } from "node:child_process";
42519
42787
  import { constants as constants4 } from "node:fs";
42520
- import { access as access6, mkdir as mkdir15, open as open9, readFile as readFile11, rename as rename8, rm as rm11 } from "node:fs/promises";
42521
- import { homedir as homedir11 } from "node:os";
42522
- import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute17, join as join21, relative as relative11, resolve as resolve14, sep as sep7 } from "node:path";
42788
+ import { access as access6, mkdir as mkdir16, open as open9, readFile as readFile11, rename as rename8, rm as rm12 } from "node:fs/promises";
42789
+ import { homedir as homedir12 } from "node:os";
42790
+ import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute18, join as join23, relative as relative11, resolve as resolve14, sep as sep7 } from "node:path";
42523
42791
  var TASK_NAME = "Zixt Host";
42524
42792
  var COMMAND_TIMEOUT_MS3 = 7e4;
42525
42793
  var SERVICE_STABILITY_DELAY_MS3 = 2e3;
@@ -42545,31 +42813,31 @@ async function syncDirectory5(path) {
42545
42813
  }
42546
42814
  }
42547
42815
  async function ensureDirectory3(path, sync) {
42548
- const firstCreated = await mkdir15(path, { recursive: true, mode: 448 });
42816
+ const firstCreated = await mkdir16(path, { recursive: true, mode: 448 });
42549
42817
  if (!firstCreated) return;
42550
42818
  const first = resolve14(firstCreated);
42551
42819
  const target = resolve14(path);
42552
- await sync(dirname12(first));
42820
+ await sync(dirname13(first));
42553
42821
  let current = first;
42554
42822
  for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
42555
42823
  await sync(current);
42556
- current = join21(current, part);
42824
+ current = join23(current, part);
42557
42825
  }
42558
42826
  }
42559
- async function replacePrivateFile3(path, contents, sync) {
42560
- const parent = dirname12(path);
42827
+ async function replacePrivateFile3(path, contents, sync, encoding = "utf8") {
42828
+ const parent = dirname13(path);
42561
42829
  await ensureDirectory3(parent, sync);
42562
- const temporary = join21(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42830
+ const temporary = join23(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42563
42831
  const handle = await open9(temporary, "wx", 384);
42564
42832
  try {
42565
- await handle.writeFile(contents, "utf8");
42833
+ await handle.writeFile(encoding === "utf16le" ? `\uFEFF${contents}` : contents, encoding);
42566
42834
  await handle.sync();
42567
42835
  await handle.close();
42568
42836
  await rename8(temporary, path);
42569
42837
  await sync(parent);
42570
42838
  } catch (error52) {
42571
42839
  await handle.close().catch(() => void 0);
42572
- await rm11(temporary, { force: true }).catch(() => void 0);
42840
+ await rm12(temporary, { force: true }).catch(() => void 0);
42573
42841
  throw error52;
42574
42842
  }
42575
42843
  }
@@ -42580,7 +42848,7 @@ function commandEnvironment2(env) {
42580
42848
  }
42581
42849
  async function runChild(command, args, env, input) {
42582
42850
  return new Promise((resolveResult) => {
42583
- const child = spawn13(command, [...args], {
42851
+ const child = spawn14(command, [...args], {
42584
42852
  stdio: [input === void 0 ? "ignore" : "pipe", "pipe", "pipe"],
42585
42853
  env: commandEnvironment2(env),
42586
42854
  windowsHide: true
@@ -42613,8 +42881,8 @@ async function runChild(command, args, env, input) {
42613
42881
  }
42614
42882
  async function defaultResolveCommand3(name, env) {
42615
42883
  const root = env.SYSTEMROOT ?? env.WINDIR;
42616
- if (!root || !isAbsolute17(root)) return null;
42617
- const candidate = name === "powershell" ? join21(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join21(root, "System32", `${name}.exe`);
42884
+ if (!root || !isAbsolute18(root)) return null;
42885
+ const candidate = name === "powershell" ? join23(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join23(root, "System32", `${name}.exe`);
42618
42886
  return access6(candidate, constants4.X_OK).then(
42619
42887
  () => candidate,
42620
42888
  () => null
@@ -42664,8 +42932,10 @@ try {
42664
42932
  if ($config.cloudUrl) { $env:ZIXT_CLOUD_URL = $config.cloudUrl } else { Remove-Item Env:ZIXT_CLOUD_URL -ErrorAction SilentlyContinue }
42665
42933
  $env:PATH = $config.path
42666
42934
  if ($config.update) { $env:ZIXT_HOST_UPDATE = $config.update }
42935
+ if ($config.runnerAutoinstall) { $env:ZIXT_RUNNER_AUTOINSTALL = $config.runnerAutoinstall }
42667
42936
  if ($config.updateUrl) { $env:ZIXT_HOST_UPDATE_URL = $config.updateUrl }
42668
42937
  if ($config.versionsRoot) { $env:ZIXT_HOST_VERSIONS_DIR = $config.versionsRoot }
42938
+ if ($config.npmRegistry) { $env:NPM_CONFIG_REGISTRY = $config.npmRegistry }
42669
42939
  Set-Location -LiteralPath $config.cwd
42670
42940
 
42671
42941
  # Task Scheduler does not provide a durable stdin lifetime boundary. Give
@@ -42713,8 +42983,20 @@ async function defaultObserveStatus(path, generation) {
42713
42983
  return null;
42714
42984
  }
42715
42985
  }
42986
+ function hiddenLaunchSource(powershell, launcherPath) {
42987
+ const vbsPath = (value) => {
42988
+ if (/[\0\r\n"]/.test(value)) throw new Error("launch path is not a valid one-line value");
42989
+ return value;
42990
+ };
42991
+ return [
42992
+ "Dim q : q = Chr(34)",
42993
+ 'Dim shell : Set shell = CreateObject("WScript.Shell")',
42994
+ `WScript.Quit shell.Run(q & "${vbsPath(powershell)}" & q & " -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File " & q & "${vbsPath(launcherPath)}" & q, 0, True)`,
42995
+ ""
42996
+ ].join("\r\n");
42997
+ }
42716
42998
  function taskXml(input) {
42717
- return `<?xml version="1.0" encoding="UTF-8"?>
42999
+ return `<?xml version="1.0" encoding="UTF-16"?>
42718
43000
  <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
42719
43001
  <Triggers><LogonTrigger><Enabled>true</Enabled><UserId>${xml2(input.sid)}</UserId></LogonTrigger></Triggers>
42720
43002
  <Principals><Principal id="ZixtUser"><UserId>${xml2(input.sid)}</UserId><LogonType>InteractiveToken</LogonType><RunLevel>LeastPrivilege</RunLevel></Principal></Principals>
@@ -42727,8 +43009,8 @@ function taskXml(input) {
42727
43009
  <RestartOnFailure><Interval>PT1M</Interval><Count>999</Count></RestartOnFailure>
42728
43010
  </Settings>
42729
43011
  <Actions Context="ZixtUser"><Exec>
42730
- <Command>${xml2(input.powershell)}</Command>
42731
- <Arguments>-NoProfile -NonInteractive -ExecutionPolicy Bypass -File &quot;${xml2(input.launcherPath)}&quot;</Arguments>
43012
+ <Command>${xml2(input.wscript)}</Command>
43013
+ <Arguments>//B //NoLogo &quot;${xml2(input.launchShimPath)}&quot;</Arguments>
42732
43014
  <WorkingDirectory>${xml2(input.home)}</WorkingDirectory>
42733
43015
  </Exec></Actions>
42734
43016
  </Task>
@@ -42743,39 +43025,47 @@ async function installWindowsService(options) {
42743
43025
  throw new Error("Windows automatic startup is available only on Windows.");
42744
43026
  }
42745
43027
  const env = options.env ?? process.env;
42746
- const home = options.home ?? homedir11();
43028
+ const home = options.home ?? homedir12();
42747
43029
  const localAppData = options.localAppData ?? env.LOCALAPPDATA;
42748
- if (!localAppData || !isAbsolute17(localAppData)) {
43030
+ if (!localAppData || !isAbsolute18(localAppData)) {
42749
43031
  throw new Error("Windows local application data path is unavailable.");
42750
43032
  }
42751
43033
  const token2 = oneLine3(options.token, "pairing code");
42752
43034
  const cloudUrl = options.cloudUrl ? oneLine3(options.cloudUrl, "Zixt Cloud address") : void 0;
42753
43035
  const path = oneLine3(options.path ?? env.PATH ?? "", "command search path");
42754
- const configRoot = options.configRoot ?? join21(localAppData, "Zixt", "Host");
42755
- const configPath = join21(configRoot, "host.json");
42756
- const launcherPath = join21(configRoot, "host-launcher.ps1");
42757
- const taskXmlPath = join21(configRoot, "host-task.xml");
42758
- const statusPath = join21(configRoot, "host-status.json");
42759
- const installVersion = options.installVersion ?? installRelease;
43036
+ const configRoot = options.configRoot ?? join23(localAppData, "Zixt", "Host");
43037
+ const configPath = join23(configRoot, "host.json");
43038
+ const launcherPath = join23(configRoot, "host-launcher.ps1");
43039
+ const launchShimPath = join23(configRoot, "host-launch.vbs");
43040
+ const taskXmlPath = join23(configRoot, "host-task.xml");
43041
+ const statusPath = join23(configRoot, "host-status.json");
43042
+ const installVersion = options.installVersion ?? ((version2, onFailure) => installRelease(version2, onFailure ? { onFailure } : {}));
42760
43043
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
42761
43044
  const resolveCommand = options.resolveCommand ?? ((name) => defaultResolveCommand3(name, env));
42762
43045
  const run3 = options.runCommand ?? ((command, args) => runChild(command, args, env));
42763
43046
  const sync = options.syncDirectory ?? syncDirectory5;
42764
43047
  const delay4 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
42765
43048
  const observe = options.observeStatus ?? defaultObserveStatus;
42766
- const [powershell, schtasks, icacls] = await Promise.all([
43049
+ const [powershell, schtasks, icacls, wscript] = await Promise.all([
42767
43050
  resolveCommand("powershell"),
42768
43051
  resolveCommand("schtasks"),
42769
- resolveCommand("icacls")
43052
+ resolveCommand("icacls"),
43053
+ resolveCommand("wscript")
42770
43054
  ]);
42771
- if (!powershell || !schtasks || !icacls) {
43055
+ if (!powershell || !schtasks || !icacls || !wscript) {
42772
43056
  throw new Error("Windows Scheduled Task tools could not be found.");
42773
43057
  }
42774
43058
  const sid = options.sid ?? await defaultCurrentSid(powershell, env);
42775
43059
  if (!sid || !SAFE_SID.test(sid)) throw new Error("Windows user identity could not be confirmed.");
42776
- const releaseEntry = await installVersion(options.hostVersion);
43060
+ const attempt = { failure: null };
43061
+ const releaseEntry = await installVersion(options.hostVersion, (failure2) => {
43062
+ attempt.failure = failure2;
43063
+ });
42777
43064
  if (!releaseEntry) {
42778
- throw new Error(`Zixt Host ${options.hostVersion} could not be installed for automatic start.`);
43065
+ const failed = attempt.failure;
43066
+ throw new Error(
43067
+ `Zixt Host ${options.hostVersion} could not be installed for automatic start${failed ? ` (${failed.reason}: ${failed.detail})` : ""}.`
43068
+ );
42779
43069
  }
42780
43070
  const currentEntry = await activateVersion(releaseEntry);
42781
43071
  const protectedToken = await (options.protectToken ?? ((value, shell) => defaultProtectToken(value, shell, env)))(token2, powershell);
@@ -42796,15 +43086,25 @@ async function installWindowsService(options) {
42796
43086
  ...cloudUrl ? { cloudUrl } : {},
42797
43087
  path,
42798
43088
  ...env.ZIXT_HOST_UPDATE ? { update: env.ZIXT_HOST_UPDATE } : {},
43089
+ ...env.ZIXT_RUNNER_AUTOINSTALL ? { runnerAutoinstall: env.ZIXT_RUNNER_AUTOINSTALL } : {},
42799
43090
  ...env.ZIXT_HOST_UPDATE_URL ? { updateUrl: env.ZIXT_HOST_UPDATE_URL } : {},
42800
- ...env.ZIXT_HOST_VERSIONS_DIR ? { versionsRoot: env.ZIXT_HOST_VERSIONS_DIR } : {}
43091
+ ...env.ZIXT_HOST_VERSIONS_DIR ? { versionsRoot: env.ZIXT_HOST_VERSIONS_DIR } : {},
43092
+ // A Machine on a private registry mirror checks updateUrl for releases;
43093
+ // its unattended npm installs must follow the same mirror.
43094
+ ...env.NPM_CONFIG_REGISTRY ? { npmRegistry: env.NPM_CONFIG_REGISTRY } : {}
42801
43095
  })}
42802
43096
  `,
42803
43097
  sync
42804
43098
  );
42805
43099
  await replacePrivateFile3(launcherPath, launcherSource2(configPath, statusPath), sync);
42806
- await replacePrivateFile3(taskXmlPath, taskXml({ sid, powershell, launcherPath, home }), sync);
42807
- await rm11(statusPath, { force: true });
43100
+ await replacePrivateFile3(launchShimPath, hiddenLaunchSource(powershell, launcherPath), sync);
43101
+ await replacePrivateFile3(
43102
+ taskXmlPath,
43103
+ taskXml({ sid, wscript, launchShimPath, home }),
43104
+ sync,
43105
+ "utf16le"
43106
+ );
43107
+ await rm12(statusPath, { force: true });
42808
43108
  const acl = await run3(icacls, [
42809
43109
  configRoot,
42810
43110
  "/inheritance:r",
@@ -42814,6 +43114,13 @@ async function installWindowsService(options) {
42814
43114
  "*S-1-5-18:(OI)(CI)F"
42815
43115
  ]);
42816
43116
  if (acl.code !== 0) throw commandFailure3("Protecting Zixt startup files", acl);
43117
+ const sweep = await run3(powershell, [
43118
+ "-NoProfile",
43119
+ "-NonInteractive",
43120
+ "-Command",
43121
+ `$stopped = 0; Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" | Where-Object { $_.ProcessId -ne $PID -and $_.CommandLine -and $_.CommandLine.Contains(${psLiteral(launcherPath)}) } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue; $stopped++ }; Write-Output $stopped`
43122
+ ]);
43123
+ if (Number.parseInt(sweep.stdout.trim(), 10) > 0) await delay4(1500);
42817
43124
  await run3(schtasks, ["/End", "/TN", TASK_NAME]);
42818
43125
  const create = await run3(schtasks, ["/Create", "/TN", TASK_NAME, "/XML", taskXmlPath, "/F"]);
42819
43126
  if (create.code !== 0) throw commandFailure3("Installing Zixt at sign-in", create);
@@ -42837,6 +43144,7 @@ async function installWindowsService(options) {
42837
43144
  taskXmlPath,
42838
43145
  configPath,
42839
43146
  launcherPath,
43147
+ launchShimPath,
42840
43148
  statusPath,
42841
43149
  releaseEntry,
42842
43150
  currentEntry,
@@ -42856,23 +43164,23 @@ async function installSystemService(options) {
42856
43164
  }
42857
43165
 
42858
43166
  // src/terminal-outcomes.ts
42859
- import { chmod as chmod9, lstat as lstat12, mkdir as mkdir16, open as open10, readdir as readdir6, readFile as readFile12, rename as rename9, rm as rm12 } from "node:fs/promises";
42860
- import { homedir as homedir12 } from "node:os";
42861
- import { dirname as dirname13, join as join22, relative as relative12, resolve as resolve15, sep as sep8 } from "node:path";
43167
+ import { chmod as chmod9, lstat as lstat12, mkdir as mkdir17, open as open10, readdir as readdir6, readFile as readFile12, rename as rename9, rm as rm13 } from "node:fs/promises";
43168
+ import { homedir as homedir13 } from "node:os";
43169
+ import { dirname as dirname14, join as join24, relative as relative12, resolve as resolve15, sep as sep8 } from "node:path";
42862
43170
  var DIRECTORY_MODE5 = 448;
42863
43171
  var FILE_MODE4 = 384;
42864
43172
  var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
42865
43173
  var HOST_DIRECTORY = /^hst_[0-9a-f]{32}$/;
42866
43174
  var OUTCOME_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
42867
43175
  function defaultTerminalOutcomeRoot() {
42868
- return join22(homedir12(), ".zixt", "terminal-outcomes");
43176
+ return join24(homedir13(), ".zixt", "terminal-outcomes");
42869
43177
  }
42870
43178
  function hostOutcomeRoot(root, hostId) {
42871
43179
  if (!HOST_DIRECTORY.test(hostId)) throw new Error("terminal outcome Host identity is malformed");
42872
- return join22(root, hostId);
43180
+ return join24(root, hostId);
42873
43181
  }
42874
43182
  function outcomePath(root, hostId, taskId, epoch) {
42875
- return join22(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
43183
+ return join24(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
42876
43184
  }
42877
43185
  async function syncDirectory6(root) {
42878
43186
  if (process.platform === "win32") return;
@@ -42884,19 +43192,19 @@ async function syncDirectory6(root) {
42884
43192
  }
42885
43193
  }
42886
43194
  async function requirePrivateRoot(root, sync = syncDirectory6) {
42887
- const firstCreated = await mkdir16(root, { recursive: true, mode: DIRECTORY_MODE5 });
43195
+ const firstCreated = await mkdir17(root, { recursive: true, mode: DIRECTORY_MODE5 });
42888
43196
  if (firstCreated) {
42889
43197
  const first = resolve15(firstCreated);
42890
43198
  const target = resolve15(root);
42891
- await sync(dirname13(first));
43199
+ await sync(dirname14(first));
42892
43200
  let current = first;
42893
43201
  for (const part of relative12(first, target).split(sep8).filter(Boolean)) {
42894
43202
  await sync(current);
42895
- current = join22(current, part);
43203
+ current = join24(current, part);
42896
43204
  }
42897
43205
  }
42898
- const stat3 = await lstat12(root);
42899
- if (stat3.isSymbolicLink() || !stat3.isDirectory()) {
43206
+ const stat4 = await lstat12(root);
43207
+ if (stat4.isSymbolicLink() || !stat4.isDirectory()) {
42900
43208
  throw new Error("terminal outcome journal root is not a trusted directory");
42901
43209
  }
42902
43210
  await chmod9(root, DIRECTORY_MODE5);
@@ -42932,7 +43240,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
42932
43240
  } catch (error52) {
42933
43241
  if (error52.code !== "ENOENT") throw error52;
42934
43242
  }
42935
- const temporary = join22(
43243
+ const temporary = join24(
42936
43244
  scopedRoot,
42937
43245
  `.${outcome.taskId}.${outcome.epoch}.${process.pid}.${Date.now()}.${outcome.resultId}.tmp`
42938
43246
  );
@@ -42949,7 +43257,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
42949
43257
  } finally {
42950
43258
  await handle?.close().catch(() => {
42951
43259
  });
42952
- await rm12(temporary, { force: true }).catch(() => {
43260
+ await rm13(temporary, { force: true }).catch(() => {
42953
43261
  });
42954
43262
  }
42955
43263
  }
@@ -42985,9 +43293,9 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
42985
43293
  if (!match || !entry.isFile() || entry.isSymbolicLink()) {
42986
43294
  throw new Error("committed terminal outcome is not a trusted regular file");
42987
43295
  }
42988
- const path = join22(scopedRoot, entry.name);
42989
- const stat3 = await lstat12(path);
42990
- if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_OUTCOME_BYTES) {
43296
+ const path = join24(scopedRoot, entry.name);
43297
+ const stat4 = await lstat12(path);
43298
+ if (!stat4.isFile() || stat4.isSymbolicLink() || stat4.size > MAX_OUTCOME_BYTES) {
42991
43299
  throw new Error("committed terminal outcome is not a trusted regular file");
42992
43300
  }
42993
43301
  const outcome = parseCommittedOutcome(
@@ -43018,7 +43326,7 @@ async function forgetAcknowledgedTerminalOutcomes(refs, root = defaultTerminalOu
43018
43326
  if (acknowledged.get(`${hostId}:${outcome.taskId}:${outcome.epoch}`) !== outcome.resultId) {
43019
43327
  continue;
43020
43328
  }
43021
- await rm12(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43329
+ await rm13(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43022
43330
  changedHostRoots.add(hostOutcomeRoot(root, hostId));
43023
43331
  }
43024
43332
  for (const scopedRoot of changedHostRoots) await syncDirectory6(scopedRoot);
@@ -43030,22 +43338,22 @@ async function forgetSupersededTerminalOutcomes(hostId, taskId, epoch, root = de
43030
43338
  if (scoped.hostId !== hostId) continue;
43031
43339
  const { outcome } = scoped;
43032
43340
  if (outcome.taskId !== taskId || outcome.epoch >= epoch) continue;
43033
- await rm12(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43341
+ await rm13(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43034
43342
  removed = true;
43035
43343
  }
43036
43344
  if (removed) await syncDirectory6(hostOutcomeRoot(root, hostId));
43037
43345
  }
43038
43346
 
43039
43347
  // src/accepted-assignments.ts
43040
- import { chmod as chmod10, lstat as lstat13, mkdir as mkdir17, open as open11, readdir as readdir7, rename as rename10, rm as rm13 } from "node:fs/promises";
43041
- import { homedir as homedir13 } from "node:os";
43042
- import { dirname as dirname14, join as join23, relative as relative13, resolve as resolve16, sep as sep9 } from "node:path";
43348
+ import { chmod as chmod10, lstat as lstat13, mkdir as mkdir18, open as open11, readdir as readdir7, rename as rename10, rm as rm14 } from "node:fs/promises";
43349
+ import { homedir as homedir14 } from "node:os";
43350
+ import { dirname as dirname15, join as join25, relative as relative13, resolve as resolve16, sep as sep9 } from "node:path";
43043
43351
  var DIRECTORY_MODE6 = 448;
43044
43352
  var FILE_MODE5 = 384;
43045
43353
  var CLAIM_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
43046
43354
  var TASK_ID = /^tsk_[0-9a-f]{32}$/;
43047
43355
  function defaultAcceptedAssignmentRoot() {
43048
- return join23(homedir13(), ".zixt", "accepted-assignments");
43356
+ return join25(homedir14(), ".zixt", "accepted-assignments");
43049
43357
  }
43050
43358
  async function syncDirectory7(root) {
43051
43359
  if (process.platform === "win32") return;
@@ -43057,19 +43365,19 @@ async function syncDirectory7(root) {
43057
43365
  }
43058
43366
  }
43059
43367
  async function requirePrivateRoot2(root, sync = syncDirectory7) {
43060
- const firstCreated = await mkdir17(root, { recursive: true, mode: DIRECTORY_MODE6 });
43368
+ const firstCreated = await mkdir18(root, { recursive: true, mode: DIRECTORY_MODE6 });
43061
43369
  if (firstCreated) {
43062
43370
  const first = resolve16(firstCreated);
43063
43371
  const target = resolve16(root);
43064
- await sync(dirname14(first));
43372
+ await sync(dirname15(first));
43065
43373
  let current = first;
43066
43374
  for (const part of relative13(first, target).split(sep9).filter(Boolean)) {
43067
43375
  await sync(current);
43068
- current = join23(current, part);
43376
+ current = join25(current, part);
43069
43377
  }
43070
43378
  }
43071
- const stat3 = await lstat13(root);
43072
- if (stat3.isSymbolicLink() || !stat3.isDirectory()) {
43379
+ const stat4 = await lstat13(root);
43380
+ if (stat4.isSymbolicLink() || !stat4.isDirectory()) {
43073
43381
  throw new Error("accepted assignment journal root is not a trusted directory");
43074
43382
  }
43075
43383
  await chmod10(root, DIRECTORY_MODE6);
@@ -43079,7 +43387,7 @@ function claimPath(root, taskId, epoch) {
43079
43387
  if (!Number.isSafeInteger(epoch) || epoch < 1) {
43080
43388
  throw new Error("accepted assignment epoch is malformed");
43081
43389
  }
43082
- return join23(root, `${taskId}.${epoch}.json`);
43390
+ return join25(root, `${taskId}.${epoch}.json`);
43083
43391
  }
43084
43392
  async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssignmentRoot(), options = {}) {
43085
43393
  const sync = options.syncDirectory ?? syncDirectory7;
@@ -43089,7 +43397,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
43089
43397
  } catch {
43090
43398
  return false;
43091
43399
  }
43092
- const temporary = join23(
43400
+ const temporary = join25(
43093
43401
  root,
43094
43402
  `.${assignment.taskId}.${assignment.epoch}.${process.pid}.${Date.now()}.tmp`
43095
43403
  );
@@ -43109,7 +43417,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
43109
43417
  } finally {
43110
43418
  await handle?.close().catch(() => {
43111
43419
  });
43112
- await rm13(temporary, { force: true }).catch(() => {
43420
+ await rm14(temporary, { force: true }).catch(() => {
43113
43421
  });
43114
43422
  }
43115
43423
  }
@@ -43143,13 +43451,18 @@ async function forgetAcceptedAssignment(assignment, root = defaultAcceptedAssign
43143
43451
  } catch {
43144
43452
  return;
43145
43453
  }
43146
- await rm13(path, { force: true }).catch(() => {
43454
+ await rm14(path, { force: true }).catch(() => {
43147
43455
  });
43148
43456
  }
43149
43457
  async function forgetAcknowledgedAcceptedAssignments(assignments, root = defaultAcceptedAssignmentRoot()) {
43150
43458
  for (const assignment of assignments) await forgetAcceptedAssignment(assignment, root);
43151
43459
  }
43152
43460
 
43461
+ // src/local-observability.ts
43462
+ import { appendFile, mkdir as mkdir19, open as open12, rename as rename11, rm as rm15, stat as stat3 } from "node:fs/promises";
43463
+ import { homedir as homedir15 } from "node:os";
43464
+ import { basename as basename7, dirname as dirname16, join as join26 } from "node:path";
43465
+
43153
43466
  // src/logger.ts
43154
43467
  var ANSI = {
43155
43468
  reset: "\x1B[0m",
@@ -43241,7 +43554,9 @@ function createHostLogger(options = {}) {
43241
43554
  const color = options.color ?? (process.stderr.isTTY === true && process.env.NO_COLOR === void 0);
43242
43555
  const write = options.write ?? ((line) => console.error(line));
43243
43556
  const log2 = (level, message, context) => {
43244
- write(formatHostLogLine(level, message, context, { at: now(), color }));
43557
+ const at = now();
43558
+ write(formatHostLogLine(level, message, context, { at, color }));
43559
+ options.onEntry?.({ at, level, message, context: context ?? {} });
43245
43560
  };
43246
43561
  return {
43247
43562
  info: (message, context) => log2("info", message, context),
@@ -43251,24 +43566,105 @@ function createHostLogger(options = {}) {
43251
43566
  };
43252
43567
  }
43253
43568
 
43569
+ // src/local-observability.ts
43570
+ var LOCAL_CONSOLE_FILE = "console.jsonl";
43571
+ var LOCAL_CONSOLE_PREVIOUS_FILE = "console.prev.jsonl";
43572
+ var LOCAL_STATUS_FILE = "status.json";
43573
+ var DEFAULT_CONSOLE_ROTATE_BYTES = 2 * 1024 * 1024;
43574
+ function defaultLocalObservabilityRoot() {
43575
+ return join26(homedir15(), ".zixt", "observability");
43576
+ }
43577
+ function createLocalConsoleSink(options = {}) {
43578
+ const root = options.root ?? defaultLocalObservabilityRoot();
43579
+ const consolePath = join26(root, LOCAL_CONSOLE_FILE);
43580
+ const rotateBytes = options.rotateBytes ?? DEFAULT_CONSOLE_ROTATE_BYTES;
43581
+ let disabled = false;
43582
+ let prepared = false;
43583
+ let approximateBytes = 0;
43584
+ let queue = Promise.resolve();
43585
+ const write = async (entry) => {
43586
+ if (disabled) return;
43587
+ try {
43588
+ if (!prepared) {
43589
+ await mkdir19(root, { recursive: true, mode: 448 });
43590
+ approximateBytes = await stat3(consolePath).then(
43591
+ (existing) => existing.size,
43592
+ () => 0
43593
+ );
43594
+ prepared = true;
43595
+ }
43596
+ if (approximateBytes >= rotateBytes) {
43597
+ await rm15(join26(root, LOCAL_CONSOLE_PREVIOUS_FILE), { force: true });
43598
+ await rename11(consolePath, join26(root, LOCAL_CONSOLE_PREVIOUS_FILE)).catch(
43599
+ (error52) => {
43600
+ if (error52.code !== "ENOENT") throw error52;
43601
+ }
43602
+ );
43603
+ approximateBytes = 0;
43604
+ }
43605
+ const line = `${JSON.stringify({
43606
+ at: entry.at.toISOString(),
43607
+ level: entry.level,
43608
+ line: formatHostLogLine(entry.level, entry.message, entry.context, {
43609
+ at: entry.at,
43610
+ color: false
43611
+ })
43612
+ })}
43613
+ `;
43614
+ await appendFile(consolePath, line, { encoding: "utf8", mode: 384 });
43615
+ approximateBytes += Buffer.byteLength(line);
43616
+ } catch (error52) {
43617
+ disabled = true;
43618
+ options.onDisabled?.(error52);
43619
+ }
43620
+ };
43621
+ return {
43622
+ entry(entry) {
43623
+ queue = queue.then(() => write(entry));
43624
+ },
43625
+ settled: () => queue
43626
+ };
43627
+ }
43628
+ async function writeLocalStatus(status, root = defaultLocalObservabilityRoot()) {
43629
+ const destination = join26(root, LOCAL_STATUS_FILE);
43630
+ const temporary = join26(
43631
+ dirname16(destination),
43632
+ `.${basename7(destination)}.${process.pid}.${crypto.randomUUID()}.tmp`
43633
+ );
43634
+ try {
43635
+ await mkdir19(root, { recursive: true, mode: 448 });
43636
+ const handle = await open12(temporary, "wx", 384);
43637
+ try {
43638
+ await handle.writeFile(`${JSON.stringify(status)}
43639
+ `, "utf8");
43640
+ } finally {
43641
+ await handle.close();
43642
+ }
43643
+ await rename11(temporary, destination);
43644
+ } catch {
43645
+ await rm15(temporary, { force: true }).catch(() => void 0);
43646
+ }
43647
+ }
43648
+
43254
43649
  // src/demo-state.ts
43255
- import { isAbsolute as isAbsolute18, join as join24, parse as parse3, resolve as resolve17 } from "node:path";
43650
+ import { isAbsolute as isAbsolute19, join as join27, parse as parse3, resolve as resolve17 } from "node:path";
43256
43651
  var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
43257
43652
  function resolveDemoHostStatePaths(env = process.env) {
43258
43653
  const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
43259
43654
  if (!configured) return null;
43260
43655
  const root = resolve17(configured);
43261
- if (!isAbsolute18(configured) || root === parse3(root).root) {
43656
+ if (!isAbsolute19(configured) || root === parse3(root).root) {
43262
43657
  throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
43263
43658
  }
43264
43659
  return {
43265
- runRegistryRoot: join24(root, "run-registry"),
43266
- terminalOutcomeRoot: join24(root, "terminal-outcomes"),
43267
- acceptedAssignmentRoot: join24(root, "accepted-assignments"),
43268
- runArtifactRoot: join24(root, "run-artifacts"),
43269
- browserProfileRoot: join24(root, "browser-profiles"),
43270
- runnerWorkspaceRoot: join24(root, "workspaces"),
43271
- codexThreadIndexRoot: join24(root, "codex-threads")
43660
+ runRegistryRoot: join27(root, "run-registry"),
43661
+ terminalOutcomeRoot: join27(root, "terminal-outcomes"),
43662
+ acceptedAssignmentRoot: join27(root, "accepted-assignments"),
43663
+ runArtifactRoot: join27(root, "run-artifacts"),
43664
+ browserProfileRoot: join27(root, "browser-profiles"),
43665
+ runnerWorkspaceRoot: join27(root, "workspaces"),
43666
+ codexThreadIndexRoot: join27(root, "codex-threads"),
43667
+ localObservabilityRoot: join27(root, "local-observability")
43272
43668
  };
43273
43669
  }
43274
43670
 
@@ -43330,6 +43726,9 @@ function parseHostCliOptions(argv) {
43330
43726
  }
43331
43727
  return options;
43332
43728
  }
43729
+ function isServiceSetupInvocation(argv) {
43730
+ return argv.includes("--install-service");
43731
+ }
43333
43732
  function forcedColor(mode) {
43334
43733
  if (mode === "always") return true;
43335
43734
  if (mode === "never") return false;
@@ -43412,7 +43811,9 @@ if (packagedBuild) {
43412
43811
  if (isWorkerProxyRole()) process.exit(managedExit(await runWorkerCompatibilityProxy()));
43413
43812
  if (needsLegacySupervisorHandoff()) process.exit(managedExit(await launchHostSupervisor()));
43414
43813
  if (isSupervisorRole()) process.exit(managedExit(await superviseHost()));
43415
- if (!isWorkerRole()) process.exit(managedExit(await launchHostSupervisor()));
43814
+ if (!isWorkerRole() && !isServiceSetupInvocation(process.argv.slice(2))) {
43815
+ process.exit(managedExit(await launchHostSupervisor()));
43816
+ }
43416
43817
  }
43417
43818
  var workerWatchdog = startWorkerWatchdogHeartbeat();
43418
43819
  if (packagedBuild && isWorkerRole() && process.env[WORKER_WATCHDOG_NONCE_ENV] !== void 0 && !workerWatchdog.active) {
@@ -43440,12 +43841,14 @@ function recordConsoleLine(line) {
43440
43841
  if (hostConsoleTail.length > 200) hostConsoleTail.shift();
43441
43842
  clientForConsole.current?.hostConsoleLine(entry);
43442
43843
  }
43844
+ var localConsoleSink = { current: null };
43443
43845
  var log = createHostLogger({
43444
43846
  ...colorOverride === void 0 ? {} : { color: colorOverride },
43445
43847
  write: (line) => {
43446
43848
  console.error(line);
43447
43849
  recordConsoleLine(line);
43448
- }
43850
+ },
43851
+ onEntry: (entry) => localConsoleSink.current?.entry(entry)
43449
43852
  });
43450
43853
  function replayConsoleLine(level, message, context) {
43451
43854
  recordConsoleLine(
@@ -43453,6 +43856,7 @@ function replayConsoleLine(level, message, context) {
43453
43856
  ...colorOverride === void 0 ? {} : { color: colorOverride }
43454
43857
  })
43455
43858
  );
43859
+ localConsoleSink.current?.entry({ at: /* @__PURE__ */ new Date(), level, message, context: context ?? {} });
43456
43860
  }
43457
43861
  if (cliOptions.help) {
43458
43862
  process.stdout.write(`${hostHelpText()}
@@ -43516,8 +43920,20 @@ var {
43516
43920
  runArtifactRoot,
43517
43921
  browserProfileRoot,
43518
43922
  runnerWorkspaceRoot,
43519
- codexThreadIndexRoot
43923
+ codexThreadIndexRoot,
43924
+ localObservabilityRoot
43520
43925
  } = demoState ?? {};
43926
+ localConsoleSink.current = createLocalConsoleSink({
43927
+ ...localObservabilityRoot ? { root: localObservabilityRoot } : {},
43928
+ onDisabled: (error52) => {
43929
+ console.error(
43930
+ formatHostLogLine("warn", "The local console file was disabled after a write failure", {
43931
+ machine,
43932
+ error: error52 instanceof Error ? error52.message : "unknown error"
43933
+ })
43934
+ );
43935
+ }
43936
+ });
43521
43937
  var disclaimableAssignments;
43522
43938
  var acceptedAssignments;
43523
43939
  var terminalOutcomes;
@@ -43559,6 +43975,23 @@ if (!token) {
43559
43975
  process.exit(DO_NOT_RESTART_EXIT_CODE);
43560
43976
  }
43561
43977
  var demoPreflightScript = forceDemo ? process.env.ZIXT_DEMO_PREFLIGHT_SCRIPT : void 0;
43978
+ var runnerAutoInstaller = forceDemo || process.env.ZIXT_RUNNER_AUTOINSTALL === "off" ? null : createRunnerAutoInstaller({
43979
+ onEvent: (event) => {
43980
+ const name = event.runner === "claude-code" ? "Claude Code" : "Codex";
43981
+ if (event.state === "started") {
43982
+ log.info(`${name} not found; installing it for this Machine`, { machine });
43983
+ } else if (event.state === "completed") {
43984
+ log.success(`${name} installed`, { machine });
43985
+ cachedRunners = null;
43986
+ } else {
43987
+ log.warn(`${name} installation failed`, {
43988
+ machine,
43989
+ ...event.error ? { error: event.error } : {},
43990
+ next: `Install the ${event.runner === "claude-code" ? "claude" : "codex"} CLI manually; the Host retries later`
43991
+ });
43992
+ }
43993
+ }
43994
+ });
43562
43995
  var gitPreflight = await preflightGit();
43563
43996
  var gitRefresh = null;
43564
43997
  var GIT_PREFLIGHT_REFRESH_MS = 4 * 6e4;
@@ -43702,12 +44135,18 @@ async function telemetry() {
43702
44135
  preflightCodex()
43703
44136
  ]);
43704
44137
  cachedRunnersAt = Date.now();
43705
- for (const runner of cachedRunners) reportRunnerReadiness(runner);
44138
+ for (const runner of cachedRunners) {
44139
+ reportRunnerReadiness(runner);
44140
+ if (!runner.installed && (runner.type === "claude-code" || runner.type === "codex") && runnerAutoInstaller) {
44141
+ runnerAutoInstaller.ensureInstalled(runner.type);
44142
+ }
44143
+ }
43706
44144
  }
43707
44145
  const providerToolPacks = toolPackRegistry.capabilities({
43708
44146
  now: /* @__PURE__ */ new Date(),
43709
44147
  git: await currentGitPreflight()
43710
44148
  });
44149
+ publishLocalStatus();
43711
44150
  providerToolPacks.push({
43712
44151
  provider: "email",
43713
44152
  version: 1,
@@ -43734,7 +44173,7 @@ async function telemetry() {
43734
44173
  // Measured per heartbeat: free memory and free disk are only useful while
43735
44174
  // they are current, and a demo Host reports its own private root so the
43736
44175
  // number describes the filesystem its Tasks would really write to.
43737
- hardware: await machineHardware(runnerWorkspaceRoot ?? homedir14()),
44176
+ hardware: await machineHardware(runnerWorkspaceRoot ?? homedir16()),
43738
44177
  capabilities: {
43739
44178
  linearToolPack: providerToolPacks.some(
43740
44179
  (pack) => pack.provider === "linear" && pack.health === "ready"
@@ -43791,6 +44230,36 @@ var connectionContext = connectionLogContext({
43791
44230
  cloud: cloudTarget,
43792
44231
  version: HOST_VERSION
43793
44232
  });
44233
+ var hostStartedAt = (/* @__PURE__ */ new Date()).toISOString();
44234
+ var localCloudState = "connecting";
44235
+ var localCloudConnectedAt;
44236
+ var localStatusQueued = false;
44237
+ function publishLocalStatus() {
44238
+ if (localStatusQueued) return;
44239
+ localStatusQueued = true;
44240
+ queueMicrotask(() => {
44241
+ localStatusQueued = false;
44242
+ void writeLocalStatus(
44243
+ {
44244
+ schema: 1,
44245
+ version: HOST_VERSION,
44246
+ pid: process.pid,
44247
+ machine,
44248
+ startedAt: hostStartedAt,
44249
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
44250
+ cloud: {
44251
+ target: cloudTarget,
44252
+ state: localCloudState,
44253
+ ...localCloudConnectedAt ? { connectedAt: localCloudConnectedAt } : {}
44254
+ },
44255
+ activeSessions,
44256
+ runners: cachedRunners ?? [],
44257
+ browser: cachedBrowserCapability ?? { status: "unavailable" }
44258
+ },
44259
+ ...localObservabilityRoot ? [localObservabilityRoot] : []
44260
+ );
44261
+ });
44262
+ }
43794
44263
  var stopUpdateWatch = () => {
43795
44264
  };
43796
44265
  var releaseParentPipeWatch = () => {
@@ -43915,6 +44384,9 @@ var client = new HostClient({
43915
44384
  switch (status) {
43916
44385
  case "connected":
43917
44386
  log.success("Connected to Zixt Cloud", connectionContext);
44387
+ localCloudState = "connected";
44388
+ localCloudConnectedAt = (/* @__PURE__ */ new Date()).toISOString();
44389
+ publishLocalStatus();
43918
44390
  if (reportedWorkerExits.length > 0) {
43919
44391
  void forgetWorkerExits(reportedWorkerExits.map(({ file: file2 }) => file2));
43920
44392
  }
@@ -43924,12 +44396,16 @@ var client = new HostClient({
43924
44396
  ...connectionContext,
43925
44397
  next: "Check the cloud and Machine pairing if this continues"
43926
44398
  });
44399
+ localCloudState = "connecting";
44400
+ publishLocalStatus();
43927
44401
  break;
43928
44402
  case "unresponsive":
43929
44403
  log.warn("Zixt Cloud stopped answering; Tasks unwound before reconnecting", {
43930
44404
  ...connectionContext,
43931
44405
  next: "Check this Machine's network path and Zixt Cloud health if this repeats"
43932
44406
  });
44407
+ localCloudState = "connecting";
44408
+ publishLocalStatus();
43933
44409
  break;
43934
44410
  case "replaced":
43935
44411
  log.warn("Another Host process took over this Machine", connectionContext);