@zixt/host 0.0.83 → 0.0.84

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 +63 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import { homedir as homedir3 } from "node:os";
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "@zixt/host",
34
- version: "0.0.83",
34
+ version: "0.0.84",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -16805,6 +16805,7 @@ var ListTasksResponse = external_exports.object({
16805
16805
  // ../../packages/contracts/src/protocol.ts
16806
16806
  var PROTOCOL_VERSION = 8;
16807
16807
  var BROWSER_PROFILE_INVENTORY_PAGE_SIZE = 200;
16808
+ var HELLO_UNWOUND_ASSIGNMENT_LIMIT = 1e3;
16808
16809
  var TASK_CANCEL_ACK_EVENT = "zixt.task.cancel.acknowledged";
16809
16810
  var TASK_CREDENTIAL_ROLLOVER_ACK_EVENT = "zixt.task.credential_rollover.acknowledged";
16810
16811
  var UnwoundAssignmentRef = external_exports.object({
@@ -18051,7 +18052,7 @@ var HelloFrame = external_exports.object({
18051
18052
  * prior socket died. Optional for rolling v5 hosts; repeated references are
18052
18053
  * idempotent and remain presence/host/org/epoch fenced by the cloud.
18053
18054
  */
18054
- unwoundAssignments: external_exports.array(UnwoundAssignmentRef).max(1e3).optional()
18055
+ unwoundAssignments: external_exports.array(UnwoundAssignmentRef).max(HELLO_UNWOUND_ASSIGNMENT_LIMIT).optional()
18055
18056
  });
18056
18057
  var BrowserProfileInventoryFrame = external_exports.object({
18057
18058
  type: external_exports.literal("browser.profile.inventory"),
@@ -18176,6 +18177,8 @@ var CLOSE_CODES = {
18176
18177
  replacedByNewerConnection: 4003,
18177
18178
  revoked: 4004
18178
18179
  };
18180
+ var UNSUPPORTED_PROTOCOL_CLOSE_REASON = "unsupported protocol version";
18181
+ var CLOSE_REASON_MAX_BYTES = 123;
18179
18182
 
18180
18183
  // ../../packages/contracts/src/manager.ts
18181
18184
  var MANAGER_DEFAULT_MODEL = "gpt-5.6-luna";
@@ -21315,6 +21318,17 @@ function operationGrantRetryCause(code) {
21315
21318
  }
21316
21319
  return "GitHub is temporarily unavailable for credential issuance";
21317
21320
  }
21321
+ function closeDetail(reason) {
21322
+ if (reason === void 0) return void 0;
21323
+ const raw = typeof reason === "string" ? reason : reason.toString("utf8");
21324
+ let printable = "";
21325
+ for (const character of raw) {
21326
+ const code = character.codePointAt(0) ?? 0;
21327
+ printable += code < 32 || code === 127 ? " " : character;
21328
+ }
21329
+ const text = printable.trim().slice(0, CLOSE_REASON_MAX_BYTES);
21330
+ return text.length > 0 ? text : void 0;
21331
+ }
21318
21332
  var HostClient = class _HostClient {
21319
21333
  constructor(opts) {
21320
21334
  this.opts = opts;
@@ -21687,9 +21701,13 @@ var HostClient = class _HostClient {
21687
21701
  const inventoryConfigured = Boolean(
21688
21702
  this.opts.browser?.profileInventoryPages || this.opts.browser?.profileInventory
21689
21703
  );
21690
- const unwoundAssignments = [...this.pendingUnwoundAssignments.values()].sort(
21704
+ const disclaimable = [...this.pendingUnwoundAssignments.values()].sort(
21691
21705
  (left, right) => left.taskId === right.taskId ? left.epoch - right.epoch : left.taskId.localeCompare(right.taskId)
21692
21706
  );
21707
+ const unwoundAssignments = disclaimable.slice(0, HELLO_UNWOUND_ASSIGNMENT_LIMIT);
21708
+ if (disclaimable.length > unwoundAssignments.length) {
21709
+ this.opts.onDisclaimerBacklog?.(disclaimable.length, unwoundAssignments.length);
21710
+ }
21693
21711
  this.send(
21694
21712
  {
21695
21713
  type: "hello",
@@ -21721,14 +21739,14 @@ var HostClient = class _HostClient {
21721
21739
  if (this.ws === ws) ws.terminate();
21722
21740
  });
21723
21741
  });
21724
- ws.on("close", (code) => {
21742
+ ws.on("close", (code, reason) => {
21725
21743
  if (inventoryRetryTimer) clearTimeout(inventoryRetryTimer);
21726
- void this.handleClose(ws, code, closeReason, frameTail);
21744
+ void this.handleClose(ws, code, closeReason, frameTail, closeDetail(reason));
21727
21745
  });
21728
21746
  ws.on("error", () => {
21729
21747
  });
21730
21748
  }
21731
- async handleClose(ws, code, closeReason, frameTail = Promise.resolve()) {
21749
+ async handleClose(ws, code, closeReason, frameTail = Promise.resolve(), detail) {
21732
21750
  if (this.ws !== ws) return;
21733
21751
  this.ws = void 0;
21734
21752
  this.protocolReady = false;
@@ -21767,13 +21785,18 @@ var HostClient = class _HostClient {
21767
21785
  await this.unwindAllRuns("host connection was replaced by a newer client", "client_shutdown");
21768
21786
  return;
21769
21787
  }
21770
- if (code === CLOSE_CODES.protocolError) {
21771
- this.opts.onStatus?.("incompatible");
21788
+ const versionMismatch = code === CLOSE_CODES.protocolError && detail === UNSUPPORTED_PROTOCOL_CLOSE_REASON;
21789
+ if (versionMismatch) {
21790
+ this.opts.onStatus?.("incompatible", detail);
21772
21791
  this.stopped = true;
21773
21792
  await this.unwindAllRuns("host protocol is incompatible", "client_shutdown");
21774
21793
  return;
21775
21794
  }
21776
- this.opts.onStatus?.(closeReason === "heartbeat_timeout" ? "unresponsive" : "disconnected");
21795
+ if (code === CLOSE_CODES.protocolError) {
21796
+ this.opts.onStatus?.("rejected", detail);
21797
+ } else {
21798
+ this.opts.onStatus?.(closeReason === "heartbeat_timeout" ? "unresponsive" : "disconnected");
21799
+ }
21777
21800
  if (this.stopped) return;
21778
21801
  await this.unwindAllRuns(
21779
21802
  closeReason === "heartbeat_timeout" ? "Zixt Cloud stopped answering heartbeat probes" : "host connection was lost",
@@ -40411,16 +40434,26 @@ var colorOverride = forcedColor(cliOptions.color) ?? (process.env[HOST_CONSOLE_C
40411
40434
  var hostConsoleTail = [];
40412
40435
  var hostConsoleSequence = 0;
40413
40436
  var clientForConsole = {};
40437
+ function recordConsoleLine(line) {
40438
+ const entry = { sequence: ++hostConsoleSequence, line };
40439
+ hostConsoleTail.push(entry);
40440
+ if (hostConsoleTail.length > 200) hostConsoleTail.shift();
40441
+ clientForConsole.current?.hostConsoleLine(entry);
40442
+ }
40414
40443
  var log = createHostLogger({
40415
40444
  ...colorOverride === void 0 ? {} : { color: colorOverride },
40416
40445
  write: (line) => {
40417
40446
  console.error(line);
40418
- const entry = { sequence: ++hostConsoleSequence, line };
40419
- hostConsoleTail.push(entry);
40420
- if (hostConsoleTail.length > 200) hostConsoleTail.shift();
40421
- clientForConsole.current?.hostConsoleLine(entry);
40447
+ recordConsoleLine(line);
40422
40448
  }
40423
40449
  });
40450
+ function replayConsoleLine(level, message, context) {
40451
+ recordConsoleLine(
40452
+ formatHostLogLine(level, message, context, {
40453
+ ...colorOverride === void 0 ? {} : { color: colorOverride }
40454
+ })
40455
+ );
40456
+ }
40424
40457
  if (cliOptions.help) {
40425
40458
  process.stdout.write(`${hostHelpText()}
40426
40459
  `);
@@ -40805,6 +40838,14 @@ var client = new HostClient({
40805
40838
  forgetAcknowledgedAcceptedAssignments(assignments, acceptedAssignmentRoot)
40806
40839
  ]);
40807
40840
  },
40841
+ onDisclaimerBacklog: (pending, reported) => {
40842
+ log.warn("More unfinished Task claims than one connection can report", {
40843
+ machine,
40844
+ pending,
40845
+ reported,
40846
+ next: "The rest are reported as this Machine reconnects; report this if it does not clear"
40847
+ });
40848
+ },
40808
40849
  persistAcceptedAssignment: (assignment) => recordAcceptedAssignment(assignment, acceptedAssignmentRoot).then(() => void 0),
40809
40850
  forgetAcceptedAssignment: (assignment) => forgetAcceptedAssignment(assignment, acceptedAssignmentRoot),
40810
40851
  persistTerminalOutcome: (hostId, outcome) => recordTerminalOutcome(hostId, outcome, terminalOutcomeRoot),
@@ -40836,7 +40877,7 @@ var client = new HostClient({
40836
40877
  onUsableTelemetryReport: () => {
40837
40878
  reportWorkerReadiness();
40838
40879
  },
40839
- onStatus: (status) => {
40880
+ onStatus: (status, detail) => {
40840
40881
  if (status === lastReportedStatus) return;
40841
40882
  lastReportedStatus = status;
40842
40883
  switch (status) {
@@ -40876,6 +40917,13 @@ var client = new HostClient({
40876
40917
  });
40877
40918
  queueMicrotask(() => shutdown(packagedBuild ? UPDATE_EXIT_CODE : DO_NOT_RESTART_EXIT_CODE));
40878
40919
  break;
40920
+ case "rejected":
40921
+ log.error("Zixt Cloud refused this Machine", {
40922
+ ...connectionContext,
40923
+ reason: detail ?? "the cloud gave no reason",
40924
+ next: "Zixt keeps retrying; report this reason if the Machine stays offline, because no update changes it"
40925
+ });
40926
+ break;
40879
40927
  }
40880
40928
  },
40881
40929
  executor,
@@ -40893,7 +40941,7 @@ for (const { record: record2 } of reportedWorkerExits) {
40893
40941
  ...context,
40894
40942
  next: "This Machine restarted itself; report it if the same exit repeats"
40895
40943
  });
40896
- for (const line of record2.stderr) log.error("Previous worker output", { machine, line });
40944
+ for (const line of record2.stderr) replayConsoleLine("error", "Previous worker output", { line });
40897
40945
  }
40898
40946
  log.info("Starting Zixt Host", connectionContext);
40899
40947
  client.start();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.83",
3
+ "version": "0.0.84",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",