meshy-node 0.0.7 → 0.0.8

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.
package/main.cjs CHANGED
@@ -14251,11 +14251,11 @@ var require_mime_types = __commonJS({
14251
14251
  }
14252
14252
  return exts[0];
14253
14253
  }
14254
- function lookup(path16) {
14255
- if (!path16 || typeof path16 !== "string") {
14254
+ function lookup(path17) {
14255
+ if (!path17 || typeof path17 !== "string") {
14256
14256
  return false;
14257
14257
  }
14258
- var extension2 = extname3("x." + path16).toLowerCase().substr(1);
14258
+ var extension2 = extname3("x." + path17).toLowerCase().substr(1);
14259
14259
  if (!extension2) {
14260
14260
  return false;
14261
14261
  }
@@ -17773,7 +17773,7 @@ var require_path_to_regexp = __commonJS({
17773
17773
  "use strict";
17774
17774
  module2.exports = pathToRegexp;
17775
17775
  var MATCHING_GROUP_REGEXP = /\\.|\((?:\?<(.*?)>)?(?!\?)/g;
17776
- function pathToRegexp(path16, keys, options) {
17776
+ function pathToRegexp(path17, keys, options) {
17777
17777
  options = options || {};
17778
17778
  keys = keys || [];
17779
17779
  var strict = options.strict;
@@ -17787,8 +17787,8 @@ var require_path_to_regexp = __commonJS({
17787
17787
  var pos = 0;
17788
17788
  var backtrack = "";
17789
17789
  var m;
17790
- if (path16 instanceof RegExp) {
17791
- while (m = MATCHING_GROUP_REGEXP.exec(path16.source)) {
17790
+ if (path17 instanceof RegExp) {
17791
+ while (m = MATCHING_GROUP_REGEXP.exec(path17.source)) {
17792
17792
  if (m[0][0] === "\\") continue;
17793
17793
  keys.push({
17794
17794
  name: m[1] || name++,
@@ -17796,18 +17796,18 @@ var require_path_to_regexp = __commonJS({
17796
17796
  offset: m.index
17797
17797
  });
17798
17798
  }
17799
- return path16;
17799
+ return path17;
17800
17800
  }
17801
- if (Array.isArray(path16)) {
17802
- path16 = path16.map(function(value) {
17801
+ if (Array.isArray(path17)) {
17802
+ path17 = path17.map(function(value) {
17803
17803
  return pathToRegexp(value, keys, options).source;
17804
17804
  });
17805
- return new RegExp(path16.join("|"), flags);
17805
+ return new RegExp(path17.join("|"), flags);
17806
17806
  }
17807
- if (typeof path16 !== "string") {
17807
+ if (typeof path17 !== "string") {
17808
17808
  throw new TypeError("path must be a string, array of strings, or regular expression");
17809
17809
  }
17810
- path16 = path16.replace(
17810
+ path17 = path17.replace(
17811
17811
  /\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g,
17812
17812
  function(match, slash, format, key, capture, star, optional, offset) {
17813
17813
  if (match[0] === "\\") {
@@ -17824,7 +17824,7 @@ var require_path_to_regexp = __commonJS({
17824
17824
  if (slash || format) {
17825
17825
  backtrack = "";
17826
17826
  } else {
17827
- backtrack += path16.slice(pos, offset);
17827
+ backtrack += path17.slice(pos, offset);
17828
17828
  }
17829
17829
  pos = offset + match.length;
17830
17830
  if (match === "*") {
@@ -17854,7 +17854,7 @@ var require_path_to_regexp = __commonJS({
17854
17854
  return result;
17855
17855
  }
17856
17856
  );
17857
- while (m = MATCHING_GROUP_REGEXP.exec(path16)) {
17857
+ while (m = MATCHING_GROUP_REGEXP.exec(path17)) {
17858
17858
  if (m[0][0] === "\\") continue;
17859
17859
  if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {
17860
17860
  keys.splice(keysOffset + i, 0, {
@@ -17866,13 +17866,13 @@ var require_path_to_regexp = __commonJS({
17866
17866
  }
17867
17867
  i++;
17868
17868
  }
17869
- path16 += strict ? "" : path16[path16.length - 1] === "/" ? "?" : "/?";
17869
+ path17 += strict ? "" : path17[path17.length - 1] === "/" ? "?" : "/?";
17870
17870
  if (end) {
17871
- path16 += "$";
17872
- } else if (path16[path16.length - 1] !== "/") {
17873
- path16 += lookahead ? "(?=/|$)" : "(?:/|$)";
17871
+ path17 += "$";
17872
+ } else if (path17[path17.length - 1] !== "/") {
17873
+ path17 += lookahead ? "(?=/|$)" : "(?:/|$)";
17874
17874
  }
17875
- return new RegExp("^" + path16, flags);
17875
+ return new RegExp("^" + path17, flags);
17876
17876
  }
17877
17877
  }
17878
17878
  });
@@ -17885,19 +17885,19 @@ var require_layer = __commonJS({
17885
17885
  var debug = require_src()("express:router:layer");
17886
17886
  var hasOwnProperty = Object.prototype.hasOwnProperty;
17887
17887
  module2.exports = Layer;
17888
- function Layer(path16, options, fn) {
17888
+ function Layer(path17, options, fn) {
17889
17889
  if (!(this instanceof Layer)) {
17890
- return new Layer(path16, options, fn);
17890
+ return new Layer(path17, options, fn);
17891
17891
  }
17892
- debug("new %o", path16);
17892
+ debug("new %o", path17);
17893
17893
  var opts = options || {};
17894
17894
  this.handle = fn;
17895
17895
  this.name = fn.name || "<anonymous>";
17896
17896
  this.params = void 0;
17897
17897
  this.path = void 0;
17898
- this.regexp = pathRegexp(path16, this.keys = [], opts);
17899
- this.regexp.fast_star = path16 === "*";
17900
- this.regexp.fast_slash = path16 === "/" && opts.end === false;
17898
+ this.regexp = pathRegexp(path17, this.keys = [], opts);
17899
+ this.regexp.fast_star = path17 === "*";
17900
+ this.regexp.fast_slash = path17 === "/" && opts.end === false;
17901
17901
  }
17902
17902
  Layer.prototype.handle_error = function handle_error(error, req, res, next) {
17903
17903
  var fn = this.handle;
@@ -17921,20 +17921,20 @@ var require_layer = __commonJS({
17921
17921
  next(err);
17922
17922
  }
17923
17923
  };
17924
- Layer.prototype.match = function match(path16) {
17924
+ Layer.prototype.match = function match(path17) {
17925
17925
  var match2;
17926
- if (path16 != null) {
17926
+ if (path17 != null) {
17927
17927
  if (this.regexp.fast_slash) {
17928
17928
  this.params = {};
17929
17929
  this.path = "";
17930
17930
  return true;
17931
17931
  }
17932
17932
  if (this.regexp.fast_star) {
17933
- this.params = { "0": decode_param(path16) };
17934
- this.path = path16;
17933
+ this.params = { "0": decode_param(path17) };
17934
+ this.path = path17;
17935
17935
  return true;
17936
17936
  }
17937
- match2 = this.regexp.exec(path16);
17937
+ match2 = this.regexp.exec(path17);
17938
17938
  }
17939
17939
  if (!match2) {
17940
17940
  this.params = void 0;
@@ -18027,10 +18027,10 @@ var require_route = __commonJS({
18027
18027
  var slice = Array.prototype.slice;
18028
18028
  var toString = Object.prototype.toString;
18029
18029
  module2.exports = Route;
18030
- function Route(path16) {
18031
- this.path = path16;
18030
+ function Route(path17) {
18031
+ this.path = path17;
18032
18032
  this.stack = [];
18033
- debug("new %o", path16);
18033
+ debug("new %o", path17);
18034
18034
  this.methods = {};
18035
18035
  }
18036
18036
  Route.prototype._handles_method = function _handles_method(method) {
@@ -18243,8 +18243,8 @@ var require_router = __commonJS({
18243
18243
  if (++sync > 100) {
18244
18244
  return setImmediate(next, err);
18245
18245
  }
18246
- var path16 = getPathname(req);
18247
- if (path16 == null) {
18246
+ var path17 = getPathname(req);
18247
+ if (path17 == null) {
18248
18248
  return done(layerError);
18249
18249
  }
18250
18250
  var layer;
@@ -18252,7 +18252,7 @@ var require_router = __commonJS({
18252
18252
  var route;
18253
18253
  while (match !== true && idx < stack.length) {
18254
18254
  layer = stack[idx++];
18255
- match = matchLayer(layer, path16);
18255
+ match = matchLayer(layer, path17);
18256
18256
  route = layer.route;
18257
18257
  if (typeof match !== "boolean") {
18258
18258
  layerError = layerError || match;
@@ -18290,18 +18290,18 @@ var require_router = __commonJS({
18290
18290
  } else if (route) {
18291
18291
  layer.handle_request(req, res, next);
18292
18292
  } else {
18293
- trim_prefix(layer, layerError, layerPath, path16);
18293
+ trim_prefix(layer, layerError, layerPath, path17);
18294
18294
  }
18295
18295
  sync = 0;
18296
18296
  });
18297
18297
  }
18298
- function trim_prefix(layer, layerError, layerPath, path16) {
18298
+ function trim_prefix(layer, layerError, layerPath, path17) {
18299
18299
  if (layerPath.length !== 0) {
18300
- if (layerPath !== path16.slice(0, layerPath.length)) {
18300
+ if (layerPath !== path17.slice(0, layerPath.length)) {
18301
18301
  next(layerError);
18302
18302
  return;
18303
18303
  }
18304
- var c = path16[layerPath.length];
18304
+ var c = path17[layerPath.length];
18305
18305
  if (c && c !== "/" && c !== ".") return next(layerError);
18306
18306
  debug("trim prefix (%s) from url %s", layerPath, req.url);
18307
18307
  removed = layerPath;
@@ -18379,7 +18379,7 @@ var require_router = __commonJS({
18379
18379
  };
18380
18380
  proto.use = function use(fn) {
18381
18381
  var offset = 0;
18382
- var path16 = "/";
18382
+ var path17 = "/";
18383
18383
  if (typeof fn !== "function") {
18384
18384
  var arg = fn;
18385
18385
  while (Array.isArray(arg) && arg.length !== 0) {
@@ -18387,7 +18387,7 @@ var require_router = __commonJS({
18387
18387
  }
18388
18388
  if (typeof arg !== "function") {
18389
18389
  offset = 1;
18390
- path16 = fn;
18390
+ path17 = fn;
18391
18391
  }
18392
18392
  }
18393
18393
  var callbacks = flatten(slice.call(arguments, offset));
@@ -18399,8 +18399,8 @@ var require_router = __commonJS({
18399
18399
  if (typeof fn !== "function") {
18400
18400
  throw new TypeError("Router.use() requires a middleware function but got a " + gettype(fn));
18401
18401
  }
18402
- debug("use %o %s", path16, fn.name || "<anonymous>");
18403
- var layer = new Layer(path16, {
18402
+ debug("use %o %s", path17, fn.name || "<anonymous>");
18403
+ var layer = new Layer(path17, {
18404
18404
  sensitive: this.caseSensitive,
18405
18405
  strict: false,
18406
18406
  end: false
@@ -18410,9 +18410,9 @@ var require_router = __commonJS({
18410
18410
  }
18411
18411
  return this;
18412
18412
  };
18413
- proto.route = function route(path16) {
18414
- var route2 = new Route(path16);
18415
- var layer = new Layer(path16, {
18413
+ proto.route = function route(path17) {
18414
+ var route2 = new Route(path17);
18415
+ var layer = new Layer(path17, {
18416
18416
  sensitive: this.caseSensitive,
18417
18417
  strict: this.strict,
18418
18418
  end: true
@@ -18422,8 +18422,8 @@ var require_router = __commonJS({
18422
18422
  return route2;
18423
18423
  };
18424
18424
  methods.concat("all").forEach(function(method) {
18425
- proto[method] = function(path16) {
18426
- var route = this.route(path16);
18425
+ proto[method] = function(path17) {
18426
+ var route = this.route(path17);
18427
18427
  route[method].apply(route, slice.call(arguments, 1));
18428
18428
  return this;
18429
18429
  };
@@ -18459,9 +18459,9 @@ var require_router = __commonJS({
18459
18459
  }
18460
18460
  return toString.call(obj).replace(objectRegExp, "$1");
18461
18461
  }
18462
- function matchLayer(layer, path16) {
18462
+ function matchLayer(layer, path17) {
18463
18463
  try {
18464
- return layer.match(path16);
18464
+ return layer.match(path17);
18465
18465
  } catch (err) {
18466
18466
  return err;
18467
18467
  }
@@ -18579,13 +18579,13 @@ var require_view = __commonJS({
18579
18579
  "../../node_modules/.pnpm/express@4.22.1/node_modules/express/lib/view.js"(exports2, module2) {
18580
18580
  "use strict";
18581
18581
  var debug = require_src()("express:view");
18582
- var path16 = require("path");
18582
+ var path17 = require("path");
18583
18583
  var fs17 = require("fs");
18584
- var dirname3 = path16.dirname;
18585
- var basename4 = path16.basename;
18586
- var extname3 = path16.extname;
18587
- var join12 = path16.join;
18588
- var resolve10 = path16.resolve;
18584
+ var dirname3 = path17.dirname;
18585
+ var basename4 = path17.basename;
18586
+ var extname3 = path17.extname;
18587
+ var join13 = path17.join;
18588
+ var resolve10 = path17.resolve;
18589
18589
  module2.exports = View;
18590
18590
  function View(name, options) {
18591
18591
  var opts = options || {};
@@ -18614,17 +18614,17 @@ var require_view = __commonJS({
18614
18614
  this.path = this.lookup(fileName);
18615
18615
  }
18616
18616
  View.prototype.lookup = function lookup(name) {
18617
- var path17;
18617
+ var path18;
18618
18618
  var roots = [].concat(this.root);
18619
18619
  debug('lookup "%s"', name);
18620
- for (var i = 0; i < roots.length && !path17; i++) {
18620
+ for (var i = 0; i < roots.length && !path18; i++) {
18621
18621
  var root = roots[i];
18622
18622
  var loc = resolve10(root, name);
18623
18623
  var dir = dirname3(loc);
18624
18624
  var file = basename4(loc);
18625
- path17 = this.resolve(dir, file);
18625
+ path18 = this.resolve(dir, file);
18626
18626
  }
18627
- return path17;
18627
+ return path18;
18628
18628
  };
18629
18629
  View.prototype.render = function render(options, callback) {
18630
18630
  debug('render "%s"', this.path);
@@ -18632,21 +18632,21 @@ var require_view = __commonJS({
18632
18632
  };
18633
18633
  View.prototype.resolve = function resolve11(dir, file) {
18634
18634
  var ext = this.ext;
18635
- var path17 = join12(dir, file);
18636
- var stat = tryStat(path17);
18635
+ var path18 = join13(dir, file);
18636
+ var stat = tryStat(path18);
18637
18637
  if (stat && stat.isFile()) {
18638
- return path17;
18638
+ return path18;
18639
18639
  }
18640
- path17 = join12(dir, basename4(file, ext), "index" + ext);
18641
- stat = tryStat(path17);
18640
+ path18 = join13(dir, basename4(file, ext), "index" + ext);
18641
+ stat = tryStat(path18);
18642
18642
  if (stat && stat.isFile()) {
18643
- return path17;
18643
+ return path18;
18644
18644
  }
18645
18645
  };
18646
- function tryStat(path17) {
18647
- debug('stat "%s"', path17);
18646
+ function tryStat(path18) {
18647
+ debug('stat "%s"', path18);
18648
18648
  try {
18649
- return fs17.statSync(path17);
18649
+ return fs17.statSync(path18);
18650
18650
  } catch (e) {
18651
18651
  return void 0;
18652
18652
  }
@@ -19002,7 +19002,7 @@ var require_types = __commonJS({
19002
19002
  var require_mime = __commonJS({
19003
19003
  "../../node_modules/.pnpm/mime@1.6.0/node_modules/mime/mime.js"(exports2, module2) {
19004
19004
  "use strict";
19005
- var path16 = require("path");
19005
+ var path17 = require("path");
19006
19006
  var fs17 = require("fs");
19007
19007
  function Mime() {
19008
19008
  this.types = /* @__PURE__ */ Object.create(null);
@@ -19032,8 +19032,8 @@ var require_mime = __commonJS({
19032
19032
  this.define(map);
19033
19033
  this._loading = null;
19034
19034
  };
19035
- Mime.prototype.lookup = function(path17, fallback) {
19036
- var ext = path17.replace(/^.*[\.\/\\]/, "").toLowerCase();
19035
+ Mime.prototype.lookup = function(path18, fallback) {
19036
+ var ext = path18.replace(/^.*[\.\/\\]/, "").toLowerCase();
19037
19037
  return this.types[ext] || fallback || this.default_type;
19038
19038
  };
19039
19039
  Mime.prototype.extension = function(mimeType) {
@@ -19268,28 +19268,28 @@ var require_send = __commonJS({
19268
19268
  var ms = require_ms2();
19269
19269
  var onFinished = require_on_finished();
19270
19270
  var parseRange = require_range_parser();
19271
- var path16 = require("path");
19271
+ var path17 = require("path");
19272
19272
  var statuses = require_statuses();
19273
19273
  var Stream = require("stream");
19274
19274
  var util2 = require("util");
19275
- var extname3 = path16.extname;
19276
- var join12 = path16.join;
19277
- var normalize = path16.normalize;
19278
- var resolve10 = path16.resolve;
19279
- var sep3 = path16.sep;
19275
+ var extname3 = path17.extname;
19276
+ var join13 = path17.join;
19277
+ var normalize = path17.normalize;
19278
+ var resolve10 = path17.resolve;
19279
+ var sep3 = path17.sep;
19280
19280
  var BYTES_RANGE_REGEXP = /^ *bytes=/;
19281
19281
  var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
19282
19282
  var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
19283
19283
  module2.exports = send;
19284
19284
  module2.exports.mime = mime;
19285
- function send(req, path17, options) {
19286
- return new SendStream(req, path17, options);
19285
+ function send(req, path18, options) {
19286
+ return new SendStream(req, path18, options);
19287
19287
  }
19288
- function SendStream(req, path17, options) {
19288
+ function SendStream(req, path18, options) {
19289
19289
  Stream.call(this);
19290
19290
  var opts = options || {};
19291
19291
  this.options = opts;
19292
- this.path = path17;
19292
+ this.path = path18;
19293
19293
  this.req = req;
19294
19294
  this._acceptRanges = opts.acceptRanges !== void 0 ? Boolean(opts.acceptRanges) : true;
19295
19295
  this._cacheControl = opts.cacheControl !== void 0 ? Boolean(opts.cacheControl) : true;
@@ -19335,8 +19335,8 @@ var require_send = __commonJS({
19335
19335
  this._index = index2;
19336
19336
  return this;
19337
19337
  }, "send.index: pass index as option");
19338
- SendStream.prototype.root = function root(path17) {
19339
- this._root = resolve10(String(path17));
19338
+ SendStream.prototype.root = function root(path18) {
19339
+ this._root = resolve10(String(path18));
19340
19340
  debug("root %s", this._root);
19341
19341
  return this;
19342
19342
  };
@@ -19449,10 +19449,10 @@ var require_send = __commonJS({
19449
19449
  var lastModified = this.res.getHeader("Last-Modified");
19450
19450
  return parseHttpDate(lastModified) <= parseHttpDate(ifRange);
19451
19451
  };
19452
- SendStream.prototype.redirect = function redirect(path17) {
19452
+ SendStream.prototype.redirect = function redirect(path18) {
19453
19453
  var res = this.res;
19454
19454
  if (hasListeners(this, "directory")) {
19455
- this.emit("directory", res, path17);
19455
+ this.emit("directory", res, path18);
19456
19456
  return;
19457
19457
  }
19458
19458
  if (this.hasTrailingSlash()) {
@@ -19472,42 +19472,42 @@ var require_send = __commonJS({
19472
19472
  SendStream.prototype.pipe = function pipe(res) {
19473
19473
  var root = this._root;
19474
19474
  this.res = res;
19475
- var path17 = decode(this.path);
19476
- if (path17 === -1) {
19475
+ var path18 = decode(this.path);
19476
+ if (path18 === -1) {
19477
19477
  this.error(400);
19478
19478
  return res;
19479
19479
  }
19480
- if (~path17.indexOf("\0")) {
19480
+ if (~path18.indexOf("\0")) {
19481
19481
  this.error(400);
19482
19482
  return res;
19483
19483
  }
19484
19484
  var parts;
19485
19485
  if (root !== null) {
19486
- if (path17) {
19487
- path17 = normalize("." + sep3 + path17);
19486
+ if (path18) {
19487
+ path18 = normalize("." + sep3 + path18);
19488
19488
  }
19489
- if (UP_PATH_REGEXP.test(path17)) {
19490
- debug('malicious path "%s"', path17);
19489
+ if (UP_PATH_REGEXP.test(path18)) {
19490
+ debug('malicious path "%s"', path18);
19491
19491
  this.error(403);
19492
19492
  return res;
19493
19493
  }
19494
- parts = path17.split(sep3);
19495
- path17 = normalize(join12(root, path17));
19494
+ parts = path18.split(sep3);
19495
+ path18 = normalize(join13(root, path18));
19496
19496
  } else {
19497
- if (UP_PATH_REGEXP.test(path17)) {
19498
- debug('malicious path "%s"', path17);
19497
+ if (UP_PATH_REGEXP.test(path18)) {
19498
+ debug('malicious path "%s"', path18);
19499
19499
  this.error(403);
19500
19500
  return res;
19501
19501
  }
19502
- parts = normalize(path17).split(sep3);
19503
- path17 = resolve10(path17);
19502
+ parts = normalize(path18).split(sep3);
19503
+ path18 = resolve10(path18);
19504
19504
  }
19505
19505
  if (containsDotFile(parts)) {
19506
19506
  var access = this._dotfiles;
19507
19507
  if (access === void 0) {
19508
19508
  access = parts[parts.length - 1][0] === "." ? this._hidden ? "allow" : "ignore" : "allow";
19509
19509
  }
19510
- debug('%s dotfile "%s"', access, path17);
19510
+ debug('%s dotfile "%s"', access, path18);
19511
19511
  switch (access) {
19512
19512
  case "allow":
19513
19513
  break;
@@ -19521,13 +19521,13 @@ var require_send = __commonJS({
19521
19521
  }
19522
19522
  }
19523
19523
  if (this._index.length && this.hasTrailingSlash()) {
19524
- this.sendIndex(path17);
19524
+ this.sendIndex(path18);
19525
19525
  return res;
19526
19526
  }
19527
- this.sendFile(path17);
19527
+ this.sendFile(path18);
19528
19528
  return res;
19529
19529
  };
19530
- SendStream.prototype.send = function send2(path17, stat) {
19530
+ SendStream.prototype.send = function send2(path18, stat) {
19531
19531
  var len = stat.size;
19532
19532
  var options = this.options;
19533
19533
  var opts = {};
@@ -19539,9 +19539,9 @@ var require_send = __commonJS({
19539
19539
  this.headersAlreadySent();
19540
19540
  return;
19541
19541
  }
19542
- debug('pipe "%s"', path17);
19543
- this.setHeader(path17, stat);
19544
- this.type(path17);
19542
+ debug('pipe "%s"', path18);
19543
+ this.setHeader(path18, stat);
19544
+ this.type(path18);
19545
19545
  if (this.isConditionalGET()) {
19546
19546
  if (this.isPreconditionFailure()) {
19547
19547
  this.error(412);
@@ -19590,26 +19590,26 @@ var require_send = __commonJS({
19590
19590
  res.end();
19591
19591
  return;
19592
19592
  }
19593
- this.stream(path17, opts);
19593
+ this.stream(path18, opts);
19594
19594
  };
19595
- SendStream.prototype.sendFile = function sendFile(path17) {
19595
+ SendStream.prototype.sendFile = function sendFile(path18) {
19596
19596
  var i = 0;
19597
19597
  var self = this;
19598
- debug('stat "%s"', path17);
19599
- fs17.stat(path17, function onstat(err, stat) {
19600
- if (err && err.code === "ENOENT" && !extname3(path17) && path17[path17.length - 1] !== sep3) {
19598
+ debug('stat "%s"', path18);
19599
+ fs17.stat(path18, function onstat(err, stat) {
19600
+ if (err && err.code === "ENOENT" && !extname3(path18) && path18[path18.length - 1] !== sep3) {
19601
19601
  return next(err);
19602
19602
  }
19603
19603
  if (err) return self.onStatError(err);
19604
- if (stat.isDirectory()) return self.redirect(path17);
19605
- self.emit("file", path17, stat);
19606
- self.send(path17, stat);
19604
+ if (stat.isDirectory()) return self.redirect(path18);
19605
+ self.emit("file", path18, stat);
19606
+ self.send(path18, stat);
19607
19607
  });
19608
19608
  function next(err) {
19609
19609
  if (self._extensions.length <= i) {
19610
19610
  return err ? self.onStatError(err) : self.error(404);
19611
19611
  }
19612
- var p = path17 + "." + self._extensions[i++];
19612
+ var p = path18 + "." + self._extensions[i++];
19613
19613
  debug('stat "%s"', p);
19614
19614
  fs17.stat(p, function(err2, stat) {
19615
19615
  if (err2) return next(err2);
@@ -19619,7 +19619,7 @@ var require_send = __commonJS({
19619
19619
  });
19620
19620
  }
19621
19621
  };
19622
- SendStream.prototype.sendIndex = function sendIndex(path17) {
19622
+ SendStream.prototype.sendIndex = function sendIndex(path18) {
19623
19623
  var i = -1;
19624
19624
  var self = this;
19625
19625
  function next(err) {
@@ -19627,7 +19627,7 @@ var require_send = __commonJS({
19627
19627
  if (err) return self.onStatError(err);
19628
19628
  return self.error(404);
19629
19629
  }
19630
- var p = join12(path17, self._index[i]);
19630
+ var p = join13(path18, self._index[i]);
19631
19631
  debug('stat "%s"', p);
19632
19632
  fs17.stat(p, function(err2, stat) {
19633
19633
  if (err2) return next(err2);
@@ -19638,10 +19638,10 @@ var require_send = __commonJS({
19638
19638
  }
19639
19639
  next();
19640
19640
  };
19641
- SendStream.prototype.stream = function stream(path17, options) {
19641
+ SendStream.prototype.stream = function stream(path18, options) {
19642
19642
  var self = this;
19643
19643
  var res = this.res;
19644
- var stream2 = fs17.createReadStream(path17, options);
19644
+ var stream2 = fs17.createReadStream(path18, options);
19645
19645
  this.emit("stream", stream2);
19646
19646
  stream2.pipe(res);
19647
19647
  function cleanup() {
@@ -19656,10 +19656,10 @@ var require_send = __commonJS({
19656
19656
  self.emit("end");
19657
19657
  });
19658
19658
  };
19659
- SendStream.prototype.type = function type(path17) {
19659
+ SendStream.prototype.type = function type(path18) {
19660
19660
  var res = this.res;
19661
19661
  if (res.getHeader("Content-Type")) return;
19662
- var type2 = mime.lookup(path17);
19662
+ var type2 = mime.lookup(path18);
19663
19663
  if (!type2) {
19664
19664
  debug("no content-type");
19665
19665
  return;
@@ -19668,9 +19668,9 @@ var require_send = __commonJS({
19668
19668
  debug("content-type %s", type2);
19669
19669
  res.setHeader("Content-Type", type2 + (charset ? "; charset=" + charset : ""));
19670
19670
  };
19671
- SendStream.prototype.setHeader = function setHeader(path17, stat) {
19671
+ SendStream.prototype.setHeader = function setHeader(path18, stat) {
19672
19672
  var res = this.res;
19673
- this.emit("headers", res, path17, stat);
19673
+ this.emit("headers", res, path18, stat);
19674
19674
  if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
19675
19675
  debug("accept ranges");
19676
19676
  res.setHeader("Accept-Ranges", "bytes");
@@ -19729,9 +19729,9 @@ var require_send = __commonJS({
19729
19729
  }
19730
19730
  return err instanceof Error ? createError(status, err, { expose: false }) : createError(status, err);
19731
19731
  }
19732
- function decode(path17) {
19732
+ function decode(path18) {
19733
19733
  try {
19734
- return decodeURIComponent(path17);
19734
+ return decodeURIComponent(path18);
19735
19735
  } catch (err) {
19736
19736
  return -1;
19737
19737
  }
@@ -20641,10 +20641,10 @@ var require_utils2 = __commonJS({
20641
20641
  var querystring = require("querystring");
20642
20642
  exports2.etag = createETagGenerator({ weak: false });
20643
20643
  exports2.wetag = createETagGenerator({ weak: true });
20644
- exports2.isAbsolute = function(path16) {
20645
- if ("/" === path16[0]) return true;
20646
- if (":" === path16[1] && ("\\" === path16[2] || "/" === path16[2])) return true;
20647
- if ("\\\\" === path16.substring(0, 2)) return true;
20644
+ exports2.isAbsolute = function(path17) {
20645
+ if ("/" === path17[0]) return true;
20646
+ if (":" === path17[1] && ("\\" === path17[2] || "/" === path17[2])) return true;
20647
+ if ("\\\\" === path17.substring(0, 2)) return true;
20648
20648
  };
20649
20649
  exports2.flatten = deprecate.function(
20650
20650
  flatten,
@@ -20855,7 +20855,7 @@ var require_application = __commonJS({
20855
20855
  };
20856
20856
  app.use = function use(fn) {
20857
20857
  var offset = 0;
20858
- var path16 = "/";
20858
+ var path17 = "/";
20859
20859
  if (typeof fn !== "function") {
20860
20860
  var arg = fn;
20861
20861
  while (Array.isArray(arg) && arg.length !== 0) {
@@ -20863,7 +20863,7 @@ var require_application = __commonJS({
20863
20863
  }
20864
20864
  if (typeof arg !== "function") {
20865
20865
  offset = 1;
20866
- path16 = fn;
20866
+ path17 = fn;
20867
20867
  }
20868
20868
  }
20869
20869
  var fns = flatten(slice.call(arguments, offset));
@@ -20874,12 +20874,12 @@ var require_application = __commonJS({
20874
20874
  var router = this._router;
20875
20875
  fns.forEach(function(fn2) {
20876
20876
  if (!fn2 || !fn2.handle || !fn2.set) {
20877
- return router.use(path16, fn2);
20877
+ return router.use(path17, fn2);
20878
20878
  }
20879
- debug(".use app under %s", path16);
20880
- fn2.mountpath = path16;
20879
+ debug(".use app under %s", path17);
20880
+ fn2.mountpath = path17;
20881
20881
  fn2.parent = this;
20882
- router.use(path16, function mounted_app(req, res, next) {
20882
+ router.use(path17, function mounted_app(req, res, next) {
20883
20883
  var orig = req.app;
20884
20884
  fn2.handle(req, res, function(err) {
20885
20885
  setPrototypeOf(req, orig.request);
@@ -20891,9 +20891,9 @@ var require_application = __commonJS({
20891
20891
  }, this);
20892
20892
  return this;
20893
20893
  };
20894
- app.route = function route(path16) {
20894
+ app.route = function route(path17) {
20895
20895
  this.lazyrouter();
20896
- return this._router.route(path16);
20896
+ return this._router.route(path17);
20897
20897
  };
20898
20898
  app.engine = function engine(ext, fn) {
20899
20899
  if (typeof fn !== "function") {
@@ -20944,7 +20944,7 @@ var require_application = __commonJS({
20944
20944
  }
20945
20945
  return this;
20946
20946
  };
20947
- app.path = function path16() {
20947
+ app.path = function path17() {
20948
20948
  return this.parent ? this.parent.path() + this.mountpath : "";
20949
20949
  };
20950
20950
  app.enabled = function enabled(setting) {
@@ -20960,19 +20960,19 @@ var require_application = __commonJS({
20960
20960
  return this.set(setting, false);
20961
20961
  };
20962
20962
  methods.forEach(function(method) {
20963
- app[method] = function(path16) {
20963
+ app[method] = function(path17) {
20964
20964
  if (method === "get" && arguments.length === 1) {
20965
- return this.set(path16);
20965
+ return this.set(path17);
20966
20966
  }
20967
20967
  this.lazyrouter();
20968
- var route = this._router.route(path16);
20968
+ var route = this._router.route(path17);
20969
20969
  route[method].apply(route, slice.call(arguments, 1));
20970
20970
  return this;
20971
20971
  };
20972
20972
  });
20973
- app.all = function all(path16) {
20973
+ app.all = function all(path17) {
20974
20974
  this.lazyrouter();
20975
- var route = this._router.route(path16);
20975
+ var route = this._router.route(path17);
20976
20976
  var args = slice.call(arguments, 1);
20977
20977
  for (var i = 0; i < methods.length; i++) {
20978
20978
  route[methods[i]].apply(route, args);
@@ -21731,7 +21731,7 @@ var require_request = __commonJS({
21731
21731
  var subdomains2 = !isIP(hostname2) ? hostname2.split(".").reverse() : [hostname2];
21732
21732
  return subdomains2.slice(offset);
21733
21733
  });
21734
- defineGetter(req, "path", function path16() {
21734
+ defineGetter(req, "path", function path17() {
21735
21735
  return parse(this).pathname;
21736
21736
  });
21737
21737
  defineGetter(req, "hostname", function hostname2() {
@@ -22054,7 +22054,7 @@ var require_response = __commonJS({
22054
22054
  var http2 = require("http");
22055
22055
  var isAbsolute2 = require_utils2().isAbsolute;
22056
22056
  var onFinished = require_on_finished();
22057
- var path16 = require("path");
22057
+ var path17 = require("path");
22058
22058
  var statuses = require_statuses();
22059
22059
  var merge = require_utils_merge();
22060
22060
  var sign = require_cookie_signature().sign;
@@ -22063,9 +22063,9 @@ var require_response = __commonJS({
22063
22063
  var setCharset = require_utils2().setCharset;
22064
22064
  var cookie = require_cookie();
22065
22065
  var send = require_send();
22066
- var extname3 = path16.extname;
22066
+ var extname3 = path17.extname;
22067
22067
  var mime = send.mime;
22068
- var resolve10 = path16.resolve;
22068
+ var resolve10 = path17.resolve;
22069
22069
  var vary = require_vary();
22070
22070
  var res = Object.create(http2.ServerResponse.prototype);
22071
22071
  module2.exports = res;
@@ -22242,26 +22242,26 @@ var require_response = __commonJS({
22242
22242
  this.type("txt");
22243
22243
  return this.send(body);
22244
22244
  };
22245
- res.sendFile = function sendFile(path17, options, callback) {
22245
+ res.sendFile = function sendFile(path18, options, callback) {
22246
22246
  var done = callback;
22247
22247
  var req = this.req;
22248
22248
  var res2 = this;
22249
22249
  var next = req.next;
22250
22250
  var opts = options || {};
22251
- if (!path17) {
22251
+ if (!path18) {
22252
22252
  throw new TypeError("path argument is required to res.sendFile");
22253
22253
  }
22254
- if (typeof path17 !== "string") {
22254
+ if (typeof path18 !== "string") {
22255
22255
  throw new TypeError("path must be a string to res.sendFile");
22256
22256
  }
22257
22257
  if (typeof options === "function") {
22258
22258
  done = options;
22259
22259
  opts = {};
22260
22260
  }
22261
- if (!opts.root && !isAbsolute2(path17)) {
22261
+ if (!opts.root && !isAbsolute2(path18)) {
22262
22262
  throw new TypeError("path must be absolute or specify root to res.sendFile");
22263
22263
  }
22264
- var pathname = encodeURI(path17);
22264
+ var pathname = encodeURI(path18);
22265
22265
  var file = send(req, pathname, opts);
22266
22266
  sendfile(res2, file, opts, function(err) {
22267
22267
  if (done) return done(err);
@@ -22271,7 +22271,7 @@ var require_response = __commonJS({
22271
22271
  }
22272
22272
  });
22273
22273
  };
22274
- res.sendfile = function(path17, options, callback) {
22274
+ res.sendfile = function(path18, options, callback) {
22275
22275
  var done = callback;
22276
22276
  var req = this.req;
22277
22277
  var res2 = this;
@@ -22281,7 +22281,7 @@ var require_response = __commonJS({
22281
22281
  done = options;
22282
22282
  opts = {};
22283
22283
  }
22284
- var file = send(req, path17, opts);
22284
+ var file = send(req, path18, opts);
22285
22285
  sendfile(res2, file, opts, function(err) {
22286
22286
  if (done) return done(err);
22287
22287
  if (err && err.code === "EISDIR") return next();
@@ -22294,7 +22294,7 @@ var require_response = __commonJS({
22294
22294
  res.sendfile,
22295
22295
  "res.sendfile: Use res.sendFile instead"
22296
22296
  );
22297
- res.download = function download(path17, filename, options, callback) {
22297
+ res.download = function download(path18, filename, options, callback) {
22298
22298
  var done = callback;
22299
22299
  var name = filename;
22300
22300
  var opts = options || null;
@@ -22311,7 +22311,7 @@ var require_response = __commonJS({
22311
22311
  opts = filename;
22312
22312
  }
22313
22313
  var headers = {
22314
- "Content-Disposition": contentDisposition(name || path17)
22314
+ "Content-Disposition": contentDisposition(name || path18)
22315
22315
  };
22316
22316
  if (opts && opts.headers) {
22317
22317
  var keys = Object.keys(opts.headers);
@@ -22324,7 +22324,7 @@ var require_response = __commonJS({
22324
22324
  }
22325
22325
  opts = Object.create(opts);
22326
22326
  opts.headers = headers;
22327
- var fullPath = !opts.root ? resolve10(path17) : path17;
22327
+ var fullPath = !opts.root ? resolve10(path18) : path18;
22328
22328
  return this.sendFile(fullPath, opts, done);
22329
22329
  };
22330
22330
  res.contentType = res.type = function contentType(type) {
@@ -22625,11 +22625,11 @@ var require_serve_static = __commonJS({
22625
22625
  }
22626
22626
  var forwardError = !fallthrough;
22627
22627
  var originalUrl = parseUrl.original(req);
22628
- var path16 = parseUrl(req).pathname;
22629
- if (path16 === "/" && originalUrl.pathname.substr(-1) !== "/") {
22630
- path16 = "";
22628
+ var path17 = parseUrl(req).pathname;
22629
+ if (path17 === "/" && originalUrl.pathname.substr(-1) !== "/") {
22630
+ path17 = "";
22631
22631
  }
22632
- var stream = send(req, path16, opts);
22632
+ var stream = send(req, path17, opts);
22633
22633
  stream.on("directory", onDirectory);
22634
22634
  if (setHeaders) {
22635
22635
  stream.on("headers", setHeaders);
@@ -22774,6 +22774,7 @@ __export(main_exports, {
22774
22774
  applyStartMetadata: () => applyStartMetadata,
22775
22775
  createDefaultConfig: () => createDefaultConfig,
22776
22776
  createRuntimeDefaultConfig: () => createRuntimeDefaultConfig,
22777
+ ensureStartupRequirements: () => ensureStartupRequirements,
22777
22778
  formatBanner: () => formatBanner,
22778
22779
  formatLoadedStartMetadata: () => formatLoadedStartMetadata,
22779
22780
  getDefaultNodeName: () => getDefaultNodeName,
@@ -22784,8 +22785,10 @@ __export(main_exports, {
22784
22785
  parseArgs: () => parseArgs,
22785
22786
  promptStartOptions: () => promptStartOptions,
22786
22787
  resolveRuntimeAuthMetadata: () => resolveRuntimeAuthMetadata,
22788
+ resolveStartupRequirementsMetadata: () => resolveStartupRequirementsMetadata,
22787
22789
  shouldCollectStartOptions: () => shouldCollectStartOptions,
22788
- shouldPromptForStartOptions: () => shouldPromptForStartOptions
22790
+ shouldPromptForStartOptions: () => shouldPromptForStartOptions,
22791
+ shouldSkipStartupRequirementsCheck: () => shouldSkipStartupRequirementsCheck
22789
22792
  });
22790
22793
  module.exports = __toCommonJS(main_exports);
22791
22794
  var nodePath = __toESM(require("path"), 1);
@@ -24010,14 +24013,19 @@ async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_NODE_REQUEST_TIME
24010
24013
  cleanup();
24011
24014
  }
24012
24015
  }
24013
- async function fetchNodeWithFallback(node, path16, init, timeoutMs = DEFAULT_NODE_REQUEST_TIMEOUT_MS) {
24016
+ async function fetchNodeWithFallback(node, path17, init, timeoutMs = DEFAULT_NODE_REQUEST_TIMEOUT_MS, trace) {
24014
24017
  let lastError;
24015
- for (const endpoint of getNodeRequestEndpoints(node)) {
24018
+ const endpoints = getNodeRequestEndpoints(node);
24019
+ for (const [index, endpoint] of endpoints.entries()) {
24020
+ const attempt = index + 1;
24021
+ trace?.onAttempt?.({ attempt, endpoint, path: path17, timeoutMs, totalEndpoints: endpoints.length });
24016
24022
  try {
24017
- const response = await fetchWithTimeout(`${endpoint}${path16}`, init, timeoutMs);
24023
+ const response = await fetchWithTimeout(`${endpoint}${path17}`, init, timeoutMs);
24024
+ trace?.onResponse?.({ attempt, endpoint, path: path17, response, timeoutMs, totalEndpoints: endpoints.length });
24018
24025
  return { endpoint, response };
24019
24026
  } catch (error) {
24020
24027
  lastError = error;
24028
+ trace?.onError?.({ attempt, endpoint, error, path: path17, timeoutMs, totalEndpoints: endpoints.length });
24021
24029
  }
24022
24030
  }
24023
24031
  throw lastError instanceof Error ? lastError : new Error("No reachable node endpoint");
@@ -24332,15 +24340,18 @@ var LeaderElection = class {
24332
24340
  if (announce.term < this.currentTerm) {
24333
24341
  return;
24334
24342
  }
24335
- if (announce.term > this.currentTerm) {
24336
- this.currentTerm = announce.term;
24337
- }
24338
- this.leader = false;
24339
- this.nodeRegistry.setLeader(announce.leaderId, announce.term);
24340
- this.eventBus.emit("election.complete", {
24341
- leaderId: announce.leaderId,
24342
- term: announce.term
24343
- });
24343
+ this.adoptLeader(announce);
24344
+ }
24345
+ /**
24346
+ * Explicit cluster joins are operator-driven reconfiguration, not normal
24347
+ * election traffic. Force the local node to follow the joined leader even
24348
+ * if this node previously incremented its term while detached.
24349
+ */
24350
+ adoptLeaderFromJoin(announce) {
24351
+ this.currentTerm = announce.term;
24352
+ this.votedForTerm = announce.term;
24353
+ this.votedForCandidate = announce.leaderId;
24354
+ this.adoptLeader(announce);
24344
24355
  }
24345
24356
  // ── Leader Lease ─────────────────────────────────────────────────────
24346
24357
  isLeader() {
@@ -24352,6 +24363,18 @@ var LeaderElection = class {
24352
24363
  stepDown() {
24353
24364
  this.leader = false;
24354
24365
  }
24366
+ /**
24367
+ * Adopt local leadership without running an election.
24368
+ * Used when a follower explicitly detaches from a leader and becomes
24369
+ * a solo node immediately.
24370
+ */
24371
+ assumeLeadership() {
24372
+ const self = this.nodeRegistry.getSelf();
24373
+ this.currentTerm = Math.max(this.currentTerm, 1);
24374
+ this.votedForTerm = this.currentTerm;
24375
+ this.votedForCandidate = self.id;
24376
+ this.becomeLeader();
24377
+ }
24355
24378
  /** Manually promote this node to leader. */
24356
24379
  async promote() {
24357
24380
  const self = this.nodeRegistry.getSelf();
@@ -24389,6 +24412,15 @@ var LeaderElection = class {
24389
24412
  term: this.currentTerm
24390
24413
  });
24391
24414
  }
24415
+ adoptLeader(announce) {
24416
+ this.currentTerm = announce.term;
24417
+ this.leader = false;
24418
+ this.nodeRegistry.setLeader(announce.leaderId, announce.term);
24419
+ this.eventBus.emit("election.complete", {
24420
+ leaderId: announce.leaderId,
24421
+ term: announce.term
24422
+ });
24423
+ }
24392
24424
  async broadcastAnnounce(leaderId, term) {
24393
24425
  const self = this.nodeRegistry.getSelf();
24394
24426
  const onlineNodes = this.nodeRegistry.getOnlineNodes().filter(
@@ -24990,6 +25022,12 @@ function listWorkDirFolders(workDir) {
24990
25022
 
24991
25023
  // ../../packages/core/src/heartbeat.ts
24992
25024
  var MISSED_HEARTBEAT_THRESHOLD = 3;
25025
+ function formatError(error) {
25026
+ return error instanceof Error ? error.message : String(error);
25027
+ }
25028
+ function truncateForLog(value, max = 240) {
25029
+ return !value || value.length <= max ? value : `${value.slice(0, max - 3)}...`;
25030
+ }
24993
25031
  var HeartbeatMonitor = class {
24994
25032
  constructor(nodeRegistry, election, eventBus, config, logger) {
24995
25033
  this.nodeRegistry = nodeRegistry;
@@ -25167,10 +25205,40 @@ var HeartbeatMonitor = class {
25167
25205
  };
25168
25206
  const promises2 = followers.map(async (node) => {
25169
25207
  try {
25170
- const { response } = await fetchNodeWithFallback(node, "/api/worker/heartbeat", {
25208
+ const { endpoint, response } = await fetchNodeWithFallback(node, "/api/worker/heartbeat", {
25171
25209
  method: "POST",
25172
25210
  headers: { "Content-Type": "application/json" },
25173
25211
  body: JSON.stringify(request)
25212
+ }, void 0, {
25213
+ onAttempt: ({ attempt, endpoint: targetEndpoint, totalEndpoints, timeoutMs }) => {
25214
+ this.log.info("sending heartbeat request", {
25215
+ nodeId: node.id,
25216
+ endpoint: targetEndpoint,
25217
+ attempt,
25218
+ totalEndpoints,
25219
+ timeoutMs,
25220
+ term: request.term
25221
+ });
25222
+ },
25223
+ onError: ({ attempt, endpoint: targetEndpoint, error, totalEndpoints }) => {
25224
+ this.log.warn("heartbeat request attempt failed", {
25225
+ nodeId: node.id,
25226
+ endpoint: targetEndpoint,
25227
+ attempt,
25228
+ totalEndpoints,
25229
+ error: formatError(error)
25230
+ });
25231
+ },
25232
+ onResponse: ({ attempt, endpoint: targetEndpoint, response: heartbeatResponse, totalEndpoints }) => {
25233
+ this.log.info("heartbeat response received", {
25234
+ nodeId: node.id,
25235
+ endpoint: targetEndpoint,
25236
+ attempt,
25237
+ totalEndpoints,
25238
+ ok: heartbeatResponse.ok,
25239
+ statusCode: heartbeatResponse.status
25240
+ });
25241
+ }
25174
25242
  });
25175
25243
  if (response.ok) {
25176
25244
  const result = await response.json();
@@ -25187,11 +25255,27 @@ var HeartbeatMonitor = class {
25187
25255
  if (result.status !== node.status) {
25188
25256
  this.nodeRegistry.updateStatus(node.id, result.status);
25189
25257
  }
25258
+ this.log.info("heartbeat response applied", {
25259
+ nodeId: node.id,
25260
+ endpoint,
25261
+ reportedStatus: result.status,
25262
+ load: result.load,
25263
+ workDirFolders: result.workDirFolders?.length ?? 0
25264
+ });
25190
25265
  return;
25191
25266
  }
25192
- this.recordFollowerMiss(node);
25193
- } catch {
25194
- this.recordFollowerMiss(node);
25267
+ const body = truncateForLog(await response.text().catch(() => void 0));
25268
+ this.recordFollowerMiss(node, {
25269
+ endpoint,
25270
+ reason: "non-ok heartbeat response",
25271
+ statusCode: response.status,
25272
+ body
25273
+ });
25274
+ } catch (error) {
25275
+ this.recordFollowerMiss(node, {
25276
+ reason: "heartbeat request threw",
25277
+ error: formatError(error)
25278
+ });
25195
25279
  }
25196
25280
  });
25197
25281
  await Promise.all(promises2);
@@ -25215,7 +25299,7 @@ var HeartbeatMonitor = class {
25215
25299
  term: req.term,
25216
25300
  nodeCount: req.clusterState.nodes.length
25217
25301
  });
25218
- return {
25302
+ const response = {
25219
25303
  nodeId: self.id,
25220
25304
  status: self.status,
25221
25305
  runningTasks: [],
@@ -25227,6 +25311,7 @@ var HeartbeatMonitor = class {
25227
25311
  previewOrigin: self.previewOrigin,
25228
25312
  workDirFolders: self.workDir ? listWorkDirFolders(self.workDir) : void 0
25229
25313
  };
25314
+ return response;
25230
25315
  }
25231
25316
  // ── Leader: handle keepalive from follower ──────────────────────────
25232
25317
  handleKeepalive(req) {
@@ -25250,7 +25335,6 @@ var HeartbeatMonitor = class {
25250
25335
  const normalizedEndpoint = endpoint ?? existingNode?.endpoint ?? devtunnelEndpoint ?? "";
25251
25336
  const normalizedCapabilities = capabilities ?? existingNode?.capabilities ?? [];
25252
25337
  const currentCapabilities = existingNode?.capabilities ?? [];
25253
- this.log.debug("keepalive received", { nodeId, status });
25254
25338
  this.followerMissedMap.set(nodeId, 0);
25255
25339
  let node = existingNode;
25256
25340
  const now = Date.now();
@@ -25317,7 +25401,7 @@ var HeartbeatMonitor = class {
25317
25401
  if (controlRequests.length > 0) {
25318
25402
  this.queuedControlRequests.delete(nodeId);
25319
25403
  }
25320
- return {
25404
+ const response = {
25321
25405
  leaderId: self.id,
25322
25406
  term: this.election.getCurrentTerm(),
25323
25407
  timestamp: Date.now(),
@@ -25329,6 +25413,7 @@ var HeartbeatMonitor = class {
25329
25413
  followUpMessages: followUpMessages.length > 0 ? followUpMessages : void 0,
25330
25414
  controlRequests: controlRequests.length > 0 ? controlRequests : void 0
25331
25415
  };
25416
+ return response;
25332
25417
  }
25333
25418
  // ── Follower: send keepalive to leader ──────────────────────────────
25334
25419
  async sendKeepalive() {
@@ -25353,6 +25438,13 @@ var HeartbeatMonitor = class {
25353
25438
  previewOrigin: self.previewOrigin,
25354
25439
  workDirFolders: self.workDir ? listWorkDirFolders(self.workDir) : void 0
25355
25440
  };
25441
+ this.log.info("sending keepalive request", {
25442
+ nodeId: self.id,
25443
+ leaderEndpoint,
25444
+ status: self.status,
25445
+ workDirFolders: request.workDirFolders?.length ?? 0,
25446
+ devtunnelEnabled: request.devtunnelEnabled
25447
+ });
25356
25448
  try {
25357
25449
  const response = await fetch(`${leaderEndpoint}/api/worker/keepalive`, applyRequestAuthHeaders({
25358
25450
  method: "POST",
@@ -25361,7 +25453,14 @@ var HeartbeatMonitor = class {
25361
25453
  }));
25362
25454
  if (response.ok) {
25363
25455
  const result = await response.json();
25364
- this.log.debug("keepalive ok", { nodes: result.clusterState.nodes.length });
25456
+ this.log.info("keepalive response received", {
25457
+ leaderId: result.leaderId,
25458
+ term: result.term,
25459
+ nodeCount: result.clusterState.nodes.length,
25460
+ dispatchedTaskCount: result.dispatchedTasks?.length ?? 0,
25461
+ followUpCount: result.followUpMessages?.length ?? 0,
25462
+ controlRequestCount: result.controlRequests?.length ?? 0
25463
+ });
25365
25464
  this.lastHeartbeatTime = Date.now();
25366
25465
  this.missedCount = 0;
25367
25466
  this.nodeRegistry.setLeader(result.leaderId, result.term);
@@ -25391,10 +25490,17 @@ var HeartbeatMonitor = class {
25391
25490
  ));
25392
25491
  }
25393
25492
  } else {
25394
- this.log.warn("keepalive failed", { status: response.status, leaderEndpoint });
25493
+ this.log.warn("keepalive request returned non-ok response", {
25494
+ leaderEndpoint,
25495
+ statusCode: response.status,
25496
+ body: truncateForLog(await response.text().catch(() => void 0))
25497
+ });
25395
25498
  }
25396
25499
  } catch (err) {
25397
- this.log.warn("keepalive error", { error: err instanceof Error ? err.message : String(err) });
25500
+ this.log.warn("keepalive request failed", {
25501
+ leaderEndpoint,
25502
+ error: formatError(err)
25503
+ });
25398
25504
  }
25399
25505
  }
25400
25506
  // ── Accessors ───────────────────────────────────────────────────────
@@ -25407,13 +25513,30 @@ var HeartbeatMonitor = class {
25407
25513
  canPushToNode(nodeId) {
25408
25514
  const node = this.nodeRegistry.getNode(nodeId);
25409
25515
  if (!node) return false;
25410
- if (node.devtunnelEndpoint) return true;
25411
- return this.followerEverReachedMap.get(nodeId) ?? false;
25516
+ if (node.status === "offline") return false;
25517
+ return !!(node.devtunnelEndpoint || node.endpoint);
25412
25518
  }
25413
25519
  // ── Private helpers ─────────────────────────────────────────────────
25414
25520
  startLeaderMode() {
25415
25521
  this.heartbeatTimer = setInterval(() => {
25416
- void this.sendHeartbeat();
25522
+ const self = this.nodeRegistry.getSelf();
25523
+ if (self.workDir) {
25524
+ this.nodeRegistry.updateFolders(self.id, listWorkDirFolders(self.workDir));
25525
+ }
25526
+ const now = Date.now();
25527
+ const followers = this.nodeRegistry.getAllNodes().filter((node) => node.id !== self.id);
25528
+ for (const node of followers) {
25529
+ if (node.status === "offline") continue;
25530
+ const elapsed = now - node.lastHeartbeat;
25531
+ if (elapsed >= this.config.electionTimeout) {
25532
+ this.log.warn("marking node offline from stale follower keepalive", {
25533
+ nodeId: node.id,
25534
+ lastHeartbeat: node.lastHeartbeat,
25535
+ elapsed
25536
+ });
25537
+ this.nodeRegistry.updateStatus(node.id, "offline");
25538
+ }
25539
+ }
25417
25540
  }, this.config.heartbeatInterval);
25418
25541
  }
25419
25542
  startFollowerMode() {
@@ -25447,10 +25570,21 @@ var HeartbeatMonitor = class {
25447
25570
  }
25448
25571
  }, this.config.electionTimeout);
25449
25572
  }
25450
- recordFollowerMiss(node) {
25573
+ recordFollowerMiss(node, details) {
25451
25574
  const current = this.followerMissedMap.get(node.id) ?? 0;
25452
25575
  const newCount = current + 1;
25453
25576
  this.followerMissedMap.set(node.id, newCount);
25577
+ const everReached = this.followerEverReachedMap.get(node.id) ?? false;
25578
+ this.log.warn("recorded heartbeat miss", {
25579
+ nodeId: node.id,
25580
+ misses: newCount,
25581
+ everReached,
25582
+ endpoint: details.endpoint,
25583
+ statusCode: details.statusCode,
25584
+ reason: details.reason,
25585
+ error: details.error,
25586
+ body: details.body
25587
+ });
25454
25588
  if (newCount >= MISSED_HEARTBEAT_THRESHOLD) {
25455
25589
  const freshNode = this.nodeRegistry.getNode(node.id);
25456
25590
  if (freshNode) {
@@ -25459,13 +25593,20 @@ var HeartbeatMonitor = class {
25459
25593
  this.log.debug("miss threshold but lastHeartbeat recent \u2014 skip offline", {
25460
25594
  nodeId: node.id,
25461
25595
  elapsed,
25462
- everReached: this.followerEverReachedMap.get(node.id) ?? false
25596
+ everReached
25463
25597
  });
25464
25598
  return;
25465
25599
  }
25466
25600
  }
25467
- const everReached = this.followerEverReachedMap.get(node.id) ?? false;
25468
- this.log.warn("marking node offline", { nodeId: node.id, everReached, misses: newCount });
25601
+ this.log.warn("marking node offline", {
25602
+ nodeId: node.id,
25603
+ everReached,
25604
+ misses: newCount,
25605
+ endpoint: details.endpoint,
25606
+ statusCode: details.statusCode,
25607
+ reason: details.reason,
25608
+ error: details.error
25609
+ });
25469
25610
  this.nodeRegistry.updateStatus(node.id, "offline");
25470
25611
  }
25471
25612
  }
@@ -25577,9 +25718,9 @@ var DataRouter = class {
25577
25718
  /**
25578
25719
  * Returns true if the request should be proxied to the leader.
25579
25720
  */
25580
- shouldProxy(method, path16) {
25721
+ shouldProxy(method, path17) {
25581
25722
  if (this.election.isLeader()) return false;
25582
- if (this.isExcludedPath(path16)) return false;
25723
+ if (this.isExcludedPath(path17)) return false;
25583
25724
  if (method.toUpperCase() === "GET") return false;
25584
25725
  return WRITE_METHODS.has(method.toUpperCase());
25585
25726
  }
@@ -25680,8 +25821,8 @@ var DataRouter = class {
25680
25821
  };
25681
25822
  }
25682
25823
  // ── Helpers ───────────────────────────────────────────────────────────
25683
- isExcludedPath(path16) {
25684
- return EXCLUDED_PATH_PREFIXES.some((prefix) => path16.startsWith(prefix)) || EXCLUDED_PATH_SUFFIXES.some((suffix) => path16.endsWith(suffix));
25824
+ isExcludedPath(path17) {
25825
+ return EXCLUDED_PATH_PREFIXES.some((prefix) => path17.startsWith(prefix)) || EXCLUDED_PATH_SUFFIXES.some((suffix) => path17.endsWith(suffix));
25685
25826
  }
25686
25827
  };
25687
25828
 
@@ -26693,23 +26834,53 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26693
26834
  this.started = true;
26694
26835
  }
26695
26836
  async joinCluster(seedUrl) {
26837
+ const log = this.logger.child("node/join-cluster");
26838
+ const tasks = this.taskEngine.listTasks().tasks;
26696
26839
  const joinBody = {
26697
26840
  id: this.selfInfo.id,
26698
26841
  endpoint: this.selfInfo.endpoint,
26699
26842
  name: this.config.node.name,
26700
26843
  capabilities: [],
26701
- tasks: this.taskEngine.listTasks().tasks
26844
+ tasks
26702
26845
  };
26703
26846
  if (this.selfInfo.devtunnelEndpoint) {
26704
26847
  joinBody.devtunnelEndpoint = this.selfInfo.devtunnelEndpoint;
26705
26848
  }
26706
- const response = await fetch(`${seedUrl}/api/cluster/join`, applyRequestAuthHeaders({
26707
- method: "POST",
26708
- headers: { "Content-Type": "application/json" },
26709
- body: JSON.stringify(joinBody)
26710
- }));
26849
+ log.info("sending cluster join request", {
26850
+ seedUrl,
26851
+ nodeId: this.selfInfo.id,
26852
+ endpoint: this.selfInfo.endpoint,
26853
+ taskCount: tasks.length,
26854
+ hasDevTunnel: !!this.selfInfo.devtunnelEndpoint
26855
+ });
26856
+ let response;
26857
+ try {
26858
+ response = await fetch(`${seedUrl}/api/cluster/join`, applyRequestAuthHeaders({
26859
+ method: "POST",
26860
+ headers: { "Content-Type": "application/json" },
26861
+ body: JSON.stringify(joinBody)
26862
+ }));
26863
+ } catch (error) {
26864
+ log.warn("cluster join request failed", {
26865
+ seedUrl,
26866
+ error: error instanceof Error ? error.message : String(error)
26867
+ });
26868
+ throw error;
26869
+ }
26870
+ log.info("received cluster join response", {
26871
+ seedUrl,
26872
+ ok: response.ok,
26873
+ statusCode: response.status
26874
+ });
26711
26875
  if (!response.ok) {
26712
26876
  const body = await response.json?.().catch(() => null);
26877
+ log.warn("cluster join request rejected", {
26878
+ seedUrl,
26879
+ statusCode: response.status,
26880
+ code: body?.error?.code,
26881
+ message: body?.error?.message,
26882
+ leaderEndpoint: body?.error?.leaderEndpoint
26883
+ });
26713
26884
  if (body?.error?.code === "NOT_LEADER") {
26714
26885
  const leader = body.error.leaderEndpoint;
26715
26886
  throw new Error(
@@ -26719,22 +26890,51 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26719
26890
  throw new Error(`Failed to join cluster via ${seedUrl}: ${response.status}`);
26720
26891
  }
26721
26892
  const data = await response.json();
26893
+ log.info("applied joined cluster state", {
26894
+ seedUrl,
26895
+ leaderId: data.leaderId,
26896
+ term: data.term,
26897
+ nodeCount: data.nodes.length
26898
+ });
26722
26899
  this.applyClusterState(data.nodes, data.leaderId, data.term);
26723
26900
  }
26724
26901
  async leaveCluster() {
26902
+ const log = this.logger.child("node/leave-cluster");
26725
26903
  const leader = this.nodeRegistry.getLeader();
26726
26904
  const leaderEndpoint = this.nodeRegistry.getLeaderEndpoint();
26727
26905
  const self = this.nodeRegistry.getSelf();
26728
26906
  if (!leader || !leaderEndpoint || leader.id === self.id) {
26907
+ log.info("skipping cluster leave request", {
26908
+ hasLeader: !!leader,
26909
+ leaderEndpoint,
26910
+ selfId: self.id
26911
+ });
26729
26912
  return;
26730
26913
  }
26731
26914
  try {
26732
- await fetch(`${leaderEndpoint}/api/cluster/leave`, applyRequestAuthHeaders({
26915
+ log.info("sending cluster leave request", {
26916
+ leaderId: leader.id,
26917
+ leaderEndpoint,
26918
+ nodeId: self.id
26919
+ });
26920
+ const response = await fetch(`${leaderEndpoint}/api/cluster/leave`, applyRequestAuthHeaders({
26733
26921
  method: "POST",
26734
26922
  headers: { "Content-Type": "application/json" },
26735
26923
  body: JSON.stringify({ nodeId: self.id })
26736
26924
  }));
26737
- } catch {
26925
+ log.info("received cluster leave response", {
26926
+ leaderId: leader.id,
26927
+ leaderEndpoint,
26928
+ ok: response.ok,
26929
+ statusCode: response.status
26930
+ });
26931
+ } catch (error) {
26932
+ log.warn("cluster leave request failed", {
26933
+ leaderId: leader.id,
26934
+ leaderEndpoint,
26935
+ nodeId: self.id,
26936
+ error: error instanceof Error ? error.message : String(error)
26937
+ });
26738
26938
  }
26739
26939
  const refreshedSelf = {
26740
26940
  ...self,
@@ -26747,8 +26947,13 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26747
26947
  this.nodeRegistry.setSelf(refreshedSelf);
26748
26948
  this.nodeRegistry.syncFromHeartbeat([refreshedSelf]);
26749
26949
  this.nodeRegistry.clearLeader();
26750
- this.election.stepDown();
26751
- await this.election.startElection();
26950
+ this.election.assumeLeadership();
26951
+ this.syncSelfInfoFromRegistry();
26952
+ log.info("detached from leader and assumed solo leadership", {
26953
+ previousLeaderId: leader.id,
26954
+ nodeId: refreshedSelf.id,
26955
+ term: this.election.getCurrentTerm()
26956
+ });
26752
26957
  }
26753
26958
  async stop() {
26754
26959
  if (!this.started) return;
@@ -26758,13 +26963,26 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26758
26963
  try {
26759
26964
  const leaderEndpoint = this.nodeRegistry.getLeaderEndpoint();
26760
26965
  if (leaderEndpoint) {
26761
- await fetch(`${leaderEndpoint}/api/cluster/leave`, applyRequestAuthHeaders({
26966
+ this.logger.info("sending shutdown cluster leave request", {
26967
+ leaderEndpoint,
26968
+ nodeId: this.selfInfo.id
26969
+ });
26970
+ const response = await fetch(`${leaderEndpoint}/api/cluster/leave`, applyRequestAuthHeaders({
26762
26971
  method: "POST",
26763
26972
  headers: { "Content-Type": "application/json" },
26764
26973
  body: JSON.stringify({ nodeId: this.selfInfo.id })
26765
26974
  }));
26975
+ this.logger.info("received shutdown cluster leave response", {
26976
+ leaderEndpoint,
26977
+ ok: response.ok,
26978
+ statusCode: response.status
26979
+ });
26766
26980
  }
26767
- } catch {
26981
+ } catch (error) {
26982
+ this.logger.warn("shutdown cluster leave request failed", {
26983
+ nodeId: this.selfInfo.id,
26984
+ error: error instanceof Error ? error.message : String(error)
26985
+ });
26768
26986
  }
26769
26987
  if (this.devtunnelTransport) {
26770
26988
  await this.devtunnelTransport.stop();
@@ -26925,7 +27143,7 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26925
27143
  this.selfInfo = nextSelf;
26926
27144
  this.nodeRegistry.setSelf(nextSelf);
26927
27145
  this.nodeRegistry.syncFromHeartbeat(nodes);
26928
- this.election.handleLeaderAnnounce({ leaderId, term });
27146
+ this.election.adoptLeaderFromJoin({ leaderId, term });
26929
27147
  }
26930
27148
  cloneTransportConfig(config) {
26931
27149
  return {
@@ -27564,8 +27782,8 @@ function getErrorMap() {
27564
27782
 
27565
27783
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
27566
27784
  var makeIssue = (params) => {
27567
- const { data, path: path16, errorMaps, issueData } = params;
27568
- const fullPath = [...path16, ...issueData.path || []];
27785
+ const { data, path: path17, errorMaps, issueData } = params;
27786
+ const fullPath = [...path17, ...issueData.path || []];
27569
27787
  const fullIssue = {
27570
27788
  ...issueData,
27571
27789
  path: fullPath
@@ -27681,11 +27899,11 @@ var errorUtil;
27681
27899
 
27682
27900
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
27683
27901
  var ParseInputLazyPath = class {
27684
- constructor(parent, value, path16, key) {
27902
+ constructor(parent, value, path17, key) {
27685
27903
  this._cachedPath = [];
27686
27904
  this.parent = parent;
27687
27905
  this.data = value;
27688
- this._path = path16;
27906
+ this._path = path17;
27689
27907
  this._key = key;
27690
27908
  }
27691
27909
  get path() {
@@ -31560,19 +31778,31 @@ function createErrorMiddleware() {
31560
31778
  // ../../packages/api/src/routes/cluster.ts
31561
31779
  var import_express = __toESM(require_express2(), 1);
31562
31780
  var CONNECTIVITY_TIMEOUT_MS = 8e3;
31563
- async function verifyHealth(endpoint) {
31781
+ function formatError2(error) {
31782
+ return error instanceof Error ? error.message : String(error);
31783
+ }
31784
+ async function verifyHealth(endpoint, log) {
31564
31785
  const controller = new AbortController();
31565
31786
  const timer = setTimeout(() => controller.abort(), CONNECTIVITY_TIMEOUT_MS);
31787
+ const url = `${endpoint}/api/system/health`;
31566
31788
  try {
31567
- const response = await fetch(`${endpoint}/api/system/health`, {
31789
+ log.info("sending leader health check", { endpoint, url, timeoutMs: CONNECTIVITY_TIMEOUT_MS });
31790
+ const response = await fetch(url, {
31568
31791
  signal: controller.signal
31569
31792
  });
31793
+ log.info("received leader health check response", {
31794
+ endpoint,
31795
+ url,
31796
+ ok: response.ok,
31797
+ statusCode: response.status
31798
+ });
31570
31799
  if (!response.ok) {
31571
31800
  throw new Error(`health check returned ${response.status}`);
31572
31801
  }
31573
31802
  } catch (err) {
31803
+ log.warn("leader health check failed", { endpoint, url, error: formatError2(err) });
31574
31804
  throw new Error(
31575
- `Failed to verify connectivity for ${endpoint}: ${err instanceof Error ? err.message : String(err)}`
31805
+ `Failed to verify connectivity for ${endpoint}: ${formatError2(err)}`
31576
31806
  );
31577
31807
  } finally {
31578
31808
  clearTimeout(timer);
@@ -31584,9 +31814,11 @@ function asyncHandler(fn) {
31584
31814
  function createClusterRoutes() {
31585
31815
  const router = (0, import_express.Router)();
31586
31816
  router.post("/join", asyncHandler(async (req, res) => {
31587
- const { nodeRegistry, election, taskEngine } = req.app.locals.deps;
31817
+ const { nodeRegistry, election, taskEngine, logger: rootLogger } = req.app.locals.deps;
31818
+ const log = rootLogger.child("cluster/join");
31588
31819
  if (!election.isLeader()) {
31589
31820
  const leaderEndpoint = nodeRegistry.getLeaderEndpoint();
31821
+ log.warn("rejected cluster join because node is not leader", { leaderEndpoint });
31590
31822
  res.status(421).json({
31591
31823
  error: {
31592
31824
  code: "NOT_LEADER",
@@ -31597,10 +31829,19 @@ function createClusterRoutes() {
31597
31829
  return;
31598
31830
  }
31599
31831
  const body = JoinClusterBody.parse(req.body);
31832
+ log.info("received cluster join request", {
31833
+ nodeId: body.id,
31834
+ name: body.name,
31835
+ endpoint: body.endpoint,
31836
+ taskCount: body.tasks?.length ?? 0,
31837
+ hasDevTunnel: !!body.devtunnelEndpoint
31838
+ });
31600
31839
  const existingNodes = nodeRegistry.getAllNodes();
31840
+ let removedCount = 0;
31601
31841
  for (const existing of existingNodes) {
31602
31842
  if (existing.id === body.id || existing.endpoint === body.endpoint || existing.name === body.name) {
31603
31843
  nodeRegistry.removeNode(existing.id);
31844
+ removedCount++;
31604
31845
  }
31605
31846
  }
31606
31847
  const node = {
@@ -31616,6 +31857,12 @@ function createClusterRoutes() {
31616
31857
  };
31617
31858
  nodeRegistry.addNode(node);
31618
31859
  taskEngine.importTasks(body.tasks ?? []);
31860
+ log.info("accepted cluster join request", {
31861
+ nodeId: node.id,
31862
+ endpoint: node.endpoint,
31863
+ removedCount,
31864
+ importedTaskCount: body.tasks?.length ?? 0
31865
+ });
31619
31866
  const clusterState = nodeRegistry.getClusterState();
31620
31867
  res.status(201).json({
31621
31868
  clusterId: clusterState.clusterId ?? nanoid(),
@@ -31627,14 +31874,22 @@ function createClusterRoutes() {
31627
31874
  router.post("/connect", asyncHandler(async (req, res) => {
31628
31875
  const {
31629
31876
  nodeRegistry,
31630
- joinCurrentNodeToCluster
31877
+ joinCurrentNodeToCluster,
31878
+ logger: rootLogger
31631
31879
  } = req.app.locals.deps;
31880
+ const log = rootLogger.child("cluster/connect");
31632
31881
  const body = ConnectClusterBody.parse(req.body);
31882
+ log.info("received cluster connect request", {
31883
+ leaderEndpoint: body.leaderEndpoint,
31884
+ transport: body.transport
31885
+ });
31633
31886
  if (!joinCurrentNodeToCluster) {
31634
31887
  throw new MeshyError("VALIDATION_ERROR", "Join flow is not available on this node", 501);
31635
31888
  }
31636
- await verifyHealth(body.leaderEndpoint);
31889
+ await verifyHealth(body.leaderEndpoint, log);
31890
+ log.info("leader health check succeeded", { leaderEndpoint: body.leaderEndpoint });
31637
31891
  await joinCurrentNodeToCluster(body.leaderEndpoint);
31892
+ log.info("completed cluster connect request", { leaderEndpoint: body.leaderEndpoint });
31638
31893
  const self = nodeRegistry.getSelf();
31639
31894
  const clusterState = nodeRegistry.getClusterState();
31640
31895
  res.json({
@@ -31647,17 +31902,22 @@ function createClusterRoutes() {
31647
31902
  });
31648
31903
  }));
31649
31904
  router.post("/leave", asyncHandler(async (req, res) => {
31650
- const { nodeRegistry } = req.app.locals.deps;
31905
+ const { nodeRegistry, logger: rootLogger } = req.app.locals.deps;
31906
+ const log = rootLogger.child("cluster/leave");
31651
31907
  const { nodeId } = req.body;
31908
+ log.info("received cluster leave request", { nodeId });
31652
31909
  nodeRegistry.removeNode(nodeId);
31653
31910
  res.json({ ok: true });
31654
31911
  }));
31655
31912
  router.post("/disconnect", asyncHandler(async (req, res) => {
31656
- const { leaveCurrentCluster, nodeRegistry } = req.app.locals.deps;
31913
+ const { leaveCurrentCluster, nodeRegistry, logger: rootLogger } = req.app.locals.deps;
31914
+ const log = rootLogger.child("cluster/disconnect");
31915
+ log.info("received cluster disconnect request");
31657
31916
  if (!leaveCurrentCluster) {
31658
31917
  throw new MeshyError("VALIDATION_ERROR", "Leave flow is not available on this node", 501);
31659
31918
  }
31660
31919
  await leaveCurrentCluster();
31920
+ log.info("completed cluster disconnect request");
31661
31921
  const self = nodeRegistry.getSelf();
31662
31922
  const clusterState = nodeRegistry.getClusterState();
31663
31923
  res.json({
@@ -33543,13 +33803,40 @@ function createWorkerRoutes() {
33543
33803
  res.json({ ok: true });
33544
33804
  }));
33545
33805
  router.post("/heartbeat", asyncHandler4(async (req, res) => {
33546
- const { heartbeat } = req.app.locals.deps;
33547
- const response = heartbeat.handleHeartbeat(req.body);
33806
+ const { heartbeat, logger: rootLogger } = req.app.locals.deps;
33807
+ const log = rootLogger.child("worker/heartbeat");
33808
+ const body = req.body;
33809
+ log.info("received worker heartbeat API call", {
33810
+ leaderId: body.leaderId,
33811
+ term: body.term,
33812
+ nodeCount: body.clusterState?.nodes?.length ?? 0
33813
+ });
33814
+ const response = heartbeat.handleHeartbeat(body);
33815
+ log.info("completed worker heartbeat API call", {
33816
+ nodeId: response.nodeId,
33817
+ status: response.status,
33818
+ load: response.load
33819
+ });
33548
33820
  res.json(response);
33549
33821
  }));
33550
33822
  router.post("/keepalive", asyncHandler4(async (req, res) => {
33551
- const { heartbeat } = req.app.locals.deps;
33552
- const response = heartbeat.handleKeepalive(req.body);
33823
+ const { heartbeat, logger: rootLogger } = req.app.locals.deps;
33824
+ const log = rootLogger.child("worker/keepalive");
33825
+ const body = req.body;
33826
+ log.info("received worker keepalive API call", {
33827
+ nodeId: body.nodeId,
33828
+ status: body.status,
33829
+ endpoint: body.endpoint
33830
+ });
33831
+ const response = heartbeat.handleKeepalive(body);
33832
+ log.info("completed worker keepalive API call", {
33833
+ leaderId: response.leaderId,
33834
+ term: response.term,
33835
+ nodeCount: response.clusterState.nodes.length,
33836
+ dispatchedTaskCount: response.dispatchedTasks?.length ?? 0,
33837
+ followUpCount: response.followUpMessages?.length ?? 0,
33838
+ controlRequestCount: response.controlRequests?.length ?? 0
33839
+ });
33553
33840
  res.json(response);
33554
33841
  }));
33555
33842
  router.post("/vote", asyncHandler4(async (req, res) => {
@@ -33573,8 +33860,19 @@ function createWorkerRoutes() {
33573
33860
  res.json(payload);
33574
33861
  }));
33575
33862
  router.post("/control-response", asyncHandler4(async (req, res) => {
33576
- const { heartbeat } = req.app.locals.deps;
33577
- const handled = heartbeat.handleWorkerControlResponse?.(req.body) ?? false;
33863
+ const { heartbeat, logger: rootLogger } = req.app.locals.deps;
33864
+ const log = rootLogger.child("worker/control-response");
33865
+ const body = req.body;
33866
+ log.info("received worker control response API call", {
33867
+ requestId: body.requestId,
33868
+ ok: body.ok,
33869
+ statusCode: body.statusCode
33870
+ });
33871
+ const handled = heartbeat.handleWorkerControlResponse?.(body) ?? false;
33872
+ log.info("completed worker control response API call", {
33873
+ requestId: body.requestId,
33874
+ handled
33875
+ });
33578
33876
  res.json({ ok: true, handled });
33579
33877
  }));
33580
33878
  return router;
@@ -33587,7 +33885,13 @@ function asyncHandler5(fn) {
33587
33885
  }
33588
33886
  function createSystemRoutes() {
33589
33887
  const router = (0, import_express5.Router)();
33590
- router.get("/health", asyncHandler5(async (_req, res) => {
33888
+ router.get("/health", asyncHandler5(async (req, res) => {
33889
+ const { logger: rootLogger } = req.app.locals.deps;
33890
+ rootLogger.child("system/health").info("received system health API call", {
33891
+ method: req.method,
33892
+ path: req.originalUrl || req.url,
33893
+ remoteAddress: req.ip || req.socket.remoteAddress
33894
+ });
33591
33895
  res.json({ status: "ok", timestamp: Date.now() });
33592
33896
  }));
33593
33897
  router.get("/info", asyncHandler5(async (req, res) => {
@@ -34149,18 +34453,21 @@ function createTransport(config) {
34149
34453
 
34150
34454
  // src/startup.ts
34151
34455
  var fs16 = __toESM(require("fs"), 1);
34456
+ var path16 = __toESM(require("path"), 1);
34152
34457
  var readline = __toESM(require("readline/promises"), 1);
34458
+ var import_node_child_process6 = require("child_process");
34153
34459
  function getDefaultNodeName() {
34154
34460
  return getDeviceNodeName();
34155
34461
  }
34156
34462
  var DEFAULT_NODE_NAME = getDefaultNodeName();
34157
34463
  var DEFAULT_NODE_PORT = 12345;
34158
34464
  var SUPPORTED_TRANSPORTS = ["direct", "devtunnel", "tailscale"];
34465
+ var STARTUP_REQUIREMENTS = ["az", "devtunnel", "claude", "codex"];
34159
34466
  function createDefaultConfig(storagePath = resolveDefaultStoragePath(), nodeName = DEFAULT_NODE_NAME) {
34160
34467
  return {
34161
34468
  node: { name: nodeName, port: DEFAULT_NODE_PORT },
34162
34469
  transport: { type: "direct" },
34163
- cluster: { seeds: [], heartbeatInterval: 3e3, electionTimeout: 9e3, apiKey: "" },
34470
+ cluster: { seeds: [], heartbeatInterval: 12e3, electionTimeout: 36e3, apiKey: "" },
34164
34471
  storage: { path: storagePath }
34165
34472
  };
34166
34473
  }
@@ -34170,6 +34477,257 @@ function createRuntimeDefaultConfig(fileConfig, options = {}) {
34170
34477
  const nodeName = options.ignorePersistedName ? getDeviceNodeName() : resolveDefaultNodeName(storagePath);
34171
34478
  return createDefaultConfig(storagePath, nodeName);
34172
34479
  }
34480
+ function writeLine(stream, message = "") {
34481
+ stream.write(`${message}
34482
+ `);
34483
+ }
34484
+ function createPromptSession(prompt) {
34485
+ if (prompt) {
34486
+ return {
34487
+ ask: prompt,
34488
+ close: async () => void 0
34489
+ };
34490
+ }
34491
+ if (!shouldPromptForStartOptions()) {
34492
+ return void 0;
34493
+ }
34494
+ const rl = readline.createInterface({
34495
+ input: process.stdin,
34496
+ output: process.stdout
34497
+ });
34498
+ return {
34499
+ ask: (question) => rl.question(question),
34500
+ close: async () => rl.close()
34501
+ };
34502
+ }
34503
+ function createDefaultCommandRunner(platform) {
34504
+ return (command, args, interactive = false) => {
34505
+ const result = (0, import_node_child_process6.spawnSync)(command, args, {
34506
+ encoding: "utf-8",
34507
+ shell: platform === "win32",
34508
+ stdio: interactive ? "inherit" : "pipe"
34509
+ });
34510
+ return {
34511
+ ok: result.status === 0 && !result.error,
34512
+ status: result.status,
34513
+ stdout: typeof result.stdout === "string" ? result.stdout : "",
34514
+ stderr: typeof result.stderr === "string" ? result.stderr : "",
34515
+ error: result.error?.message
34516
+ };
34517
+ };
34518
+ }
34519
+ function getNodeMetadataPath2(storagePath) {
34520
+ return path16.join(storagePath, "metadata.json");
34521
+ }
34522
+ function readStartupMetadataFile(storagePath) {
34523
+ try {
34524
+ const raw = JSON.parse(fs16.readFileSync(getNodeMetadataPath2(storagePath), "utf-8"));
34525
+ return typeof raw === "object" && raw !== null ? raw : {};
34526
+ } catch {
34527
+ return {};
34528
+ }
34529
+ }
34530
+ function writeStartupMetadataFile(storagePath, metadata) {
34531
+ fs16.mkdirSync(storagePath, { recursive: true });
34532
+ fs16.writeFileSync(getNodeMetadataPath2(storagePath), JSON.stringify(metadata, null, 2) + "\n", "utf-8");
34533
+ }
34534
+ function formatLocalDate(now) {
34535
+ const year = now.getFullYear();
34536
+ const month = String(now.getMonth() + 1).padStart(2, "0");
34537
+ const day = String(now.getDate()).padStart(2, "0");
34538
+ return `${year}-${month}-${day}`;
34539
+ }
34540
+ function isYesAnswer(value) {
34541
+ const normalized = value.trim().toLowerCase();
34542
+ return normalized === "y" || normalized === "yes";
34543
+ }
34544
+ async function confirm(ask, question) {
34545
+ const answer = await ask(`${question} [y/N]: `);
34546
+ return isYesAnswer(answer);
34547
+ }
34548
+ function isCommandAvailable(commandRunner, platform, command) {
34549
+ const lookupCommand = platform === "win32" ? "where" : "which";
34550
+ return commandRunner(lookupCommand, [command], false).ok;
34551
+ }
34552
+ function buildInstallCommand(requirement, platform) {
34553
+ switch (requirement) {
34554
+ case "az":
34555
+ if (platform === "darwin") {
34556
+ return { command: "brew", args: ["install", "azure-cli"] };
34557
+ }
34558
+ if (platform === "win32") {
34559
+ return { command: "winget", args: ["install", "--exact", "--id", "Microsoft.AzureCLI"] };
34560
+ }
34561
+ return void 0;
34562
+ case "devtunnel":
34563
+ if (platform === "darwin") {
34564
+ return { command: "brew", args: ["install", "--cask", "devtunnel"] };
34565
+ }
34566
+ if (platform === "win32") {
34567
+ return { command: "winget", args: ["install", "--exact", "--id", "Microsoft.devtunnel"] };
34568
+ }
34569
+ return void 0;
34570
+ case "claude":
34571
+ if (platform === "darwin") {
34572
+ return { command: "bash", args: ["-lc", "curl -fsSL https://claude.ai/install.sh | bash"] };
34573
+ }
34574
+ if (platform === "win32") {
34575
+ return {
34576
+ command: "powershell",
34577
+ args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "irm https://claude.ai/install.ps1 | iex"]
34578
+ };
34579
+ }
34580
+ return void 0;
34581
+ case "codex":
34582
+ return { command: "npm", args: ["install", "-g", "@openai/codex"] };
34583
+ }
34584
+ }
34585
+ function buildLoginCommand(requirement) {
34586
+ if (requirement === "az") {
34587
+ return { command: "az", args: ["login"] };
34588
+ }
34589
+ return { command: "devtunnel", args: ["user", "login"] };
34590
+ }
34591
+ function isAuthenticated(requirement, commandRunner) {
34592
+ const command = requirement === "az" ? { command: "az", args: ["account", "show"] } : { command: "devtunnel", args: ["user", "show"] };
34593
+ return commandRunner(command.command, command.args, false).ok;
34594
+ }
34595
+ function isRequirementSatisfied(requirement, status) {
34596
+ if (!status || status.installed !== true || status.status !== "ok") {
34597
+ return false;
34598
+ }
34599
+ if (requirement === "az" || requirement === "devtunnel") {
34600
+ return status.authenticated === true;
34601
+ }
34602
+ return true;
34603
+ }
34604
+ function resolveStartupRequirementsMetadata(storagePath) {
34605
+ const metadata = readStartupMetadataFile(storagePath).startupRequirements;
34606
+ return metadata && typeof metadata === "object" ? metadata : {};
34607
+ }
34608
+ function shouldSkipStartupRequirementsCheck(storagePath, now = /* @__PURE__ */ new Date()) {
34609
+ const metadata = resolveStartupRequirementsMetadata(storagePath);
34610
+ if (metadata.lastCheckedOn !== formatLocalDate(now)) {
34611
+ return false;
34612
+ }
34613
+ return STARTUP_REQUIREMENTS.every((requirement) => isRequirementSatisfied(requirement, metadata.components?.[requirement]));
34614
+ }
34615
+ async function ensureRequirementInstalled(requirement, platform, ask, commandRunner, stdout, stderr) {
34616
+ if (isCommandAvailable(commandRunner, platform, requirement)) {
34617
+ return { installed: true, status: "ok" };
34618
+ }
34619
+ if (!ask) {
34620
+ writeLine(stderr, `Missing required component "${requirement}". Start in a TTY to install it automatically.`);
34621
+ return { installed: false, status: "missing" };
34622
+ }
34623
+ const install = buildInstallCommand(requirement, platform);
34624
+ if (!install) {
34625
+ writeLine(stderr, `Missing required component "${requirement}", and automatic install is not supported on ${platform}.`);
34626
+ return { installed: false, status: "unsupported-platform" };
34627
+ }
34628
+ if (!await confirm(ask, `Required component "${requirement}" is missing. Install it now?`)) {
34629
+ return { installed: false, status: "missing" };
34630
+ }
34631
+ writeLine(stdout, `Installing ${requirement}...`);
34632
+ const result = commandRunner(install.command, install.args, true);
34633
+ if (!result.ok) {
34634
+ writeLine(stderr, `Failed to install ${requirement}.`);
34635
+ return { installed: false, status: "install-failed" };
34636
+ }
34637
+ return isCommandAvailable(commandRunner, platform, requirement) ? { installed: true, status: "ok" } : { installed: false, status: "install-failed" };
34638
+ }
34639
+ async function ensureRequirementAuthenticated(requirement, ask, commandRunner, stdout, stderr) {
34640
+ if (isAuthenticated(requirement, commandRunner)) {
34641
+ return { authenticated: true, status: "ok" };
34642
+ }
34643
+ if (!ask) {
34644
+ writeLine(stderr, `${requirement} is installed but not logged in. Start in a TTY to log in automatically.`);
34645
+ return { authenticated: false, status: "not-authenticated" };
34646
+ }
34647
+ if (!await confirm(ask, `"${requirement}" is installed but not logged in. Log in now?`)) {
34648
+ return { authenticated: false, status: "not-authenticated" };
34649
+ }
34650
+ writeLine(stdout, `Opening ${requirement} login...`);
34651
+ const login = buildLoginCommand(requirement);
34652
+ const result = commandRunner(login.command, login.args, true);
34653
+ if (!result.ok) {
34654
+ writeLine(stderr, `Failed to complete ${requirement} login.`);
34655
+ return { authenticated: false, status: "login-failed" };
34656
+ }
34657
+ return isAuthenticated(requirement, commandRunner) ? { authenticated: true, status: "ok" } : { authenticated: false, status: "login-failed" };
34658
+ }
34659
+ async function ensureStartupRequirements(storagePath, options = {}) {
34660
+ const now = options.now ?? /* @__PURE__ */ new Date();
34661
+ if (shouldSkipStartupRequirementsCheck(storagePath, now)) {
34662
+ return {
34663
+ skipped: true,
34664
+ metadata: resolveStartupRequirementsMetadata(storagePath)
34665
+ };
34666
+ }
34667
+ const platform = options.platform ?? process.platform;
34668
+ const stdout = options.stdout ?? process.stdout;
34669
+ const stderr = options.stderr ?? process.stderr;
34670
+ const commandRunner = options.commandRunner ?? createDefaultCommandRunner(platform);
34671
+ const promptSession = createPromptSession(options.prompt);
34672
+ const checkedAt = now.toISOString();
34673
+ const checkedOn = formatLocalDate(now);
34674
+ const components = {};
34675
+ try {
34676
+ for (const requirement of STARTUP_REQUIREMENTS) {
34677
+ const installResult = await ensureRequirementInstalled(
34678
+ requirement,
34679
+ platform,
34680
+ promptSession?.ask,
34681
+ commandRunner,
34682
+ stdout,
34683
+ stderr
34684
+ );
34685
+ if (!installResult.installed) {
34686
+ components[requirement] = {
34687
+ installed: false,
34688
+ status: installResult.status,
34689
+ checkedAt
34690
+ };
34691
+ continue;
34692
+ }
34693
+ if (requirement === "az" || requirement === "devtunnel") {
34694
+ const authResult = await ensureRequirementAuthenticated(
34695
+ requirement,
34696
+ promptSession?.ask,
34697
+ commandRunner,
34698
+ stdout,
34699
+ stderr
34700
+ );
34701
+ components[requirement] = {
34702
+ installed: true,
34703
+ authenticated: authResult.authenticated,
34704
+ status: authResult.status,
34705
+ checkedAt
34706
+ };
34707
+ continue;
34708
+ }
34709
+ components[requirement] = {
34710
+ installed: true,
34711
+ status: "ok",
34712
+ checkedAt
34713
+ };
34714
+ }
34715
+ } finally {
34716
+ await promptSession?.close();
34717
+ }
34718
+ const metadataFile = readStartupMetadataFile(storagePath);
34719
+ const metadata = {
34720
+ lastCheckedAt: checkedAt,
34721
+ lastCheckedOn: checkedOn,
34722
+ components
34723
+ };
34724
+ metadataFile.startupRequirements = metadata;
34725
+ writeStartupMetadataFile(storagePath, metadataFile);
34726
+ return {
34727
+ skipped: false,
34728
+ metadata
34729
+ };
34730
+ }
34173
34731
  function parseArgs(argv) {
34174
34732
  const result = {};
34175
34733
  for (let i = 0; i < argv.length; i++) {
@@ -34216,9 +34774,9 @@ function parseArgs(argv) {
34216
34774
  }
34217
34775
  return result;
34218
34776
  }
34219
- function loadConfigFile(path16) {
34777
+ function loadConfigFile(path17) {
34220
34778
  try {
34221
- const raw = fs16.readFileSync(path16, "utf-8");
34779
+ const raw = fs16.readFileSync(path17, "utf-8");
34222
34780
  return JSON.parse(raw);
34223
34781
  } catch {
34224
34782
  return {};
@@ -34435,6 +34993,11 @@ async function main() {
34435
34993
  if (!resolvedArgs.disableAuth) {
34436
34994
  persistNodeAuthMetadata(config.storage.path, authMetadata);
34437
34995
  }
34996
+ console.log("Checking startup requirements (az, devtunnel, claude, codex)...");
34997
+ const startupRequirements = await ensureStartupRequirements(config.storage.path);
34998
+ console.log(
34999
+ startupRequirements.skipped ? "Startup requirements already verified today; skipping checks." : "Startup requirements check complete."
35000
+ );
34438
35001
  const logDir = nodePath.join(config.storage.path, "logs");
34439
35002
  const logger = createLogger({
34440
35003
  component: "node",
@@ -34763,6 +35326,7 @@ if (isDirectRun) {
34763
35326
  applyStartMetadata,
34764
35327
  createDefaultConfig,
34765
35328
  createRuntimeDefaultConfig,
35329
+ ensureStartupRequirements,
34766
35330
  formatBanner,
34767
35331
  formatLoadedStartMetadata,
34768
35332
  getDefaultNodeName,
@@ -34773,8 +35337,10 @@ if (isDirectRun) {
34773
35337
  parseArgs,
34774
35338
  promptStartOptions,
34775
35339
  resolveRuntimeAuthMetadata,
35340
+ resolveStartupRequirementsMetadata,
34776
35341
  shouldCollectStartOptions,
34777
- shouldPromptForStartOptions
35342
+ shouldPromptForStartOptions,
35343
+ shouldSkipStartupRequirementsCheck
34778
35344
  });
34779
35345
  /*! Bundled license information:
34780
35346