@zixt/host 0.0.109 → 0.0.110

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 (3) hide show
  1. package/README.md +7 -2
  2. package/dist/index.js +218 -122
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -86,8 +86,13 @@ Run `zixt-host --help` for logging flags.
86
86
 
87
87
  ## Teammate browsing
88
88
 
89
- If your teammates use the live browser, install the pinned Chromium once:
89
+ On first start, Zixt checks for its exact Chromium revision and downloads it
90
+ automatically when needed. If that download fails, run the matching installer
91
+ as the same OS user that runs Zixt:
90
92
 
91
93
  ```bash
92
- npx playwright-core install chromium
94
+ npx -y playwright-core@1.61.1 install chromium
93
95
  ```
96
+
97
+ On Windows, use `npx.cmd` instead of `npx`; this works from Command Prompt and
98
+ from PowerShell even when its execution policy blocks npm's `.ps1` shim.
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ import { homedir as homedir3 } from "node:os";
28
28
  // package.json
29
29
  var package_default = {
30
30
  name: "@zixt/host",
31
- version: "0.0.109",
31
+ version: "0.0.110",
32
32
  type: "module",
33
33
  exports: {
34
34
  ".": "./src/client.ts",
@@ -30025,8 +30025,21 @@ var BrowserManager = class {
30025
30025
  };
30026
30026
 
30027
30027
  // src/browser/playwright-adapter.ts
30028
+ import { spawn as spawn6 } from "node:child_process";
30028
30029
  import { access as access3 } from "node:fs/promises";
30029
- var BROWSER_INSTALL_REMEDY = "Install the browser on this Machine: run bun run browser:install in the Zixt repo root";
30030
+ import { createRequire } from "node:module";
30031
+ import { dirname as dirname7, join as join10 } from "node:path";
30032
+ var nodeRequire = createRequire(import.meta.url);
30033
+ var playwrightCoreManifestPath = nodeRequire.resolve("playwright-core/package.json");
30034
+ var playwrightCoreRoot = dirname7(playwrightCoreManifestPath);
30035
+ var playwrightCoreVersion = nodeRequire(playwrightCoreManifestPath).version;
30036
+ if (typeof playwrightCoreVersion !== "string" || !/^\d+\.\d+\.\d+$/.test(playwrightCoreVersion)) {
30037
+ throw new Error("playwright-core package version is invalid");
30038
+ }
30039
+ var PLAYWRIGHT_CORE_VERSION = playwrightCoreVersion;
30040
+ var BROWSER_INSTALL_COMMAND = `${process.platform === "win32" ? "npx.cmd" : "npx"} -y playwright-core@${PLAYWRIGHT_CORE_VERSION} install chromium`;
30041
+ var BROWSER_INSTALL_REMEDY = `Zixt could not install its browser automatically. Run ${BROWSER_INSTALL_COMMAND} as the same user that runs Zixt, then restart Zixt.`;
30042
+ var BROWSER_INSTALL_TIMEOUT_MS = 10 * 6e4;
30030
30043
  var READ_TEXT_LIMIT = 4e4;
30031
30044
  var NAVIGATE_TIMEOUT_MS = 3e4;
30032
30045
  var ACTION_TIMEOUT_MS = 1e4;
@@ -30034,9 +30047,44 @@ var LOADING_GIVE_UP_MS = 2e4;
30034
30047
  async function loadPlaywright() {
30035
30048
  return import("playwright-core");
30036
30049
  }
30050
+ async function installChromium() {
30051
+ const cliPath = join10(playwrightCoreRoot, "cli.js");
30052
+ await new Promise((resolve18, reject3) => {
30053
+ const child = spawn6(process.execPath, [cliPath, "install", "chromium"], {
30054
+ env: process.env,
30055
+ stdio: ["ignore", "inherit", "inherit"],
30056
+ windowsHide: false
30057
+ });
30058
+ let settled = false;
30059
+ const finish = (error52) => {
30060
+ if (settled) return;
30061
+ settled = true;
30062
+ clearTimeout(timeout);
30063
+ if (error52) reject3(error52);
30064
+ else resolve18();
30065
+ };
30066
+ const timeout = setTimeout(() => {
30067
+ child.kill();
30068
+ finish(new Error("browser download did not finish within 10 minutes"));
30069
+ }, BROWSER_INSTALL_TIMEOUT_MS);
30070
+ child.once("error", (error52) => finish(error52));
30071
+ child.once("exit", (code, signal) => {
30072
+ if (code === 0) finish();
30073
+ else {
30074
+ finish(
30075
+ new Error(
30076
+ signal ? `browser installer stopped with ${signal}` : `browser installer exited with code ${code ?? "unknown"}`
30077
+ )
30078
+ );
30079
+ }
30080
+ });
30081
+ });
30082
+ }
30037
30083
  var KEY_ALIASES = { " ": "Space" };
30038
30084
  function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
30039
30085
  const load = dependencies.loadPlaywright ?? loadPlaywright;
30086
+ const install = dependencies.installChromium ?? installChromium;
30087
+ let installation = null;
30040
30088
  const runtimes = /* @__PURE__ */ new Map();
30041
30089
  const runtimeLocks = /* @__PURE__ */ new Map();
30042
30090
  const withRuntimeLock = (profileDir, work) => {
@@ -30080,15 +30128,48 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
30080
30128
  throw error52;
30081
30129
  }
30082
30130
  });
30131
+ const measureCapability = async () => {
30132
+ try {
30133
+ const playwright = await load();
30134
+ const executable = playwright.chromium.executablePath();
30135
+ if (!executable) return { status: "unavailable", error: BROWSER_INSTALL_REMEDY };
30136
+ await access3(executable);
30137
+ return { status: "ok" };
30138
+ } catch {
30139
+ return { status: "unavailable", error: BROWSER_INSTALL_REMEDY };
30140
+ }
30141
+ };
30083
30142
  return {
30084
30143
  kind: "playwright",
30085
30144
  async capability() {
30145
+ const measured = await measureCapability();
30146
+ if (measured.status === "ok") return measured;
30147
+ if (!installation) {
30148
+ dependencies.onInstallEvent?.({ state: "started" });
30149
+ const attempt = (async () => {
30150
+ await install();
30151
+ const installed = await measureCapability();
30152
+ if (installed.status !== "ok") {
30153
+ throw new Error("the browser executable is still unavailable after installation");
30154
+ }
30155
+ return installed;
30156
+ })();
30157
+ const tracked = attempt.then((installed) => {
30158
+ dependencies.onInstallEvent?.({ state: "completed" });
30159
+ return installed;
30160
+ }).catch((error52) => {
30161
+ dependencies.onInstallEvent?.({
30162
+ state: "failed",
30163
+ error: error52 instanceof Error ? error52.message : "unknown browser installation error"
30164
+ });
30165
+ throw error52;
30166
+ }).finally(() => {
30167
+ if (installation === tracked) installation = null;
30168
+ });
30169
+ installation = tracked;
30170
+ }
30086
30171
  try {
30087
- const playwright = await load();
30088
- const executable = playwright.chromium.executablePath();
30089
- if (!executable) return { status: "unavailable", error: BROWSER_INSTALL_REMEDY };
30090
- await access3(executable);
30091
- return { status: "ok" };
30172
+ return await installation;
30092
30173
  } catch {
30093
30174
  return { status: "unavailable", error: BROWSER_INSTALL_REMEDY };
30094
30175
  }
@@ -30598,11 +30679,11 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
30598
30679
  }
30599
30680
 
30600
30681
  // src/runners/cli-runner.ts
30601
- import { spawn as spawn8 } from "node:child_process";
30682
+ import { spawn as spawn9 } from "node:child_process";
30602
30683
  import { randomUUID as randomUUID11 } from "node:crypto";
30603
30684
  import { lstat as lstat11, mkdir as mkdir11, realpath as realpath8 } from "node:fs/promises";
30604
30685
  import { homedir as homedir6 } from "node:os";
30605
- import { dirname as dirname8, isAbsolute as isAbsolute15, join as join15, resolve as resolve10 } from "node:path";
30686
+ import { dirname as dirname9, isAbsolute as isAbsolute15, join as join16, resolve as resolve10 } from "node:path";
30606
30687
 
30607
30688
  // src/tool-packs/browser/authentication-wall.ts
30608
30689
  var AUTH_PATH_SEGMENT = /(?:^|\/)(?:log[-_]?in|sign[-_]?in|sso|saml|auth|authorize|authenticate|oauth2?|session\/new|checkpoint)(?:\/|$)/i;
@@ -33420,16 +33501,16 @@ function createGithubPushOrchestrator(input) {
33420
33501
  }
33421
33502
 
33422
33503
  // src/tool-packs/github/git-bridge.ts
33423
- import { spawn as spawn6 } from "node:child_process";
33504
+ import { spawn as spawn7 } from "node:child_process";
33424
33505
  import { randomUUID as randomUUID8 } from "node:crypto";
33425
33506
  import { chmod as chmod4, lstat as lstat8, mkdir as mkdir7, realpath as realpath5, rm as rm7 } from "node:fs/promises";
33426
- import { dirname as dirname7, isAbsolute as isAbsolute11, join as join11, relative as relative6 } from "node:path";
33507
+ import { dirname as dirname8, isAbsolute as isAbsolute11, join as join12, relative as relative6 } from "node:path";
33427
33508
 
33428
33509
  // src/tool-packs/github/git-credential-broker.ts
33429
33510
  import { createServer } from "node:http";
33430
33511
  import { randomBytes, randomUUID as randomUUID7, timingSafeEqual } from "node:crypto";
33431
33512
  import { chmod as chmod3, lstat as lstat7, realpath as realpath4, writeFile as writeFile3 } from "node:fs/promises";
33432
- import { isAbsolute as isAbsolute10, join as join10, relative as relative5 } from "node:path";
33513
+ import { isAbsolute as isAbsolute10, join as join11, relative as relative5 } from "node:path";
33433
33514
  var MAX_REQUEST_BYTES = 16 * 1024;
33434
33515
  var FILE_MODE2 = 384;
33435
33516
  var HELPER_SOURCE = String.raw`'use strict';
@@ -33558,7 +33639,7 @@ async function createGithubGitCredentialBroker(input) {
33558
33639
  throw new Error("Git credential broker requires a private real run directory");
33559
33640
  }
33560
33641
  const runRoot = await realpath4(input.runArtifactsRoot);
33561
- const helperPath = join10(runRoot, `git-credential-${randomUUID7()}.cjs`);
33642
+ const helperPath = join11(runRoot, `git-credential-${randomUUID7()}.cjs`);
33562
33643
  assertChildPath(runRoot, helperPath);
33563
33644
  await writeFile3(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
33564
33645
  await chmod3(helperPath, FILE_MODE2);
@@ -33674,7 +33755,7 @@ async function requireRealDirectory2(path, label) {
33674
33755
  async function validateTokenlessPaths(command) {
33675
33756
  if (command.kind === "clone-from-bridge") {
33676
33757
  if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
33677
- const parent = await requireRealDirectory2(dirname7(command.destination), "clone parent");
33758
+ const parent = await requireRealDirectory2(dirname8(command.destination), "clone parent");
33678
33759
  assertBelow2(parent, command.destination, "clone destination");
33679
33760
  const destination = await lstat8(command.destination).catch((error52) => {
33680
33761
  if (error52.code === "ENOENT") return null;
@@ -33770,7 +33851,7 @@ async function runGit(input, args, env) {
33770
33851
  throw new GithubGitProcessError("invalid_input");
33771
33852
  }
33772
33853
  return new Promise((resolvePromise, rejectPromise) => {
33773
- const child = spawn6(input.executablePath, [...input.commandPrefixArgs ?? [], ...args], {
33854
+ const child = spawn7(input.executablePath, [...input.commandPrefixArgs ?? [], ...args], {
33774
33855
  cwd: input.trustedCwd,
33775
33856
  env,
33776
33857
  shell: false,
@@ -33962,7 +34043,7 @@ function createGithubGitBridge(input) {
33962
34043
  async createPrivateBridge() {
33963
34044
  if (closed) throw new GithubGitProcessError("cancelled");
33964
34045
  const current = await roots();
33965
- const path = join11(current.bridges, `${randomUUID8()}.git`);
34046
+ const path = join12(current.bridges, `${randomUUID8()}.git`);
33966
34047
  assertBelow2(current.bridges, path, "git bridge");
33967
34048
  await mkdir7(path, { mode: DIRECTORY_MODE2 });
33968
34049
  await chmod4(path, DIRECTORY_MODE2);
@@ -33980,11 +34061,11 @@ function createGithubGitBridge(input) {
33980
34061
  );
33981
34062
  const real = await requireRealDirectory2(path, "git bridge");
33982
34063
  assertBelow2(current.bridges, real, "git bridge");
33983
- const hooks = join11(real, "hooks");
34064
+ const hooks = join12(real, "hooks");
33984
34065
  await rm7(hooks, { recursive: true, force: true });
33985
34066
  await mkdir7(hooks, { mode: DIRECTORY_MODE2 });
33986
34067
  await chmod4(hooks, DIRECTORY_MODE2);
33987
- const config2 = join11(real, "config");
34068
+ const config2 = join12(real, "config");
33988
34069
  await chmod4(config2, 384);
33989
34070
  active.add(real);
33990
34071
  return real;
@@ -34433,7 +34514,7 @@ function createRepositoryTools(runtime) {
34433
34514
  // src/tool-packs/github/workspace.ts
34434
34515
  import { randomUUID as randomUUID9 } from "node:crypto";
34435
34516
  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";
34436
- import { isAbsolute as isAbsolute12, join as join12, relative as relative7, resolve as resolve8 } from "node:path";
34517
+ import { isAbsolute as isAbsolute12, join as join13, relative as relative7, resolve as resolve8 } from "node:path";
34437
34518
  var SAFE_LOCAL_ID = /^[A-Za-z0-9_-]{1,200}$/;
34438
34519
  var FULL_NAME2 = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
34439
34520
  var DIRECTORY_MODE3 = 448;
@@ -34470,7 +34551,7 @@ async function requireRealDirectory3(path, label) {
34470
34551
  return real;
34471
34552
  }
34472
34553
  async function createOrRequirePrivateDirectory(parent, name, label) {
34473
- const path = join12(parent, name);
34554
+ const path = join13(parent, name);
34474
34555
  assertBelow3(parent, path, label);
34475
34556
  try {
34476
34557
  await mkdir8(path, { mode: DIRECTORY_MODE3 });
@@ -34553,8 +34634,8 @@ async function createGithubWorkspaceService(input) {
34553
34634
  if (expectedFullName !== void 0 && repository.fullName !== expectedFullName) {
34554
34635
  throw new Error("GitHub repository name does not match this task grant");
34555
34636
  }
34556
- const destination = join12(repositoriesRoot, parsed.data);
34557
- const metadataPath = join12(metadataRoot, `${parsed.data}.json`);
34637
+ const destination = join13(repositoriesRoot, parsed.data);
34638
+ const metadataPath = join13(metadataRoot, `${parsed.data}.json`);
34558
34639
  if (!await pathExists(destination) || !await pathExists(metadataPath)) {
34559
34640
  throw new Error("GitHub repository workspace has not been prepared");
34560
34641
  }
@@ -34571,14 +34652,14 @@ async function createGithubWorkspaceService(input) {
34571
34652
  return real;
34572
34653
  };
34573
34654
  const cloneRepository = async (clone2) => {
34574
- const destination = join12(repositoriesRoot, clone2.repositoryId);
34575
- const metadataPath = join12(metadataRoot, `${clone2.repositoryId}.json`);
34655
+ const destination = join13(repositoriesRoot, clone2.repositoryId);
34656
+ const metadataPath = join13(metadataRoot, `${clone2.repositoryId}.json`);
34576
34657
  assertBelow3(repositoriesRoot, destination, "repository path");
34577
34658
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
34578
34659
  if (await pathExists(destination) || await pathExists(metadataPath)) {
34579
34660
  throw new Error("GitHub repository workspace already exists or is inconsistent");
34580
34661
  }
34581
- const temporary = join12(repositoriesRoot, `.clone-${randomUUID9()}`);
34662
+ const temporary = join13(repositoriesRoot, `.clone-${randomUUID9()}`);
34582
34663
  assertBelow3(repositoriesRoot, temporary, "temporary clone");
34583
34664
  try {
34584
34665
  await input.git.clone({
@@ -34603,7 +34684,7 @@ async function createGithubWorkspaceService(input) {
34603
34684
  path: destination,
34604
34685
  ...clone2.createIntentId === void 0 ? {} : { createIntentId: clone2.createIntentId }
34605
34686
  };
34606
- const metadataTemporary = join12(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
34687
+ const metadataTemporary = join13(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
34607
34688
  assertBelow3(metadataRoot, metadataTemporary, "temporary repository metadata");
34608
34689
  await writeFile4(metadataTemporary, `${JSON.stringify(metadata)}
34609
34690
  `, {
@@ -34638,8 +34719,8 @@ async function createGithubWorkspaceService(input) {
34638
34719
  };
34639
34720
  const prepareRepository = async (authority) => {
34640
34721
  const { repository } = authority;
34641
- const destination = join12(repositoriesRoot, repository.repositoryId);
34642
- const metadataPath = join12(metadataRoot, `${repository.repositoryId}.json`);
34722
+ const destination = join13(repositoriesRoot, repository.repositoryId);
34723
+ const metadataPath = join13(metadataRoot, `${repository.repositoryId}.json`);
34643
34724
  assertBelow3(repositoriesRoot, destination, "repository path");
34644
34725
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
34645
34726
  return withWorkspaceLock(destination, async () => {
@@ -34804,7 +34885,7 @@ async function createGithubWorkspaceService(input) {
34804
34885
  throw new Error("GitHub created repository is outside this installation");
34805
34886
  }
34806
34887
  parseGitRef(cloneInput.repository.defaultBranch, "default branch");
34807
- return withWorkspaceLock(join12(repositoriesRoot, repositoryId2), async () => {
34888
+ return withWorkspaceLock(join13(repositoriesRoot, repositoryId2), async () => {
34808
34889
  const prepared = await cloneRepository({
34809
34890
  repositoryId: repositoryId2,
34810
34891
  fullName: cloneInput.repository.fullName,
@@ -36929,7 +37010,7 @@ function createCommsToolPacks(grants, context) {
36929
37010
 
36930
37011
  // src/runners/attachments.ts
36931
37012
  import { mkdir as mkdir9, writeFile as writeFile5 } from "node:fs/promises";
36932
- import { join as join13 } from "node:path";
37013
+ import { join as join14 } from "node:path";
36933
37014
  var WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
36934
37015
  function sanitizeAttachmentFileName(name) {
36935
37016
  const base = name.split(/[/\\]/).pop() ?? "";
@@ -36958,9 +37039,9 @@ async function materializeAttachments(task, taskRoot) {
36958
37039
  `attached file "${attachment.name}" arrived incomplete (${bytes.byteLength} of ${attachment.size} bytes)`
36959
37040
  );
36960
37041
  }
36961
- const directory = join13(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
37042
+ const directory = join14(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
36962
37043
  await mkdir9(directory, { recursive: true });
36963
- const path = join13(directory, sanitizeAttachmentFileName(attachment.name));
37044
+ const path = join14(directory, sanitizeAttachmentFileName(attachment.name));
36964
37045
  await writeFile5(path, bytes);
36965
37046
  materialized.push({
36966
37047
  path,
@@ -38119,7 +38200,7 @@ import { execFile } from "node:child_process";
38119
38200
  import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
38120
38201
  import { chmod as chmod6, lstat as lstat10, mkdir as mkdir10, realpath as realpath7, writeFile as writeFile6 } from "node:fs/promises";
38121
38202
  import { createServer as createServer3 } from "node:http";
38122
- import { isAbsolute as isAbsolute14, join as join14, relative as relative8 } from "node:path";
38203
+ import { isAbsolute as isAbsolute14, join as join15, relative as relative8 } from "node:path";
38123
38204
  var MAX_REQUEST_BYTES2 = 16 * 1024;
38124
38205
  var DIRECTORY_MODE4 = 448;
38125
38206
  var PRIVATE_FILE_MODE = 384;
@@ -38507,7 +38588,7 @@ async function prepareHelpers(input) {
38507
38588
  throw new Error("GitHub shell authentication requires a private real run directory");
38508
38589
  }
38509
38590
  const runRoot = await realpath7(input.runRoot);
38510
- const helperPath = join14(runRoot, "github-shell-git-credential.cjs");
38591
+ const helperPath = join15(runRoot, "github-shell-git-credential.cjs");
38511
38592
  assertChildPath2(runRoot, helperPath);
38512
38593
  await writePrivate(helperPath, GIT_HELPER_SOURCE);
38513
38594
  if (!input.ghExecutablePath) {
@@ -38518,14 +38599,14 @@ async function prepareHelpers(input) {
38518
38599
  wrapperSourcePath: null
38519
38600
  };
38520
38601
  }
38521
- const shellToolsDirectory = join14(runRoot, "shell-tools");
38602
+ const shellToolsDirectory = join15(runRoot, "shell-tools");
38522
38603
  assertChildPath2(runRoot, shellToolsDirectory);
38523
38604
  await mkdir10(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
38524
38605
  await chmod6(shellToolsDirectory, DIRECTORY_MODE4);
38525
- const wrapperSourcePath = join14(runRoot, "github-shell-gh-wrapper.cjs");
38606
+ const wrapperSourcePath = join15(runRoot, "github-shell-gh-wrapper.cjs");
38526
38607
  assertChildPath2(runRoot, wrapperSourcePath);
38527
38608
  await writePrivate(wrapperSourcePath, GH_WRAPPER_SOURCE);
38528
- const wrapperPath = join14(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
38609
+ const wrapperPath = join15(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
38529
38610
  assertChildPath2(runRoot, wrapperPath);
38530
38611
  const launcher = process.platform === "win32" ? `@"${process.execPath.replaceAll('"', '""')}" "${wrapperSourcePath.replaceAll('"', '""')}" %*\r
38531
38612
  ` : `#!/bin/sh
@@ -38748,7 +38829,7 @@ password=${credential.accessToken}
38748
38829
  }
38749
38830
 
38750
38831
  // src/runners/working-context.ts
38751
- import { spawn as spawn7 } from "node:child_process";
38832
+ import { spawn as spawn8 } from "node:child_process";
38752
38833
  import { resolve as resolve9 } from "node:path";
38753
38834
  var COMMAND_TIMEOUT_MS = 5e3;
38754
38835
  var OUTPUT_LIMIT_BYTES = 128 * 1024;
@@ -38879,7 +38960,7 @@ async function stopWorkingContextCommand(child, childExited, options = {}) {
38879
38960
  function run(command, args, cwd, env, signal) {
38880
38961
  if (signal?.aborted) return Promise.resolve(null);
38881
38962
  return new Promise((resolvePromise) => {
38882
- const child = spawn7(command, [...args], {
38963
+ const child = spawn8(command, [...args], {
38883
38964
  cwd,
38884
38965
  env: { ...env, GIT_OPTIONAL_LOCKS: "0" },
38885
38966
  detached: process.platform !== "win32",
@@ -39319,7 +39400,7 @@ async function settlesWithin(promise2, timeoutMs) {
39319
39400
  }
39320
39401
  }
39321
39402
  function defaultRunnerWorkspaceRoot() {
39322
- return join15(homedir6(), ".zixt", "workspaces");
39403
+ return join16(homedir6(), ".zixt", "workspaces");
39323
39404
  }
39324
39405
  function defaultRunnerArtifactRoot() {
39325
39406
  return defaultRunArtifactRoot();
@@ -39368,7 +39449,7 @@ function createCliRunner(adapter, opts = {}) {
39368
39449
  const prefixArgs = opts.commandPrefixArgs ?? [];
39369
39450
  const maxWallTimeMs = opts.maxWallTimeMs;
39370
39451
  const workspaceRoot = opts.workspaceRoot ?? defaultRunnerWorkspaceRoot();
39371
- const artifactRoot = opts.artifactRoot ?? (opts.workspaceRoot === void 0 ? defaultRunnerArtifactRoot() : join15(dirname8(workspaceRoot), "run-artifacts"));
39452
+ const artifactRoot = opts.artifactRoot ?? (opts.workspaceRoot === void 0 ? defaultRunnerArtifactRoot() : join16(dirname9(workspaceRoot), "run-artifacts"));
39372
39453
  const runRegistryRoot2 = opts.runRegistryRoot ?? defaultRunRegistryRoot();
39373
39454
  const createArtifacts = opts.createArtifacts ?? createRunArtifacts;
39374
39455
  const toolPackRegistry2 = opts.toolPackRegistry ?? createDefaultToolPackRegistry();
@@ -39386,7 +39467,7 @@ function createCliRunner(adapter, opts = {}) {
39386
39467
  };
39387
39468
  const askUserServer = createAskUserServer();
39388
39469
  const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
39389
- const windowsComspecCandidate = process.platform === "win32" && windowsRoot ? join15(windowsRoot, "System32", "cmd.exe") : void 0;
39470
+ const windowsComspecCandidate = process.platform === "win32" && windowsRoot ? join16(windowsRoot, "System32", "cmd.exe") : void 0;
39390
39471
  let safetyFailure;
39391
39472
  return async (task) => {
39392
39473
  if (safetyFailure) {
@@ -39426,7 +39507,7 @@ function createCliRunner(adapter, opts = {}) {
39426
39507
  usage: { inputTokens: 0, outputTokens: 0 }
39427
39508
  };
39428
39509
  }
39429
- const taskRoot = join15(workspaceRoot, task.agentId);
39510
+ const taskRoot = join16(workspaceRoot, task.agentId);
39430
39511
  await mkdir11(taskRoot, { recursive: true });
39431
39512
  if (task.cancelledNow()) return cancelledBeforeRun();
39432
39513
  const configuredWorkspace = task.spec.workspace;
@@ -39764,7 +39845,7 @@ ${attachmentSection}` : prompt;
39764
39845
  for (const path of paths) {
39765
39846
  if (!path || path.length > 4096) continue;
39766
39847
  const absolutePath = isAbsolute15(path) ? path : resolve10(cwd, path);
39767
- const directory = dirname8(absolutePath);
39848
+ const directory = dirname9(absolutePath);
39768
39849
  observedWorkingDirectories.delete(directory);
39769
39850
  observedWorkingDirectories.add(directory);
39770
39851
  while (observedWorkingDirectories.size > 19) {
@@ -40199,7 +40280,7 @@ function runCliProcess(options) {
40199
40280
  return new Promise((resolve18) => {
40200
40281
  const platform = options.platform ?? process.platform;
40201
40282
  const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID11() : void 0;
40202
- const child = options.guardian ? spawn8(
40283
+ const child = options.guardian ? spawn9(
40203
40284
  options.guardian.nodeCommand,
40204
40285
  [
40205
40286
  options.guardian.scriptPath,
@@ -40210,7 +40291,7 @@ function runCliProcess(options) {
40210
40291
  // The idle pre-assignment guardian must never load from or depend
40211
40292
  // on an untrusted Task checkout. Only the post-gate target enters
40212
40293
  // the requested working directory from its private release frame.
40213
- cwd: dirname8(options.guardian.scriptPath),
40294
+ cwd: dirname9(options.guardian.scriptPath),
40214
40295
  env: runnerGuardianEnv(process.env, containmentGateNonce),
40215
40296
  stdio: ["pipe", "pipe", "pipe"],
40216
40297
  windowsHide: true,
@@ -40492,7 +40573,7 @@ import { randomUUID as randomUUID12 } from "node:crypto";
40492
40573
  // src/runners/runtime-observation.ts
40493
40574
  import { open as open6, readdir as readdir5, realpath as realpath9 } from "node:fs/promises";
40494
40575
  import { homedir as homedir7 } from "node:os";
40495
- import { join as join16 } from "node:path";
40576
+ import { join as join17 } from "node:path";
40496
40577
  var READ_WINDOW_BYTES = 1024 * 1024;
40497
40578
  var CATALOG_TIMEOUT_MS = 15e3;
40498
40579
  var CATALOG_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
@@ -40552,9 +40633,9 @@ function displayValue(value, maxLength) {
40552
40633
  return trimmed;
40553
40634
  }
40554
40635
  function claudeTranscriptPath(input) {
40555
- const configDir = input.env["CLAUDE_CONFIG_DIR"] || join16(homeFrom(input.env), ".claude");
40636
+ const configDir = input.env["CLAUDE_CONFIG_DIR"] || join17(homeFrom(input.env), ".claude");
40556
40637
  const slug = input.resolvedCwd.replace(/[^a-zA-Z0-9]/g, "-");
40557
- return join16(configDir, "projects", slug, `${input.sessionId}.jsonl`);
40638
+ return join17(configDir, "projects", slug, `${input.sessionId}.jsonl`);
40558
40639
  }
40559
40640
  async function readClaudeSessionEffort(input) {
40560
40641
  const resolvedCwd = await realpath9(input.cwd).catch(() => input.cwd);
@@ -40570,18 +40651,18 @@ async function readClaudeSessionEffort(input) {
40570
40651
  }
40571
40652
  async function newestDirectories(root, limit) {
40572
40653
  const entries = await readdir5(root, { withFileTypes: true }).catch(() => []);
40573
- return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join16(root, name));
40654
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join17(root, name));
40574
40655
  }
40575
40656
  async function findCodexRolloutPath(input) {
40576
- const codexHome = input.env["CODEX_HOME"] || join16(homeFrom(input.env), ".codex");
40577
- const sessions = join16(codexHome, "sessions");
40657
+ const codexHome = input.env["CODEX_HOME"] || join17(homeFrom(input.env), ".codex");
40658
+ const sessions = join17(codexHome, "sessions");
40578
40659
  const suffix = `-${input.threadId}.jsonl`;
40579
40660
  for (const year of await newestDirectories(sessions, 2)) {
40580
40661
  for (const month of await newestDirectories(year, 2)) {
40581
40662
  for (const day of await newestDirectories(month, 3)) {
40582
40663
  const files = await readdir5(day).catch(() => []);
40583
40664
  const match = files.find((name) => name.endsWith(suffix));
40584
- if (match) return join16(day, match);
40665
+ if (match) return join17(day, match);
40585
40666
  }
40586
40667
  }
40587
40668
  }
@@ -40978,15 +41059,15 @@ function improveErrorMessage(error52) {
40978
41059
  import { mkdir as mkdir12, readFile as readFile10, writeFile as writeFile7 } from "node:fs/promises";
40979
41060
  import { randomUUID as randomUUID13 } from "node:crypto";
40980
41061
  import { homedir as homedir8 } from "node:os";
40981
- import { join as join17 } from "node:path";
41062
+ import { join as join18 } from "node:path";
40982
41063
  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.";
40983
41064
  function defaultCodexThreadIndexRoot() {
40984
- return join17(homedir8(), ".zixt", "codex-threads");
41065
+ return join18(homedir8(), ".zixt", "codex-threads");
40985
41066
  }
40986
41067
  var SAFE_SEGMENT3 = /^[A-Za-z0-9_-]{1,200}$/;
40987
41068
  function threadIndexPath(root, agentId, sessionKey) {
40988
41069
  if (!SAFE_SEGMENT3.test(agentId) || !SAFE_SEGMENT3.test(sessionKey)) return null;
40989
- return join17(root, agentId, `${sessionKey}.json`);
41070
+ return join18(root, agentId, `${sessionKey}.json`);
40990
41071
  }
40991
41072
  async function readThreadId(path) {
40992
41073
  try {
@@ -41090,7 +41171,7 @@ ${value}` : value;
41090
41171
  const recordedThreadId = indexPath ? await readThreadId(indexPath) : null;
41091
41172
  const rememberThread = (threadId) => {
41092
41173
  if (!indexPath) return;
41093
- void mkdir12(join17(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile7(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
41174
+ void mkdir12(join18(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile7(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
41094
41175
  });
41095
41176
  };
41096
41177
  const observeRuntime = (threadId) => {
@@ -41553,7 +41634,7 @@ function improveCodexErrorMessage(error52) {
41553
41634
  }
41554
41635
 
41555
41636
  // src/runners/git-preflight.ts
41556
- import { spawn as spawn9 } from "node:child_process";
41637
+ import { spawn as spawn10 } from "node:child_process";
41557
41638
  import { realpath as realpath10 } from "node:fs/promises";
41558
41639
  import { isAbsolute as isAbsolute16, resolve as resolve11 } from "node:path";
41559
41640
  var OUTPUT_LIMIT = 8192;
@@ -41602,7 +41683,7 @@ async function preflightGit(options = {}) {
41602
41683
  }
41603
41684
  async function runVersionProbe(input) {
41604
41685
  return new Promise((resolvePromise) => {
41605
- const child = spawn9(input.executablePath, input.args, {
41686
+ const child = spawn10(input.executablePath, input.args, {
41606
41687
  cwd: input.cwd,
41607
41688
  env: {
41608
41689
  ...process.env.SystemRoot ? { SystemRoot: process.env.SystemRoot } : {},
@@ -41824,11 +41905,11 @@ function run2(command, args) {
41824
41905
  }
41825
41906
 
41826
41907
  // src/linux-service.ts
41827
- import { spawn as spawn10 } from "node:child_process";
41908
+ import { spawn as spawn11 } from "node:child_process";
41828
41909
  import { constants as constants2 } from "node:fs";
41829
41910
  import { access as access4, chmod as chmod7, mkdir as mkdir13, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
41830
41911
  import { homedir as homedir9, userInfo } from "node:os";
41831
- import { basename as basename4, dirname as dirname9, join as join18, relative as relative9, resolve as resolve12, sep as sep5 } from "node:path";
41912
+ import { basename as basename4, dirname as dirname10, join as join19, relative as relative9, resolve as resolve12, sep as sep5 } from "node:path";
41832
41913
  var SERVICE_NAME = "zixt-host.service";
41833
41914
  var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
41834
41915
  var SERVICE_STABILITY_DELAY_MS = 2e3;
@@ -41857,7 +41938,7 @@ function boundedAppend(current, chunk) {
41857
41938
  async function defaultRunCommand(command, args) {
41858
41939
  const commandEnvironment3 = systemServiceCommandEnvironment();
41859
41940
  return new Promise((resolve18) => {
41860
- const child = spawn10(command, [...args], {
41941
+ const child = spawn11(command, [...args], {
41861
41942
  stdio: ["ignore", "pipe", "pipe"],
41862
41943
  env: commandEnvironment3,
41863
41944
  windowsHide: true
@@ -41933,18 +42014,18 @@ async function ensureDirectory(path, mode, syncDirectory8) {
41933
42014
  if (!firstCreated) return;
41934
42015
  const first = resolve12(firstCreated);
41935
42016
  const target = resolve12(path);
41936
- await syncDirectory8(dirname9(first));
42017
+ await syncDirectory8(dirname10(first));
41937
42018
  let current = first;
41938
42019
  const descendants = relative9(first, target);
41939
42020
  for (const part of descendants ? descendants.split(sep5) : []) {
41940
42021
  await syncDirectory8(current);
41941
- current = join18(current, part);
42022
+ current = join19(current, part);
41942
42023
  }
41943
42024
  }
41944
42025
  async function replacePrivateFile(path, contents, mode, syncDirectory8) {
41945
- const parent = dirname9(path);
42026
+ const parent = dirname10(path);
41946
42027
  await ensureDirectory(parent, 448, syncDirectory8);
41947
- const temporary = join18(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42028
+ const temporary = join19(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
41948
42029
  const handle = await open7(temporary, "wx", mode);
41949
42030
  try {
41950
42031
  await handle.writeFile(contents, "utf8");
@@ -41996,11 +42077,11 @@ async function installLinuxService(options) {
41996
42077
  "command search path"
41997
42078
  );
41998
42079
  const cloudUrl = options.cloudUrl ? oneLine(options.cloudUrl, "Zixt Cloud address") : void 0;
41999
- const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join18(home, ".config");
42000
- const configRoot = options.serviceConfigRoot ?? join18(xdgConfigHome, "zixt");
42001
- const unitRoot = options.userUnitRoot ?? join18(xdgConfigHome, "systemd", "user");
42002
- const environmentPath = join18(configRoot, "host.env");
42003
- const unitPath = join18(unitRoot, SERVICE_NAME);
42080
+ const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join19(home, ".config");
42081
+ const configRoot = options.serviceConfigRoot ?? join19(xdgConfigHome, "zixt");
42082
+ const unitRoot = options.userUnitRoot ?? join19(xdgConfigHome, "systemd", "user");
42083
+ const environmentPath = join19(configRoot, "host.env");
42084
+ const unitPath = join19(unitRoot, SERVICE_NAME);
42004
42085
  const installVersion = options.installVersion ?? installRelease;
42005
42086
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : activateInstalledRelease);
42006
42087
  const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
@@ -42117,11 +42198,11 @@ async function installLinuxService(options) {
42117
42198
  }
42118
42199
 
42119
42200
  // src/macos-service.ts
42120
- import { spawn as spawn11 } from "node:child_process";
42201
+ import { spawn as spawn12 } from "node:child_process";
42121
42202
  import { constants as constants3 } from "node:fs";
42122
42203
  import { access as access5, chmod as chmod8, mkdir as mkdir14, open as open8, rename as rename7, rm as rm10 } from "node:fs/promises";
42123
42204
  import { homedir as homedir10, userInfo as userInfo2 } from "node:os";
42124
- import { basename as basename5, dirname as dirname10, join as join19, relative as relative10, resolve as resolve13, sep as sep6 } from "node:path";
42205
+ import { basename as basename5, dirname as dirname11, join as join20, relative as relative10, resolve as resolve13, sep as sep6 } from "node:path";
42125
42206
  var LAUNCH_AGENT_LABEL = "ai.zixt.host";
42126
42207
  var SERVICE_STABILITY_DELAY_MS2 = 2e3;
42127
42208
  var COMMAND_TIMEOUT_MS2 = 7e4;
@@ -42149,17 +42230,17 @@ async function ensureDirectory2(path, sync) {
42149
42230
  if (!firstCreated) return;
42150
42231
  const first = resolve13(firstCreated);
42151
42232
  const target = resolve13(path);
42152
- await sync(dirname10(first));
42233
+ await sync(dirname11(first));
42153
42234
  let current = first;
42154
42235
  for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
42155
42236
  await sync(current);
42156
- current = join19(current, part);
42237
+ current = join20(current, part);
42157
42238
  }
42158
42239
  }
42159
42240
  async function replacePrivateFile2(path, contents, mode, sync) {
42160
- const parent = dirname10(path);
42241
+ const parent = dirname11(path);
42161
42242
  await ensureDirectory2(parent, sync);
42162
- const temporary = join19(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42243
+ const temporary = join20(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42163
42244
  const handle = await open8(temporary, "wx", mode);
42164
42245
  try {
42165
42246
  await handle.writeFile(contents, "utf8");
@@ -42184,7 +42265,7 @@ function commandEnvironment(env) {
42184
42265
  }
42185
42266
  async function defaultRunCommand2(command, args, env) {
42186
42267
  return new Promise((resolveResult) => {
42187
- const child = spawn11(command, [...args], {
42268
+ const child = spawn12(command, [...args], {
42188
42269
  stdio: ["ignore", "pipe", "pipe"],
42189
42270
  env: commandEnvironment(env)
42190
42271
  });
@@ -42256,14 +42337,14 @@ async function installMacosService(options) {
42256
42337
  options.path ?? env.PATH ?? "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin",
42257
42338
  "command search path"
42258
42339
  );
42259
- const configRoot = options.configRoot ?? join19(home, "Library", "Application Support", "Zixt");
42260
- const launchAgentsRoot = options.launchAgentsRoot ?? join19(home, "Library", "LaunchAgents");
42261
- const logRoot = options.logRoot ?? join19(home, "Library", "Logs", "Zixt");
42262
- const configPath = join19(configRoot, "host.env");
42263
- const launcherPath = join19(configRoot, "host-launcher.sh");
42264
- const plistPath = join19(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
42265
- const stdoutPath = join19(logRoot, "host.log");
42266
- const stderrPath = join19(logRoot, "host-error.log");
42340
+ const configRoot = options.configRoot ?? join20(home, "Library", "Application Support", "Zixt");
42341
+ const launchAgentsRoot = options.launchAgentsRoot ?? join20(home, "Library", "LaunchAgents");
42342
+ const logRoot = options.logRoot ?? join20(home, "Library", "Logs", "Zixt");
42343
+ const configPath = join20(configRoot, "host.env");
42344
+ const launcherPath = join20(configRoot, "host-launcher.sh");
42345
+ const plistPath = join20(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
42346
+ const stdoutPath = join20(logRoot, "host.log");
42347
+ const stderrPath = join20(logRoot, "host-error.log");
42267
42348
  const installVersion = options.installVersion ?? installRelease;
42268
42349
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
42269
42350
  const resolveCommand = options.resolveCommand ?? (async () => defaultResolveCommand2());
@@ -42348,11 +42429,11 @@ async function installMacosService(options) {
42348
42429
  }
42349
42430
 
42350
42431
  // src/windows-service.ts
42351
- import { spawn as spawn12 } from "node:child_process";
42432
+ import { spawn as spawn13 } from "node:child_process";
42352
42433
  import { constants as constants4 } from "node:fs";
42353
42434
  import { access as access6, mkdir as mkdir15, open as open9, readFile as readFile11, rename as rename8, rm as rm11 } from "node:fs/promises";
42354
42435
  import { homedir as homedir11 } from "node:os";
42355
- import { basename as basename6, dirname as dirname11, isAbsolute as isAbsolute17, join as join20, relative as relative11, resolve as resolve14, sep as sep7 } from "node:path";
42436
+ 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";
42356
42437
  var TASK_NAME = "Zixt Host";
42357
42438
  var COMMAND_TIMEOUT_MS3 = 7e4;
42358
42439
  var SERVICE_STABILITY_DELAY_MS3 = 2e3;
@@ -42382,17 +42463,17 @@ async function ensureDirectory3(path, sync) {
42382
42463
  if (!firstCreated) return;
42383
42464
  const first = resolve14(firstCreated);
42384
42465
  const target = resolve14(path);
42385
- await sync(dirname11(first));
42466
+ await sync(dirname12(first));
42386
42467
  let current = first;
42387
42468
  for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
42388
42469
  await sync(current);
42389
- current = join20(current, part);
42470
+ current = join21(current, part);
42390
42471
  }
42391
42472
  }
42392
42473
  async function replacePrivateFile3(path, contents, sync) {
42393
- const parent = dirname11(path);
42474
+ const parent = dirname12(path);
42394
42475
  await ensureDirectory3(parent, sync);
42395
- const temporary = join20(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42476
+ const temporary = join21(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
42396
42477
  const handle = await open9(temporary, "wx", 384);
42397
42478
  try {
42398
42479
  await handle.writeFile(contents, "utf8");
@@ -42413,7 +42494,7 @@ function commandEnvironment2(env) {
42413
42494
  }
42414
42495
  async function runChild(command, args, env, input) {
42415
42496
  return new Promise((resolveResult) => {
42416
- const child = spawn12(command, [...args], {
42497
+ const child = spawn13(command, [...args], {
42417
42498
  stdio: [input === void 0 ? "ignore" : "pipe", "pipe", "pipe"],
42418
42499
  env: commandEnvironment2(env),
42419
42500
  windowsHide: true
@@ -42447,7 +42528,7 @@ async function runChild(command, args, env, input) {
42447
42528
  async function defaultResolveCommand3(name, env) {
42448
42529
  const root = env.SYSTEMROOT ?? env.WINDIR;
42449
42530
  if (!root || !isAbsolute17(root)) return null;
42450
- const candidate = name === "powershell" ? join20(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join20(root, "System32", `${name}.exe`);
42531
+ const candidate = name === "powershell" ? join21(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join21(root, "System32", `${name}.exe`);
42451
42532
  return access6(candidate, constants4.X_OK).then(
42452
42533
  () => candidate,
42453
42534
  () => null
@@ -42584,11 +42665,11 @@ async function installWindowsService(options) {
42584
42665
  const token2 = oneLine3(options.token, "pairing code");
42585
42666
  const cloudUrl = options.cloudUrl ? oneLine3(options.cloudUrl, "Zixt Cloud address") : void 0;
42586
42667
  const path = oneLine3(options.path ?? env.PATH ?? "", "command search path");
42587
- const configRoot = options.configRoot ?? join20(localAppData, "Zixt", "Host");
42588
- const configPath = join20(configRoot, "host.json");
42589
- const launcherPath = join20(configRoot, "host-launcher.ps1");
42590
- const taskXmlPath = join20(configRoot, "host-task.xml");
42591
- const statusPath = join20(configRoot, "host-status.json");
42668
+ const configRoot = options.configRoot ?? join21(localAppData, "Zixt", "Host");
42669
+ const configPath = join21(configRoot, "host.json");
42670
+ const launcherPath = join21(configRoot, "host-launcher.ps1");
42671
+ const taskXmlPath = join21(configRoot, "host-task.xml");
42672
+ const statusPath = join21(configRoot, "host-status.json");
42592
42673
  const installVersion = options.installVersion ?? installRelease;
42593
42674
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
42594
42675
  const resolveCommand = options.resolveCommand ?? ((name) => defaultResolveCommand3(name, env));
@@ -42691,21 +42772,21 @@ async function installSystemService(options) {
42691
42772
  // src/terminal-outcomes.ts
42692
42773
  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";
42693
42774
  import { homedir as homedir12 } from "node:os";
42694
- import { dirname as dirname12, join as join21, relative as relative12, resolve as resolve15, sep as sep8 } from "node:path";
42775
+ import { dirname as dirname13, join as join22, relative as relative12, resolve as resolve15, sep as sep8 } from "node:path";
42695
42776
  var DIRECTORY_MODE5 = 448;
42696
42777
  var FILE_MODE4 = 384;
42697
42778
  var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
42698
42779
  var HOST_DIRECTORY = /^hst_[0-9a-f]{32}$/;
42699
42780
  var OUTCOME_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
42700
42781
  function defaultTerminalOutcomeRoot() {
42701
- return join21(homedir12(), ".zixt", "terminal-outcomes");
42782
+ return join22(homedir12(), ".zixt", "terminal-outcomes");
42702
42783
  }
42703
42784
  function hostOutcomeRoot(root, hostId) {
42704
42785
  if (!HOST_DIRECTORY.test(hostId)) throw new Error("terminal outcome Host identity is malformed");
42705
- return join21(root, hostId);
42786
+ return join22(root, hostId);
42706
42787
  }
42707
42788
  function outcomePath(root, hostId, taskId, epoch) {
42708
- return join21(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
42789
+ return join22(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
42709
42790
  }
42710
42791
  async function syncDirectory6(root) {
42711
42792
  if (process.platform === "win32") return;
@@ -42721,11 +42802,11 @@ async function requirePrivateRoot(root, sync = syncDirectory6) {
42721
42802
  if (firstCreated) {
42722
42803
  const first = resolve15(firstCreated);
42723
42804
  const target = resolve15(root);
42724
- await sync(dirname12(first));
42805
+ await sync(dirname13(first));
42725
42806
  let current = first;
42726
42807
  for (const part of relative12(first, target).split(sep8).filter(Boolean)) {
42727
42808
  await sync(current);
42728
- current = join21(current, part);
42809
+ current = join22(current, part);
42729
42810
  }
42730
42811
  }
42731
42812
  const stat3 = await lstat12(root);
@@ -42765,7 +42846,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
42765
42846
  } catch (error52) {
42766
42847
  if (error52.code !== "ENOENT") throw error52;
42767
42848
  }
42768
- const temporary = join21(
42849
+ const temporary = join22(
42769
42850
  scopedRoot,
42770
42851
  `.${outcome.taskId}.${outcome.epoch}.${process.pid}.${Date.now()}.${outcome.resultId}.tmp`
42771
42852
  );
@@ -42818,7 +42899,7 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
42818
42899
  if (!match || !entry.isFile() || entry.isSymbolicLink()) {
42819
42900
  throw new Error("committed terminal outcome is not a trusted regular file");
42820
42901
  }
42821
- const path = join21(scopedRoot, entry.name);
42902
+ const path = join22(scopedRoot, entry.name);
42822
42903
  const stat3 = await lstat12(path);
42823
42904
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_OUTCOME_BYTES) {
42824
42905
  throw new Error("committed terminal outcome is not a trusted regular file");
@@ -42872,13 +42953,13 @@ async function forgetSupersededTerminalOutcomes(hostId, taskId, epoch, root = de
42872
42953
  // src/accepted-assignments.ts
42873
42954
  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";
42874
42955
  import { homedir as homedir13 } from "node:os";
42875
- import { dirname as dirname13, join as join22, relative as relative13, resolve as resolve16, sep as sep9 } from "node:path";
42956
+ import { dirname as dirname14, join as join23, relative as relative13, resolve as resolve16, sep as sep9 } from "node:path";
42876
42957
  var DIRECTORY_MODE6 = 448;
42877
42958
  var FILE_MODE5 = 384;
42878
42959
  var CLAIM_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
42879
42960
  var TASK_ID = /^tsk_[0-9a-f]{32}$/;
42880
42961
  function defaultAcceptedAssignmentRoot() {
42881
- return join22(homedir13(), ".zixt", "accepted-assignments");
42962
+ return join23(homedir13(), ".zixt", "accepted-assignments");
42882
42963
  }
42883
42964
  async function syncDirectory7(root) {
42884
42965
  if (process.platform === "win32") return;
@@ -42894,11 +42975,11 @@ async function requirePrivateRoot2(root, sync = syncDirectory7) {
42894
42975
  if (firstCreated) {
42895
42976
  const first = resolve16(firstCreated);
42896
42977
  const target = resolve16(root);
42897
- await sync(dirname13(first));
42978
+ await sync(dirname14(first));
42898
42979
  let current = first;
42899
42980
  for (const part of relative13(first, target).split(sep9).filter(Boolean)) {
42900
42981
  await sync(current);
42901
- current = join22(current, part);
42982
+ current = join23(current, part);
42902
42983
  }
42903
42984
  }
42904
42985
  const stat3 = await lstat13(root);
@@ -42912,7 +42993,7 @@ function claimPath(root, taskId, epoch) {
42912
42993
  if (!Number.isSafeInteger(epoch) || epoch < 1) {
42913
42994
  throw new Error("accepted assignment epoch is malformed");
42914
42995
  }
42915
- return join22(root, `${taskId}.${epoch}.json`);
42996
+ return join23(root, `${taskId}.${epoch}.json`);
42916
42997
  }
42917
42998
  async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssignmentRoot(), options = {}) {
42918
42999
  const sync = options.syncDirectory ?? syncDirectory7;
@@ -42922,7 +43003,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
42922
43003
  } catch {
42923
43004
  return false;
42924
43005
  }
42925
- const temporary = join22(
43006
+ const temporary = join23(
42926
43007
  root,
42927
43008
  `.${assignment.taskId}.${assignment.epoch}.${process.pid}.${Date.now()}.tmp`
42928
43009
  );
@@ -43085,7 +43166,7 @@ function createHostLogger(options = {}) {
43085
43166
  }
43086
43167
 
43087
43168
  // src/demo-state.ts
43088
- import { isAbsolute as isAbsolute18, join as join23, parse as parse3, resolve as resolve17 } from "node:path";
43169
+ import { isAbsolute as isAbsolute18, join as join24, parse as parse3, resolve as resolve17 } from "node:path";
43089
43170
  var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
43090
43171
  function resolveDemoHostStatePaths(env = process.env) {
43091
43172
  const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
@@ -43095,13 +43176,13 @@ function resolveDemoHostStatePaths(env = process.env) {
43095
43176
  throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
43096
43177
  }
43097
43178
  return {
43098
- runRegistryRoot: join23(root, "run-registry"),
43099
- terminalOutcomeRoot: join23(root, "terminal-outcomes"),
43100
- acceptedAssignmentRoot: join23(root, "accepted-assignments"),
43101
- runArtifactRoot: join23(root, "run-artifacts"),
43102
- browserProfileRoot: join23(root, "browser-profiles"),
43103
- runnerWorkspaceRoot: join23(root, "workspaces"),
43104
- codexThreadIndexRoot: join23(root, "codex-threads")
43179
+ runRegistryRoot: join24(root, "run-registry"),
43180
+ terminalOutcomeRoot: join24(root, "terminal-outcomes"),
43181
+ acceptedAssignmentRoot: join24(root, "accepted-assignments"),
43182
+ runArtifactRoot: join24(root, "run-artifacts"),
43183
+ browserProfileRoot: join24(root, "browser-profiles"),
43184
+ runnerWorkspaceRoot: join24(root, "workspaces"),
43185
+ codexThreadIndexRoot: join24(root, "codex-threads")
43105
43186
  };
43106
43187
  }
43107
43188
 
@@ -43430,7 +43511,22 @@ var restartAfterUnsafeRunnerCleanup = (reason) => {
43430
43511
  };
43431
43512
  var browserManager = new BrowserManager({
43432
43513
  ...browserProfileRoot ? { profileRoot: browserProfileRoot } : {},
43433
- factory: process.env.ZIXT_BROWSER === "demo" ? createDemoBrowserAdapterFactory() : createPlaywrightBrowserAdapterFactory()
43514
+ factory: process.env.ZIXT_BROWSER === "demo" ? createDemoBrowserAdapterFactory() : createPlaywrightBrowserAdapterFactory({
43515
+ onInstallEvent: (event) => {
43516
+ if (event.state === "started") {
43517
+ log.info("Browser not found; installing Chromium for this Zixt version", {
43518
+ machine
43519
+ });
43520
+ } else if (event.state === "completed") {
43521
+ log.success("Browser installation complete", { machine });
43522
+ } else {
43523
+ log.warn("Browser installation failed", {
43524
+ machine,
43525
+ ...event.error ? { error: event.error } : {}
43526
+ });
43527
+ }
43528
+ }
43529
+ })
43434
43530
  });
43435
43531
  var claudeCode = createClaudeCodeRunner({
43436
43532
  ...runnerWorkspaceRoot ? { workspaceRoot: runnerWorkspaceRoot } : {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.109",
3
+ "version": "0.0.110",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",