@zixt/host 0.0.9 → 0.0.10

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 +66 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import { homedir } from "node:os";
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "@zixt/host",
34
- version: "0.0.9",
34
+ version: "0.0.10",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -15938,8 +15938,8 @@ var CreateTaskInput = external_exports.object({
15938
15938
  /** May be empty only when the message carries attachments (TS-15). */
15939
15939
  instructions: external_exports.string().max(1e5),
15940
15940
  priority: Task.shape.priority.default(0),
15941
- /** Must name one of the selected agent's configured workspaces. */
15942
- workspace: SafeDisplayPath.optional(),
15941
+ /** Omitted uses the teammate default; null explicitly uses its Zixt-owned persistent folder. */
15942
+ workspace: SafeDisplayPath.nullable().optional(),
15943
15943
  interactionMode: InteractionMode.optional(),
15944
15944
  /** Ask the agent to post a plan via ask_user before doing any work. */
15945
15945
  planFirst: external_exports.boolean().optional(),
@@ -20842,6 +20842,10 @@ var HostClient = class _HostClient {
20842
20842
  });
20843
20843
  }
20844
20844
  }
20845
+ try {
20846
+ this.opts.onTaskSettled?.();
20847
+ } catch {
20848
+ }
20845
20849
  }
20846
20850
  }
20847
20851
  /** Dial an MCP server on the cloud's behalf and report its tools/health. */
@@ -20888,6 +20892,28 @@ function releaseSourceUrl() {
20888
20892
  var DEFAULT_INTERVAL_MS = 15 * 6e4;
20889
20893
  var MIN_INTERVAL_MS = 6e4;
20890
20894
  var REQUEST_TIMEOUT_MS2 = 1e4;
20895
+ function createIdleUpdateRestartGate(options) {
20896
+ let pending = null;
20897
+ let restarting = false;
20898
+ const restartIfIdle = () => {
20899
+ if (restarting || pending === null || options.activeTasks() > 0) return;
20900
+ restarting = true;
20901
+ const version2 = pending;
20902
+ pending = null;
20903
+ options.restart(version2);
20904
+ };
20905
+ return {
20906
+ updateAvailable(version2) {
20907
+ if (restarting || pending !== null) return;
20908
+ pending = version2;
20909
+ const activeTasks = options.activeTasks();
20910
+ if (activeTasks > 0) options.deferred?.(version2, activeTasks);
20911
+ restartIfIdle();
20912
+ },
20913
+ taskSettled: restartIfIdle,
20914
+ pendingVersion: () => pending
20915
+ };
20916
+ }
20891
20917
  async function fetchPublishedVersion(registryUrl = DEFAULT_REGISTRY_URL, fetchImpl = fetch) {
20892
20918
  try {
20893
20919
  const response = await fetchImpl(registryUrl, {
@@ -21086,7 +21112,7 @@ function posixProcessRecordsFromPs(output) {
21086
21112
  const seen = /* @__PURE__ */ new Set();
21087
21113
  for (const line of output.split(/\r?\n/)) {
21088
21114
  if (!line.trim()) continue;
21089
- const match = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s*$/.exec(line);
21115
+ const match = /^\s*(?:(\d+)\s+)?(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s*$/.exec(line);
21090
21116
  if (!match) {
21091
21117
  throw new ProcessTreeTerminationError(
21092
21118
  "state_unknown",
@@ -21094,12 +21120,13 @@ function posixProcessRecordsFromPs(output) {
21094
21120
  );
21095
21121
  }
21096
21122
  const record2 = {
21097
- pid: Number(match[1]),
21098
- ppid: Number(match[2]),
21099
- pgid: Number(match[3]),
21100
- stat: match[4]
21123
+ uid: match[1] === void 0 ? null : Number(match[1]),
21124
+ pid: Number(match[2]),
21125
+ ppid: Number(match[3]),
21126
+ pgid: Number(match[4]),
21127
+ stat: match[5]
21101
21128
  };
21102
- if (!Number.isSafeInteger(record2.pid) || record2.pid <= 0 || !Number.isSafeInteger(record2.ppid) || record2.ppid < 0 || !Number.isSafeInteger(record2.pgid) || record2.pgid < 0 || seen.has(record2.pid)) {
21129
+ if (record2.uid !== null && (!Number.isSafeInteger(record2.uid) || record2.uid < 0) || !Number.isSafeInteger(record2.pid) || record2.pid <= 0 || !Number.isSafeInteger(record2.ppid) || record2.ppid < 0 || !Number.isSafeInteger(record2.pgid) || record2.pgid < 0 || seen.has(record2.pid)) {
21103
21130
  throw new ProcessTreeTerminationError(
21104
21131
  "state_unknown",
21105
21132
  "POSIX process-tree observation returned invalid evidence"
@@ -21112,7 +21139,7 @@ function posixProcessRecordsFromPs(output) {
21112
21139
  }
21113
21140
  async function snapshotPosixProcesses() {
21114
21141
  return new Promise((resolve13, reject3) => {
21115
- const observer = spawn2("/bin/ps", ["-axo", "pid=,ppid=,pgid=,stat="], {
21142
+ const observer = spawn2("/bin/ps", ["-axo", "uid=,pid=,ppid=,pgid=,stat="], {
21116
21143
  stdio: ["ignore", "pipe", "ignore"]
21117
21144
  });
21118
21145
  let output = "";
@@ -21176,6 +21203,9 @@ async function snapshotPosixProcesses() {
21176
21203
  });
21177
21204
  });
21178
21205
  }
21206
+ function legacyPosixProcessIsDefinitelyForeign(record2, currentUid = process.getuid?.()) {
21207
+ return record2.uid !== null && currentUid !== void 0 && record2.uid !== currentUid;
21208
+ }
21179
21209
  function capturePosixTree(rootPid, records) {
21180
21210
  const byPid = new Map(records.map((record2) => [record2.pid, record2]));
21181
21211
  const host = byPid.get(process.pid);
@@ -21648,6 +21678,7 @@ async function terminateRecordedProcessTree(pid, identity, options = {}) {
21648
21678
  const liveGroup = records.some((record2) => record2.pgid === pid && !record2.stat.startsWith("Z"));
21649
21679
  if (!root && !liveGroup) return;
21650
21680
  if (!identity) {
21681
+ if (root && legacyPosixProcessIsDefinitelyForeign(root)) return;
21651
21682
  throw new ProcessTreeTerminationError(
21652
21683
  "state_unknown",
21653
21684
  "a live legacy runner has no process identity and cannot be stopped safely"
@@ -36382,6 +36413,28 @@ var connectionContext = connectionLogContext({
36382
36413
  cloud: cloudTarget,
36383
36414
  version: HOST_VERSION
36384
36415
  });
36416
+ var stopUpdateWatch = () => {
36417
+ };
36418
+ var updateRestartGate = createIdleUpdateRestartGate({
36419
+ activeTasks: () => activeSessions,
36420
+ deferred: (version2, activeTasks) => {
36421
+ log.info("A newer Zixt Host is ready; update waits for active Tasks to finish", {
36422
+ machine,
36423
+ version: version2,
36424
+ running: HOST_VERSION,
36425
+ activeTasks
36426
+ });
36427
+ },
36428
+ restart: (version2) => {
36429
+ log.info("Active Tasks settled; restarting to update Zixt Host", {
36430
+ machine,
36431
+ version: version2,
36432
+ running: HOST_VERSION
36433
+ });
36434
+ stopUpdateWatch();
36435
+ shutdown(UPDATE_EXIT_CODE);
36436
+ }
36437
+ });
36385
36438
  var client = new HostClient({
36386
36439
  url: url2,
36387
36440
  token,
@@ -36403,6 +36456,7 @@ var client = new HostClient({
36403
36456
  forgetSupersededTerminalOutcomes(hostId, taskId, epoch, terminalOutcomeRoot)
36404
36457
  ]);
36405
36458
  },
36459
+ onTaskSettled: () => updateRestartGate.taskSettled(),
36406
36460
  onUnwindStalled: (reason) => {
36407
36461
  retainRunAssignments();
36408
36462
  log.error("Task cleanup did not finish; restarting the Host to recover safely", {
@@ -36474,17 +36528,11 @@ function shutdown(exitCode = 0) {
36474
36528
  ).unref();
36475
36529
  void client.stop().then(() => process.exit(exitCode));
36476
36530
  }
36477
- var stopUpdateWatch = !packagedBuild ? () => {
36531
+ stopUpdateWatch = !packagedBuild ? () => {
36478
36532
  } : watchForUpdates({
36479
36533
  onUpdateAvailable: (version2) => {
36480
- log.info("A newer Zixt Host was published; restarting to pick it up", {
36481
- machine,
36482
- version: version2,
36483
- running: HOST_VERSION,
36484
- activeTasks: activeSessions
36485
- });
36486
36534
  stopUpdateWatch();
36487
- shutdown(UPDATE_EXIT_CODE);
36535
+ updateRestartGate.updateAvailable(version2);
36488
36536
  }
36489
36537
  });
36490
36538
  process.on("SIGINT", () => shutdown());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",