@zixt/host 0.0.9 → 0.0.11

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 +87 -20
  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.11",
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"
@@ -25753,6 +25784,7 @@ var GITHUB_TOOL_DEFINITIONS = {
25753
25784
  description: "Open one exact GitHub repository for this task, prepare its local workspace, and enable its granted tools.",
25754
25785
  inputSchema: {
25755
25786
  type: "object",
25787
+ description: "Provide exactly one of repository_id or full_name.",
25756
25788
  properties: {
25757
25789
  repository_id: repositoryId,
25758
25790
  full_name: {
@@ -25760,7 +25792,6 @@ var GITHUB_TOOL_DEFINITIONS = {
25760
25792
  pattern: "^[A-Za-z0-9_.-]{1,100}/[A-Za-z0-9_.-]{1,100}$"
25761
25793
  }
25762
25794
  },
25763
- oneOf: [{ required: ["repository_id"] }, { required: ["full_name"] }],
25764
25795
  additionalProperties: false
25765
25796
  }
25766
25797
  },
@@ -33311,7 +33342,26 @@ function createCliRunner(adapter, opts = {}) {
33311
33342
  }
33312
33343
  },
33313
33344
  agentOp: (op) => task.agentOp(op),
33314
- toolPacks
33345
+ // GitHub repository work belongs in the installed `git` and `gh`
33346
+ // commands backed by GithubShellAuth. Do not advertise the bundled
33347
+ // repository/Issue/PR/Actions MCP surface to the model: besides being
33348
+ // redundant, provider schema dialect changes can otherwise prevent a
33349
+ // Claude request before any command runs. Repository creation remains
33350
+ // the one bounded exception because it uses Zixt's durable admin-intent
33351
+ // reservation and ambiguity reconciliation rather than ordinary repo
33352
+ // authority.
33353
+ toolPacks: toolPacks.flatMap((pack) => {
33354
+ if (pack.provider !== "github") return [pack];
33355
+ const tools = pack.tools.filter(({ name }) => name === "github_create_repository");
33356
+ if (tools.length === 0) return [];
33357
+ return [
33358
+ {
33359
+ ...pack,
33360
+ tools,
33361
+ call: (name, args) => name === "github_create_repository" ? pack.call(name, args) : Promise.resolve({ ok: false, error: "Unknown GitHub operation." })
33362
+ }
33363
+ ];
33364
+ })
33315
33365
  });
33316
33366
  const prepared = await adapter.prepareRun({
33317
33367
  task,
@@ -36382,6 +36432,28 @@ var connectionContext = connectionLogContext({
36382
36432
  cloud: cloudTarget,
36383
36433
  version: HOST_VERSION
36384
36434
  });
36435
+ var stopUpdateWatch = () => {
36436
+ };
36437
+ var updateRestartGate = createIdleUpdateRestartGate({
36438
+ activeTasks: () => activeSessions,
36439
+ deferred: (version2, activeTasks) => {
36440
+ log.info("A newer Zixt Host is ready; update waits for active Tasks to finish", {
36441
+ machine,
36442
+ version: version2,
36443
+ running: HOST_VERSION,
36444
+ activeTasks
36445
+ });
36446
+ },
36447
+ restart: (version2) => {
36448
+ log.info("Active Tasks settled; restarting to update Zixt Host", {
36449
+ machine,
36450
+ version: version2,
36451
+ running: HOST_VERSION
36452
+ });
36453
+ stopUpdateWatch();
36454
+ shutdown(UPDATE_EXIT_CODE);
36455
+ }
36456
+ });
36385
36457
  var client = new HostClient({
36386
36458
  url: url2,
36387
36459
  token,
@@ -36403,6 +36475,7 @@ var client = new HostClient({
36403
36475
  forgetSupersededTerminalOutcomes(hostId, taskId, epoch, terminalOutcomeRoot)
36404
36476
  ]);
36405
36477
  },
36478
+ onTaskSettled: () => updateRestartGate.taskSettled(),
36406
36479
  onUnwindStalled: (reason) => {
36407
36480
  retainRunAssignments();
36408
36481
  log.error("Task cleanup did not finish; restarting the Host to recover safely", {
@@ -36474,17 +36547,11 @@ function shutdown(exitCode = 0) {
36474
36547
  ).unref();
36475
36548
  void client.stop().then(() => process.exit(exitCode));
36476
36549
  }
36477
- var stopUpdateWatch = !packagedBuild ? () => {
36550
+ stopUpdateWatch = !packagedBuild ? () => {
36478
36551
  } : watchForUpdates({
36479
36552
  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
36553
  stopUpdateWatch();
36487
- shutdown(UPDATE_EXIT_CODE);
36554
+ updateRestartGate.updateAvailable(version2);
36488
36555
  }
36489
36556
  });
36490
36557
  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.11",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",