@zixt/host 0.0.119 → 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 +868 -444
  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.119",
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];
@@ -27899,15 +28130,15 @@ async function installRelease(version2, options = {}) {
27899
28130
  }
27900
28131
  const platform = options.platform ?? process.platform;
27901
28132
  const root = options.root ?? versionsRoot();
27902
- const prefix = join8(root, version2);
28133
+ const prefix = join10(root, version2);
27903
28134
  const entry = installedReleaseEntry(version2, root);
27904
28135
  if (await validReleaseAtPrefix(prefix, version2)) return entry;
27905
28136
  if (options.signal?.aborted)
27906
28137
  return fail("cancelled", "this Host was stopping before npm started");
27907
28138
  const installerCommand = options.installerCommand ?? await resolveInstallerCommand({ platform });
27908
- await mkdir5(root, { recursive: true, mode: 448 });
27909
- const staging = join8(root, `.install-${version2}-${process.pid}-${crypto.randomUUID()}`);
27910
- 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()}`);
27911
28142
  const usesWindowsInstallerGuardian = platform === "win32" && options.spawnInstaller === void 0;
27912
28143
  const installerGateNonce = usesWindowsInstallerGuardian ? crypto.randomUUID() : null;
27913
28144
  const installerArguments = (installPrefix, installVersion) => [
@@ -27922,14 +28153,14 @@ async function installRelease(version2, options = {}) {
27922
28153
  const spawnInstaller = options.spawnInstaller ?? ((installPrefix, installVersion) => {
27923
28154
  const installerArgs = installerArguments(installPrefix, installVersion);
27924
28155
  if (usesWindowsInstallerGuardian) {
27925
- return spawn5(process.execPath, ["-e", WINDOWS_INSTALLER_GUARDIAN, installerGateNonce], {
28156
+ return spawn6(process.execPath, ["-e", WINDOWS_INSTALLER_GUARDIAN, installerGateNonce], {
27926
28157
  cwd: root,
27927
28158
  stdio: ["pipe", "inherit", "inherit", "ipc"],
27928
28159
  env: sanitizedInstallerEnv(process.env),
27929
28160
  windowsHide: true
27930
28161
  });
27931
28162
  }
27932
- return spawn5(installerCommand, installerArgs, {
28163
+ return spawn6(installerCommand, installerArgs, {
27933
28164
  // stdin stays closed for the same reason as the Windows guardian
27934
28165
  // above: this worker actively reads its own stdin (the supervisor's
27935
28166
  // stop pipe), and an unattended npm must not share or depend on it.
@@ -27942,7 +28173,7 @@ async function installRelease(version2, options = {}) {
27942
28173
  try {
27943
28174
  child = spawnInstaller(staging, version2);
27944
28175
  } catch (error52) {
27945
- await rm5(staging, { recursive: true, force: true }).catch(() => void 0);
28176
+ await rm6(staging, { recursive: true, force: true }).catch(() => void 0);
27946
28177
  return fail(
27947
28178
  "installer_unavailable",
27948
28179
  `${installerCommand} could not be started (${error52 instanceof Error ? error52.message : "unknown error"})`
@@ -27968,7 +28199,7 @@ async function installRelease(version2, options = {}) {
27968
28199
  installerContainmentSetupError = error52;
27969
28200
  return null;
27970
28201
  }) : Promise.resolve(null);
27971
- const timeoutMs = options.timeoutMs ?? INSTALL_TIMEOUT_MS;
28202
+ const timeoutMs = options.timeoutMs ?? INSTALL_TIMEOUT_MS2;
27972
28203
  const outcome = { code: null, signal: null, timedOut: false, spawnError: null };
27973
28204
  const installed = await new Promise((resolve18, reject3) => {
27974
28205
  let finished = false;
@@ -28139,8 +28370,8 @@ async function installRelease(version2, options = {}) {
28139
28370
  `${prefix} is not a runnable ${PACKAGE_NAME}@${version2} after installing`
28140
28371
  );
28141
28372
  } finally {
28142
- await rm5(staging, { recursive: true, force: true }).catch(() => void 0);
28143
- 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);
28144
28375
  }
28145
28376
  }
28146
28377
  async function pruneInstalledVersions(keep, root = versionsRoot()) {
@@ -28155,10 +28386,10 @@ async function pruneInstalledVersions(keep, root = versionsRoot()) {
28155
28386
  const removed = [];
28156
28387
  for (const name of entries) {
28157
28388
  if (protectedDirs.has(name) || !VERSION_DIR.test(name)) continue;
28158
- const dir = join8(root, name);
28389
+ const dir = join10(root, name);
28159
28390
  if (running && running.startsWith(`${dir}${sep4}`)) continue;
28160
28391
  try {
28161
- await rm5(dir, { recursive: true, force: true });
28392
+ await rm6(dir, { recursive: true, force: true });
28162
28393
  removed.push(name);
28163
28394
  } catch {
28164
28395
  }
@@ -28169,7 +28400,7 @@ function durableState(phase, candidateVersion, fallbackVersion) {
28169
28400
  return { schema: 1, phase, candidateVersion, fallbackVersion };
28170
28401
  }
28171
28402
  async function validInstalledRelease(version2, root = versionsRoot()) {
28172
- return validReleaseAtPrefix(join8(root, version2), version2);
28403
+ return validReleaseAtPrefix(join10(root, version2), version2);
28173
28404
  }
28174
28405
  async function recoverDurableReleaseState(store, runningVersion, activeBootVersion, activate, log2) {
28175
28406
  const state = await store.load();
@@ -28287,7 +28518,7 @@ function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityO
28287
28518
  delete env.ZIXT_HOST_REJECT_VERSION;
28288
28519
  if (command.rejectedVersion) env.ZIXT_HOST_REJECT_VERSION = command.rejectedVersion;
28289
28520
  const entry = compatibilityProxy ? process.argv[1] ?? "" : command.entry ?? process.argv[1] ?? "";
28290
- const child = spawn5(process.execPath, [entry, ...argv, ...ownership?.argv ?? []], {
28521
+ const child = spawn6(process.execPath, [entry, ...argv, ...ownership?.argv ?? []], {
28291
28522
  // stdin is a pipe this process owns: closing it is how the worker is
28292
28523
  // asked to stop, which works identically on Windows, where there is no
28293
28524
  // real SIGINT to send. stdout stays the person's terminal; stderr is teed
@@ -28295,7 +28526,7 @@ function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityO
28295
28526
  stdio: watchdog ? ["pipe", "inherit", "pipe", "ipc"] : ["pipe", "inherit", "pipe"],
28296
28527
  env,
28297
28528
  ...containmentGateNonce ? {
28298
- cwd: ownership?.ownershipFile ? dirname4(ownership.ownershipFile) : dirname4(entry)
28529
+ cwd: ownership?.ownershipFile ? dirname5(ownership.ownershipFile) : dirname5(entry)
28299
28530
  } : {},
28300
28531
  // The launch nonce is not a user-facing CLI argument. Keeping it as
28301
28532
  // argv[0] gives the stable launcher an exact cross-platform process
@@ -28324,7 +28555,7 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
28324
28555
  const ownership = consumeWorkerOwnershipArguments(argv, env);
28325
28556
  const nonce = env[WORKER_WATCHDOG_NONCE_ENV];
28326
28557
  const ownershipFile = env[WORKER_OWNERSHIP_FILE_ENV];
28327
- 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) {
28328
28559
  return 1;
28329
28560
  }
28330
28561
  if (!recordWorkerOwnership(ownershipFile, nonce)) return 1;
@@ -28341,7 +28572,7 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
28341
28572
  delete workerEnv[SUPERVISOR_OWNERSHIP_FILE_ENV];
28342
28573
  delete workerEnv[WINDOWS_CONTAINMENT_GATE_ENV];
28343
28574
  delete workerEnv[WINDOWS_POST_CONTAINMENT_CWD_ENV];
28344
- const child = spawn5(process.execPath, [target, ...ownership.argv], {
28575
+ const child = spawn6(process.execPath, [target, ...ownership.argv], {
28345
28576
  stdio: ["pipe", "inherit", "inherit"],
28346
28577
  env: workerEnv,
28347
28578
  // The proxy is already a detached group/session leader on POSIX. The old
@@ -28397,7 +28628,7 @@ async function launchHostSupervisor(options = {}) {
28397
28628
  const generationNonce = ownershipDirectory ? basename3(ownershipDirectory) : null;
28398
28629
  if (ownershipDirectory && generationNonce) {
28399
28630
  env[LAUNCHER_OWNERSHIP_DIR_ENV] = ownershipDirectory;
28400
- env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join8(ownershipDirectory, `${generationNonce}.json`);
28631
+ env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join10(ownershipDirectory, `${generationNonce}.json`);
28401
28632
  } else {
28402
28633
  delete env[LAUNCHER_OWNERSHIP_DIR_ENV];
28403
28634
  }
@@ -28405,10 +28636,10 @@ async function launchHostSupervisor(options = {}) {
28405
28636
  if (!containmentGateNonce) delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
28406
28637
  if (version2) env[SUPERVISOR_VERSION_ENV] = version2;
28407
28638
  else delete env[SUPERVISOR_VERSION_ENV];
28408
- const child2 = spawn5(process.execPath, [supervisorEntry, ...argv], {
28639
+ const child2 = spawn6(process.execPath, [supervisorEntry, ...argv], {
28409
28640
  stdio: ["pipe", "inherit", "inherit"],
28410
28641
  env,
28411
- ...containmentGateNonce ? { cwd: ownershipDirectory ?? dirname4(supervisorEntry) } : {},
28642
+ ...containmentGateNonce ? { cwd: ownershipDirectory ?? dirname5(supervisorEntry) } : {},
28412
28643
  detached: platform !== "win32",
28413
28644
  // The new launcher can discover the durable PID record and still has
28414
28645
  // to bind it to this exact process before signalling a recycled PID.
@@ -28420,8 +28651,8 @@ async function launchHostSupervisor(options = {}) {
28420
28651
  });
28421
28652
  const customDelay = options.delay;
28422
28653
  const ownsWorkerBoundary = options.spawnSupervisor === void 0 || options.ownershipRoot !== void 0;
28423
- const ownershipRoot = options.ownershipRoot ?? join8(versionsRoot(), "launcher-ownership");
28424
- 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());
28425
28656
  const terminateRecordedOwnership = options.terminateRecordedOwnership ?? terminateRecordedProcessTree;
28426
28657
  const createSupervisorContainment = options.createSupervisorContainment ?? (platform === "win32" && options.spawnSupervisor === void 0 ? async (target, identityNonce, signal) => {
28427
28658
  if (!target.pid) throw new Error("supervisor process id is unavailable");
@@ -28530,8 +28761,8 @@ async function launchHostSupervisor(options = {}) {
28530
28761
  let stdinIsPipe = options.parentStdinIsPipe ?? false;
28531
28762
  if (options.parentStdinIsPipe === void 0) {
28532
28763
  try {
28533
- const stat3 = fstatSync(0);
28534
- stdinIsPipe = !stat3.isCharacterDevice() && !stat3.isFile() && !process.stdin.isTTY;
28764
+ const stat4 = fstatSync(0);
28765
+ stdinIsPipe = !stat4.isCharacterDevice() && !stat4.isFile() && !process.stdin.isTTY;
28535
28766
  } catch {
28536
28767
  }
28537
28768
  }
@@ -28688,10 +28919,10 @@ async function superviseHost(options = {}) {
28688
28919
  const log2 = options.log ?? ((message) => console.error(message));
28689
28920
  const signalWorker = options.signalWorker ?? signalWorkerGroup;
28690
28921
  const inheritedOwnershipDirectory = process.env[LAUNCHER_OWNERSHIP_DIR_ENV];
28691
- const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute9(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
28922
+ const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute10(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
28692
28923
  if (productionLifecycle && isSupervisorRole() && launcherOwnershipDirectory) {
28693
28924
  const generationNonce = basename3(launcherOwnershipDirectory);
28694
- const expectedOwnershipFile = join8(launcherOwnershipDirectory, `${generationNonce}.json`);
28925
+ const expectedOwnershipFile = join10(launcherOwnershipDirectory, `${generationNonce}.json`);
28695
28926
  const configuredOwnershipFile = process.env[SUPERVISOR_OWNERSHIP_FILE_ENV];
28696
28927
  if (process.argv0 !== generationNonce || configuredOwnershipFile !== expectedOwnershipFile || !recordWorkerOwnership(expectedOwnershipFile, generationNonce)) {
28697
28928
  log2("Zixt Host: supervisor ownership could not be committed; refusing to start a worker");
@@ -29340,9 +29571,9 @@ function beginWorkerShutdown(options) {
29340
29571
  // src/parent-pipe.ts
29341
29572
  import { fstatSync as fstatSync2 } from "node:fs";
29342
29573
  var END_OF_TEXT = 3;
29343
- function stdinIsParentPipe(stat3 = (fd) => fstatSync2(fd), isTTY = process.stdin.isTTY === true) {
29574
+ function stdinIsParentPipe(stat4 = (fd) => fstatSync2(fd), isTTY = process.stdin.isTTY === true) {
29344
29575
  try {
29345
- const stdin = stat3(0);
29576
+ const stdin = stat4(0);
29346
29577
  return !stdin.isCharacterDevice() && !stdin.isFile() && !isTTY;
29347
29578
  } catch {
29348
29579
  return false;
@@ -29370,14 +29601,14 @@ function watchParentPipe(pipe2, onStop) {
29370
29601
  }
29371
29602
 
29372
29603
  // src/index.ts
29373
- import { homedir as homedir14, hostname as hostname3 } from "node:os";
29604
+ import { homedir as homedir16, hostname as hostname3 } from "node:os";
29374
29605
 
29375
29606
  // src/hardware.ts
29376
29607
  import { existsSync } from "node:fs";
29377
29608
  import { statfs } from "node:fs/promises";
29378
- import { cpus, freemem, homedir as homedir4, totalmem } from "node:os";
29379
- import { dirname as dirname5, resolve as resolve6 } from "node:path";
29380
- 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()) {
29381
29612
  return {
29382
29613
  // A container or cgroup can hide processors from this count; it is what
29383
29614
  // this process can see, which is what its Tasks will actually get.
@@ -29405,7 +29636,7 @@ function nearestExistingPath(start) {
29405
29636
  let candidate = resolve6(start);
29406
29637
  for (let depth = 0; depth < 16; depth++) {
29407
29638
  if (existsSync(candidate)) return candidate;
29408
- const parent = dirname5(candidate);
29639
+ const parent = dirname6(candidate);
29409
29640
  if (parent === candidate) return null;
29410
29641
  candidate = parent;
29411
29642
  }
@@ -29599,17 +29830,17 @@ function createDemoBrowserAdapterFactory() {
29599
29830
  }
29600
29831
 
29601
29832
  // src/browser/manager.ts
29602
- import { lstat as lstat6, mkdir as mkdir6, open as open5, opendir, readFile as readFile8, rename as rename4, rm as rm6 } from "node:fs/promises";
29603
- import { homedir as homedir5 } from "node:os";
29604
- 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";
29605
29836
  var SAFE_SEGMENT2 = /^[A-Za-z0-9_-]{1,200}$/;
29606
29837
  var FRAME_MIN_INTERVAL_MS = 100;
29607
29838
  var IDLE_TIMEOUT_MS = 15 * 6e4;
29608
29839
  var BrowserManager = class {
29609
29840
  constructor(opts) {
29610
29841
  this.opts = opts;
29611
- this.profileRoot = opts.profileRoot ?? join9(homedir5(), ".zixt", "browser-profiles");
29612
- 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");
29613
29844
  this.viewport = opts.viewport ?? BROWSER_DEFAULT_VIEWPORT;
29614
29845
  this.idleTimeoutMs = opts.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
29615
29846
  this.frameMinIntervalMs = opts.frameMinIntervalMs ?? FRAME_MIN_INTERVAL_MS;
@@ -29706,15 +29937,15 @@ var BrowserManager = class {
29706
29937
  exactChild(root, child) {
29707
29938
  const canonicalRoot = resolve7(root);
29708
29939
  const target = resolve7(canonicalRoot, child);
29709
- if (dirname6(target) !== canonicalRoot) {
29940
+ if (dirname7(target) !== canonicalRoot) {
29710
29941
  throw new Error("browser profile path escaped its owned root");
29711
29942
  }
29712
29943
  return target;
29713
29944
  }
29714
29945
  async ensureOwnedDirectory(path) {
29715
- await mkdir6(path, { recursive: true, mode: 448 });
29716
- const stat3 = await lstat6(path);
29717
- 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()) {
29718
29949
  throw new Error("browser profile root must be an owned directory, not a symbolic link");
29719
29950
  }
29720
29951
  }
@@ -29778,7 +30009,7 @@ var BrowserManager = class {
29778
30009
  await this.syncDirectory(this.profileStateRoot);
29779
30010
  await this.syncDirectory(this.profileRoot);
29780
30011
  } catch (error52) {
29781
- await rm6(temporary, { force: true }).catch(() => {
30012
+ await rm7(temporary, { force: true }).catch(() => {
29782
30013
  });
29783
30014
  throw error52;
29784
30015
  }
@@ -29858,7 +30089,7 @@ var BrowserManager = class {
29858
30089
  } catch (error52) {
29859
30090
  if (error52.code !== "ENOENT") throw error52;
29860
30091
  }
29861
- await mkdir6(profileDir, { recursive: true, mode: 448 });
30092
+ await mkdir7(profileDir, { recursive: true, mode: 448 });
29862
30093
  const adapter = await this.opts.factory.open({
29863
30094
  taskId,
29864
30095
  agentId,
@@ -29946,7 +30177,7 @@ var BrowserManager = class {
29946
30177
  });
29947
30178
  const sessionTaskIds = [...this.sessions.values()].filter((session) => session.agentId === agentId).map((session) => session.taskId);
29948
30179
  for (const taskId of sessionTaskIds) await this.closeLocked(taskId, "stopped");
29949
- await rm6(this.profilePath(agentId), { recursive: true, force: true, maxRetries: 3 });
30180
+ await rm7(this.profilePath(agentId), { recursive: true, force: true, maxRetries: 3 });
29950
30181
  await this.syncDirectory(this.profileRoot);
29951
30182
  });
29952
30183
  }
@@ -30117,13 +30348,13 @@ var BrowserManager = class {
30117
30348
  };
30118
30349
 
30119
30350
  // src/browser/playwright-adapter.ts
30120
- import { spawn as spawn6 } from "node:child_process";
30351
+ import { spawn as spawn7 } from "node:child_process";
30121
30352
  import { access as access3 } from "node:fs/promises";
30122
30353
  import { createRequire } from "node:module";
30123
- import { dirname as dirname7, join as join10 } from "node:path";
30354
+ import { dirname as dirname8, join as join12 } from "node:path";
30124
30355
  var nodeRequire = createRequire(import.meta.url);
30125
30356
  var playwrightCoreManifestPath = nodeRequire.resolve("playwright-core/package.json");
30126
- var playwrightCoreRoot = dirname7(playwrightCoreManifestPath);
30357
+ var playwrightCoreRoot = dirname8(playwrightCoreManifestPath);
30127
30358
  var playwrightCoreVersion = nodeRequire(playwrightCoreManifestPath).version;
30128
30359
  if (typeof playwrightCoreVersion !== "string" || !/^\d+\.\d+\.\d+$/.test(playwrightCoreVersion)) {
30129
30360
  throw new Error("playwright-core package version is invalid");
@@ -30140,9 +30371,9 @@ async function loadPlaywright() {
30140
30371
  return import("playwright-core");
30141
30372
  }
30142
30373
  async function installChromium() {
30143
- const cliPath = join10(playwrightCoreRoot, "cli.js");
30374
+ const cliPath = join12(playwrightCoreRoot, "cli.js");
30144
30375
  await new Promise((resolve18, reject3) => {
30145
- const child = spawn6(process.execPath, [cliPath, "install", "chromium"], {
30376
+ const child = spawn7(process.execPath, [cliPath, "install", "chromium"], {
30146
30377
  env: process.env,
30147
30378
  stdio: ["ignore", "inherit", "inherit"],
30148
30379
  // A service-managed Host has no console; letting Windows allocate one
@@ -30774,11 +31005,11 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
30774
31005
  }
30775
31006
 
30776
31007
  // src/runners/cli-runner.ts
30777
- import { spawn as spawn9 } from "node:child_process";
31008
+ import { spawn as spawn10 } from "node:child_process";
30778
31009
  import { randomUUID as randomUUID11 } from "node:crypto";
30779
- import { lstat as lstat11, mkdir as mkdir11, realpath as realpath8 } from "node:fs/promises";
30780
- import { homedir as homedir6 } from "node:os";
30781
- 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";
30782
31013
 
30783
31014
  // src/tool-packs/browser/authentication-wall.ts
30784
31015
  var AUTH_PATH_SEGMENT = /(?:^|\/)(?:log[-_]?in|sign[-_]?in|sso|saml|auth|authorize|authenticate|oauth2?|session\/new|checkpoint)(?:\/|$)/i;
@@ -33596,16 +33827,16 @@ function createGithubPushOrchestrator(input) {
33596
33827
  }
33597
33828
 
33598
33829
  // src/tool-packs/github/git-bridge.ts
33599
- import { spawn as spawn7 } from "node:child_process";
33830
+ import { spawn as spawn8 } from "node:child_process";
33600
33831
  import { randomUUID as randomUUID8 } from "node:crypto";
33601
- import { chmod as chmod4, lstat as lstat8, mkdir as mkdir7, realpath as realpath5, rm as rm7 } from "node:fs/promises";
33602
- 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";
33603
33834
 
33604
33835
  // src/tool-packs/github/git-credential-broker.ts
33605
33836
  import { createServer } from "node:http";
33606
33837
  import { randomBytes, randomUUID as randomUUID7, timingSafeEqual } from "node:crypto";
33607
- import { chmod as chmod3, lstat as lstat7, realpath as realpath4, writeFile as writeFile3 } from "node:fs/promises";
33608
- 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";
33609
33840
  var MAX_REQUEST_BYTES = 16 * 1024;
33610
33841
  var FILE_MODE2 = 384;
33611
33842
  var HELPER_SOURCE = String.raw`'use strict';
@@ -33719,7 +33950,7 @@ async function readBoundedBody2(request) {
33719
33950
  }
33720
33951
  function assertChildPath(parent, child) {
33721
33952
  const path = relative5(parent, child);
33722
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute10(path)) {
33953
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute11(path)) {
33723
33954
  throw new Error("Git credential helper path escaped its private run directory");
33724
33955
  }
33725
33956
  }
@@ -33734,9 +33965,9 @@ async function createGithubGitCredentialBroker(input) {
33734
33965
  throw new Error("Git credential broker requires a private real run directory");
33735
33966
  }
33736
33967
  const runRoot = await realpath4(input.runArtifactsRoot);
33737
- const helperPath = join11(runRoot, `git-credential-${randomUUID7()}.cjs`);
33968
+ const helperPath = join13(runRoot, `git-credential-${randomUUID7()}.cjs`);
33738
33969
  assertChildPath(runRoot, helperPath);
33739
- await writeFile3(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
33970
+ await writeFile4(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
33740
33971
  await chmod3(helperPath, FILE_MODE2);
33741
33972
  const capability2 = randomBytes(32).toString("base64url");
33742
33973
  const expectedPath = `${input.repositoryFullName}.git`;
@@ -33834,7 +34065,7 @@ ${stderr}`;
33834
34065
  }
33835
34066
  function assertBelow2(parent, child, label) {
33836
34067
  const path = relative6(parent, child);
33837
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute11(path)) {
34068
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
33838
34069
  throw new GithubGitProcessError("invalid_input");
33839
34070
  }
33840
34071
  void label;
@@ -33849,8 +34080,8 @@ async function requireRealDirectory2(path, label) {
33849
34080
  }
33850
34081
  async function validateTokenlessPaths(command) {
33851
34082
  if (command.kind === "clone-from-bridge") {
33852
- if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
33853
- 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");
33854
34085
  assertBelow2(parent, command.destination, "clone destination");
33855
34086
  const destination = await lstat8(command.destination).catch((error52) => {
33856
34087
  if (error52.code === "ENOENT") return null;
@@ -33860,7 +34091,7 @@ async function validateTokenlessPaths(command) {
33860
34091
  return;
33861
34092
  }
33862
34093
  if ("repositoryPath" in command) {
33863
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34094
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
33864
34095
  const repositoryPath5 = await requireRealDirectory2(command.repositoryPath, "repository path");
33865
34096
  if (repositoryPath5 !== command.repositoryPath) throw new GithubGitProcessError("invalid_input");
33866
34097
  }
@@ -33940,13 +34171,13 @@ async function runGit(input, args, env) {
33940
34171
  if (input.authoritySignal.aborted || input.cancelledNow()) {
33941
34172
  throw new GithubGitProcessError("cancelled");
33942
34173
  }
33943
- if (!isAbsolute11(input.executablePath)) throw new GithubGitProcessError("invalid_input");
34174
+ if (!isAbsolute12(input.executablePath)) throw new GithubGitProcessError("invalid_input");
33944
34175
  const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
33945
34176
  if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > DEFAULT_TIMEOUT_MS2) {
33946
34177
  throw new GithubGitProcessError("invalid_input");
33947
34178
  }
33948
34179
  return new Promise((resolvePromise, rejectPromise) => {
33949
- const child = spawn7(input.executablePath, [...input.commandPrefixArgs ?? [], ...args], {
34180
+ const child = spawn8(input.executablePath, [...input.commandPrefixArgs ?? [], ...args], {
33950
34181
  cwd: input.trustedCwd,
33951
34182
  env,
33952
34183
  shell: false,
@@ -34046,7 +34277,7 @@ function tokenlessArgs(command) {
34046
34277
  switch (command.kind) {
34047
34278
  case "clone-from-bridge":
34048
34279
  assertRef(command.branch);
34049
- if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
34280
+ if (!isAbsolute12(command.destination)) throw new GithubGitProcessError("invalid_input");
34050
34281
  return [
34051
34282
  "clone",
34052
34283
  "--no-recurse-submodules",
@@ -34058,7 +34289,7 @@ function tokenlessArgs(command) {
34058
34289
  ];
34059
34290
  case "fetch-from-bridge":
34060
34291
  assertFetchRefspecs(command.refspecs);
34061
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34292
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34062
34293
  return [
34063
34294
  "-C",
34064
34295
  command.repositoryPath,
@@ -34070,7 +34301,7 @@ function tokenlessArgs(command) {
34070
34301
  ...command.refspecs
34071
34302
  ];
34072
34303
  case "copy-commit-to-bridge":
34073
- if (!isAbsolute11(command.repositoryPath) || !SHA.test(command.sha)) {
34304
+ if (!isAbsolute12(command.repositoryPath) || !SHA.test(command.sha)) {
34074
34305
  throw new GithubGitProcessError("invalid_input");
34075
34306
  }
34076
34307
  return [
@@ -34082,11 +34313,11 @@ function tokenlessArgs(command) {
34082
34313
  `${command.sha}:refs/zixt/push-source`
34083
34314
  ];
34084
34315
  case "rev-parse":
34085
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34316
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34086
34317
  assertRef(command.ref);
34087
34318
  return ["-C", command.repositoryPath, "rev-parse", "--verify", `${command.ref}^{commit}`];
34088
34319
  case "remote-configure":
34089
- if (!isAbsolute11(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
34320
+ if (!isAbsolute12(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
34090
34321
  throw new GithubGitProcessError("invalid_input");
34091
34322
  }
34092
34323
  return [
@@ -34098,7 +34329,7 @@ function tokenlessArgs(command) {
34098
34329
  `https://github.com/${command.repositoryFullName}.git`
34099
34330
  ];
34100
34331
  case "status":
34101
- if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34332
+ if (!isAbsolute12(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
34102
34333
  return [
34103
34334
  "-C",
34104
34335
  command.repositoryPath,
@@ -34128,7 +34359,7 @@ function createGithubGitBridge(input) {
34128
34359
  })();
34129
34360
  const requireBridge = async (value) => {
34130
34361
  const current = await roots();
34131
- if (!isAbsolute11(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
34362
+ if (!isAbsolute12(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
34132
34363
  const real = await requireRealDirectory2(value, "git bridge");
34133
34364
  assertBelow2(current.bridges, real, "git bridge");
34134
34365
  if (real !== value) throw new GithubGitProcessError("invalid_input");
@@ -34138,9 +34369,9 @@ function createGithubGitBridge(input) {
34138
34369
  async createPrivateBridge() {
34139
34370
  if (closed) throw new GithubGitProcessError("cancelled");
34140
34371
  const current = await roots();
34141
- const path = join12(current.bridges, `${randomUUID8()}.git`);
34372
+ const path = join14(current.bridges, `${randomUUID8()}.git`);
34142
34373
  assertBelow2(current.bridges, path, "git bridge");
34143
- await mkdir7(path, { mode: DIRECTORY_MODE2 });
34374
+ await mkdir8(path, { mode: DIRECTORY_MODE2 });
34144
34375
  await chmod4(path, DIRECTORY_MODE2);
34145
34376
  try {
34146
34377
  await runGit(
@@ -34156,16 +34387,16 @@ function createGithubGitBridge(input) {
34156
34387
  );
34157
34388
  const real = await requireRealDirectory2(path, "git bridge");
34158
34389
  assertBelow2(current.bridges, real, "git bridge");
34159
- const hooks = join12(real, "hooks");
34160
- await rm7(hooks, { recursive: true, force: true });
34161
- 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 });
34162
34393
  await chmod4(hooks, DIRECTORY_MODE2);
34163
- const config2 = join12(real, "config");
34394
+ const config2 = join14(real, "config");
34164
34395
  await chmod4(config2, 384);
34165
34396
  active.add(real);
34166
34397
  return real;
34167
34398
  } catch (error52) {
34168
- await rm7(path, { recursive: true, force: true }).catch(() => {
34399
+ await rm8(path, { recursive: true, force: true }).catch(() => {
34169
34400
  });
34170
34401
  throw error52;
34171
34402
  }
@@ -34259,7 +34490,7 @@ function createGithubGitBridge(input) {
34259
34490
  },
34260
34491
  async destroyPrivateBridge(path) {
34261
34492
  const bridge = await requireBridge(path);
34262
- await rm7(bridge, { recursive: true, force: true });
34493
+ await rm8(bridge, { recursive: true, force: true });
34263
34494
  active.delete(bridge);
34264
34495
  credentialed2.delete(bridge);
34265
34496
  },
@@ -34267,7 +34498,7 @@ function createGithubGitBridge(input) {
34267
34498
  if (closed) return;
34268
34499
  closed = true;
34269
34500
  const paths = [...active];
34270
- 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 })));
34271
34502
  active.clear();
34272
34503
  credentialed2.clear();
34273
34504
  }
@@ -34608,8 +34839,8 @@ function createRepositoryTools(runtime) {
34608
34839
 
34609
34840
  // src/tool-packs/github/workspace.ts
34610
34841
  import { randomUUID as randomUUID9 } from "node:crypto";
34611
- 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";
34612
- 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";
34613
34844
  var SAFE_LOCAL_ID = /^[A-Za-z0-9_-]{1,200}$/;
34614
34845
  var FULL_NAME2 = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
34615
34846
  var DIRECTORY_MODE3 = 448;
@@ -34627,7 +34858,7 @@ function hasControlCharacter2(value) {
34627
34858
  }
34628
34859
  function assertBelow3(parent, child, label) {
34629
34860
  const path = relative7(parent, child);
34630
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
34861
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute13(path)) {
34631
34862
  throw new Error(`${label} escaped the task workspace`);
34632
34863
  }
34633
34864
  }
@@ -34646,10 +34877,10 @@ async function requireRealDirectory3(path, label) {
34646
34877
  return real;
34647
34878
  }
34648
34879
  async function createOrRequirePrivateDirectory(parent, name, label) {
34649
- const path = join13(parent, name);
34880
+ const path = join15(parent, name);
34650
34881
  assertBelow3(parent, path, label);
34651
34882
  try {
34652
- await mkdir8(path, { mode: DIRECTORY_MODE3 });
34883
+ await mkdir9(path, { mode: DIRECTORY_MODE3 });
34653
34884
  } catch (error52) {
34654
34885
  if (error52.code !== "EEXIST") throw error52;
34655
34886
  }
@@ -34729,8 +34960,8 @@ async function createGithubWorkspaceService(input) {
34729
34960
  if (expectedFullName !== void 0 && repository.fullName !== expectedFullName) {
34730
34961
  throw new Error("GitHub repository name does not match this task grant");
34731
34962
  }
34732
- const destination = join13(repositoriesRoot, parsed.data);
34733
- const metadataPath = join13(metadataRoot, `${parsed.data}.json`);
34963
+ const destination = join15(repositoriesRoot, parsed.data);
34964
+ const metadataPath = join15(metadataRoot, `${parsed.data}.json`);
34734
34965
  if (!await pathExists(destination) || !await pathExists(metadataPath)) {
34735
34966
  throw new Error("GitHub repository workspace has not been prepared");
34736
34967
  }
@@ -34747,14 +34978,14 @@ async function createGithubWorkspaceService(input) {
34747
34978
  return real;
34748
34979
  };
34749
34980
  const cloneRepository = async (clone2) => {
34750
- const destination = join13(repositoriesRoot, clone2.repositoryId);
34751
- const metadataPath = join13(metadataRoot, `${clone2.repositoryId}.json`);
34981
+ const destination = join15(repositoriesRoot, clone2.repositoryId);
34982
+ const metadataPath = join15(metadataRoot, `${clone2.repositoryId}.json`);
34752
34983
  assertBelow3(repositoriesRoot, destination, "repository path");
34753
34984
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
34754
34985
  if (await pathExists(destination) || await pathExists(metadataPath)) {
34755
34986
  throw new Error("GitHub repository workspace already exists or is inconsistent");
34756
34987
  }
34757
- const temporary = join13(repositoriesRoot, `.clone-${randomUUID9()}`);
34988
+ const temporary = join15(repositoriesRoot, `.clone-${randomUUID9()}`);
34758
34989
  assertBelow3(repositoriesRoot, temporary, "temporary clone");
34759
34990
  try {
34760
34991
  await input.git.clone({
@@ -34779,9 +35010,9 @@ async function createGithubWorkspaceService(input) {
34779
35010
  path: destination,
34780
35011
  ...clone2.createIntentId === void 0 ? {} : { createIntentId: clone2.createIntentId }
34781
35012
  };
34782
- const metadataTemporary = join13(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
35013
+ const metadataTemporary = join15(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
34783
35014
  assertBelow3(metadataRoot, metadataTemporary, "temporary repository metadata");
34784
- await writeFile4(metadataTemporary, `${JSON.stringify(metadata)}
35015
+ await writeFile5(metadataTemporary, `${JSON.stringify(metadata)}
34785
35016
  `, {
34786
35017
  flag: "wx",
34787
35018
  mode: FILE_MODE3
@@ -34792,11 +35023,11 @@ async function createGithubWorkspaceService(input) {
34792
35023
  try {
34793
35024
  await rename5(metadataTemporary, metadataPath);
34794
35025
  } catch (error52) {
34795
- await rm8(destination, { recursive: true, force: true });
35026
+ await rm9(destination, { recursive: true, force: true });
34796
35027
  throw error52;
34797
35028
  }
34798
35029
  } finally {
34799
- await rm8(metadataTemporary, { force: true }).catch(() => {
35030
+ await rm9(metadataTemporary, { force: true }).catch(() => {
34800
35031
  });
34801
35032
  }
34802
35033
  const path = await requireRealDirectory3(destination, "GitHub repository");
@@ -34808,14 +35039,14 @@ async function createGithubWorkspaceService(input) {
34808
35039
  headSha
34809
35040
  };
34810
35041
  } finally {
34811
- await rm8(temporary, { recursive: true, force: true }).catch(() => {
35042
+ await rm9(temporary, { recursive: true, force: true }).catch(() => {
34812
35043
  });
34813
35044
  }
34814
35045
  };
34815
35046
  const prepareRepository = async (authority) => {
34816
35047
  const { repository } = authority;
34817
- const destination = join13(repositoriesRoot, repository.repositoryId);
34818
- const metadataPath = join13(metadataRoot, `${repository.repositoryId}.json`);
35048
+ const destination = join15(repositoriesRoot, repository.repositoryId);
35049
+ const metadataPath = join15(metadataRoot, `${repository.repositoryId}.json`);
34819
35050
  assertBelow3(repositoriesRoot, destination, "repository path");
34820
35051
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
34821
35052
  return withWorkspaceLock(destination, async () => {
@@ -34980,7 +35211,7 @@ async function createGithubWorkspaceService(input) {
34980
35211
  throw new Error("GitHub created repository is outside this installation");
34981
35212
  }
34982
35213
  parseGitRef(cloneInput.repository.defaultBranch, "default branch");
34983
- return withWorkspaceLock(join13(repositoriesRoot, repositoryId2), async () => {
35214
+ return withWorkspaceLock(join15(repositoriesRoot, repositoryId2), async () => {
34984
35215
  const prepared = await cloneRepository({
34985
35216
  repositoryId: repositoryId2,
34986
35217
  fullName: cloneInput.repository.fullName,
@@ -37104,8 +37335,8 @@ function createCommsToolPacks(grants, context) {
37104
37335
  }
37105
37336
 
37106
37337
  // src/runners/attachments.ts
37107
- import { mkdir as mkdir9, writeFile as writeFile5 } from "node:fs/promises";
37108
- 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";
37109
37340
  var WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
37110
37341
  function sanitizeAttachmentFileName(name) {
37111
37342
  const base = name.split(/[/\\]/).pop() ?? "";
@@ -37134,10 +37365,10 @@ async function materializeAttachments(task, taskRoot) {
37134
37365
  `attached file "${attachment.name}" arrived incomplete (${bytes.byteLength} of ${attachment.size} bytes)`
37135
37366
  );
37136
37367
  }
37137
- const directory = join14(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
37138
- await mkdir9(directory, { recursive: true });
37139
- const path = join14(directory, sanitizeAttachmentFileName(attachment.name));
37140
- 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);
37141
37372
  materialized.push({
37142
37373
  path,
37143
37374
  name: attachment.name,
@@ -38154,7 +38385,7 @@ function createAskUserServer() {
38154
38385
  }
38155
38386
 
38156
38387
  // src/runners/runner-env.ts
38157
- import { delimiter as delimiter2, isAbsolute as isAbsolute13 } from "node:path";
38388
+ import { delimiter as delimiter2, isAbsolute as isAbsolute14 } from "node:path";
38158
38389
  var PROVIDER_AUTHORITY_PREFIXES = ["GH_", "GITHUB_", "GIT_", "SSH_"];
38159
38390
  var HOST_AUTHORITY_PREFIXES = [
38160
38391
  "ZIXT_",
@@ -38213,7 +38444,7 @@ function inheritedValue(env, name) {
38213
38444
  }
38214
38445
  function sanitizeInheritedSearchPath(path) {
38215
38446
  if (!path) return "";
38216
- return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute13(entry)).join(delimiter2);
38447
+ return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute14(entry)).join(delimiter2);
38217
38448
  }
38218
38449
  function buildRunnerEnv(input) {
38219
38450
  const env = {};
@@ -38294,9 +38525,9 @@ function buildRunnerEnv(input) {
38294
38525
  // src/runners/github-shell-auth.ts
38295
38526
  import { execFile } from "node:child_process";
38296
38527
  import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
38297
- 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";
38298
38529
  import { createServer as createServer3 } from "node:http";
38299
- 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";
38300
38531
  var MAX_REQUEST_BYTES2 = 16 * 1024;
38301
38532
  var DIRECTORY_MODE4 = 448;
38302
38533
  var PRIVATE_FILE_MODE = 384;
@@ -38502,7 +38733,7 @@ function parseGhInvocation(body) {
38502
38733
  }
38503
38734
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
38504
38735
  const { args, cwd } = value;
38505
- 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)) {
38506
38737
  return null;
38507
38738
  }
38508
38739
  return { args, cwd };
@@ -38661,7 +38892,7 @@ function activationCredential(grant, now = Date.now()) {
38661
38892
  }
38662
38893
  function assertChildPath2(parent, child) {
38663
38894
  const path = relative8(parent, child);
38664
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute14(path)) {
38895
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute15(path)) {
38665
38896
  throw new Error("GitHub shell helper path escaped its private run directory");
38666
38897
  }
38667
38898
  }
@@ -38672,7 +38903,7 @@ function quoteForPosixShell(value) {
38672
38903
  return quoteForGitShell2(value);
38673
38904
  }
38674
38905
  async function writePrivate(path, content, executable = false) {
38675
- await writeFile6(path, content, {
38906
+ await writeFile7(path, content, {
38676
38907
  flag: "wx",
38677
38908
  mode: executable ? EXECUTABLE_FILE_MODE : PRIVATE_FILE_MODE
38678
38909
  });
@@ -38684,7 +38915,7 @@ async function prepareHelpers(input) {
38684
38915
  throw new Error("GitHub shell authentication requires a private real run directory");
38685
38916
  }
38686
38917
  const runRoot = await realpath7(input.runRoot);
38687
- const helperPath = join15(runRoot, "github-shell-git-credential.cjs");
38918
+ const helperPath = join17(runRoot, "github-shell-git-credential.cjs");
38688
38919
  assertChildPath2(runRoot, helperPath);
38689
38920
  await writePrivate(helperPath, GIT_HELPER_SOURCE);
38690
38921
  if (!input.ghExecutablePath) {
@@ -38695,14 +38926,14 @@ async function prepareHelpers(input) {
38695
38926
  wrapperSourcePath: null
38696
38927
  };
38697
38928
  }
38698
- const shellToolsDirectory = join15(runRoot, "shell-tools");
38929
+ const shellToolsDirectory = join17(runRoot, "shell-tools");
38699
38930
  assertChildPath2(runRoot, shellToolsDirectory);
38700
- await mkdir10(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
38931
+ await mkdir11(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
38701
38932
  await chmod6(shellToolsDirectory, DIRECTORY_MODE4);
38702
- const wrapperSourcePath = join15(runRoot, "github-shell-gh-wrapper.cjs");
38933
+ const wrapperSourcePath = join17(runRoot, "github-shell-gh-wrapper.cjs");
38703
38934
  assertChildPath2(runRoot, wrapperSourcePath);
38704
38935
  await writePrivate(wrapperSourcePath, GH_WRAPPER_SOURCE);
38705
- const wrapperPath = join15(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
38936
+ const wrapperPath = join17(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
38706
38937
  assertChildPath2(runRoot, wrapperPath);
38707
38938
  const launcher = process.platform === "win32" ? `@"${process.execPath.replaceAll('"', '""')}" "${wrapperSourcePath.replaceAll('"', '""')}" %*\r
38708
38939
  ` : `#!/bin/sh
@@ -38925,7 +39156,7 @@ password=${credential.accessToken}
38925
39156
  }
38926
39157
 
38927
39158
  // src/runners/working-context.ts
38928
- import { spawn as spawn8 } from "node:child_process";
39159
+ import { spawn as spawn9 } from "node:child_process";
38929
39160
  import { resolve as resolve9 } from "node:path";
38930
39161
  var COMMAND_TIMEOUT_MS = 5e3;
38931
39162
  var OUTPUT_LIMIT_BYTES = 128 * 1024;
@@ -39056,7 +39287,7 @@ async function stopWorkingContextCommand(child, childExited, options = {}) {
39056
39287
  function run(command, args, cwd, env, signal) {
39057
39288
  if (signal?.aborted) return Promise.resolve(null);
39058
39289
  return new Promise((resolvePromise) => {
39059
- const child = spawn8(command, [...args], {
39290
+ const child = spawn9(command, [...args], {
39060
39291
  cwd,
39061
39292
  env: { ...env, GIT_OPTIONAL_LOCKS: "0" },
39062
39293
  detached: process.platform !== "win32",
@@ -39496,7 +39727,7 @@ async function settlesWithin(promise2, timeoutMs) {
39496
39727
  }
39497
39728
  }
39498
39729
  function defaultRunnerWorkspaceRoot() {
39499
- return join16(homedir6(), ".zixt", "workspaces");
39730
+ return join18(homedir7(), ".zixt", "workspaces");
39500
39731
  }
39501
39732
  function defaultRunnerArtifactRoot() {
39502
39733
  return defaultRunArtifactRoot();
@@ -39545,7 +39776,7 @@ function createCliRunner(adapter, opts = {}) {
39545
39776
  const prefixArgs = opts.commandPrefixArgs ?? [];
39546
39777
  const maxWallTimeMs = opts.maxWallTimeMs;
39547
39778
  const workspaceRoot = opts.workspaceRoot ?? defaultRunnerWorkspaceRoot();
39548
- 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"));
39549
39780
  const runRegistryRoot2 = opts.runRegistryRoot ?? defaultRunRegistryRoot();
39550
39781
  const createArtifacts = opts.createArtifacts ?? createRunArtifacts;
39551
39782
  const toolPackRegistry2 = opts.toolPackRegistry ?? createDefaultToolPackRegistry();
@@ -39563,7 +39794,7 @@ function createCliRunner(adapter, opts = {}) {
39563
39794
  };
39564
39795
  const askUserServer = createAskUserServer();
39565
39796
  const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
39566
- 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;
39567
39798
  let safetyFailure;
39568
39799
  return async (task) => {
39569
39800
  if (safetyFailure) {
@@ -39603,8 +39834,8 @@ function createCliRunner(adapter, opts = {}) {
39603
39834
  usage: { inputTokens: 0, outputTokens: 0 }
39604
39835
  };
39605
39836
  }
39606
- const taskRoot = join16(workspaceRoot, task.agentId);
39607
- await mkdir11(taskRoot, { recursive: true });
39837
+ const taskRoot = join18(workspaceRoot, task.agentId);
39838
+ await mkdir12(taskRoot, { recursive: true });
39608
39839
  if (task.cancelledNow()) return cancelledBeforeRun();
39609
39840
  const configuredWorkspace = task.spec.workspace;
39610
39841
  let cwd = taskRoot;
@@ -39670,7 +39901,10 @@ function createCliRunner(adapter, opts = {}) {
39670
39901
  let terminalOutcomeProducedUnderAuthority = false;
39671
39902
  let preparedTerminalOutcome;
39672
39903
  try {
39673
- const resolvedCommand = await resolveTrustedCliCommand(command, trustedCommandOptions);
39904
+ const resolvedCommand = await resolveRunnerCommand(command, adapter.type, {
39905
+ resolution: trustedCommandOptions,
39906
+ probe: true
39907
+ });
39674
39908
  const resolvedWindowsComspec = windowsComspecCandidate ? await resolveTrustedCliCommand(windowsComspecCandidate, trustedCommandOptions) : null;
39675
39909
  const git = await measuredGit();
39676
39910
  const githubGrant = providerGrants.find(
@@ -39940,8 +40174,8 @@ ${attachmentSection}` : prompt;
39940
40174
  let changed = false;
39941
40175
  for (const path of paths) {
39942
40176
  if (!path || path.length > 4096) continue;
39943
- const absolutePath = isAbsolute15(path) ? path : resolve10(cwd, path);
39944
- const directory = dirname9(absolutePath);
40177
+ const absolutePath = isAbsolute16(path) ? path : resolve10(cwd, path);
40178
+ const directory = dirname10(absolutePath);
39945
40179
  observedWorkingDirectories.delete(directory);
39946
40180
  observedWorkingDirectories.add(directory);
39947
40181
  while (observedWorkingDirectories.size > 19) {
@@ -40380,7 +40614,7 @@ function runCliProcess(options) {
40380
40614
  return new Promise((resolve18) => {
40381
40615
  const platform = options.platform ?? process.platform;
40382
40616
  const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID11() : void 0;
40383
- const child = options.guardian ? spawn9(
40617
+ const child = options.guardian ? spawn10(
40384
40618
  options.guardian.nodeCommand,
40385
40619
  [
40386
40620
  options.guardian.scriptPath,
@@ -40391,7 +40625,7 @@ function runCliProcess(options) {
40391
40625
  // The idle pre-assignment guardian must never load from or depend
40392
40626
  // on an untrusted Task checkout. Only the post-gate target enters
40393
40627
  // the requested working directory from its private release frame.
40394
- cwd: dirname9(options.guardian.scriptPath),
40628
+ cwd: dirname10(options.guardian.scriptPath),
40395
40629
  env: runnerGuardianEnv(process.env, containmentGateNonce),
40396
40630
  stdio: ["pipe", "pipe", "pipe"],
40397
40631
  windowsHide: true,
@@ -40672,13 +40906,13 @@ import { randomUUID as randomUUID12 } from "node:crypto";
40672
40906
 
40673
40907
  // src/runners/runtime-observation.ts
40674
40908
  import { open as open6, readdir as readdir5, realpath as realpath9 } from "node:fs/promises";
40675
- import { homedir as homedir7 } from "node:os";
40676
- import { join as join17 } from "node:path";
40909
+ import { homedir as homedir8 } from "node:os";
40910
+ import { join as join19 } from "node:path";
40677
40911
  var READ_WINDOW_BYTES = 1024 * 1024;
40678
40912
  var CATALOG_TIMEOUT_MS = 15e3;
40679
40913
  var CATALOG_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
40680
40914
  function homeFrom(env) {
40681
- return env["HOME"] || env["USERPROFILE"] || homedir7();
40915
+ return env["HOME"] || env["USERPROFILE"] || homedir8();
40682
40916
  }
40683
40917
  async function readHead(path) {
40684
40918
  let handle;
@@ -40733,9 +40967,9 @@ function displayValue(value, maxLength) {
40733
40967
  return trimmed;
40734
40968
  }
40735
40969
  function claudeTranscriptPath(input) {
40736
- 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");
40737
40971
  const slug = input.resolvedCwd.replace(/[^a-zA-Z0-9]/g, "-");
40738
- return join17(configDir, "projects", slug, `${input.sessionId}.jsonl`);
40972
+ return join19(configDir, "projects", slug, `${input.sessionId}.jsonl`);
40739
40973
  }
40740
40974
  async function readClaudeSessionEffort(input) {
40741
40975
  const resolvedCwd = await realpath9(input.cwd).catch(() => input.cwd);
@@ -40751,18 +40985,18 @@ async function readClaudeSessionEffort(input) {
40751
40985
  }
40752
40986
  async function newestDirectories(root, limit) {
40753
40987
  const entries = await readdir5(root, { withFileTypes: true }).catch(() => []);
40754
- 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));
40755
40989
  }
40756
40990
  async function findCodexRolloutPath(input) {
40757
- const codexHome = input.env["CODEX_HOME"] || join17(homeFrom(input.env), ".codex");
40758
- const sessions = join17(codexHome, "sessions");
40991
+ const codexHome = input.env["CODEX_HOME"] || join19(homeFrom(input.env), ".codex");
40992
+ const sessions = join19(codexHome, "sessions");
40759
40993
  const suffix = `-${input.threadId}.jsonl`;
40760
40994
  for (const year of await newestDirectories(sessions, 2)) {
40761
40995
  for (const month of await newestDirectories(year, 2)) {
40762
40996
  for (const day of await newestDirectories(month, 3)) {
40763
40997
  const files = await readdir5(day).catch(() => []);
40764
40998
  const match = files.find((name) => name.endsWith(suffix));
40765
- if (match) return join17(day, match);
40999
+ if (match) return join19(day, match);
40766
41000
  }
40767
41001
  }
40768
41002
  }
@@ -41156,18 +41390,18 @@ function improveErrorMessage(error52) {
41156
41390
  }
41157
41391
 
41158
41392
  // src/runners/codex.ts
41159
- 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";
41160
41394
  import { randomUUID as randomUUID13 } from "node:crypto";
41161
- import { homedir as homedir8 } from "node:os";
41162
- import { join as join18 } from "node:path";
41395
+ import { homedir as homedir9 } from "node:os";
41396
+ import { join as join20 } from "node:path";
41163
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.";
41164
41398
  function defaultCodexThreadIndexRoot() {
41165
- return join18(homedir8(), ".zixt", "codex-threads");
41399
+ return join20(homedir9(), ".zixt", "codex-threads");
41166
41400
  }
41167
41401
  var SAFE_SEGMENT3 = /^[A-Za-z0-9_-]{1,200}$/;
41168
41402
  function threadIndexPath(root, agentId, sessionKey) {
41169
41403
  if (!SAFE_SEGMENT3.test(agentId) || !SAFE_SEGMENT3.test(sessionKey)) return null;
41170
- return join18(root, agentId, `${sessionKey}.json`);
41404
+ return join20(root, agentId, `${sessionKey}.json`);
41171
41405
  }
41172
41406
  async function readThreadId(path) {
41173
41407
  try {
@@ -41271,7 +41505,7 @@ ${value}` : value;
41271
41505
  const recordedThreadId = indexPath ? await readThreadId(indexPath) : null;
41272
41506
  const rememberThread = (threadId) => {
41273
41507
  if (!indexPath) return;
41274
- 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(() => {
41275
41509
  });
41276
41510
  };
41277
41511
  const observeRuntime = (threadId) => {
@@ -41734,9 +41968,9 @@ function improveCodexErrorMessage(error52) {
41734
41968
  }
41735
41969
 
41736
41970
  // src/runners/git-preflight.ts
41737
- import { spawn as spawn10 } from "node:child_process";
41971
+ import { spawn as spawn11 } from "node:child_process";
41738
41972
  import { realpath as realpath10 } from "node:fs/promises";
41739
- import { isAbsolute as isAbsolute16, resolve as resolve11 } from "node:path";
41973
+ import { isAbsolute as isAbsolute17, resolve as resolve11 } from "node:path";
41740
41974
  var OUTPUT_LIMIT = 8192;
41741
41975
  var DEFAULT_TIMEOUT_MS4 = 1e4;
41742
41976
  var VERSION_PATTERN = /^git version [^\r\n]{1,108}$/;
@@ -41752,7 +41986,7 @@ function unavailable(error52, checkedAt, executablePath = null) {
41752
41986
  async function preflightGit(options = {}) {
41753
41987
  const checkedAt = (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
41754
41988
  const configured = options.command;
41755
- if (configured !== void 0 && !isAbsolute16(configured)) {
41989
+ if (configured !== void 0 && !isAbsolute17(configured)) {
41756
41990
  return unavailable("configured git command must be an absolute file", checkedAt);
41757
41991
  }
41758
41992
  const trustedCwd = await realpath10(resolve11(options.trustedCwd ?? process.cwd())).catch(() => null);
@@ -41783,7 +42017,7 @@ async function preflightGit(options = {}) {
41783
42017
  }
41784
42018
  async function runVersionProbe(input) {
41785
42019
  return new Promise((resolvePromise) => {
41786
- const child = spawn10(input.executablePath, input.args, {
42020
+ const child = spawn11(input.executablePath, input.args, {
41787
42021
  cwd: input.cwd,
41788
42022
  env: {
41789
42023
  ...process.env.SystemRoot ? { SystemRoot: process.env.SystemRoot } : {},
@@ -41852,7 +42086,7 @@ async function preflightClaudeCode(options = {}) {
41852
42086
  const command = options.command ?? "claude";
41853
42087
  const prefixArgs = options.commandPrefixArgs ?? [];
41854
42088
  const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
41855
- const trustedCommand = await resolveTrustedCliCommand(command);
42089
+ const trustedCommand = await resolveRunnerCommand(command, "claude-code", { probe: true });
41856
42090
  if (!trustedCommand) {
41857
42091
  return {
41858
42092
  type: "claude-code",
@@ -41903,7 +42137,7 @@ async function preflightCodex(options = {}) {
41903
42137
  const command = options.command ?? "codex";
41904
42138
  const prefixArgs = options.commandPrefixArgs ?? [];
41905
42139
  const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
41906
- const trustedCommand = await resolveTrustedCliCommand(command);
42140
+ const trustedCommand = await resolveRunnerCommand(command, "codex", { probe: true });
41907
42141
  if (!trustedCommand) {
41908
42142
  return {
41909
42143
  type: "codex",
@@ -42005,11 +42239,11 @@ function run2(command, args) {
42005
42239
  }
42006
42240
 
42007
42241
  // src/linux-service.ts
42008
- import { spawn as spawn11 } from "node:child_process";
42242
+ import { spawn as spawn12 } from "node:child_process";
42009
42243
  import { constants as constants2 } from "node:fs";
42010
- import { access as access4, chmod as chmod7, mkdir as mkdir13, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
42011
- import { homedir as homedir9, userInfo } from "node:os";
42012
- 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";
42013
42247
  var SERVICE_NAME = "zixt-host.service";
42014
42248
  var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
42015
42249
  var SERVICE_STABILITY_DELAY_MS = 2e3;
@@ -42038,7 +42272,7 @@ function boundedAppend(current, chunk) {
42038
42272
  async function defaultRunCommand(command, args) {
42039
42273
  const commandEnvironment3 = systemServiceCommandEnvironment();
42040
42274
  return new Promise((resolve18) => {
42041
- const child = spawn11(command, [...args], {
42275
+ const child = spawn12(command, [...args], {
42042
42276
  stdio: ["ignore", "pipe", "pipe"],
42043
42277
  env: commandEnvironment3,
42044
42278
  windowsHide: true
@@ -42110,22 +42344,22 @@ async function defaultSyncDirectory(path) {
42110
42344
  }
42111
42345
  }
42112
42346
  async function ensureDirectory(path, mode, syncDirectory8) {
42113
- const firstCreated = await mkdir13(path, { recursive: true, mode });
42347
+ const firstCreated = await mkdir14(path, { recursive: true, mode });
42114
42348
  if (!firstCreated) return;
42115
42349
  const first = resolve12(firstCreated);
42116
42350
  const target = resolve12(path);
42117
- await syncDirectory8(dirname10(first));
42351
+ await syncDirectory8(dirname11(first));
42118
42352
  let current = first;
42119
42353
  const descendants = relative9(first, target);
42120
42354
  for (const part of descendants ? descendants.split(sep5) : []) {
42121
42355
  await syncDirectory8(current);
42122
- current = join19(current, part);
42356
+ current = join21(current, part);
42123
42357
  }
42124
42358
  }
42125
42359
  async function replacePrivateFile(path, contents, mode, syncDirectory8) {
42126
- const parent = dirname10(path);
42360
+ const parent = dirname11(path);
42127
42361
  await ensureDirectory(parent, 448, syncDirectory8);
42128
- const temporary = join19(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42362
+ const temporary = join21(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42129
42363
  const handle = await open7(temporary, "wx", mode);
42130
42364
  try {
42131
42365
  await handle.writeFile(contents, "utf8");
@@ -42136,7 +42370,7 @@ async function replacePrivateFile(path, contents, mode, syncDirectory8) {
42136
42370
  await syncDirectory8(parent);
42137
42371
  } catch (error52) {
42138
42372
  await handle.close().catch(() => void 0);
42139
- await rm9(temporary, { force: true }).catch(() => void 0);
42373
+ await rm10(temporary, { force: true }).catch(() => void 0);
42140
42374
  throw error52;
42141
42375
  }
42142
42376
  }
@@ -42169,7 +42403,7 @@ async function installLinuxService(options) {
42169
42403
  throw new Error("Linux automatic startup is available only on Linux.");
42170
42404
  }
42171
42405
  const env = options.env ?? process.env;
42172
- const home = options.home ?? homedir9();
42406
+ const home = options.home ?? homedir10();
42173
42407
  const username = oneLine(options.username ?? userInfo().username, "user name");
42174
42408
  const token2 = oneLine(options.token, "pairing code");
42175
42409
  const path = oneLine(
@@ -42177,11 +42411,11 @@ async function installLinuxService(options) {
42177
42411
  "command search path"
42178
42412
  );
42179
42413
  const cloudUrl = options.cloudUrl ? oneLine(options.cloudUrl, "Zixt Cloud address") : void 0;
42180
- const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join19(home, ".config");
42181
- const configRoot = options.serviceConfigRoot ?? join19(xdgConfigHome, "zixt");
42182
- const unitRoot = options.userUnitRoot ?? join19(xdgConfigHome, "systemd", "user");
42183
- const environmentPath = join19(configRoot, "host.env");
42184
- const unitPath = join19(unitRoot, SERVICE_NAME);
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);
42185
42419
  const installVersion = options.installVersion ?? ((version2, onFailure) => installRelease(version2, onFailure ? { onFailure } : {}));
42186
42420
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : activateInstalledRelease);
42187
42421
  const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
@@ -42227,6 +42461,7 @@ async function installLinuxService(options) {
42227
42461
  ...cloudUrl ? [`ZIXT_CLOUD_URL=${systemdEnvironmentValue(cloudUrl)}`] : [],
42228
42462
  `PATH=${systemdEnvironmentValue(path)}`,
42229
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)}`] : [],
42230
42465
  ...env.ZIXT_HOST_UPDATE_URL ? [`ZIXT_HOST_UPDATE_URL=${systemdEnvironmentValue(env.ZIXT_HOST_UPDATE_URL)}`] : [],
42231
42466
  ...env.ZIXT_HOST_VERSIONS_DIR ? [`ZIXT_HOST_VERSIONS_DIR=${systemdEnvironmentValue(env.ZIXT_HOST_VERSIONS_DIR)}`] : [],
42232
42467
  // A Machine on a private registry mirror checks ZIXT_HOST_UPDATE_URL for
@@ -42307,11 +42542,11 @@ async function installLinuxService(options) {
42307
42542
  }
42308
42543
 
42309
42544
  // src/macos-service.ts
42310
- import { spawn as spawn12 } from "node:child_process";
42545
+ import { spawn as spawn13 } from "node:child_process";
42311
42546
  import { constants as constants3 } from "node:fs";
42312
- import { access as access5, chmod as chmod8, mkdir as mkdir14, open as open8, rename as rename7, rm as rm10 } from "node:fs/promises";
42313
- import { homedir as homedir10, userInfo as userInfo2 } from "node:os";
42314
- 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";
42315
42550
  var LAUNCH_AGENT_LABEL = "ai.zixt.host";
42316
42551
  var SERVICE_STABILITY_DELAY_MS2 = 2e3;
42317
42552
  var COMMAND_TIMEOUT_MS2 = 7e4;
@@ -42335,21 +42570,21 @@ async function syncDirectory4(path) {
42335
42570
  }
42336
42571
  }
42337
42572
  async function ensureDirectory2(path, sync) {
42338
- const firstCreated = await mkdir14(path, { recursive: true, mode: 448 });
42573
+ const firstCreated = await mkdir15(path, { recursive: true, mode: 448 });
42339
42574
  if (!firstCreated) return;
42340
42575
  const first = resolve13(firstCreated);
42341
42576
  const target = resolve13(path);
42342
- await sync(dirname11(first));
42577
+ await sync(dirname12(first));
42343
42578
  let current = first;
42344
42579
  for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
42345
42580
  await sync(current);
42346
- current = join20(current, part);
42581
+ current = join22(current, part);
42347
42582
  }
42348
42583
  }
42349
42584
  async function replacePrivateFile2(path, contents, mode, sync) {
42350
- const parent = dirname11(path);
42585
+ const parent = dirname12(path);
42351
42586
  await ensureDirectory2(parent, sync);
42352
- const temporary = join20(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42587
+ const temporary = join22(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42353
42588
  const handle = await open8(temporary, "wx", mode);
42354
42589
  try {
42355
42590
  await handle.writeFile(contents, "utf8");
@@ -42360,7 +42595,7 @@ async function replacePrivateFile2(path, contents, mode, sync) {
42360
42595
  await sync(parent);
42361
42596
  } catch (error52) {
42362
42597
  await handle.close().catch(() => void 0);
42363
- await rm10(temporary, { force: true }).catch(() => void 0);
42598
+ await rm11(temporary, { force: true }).catch(() => void 0);
42364
42599
  throw error52;
42365
42600
  }
42366
42601
  }
@@ -42374,7 +42609,7 @@ function commandEnvironment(env) {
42374
42609
  }
42375
42610
  async function defaultRunCommand2(command, args, env) {
42376
42611
  return new Promise((resolveResult) => {
42377
- const child = spawn12(command, [...args], {
42612
+ const child = spawn13(command, [...args], {
42378
42613
  stdio: ["ignore", "pipe", "pipe"],
42379
42614
  env: commandEnvironment(env)
42380
42615
  });
@@ -42437,7 +42672,7 @@ async function installMacosService(options) {
42437
42672
  throw new Error("macOS automatic startup is available only on macOS.");
42438
42673
  }
42439
42674
  const env = options.env ?? process.env;
42440
- const home = options.home ?? homedir10();
42675
+ const home = options.home ?? homedir11();
42441
42676
  const uid = options.uid ?? userInfo2().uid;
42442
42677
  if (!Number.isSafeInteger(uid) || uid < 0) throw new Error("macOS user id is invalid.");
42443
42678
  const token2 = oneLine2(options.token, "pairing code");
@@ -42446,14 +42681,14 @@ async function installMacosService(options) {
42446
42681
  options.path ?? env.PATH ?? "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin",
42447
42682
  "command search path"
42448
42683
  );
42449
- const configRoot = options.configRoot ?? join20(home, "Library", "Application Support", "Zixt");
42450
- const launchAgentsRoot = options.launchAgentsRoot ?? join20(home, "Library", "LaunchAgents");
42451
- const logRoot = options.logRoot ?? join20(home, "Library", "Logs", "Zixt");
42452
- const configPath = join20(configRoot, "host.env");
42453
- const launcherPath = join20(configRoot, "host-launcher.sh");
42454
- const plistPath = join20(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
42455
- const stdoutPath = join20(logRoot, "host.log");
42456
- const stderrPath = join20(logRoot, "host-error.log");
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");
42457
42692
  const installVersion = options.installVersion ?? ((version2, onFailure) => installRelease(version2, onFailure ? { onFailure } : {}));
42458
42693
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
42459
42694
  const resolveCommand = options.resolveCommand ?? (async () => defaultResolveCommand2());
@@ -42483,6 +42718,7 @@ async function installMacosService(options) {
42483
42718
  `PATH=${shellValue(path)}`,
42484
42719
  "ZIXT_HOST_SERVICE_MANAGER=launchd",
42485
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)}`] : [],
42486
42722
  ...env.ZIXT_HOST_UPDATE_URL ? [`ZIXT_HOST_UPDATE_URL=${shellValue(env.ZIXT_HOST_UPDATE_URL)}`] : [],
42487
42723
  ...env.ZIXT_HOST_VERSIONS_DIR ? [`ZIXT_HOST_VERSIONS_DIR=${shellValue(env.ZIXT_HOST_VERSIONS_DIR)}`] : [],
42488
42724
  // A Machine on a private registry mirror checks ZIXT_HOST_UPDATE_URL for
@@ -42547,11 +42783,11 @@ async function installMacosService(options) {
42547
42783
  }
42548
42784
 
42549
42785
  // src/windows-service.ts
42550
- import { spawn as spawn13 } from "node:child_process";
42786
+ import { spawn as spawn14 } from "node:child_process";
42551
42787
  import { constants as constants4 } from "node:fs";
42552
- import { access as access6, mkdir as mkdir15, open as open9, readFile as readFile11, rename as rename8, rm as rm11 } from "node:fs/promises";
42553
- import { homedir as homedir11 } from "node:os";
42554
- 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";
42555
42791
  var TASK_NAME = "Zixt Host";
42556
42792
  var COMMAND_TIMEOUT_MS3 = 7e4;
42557
42793
  var SERVICE_STABILITY_DELAY_MS3 = 2e3;
@@ -42577,21 +42813,21 @@ async function syncDirectory5(path) {
42577
42813
  }
42578
42814
  }
42579
42815
  async function ensureDirectory3(path, sync) {
42580
- const firstCreated = await mkdir15(path, { recursive: true, mode: 448 });
42816
+ const firstCreated = await mkdir16(path, { recursive: true, mode: 448 });
42581
42817
  if (!firstCreated) return;
42582
42818
  const first = resolve14(firstCreated);
42583
42819
  const target = resolve14(path);
42584
- await sync(dirname12(first));
42820
+ await sync(dirname13(first));
42585
42821
  let current = first;
42586
42822
  for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
42587
42823
  await sync(current);
42588
- current = join21(current, part);
42824
+ current = join23(current, part);
42589
42825
  }
42590
42826
  }
42591
42827
  async function replacePrivateFile3(path, contents, sync, encoding = "utf8") {
42592
- const parent = dirname12(path);
42828
+ const parent = dirname13(path);
42593
42829
  await ensureDirectory3(parent, sync);
42594
- const temporary = join21(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42830
+ const temporary = join23(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42595
42831
  const handle = await open9(temporary, "wx", 384);
42596
42832
  try {
42597
42833
  await handle.writeFile(encoding === "utf16le" ? `\uFEFF${contents}` : contents, encoding);
@@ -42601,7 +42837,7 @@ async function replacePrivateFile3(path, contents, sync, encoding = "utf8") {
42601
42837
  await sync(parent);
42602
42838
  } catch (error52) {
42603
42839
  await handle.close().catch(() => void 0);
42604
- await rm11(temporary, { force: true }).catch(() => void 0);
42840
+ await rm12(temporary, { force: true }).catch(() => void 0);
42605
42841
  throw error52;
42606
42842
  }
42607
42843
  }
@@ -42612,7 +42848,7 @@ function commandEnvironment2(env) {
42612
42848
  }
42613
42849
  async function runChild(command, args, env, input) {
42614
42850
  return new Promise((resolveResult) => {
42615
- const child = spawn13(command, [...args], {
42851
+ const child = spawn14(command, [...args], {
42616
42852
  stdio: [input === void 0 ? "ignore" : "pipe", "pipe", "pipe"],
42617
42853
  env: commandEnvironment2(env),
42618
42854
  windowsHide: true
@@ -42645,8 +42881,8 @@ async function runChild(command, args, env, input) {
42645
42881
  }
42646
42882
  async function defaultResolveCommand3(name, env) {
42647
42883
  const root = env.SYSTEMROOT ?? env.WINDIR;
42648
- if (!root || !isAbsolute17(root)) return null;
42649
- 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`);
42650
42886
  return access6(candidate, constants4.X_OK).then(
42651
42887
  () => candidate,
42652
42888
  () => null
@@ -42696,6 +42932,7 @@ try {
42696
42932
  if ($config.cloudUrl) { $env:ZIXT_CLOUD_URL = $config.cloudUrl } else { Remove-Item Env:ZIXT_CLOUD_URL -ErrorAction SilentlyContinue }
42697
42933
  $env:PATH = $config.path
42698
42934
  if ($config.update) { $env:ZIXT_HOST_UPDATE = $config.update }
42935
+ if ($config.runnerAutoinstall) { $env:ZIXT_RUNNER_AUTOINSTALL = $config.runnerAutoinstall }
42699
42936
  if ($config.updateUrl) { $env:ZIXT_HOST_UPDATE_URL = $config.updateUrl }
42700
42937
  if ($config.versionsRoot) { $env:ZIXT_HOST_VERSIONS_DIR = $config.versionsRoot }
42701
42938
  if ($config.npmRegistry) { $env:NPM_CONFIG_REGISTRY = $config.npmRegistry }
@@ -42746,6 +42983,18 @@ async function defaultObserveStatus(path, generation) {
42746
42983
  return null;
42747
42984
  }
42748
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
+ }
42749
42998
  function taskXml(input) {
42750
42999
  return `<?xml version="1.0" encoding="UTF-16"?>
42751
43000
  <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
@@ -42760,8 +43009,8 @@ function taskXml(input) {
42760
43009
  <RestartOnFailure><Interval>PT1M</Interval><Count>999</Count></RestartOnFailure>
42761
43010
  </Settings>
42762
43011
  <Actions Context="ZixtUser"><Exec>
42763
- <Command>${xml2(input.powershell)}</Command>
42764
- <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>
42765
43014
  <WorkingDirectory>${xml2(input.home)}</WorkingDirectory>
42766
43015
  </Exec></Actions>
42767
43016
  </Task>
@@ -42776,19 +43025,20 @@ async function installWindowsService(options) {
42776
43025
  throw new Error("Windows automatic startup is available only on Windows.");
42777
43026
  }
42778
43027
  const env = options.env ?? process.env;
42779
- const home = options.home ?? homedir11();
43028
+ const home = options.home ?? homedir12();
42780
43029
  const localAppData = options.localAppData ?? env.LOCALAPPDATA;
42781
- if (!localAppData || !isAbsolute17(localAppData)) {
43030
+ if (!localAppData || !isAbsolute18(localAppData)) {
42782
43031
  throw new Error("Windows local application data path is unavailable.");
42783
43032
  }
42784
43033
  const token2 = oneLine3(options.token, "pairing code");
42785
43034
  const cloudUrl = options.cloudUrl ? oneLine3(options.cloudUrl, "Zixt Cloud address") : void 0;
42786
43035
  const path = oneLine3(options.path ?? env.PATH ?? "", "command search path");
42787
- const configRoot = options.configRoot ?? join21(localAppData, "Zixt", "Host");
42788
- const configPath = join21(configRoot, "host.json");
42789
- const launcherPath = join21(configRoot, "host-launcher.ps1");
42790
- const taskXmlPath = join21(configRoot, "host-task.xml");
42791
- const statusPath = join21(configRoot, "host-status.json");
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");
42792
43042
  const installVersion = options.installVersion ?? ((version2, onFailure) => installRelease(version2, onFailure ? { onFailure } : {}));
42793
43043
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
42794
43044
  const resolveCommand = options.resolveCommand ?? ((name) => defaultResolveCommand3(name, env));
@@ -42796,12 +43046,13 @@ async function installWindowsService(options) {
42796
43046
  const sync = options.syncDirectory ?? syncDirectory5;
42797
43047
  const delay4 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
42798
43048
  const observe = options.observeStatus ?? defaultObserveStatus;
42799
- const [powershell, schtasks, icacls] = await Promise.all([
43049
+ const [powershell, schtasks, icacls, wscript] = await Promise.all([
42800
43050
  resolveCommand("powershell"),
42801
43051
  resolveCommand("schtasks"),
42802
- resolveCommand("icacls")
43052
+ resolveCommand("icacls"),
43053
+ resolveCommand("wscript")
42803
43054
  ]);
42804
- if (!powershell || !schtasks || !icacls) {
43055
+ if (!powershell || !schtasks || !icacls || !wscript) {
42805
43056
  throw new Error("Windows Scheduled Task tools could not be found.");
42806
43057
  }
42807
43058
  const sid = options.sid ?? await defaultCurrentSid(powershell, env);
@@ -42835,6 +43086,7 @@ async function installWindowsService(options) {
42835
43086
  ...cloudUrl ? { cloudUrl } : {},
42836
43087
  path,
42837
43088
  ...env.ZIXT_HOST_UPDATE ? { update: env.ZIXT_HOST_UPDATE } : {},
43089
+ ...env.ZIXT_RUNNER_AUTOINSTALL ? { runnerAutoinstall: env.ZIXT_RUNNER_AUTOINSTALL } : {},
42838
43090
  ...env.ZIXT_HOST_UPDATE_URL ? { updateUrl: env.ZIXT_HOST_UPDATE_URL } : {},
42839
43091
  ...env.ZIXT_HOST_VERSIONS_DIR ? { versionsRoot: env.ZIXT_HOST_VERSIONS_DIR } : {},
42840
43092
  // A Machine on a private registry mirror checks updateUrl for releases;
@@ -42845,13 +43097,14 @@ async function installWindowsService(options) {
42845
43097
  sync
42846
43098
  );
42847
43099
  await replacePrivateFile3(launcherPath, launcherSource2(configPath, statusPath), sync);
43100
+ await replacePrivateFile3(launchShimPath, hiddenLaunchSource(powershell, launcherPath), sync);
42848
43101
  await replacePrivateFile3(
42849
43102
  taskXmlPath,
42850
- taskXml({ sid, powershell, launcherPath, home }),
43103
+ taskXml({ sid, wscript, launchShimPath, home }),
42851
43104
  sync,
42852
43105
  "utf16le"
42853
43106
  );
42854
- await rm11(statusPath, { force: true });
43107
+ await rm12(statusPath, { force: true });
42855
43108
  const acl = await run3(icacls, [
42856
43109
  configRoot,
42857
43110
  "/inheritance:r",
@@ -42861,6 +43114,13 @@ async function installWindowsService(options) {
42861
43114
  "*S-1-5-18:(OI)(CI)F"
42862
43115
  ]);
42863
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);
42864
43124
  await run3(schtasks, ["/End", "/TN", TASK_NAME]);
42865
43125
  const create = await run3(schtasks, ["/Create", "/TN", TASK_NAME, "/XML", taskXmlPath, "/F"]);
42866
43126
  if (create.code !== 0) throw commandFailure3("Installing Zixt at sign-in", create);
@@ -42884,6 +43144,7 @@ async function installWindowsService(options) {
42884
43144
  taskXmlPath,
42885
43145
  configPath,
42886
43146
  launcherPath,
43147
+ launchShimPath,
42887
43148
  statusPath,
42888
43149
  releaseEntry,
42889
43150
  currentEntry,
@@ -42903,23 +43164,23 @@ async function installSystemService(options) {
42903
43164
  }
42904
43165
 
42905
43166
  // src/terminal-outcomes.ts
42906
- 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";
42907
- import { homedir as homedir12 } from "node:os";
42908
- 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";
42909
43170
  var DIRECTORY_MODE5 = 448;
42910
43171
  var FILE_MODE4 = 384;
42911
43172
  var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
42912
43173
  var HOST_DIRECTORY = /^hst_[0-9a-f]{32}$/;
42913
43174
  var OUTCOME_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
42914
43175
  function defaultTerminalOutcomeRoot() {
42915
- return join22(homedir12(), ".zixt", "terminal-outcomes");
43176
+ return join24(homedir13(), ".zixt", "terminal-outcomes");
42916
43177
  }
42917
43178
  function hostOutcomeRoot(root, hostId) {
42918
43179
  if (!HOST_DIRECTORY.test(hostId)) throw new Error("terminal outcome Host identity is malformed");
42919
- return join22(root, hostId);
43180
+ return join24(root, hostId);
42920
43181
  }
42921
43182
  function outcomePath(root, hostId, taskId, epoch) {
42922
- return join22(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
43183
+ return join24(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
42923
43184
  }
42924
43185
  async function syncDirectory6(root) {
42925
43186
  if (process.platform === "win32") return;
@@ -42931,19 +43192,19 @@ async function syncDirectory6(root) {
42931
43192
  }
42932
43193
  }
42933
43194
  async function requirePrivateRoot(root, sync = syncDirectory6) {
42934
- const firstCreated = await mkdir16(root, { recursive: true, mode: DIRECTORY_MODE5 });
43195
+ const firstCreated = await mkdir17(root, { recursive: true, mode: DIRECTORY_MODE5 });
42935
43196
  if (firstCreated) {
42936
43197
  const first = resolve15(firstCreated);
42937
43198
  const target = resolve15(root);
42938
- await sync(dirname13(first));
43199
+ await sync(dirname14(first));
42939
43200
  let current = first;
42940
43201
  for (const part of relative12(first, target).split(sep8).filter(Boolean)) {
42941
43202
  await sync(current);
42942
- current = join22(current, part);
43203
+ current = join24(current, part);
42943
43204
  }
42944
43205
  }
42945
- const stat3 = await lstat12(root);
42946
- if (stat3.isSymbolicLink() || !stat3.isDirectory()) {
43206
+ const stat4 = await lstat12(root);
43207
+ if (stat4.isSymbolicLink() || !stat4.isDirectory()) {
42947
43208
  throw new Error("terminal outcome journal root is not a trusted directory");
42948
43209
  }
42949
43210
  await chmod9(root, DIRECTORY_MODE5);
@@ -42979,7 +43240,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
42979
43240
  } catch (error52) {
42980
43241
  if (error52.code !== "ENOENT") throw error52;
42981
43242
  }
42982
- const temporary = join22(
43243
+ const temporary = join24(
42983
43244
  scopedRoot,
42984
43245
  `.${outcome.taskId}.${outcome.epoch}.${process.pid}.${Date.now()}.${outcome.resultId}.tmp`
42985
43246
  );
@@ -42996,7 +43257,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
42996
43257
  } finally {
42997
43258
  await handle?.close().catch(() => {
42998
43259
  });
42999
- await rm12(temporary, { force: true }).catch(() => {
43260
+ await rm13(temporary, { force: true }).catch(() => {
43000
43261
  });
43001
43262
  }
43002
43263
  }
@@ -43032,9 +43293,9 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
43032
43293
  if (!match || !entry.isFile() || entry.isSymbolicLink()) {
43033
43294
  throw new Error("committed terminal outcome is not a trusted regular file");
43034
43295
  }
43035
- const path = join22(scopedRoot, entry.name);
43036
- const stat3 = await lstat12(path);
43037
- 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) {
43038
43299
  throw new Error("committed terminal outcome is not a trusted regular file");
43039
43300
  }
43040
43301
  const outcome = parseCommittedOutcome(
@@ -43065,7 +43326,7 @@ async function forgetAcknowledgedTerminalOutcomes(refs, root = defaultTerminalOu
43065
43326
  if (acknowledged.get(`${hostId}:${outcome.taskId}:${outcome.epoch}`) !== outcome.resultId) {
43066
43327
  continue;
43067
43328
  }
43068
- await rm12(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43329
+ await rm13(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43069
43330
  changedHostRoots.add(hostOutcomeRoot(root, hostId));
43070
43331
  }
43071
43332
  for (const scopedRoot of changedHostRoots) await syncDirectory6(scopedRoot);
@@ -43077,22 +43338,22 @@ async function forgetSupersededTerminalOutcomes(hostId, taskId, epoch, root = de
43077
43338
  if (scoped.hostId !== hostId) continue;
43078
43339
  const { outcome } = scoped;
43079
43340
  if (outcome.taskId !== taskId || outcome.epoch >= epoch) continue;
43080
- await rm12(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43341
+ await rm13(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
43081
43342
  removed = true;
43082
43343
  }
43083
43344
  if (removed) await syncDirectory6(hostOutcomeRoot(root, hostId));
43084
43345
  }
43085
43346
 
43086
43347
  // src/accepted-assignments.ts
43087
- 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";
43088
- import { homedir as homedir13 } from "node:os";
43089
- 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";
43090
43351
  var DIRECTORY_MODE6 = 448;
43091
43352
  var FILE_MODE5 = 384;
43092
43353
  var CLAIM_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
43093
43354
  var TASK_ID = /^tsk_[0-9a-f]{32}$/;
43094
43355
  function defaultAcceptedAssignmentRoot() {
43095
- return join23(homedir13(), ".zixt", "accepted-assignments");
43356
+ return join25(homedir14(), ".zixt", "accepted-assignments");
43096
43357
  }
43097
43358
  async function syncDirectory7(root) {
43098
43359
  if (process.platform === "win32") return;
@@ -43104,19 +43365,19 @@ async function syncDirectory7(root) {
43104
43365
  }
43105
43366
  }
43106
43367
  async function requirePrivateRoot2(root, sync = syncDirectory7) {
43107
- const firstCreated = await mkdir17(root, { recursive: true, mode: DIRECTORY_MODE6 });
43368
+ const firstCreated = await mkdir18(root, { recursive: true, mode: DIRECTORY_MODE6 });
43108
43369
  if (firstCreated) {
43109
43370
  const first = resolve16(firstCreated);
43110
43371
  const target = resolve16(root);
43111
- await sync(dirname14(first));
43372
+ await sync(dirname15(first));
43112
43373
  let current = first;
43113
43374
  for (const part of relative13(first, target).split(sep9).filter(Boolean)) {
43114
43375
  await sync(current);
43115
- current = join23(current, part);
43376
+ current = join25(current, part);
43116
43377
  }
43117
43378
  }
43118
- const stat3 = await lstat13(root);
43119
- if (stat3.isSymbolicLink() || !stat3.isDirectory()) {
43379
+ const stat4 = await lstat13(root);
43380
+ if (stat4.isSymbolicLink() || !stat4.isDirectory()) {
43120
43381
  throw new Error("accepted assignment journal root is not a trusted directory");
43121
43382
  }
43122
43383
  await chmod10(root, DIRECTORY_MODE6);
@@ -43126,7 +43387,7 @@ function claimPath(root, taskId, epoch) {
43126
43387
  if (!Number.isSafeInteger(epoch) || epoch < 1) {
43127
43388
  throw new Error("accepted assignment epoch is malformed");
43128
43389
  }
43129
- return join23(root, `${taskId}.${epoch}.json`);
43390
+ return join25(root, `${taskId}.${epoch}.json`);
43130
43391
  }
43131
43392
  async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssignmentRoot(), options = {}) {
43132
43393
  const sync = options.syncDirectory ?? syncDirectory7;
@@ -43136,7 +43397,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
43136
43397
  } catch {
43137
43398
  return false;
43138
43399
  }
43139
- const temporary = join23(
43400
+ const temporary = join25(
43140
43401
  root,
43141
43402
  `.${assignment.taskId}.${assignment.epoch}.${process.pid}.${Date.now()}.tmp`
43142
43403
  );
@@ -43156,7 +43417,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
43156
43417
  } finally {
43157
43418
  await handle?.close().catch(() => {
43158
43419
  });
43159
- await rm13(temporary, { force: true }).catch(() => {
43420
+ await rm14(temporary, { force: true }).catch(() => {
43160
43421
  });
43161
43422
  }
43162
43423
  }
@@ -43190,13 +43451,18 @@ async function forgetAcceptedAssignment(assignment, root = defaultAcceptedAssign
43190
43451
  } catch {
43191
43452
  return;
43192
43453
  }
43193
- await rm13(path, { force: true }).catch(() => {
43454
+ await rm14(path, { force: true }).catch(() => {
43194
43455
  });
43195
43456
  }
43196
43457
  async function forgetAcknowledgedAcceptedAssignments(assignments, root = defaultAcceptedAssignmentRoot()) {
43197
43458
  for (const assignment of assignments) await forgetAcceptedAssignment(assignment, root);
43198
43459
  }
43199
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
+
43200
43466
  // src/logger.ts
43201
43467
  var ANSI = {
43202
43468
  reset: "\x1B[0m",
@@ -43288,7 +43554,9 @@ function createHostLogger(options = {}) {
43288
43554
  const color = options.color ?? (process.stderr.isTTY === true && process.env.NO_COLOR === void 0);
43289
43555
  const write = options.write ?? ((line) => console.error(line));
43290
43556
  const log2 = (level, message, context) => {
43291
- 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 ?? {} });
43292
43560
  };
43293
43561
  return {
43294
43562
  info: (message, context) => log2("info", message, context),
@@ -43298,24 +43566,105 @@ function createHostLogger(options = {}) {
43298
43566
  };
43299
43567
  }
43300
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
+
43301
43649
  // src/demo-state.ts
43302
- 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";
43303
43651
  var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
43304
43652
  function resolveDemoHostStatePaths(env = process.env) {
43305
43653
  const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
43306
43654
  if (!configured) return null;
43307
43655
  const root = resolve17(configured);
43308
- if (!isAbsolute18(configured) || root === parse3(root).root) {
43656
+ if (!isAbsolute19(configured) || root === parse3(root).root) {
43309
43657
  throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
43310
43658
  }
43311
43659
  return {
43312
- runRegistryRoot: join24(root, "run-registry"),
43313
- terminalOutcomeRoot: join24(root, "terminal-outcomes"),
43314
- acceptedAssignmentRoot: join24(root, "accepted-assignments"),
43315
- runArtifactRoot: join24(root, "run-artifacts"),
43316
- browserProfileRoot: join24(root, "browser-profiles"),
43317
- runnerWorkspaceRoot: join24(root, "workspaces"),
43318
- 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")
43319
43668
  };
43320
43669
  }
43321
43670
 
@@ -43492,12 +43841,14 @@ function recordConsoleLine(line) {
43492
43841
  if (hostConsoleTail.length > 200) hostConsoleTail.shift();
43493
43842
  clientForConsole.current?.hostConsoleLine(entry);
43494
43843
  }
43844
+ var localConsoleSink = { current: null };
43495
43845
  var log = createHostLogger({
43496
43846
  ...colorOverride === void 0 ? {} : { color: colorOverride },
43497
43847
  write: (line) => {
43498
43848
  console.error(line);
43499
43849
  recordConsoleLine(line);
43500
- }
43850
+ },
43851
+ onEntry: (entry) => localConsoleSink.current?.entry(entry)
43501
43852
  });
43502
43853
  function replayConsoleLine(level, message, context) {
43503
43854
  recordConsoleLine(
@@ -43505,6 +43856,7 @@ function replayConsoleLine(level, message, context) {
43505
43856
  ...colorOverride === void 0 ? {} : { color: colorOverride }
43506
43857
  })
43507
43858
  );
43859
+ localConsoleSink.current?.entry({ at: /* @__PURE__ */ new Date(), level, message, context: context ?? {} });
43508
43860
  }
43509
43861
  if (cliOptions.help) {
43510
43862
  process.stdout.write(`${hostHelpText()}
@@ -43568,8 +43920,20 @@ var {
43568
43920
  runArtifactRoot,
43569
43921
  browserProfileRoot,
43570
43922
  runnerWorkspaceRoot,
43571
- codexThreadIndexRoot
43923
+ codexThreadIndexRoot,
43924
+ localObservabilityRoot
43572
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
+ });
43573
43937
  var disclaimableAssignments;
43574
43938
  var acceptedAssignments;
43575
43939
  var terminalOutcomes;
@@ -43611,6 +43975,23 @@ if (!token) {
43611
43975
  process.exit(DO_NOT_RESTART_EXIT_CODE);
43612
43976
  }
43613
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
+ });
43614
43995
  var gitPreflight = await preflightGit();
43615
43996
  var gitRefresh = null;
43616
43997
  var GIT_PREFLIGHT_REFRESH_MS = 4 * 6e4;
@@ -43754,12 +44135,18 @@ async function telemetry() {
43754
44135
  preflightCodex()
43755
44136
  ]);
43756
44137
  cachedRunnersAt = Date.now();
43757
- 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
+ }
43758
44144
  }
43759
44145
  const providerToolPacks = toolPackRegistry.capabilities({
43760
44146
  now: /* @__PURE__ */ new Date(),
43761
44147
  git: await currentGitPreflight()
43762
44148
  });
44149
+ publishLocalStatus();
43763
44150
  providerToolPacks.push({
43764
44151
  provider: "email",
43765
44152
  version: 1,
@@ -43786,7 +44173,7 @@ async function telemetry() {
43786
44173
  // Measured per heartbeat: free memory and free disk are only useful while
43787
44174
  // they are current, and a demo Host reports its own private root so the
43788
44175
  // number describes the filesystem its Tasks would really write to.
43789
- hardware: await machineHardware(runnerWorkspaceRoot ?? homedir14()),
44176
+ hardware: await machineHardware(runnerWorkspaceRoot ?? homedir16()),
43790
44177
  capabilities: {
43791
44178
  linearToolPack: providerToolPacks.some(
43792
44179
  (pack) => pack.provider === "linear" && pack.health === "ready"
@@ -43843,6 +44230,36 @@ var connectionContext = connectionLogContext({
43843
44230
  cloud: cloudTarget,
43844
44231
  version: HOST_VERSION
43845
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
+ }
43846
44263
  var stopUpdateWatch = () => {
43847
44264
  };
43848
44265
  var releaseParentPipeWatch = () => {
@@ -43967,6 +44384,9 @@ var client = new HostClient({
43967
44384
  switch (status) {
43968
44385
  case "connected":
43969
44386
  log.success("Connected to Zixt Cloud", connectionContext);
44387
+ localCloudState = "connected";
44388
+ localCloudConnectedAt = (/* @__PURE__ */ new Date()).toISOString();
44389
+ publishLocalStatus();
43970
44390
  if (reportedWorkerExits.length > 0) {
43971
44391
  void forgetWorkerExits(reportedWorkerExits.map(({ file: file2 }) => file2));
43972
44392
  }
@@ -43976,12 +44396,16 @@ var client = new HostClient({
43976
44396
  ...connectionContext,
43977
44397
  next: "Check the cloud and Machine pairing if this continues"
43978
44398
  });
44399
+ localCloudState = "connecting";
44400
+ publishLocalStatus();
43979
44401
  break;
43980
44402
  case "unresponsive":
43981
44403
  log.warn("Zixt Cloud stopped answering; Tasks unwound before reconnecting", {
43982
44404
  ...connectionContext,
43983
44405
  next: "Check this Machine's network path and Zixt Cloud health if this repeats"
43984
44406
  });
44407
+ localCloudState = "connecting";
44408
+ publishLocalStatus();
43985
44409
  break;
43986
44410
  case "replaced":
43987
44411
  log.warn("Another Host process took over this Machine", connectionContext);